Merge master.kernel.org:/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6
diff --git a/Documentation/ABI/removed/raw1394_legacy_isochronous b/Documentation/ABI/removed/raw1394_legacy_isochronous
new file mode 100644
index 0000000..1b62962
--- /dev/null
+++ b/Documentation/ABI/removed/raw1394_legacy_isochronous
@@ -0,0 +1,16 @@
+What:		legacy isochronous ABI of raw1394 (1st generation iso ABI)
+Date:		June 2007 (scheduled), removed in kernel v2.6.23
+Contact:	linux1394-devel@lists.sourceforge.net
+Description:
+	The two request types RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN have
+	been deprecated for quite some time.  They are very inefficient as they
+	come with high interrupt load and several layers of callbacks for each
+	packet.  Because of these deficiencies, the video1394 and dv1394 drivers
+	and the 3rd-generation isochronous ABI in raw1394 (rawiso) were created.
+
+Users:
+	libraw1394 users via the long deprecated API raw1394_iso_write,
+	raw1394_start_iso_write, raw1394_start_iso_rcv, raw1394_stop_iso_rcv
+
+	libdc1394, which optionally uses these old libraw1394 calls
+	alternatively to the more efficient video1394 ABI
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 38f88b6..8c5698a 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -643,4 +643,15 @@
 !Edrivers/spi/spi.c
   </chapter>
 
+  <chapter id="splice">
+      <title>splice API</title>
+  <para>)
+	splice is a method for moving blocks of data around inside the
+	kernel, without continually transferring it between the kernel
+	and user space.
+  </para>
+!Iinclude/linux/splice.h
+!Ffs/splice.c
+  </chapter>
+
 </book>
diff --git a/Documentation/block/barrier.txt b/Documentation/block/barrier.txt
index a272c3d..7d279f2 100644
--- a/Documentation/block/barrier.txt
+++ b/Documentation/block/barrier.txt
@@ -82,23 +82,12 @@
 typedef void (prepare_flush_fn)(request_queue_t *q, struct request *rq);
 
 int blk_queue_ordered(request_queue_t *q, unsigned ordered,
-		      prepare_flush_fn *prepare_flush_fn,
-		      unsigned gfp_mask);
-
-int blk_queue_ordered_locked(request_queue_t *q, unsigned ordered,
-			     prepare_flush_fn *prepare_flush_fn,
-			     unsigned gfp_mask);
-
-The only difference between the two functions is whether or not the
-caller is holding q->queue_lock on entry.  The latter expects the
-caller is holding the lock.
+		      prepare_flush_fn *prepare_flush_fn);
 
 @q			: the queue in question
 @ordered		: the ordered mode the driver/device supports
 @prepare_flush_fn	: this function should prepare @rq such that it
 			  flushes cache to physical medium when executed
-@gfp_mask		: gfp_mask used when allocating data structures
-			  for ordered processing
 
 For example, SCSI disk driver's prepare_flush_fn looks like the
 following.
@@ -106,9 +95,10 @@
 static void sd_prepare_flush(request_queue_t *q, struct request *rq)
 {
 	memset(rq->cmd, 0, sizeof(rq->cmd));
-	rq->flags |= REQ_BLOCK_PC;
+	rq->cmd_type = REQ_TYPE_BLOCK_PC;
 	rq->timeout = SD_TIMEOUT;
 	rq->cmd[0] = SYNCHRONIZE_CACHE;
+	rq->cmd_len = 10;
 }
 
 The following seven ordered modes are supported.  The following table
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 7d3f205..062fc2e 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -49,16 +49,6 @@
 
 ---------------------------
 
-What:	raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
-When:	June 2007
-Why:	Deprecated in favour of the more efficient and robust rawiso interface.
-	Affected are applications which use the deprecated part of libraw1394
-	(raw1394_iso_write, raw1394_start_iso_write, raw1394_start_iso_rcv,
-	raw1394_stop_iso_rcv) or bypass	libraw1394.
-Who:	Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
-
----------------------------
-
 What:	old NCR53C9x driver
 When:	October 2007
 Why:	Replaced by the much better esp_scsi driver.  Actual low-level
@@ -258,14 +248,6 @@
 
 ---------------------------
 
-What:   sk98lin network driver
-When:   July 2007
-Why:    In kernel tree version of driver is unmaintained. Sk98lin driver
-	replaced by the skge driver. 
-Who:    Stephen Hemminger <shemminger@osdl.org>
-
----------------------------
-
 What:	Compaq touchscreen device emulation
 When:	Oct 2007
 Files:	drivers/input/tsdev.c
@@ -280,25 +262,6 @@
 
 ---------------------------
 
-What:	Multipath cached routing support in ipv4
-When:	in 2.6.23
-Why:	Code was merged, then submitter immediately disappeared leaving
-	us with no maintainer and lots of bugs.  The code should not have
-	been merged in the first place, and many aspects of it's
-	implementation are blocking more critical core networking
-	development.  It's marked EXPERIMENTAL and no distribution
-	enables it because it cause obscure crashes due to unfixable bugs
-	(interfaces don't return errors so memory allocation can't be
-	handled, calling contexts of these interfaces make handling
-	errors impossible too because they get called after we've
-	totally commited to creating a route object, for example).
-	This problem has existed for years and no forward progress
-	has ever been made, and nobody steps up to try and salvage
-	this code, so we're going to finally just get rid of it.
-Who:	David S. Miller <davem@davemloft.net>
-
----------------------------
-
 What:	read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer)
 When:	December 2007
 Why:	These functions are a leftover from 2.4 times. They have several
@@ -348,3 +311,11 @@
 
 ---------------------------
 
+What:	iptables SAME target
+When:	1.1. 2008
+Files:	net/ipv4/netfilter/ipt_SAME.c, include/linux/netfilter_ipv4/ipt_SAME.h
+Why:	Obsolete for multiple years now, NAT core provides the same behaviour.
+	Unfixable broken wrt. 32/64 bit cleanness.
+Who:	Patrick McHardy <kaber@trash.net>
+
+---------------------------
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index af50f9b..4d880b3 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1014,49 +1014,6 @@
 
 	mga=		[HW,DRM]
 
-	migration_cost=
-			[KNL,SMP] debug: override scheduler migration costs
-			Format: <level-1-usecs>,<level-2-usecs>,...
-			This debugging option can be used to override the
-			default scheduler migration cost matrix. The numbers
-			are indexed by 'CPU domain distance'.
-			E.g. migration_cost=1000,2000,3000 on an SMT NUMA
-			box will set up an intra-core migration cost of
-			1 msec, an inter-core migration cost of 2 msecs,
-			and an inter-node migration cost of 3 msecs.
-
-			WARNING: using the wrong values here can break
-			scheduler performance, so it's only for scheduler
-			development purposes, not production environments.
-
-	migration_debug=
-			[KNL,SMP] migration cost auto-detect verbosity
-			Format=<0|1|2>
-			If a system's migration matrix reported at bootup
-			seems erroneous then this option can be used to
-			increase verbosity of the detection process.
-			We default to 0 (no extra messages), 1 will print
-			some more information, and 2 will be really
-			verbose (probably only useful if you also have a
-			serial console attached to the system).
-
-	migration_factor=
-			[KNL,SMP] multiply/divide migration costs by a factor
-			Format=<percent>
-			This debug option can be used to proportionally
-			increase or decrease the auto-detected migration
-			costs for all entries of the migration matrix.
-			E.g. migration_factor=150 will increase migration
-			costs by 50%. (and thus the scheduler will be less
-			eager migrating cache-hot tasks)
-			migration_factor=80 will decrease migration costs
-			by 20%. (thus the scheduler will be more eager to
-			migrate tasks)
-
-			WARNING: using the wrong values here can break
-			scheduler performance, so it's only for scheduler
-			development purposes, not production environments.
-
 	mousedev.tap_time=
 			[MOUSE] Maximum time between finger touching and
 			leaving touchpad surface for touch to be considered
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 153d84d..d63f480 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -96,9 +96,6 @@
 	- the new routing mechanism
 shaper.txt
 	- info on the module that can shape/limit transmitted traffic.
-sk98lin.txt
-	- Marvell Yukon Chipset / SysKonnect SK-98xx compliant Gigabit
-	  Ethernet Adapter family driver info
 skfp.txt
 	- SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info.
 smc9.txt
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index af6a63a..09c184e 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -874,8 +874,7 @@
 accept_source_route - INTEGER
 	Accept source routing (routing extension header).
 
-	> 0: Accept routing header.
-	= 0: Accept only routing header type 2.
+	>= 0: Accept only routing header type 2.
 	< 0: Do not accept routing header.
 
 	Default: 0
diff --git a/Documentation/networking/l2tp.txt b/Documentation/networking/l2tp.txt
new file mode 100644
index 0000000..2451f55
--- /dev/null
+++ b/Documentation/networking/l2tp.txt
@@ -0,0 +1,169 @@
+This brief document describes how to use the kernel's PPPoL2TP driver
+to provide L2TP functionality. L2TP is a protocol that tunnels one or
+more PPP sessions over a UDP tunnel. It is commonly used for VPNs
+(L2TP/IPSec) and by ISPs to tunnel subscriber PPP sessions over an IP
+network infrastructure.
+
+Design
+======
+
+The PPPoL2TP driver, drivers/net/pppol2tp.c, provides a mechanism by
+which PPP frames carried through an L2TP session are passed through
+the kernel's PPP subsystem. The standard PPP daemon, pppd, handles all
+PPP interaction with the peer. PPP network interfaces are created for
+each local PPP endpoint.
+
+The L2TP protocol http://www.faqs.org/rfcs/rfc2661.html defines L2TP
+control and data frames. L2TP control frames carry messages between
+L2TP clients/servers and are used to setup / teardown tunnels and
+sessions. An L2TP client or server is implemented in userspace and
+will use a regular UDP socket per tunnel. L2TP data frames carry PPP
+frames, which may be PPP control or PPP data. The kernel's PPP
+subsystem arranges for PPP control frames to be delivered to pppd,
+while data frames are forwarded as usual.
+
+Each tunnel and session within a tunnel is assigned a unique tunnel_id
+and session_id. These ids are carried in the L2TP header of every
+control and data packet. The pppol2tp driver uses them to lookup
+internal tunnel and/or session contexts. Zero tunnel / session ids are
+treated specially - zero ids are never assigned to tunnels or sessions
+in the network. In the driver, the tunnel context keeps a pointer to
+the tunnel UDP socket. The session context keeps a pointer to the
+PPPoL2TP socket, as well as other data that lets the driver interface
+to the kernel PPP subsystem.
+
+Note that the pppol2tp kernel driver handles only L2TP data frames;
+L2TP control frames are simply passed up to userspace in the UDP
+tunnel socket. The kernel handles all datapath aspects of the
+protocol, including data packet resequencing (if enabled).
+
+There are a number of requirements on the userspace L2TP daemon in
+order to use the pppol2tp driver.
+
+1. Use a UDP socket per tunnel.
+
+2. Create a single PPPoL2TP socket per tunnel bound to a special null
+   session id. This is used only for communicating with the driver but
+   must remain open while the tunnel is active. Opening this tunnel
+   management socket causes the driver to mark the tunnel socket as an
+   L2TP UDP encapsulation socket and flags it for use by the
+   referenced tunnel id. This hooks up the UDP receive path via
+   udp_encap_rcv() in net/ipv4/udp.c. PPP data frames are never passed
+   in this special PPPoX socket.
+
+3. Create a PPPoL2TP socket per L2TP session. This is typically done
+   by starting pppd with the pppol2tp plugin and appropriate
+   arguments. A PPPoL2TP tunnel management socket (Step 2) must be
+   created before the first PPPoL2TP session socket is created.
+
+When creating PPPoL2TP sockets, the application provides information
+to the driver about the socket in a socket connect() call. Source and
+destination tunnel and session ids are provided, as well as the file
+descriptor of a UDP socket. See struct pppol2tp_addr in
+include/linux/if_ppp.h. Note that zero tunnel / session ids are
+treated specially. When creating the per-tunnel PPPoL2TP management
+socket in Step 2 above, zero source and destination session ids are
+specified, which tells the driver to prepare the supplied UDP file
+descriptor for use as an L2TP tunnel socket.
+
+Userspace may control behavior of the tunnel or session using
+setsockopt and ioctl on the PPPoX socket. The following socket
+options are supported:-
+
+DEBUG     - bitmask of debug message categories. See below.
+SENDSEQ   - 0 => don't send packets with sequence numbers
+            1 => send packets with sequence numbers
+RECVSEQ   - 0 => receive packet sequence numbers are optional
+            1 => drop receive packets without sequence numbers
+LNSMODE   - 0 => act as LAC.
+            1 => act as LNS.
+REORDERTO - reorder timeout (in millisecs). If 0, don't try to reorder.
+
+Only the DEBUG option is supported by the special tunnel management
+PPPoX socket.
+
+In addition to the standard PPP ioctls, a PPPIOCGL2TPSTATS is provided
+to retrieve tunnel and session statistics from the kernel using the
+PPPoX socket of the appropriate tunnel or session.
+
+Debugging
+=========
+
+The driver supports a flexible debug scheme where kernel trace
+messages may be optionally enabled per tunnel and per session. Care is
+needed when debugging a live system since the messages are not
+rate-limited and a busy system could be swamped. Userspace uses
+setsockopt on the PPPoX socket to set a debug mask.
+
+The following debug mask bits are available:
+
+PPPOL2TP_MSG_DEBUG    verbose debug (if compiled in)
+PPPOL2TP_MSG_CONTROL  userspace - kernel interface
+PPPOL2TP_MSG_SEQ      sequence numbers handling
+PPPOL2TP_MSG_DATA     data packets
+
+Sample Userspace Code
+=====================
+
+1. Create tunnel management PPPoX socket
+
+        kernel_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
+        if (kernel_fd >= 0) {
+                struct sockaddr_pppol2tp sax;
+                struct sockaddr_in const *peer_addr;
+
+                peer_addr = l2tp_tunnel_get_peer_addr(tunnel);
+                memset(&sax, 0, sizeof(sax));
+                sax.sa_family = AF_PPPOX;
+                sax.sa_protocol = PX_PROTO_OL2TP;
+                sax.pppol2tp.fd = udp_fd;       /* fd of tunnel UDP socket */
+                sax.pppol2tp.addr.sin_addr.s_addr = peer_addr->sin_addr.s_addr;
+                sax.pppol2tp.addr.sin_port = peer_addr->sin_port;
+                sax.pppol2tp.addr.sin_family = AF_INET;
+                sax.pppol2tp.s_tunnel = tunnel_id;
+                sax.pppol2tp.s_session = 0;     /* special case: mgmt socket */
+                sax.pppol2tp.d_tunnel = 0;
+                sax.pppol2tp.d_session = 0;     /* special case: mgmt socket */
+
+                if(connect(kernel_fd, (struct sockaddr *)&sax, sizeof(sax) ) < 0 ) {
+                        perror("connect failed");
+                        result = -errno;
+                        goto err;
+                }
+        }
+
+2. Create session PPPoX data socket
+
+        struct sockaddr_pppol2tp sax;
+        int fd;
+
+        /* Note, the target socket must be bound already, else it will not be ready */
+        sax.sa_family = AF_PPPOX;
+        sax.sa_protocol = PX_PROTO_OL2TP;
+        sax.pppol2tp.fd = tunnel_fd;
+        sax.pppol2tp.addr.sin_addr.s_addr = addr->sin_addr.s_addr;
+        sax.pppol2tp.addr.sin_port = addr->sin_port;
+        sax.pppol2tp.addr.sin_family = AF_INET;
+        sax.pppol2tp.s_tunnel  = tunnel_id;
+        sax.pppol2tp.s_session = session_id;
+        sax.pppol2tp.d_tunnel  = peer_tunnel_id;
+        sax.pppol2tp.d_session = peer_session_id;
+
+        /* session_fd is the fd of the session's PPPoL2TP socket.
+         * tunnel_fd is the fd of the tunnel UDP socket.
+         */
+        fd = connect(session_fd, (struct sockaddr *)&sax, sizeof(sax));
+        if (fd < 0 )    {
+                return -errno;
+        }
+        return 0;
+
+Miscellanous
+============
+
+The PPPoL2TP driver was developed as part of the OpenL2TP project by
+Katalix Systems Ltd. OpenL2TP is a full-featured L2TP client / server,
+designed from the ground up to have the L2TP datapath in the
+kernel. The project also implemented the pppol2tp plugin for pppd
+which allows pppd to use the kernel driver. Details can be found at
+http://openl2tp.sourceforge.net.
diff --git a/Documentation/networking/multiqueue.txt b/Documentation/networking/multiqueue.txt
new file mode 100644
index 0000000..00b60cc
--- /dev/null
+++ b/Documentation/networking/multiqueue.txt
@@ -0,0 +1,111 @@
+
+		HOWTO for multiqueue network device support
+		===========================================
+
+Section 1: Base driver requirements for implementing multiqueue support
+Section 2: Qdisc support for multiqueue devices
+Section 3: Brief howto using PRIO or RR for multiqueue devices
+
+
+Intro: Kernel support for multiqueue devices
+---------------------------------------------------------
+
+Kernel support for multiqueue devices is only an API that is presented to the
+netdevice layer for base drivers to implement.  This feature is part of the
+core networking stack, and all network devices will be running on the
+multiqueue-aware stack.  If a base driver only has one queue, then these
+changes are transparent to that driver.
+
+
+Section 1: Base driver requirements for implementing multiqueue support
+-----------------------------------------------------------------------
+
+Base drivers are required to use the new alloc_etherdev_mq() or
+alloc_netdev_mq() functions to allocate the subqueues for the device.  The
+underlying kernel API will take care of the allocation and deallocation of
+the subqueue memory, as well as netdev configuration of where the queues
+exist in memory.
+
+The base driver will also need to manage the queues as it does the global
+netdev->queue_lock today.  Therefore base drivers should use the
+netif_{start|stop|wake}_subqueue() functions to manage each queue while the
+device is still operational.  netdev->queue_lock is still used when the device
+comes online or when it's completely shut down (unregister_netdev(), etc.).
+
+Finally, the base driver should indicate that it is a multiqueue device.  The
+feature flag NETIF_F_MULTI_QUEUE should be added to the netdev->features
+bitmap on device initialization.  Below is an example from e1000:
+
+#ifdef CONFIG_E1000_MQ
+	if ( (adapter->hw.mac.type == e1000_82571) ||
+	     (adapter->hw.mac.type == e1000_82572) ||
+	     (adapter->hw.mac.type == e1000_80003es2lan))
+		netdev->features |= NETIF_F_MULTI_QUEUE;
+#endif
+
+
+Section 2: Qdisc support for multiqueue devices
+-----------------------------------------------
+
+Currently two qdiscs support multiqueue devices.  A new round-robin qdisc,
+sch_rr, and sch_prio. The qdisc is responsible for classifying the skb's to
+bands and queues, and will store the queue mapping into skb->queue_mapping.
+Use this field in the base driver to determine which queue to send the skb
+to.
+
+sch_rr has been added for hardware that doesn't want scheduling policies from
+software, so it's a straight round-robin qdisc.  It uses the same syntax and
+classification priomap that sch_prio uses, so it should be intuitive to
+configure for people who've used sch_prio.
+
+The PRIO qdisc naturally plugs into a multiqueue device.  If PRIO has been
+built with NET_SCH_PRIO_MQ, then upon load, it will make sure the number of
+bands requested is equal to the number of queues on the hardware.  If they
+are equal, it sets a one-to-one mapping up between the queues and bands.  If
+they're not equal, it will not load the qdisc.  This is the same behavior
+for RR.  Once the association is made, any skb that is classified will have
+skb->queue_mapping set, which will allow the driver to properly queue skb's
+to multiple queues.
+
+
+Section 3: Brief howto using PRIO and RR for multiqueue devices
+---------------------------------------------------------------
+
+The userspace command 'tc,' part of the iproute2 package, is used to configure
+qdiscs.  To add the PRIO qdisc to your network device, assuming the device is
+called eth0, run the following command:
+
+# tc qdisc add dev eth0 root handle 1: prio bands 4 multiqueue
+
+This will create 4 bands, 0 being highest priority, and associate those bands
+to the queues on your NIC.  Assuming eth0 has 4 Tx queues, the band mapping
+would look like:
+
+band 0 => queue 0
+band 1 => queue 1
+band 2 => queue 2
+band 3 => queue 3
+
+Traffic will begin flowing through each queue if your TOS values are assigning
+traffic across the various bands.  For example, ssh traffic will always try to
+go out band 0 based on TOS -> Linux priority conversion (realtime traffic),
+so it will be sent out queue 0.  ICMP traffic (pings) fall into the "normal"
+traffic classification, which is band 1.  Therefore pings will be send out
+queue 1 on the NIC.
+
+Note the use of the multiqueue keyword.  This is only in versions of iproute2
+that support multiqueue networking devices; if this is omitted when loading
+a qdisc onto a multiqueue device, the qdisc will load and operate the same
+if it were loaded onto a single-queue device (i.e. - sends all traffic to
+queue 0).
+
+Another alternative to multiqueue band allocation can be done by using the
+multiqueue option and specify 0 bands.  If this is the case, the qdisc will
+allocate the number of bands to equal the number of queues that the device
+reports, and bring the qdisc online.
+
+The behavior of tc filters remains the same, where it will override TOS priority
+classification.
+
+
+Author: Peter P. Waskiewicz Jr. <peter.p.waskiewicz.jr@intel.com>
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
index ce1361f..3786929 100644
--- a/Documentation/networking/netdevices.txt
+++ b/Documentation/networking/netdevices.txt
@@ -20,6 +20,30 @@
 separately allocated data is attached to the network device
 (dev->priv) then it is up to the module exit handler to free that.
 
+MTU
+===
+Each network device has a Maximum Transfer Unit. The MTU does not
+include any link layer protocol overhead. Upper layer protocols must
+not pass a socket buffer (skb) to a device to transmit with more data
+than the mtu. The MTU does not include link layer header overhead, so
+for example on Ethernet if the standard MTU is 1500 bytes used, the
+actual skb will contain up to 1514 bytes because of the Ethernet
+header. Devices should allow for the 4 byte VLAN header as well.
+
+Segmentation Offload (GSO, TSO) is an exception to this rule.  The
+upper layer protocol may pass a large socket buffer to the device
+transmit routine, and the device will break that up into separate
+packets based on the current MTU.
+
+MTU is symmetrical and applies both to receive and transmit. A device
+must be able to receive at least the maximum size packet allowed by
+the MTU. A network device may use the MTU as mechanism to size receive
+buffers, but the device should allow packets with VLAN header. With
+standard Ethernet mtu of 1500 bytes, the device should allow up to
+1518 byte packets (1500 + 14 header + 4 tag).  The device may either:
+drop, truncate, or pass up oversize packets, but dropping oversize
+packets is preferred.
+
 
 struct net_device synchronization rules
 =======================================
@@ -43,16 +67,17 @@
 
 dev->hard_start_xmit:
 	Synchronization: netif_tx_lock spinlock.
+
 	When the driver sets NETIF_F_LLTX in dev->features this will be
 	called without holding netif_tx_lock. In this case the driver
 	has to lock by itself when needed. It is recommended to use a try lock
-	for this and return -1 when the spin lock fails. 
+	for this and return NETDEV_TX_LOCKED when the spin lock fails.
 	The locking there should also properly protect against 
-	set_multicast_list
-	Context: Process with BHs disabled or BH (timer).
-	Notes: netif_queue_stopped() is guaranteed false
-               Interrupts must be enabled when calling hard_start_xmit.
-                (Interrupts must also be enabled when enabling the BH handler.)
+	set_multicast_list.
+
+	Context: Process with BHs disabled or BH (timer),
+	         will be called with interrupts disabled by netconsole.
+
 	Return codes: 
 	o NETDEV_TX_OK everything ok. 
 	o NETDEV_TX_BUSY Cannot transmit packet, try later 
@@ -74,4 +99,5 @@
 	Synchronization: __LINK_STATE_RX_SCHED bit in dev->state.  See
 		dev_close code and comments in net/core/dev.c for more info.
 	Context: softirq
+	         will be called with interrupts disabled by netconsole.
 
diff --git a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt
deleted file mode 100644
index 8590a95..0000000
--- a/Documentation/networking/sk98lin.txt
+++ /dev/null
@@ -1,568 +0,0 @@
-(C)Copyright 1999-2004 Marvell(R).
-All rights reserved
-===========================================================================
-
-sk98lin.txt created 13-Feb-2004
-
-Readme File for sk98lin v6.23
-Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX
-
-This file contains
- 1  Overview
- 2  Required Files
- 3  Installation
-    3.1  Driver Installation
-    3.2  Inclusion of adapter at system start
- 4  Driver Parameters
-    4.1  Per-Port Parameters
-    4.2  Adapter Parameters
- 5  Large Frame Support
- 6  VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
- 7  Troubleshooting
-
-===========================================================================
-
-
-1  Overview
-===========
-
-The sk98lin driver supports the Marvell Yukon and SysKonnect 
-SK-98xx/SK-95xx compliant Gigabit Ethernet Adapter on Linux. It has 
-been tested with Linux on Intel/x86 machines.
-***
-
-
-2  Required Files
-=================
-
-The linux kernel source.
-No additional files required.
-***
-
-
-3  Installation
-===============
-
-It is recommended to download the latest version of the driver from the 
-SysKonnect web site www.syskonnect.com. If you have downloaded the latest
-driver, the Linux kernel has to be patched before the driver can be 
-installed. For details on how to patch a Linux kernel, refer to the 
-patch.txt file.
-
-3.1  Driver Installation
-------------------------
-
-The following steps describe the actions that are required to install
-the driver and to start it manually. These steps should be carried
-out for the initial driver setup. Once confirmed to be ok, they can
-be included in the system start.
-
-NOTE 1: To perform the following tasks you need 'root' access.
-
-NOTE 2: In case of problems, please read the section "Troubleshooting" 
-        below.
-
-The driver can either be integrated into the kernel or it can be compiled 
-as a module. Select the appropriate option during the kernel 
-configuration.
-
-Compile/use the driver as a module
-----------------------------------
-To compile the driver, go to the directory /usr/src/linux and
-execute the command "make menuconfig" or "make xconfig" and proceed as 
-follows:
-
-To integrate the driver permanently into the kernel, proceed as follows:
-
-1. Select the menu "Network device support" and then "Ethernet(1000Mbit)"
-2. Mark "Marvell Yukon Chipset / SysKonnect SK-98xx family support" 
-   with (*) 
-3. Build a new kernel when the configuration of the above options is 
-   finished.
-4. Install the new kernel.
-5. Reboot your system.
-
-To use the driver as a module, proceed as follows:
-
-1. Enable 'loadable module support' in the kernel.
-2. For automatic driver start, enable the 'Kernel module loader'.
-3. Select the menu "Network device support" and then "Ethernet(1000Mbit)"
-4. Mark "Marvell Yukon Chipset / SysKonnect SK-98xx family support" 
-   with (M)
-5. Execute the command "make modules".
-6. Execute the command "make modules_install".
-   The appropriate modules will be installed.
-7. Reboot your system.
-
-
-Load the module manually
-------------------------
-To load the module manually, proceed as follows:
-
-1. Enter "modprobe sk98lin".
-2. If a Marvell Yukon or SysKonnect SK-98xx adapter is installed in 
-   your computer and you have a /proc file system, execute the command:
-   "ls /proc/net/sk98lin/" 
-   This should produce an output containing a line with the following 
-   format:
-   eth0   eth1  ...
-   which indicates that your adapter has been found and initialized.
-   
-   NOTE 1: If you have more than one Marvell Yukon or SysKonnect SK-98xx 
-           adapter installed, the adapters will be listed as 'eth0', 
-                   'eth1', 'eth2', etc.
-                   For each adapter, repeat steps 3 and 4 below.
-
-   NOTE 2: If you have other Ethernet adapters installed, your Marvell
-           Yukon or SysKonnect SK-98xx adapter will be mapped to the 
-                   next available number, e.g. 'eth1'. The mapping is executed 
-                   automatically.
-           The module installation message (displayed either in a system
-           log file or on the console) prints a line for each adapter 
-           found containing the corresponding 'ethX'.
-
-3. Select an IP address and assign it to the respective adapter by 
-   entering:
-   ifconfig eth0 <ip-address>
-   With this command, the adapter is connected to the Ethernet. 
-   
-   SK-98xx Gigabit Ethernet Server Adapters: The yellow LED on the adapter 
-   is now active, the link status LED of the primary port is active and 
-   the link status LED of the secondary port (on dual port adapters) is 
-   blinking (if the ports are connected to a switch or hub).
-   SK-98xx V2.0 Gigabit Ethernet Adapters: The link status LED is active.
-   In addition, you will receive a status message on the console stating
-   "ethX: network connection up using port Y" and showing the selected 
-   connection parameters (x stands for the ethernet device number 
-   (0,1,2, etc), y stands for the port name (A or B)).
-
-   NOTE: If you are in doubt about IP addresses, ask your network
-         administrator for assistance.
-  
-4. Your adapter should now be fully operational.
-   Use 'ping <otherstation>' to verify the connection to other computers 
-   on your network.
-5. To check the adapter configuration view /proc/net/sk98lin/[devicename].
-   For example by executing:    
-   "cat /proc/net/sk98lin/eth0" 
-
-Unload the module
------------------
-To stop and unload the driver modules, proceed as follows:
-
-1. Execute the command "ifconfig eth0 down".
-2. Execute the command "rmmod sk98lin".
-
-3.2  Inclusion of adapter at system start
------------------------------------------
-
-Since a large number of different Linux distributions are 
-available, we are unable to describe a general installation procedure
-for the driver module.
-Because the driver is now integrated in the kernel, installation should
-be easy, using the standard mechanism of your distribution.
-Refer to the distribution's manual for installation of ethernet adapters.
-
-***
-
-4  Driver Parameters
-====================
-
-Parameters can be set at the command line after the module has been 
-loaded with the command 'modprobe'.
-In some distributions, the configuration tools are able to pass parameters
-to the driver module.
-
-If you use the kernel module loader, you can set driver parameters
-in the file /etc/modprobe.conf (or /etc/modules.conf in 2.4 or earlier).
-To set the driver parameters in this file, proceed as follows:
-
-1. Insert a line of the form :
-   options sk98lin ...
-   For "...", the same syntax is required as described for the command
-   line parameters of modprobe below.
-2. To activate the new parameters, either reboot your computer
-   or 
-   unload and reload the driver.
-   The syntax of the driver parameters is:
-
-        modprobe sk98lin parameter=value1[,value2[,value3...]]
-
-   where value1 refers to the first adapter, value2 to the second etc.
-
-NOTE: All parameters are case sensitive. Write them exactly as shown 
-      below.
-
-Example:
-Suppose you have two adapters. You want to set auto-negotiation
-on the first adapter to ON and on the second adapter to OFF.
-You also want to set DuplexCapabilities on the first adapter
-to FULL, and on the second adapter to HALF.
-Then, you must enter:
-
-        modprobe sk98lin AutoNeg_A=On,Off DupCap_A=Full,Half
-
-NOTE: The number of adapters that can be configured this way is
-      limited in the driver (file skge.c, constant SK_MAX_CARD_PARAM).
-      The current limit is 16. If you happen to install
-      more adapters, adjust this and recompile.
-
-
-4.1  Per-Port Parameters
-------------------------
-
-These settings are available for each port on the adapter.
-In the following description, '?' stands for the port for
-which you set the parameter (A or B).
-
-Speed
------
-Parameter:    Speed_?
-Values:       10, 100, 1000, Auto
-Default:      Auto
-
-This parameter is used to set the speed capabilities. It is only valid 
-for the SK-98xx V2.0 copper adapters.
-Usually, the speed is negotiated between the two ports during link 
-establishment. If this fails, a port can be forced to a specific setting
-with this parameter.
-
-Auto-Negotiation
-----------------
-Parameter:    AutoNeg_?
-Values:       On, Off, Sense
-Default:      On
-  
-The "Sense"-mode automatically detects whether the link partner supports
-auto-negotiation or not.
-
-Duplex Capabilities
--------------------
-Parameter:    DupCap_?
-Values:       Half, Full, Both
-Default:      Both
-
-This parameters is only relevant if auto-negotiation for this port is 
-not set to "Sense". If auto-negotiation is set to "On", all three values
-are possible. If it is set to "Off", only "Full" and "Half" are allowed.
-This parameter is useful if your link partner does not support all
-possible combinations.
-
-Flow Control
-------------
-Parameter:    FlowCtrl_?
-Values:       Sym, SymOrRem, LocSend, None
-Default:      SymOrRem
-
-This parameter can be used to set the flow control capabilities the 
-port reports during auto-negotiation. It can be set for each port 
-individually.
-Possible modes:
-   -- Sym      = Symmetric: both link partners are allowed to send 
-                  PAUSE frames
-   -- SymOrRem = SymmetricOrRemote: both or only remote partner 
-                  are allowed to send PAUSE frames
-   -- LocSend  = LocalSend: only local link partner is allowed 
-                  to send PAUSE frames
-   -- None     = no link partner is allowed to send PAUSE frames
-  
-NOTE: This parameter is ignored if auto-negotiation is set to "Off".
-
-Role in Master-Slave-Negotiation (1000Base-T only)
---------------------------------------------------
-Parameter:    Role_?
-Values:       Auto, Master, Slave
-Default:      Auto
-
-This parameter is only valid for the SK-9821 and SK-9822 adapters.
-For two 1000Base-T ports to communicate, one must take the role of the
-master (providing timing information), while the other must be the 
-slave. Usually, this is negotiated between the two ports during link 
-establishment. If this fails, a port can be forced to a specific setting
-with this parameter.
-
-
-4.2  Adapter Parameters
------------------------
-
-Connection Type (SK-98xx V2.0 copper adapters only)
----------------
-Parameter:    ConType
-Values:       Auto, 100FD, 100HD, 10FD, 10HD
-Default:      Auto
-
-The parameter 'ConType' is a combination of all five per-port parameters
-within one single parameter. This simplifies the configuration of both ports
-of an adapter card! The different values of this variable reflect the most 
-meaningful combinations of port parameters.
-
-The following table shows the values of 'ConType' and the corresponding
-combinations of the per-port parameters:
-
-    ConType   |  DupCap   AutoNeg   FlowCtrl   Role             Speed
-    ----------+------------------------------------------------------
-    Auto      |  Both     On        SymOrRem   Auto             Auto
-    100FD     |  Full     Off       None       Auto (ignored)   100
-    100HD     |  Half     Off       None       Auto (ignored)   100
-    10FD      |  Full     Off       None       Auto (ignored)   10
-    10HD      |  Half     Off       None       Auto (ignored)   10
-
-Stating any other port parameter together with this 'ConType' variable
-will result in a merged configuration of those settings. This due to 
-the fact, that the per-port parameters (e.g. Speed_? ) have a higher
-priority than the combined variable 'ConType'.
-
-NOTE: This parameter is always used on both ports of the adapter card.
-
-Interrupt Moderation
---------------------
-Parameter:    Moderation
-Values:       None, Static, Dynamic
-Default:      None
-
-Interrupt moderation is employed to limit the maximum number of interrupts
-the driver has to serve. That is, one or more interrupts (which indicate any
-transmit or receive packet to be processed) are queued until the driver 
-processes them. When queued interrupts are to be served, is determined by the
-'IntsPerSec' parameter, which is explained later below.
-
-Possible modes:
-
-   -- None - No interrupt moderation is applied on the adapter card. 
-      Therefore, each transmit or receive interrupt is served immediately
-      as soon as it appears on the interrupt line of the adapter card.
-
-   -- Static - Interrupt moderation is applied on the adapter card. 
-      All transmit and receive interrupts are queued until a complete
-      moderation interval ends. If such a moderation interval ends, all
-      queued interrupts are processed in one big bunch without any delay.
-      The term 'static' reflects the fact, that interrupt moderation is
-      always enabled, regardless how much network load is currently 
-      passing via a particular interface. In addition, the duration of
-      the moderation interval has a fixed length that never changes while
-      the driver is operational.
-
-   -- Dynamic - Interrupt moderation might be applied on the adapter card,
-      depending on the load of the system. If the driver detects that the
-      system load is too high, the driver tries to shield the system against 
-      too much network load by enabling interrupt moderation. If - at a later
-      time - the CPU utilization decreases again (or if the network load is 
-      negligible) the interrupt moderation will automatically be disabled.
-
-Interrupt moderation should be used when the driver has to handle one or more
-interfaces with a high network load, which - as a consequence - leads also to a
-high CPU utilization. When moderation is applied in such high network load 
-situations, CPU load might be reduced by 20-30%.
-
-NOTE: The drawback of using interrupt moderation is an increase of the round-
-trip-time (RTT), due to the queueing and serving of interrupts at dedicated
-moderation times.
-
-Interrupts per second
----------------------
-Parameter:    IntsPerSec
-Values:       30...40000 (interrupts per second)
-Default:      2000
-
-This parameter is only used if either static or dynamic interrupt moderation
-is used on a network adapter card. Using this parameter if no moderation is
-applied will lead to no action performed.
-
-This parameter determines the length of any interrupt moderation interval. 
-Assuming that static interrupt moderation is to be used, an 'IntsPerSec' 
-parameter value of 2000 will lead to an interrupt moderation interval of
-500 microseconds. 
-
-NOTE: The duration of the moderation interval is to be chosen with care.
-At first glance, selecting a very long duration (e.g. only 100 interrupts per 
-second) seems to be meaningful, but the increase of packet-processing delay 
-is tremendous. On the other hand, selecting a very short moderation time might
-compensate the use of any moderation being applied.
-
-
-Preferred Port
---------------
-Parameter:    PrefPort
-Values:       A, B
-Default:      A
-
-This is used to force the preferred port to A or B (on dual-port network 
-adapters). The preferred port is the one that is used if both are detected
-as fully functional.
-
-RLMT Mode (Redundant Link Management Technology)
-------------------------------------------------
-Parameter:    RlmtMode
-Values:       CheckLinkState,CheckLocalPort, CheckSeg, DualNet
-Default:      CheckLinkState
-
-RLMT monitors the status of the port. If the link of the active port 
-fails, RLMT switches immediately to the standby link. The virtual link is 
-maintained as long as at least one 'physical' link is up. 
-
-Possible modes:
-
-   -- CheckLinkState - Check link state only: RLMT uses the link state
-      reported by the adapter hardware for each individual port to 
-      determine whether a port can be used for all network traffic or 
-      not.
-
-   -- CheckLocalPort - In this mode, RLMT monitors the network path 
-      between the two ports of an adapter by regularly exchanging packets
-      between them. This mode requires a network configuration in which 
-      the two ports are able to "see" each other (i.e. there must not be 
-      any router between the ports).
-
-   -- CheckSeg - Check local port and segmentation: This mode supports the
-      same functions as the CheckLocalPort mode and additionally checks 
-      network segmentation between the ports. Therefore, this mode is only
-      to be used if Gigabit Ethernet switches are installed on the network
-      that have been configured to use the Spanning Tree protocol. 
-
-   -- DualNet - In this mode, ports A and B are used as separate devices. 
-      If you have a dual port adapter, port A will be configured as eth0 
-      and port B as eth1. Both ports can be used independently with 
-      distinct IP addresses. The preferred port setting is not used. 
-      RLMT is turned off.
-   
-NOTE: RLMT modes CLP and CLPSS are designed to operate in configurations 
-      where a network path between the ports on one adapter exists. 
-      Moreover, they are not designed to work where adapters are connected
-      back-to-back.
-***
-
-
-5  Large Frame Support
-======================
-
-The driver supports large frames (also called jumbo frames). Using large 
-frames can result in an improved throughput if transferring large amounts 
-of data.
-To enable large frames, set the MTU (maximum transfer unit) of the 
-interface to the desired value (up to 9000), execute the following 
-command:
-      ifconfig eth0 mtu 9000
-This will only work if you have two adapters connected back-to-back
-or if you use a switch that supports large frames. When using a switch, 
-it should be configured to allow large frames and auto-negotiation should  
-be set to OFF. The setting must be configured on all adapters that can be 
-reached by the large frames. If one adapter is not set to receive large 
-frames, it will simply drop them.
-
-You can switch back to the standard ethernet frame size by executing the 
-following command:
-      ifconfig eth0 mtu 1500
-
-To permanently configure this setting, add a script with the 'ifconfig' 
-line to the system startup sequence (named something like "S99sk98lin" 
-in /etc/rc.d/rc2.d).
-***
-
-
-6  VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
-==================================================================
-
-The Marvell Yukon/SysKonnect Linux drivers are able to support VLAN and 
-Link Aggregation according to IEEE standards 802.1, 802.1q, and 802.3ad. 
-These features are only available after installation of open source 
-modules available on the Internet:
-For VLAN go to: http://www.candelatech.com/~greear/vlan.html
-For Link Aggregation go to: http://www.st.rim.or.jp/~yumo
-
-NOTE: SysKonnect GmbH does not offer any support for these open source 
-      modules and does not take the responsibility for any kind of 
-      failures or problems arising in connection with these modules.
-
-NOTE: Configuring Link Aggregation on a SysKonnect dual link adapter may 
-      cause problems when unloading the driver.
-
-
-7  Troubleshooting
-==================
-
-If any problems occur during the installation process, check the 
-following list:
-
-
-Problem:  The SK-98xx adapter cannot be found by the driver.
-Solution: In /proc/pci search for the following entry:
-             'Ethernet controller: SysKonnect SK-98xx ...'
-          If this entry exists, the SK-98xx or SK-98xx V2.0 adapter has 
-          been found by the system and should be operational.
-          If this entry does not exist or if the file '/proc/pci' is not 
-          found, there may be a hardware problem or the PCI support may 
-          not be enabled in your kernel.
-          The adapter can be checked using the diagnostics program which 
-          is available on the SysKonnect web site:
-          www.syskonnect.com
-          
-          Some COMPAQ machines have problems dealing with PCI under Linux.
-          This problem is described in the 'PCI howto' document
-          (included in some distributions or available from the
-          web, e.g. at 'www.linux.org'). 
-
-
-Problem:  Programs such as 'ifconfig' or 'route' cannot be found or the 
-          error message 'Operation not permitted' is displayed.
-Reason:   You are not logged in as user 'root'.
-Solution: Logout and login as 'root' or change to 'root' via 'su'.
-
-
-Problem:  Upon use of the command 'ping <address>' the message
-          "ping: sendto: Network is unreachable" is displayed.
-Reason:   Your route is not set correctly.
-Solution: If you are using RedHat, you probably forgot to set up the 
-          route in the 'network configuration'.
-          Check the existing routes with the 'route' command and check 
-          if an entry for 'eth0' exists, and if so, if it is set correctly.
-
-
-Problem:  The driver can be started, the adapter is connected to the 
-          network, but you cannot receive or transmit any packets; 
-          e.g. 'ping' does not work.
-Reason:   There is an incorrect route in your routing table.
-Solution: Check the routing table with the command 'route' and read the 
-          manual help pages dealing with routes (enter 'man route').
-
-NOTE: Although the 2.2.x kernel versions generate the routing entry 
-      automatically, problems of this kind may occur here as well. We've 
-      come across a situation in which the driver started correctly at 
-      system start, but after the driver has been removed and reloaded,
-      the route of the adapter's network pointed to the 'dummy0'device 
-      and had to be corrected manually.
-
-
-Problem:  Your computer should act as a router between multiple 
-          IP subnetworks (using multiple adapters), but computers in 
-          other subnetworks cannot be reached.
-Reason:   Either the router's kernel is not configured for IP forwarding 
-          or the routing table and gateway configuration of at least one 
-          computer is not working.
-
-Problem:  Upon driver start, the following error message is displayed:
-          "eth0: -- ERROR --
-          Class: internal Software error
-          Nr:    0xcc
-          Msg:   SkGeInitPort() cannot init running ports"
-Reason:   You are using a driver compiled for single processor machines 
-          on a multiprocessor machine with SMP (Symmetric MultiProcessor) 
-          kernel.
-Solution: Configure your kernel appropriately and recompile the kernel or
-          the modules.
-
-
-
-If your problem is not listed here, please contact SysKonnect's technical
-support for help (linux@syskonnect.de).
-When contacting our technical support, please ensure that the following 
-information is available:
-- System Manufacturer and HW Informations (CPU, Memory... )
-- PCI-Boards in your system
-- Distribution
-- Kernel version
-- Driver version
-***
-
-
-
-***End of Readme File***
diff --git a/Documentation/networking/spider_net.txt b/Documentation/networking/spider_net.txt
new file mode 100644
index 0000000..4b4adb8
--- /dev/null
+++ b/Documentation/networking/spider_net.txt
@@ -0,0 +1,204 @@
+
+            The Spidernet Device Driver
+            ===========================
+
+Written by Linas Vepstas <linas@austin.ibm.com>
+
+Version of 7 June 2007
+
+Abstract
+========
+This document sketches the structure of portions of the spidernet
+device driver in the Linux kernel tree. The spidernet is a gigabit
+ethernet device built into the Toshiba southbridge commonly used
+in the SONY Playstation 3 and the IBM QS20 Cell blade.
+
+The Structure of the RX Ring.
+=============================
+The receive (RX) ring is a circular linked list of RX descriptors,
+together with three pointers into the ring that are used to manage its
+contents.
+
+The elements of the ring are called "descriptors" or "descrs"; they
+describe the received data. This includes a pointer to a buffer
+containing the received data, the buffer size, and various status bits.
+
+There are three primary states that a descriptor can be in: "empty",
+"full" and "not-in-use".  An "empty" or "ready" descriptor is ready
+to receive data from the hardware. A "full" descriptor has data in it,
+and is waiting to be emptied and processed by the OS. A "not-in-use"
+descriptor is neither empty or full; it is simply not ready. It may
+not even have a data buffer in it, or is otherwise unusable.
+
+During normal operation, on device startup, the OS (specifically, the
+spidernet device driver) allocates a set of RX descriptors and RX
+buffers. These are all marked "empty", ready to receive data. This
+ring is handed off to the hardware, which sequentially fills in the
+buffers, and marks them "full". The OS follows up, taking the full
+buffers, processing them, and re-marking them empty.
+
+This filling and emptying is managed by three pointers, the "head"
+and "tail" pointers, managed by the OS, and a hardware current
+descriptor pointer (GDACTDPA). The GDACTDPA points at the descr
+currently being filled. When this descr is filled, the hardware
+marks it full, and advances the GDACTDPA by one.  Thus, when there is
+flowing RX traffic, every descr behind it should be marked "full",
+and everything in front of it should be "empty".  If the hardware
+discovers that the current descr is not empty, it will signal an
+interrupt, and halt processing.
+
+The tail pointer tails or trails the hardware pointer. When the
+hardware is ahead, the tail pointer will be pointing at a "full"
+descr. The OS will process this descr, and then mark it "not-in-use",
+and advance the tail pointer.  Thus, when there is flowing RX traffic,
+all of the descrs in front of the tail pointer should be "full", and
+all of those behind it should be "not-in-use". When RX traffic is not
+flowing, then the tail pointer can catch up to the hardware pointer.
+The OS will then note that the current tail is "empty", and halt
+processing.
+
+The head pointer (somewhat mis-named) follows after the tail pointer.
+When traffic is flowing, then the head pointer will be pointing at
+a "not-in-use" descr. The OS will perform various housekeeping duties
+on this descr. This includes allocating a new data buffer and
+dma-mapping it so as to make it visible to the hardware. The OS will
+then mark the descr as "empty", ready to receive data. Thus, when there
+is flowing RX traffic, everything in front of the head pointer should
+be "not-in-use", and everything behind it should be "empty". If no
+RX traffic is flowing, then the head pointer can catch up to the tail
+pointer, at which point the OS will notice that the head descr is
+"empty", and it will halt processing.
+
+Thus, in an idle system, the GDACTDPA, tail and head pointers will
+all be pointing at the same descr, which should be "empty". All of the
+other descrs in the ring should be "empty" as well.
+
+The show_rx_chain() routine will print out the the locations of the
+GDACTDPA, tail and head pointers. It will also summarize the contents
+of the ring, starting at the tail pointer, and listing the status
+of the descrs that follow.
+
+A typical example of the output, for a nearly idle system, might be
+
+net eth1: Total number of descrs=256
+net eth1: Chain tail located at descr=20
+net eth1: Chain head is at 20
+net eth1: HW curr desc (GDACTDPA) is at 21
+net eth1: Have 1 descrs with stat=x40800101
+net eth1: HW next desc (GDACNEXTDA) is at 22
+net eth1: Last 255 descrs with stat=xa0800000
+
+In the above, the hardware has filled in one descr, number 20. Both
+head and tail are pointing at 20, because it has not yet been emptied.
+Meanwhile, hw is pointing at 21, which is free.
+
+The "Have nnn decrs" refers to the descr starting at the tail: in this
+case, nnn=1 descr, starting at descr 20. The "Last nnn descrs" refers
+to all of the rest of the descrs, from the last status change. The "nnn"
+is a count of how many descrs have exactly the same status.
+
+The status x4... corresponds to "full" and status xa... corresponds
+to "empty". The actual value printed is RXCOMST_A.
+
+In the device driver source code, a different set of names are
+used for these same concepts, so that
+
+"empty" == SPIDER_NET_DESCR_CARDOWNED == 0xa
+"full"  == SPIDER_NET_DESCR_FRAME_END == 0x4
+"not in use" == SPIDER_NET_DESCR_NOT_IN_USE == 0xf
+
+
+The RX RAM full bug/feature
+===========================
+
+As long as the OS can empty out the RX buffers at a rate faster than
+the hardware can fill them, there is no problem. If, for some reason,
+the OS fails to empty the RX ring fast enough, the hardware GDACTDPA
+pointer will catch up to the head, notice the not-empty condition,
+ad stop. However, RX packets may still continue arriving on the wire.
+The spidernet chip can save some limited number of these in local RAM.
+When this local ram fills up, the spider chip will issue an interrupt
+indicating this (GHIINT0STS will show ERRINT, and the GRMFLLINT bit
+will be set in GHIINT1STS).  When the RX ram full condition occurs,
+a certain bug/feature is triggered that has to be specially handled.
+This section describes the special handling for this condition.
+
+When the OS finally has a chance to run, it will empty out the RX ring.
+In particular, it will clear the descriptor on which the hardware had
+stopped. However, once the hardware has decided that a certain
+descriptor is invalid, it will not restart at that descriptor; instead
+it will restart at the next descr. This potentially will lead to a
+deadlock condition, as the tail pointer will be pointing at this descr,
+which, from the OS point of view, is empty; the OS will be waiting for
+this descr to be filled. However, the hardware has skipped this descr,
+and is filling the next descrs. Since the OS doesn't see this, there
+is a potential deadlock, with the OS waiting for one descr to fill,
+while the hardware is waiting for a different set of descrs to become
+empty.
+
+A call to show_rx_chain() at this point indicates the nature of the
+problem. A typical print when the network is hung shows the following:
+
+net eth1: Spider RX RAM full, incoming packets might be discarded!
+net eth1: Total number of descrs=256
+net eth1: Chain tail located at descr=255
+net eth1: Chain head is at 255
+net eth1: HW curr desc (GDACTDPA) is at 0
+net eth1: Have 1 descrs with stat=xa0800000
+net eth1: HW next desc (GDACNEXTDA) is at 1
+net eth1: Have 127 descrs with stat=x40800101
+net eth1: Have 1 descrs with stat=x40800001
+net eth1: Have 126 descrs with stat=x40800101
+net eth1: Last 1 descrs with stat=xa0800000
+
+Both the tail and head pointers are pointing at descr 255, which is
+marked xa... which is "empty". Thus, from the OS point of view, there
+is nothing to be done. In particular, there is the implicit assumption
+that everything in front of the "empty" descr must surely also be empty,
+as explained in the last section. The OS is waiting for descr 255 to
+become non-empty, which, in this case, will never happen.
+
+The HW pointer is at descr 0. This descr is marked 0x4.. or "full".
+Since its already full, the hardware can do nothing more, and thus has
+halted processing. Notice that descrs 0 through 254 are all marked
+"full", while descr 254 and 255 are empty. (The "Last 1 descrs" is
+descr 254, since tail was at 255.) Thus, the system is deadlocked,
+and there can be no forward progress; the OS thinks there's nothing
+to do, and the hardware has nowhere to put incoming data.
+
+This bug/feature is worked around with the spider_net_resync_head_ptr()
+routine. When the driver receives RX interrupts, but an examination
+of the RX chain seems to show it is empty, then it is probable that
+the hardware has skipped a descr or two (sometimes dozens under heavy
+network conditions). The spider_net_resync_head_ptr() subroutine will
+search the ring for the next full descr, and the driver will resume
+operations there.  Since this will leave "holes" in the ring, there
+is also a spider_net_resync_tail_ptr() that will skip over such holes.
+
+As of this writing, the spider_net_resync() strategy seems to work very
+well, even under heavy network loads.
+
+
+The TX ring
+===========
+The TX ring uses a low-watermark interrupt scheme to make sure that
+the TX queue is appropriately serviced for large packet sizes.
+
+For packet sizes greater than about 1KBytes, the kernel can fill
+the TX ring quicker than the device can drain it. Once the ring
+is full, the netdev is stopped. When there is room in the ring,
+the netdev needs to be reawakened, so that more TX packets are placed
+in the ring. The hardware can empty the ring about four times per jiffy,
+so its not appropriate to wait for the poll routine to refill, since
+the poll routine runs only once per jiffy.  The low-watermark mechanism
+marks a descr about 1/4th of the way from the bottom of the queue, so
+that an interrupt is generated when the descr is processed. This
+interrupt wakes up the netdev, which can then refill the queue.
+For large packets, this mechanism generates a relatively small number
+of interrupts, about 1K/sec. For smaller packets, this will drop to zero
+interrupts, as the hardware can empty the queue faster than the kernel
+can fill it.
+
+
+ ======= END OF DOCUMENT ========
+
diff --git a/Documentation/power_supply_class.txt b/Documentation/power_supply_class.txt
new file mode 100644
index 0000000..9758cf4
--- /dev/null
+++ b/Documentation/power_supply_class.txt
@@ -0,0 +1,167 @@
+Linux power supply class
+========================
+
+Synopsis
+~~~~~~~~
+Power supply class used to represent battery, UPS, AC or DC power supply
+properties to user-space.
+
+It defines core set of attributes, which should be applicable to (almost)
+every power supply out there. Attributes are available via sysfs and uevent
+interfaces.
+
+Each attribute has well defined meaning, up to unit of measure used. While
+the attributes provided are believed to be universally applicable to any
+power supply, specific monitoring hardware may not be able to provide them
+all, so any of them may be skipped.
+
+Power supply class is extensible, and allows to define drivers own attributes.
+The core attribute set is subject to the standard Linux evolution (i.e.
+if it will be found that some attribute is applicable to many power supply
+types or their drivers, it can be added to the core set).
+
+It also integrates with LED framework, for the purpose of providing
+typically expected feedback of battery charging/fully charged status and
+AC/USB power supply online status. (Note that specific details of the
+indication (including whether to use it at all) are fully controllable by
+user and/or specific machine defaults, per design principles of LED
+framework).
+
+
+Attributes/properties
+~~~~~~~~~~~~~~~~~~~~~
+Power supply class has predefined set of attributes, this eliminates code
+duplication across drivers. Power supply class insist on reusing its
+predefined attributes *and* their units.
+
+So, userspace gets predictable set of attributes and their units for any
+kind of power supply, and can process/present them to a user in consistent
+manner. Results for different power supplies and machines are also directly
+comparable.
+
+See drivers/power/ds2760_battery.c and drivers/power/pda_power.c for the
+example how to declare and handle attributes.
+
+
+Units
+~~~~~
+Quoting include/linux/power_supply.h:
+
+  All voltages, currents, charges, energies, time and temperatures in µV,
+  µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+  stated. It's driver's job to convert its raw values to units in which
+  this class operates.
+
+
+Attributes/properties detailed
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+~ ~ ~ ~ ~ ~ ~  Charge/Energy/Capacity - how to not confuse  ~ ~ ~ ~ ~ ~ ~
+~                                                                       ~
+~ Because both "charge" (µAh) and "energy" (µWh) represents "capacity"  ~
+~ of battery, this class distinguish these terms. Don't mix them!       ~
+~                                                                       ~
+~ CHARGE_* attributes represents capacity in µAh only.                  ~
+~ ENERGY_* attributes represents capacity in µWh only.                  ~
+~ CAPACITY attribute represents capacity in *percents*, from 0 to 100.  ~
+~                                                                       ~
+~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+Postfixes:
+_AVG - *hardware* averaged value, use it if your hardware is really able to
+report averaged values.
+_NOW - momentary/instantaneous values.
+
+STATUS - this attribute represents operating status (charging, full,
+discharging (i.e. powering a load), etc.). This corresponds to
+BATTERY_STATUS_* values, as defined in battery.h.
+
+HEALTH - represents health of the battery, values corresponds to
+POWER_SUPPLY_HEALTH_*, defined in battery.h.
+
+VOLTAGE_MAX_DESIGN, VOLTAGE_MIN_DESIGN - design values for maximal and
+minimal power supply voltages. Maximal/minimal means values of voltages
+when battery considered "full"/"empty" at normal conditions. Yes, there is
+no direct relation between voltage and battery capacity, but some dumb
+batteries use voltage for very approximated calculation of capacity.
+Battery driver also can use this attribute just to inform userspace
+about maximal and minimal voltage thresholds of a given battery.
+
+CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN - design charge values, when
+battery considered full/empty.
+
+ENERGY_FULL_DESIGN, ENERGY_EMPTY_DESIGN - same as above but for energy.
+
+CHARGE_FULL, CHARGE_EMPTY - These attributes means "last remembered value
+of charge when battery became full/empty". It also could mean "value of
+charge when battery considered full/empty at given conditions (temperature,
+age)". I.e. these attributes represents real thresholds, not design values.
+
+ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
+
+CAPACITY - capacity in percents.
+CAPACITY_LEVEL - capacity level. This corresponds to
+POWER_SUPPLY_CAPACITY_LEVEL_*.
+
+TEMP - temperature of the power supply.
+TEMP_AMBIENT - ambient temperature.
+
+TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e.
+while battery powers a load)
+TIME_TO_FULL - seconds left for battery to be considered full (i.e.
+while battery is charging)
+
+
+Battery <-> external power supply interaction
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Often power supplies are acting as supplies and supplicants at the same
+time. Batteries are good example. So, batteries usually care if they're
+externally powered or not.
+
+For that case, power supply class implements notification mechanism for
+batteries.
+
+External power supply (AC) lists supplicants (batteries) names in
+"supplied_to" struct member, and each power_supply_changed() call
+issued by external power supply will notify supplicants via
+external_power_changed callback.
+
+
+QA
+~~
+Q: Where is POWER_SUPPLY_PROP_XYZ attribute?
+A: If you cannot find attribute suitable for your driver needs, feel free
+   to add it and send patch along with your driver.
+
+   The attributes available currently are the ones currently provided by the
+   drivers written.
+
+   Good candidates to add in future: model/part#, cycle_time, manufacturer,
+   etc.
+
+
+Q: I have some very specific attribute (e.g. battery color), should I add
+   this attribute to standard ones?
+A: Most likely, no. Such attribute can be placed in the driver itself, if
+   it is useful. Of course, if the attribute in question applicable to
+   large set of batteries, provided by many drivers, and/or comes from
+   some general battery specification/standard, it may be a candidate to
+   be added to the core attribute set.
+
+
+Q: Suppose, my battery monitoring chip/firmware does not provides capacity
+   in percents, but provides charge_{now,full,empty}. Should I calculate
+   percentage capacity manually, inside the driver, and register CAPACITY
+   attribute? The same question about time_to_empty/time_to_full.
+A: Most likely, no. This class is designed to export properties which are
+   directly measurable by the specific hardware available.
+
+   Inferring not available properties using some heuristics or mathematical
+   model is not subject of work for a battery driver. Such functionality
+   should be factored out, and in fact, apm_power, the driver to serve
+   legacy APM API on top of power supply class, uses a simple heuristic of
+   approximating remaining battery capacity based on its charge, current,
+   voltage and so on. But full-fledged battery model is likely not subject
+   for kernel at all, as it would require floating point calculation to deal
+   with things like differential equations and Kalman filters. This is
+   better be handled by batteryd/libbattery, yet to be written.
diff --git a/Documentation/sched-design-CFS.txt b/Documentation/sched-design-CFS.txt
new file mode 100644
index 0000000..16feebb
--- /dev/null
+++ b/Documentation/sched-design-CFS.txt
@@ -0,0 +1,119 @@
+
+This is the CFS scheduler.
+
+80% of CFS's design can be summed up in a single sentence: CFS basically
+models an "ideal, precise multi-tasking CPU" on real hardware.
+
+"Ideal multi-tasking CPU" is a (non-existent  :-))  CPU that has 100%
+physical power and which can run each task at precise equal speed, in
+parallel, each at 1/nr_running speed. For example: if there are 2 tasks
+running then it runs each at 50% physical power - totally in parallel.
+
+On real hardware, we can run only a single task at once, so while that
+one task runs, the other tasks that are waiting for the CPU are at a
+disadvantage - the current task gets an unfair amount of CPU time. In
+CFS this fairness imbalance is expressed and tracked via the per-task
+p->wait_runtime (nanosec-unit) value. "wait_runtime" is the amount of
+time the task should now run on the CPU for it to become completely fair
+and balanced.
+
+( small detail: on 'ideal' hardware, the p->wait_runtime value would
+  always be zero - no task would ever get 'out of balance' from the
+  'ideal' share of CPU time. )
+
+CFS's task picking logic is based on this p->wait_runtime value and it
+is thus very simple: it always tries to run the task with the largest
+p->wait_runtime value. In other words, CFS tries to run the task with
+the 'gravest need' for more CPU time. So CFS always tries to split up
+CPU time between runnable tasks as close to 'ideal multitasking
+hardware' as possible.
+
+Most of the rest of CFS's design just falls out of this really simple
+concept, with a few add-on embellishments like nice levels,
+multiprocessing and various algorithm variants to recognize sleepers.
+
+In practice it works like this: the system runs a task a bit, and when
+the task schedules (or a scheduler tick happens) the task's CPU usage is
+'accounted for': the (small) time it just spent using the physical CPU
+is deducted from p->wait_runtime. [minus the 'fair share' it would have
+gotten anyway]. Once p->wait_runtime gets low enough so that another
+task becomes the 'leftmost task' of the time-ordered rbtree it maintains
+(plus a small amount of 'granularity' distance relative to the leftmost
+task so that we do not over-schedule tasks and trash the cache) then the
+new leftmost task is picked and the current task is preempted.
+
+The rq->fair_clock value tracks the 'CPU time a runnable task would have
+fairly gotten, had it been runnable during that time'. So by using
+rq->fair_clock values we can accurately timestamp and measure the
+'expected CPU time' a task should have gotten. All runnable tasks are
+sorted in the rbtree by the "rq->fair_clock - p->wait_runtime" key, and
+CFS picks the 'leftmost' task and sticks to it. As the system progresses
+forwards, newly woken tasks are put into the tree more and more to the
+right - slowly but surely giving a chance for every task to become the
+'leftmost task' and thus get on the CPU within a deterministic amount of
+time.
+
+Some implementation details:
+
+ - the introduction of Scheduling Classes: an extensible hierarchy of
+   scheduler modules. These modules encapsulate scheduling policy
+   details and are handled by the scheduler core without the core
+   code assuming about them too much.
+
+ - sched_fair.c implements the 'CFS desktop scheduler': it is a
+   replacement for the vanilla scheduler's SCHED_OTHER interactivity
+   code.
+
+   I'd like to give credit to Con Kolivas for the general approach here:
+   he has proven via RSDL/SD that 'fair scheduling' is possible and that
+   it results in better desktop scheduling. Kudos Con!
+
+   The CFS patch uses a completely different approach and implementation
+   from RSDL/SD. My goal was to make CFS's interactivity quality exceed
+   that of RSDL/SD, which is a high standard to meet :-) Testing
+   feedback is welcome to decide this one way or another. [ and, in any
+   case, all of SD's logic could be added via a kernel/sched_sd.c module
+   as well, if Con is interested in such an approach. ]
+
+   CFS's design is quite radical: it does not use runqueues, it uses a
+   time-ordered rbtree to build a 'timeline' of future task execution,
+   and thus has no 'array switch' artifacts (by which both the vanilla
+   scheduler and RSDL/SD are affected).
+
+   CFS uses nanosecond granularity accounting and does not rely on any
+   jiffies or other HZ detail. Thus the CFS scheduler has no notion of
+   'timeslices' and has no heuristics whatsoever. There is only one
+   central tunable:
+
+         /proc/sys/kernel/sched_granularity_ns
+
+   which can be used to tune the scheduler from 'desktop' (low
+   latencies) to 'server' (good batching) workloads. It defaults to a
+   setting suitable for desktop workloads. SCHED_BATCH is handled by the
+   CFS scheduler module too.
+
+   Due to its design, the CFS scheduler is not prone to any of the
+   'attacks' that exist today against the heuristics of the stock
+   scheduler: fiftyp.c, thud.c, chew.c, ring-test.c, massive_intr.c all
+   work fine and do not impact interactivity and produce the expected
+   behavior.
+
+   the CFS scheduler has a much stronger handling of nice levels and
+   SCHED_BATCH: both types of workloads should be isolated much more
+   agressively than under the vanilla scheduler.
+
+   ( another detail: due to nanosec accounting and timeline sorting,
+     sched_yield() support is very simple under CFS, and in fact under
+     CFS sched_yield() behaves much better than under any other
+     scheduler i have tested so far. )
+
+ - sched_rt.c implements SCHED_FIFO and SCHED_RR semantics, in a simpler
+   way than the vanilla scheduler does. It uses 100 runqueues (for all
+   100 RT priority levels, instead of 140 in the vanilla scheduler)
+   and it needs no expired array.
+
+ - reworked/sanitized SMP load-balancing: the runqueue-walking
+   assumptions are gone from the load-balancing code now, and
+   iterators of the scheduling modules are used. The balancing code got
+   quite a bit simpler as a result.
+
diff --git a/MAINTAINERS b/MAINTAINERS
index df40a4e..fcfe598 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1856,7 +1856,7 @@
 T:	git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
 S:	Supported
 
-INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
+INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS
 P:	Dmitry Torokhov
 M:	dmitry.torokhov@gmail.com
 M:	dtor@mail.ru
@@ -2903,6 +2903,11 @@
 M:	mostrows@speakeasy.net
 S:	Maintained
 
+PPP OVER L2TP
+P:	James Chapman
+M:	jchapman@katalix.com
+S:	Maintained
+
 PREEMPTIBLE KERNEL
 P:	Robert Love
 M:	rml@tech9.net
@@ -2930,6 +2935,13 @@
 L:	linux-ide@vger.kernel.org
 S:	Maintained
 
+PS3 NETWORK SUPPORT
+P:	Masakazu Mokuno
+M:	mokuno@sm.sony.co.jp
+L:	netdev@vger.kernel.org
+L:	cbe-oss-dev@ozlabs.org
+S:	Supported
+
 PS3 PLATFORM SUPPORT
 P:	Geoff Levand
 M:	geoffrey.levand@am.sony.com
@@ -3049,6 +3061,16 @@
 RISCOM8 DRIVER
 S:	Orphan
 
+RTL818X WIRELESS DRIVER
+P:	Michael Wu
+M:	flamingice@sourmilk.net
+P:	Andrea Merello
+M:	andreamrl@tiscali.it
+L:	linux-wireless@vger.kernel.org
+W:	http://linuxwireless.org/
+T:	git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
+S:	Maintained
+
 S3 SAVAGE FRAMEBUFFER DRIVER
 P:	Antonino Daplas
 M:	adaplas@gmail.com
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 88baed1..0b29545 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -941,17 +941,6 @@
 }
 #endif
 
-static void smp_tune_scheduling(void)
-{
-	if (cpu_khz) {
-		/* cache size in kB */
-		long cachesize = boot_cpu_data.x86_cache_size;
-
-		if (cachesize > 0)
-			max_cache_size = cachesize * 1024;
-	}
-}
-
 /*
  * Cycle through the processors sending APIC IPIs to boot each.
  */
@@ -980,7 +969,6 @@
 	x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
 
 	current_thread_info()->cpu = 0;
-	smp_tune_scheduling();
 
 	set_cpu_sibling_map(0);
 
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
index f64b81f..ea63a30 100644
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -4,6 +4,7 @@
  * See comments there for proper credits.
  */
 
+#include <linux/sched.h>
 #include <linux/clocksource.h>
 #include <linux/workqueue.h>
 #include <linux/cpufreq.h>
@@ -106,8 +107,13 @@
 
 	/*
 	 * Fall back to jiffies if there's no TSC available:
+	 * ( But note that we still use it if the TSC is marked
+	 *   unstable. We do this because unlike Time Of Day,
+	 *   the scheduler clock tolerates small errors and it's
+	 *   very important for it to be as fast as the platform
+	 *   can achive it. )
 	 */
-	if (unlikely(!tsc_enabled))
+	if (unlikely(!tsc_enabled && !tsc_unstable))
 		/* No locking but a rare wrong value is not a big deal: */
 		return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
 
@@ -277,6 +283,7 @@
 
 void mark_tsc_unstable(char *reason)
 {
+	sched_clock_unstable_event();
 	if (!tsc_unstable) {
 		tsc_unstable = 1;
 		tsc_enabled = 0;
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index eaa6a24..188fb73 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -805,7 +805,6 @@
 get_max_cacheline_size (void)
 {
 	unsigned long line_size, max = 1;
-	unsigned int cache_size = 0;
 	u64 l, levels, unique_caches;
         pal_cache_config_info_t cci;
         s64 status;
@@ -835,8 +834,6 @@
 		line_size = 1 << cci.pcci_line_size;
 		if (line_size > max)
 			max = line_size;
-		if (cache_size < cci.pcci_cache_size)
-			cache_size = cci.pcci_cache_size;
 		if (!cci.pcci_unified) {
 			status = ia64_pal_cache_config_info(l,
 						    /* cache_type (instruction)= */ 1,
@@ -853,9 +850,6 @@
 			ia64_i_cache_stride_shift = cci.pcci_stride;
 	}
   out:
-#ifdef CONFIG_SMP
-	max_cache_size = max(max_cache_size, cache_size);
-#endif
 	if (max > ia64_max_cacheline_size)
 		ia64_max_cacheline_size = max;
 }
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 7345538..a00fabe 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -15,6 +15,29 @@
 	prompt "System type"
 	default SGI_IP22
 
+config LEMOTE_FULONG
+	bool "Lemote Fulong mini-PC"
+	select ARCH_SPARSEMEM_ENABLE
+	select SYS_HAS_CPU_LOONGSON2
+	select DMA_NONCOHERENT
+	select BOOT_ELF32
+	select BOARD_SCACHE
+	select HAVE_STD_PC_SERIAL_PORT
+	select HW_HAS_PCI
+	select I8259
+	select ISA
+	select IRQ_CPU
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_SUPPORTS_HIGHMEM
+	select SYS_HAS_EARLY_PRINTK
+	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select CPU_HAS_WB
+	help
+	  Lemote Fulong mini-PC board based on the Chinese Loongson-2E CPU and
+	  an FPGA northbridge
+
 config MACH_ALCHEMY
 	bool "Alchemy processor based machines"
 
@@ -63,7 +86,7 @@
 	bool "DECstations"
 	select BOOT_ELF32
 	select DMA_NONCOHERENT
-	select SYS_HAS_EARLY_PRINTK
+	select NO_IOPORT
 	select IRQ_CPU
 	select SYS_HAS_CPU_R3000
 	select SYS_HAS_CPU_R4X00
@@ -88,24 +111,6 @@
 
 	  otherwise choose R3000.
 
-config MIPS_EV64120
-	bool "Galileo EV64120 Evaluation board (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select PCI_GT64XXX_PCI0
-	select SYS_HAS_CPU_R5000
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	select SYS_SUPPORTS_BIG_ENDIAN
-	select SYS_SUPPORTS_KGDB
-	help
-	  This is an evaluation board based on the Galileo GT-64120
-	  single-chip system controller that contains a MIPS R5000 compatible
-	  core running at 75/100MHz.  Their website is located at
-	  <http://www.marvell.com/>.  Say Y here if you wish to build a
-	  kernel for this platform.
-
 config MACH_JAZZ
 	bool "Jazz family of machines"
 	select ARC
@@ -126,20 +131,6 @@
 	 Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
 	 Olivetti M700-10 workstations.
 
-config LASAT
-	bool "LASAT Networks platforms"
-	select DMA_NONCOHERENT
-	select SYS_HAS_EARLY_PRINTK
-	select HW_HAS_PCI
-	select PCI_GT64XXX_PCI0
-	select MIPS_NILE4
-	select R5000_CPU_SCACHE
-	select SYS_HAS_CPU_R5000
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if BROKEN
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-	select GENERIC_HARDIRQS_NO__DO_IRQ
-
 config MIPS_ATLAS
 	bool "MIPS Atlas board"
 	select BOOT_ELF32
@@ -173,7 +164,6 @@
 	bool "MIPS Malta board"
 	select ARCH_MAY_HAVE_PC_FDC
 	select BOOT_ELF32
-	select HAVE_STD_PC_SERIAL_PORT
 	select DMA_NONCOHERENT
 	select GENERIC_ISA_DMA
 	select IRQ_CPU
@@ -246,11 +236,13 @@
 	select DMA_NONCOHERENT
 	select SYS_HAS_EARLY_PRINTK
 	select IRQ_CPU
+	select BOOT_RAW
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R2
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_MULTITHREADING
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	help
 	  This option enables support for MIPS Technologies MIPSsim software
@@ -274,43 +266,6 @@
 	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
 	  Momentum Computer <http://www.momenco.com/>.
 
-config MOMENCO_OCELOT_3
-	bool "Momentum Ocelot-3 board"
-	select BOOT_ELF32
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_CPU_RM7K
-	select IRQ_MV64340
-	select PCI_MARVELL
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_HAS_CPU_RM9000
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	select SYS_SUPPORTS_BIG_ENDIAN
-	help
-	  The Ocelot-3 is based off Discovery III System Controller and
-	  PMC-Sierra Rm79000 core.
-
-config MOMENCO_OCELOT_C
-	bool "Momentum Ocelot-C board"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_MV64340
-	select PCI_MARVELL
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_HAS_CPU_RM7000
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	select SYS_SUPPORTS_BIG_ENDIAN
-	select GENERIC_HARDIRQS_NO__DO_IRQ
-	help
-	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
-	  Momentum Computer <http://www.momenco.com/>.
-
 config PNX8550_JBS
 	bool "Philips PNX8550 based JBS board"
 	select PNX8550
@@ -346,6 +301,27 @@
 	select SYS_HAS_CPU_VR41XX
 	select GENERIC_HARDIRQS_NO__DO_IRQ
 
+config PMC_MSP
+	bool "PMC-Sierra MSP chipsets"
+	depends on EXPERIMENTAL
+	select DMA_NONCOHERENT
+	select SWAP_IO_SPACE
+	select NO_EXCEPT_FILL
+	select BOOT_RAW
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_KGDB
+	select IRQ_CPU
+	select SERIAL_8250
+	select SERIAL_8250_CONSOLE
+	help
+	  This adds support for the PMC-Sierra family of Multi-Service
+	  Processor System-On-A-Chips.  These parts include a number
+	  of integrated peripherals, interfaces and DSPs in addition to
+	  a variety of MIPS cores.
+
 config PMC_YOSEMITE
 	bool "PMC-Sierra Yosemite eval board"
 	select DMA_COHERENT
@@ -450,8 +426,7 @@
 	  here.
 
 config SGI_IP32
-	bool "SGI IP32 (O2) (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	bool "SGI IP32 (O2)"
 	select ARC
 	select ARC32
 	select BOOT_ELF32
@@ -652,6 +627,7 @@
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_KGDB
 	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select GENERIC_GPIO
 	help
 	  This Toshiba board is based on the TX4938 processor. Say Y here to
 	  support this machine type
@@ -660,9 +636,7 @@
 
 source "arch/mips/au1000/Kconfig"
 source "arch/mips/ddb5xxx/Kconfig"
-source "arch/mips/gt64120/ev64120/Kconfig"
 source "arch/mips/jazz/Kconfig"
-source "arch/mips/lasat/Kconfig"
 source "arch/mips/pmc-sierra/Kconfig"
 source "arch/mips/sgi-ip27/Kconfig"
 source "arch/mips/sibyte/Kconfig"
@@ -721,6 +695,9 @@
 config ARCH_MAY_HAVE_PC_FDC
 	bool
 
+config BOOT_RAW
+	bool
+
 config DMA_COHERENT
 	bool
 
@@ -768,16 +745,19 @@
 config MIPS_MSC
 	bool
 
-config MIPS_NILE4
-	bool
-
 config MIPS_DISABLE_OBSOLETE_IDE
 	bool
 
+config NO_IOPORT
+	def_bool n
+
 config GENERIC_ISA_DMA_SUPPORT_BROKEN
 	bool
 	select ZONE_DMA
 
+config GENERIC_GPIO
+	bool
+
 #
 # Endianess selection.  Sufficiently obscure so many users don't know what to
 # answer,so we try hard to limit the available choices.  Also the use of a
@@ -821,7 +801,10 @@
 config IRQ_CPU_RM9K
 	bool
 
-config IRQ_MV64340
+config IRQ_MSP_SLP
+	bool
+
+config IRQ_MSP_CIC
 	bool
 
 config DDB5XXX_COMMON
@@ -834,6 +817,9 @@
 config PCI_GT64XXX_PCI0
 	bool
 
+config NO_EXCEPT_FILL
+	bool
+
 config MIPS_TX3927
 	bool
 	select HAS_TXX9_SERIAL
@@ -841,14 +827,6 @@
 config MIPS_RM9122
 	bool
 	select SERIAL_RM9000
-	select GPI_RM9000
-	select WDT_RM9000
-
-config PCI_MARVELL
-	bool
-
-config SERIAL_RM9000
-	bool
 
 config PNX8550
 	bool
@@ -863,6 +841,7 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select GENERIC_HARDIRQS_NO__DO_IRQ
 	select SYS_SUPPORTS_KGDB
+	select GENERIC_GPIO
 
 config SWAP_IO_SPACE
 	bool
@@ -875,31 +854,17 @@
 config SERIAL_RM9000
 	bool
 
-config GPI_RM9000
-	bool
-
-config WDT_RM9000
-	bool
-
 #
 # Unfortunately not all GT64120 systems run the chip at the same clock.
 # As the user for the clock rate and try to minimize the available options.
 #
 choice
 	prompt "Galileo Chip Clock"
-	#default SYSCLK_83 if MIPS_EV64120
-	depends on MIPS_EV64120 || MOMENCO_OCELOT
-	default SYSCLK_83 if MIPS_EV64120
+	depends on MOMENCO_OCELOT
 	default SYSCLK_100 if MOMENCO_OCELOT
 
-config SYSCLK_75
-	bool "75" if MIPS_EV64120
-
-config SYSCLK_83
-	bool "83.3" if MIPS_EV64120
-
 config SYSCLK_100
-	bool "100" if MIPS_EV64120 || MOMENCO_OCELOT
+	bool "100" if MOMENCO_OCELOT
 
 endchoice
 
@@ -911,8 +876,9 @@
 
 config MIPS_L1_CACHE_SHIFT
 	int
-	default "4" if MACH_DECSTATION || SNI_RM
-	default "7" if SGI_IP27
+	default "4" if MACH_DECSTATION
+	default "7" if SGI_IP27 || SNI_RM
+	default "4" if PMC_MSP4200_EVAL
 	default "5"
 
 config HAVE_STD_PC_SERIAL_PORT
@@ -944,6 +910,16 @@
 	prompt "CPU type"
 	default CPU_R4X00
 
+config CPU_LOONGSON2
+	bool "Loongson 2"
+	depends on SYS_HAS_CPU_LOONGSON2
+	select CPU_SUPPORTS_32BIT_KERNEL
+	select CPU_SUPPORTS_64BIT_KERNEL
+	select CPU_SUPPORTS_HIGHMEM
+	help
+	  The Loongson 2E processor implements the MIPS III instruction set
+	  with many extensions.
+
 config CPU_MIPS32_R1
 	bool "MIPS32 Release 1"
 	depends on SYS_HAS_CPU_MIPS32_R1
@@ -1154,6 +1130,9 @@
 
 endchoice
 
+config SYS_HAS_CPU_LOONGSON2
+	bool
+
 config SYS_HAS_CPU_MIPS32_R1
 	bool
 
@@ -1488,6 +1467,15 @@
 config CPU_HAS_WB
 	bool
 
+config 64BIT_CONTEXT
+	bool "Save 64bit integer registers"
+	depends on 32BIT && CPU_LOONGSON2
+	help
+	  Loongson2 CPU is 64bit , when used in 32BIT mode, its integer
+	  registers can still be accessed as 64bit, mainly for multimedia
+	  instructions. We must have all 64bit save/restored to make sure
+	  those instructions to get correct result.
+
 #
 # Vectored interrupt mode is an R2 feature
 #
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index f450066..20d19c9 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -118,6 +118,7 @@
 cflags-$(CONFIG_CPU_VR41XX)	+= -march=r4100 -Wa,--trap
 cflags-$(CONFIG_CPU_R4X00)	+= -march=r4600 -Wa,--trap
 cflags-$(CONFIG_CPU_TX49XX)	+= -march=r4600 -Wa,--trap
+cflags-$(CONFIG_CPU_LOONGSON2)	+= -march=r4600 -Wa,--trap
 cflags-$(CONFIG_CPU_MIPS32_R1)	+= $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
 			-Wa,-mips32 -Wa,--trap
 cflags-$(CONFIG_CPU_MIPS32_R2)	+= $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
@@ -283,14 +284,6 @@
 CLEAN_FILES			+= drivers/tc/lk201-map.c
 
 #
-# Galileo EV64120 Board
-#
-core-$(CONFIG_MIPS_EV64120)	+= arch/mips/gt64120/ev64120/
-core-$(CONFIG_MIPS_EV64120)	+= arch/mips/gt64120/common/
-cflags-$(CONFIG_MIPS_EV64120)	+= -Iinclude/asm-mips/mach-ev64120
-load-$(CONFIG_MIPS_EV64120)	+= 0xffffffff80100000
-
-#
 # Wind River PPMC Board (4KC + GT64120)
 #
 core-$(CONFIG_WR_PPMC)		+= arch/mips/gt64120/wrppmc/
@@ -298,6 +291,13 @@
 load-$(CONFIG_WR_PPMC)		+= 0xffffffff80100000
 
 #
+# lemote fulong mini-PC board
+#
+core-$(CONFIG_LEMOTE_FULONG) +=arch/mips/lemote/lm2e/
+load-$(CONFIG_LEMOTE_FULONG) +=0xffffffff80100000
+cflags-$(CONFIG_LEMOTE_FULONG) += -Iinclude/asm-mips/mach-lemote
+
+#
 # For all MIPS, Inc. eval boards
 #
 core-$(CONFIG_MIPS_BOARDS_GEN)	+= arch/mips/mips-boards/generic/
@@ -327,7 +327,7 @@
 #
 # MIPS SIM
 #
-core-$(CONFIG_MIPS_SIM)		+= arch/mips/mips-boards/sim/
+core-$(CONFIG_MIPS_SIM)		+= arch/mips/mipssim/
 cflags-$(CONFIG_MIPS_SIM)	+= -Iinclude/asm-mips/mach-sim
 load-$(CONFIG_MIPS_SIM)		+= 0x80100000
 
@@ -343,12 +343,12 @@
 load-$(CONFIG_MOMENCO_OCELOT)	+= 0xffffffff80100000
 
 #
-# Momentum Ocelot-C and -CS boards
+# PMC-Sierra MSP SOCs
 #
-# The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the
-# mips_io_port_base.
-core-$(CONFIG_MOMENCO_OCELOT_C)	+= arch/mips/momentum/ocelot_c/
-load-$(CONFIG_MOMENCO_OCELOT_C)	+= 0xffffffff80100000
+core-$(CONFIG_PMC_MSP)		+= arch/mips/pmc-sierra/msp71xx/
+cflags-$(CONFIG_PMC_MSP)	+= -Iinclude/asm-mips/pmc-sierra/msp71xx \
+					-mno-branch-likely
+load-$(CONFIG_PMC_MSP)		+= 0xffffffff80100000
 
 #
 # PMC-Sierra Yosemite
@@ -365,13 +365,6 @@
 load-$(CONFIG_QEMU)		+= 0xffffffff80010000
 
 #
-# Momentum Ocelot-3
-#
-core-$(CONFIG_MOMENCO_OCELOT_3) 	+= arch/mips/momentum/ocelot_3/
-cflags-$(CONFIG_MOMENCO_OCELOT_3)	+= -Iinclude/asm-mips/mach-ocelot3
-load-$(CONFIG_MOMENCO_OCELOT_3) 	+= 0xffffffff80100000
-
-#
 # Basler eXcite
 #
 core-$(CONFIG_BASLER_EXCITE)	+= arch/mips/basler/excite/
@@ -389,10 +382,6 @@
 core-$(CONFIG_DDB5477)		+= arch/mips/ddb5xxx/ddb5477/
 load-$(CONFIG_DDB5477)		+= 0xffffffff80100000
 
-core-$(CONFIG_LASAT)		+= arch/mips/lasat/
-cflags-$(CONFIG_LASAT)		+= -Iinclude/asm-mips/mach-lasat
-load-$(CONFIG_LASAT)		+= 0xffffffff80000000
-
 #
 # Common VR41xx
 #
@@ -580,6 +569,7 @@
 #
 core-$(CONFIG_TOSHIBA_RBTX4927)	+= arch/mips/tx4927/toshiba_rbtx4927/
 core-$(CONFIG_TOSHIBA_RBTX4927)	+= arch/mips/tx4927/common/
+cflags-$(CONFIG_TOSHIBA_RBTX4927) += -Iinclude/asm-mips/mach-tx49xx
 load-$(CONFIG_TOSHIBA_RBTX4927)	+= 0xffffffff80020000
 
 #
@@ -587,6 +577,7 @@
 #
 core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/toshiba_rbtx4938/
 core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/common/
+cflags-$(CONFIG_TOSHIBA_RBTX4938) += -Iinclude/asm-mips/mach-tx49xx
 load-$(CONFIG_TOSHIBA_RBTX4938) += 0xffffffff80100000
 
 cflags-y			+= -Iinclude/asm-mips/mach-generic
@@ -603,7 +594,8 @@
 endif
 
 AFLAGS		+= $(cflags-y)
-CFLAGS		+= $(cflags-y)
+CFLAGS		+= $(cflags-y) \
+			-D"VMLINUX_LOAD_ADDRESS=$(load-y)"
 
 LDFLAGS			+= -m $(ld-emul)
 
@@ -633,18 +625,11 @@
 head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
 
 libs-y			+= arch/mips/lib/
-libs-$(CONFIG_32BIT)	+= arch/mips/lib-32/
-libs-$(CONFIG_64BIT)	+= arch/mips/lib-64/
 
 core-y			+= arch/mips/kernel/ arch/mips/mm/ arch/mips/math-emu/
 
 drivers-$(CONFIG_OPROFILE)	+= arch/mips/oprofile/
 
-ifdef CONFIG_LASAT
-rom.bin rom.sw: vmlinux
-	$(Q)$(MAKE) $(build)=arch/mips/lasat/image $@
-endif
-
 #
 # Some machines like the Indy need 32-bit ELF binaries for booting purposes.
 # Other need ECOFF, so we build a 32-bit ELF binary for them which we then
@@ -702,32 +687,19 @@
 CLEAN_FILES += vmlinux.ecoff \
 	       vmlinux.srec
 
+archprepare:
+ifdef CONFIG_MIPS32_N32
+	@echo '  Checking missing-syscalls for N32'
+	$(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=n32"
+endif
+ifdef CONFIG_MIPS32_O32
+	@echo '  Checking missing-syscalls for O32'
+	$(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=32"
+endif
+
 archclean:
 	@$(MAKE) $(clean)=arch/mips/boot
-	@$(MAKE) $(clean)=arch/mips/lasat
 
 CLEAN_FILES += vmlinux.32 \
 	       vmlinux.64 \
 	       vmlinux.ecoff
-
-quiet_cmd_syscalls_n32 = CALL-N32 $<
-      cmd_syscalls_n32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=n32
-
-quiet_cmd_syscalls_o32 = CALL-O32 $<
-      cmd_syscalls_o32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=32
-
-PHONY += missing-syscalls-n32 missing-syscalls-o32
-
-missing-syscalls-n32: scripts/checksyscalls.sh FORCE
-	$(call cmd,syscalls_n32)
-
-missing-syscalls-o32: scripts/checksyscalls.sh FORCE
-	$(call cmd,syscalls_o32)
-
-archprepare:
-ifdef CONFIG_MIPS32_N32
-	$(Q)$(MAKE) $(build)=arch/mips missing-syscalls-n32
-endif
-ifdef CONFIG_MIPS32_O32
-	$(Q)$(MAKE) $(build)=arch/mips missing-syscalls-o32
-endif
diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c
index ce55297..7abe420 100644
--- a/arch/mips/au1000/common/gpio.c
+++ b/arch/mips/au1000/common/gpio.c
@@ -1,4 +1,7 @@
 /*
+ *  Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ *  	Architecture specific GPIO support
+ *
  *  This program is free software; you can redistribute	 it and/or modify it
  *  under  the terms of	 the GNU General  Public License as published by the
  *  Free Software Foundation;  either version 2 of the	License, or (at your
@@ -18,101 +21,136 @@
  *  You should have received a copy of the  GNU General Public License along
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Notes :
+ * 	au1000 SoC have only one GPIO line : GPIO1
+ * 	others have a second one : GPIO2
  */
+
+#include <linux/autoconf.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/types.h>
 #include <linux/module.h>
-#include <au1000.h>
-#include <au1xxx_gpio.h>
+
+#include <asm/addrspace.h>
+
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/gpio.h>
 
 #define gpio1 sys
 #if !defined(CONFIG_SOC_AU1000)
-static AU1X00_GPIO2 * const gpio2 = (AU1X00_GPIO2 *)GPIO2_BASE;
 
-#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000
+static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE;
+#define GPIO2_OUTPUT_ENABLE_MASK 	0x00010000
 
-int au1xxx_gpio2_read(int signal)
+static int au1xxx_gpio2_read(unsigned gpio)
 {
-	signal -= 200;
-/*	gpio2->dir &= ~(0x01 << signal);						//Set GPIO to input */
-	return ((gpio2->pinstate >> signal) & 0x01);
+	gpio -= AU1XXX_GPIO_BASE;
+	return ((gpio2->pinstate >> gpio) & 0x01);
 }
 
-void au1xxx_gpio2_write(int signal, int value)
+static void au1xxx_gpio2_write(unsigned gpio, int value)
 {
-	signal -= 200;
+	gpio -= AU1XXX_GPIO_BASE;
 
-	gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << signal) |
-		(value << signal);
+	gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | (value << gpio);
 }
 
-void au1xxx_gpio2_tristate(int signal)
+static int au1xxx_gpio2_direction_input(unsigned gpio)
 {
-	signal -= 200;
-	gpio2->dir &= ~(0x01 << signal); 	/* Set GPIO to input */
-}
-#endif
-
-int au1xxx_gpio1_read(int signal)
-{
-/*	gpio1->trioutclr |= (0x01 << signal); */
-	return ((gpio1->pinstaterd >> signal) & 0x01);
+	gpio -= AU1XXX_GPIO_BASE;
+	gpio2->dir &= ~(0x01 << gpio);
+	return 0;
 }
 
-void au1xxx_gpio1_write(int signal, int value)
+static int au1xxx_gpio2_direction_output(unsigned gpio, int value)
 {
-	if(value)
-		gpio1->outputset = (0x01 << signal);
+	gpio -= AU1XXX_GPIO_BASE;
+	gpio2->dir = (0x01 << gpio) | (value << gpio);
+	return 0;
+}
+
+#endif /* !defined(CONFIG_SOC_AU1000) */
+
+static int au1xxx_gpio1_read(unsigned gpio)
+{
+	return ((gpio1->pinstaterd >> gpio) & 0x01);
+}
+
+static void au1xxx_gpio1_write(unsigned gpio, int value)
+{
+	if (value)
+		gpio1->outputset = (0x01 << gpio);
 	else
-		gpio1->outputclr = (0x01 << signal);	/* Output a Zero */
+		/* Output a zero */
+		gpio1->outputclr = (0x01 << gpio);
 }
 
-void au1xxx_gpio1_tristate(int signal)
+static int au1xxx_gpio1_direction_input(unsigned gpio)
 {
-	gpio1->trioutclr = (0x01 << signal);		/* Tristate signal */
+	gpio1->pininputen = (0x01 << gpio);
+	return 0;
 }
 
-
-int au1xxx_gpio_read(int signal)
+static int au1xxx_gpio1_direction_output(unsigned gpio, int value)
 {
-	if(signal >= 200)
+	gpio1->trioutclr = (0x01 & gpio);
+	return 0;
+}
+
+int au1xxx_gpio_get_value(unsigned gpio)
+{
+	if (gpio >= AU1XXX_GPIO_BASE)
 #if defined(CONFIG_SOC_AU1000)
 		return 0;
 #else
-		return au1xxx_gpio2_read(signal);
+		return au1xxx_gpio2_read(gpio);
 #endif
 	else
-		return au1xxx_gpio1_read(signal);
+		return au1xxx_gpio1_read(gpio);
 }
 
-void au1xxx_gpio_write(int signal, int value)
+EXPORT_SYMBOL(au1xxx_gpio_get_value);
+
+void au1xxx_gpio_set_value(unsigned gpio, int value)
 {
-	if(signal >= 200)
+	if (gpio >= AU1XXX_GPIO_BASE)
 #if defined(CONFIG_SOC_AU1000)
 		;
 #else
-		au1xxx_gpio2_write(signal, value);
+		au1xxx_gpio2_write(gpio, value);
 #endif
 	else
-		au1xxx_gpio1_write(signal, value);
+		au1xxx_gpio1_write(gpio, value);
 }
 
-void au1xxx_gpio_tristate(int signal)
+EXPORT_SYMBOL(au1xxx_gpio_set_value);
+
+int au1xxx_gpio_direction_input(unsigned gpio)
 {
-	if(signal >= 200)
+	if (gpio >= AU1XXX_GPIO_BASE)
 #if defined(CONFIG_SOC_AU1000)
 		;
 #else
-		au1xxx_gpio2_tristate(signal);
+		return au1xxx_gpio2_direction_input(gpio);
 #endif
 	else
-		au1xxx_gpio1_tristate(signal);
+		return au1xxx_gpio1_direction_input(gpio);
 }
 
-void au1xxx_gpio1_set_inputs(void)
+EXPORT_SYMBOL(au1xxx_gpio_direction_input);
+
+int au1xxx_gpio_direction_output(unsigned gpio, int value)
 {
-	gpio1->pininputen = 0;
+	if (gpio >= AU1XXX_GPIO_BASE)
+#if defined(CONFIG_SOC_AU1000)
+		;
+#else
+		return au1xxx_gpio2_direction_output(gpio, value);
+#endif
+	else
+		return au1xxx_gpio1_direction_output(gpio, value);
 }
 
-EXPORT_SYMBOL(au1xxx_gpio1_set_inputs);
-EXPORT_SYMBOL(au1xxx_gpio_tristate);
-EXPORT_SYMBOL(au1xxx_gpio_write);
-EXPORT_SYMBOL(au1xxx_gpio_read);
+EXPORT_SYMBOL(au1xxx_gpio_direction_output);
diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
index 8fd203d..d51e18f 100644
--- a/arch/mips/au1000/common/platform.c
+++ b/arch/mips/au1000/common/platform.c
@@ -289,7 +289,7 @@
 #endif
 };
 
-int au1xxx_platform_init(void)
+int __init au1xxx_platform_init(void)
 {
 	return platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices));
 }
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index 39e2513..129e2c9 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 CONFIG_MIPS_ATLAS=y
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 4713a13..dc3e1bf 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 5e7ae56..4c70312 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 631b213..c8c0578 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -1,44 +1,24 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc7
-# Wed Apr 18 14:25:45 2007
+# Linux kernel version: 2.6.22-rc2
+# Fri May 25 11:17:29 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MACH_ALCHEMY is not set
 # CONFIG_BASLER_EXCITE is not set
 CONFIG_MIPS_COBALT=y
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
 # CONFIG_WR_PPMC is not set
 # CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
 # CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
@@ -138,7 +118,7 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
+CONFIG_ZONE_DMA_FLAG=0
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
@@ -178,6 +158,7 @@
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
 # CONFIG_BLK_DEV_INITRD is not set
@@ -193,14 +174,19 @@
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -233,16 +219,13 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_MMU=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 # CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -268,7 +251,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -300,11 +282,11 @@
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -345,13 +327,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -370,10 +355,6 @@
 #
 CONFIG_CONNECTOR=y
 CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_CONCAT is not set
@@ -418,7 +399,6 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -445,16 +425,13 @@
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
 # CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
 
 #
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
 #
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
 
 #
 # Parallel port support
@@ -479,87 +456,145 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-CONFIG_SGI_IOC4=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=y
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_BLK_DEV_TC86C001=y
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
 CONFIG_RAID_ATTRS=y
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
 
 #
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
+# SCSI support type (disk, tape, CD-ROM)
 #
-# CONFIG_ATA is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_ESP_CORE is not set
+# CONFIG_SCSI_SRP is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+CONFIG_PATA_VIA=y
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -570,10 +605,14 @@
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
 
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -594,24 +633,7 @@
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -639,35 +661,8 @@
 # CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=y
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=y
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
 # Token Ring devices
@@ -675,18 +670,16 @@
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -711,10 +704,7 @@
 #
 # Userland interfaces
 #
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
@@ -726,18 +716,23 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_COBALT_BTNS=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_UINPUT is not set
+CONFIG_INPUT_POLLDEV=y
 
 #
 # Hardware I/O ports
 #
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
+# CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
 
 #
@@ -754,7 +749,7 @@
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
+# CONFIG_SERIAL_8250_PCI is not set
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -773,16 +768,11 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
 CONFIG_COBALT_LCD=y
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_DRM is not set
@@ -792,10 +782,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -808,12 +795,7 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
 # CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
 
 #
 # Multifunction device drivers
@@ -824,16 +806,19 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
 # CONFIG_FB is not set
 
 #
@@ -868,10 +853,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -912,18 +893,30 @@
 CONFIG_RTC_INTF_PROC=y
 CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# RTC drivers
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
 #
 CONFIG_RTC_DRV_CMOS=y
 # CONFIG_RTC_DRV_DS1553 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
+# on-CPU RTC drivers
+#
+
+#
 # DMA Engine support
 #
 # CONFIG_DMA_ENGINE is not set
@@ -937,14 +930,6 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -952,8 +937,13 @@
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
 # CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
 # CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
@@ -969,7 +959,7 @@
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
+# CONFIG_FUSE_FS is not set
 CONFIG_GENERIC_ACL=y
 
 #
@@ -1003,7 +993,6 @@
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -1021,13 +1010,23 @@
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_ACL_SUPPORT=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1051,10 +1050,7 @@
 #
 # Distributed Lock Manager
 #
-CONFIG_DLM=y
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
 
 #
 # Profiling support
@@ -1072,72 +1068,30 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 
 #
 # Security options
 #
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
 CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 10f6af4..ec60beb 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 4b08629..f3c25f0 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index 820659e..6d400be 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 4050b9b..82aea6e 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 7b35190..8269771 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index 5b502a2..a42ab9a 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 4bbdab0..d6e3fff 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 CONFIG_MACH_DECSTATION=y
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index b5714a6a..78f5004 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig
index 2e3e155..b29bff0 100644
--- a/arch/mips/configs/emma2rh_defconfig
+++ b/arch/mips/configs/emma2rh_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
deleted file mode 100644
index c10e4e0..0000000
--- a/arch/mips/configs/ev64120_defconfig
+++ /dev/null
@@ -1,985 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:30 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-CONFIG_MIPS_EV64120=y
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-# CONFIG_EVB_PCI1 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_MIPS_GT64120=y
-# CONFIG_SYSCLK_75 is not set
-# CONFIG_SYSCLK_83 is not set
-CONFIG_SYSCLK_100=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_KMOD is not set
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=y
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-# CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
-CONFIG_SLHC=y
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 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_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::"
-CONFIG_SYS_SUPPORTS_KGDB=y
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=m
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
index 460d7a2..6981059 100644
--- a/arch/mips/configs/excite_defconfig
+++ b/arch/mips/configs/excite_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE_PROTOTYPE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/fulong_defconfig b/arch/mips/configs/fulong_defconfig
new file mode 100644
index 0000000..6ab94d8
--- /dev/null
+++ b/arch/mips/configs/fulong_defconfig
@@ -0,0 +1,1765 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22-rc4
+# Mon Jun 11 00:23:51 2007
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+CONFIG_LEMOTE_FULONG=y
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_I8259=y
+# CONFIG_NO_IOPORT is not set
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_LOONGSON2=y
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_LOONGSON2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
+# CONFIG_PAGE_SIZE_4KB is not set
+# CONFIG_PAGE_SIZE_8KB is not set
+CONFIG_PAGE_SIZE_16KB=y
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_BOARD_SCACHE=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+CONFIG_CPU_HAS_WB=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION="lm32"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_ISA=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_BUILD_ELF64 is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+# CONFIG_IEEE80211_CRYPT_CCMP is not set
+# CONFIG_IEEE80211_CRYPT_TKIP is not set
+# CONFIG_IEEE80211_SOFTMAC is not set
+# CONFIG_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x1fc00000
+CONFIG_MTD_PHYSMAP_LEN=0x80000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# Misc devices
+#
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_BLK_DEV_TC86C001 is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_ATA is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_DM9000 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_TC35815 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_ELEKTOR is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_VIA is not set
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_IVTV is not set
+# CONFIG_VIDEO_CAFE_CCIC is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_W9968CF is not set
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_RADEON=y
+# CONFIG_FB_RADEON_I2C is not set
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+CONFIG_SND_VIA82XX=m
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
+
+#
+# ALSA MIPS devices
+#
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=y
+CONFIG_USB_PRINTER=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=936
+CONFIG_FAT_DEFAULT_IOCHARSET="utf8"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp936"
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_DEBUG2=y
+CONFIG_CIFS_EXPERIMENTAL=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
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+CONFIG_NLS_CODEPAGE_936=y
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 7ec618f..405c9f505 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 9ddc3ef..a9dcbcf 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 8fc1880..a040459 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index 9331cb0..dd04eece 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 CONFIG_MACH_JAZZ=y
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 1b364cf..9a25e77 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
deleted file mode 100644
index fd4272c..0000000
--- a/arch/mips/configs/lasat200_defconfig
+++ /dev/null
@@ -1,1118 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:34 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-CONFIG_LASAT=y
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_PICVUE=y
-CONFIG_PICVUE_PROC=y
-CONFIG_DS1603=y
-CONFIG_LASAT_SYSCTL=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_MIPS_NILE4=y
-# CONFIG_CPU_BIG_ENDIAN is not set
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
-CONFIG_MIPS_GT64120=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_R5000_CPU_SCACHE=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_LASAT=y
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# OneNAND Flash Device Drivers
-#
-# CONFIG_MTD_ONENAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-CONFIG_BLK_DEV_GENERIC=y
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=m
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_TC86C001=m
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-CONFIG_EXT3_FS_SECURITY=y
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 1f64d76..546cb24 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 CONFIG_MIPS_MALTA=y
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index a2db5c2..6abad6f 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 CONFIG_MIPS_SIM=y
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
@@ -496,36 +492,23 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# PHY device support
-#
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
-# CONFIG_NET_ETHERNET is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MIPS_SIM_NET=y
+# CONFIG_DM9000 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
-# Ethernet (1000 Mbit)
+# Wireless LAN
 #
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index ad5c0bf..4981ce4 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/msp71xx_defconfig b/arch/mips/configs/msp71xx_defconfig
new file mode 100644
index 0000000..adca5f7
--- /dev/null
+++ b/arch/mips/configs/msp71xx_defconfig
@@ -0,0 +1,1493 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.21-rc4
+# Thu Apr 26 18:11:29 2007
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+CONFIG_ZONE_DMA=y
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+CONFIG_PMC_MSP=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_PMC_MSP4200_EVAL is not set
+# CONFIG_PMC_MSP4200_GW is not set
+# CONFIG_PMC_MSP7120_EVAL is not set
+CONFIG_PMC_MSP7120_GW=y
+# CONFIG_PMC_MSP7120_FPGA is not set
+
+#
+# Options for PMC-Sierra MSP chipsets
+#
+CONFIG_PMC_MSP_EMBEDDED_ROOTFS=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
+CONFIG_BOOT_RAW=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_NO_EXCEPT_FILL=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_MSP_CIC=y
+CONFIG_MSP_USB=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+CONFIG_SYS_SUPPORTS_MULTITHREADING=y
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_BKL is not set
+# CONFIG_KEXEC is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION="-pmc"
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_SHMEM is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+CONFIG_NETFILTER_XTABLES=y
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES 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
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PMC_MSP_EVM=y
+CONFIG_MSP_FLASH_MAP_LIMIT_32M=y
+CONFIG_MSP_FLASH_MAP_LIMIT=0x02000000
+CONFIG_MTD_PMC_MSP_RAMROOT=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_MSPETH=y
+CONFIG_MSPETH_NAPI=y
+# CONFIG_MSPETH_SKB_RECYCLE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_PMCMSP_GPIO=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_PMCMSP=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+CONFIG_PMCTWILED=y
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 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
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_SQUASHFS_VMALLOC=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+CONFIG_SYS_SUPPORTS_KGDB=y
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_MIPS_UNCACHED is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
deleted file mode 100644
index 2854731..0000000
--- a/arch/mips/configs/ocelot_3_defconfig
+++ /dev/null
@@ -1,1283 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:35 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-CONFIG_MOMENCO_OCELOT_3=y
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_CPU_RM7K=y
-CONFIG_IRQ_MV64340=y
-CONFIG_PCI_MARVELL=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_BOOT_ELF32=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-CONFIG_CPU_RM9000=y
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM9000=y
-CONFIG_WEAK_ORDERING=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-CONFIG_IPV6_MIP6=y
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_SIT=m
-# CONFIG_IPV6_TUNNEL is not set
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_NETWORK_SECMARK=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# Core Netfilter Configuration
-#
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_CT_ACCT=y
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-CONFIG_NETFILTER_XT_MATCH_DCCP=m
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_CONNTRACK_PROC_COMPAT=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-
-#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
-#
-CONFIG_NF_CONNTRACK_IPV6=m
-# CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-CONFIG_FIB_RULES=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
-CONFIG_SCSI_NETLINK=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-# CONFIG_BLK_DEV_SD is not set
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
-# CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-CONFIG_SCSI_SCAN_ASYNC=y
-
-#
-# SCSI Transports
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-CONFIG_SCSI_FC_ATTRS=m
-CONFIG_SCSI_ISCSI_ATTRS=m
-CONFIG_SCSI_SAS_ATTRS=m
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
-
-#
-# SCSI low-level drivers
-#
-CONFIG_ISCSI_TCP=m
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-CONFIG_SCSI_AIC94XX=m
-# CONFIG_AIC94XX_DEBUG is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_STEX is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
-# CONFIG_SCSI_QLA_ISCSI is not set
-# CONFIG_SCSI_LPFC is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-CONFIG_E100=y
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_MV643XX_ETH=y
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-CONFIG_SLHC=m
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
-# CONFIG_XFS_POSIX_ACL is not set
-# CONFIG_XFS_RT is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=m
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EFS_FS=y
-CONFIG_CRAMFS=y
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V3_ACL is not set
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS=m
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="ip=any root=nfs"
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
deleted file mode 100644
index 82ff6fc..0000000
--- a/arch/mips/configs/ocelot_c_defconfig
+++ /dev/null
@@ -1,982 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:36 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-CONFIG_MOMENCO_OCELOT_C=y
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_MV64340=y
-CONFIG_PCI_MARVELL=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-CONFIG_CPU_RM7000=y
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM7000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-# CONFIG_32BIT is not set
-CONFIG_64BIT=y
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_RESOURCES_64BIT=y
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_BUILD_ELF64 is not set
-CONFIG_MIPS32_COMPAT=y
-CONFIG_COMPAT=y
-CONFIG_SYSVIPC_COMPAT=y
-CONFIG_MIPS32_O32=y
-CONFIG_MIPS32_N32=y
-CONFIG_BINFMT_ELF32=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=y
-CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=y
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=y
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_MV643XX_ETH is not set
-CONFIG_QLA3XXX=y
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=y
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=y
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=y
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index 15a027e..e1db1fb 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 CONFIG_MOMENCO_OCELOT=y
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 37d696c..0028aef 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index b11f0e8..8a1d588 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 2927f38..5581ad2 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -26,9 +26,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index fae16c5..821c1ce 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 CONFIG_PNX8550_JBS=y
diff --git a/arch/mips/configs/pnx8550-stb810_defconfig b/arch/mips/configs/pnx8550-stb810_defconfig
index cd821e5..0e8bd92 100644
--- a/arch/mips/configs/pnx8550-stb810_defconfig
+++ b/arch/mips/configs/pnx8550-stb810_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index 8e8d031..6cca105 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/rbhma4200_defconfig b/arch/mips/configs/rbhma4200_defconfig
index 35d6426..20a3852 100644
--- a/arch/mips/configs/rbhma4200_defconfig
+++ b/arch/mips/configs/rbhma4200_defconfig
@@ -24,17 +24,13 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
 # CONFIG_WR_PPMC is not set
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
 # CONFIG_PNX8550_STB810 is not set
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index 41011f7..5dbb250 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:39 2007
+# Linux kernel version: 2.6.22-rc5
+# Fri Jun 22 21:39:45 2007
 #
 CONFIG_MIPS=y
 
@@ -9,40 +9,23 @@
 # Machine selection
 #
 CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MACH_ALCHEMY is not set
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
 # CONFIG_WR_PPMC is not set
 # CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
 # CONFIG_PNX8550_STB810 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_MSP is not set
 # CONFIG_PMC_YOSEMITE is not set
 # CONFIG_QEMU is not set
 # CONFIG_MARKEINS is not set
@@ -82,6 +65,8 @@
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_I8259=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_GPIO=y
 # CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
@@ -93,6 +78,7 @@
 #
 # CPU selection
 #
+# CONFIG_CPU_LOONGSON2 is not set
 # CONFIG_CPU_MIPS32_R1 is not set
 # CONFIG_CPU_MIPS32_R2 is not set
 # CONFIG_CPU_MIPS64_R1 is not set
@@ -149,12 +135,12 @@
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
+CONFIG_HZ_250=y
 # CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
 # CONFIG_HZ_1024 is not set
 CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
+CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -186,28 +172,35 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
+# CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
 # CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -244,17 +237,12 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_MMU=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -266,10 +254,7 @@
 #
 # Power management options
 #
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+# CONFIG_PM is not set
 
 #
 # Networking
@@ -279,14 +264,9 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -294,7 +274,7 @@
 CONFIG_IP_FIB_HASH=y
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
@@ -305,130 +285,23 @@
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-CONFIG_IPV6_MIP6=y
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_SIT=m
-# CONFIG_IPV6_TUNNEL is not set
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_NETWORK_SECMARK=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# Core Netfilter Configuration
-#
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_CT_ACCT=y
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-CONFIG_NETFILTER_XT_MATCH_DCCP=m
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_CONNTRACK_PROC_COMPAT=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-
-#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
-#
-CONFIG_NF_CONNTRACK_IPV6=m
-# CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -446,7 +319,6 @@
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -455,15 +327,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-CONFIG_FIB_RULES=y
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -474,94 +347,13 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# OneNAND Flash Device Drivers
-#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
 
 #
 # Parallel port support
@@ -583,93 +375,30 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-CONFIG_SGI_IOC4=m
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=m
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_TC86C001=m
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
-CONFIG_RAID_ATTRS=m
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
 # CONFIG_ATA is not set
 
 #
@@ -685,6 +414,7 @@
 #
 # IEEE 1394 (FireWire) support
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 
 #
@@ -699,36 +429,15 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
+# CONFIG_TUN is not set
 # CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=y
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
@@ -747,6 +456,7 @@
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
+CONFIG_TC35815=y
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
@@ -761,91 +471,20 @@
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_IPW2100 is not set
-CONFIG_IPW2200=m
-# CONFIG_IPW2200_MONITOR is not set
-# CONFIG_IPW2200_QOS is not set
-# CONFIG_IPW2200_DEBUG is not set
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-# CONFIG_USB_ZD1201 is not set
-# CONFIG_HOSTAP is not set
-# CONFIG_BCM43XX is not set
-# CONFIG_ZD1211RW is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Wan interfaces
-#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
+# CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-CONFIG_SLHC=m
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
@@ -864,57 +503,18 @@
 #
 # Input device support
 #
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+# CONFIG_INPUT is not set
 
 #
 # Hardware I/O ports
 #
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
 
 #
 # Character devices
 #
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -926,11 +526,12 @@
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_TXX9=y
 CONFIG_HAS_TXX9_SERIAL=y
 CONFIG_SERIAL_TXX9_NR_UARTS=6
-# CONFIG_SERIAL_TXX9_CONSOLE is not set
-# CONFIG_SERIAL_TXX9_STDSERIAL is not set
+CONFIG_SERIAL_TXX9_CONSOLE=y
+CONFIG_SERIAL_TXX9_STDSERIAL=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
@@ -940,15 +541,10 @@
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_DRM is not set
@@ -958,229 +554,78 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
 # SPI support
 #
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_TXX9=y
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_AT25=y
+# CONFIG_SPI_SPIDEV is not set
 
 #
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-CONFIG_FB_ATY=y
-CONFIG_FB_ATY_CT=y
-# CONFIG_FB_ATY_GENERIC_LCD is not set
-# CONFIG_FB_ATY_GX is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
+
+#
 # Sound
 #
 # CONFIG_SOUND is not set
 
 #
-# HID Devices
-#
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-
-#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB_ARCH_HAS_EHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_OTG is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_OHCI_HCD is not set
-# CONFIG_USB_UHCI_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
+# CONFIG_USB is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
-#
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-CONFIG_USB_YEALINK=m
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
-CONFIG_USB_MON=y
-
-#
-# USB port drivers
-#
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_BERRY_CHARGE is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_FTDI_ELAN is not set
-# CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
-
-#
-# USB DSL modem support
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -1208,7 +653,43 @@
 #
 # Real Time Clock
 #
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+CONFIG_RTC_DRV_RS5C348=y
+# CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
 
 #
 # DMA Engine support
@@ -1224,38 +705,15 @@
 #
 
 #
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
 # File systems
 #
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
 # CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
-# CONFIG_XFS_POSIX_ACL is not set
-# CONFIG_XFS_RT is not set
+# CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1265,26 +723,21 @@
 # CONFIG_QUOTA is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=m
-CONFIG_FUSE_FS=m
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 CONFIG_GENERIC_ACL=y
 
 #
 # CD-ROM/DVD Filesystems
 #
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
+# CONFIG_ISO9660_FS is not set
 # CONFIG_UDF_FS is not set
 
 #
 # DOS/FAT/NT Filesystems
 #
-CONFIG_FAT_FS=y
 # CONFIG_MSDOS_FS is not set
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1298,7 +751,7 @@
 CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1310,16 +763,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_SUMMARY is not set
-# CONFIG_JFFS2_FS_XATTR is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-CONFIG_CRAMFS=y
+# CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -1334,19 +778,16 @@
 # CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=m
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+# CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1362,54 +803,12 @@
 #
 # Native Language Support
 #
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+# CONFIG_NLS is not set
 
 #
 # Distributed Lock Manager
 #
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
 
 #
 # Profiling support
@@ -1427,7 +826,6 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
 CONFIG_SYS_SUPPORTS_KGDB=y
@@ -1441,62 +839,17 @@
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
+# CONFIG_LIBCRC32C is not set
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 5593cde..1a67a85 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 6c4f09a..98a9140 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 988b9cd..69c08b2 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 CONFIG_MIPS_SEAD=y
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0219_defconfig b/arch/mips/configs/tb0219_defconfig
index 8b1675c..5d4fc0e 100644
--- a/arch/mips/configs/tb0219_defconfig
+++ b/arch/mips/configs/tb0219_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index b5be8b74..1b92b48 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index 8bb6be4..5b77c7a 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 8f019ff..94a4f94 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig
index 52b48c0..e38bd9b 100644
--- a/arch/mips/configs/wrppmc_defconfig
+++ b/arch/mips/configs/wrppmc_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 6824606..f1cdb12 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile
index 23fd3b8..4864b8a 100644
--- a/arch/mips/ddb5xxx/ddb5477/Makefile
+++ b/arch/mips/ddb5xxx/ddb5477/Makefile
@@ -2,7 +2,8 @@
 # Makefile for NEC DDB-Vrc5477 board
 #
 
-obj-y	 		+= irq.o irq_5477.o setup.o lcd44780.o
+obj-y	 		+= ddb5477-platform.o irq.o irq_5477.o setup.o \
+			   lcd44780.o
 
 obj-$(CONFIG_RUNTIME_DEBUG) 	+= debug.o
 obj-$(CONFIG_KGDB)		+= kgdb_io.o
diff --git a/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c b/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c
new file mode 100644
index 0000000..c16020a
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c
@@ -0,0 +1,49 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+
+#include <asm/ddb5xxx/ddb5477.h>
+
+#define DDB_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+#define DDB5477_PORT(base, int)						\
+{									\
+	.mapbase	= base,						\
+	.irq		= int,						\
+	.uartclk	= 1843200,					\
+	.iotype		= UPIO_MEM,					\
+	.flags		= DDB_UART_FLAGS,				\
+	.regshift	= 3,						\
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+	DDB5477_PORT(0xbfa04200, VRC5477_IRQ_UART0),
+	DDB5477_PORT(0xbfa04240, VRC5477_IRQ_UART1),
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the NEC DDB5477");
diff --git a/arch/mips/dec/prom/console.c b/arch/mips/dec/prom/console.c
index 65419bf..078e1a1 100644
--- a/arch/mips/dec/prom/console.c
+++ b/arch/mips/dec/prom/console.c
@@ -3,7 +3,7 @@
  *
  *	DECstation PROM-based early console support.
  *
- *	Copyright (C) 2004  Maciej W. Rozycki
+ *	Copyright (C) 2004, 2007  Maciej W. Rozycki
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -13,15 +13,35 @@
 #include <linux/console.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/string.h>
 
 #include <asm/dec/prom.h>
 
-void prom_putchar(char c)
+static void __init prom_console_write(struct console *con, const char *s,
+				      unsigned int c)
 {
-	char s[2];
+	char buf[81];
+	unsigned int chunk = sizeof(buf) - 1;
 
-	s[0] = c;
-	s[1] = '\0';
+	while (c > 0) {
+		if (chunk > c)
+			chunk = c;
+		memcpy(buf, s, chunk);
+		buf[chunk] = '\0';
+		prom_printf("%s", buf);
+		s += chunk;
+		c -= chunk;
+	}
+}
 
-	prom_printf( s);
+static struct console promcons __initdata = {
+	.name	= "prom",
+	.write	= prom_console_write,
+	.flags	= CON_BOOT | CON_PRINTBUFFER,
+	.index	= -1,
+};
+
+void __init register_prom_console(void)
+{
+	register_console(&promcons);
 }
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
index a217aaf..808c182 100644
--- a/arch/mips/dec/prom/init.c
+++ b/arch/mips/dec/prom/init.c
@@ -86,7 +86,7 @@
 
 void __init prom_init(void)
 {
-	extern void ATTRIB_NORET dec_machine_halt(void);
+	extern void dec_machine_halt(void);
 	static char cpu_msg[] __initdata =
 		"Sorry, this kernel is compiled for a wrong CPU type!\n";
 	s32 argc = fw_arg0;
@@ -103,6 +103,9 @@
 	if (prom_is_rex(magic))
 		rex_clear_cache();
 
+	/* Register the early console.  */
+	register_prom_console();
+
 	/* Were we compiled with the right CPU option? */
 #if defined(CONFIG_CPU_R3000)
 	if ((current_cpu_data.cputype == CPU_R4000SC) ||
diff --git a/arch/mips/dec/reset.c b/arch/mips/dec/reset.c
index 5639722..c15a879 100644
--- a/arch/mips/dec/reset.c
+++ b/arch/mips/dec/reset.c
@@ -9,26 +9,26 @@
 
 #include <asm/addrspace.h>
 
-typedef void ATTRIB_NORET (* noret_func_t)(void);
+typedef void __noreturn (* noret_func_t)(void);
 
-static inline void ATTRIB_NORET back_to_prom(void)
+static inline void __noreturn back_to_prom(void)
 {
 	noret_func_t func = (void *)CKSEG1ADDR(0x1fc00000);
 
 	func();
 }
 
-void ATTRIB_NORET dec_machine_restart(char *command)
+void __noreturn dec_machine_restart(char *command)
 {
 	back_to_prom();
 }
 
-void ATTRIB_NORET dec_machine_halt(void)
+void __noreturn dec_machine_halt(void)
 {
 	back_to_prom();
 }
 
-void ATTRIB_NORET dec_machine_power_off(void)
+void __noreturn dec_machine_power_off(void)
 {
     /* DECstations don't have a software power switch */
 	back_to_prom();
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 41211f8..b3b6e58 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -25,9 +25,7 @@
 # CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
 # CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
 # CONFIG_MOMENCO_OCELOT_G is not set
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/gt64120/ev64120/Kconfig b/arch/mips/gt64120/ev64120/Kconfig
deleted file mode 100644
index d691762..0000000
--- a/arch/mips/gt64120/ev64120/Kconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-config EVB_PCI1
-	bool "Enable Second PCI (PCI1)"
-	depends on MIPS_EV64120
diff --git a/arch/mips/gt64120/ev64120/Makefile b/arch/mips/gt64120/ev64120/Makefile
deleted file mode 100644
index 323b2ce..0000000
--- a/arch/mips/gt64120/ev64120/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-#  Copyright 2000 RidgeRun, Inc.
-#  Author: RidgeRun, Inc.
-#     	glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
-#
-# Makefile for the Galileo EV64120 board.
-#
-
-obj-y	+= irq.o promcon.o reset.o serialGT.o setup.o
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
deleted file mode 100644
index 64e4c80..0000000
--- a/arch/mips/gt64120/ev64120/irq.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Code to handle irqs on GT64120A boards
- *  Derived from mips/orion and Cort <cort@fsmlabs.com>
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-#include <asm/gt64120.h>
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
-
-	if (pending & STATUSF_IP4)		/* int2 hardware line (timer) */
-		do_IRQ(4);
-	else if (pending & STATUSF_IP2)		/* int0 hardware line */
-		do_IRQ(GT_INTA);
-	else if (pending & STATUSF_IP5)		/* int3 hardware line */
-		do_IRQ(GT_INTD);
-	else if (pending & STATUSF_IP6)		/* int4 hardware line */
-		do_IRQ(6);
-	else if (pending & STATUSF_IP7)		/* compare int */
-		do_IRQ(7);
-	else
-		spurious_interrupt();
-}
-
-static void disable_ev64120_irq(unsigned int irq_nr)
-{
-	if (irq_nr >= 8) {	// All PCI interrupts are on line 5 or 2
-		clear_c0_status(9 << 10);
-	} else {
-		clear_c0_status(1 << (irq_nr + 8));
-	}
-}
-
-static void enable_ev64120_irq(unsigned int irq_nr)
-{
-	if (irq_nr >= 8)	// All PCI interrupts are on line 5 or 2
-		set_c0_status(9 << 10);
-	else
-		set_c0_status(1 << (irq_nr + 8));
-}
-
-static void end_ev64120_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_ev64120_irq(irq);
-}
-
-static struct irq_chip ev64120_irq_type = {
-	.name		= "EV64120",
-	.ack		= disable_ev64120_irq,
-	.mask		= disable_ev64120_irq,
-	.mask_ack	= disable_ev64120_irq,
-	.unmask		= enable_ev64120_irq,
-	.end		= end_ev64120_irq,
-};
-
-void gt64120_irq_setup(void)
-{
-	/*
-	 * Clear all of the interrupts while we change the able around a bit.
-	 */
-	clear_c0_status(ST0_IM);
-
-	/*
-	 * Enable timer.  Other interrupts will be enabled as they are
-	 * registered.
-	 */
-	set_c0_status(IE_IRQ2);
-}
-
-void __init arch_init_irq(void)
-{
-	gt64120_irq_setup();
-}
diff --git a/arch/mips/gt64120/ev64120/promcon.c b/arch/mips/gt64120/ev64120/promcon.c
deleted file mode 100644
index 6e0ecfe..0000000
--- a/arch/mips/gt64120/ev64120/promcon.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Wrap-around code for a console using the
- * SGI PROM io-routines.
- *
- * Copyright (c) 1999 Ulf Carlsson
- *
- * Derived from DECstation promcon.c
- * Copyright (c) 1998 Harald Koerfgen
- */
-#include <linux/tty.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-static void prom_console_write(struct console *co, const char *s,
-			       unsigned count)
-{
-	extern int CONSOLE_CHANNEL;	// The default serial port
-	unsigned i;
-
-	for (i = 0; i < count; i++) {
-		if (*s == 10)
-			serial_putc(CONSOLE_CHANNEL, 13);
-		serial_putc(CONSOLE_CHANNEL, *s++);
-	}
-}
-
-static struct console sercons = {
-    .name	= "ttyS",
-    .write	= prom_console_write,
-    .flags	= CON_PRINTBUFFER,
-    .index	= -1,
-};
-
-/*
- *    Register console.
- */
-
-static int gal_serial_console_init(void)
-{
-	//  serial_init();
-	//serial_set(115200);
-
-	register_console(&sercons);
-
-	return 0;
-}
-
-console_initcall(gal_serial_console_init);
diff --git a/arch/mips/gt64120/ev64120/reset.c b/arch/mips/gt64120/ev64120/reset.c
deleted file mode 100644
index 7b9f5e5..0000000
--- a/arch/mips/gt64120/ev64120/reset.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1997 Ralf Baechle
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void galileo_machine_restart(char *command)
-{
-	*(volatile char *) 0xbc000000 = 0x0f;
-	/*
-	 * Ouch, we're still alive ... This time we take the silver bullet ...
-	 * ... and find that we leave the hardware in a state in which the
-	 * kernel in the flush locks up somewhen during of after the PCI
-	 * detection stuff.
-	 */
-	set_c0_status(ST0_BEV | ST0_ERL);
-	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-	flush_cache_all();
-	write_c0_wired(0);
-	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
-}
-
-void galileo_machine_halt(void)
-{
-	printk(KERN_NOTICE "You can safely turn off the power\n");
-	while (1)
-		__asm__(".set\tmips3\n\t"
-	                "wait\n\t"
-			".set\tmips0");
-
-}
-
-void galileo_machine_power_off(void)
-{
-	galileo_machine_halt();
-}
diff --git a/arch/mips/gt64120/ev64120/serialGT.c b/arch/mips/gt64120/ev64120/serialGT.c
deleted file mode 100644
index 8f0d835..0000000
--- a/arch/mips/gt64120/ev64120/serialGT.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * serialGT.c
- *
- * BRIEF MODULE DESCRIPTION
- *  Low Level Serial Port control for use
- *  with the Galileo EVB64120A MIPS eval board and
- *  its on board two channel 16552 Uart.
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-// Note:
-//   Serial CHANNELS - 0 is the bottom connector of evb64120A.
-//                       (The one that maps to the "B" channel of the
-//                       board's uart)
-//                     1 is the top connector of evb64120A.
-//                       (The one that maps to the "A" channel of the
-//                       board's uart)
-int DEBUG_CHANNEL = 0;		// See Note Above
-int CONSOLE_CHANNEL = 1;	// See Note Above
-
-#define DUART 0xBD000000	/* Base address of Uart. */
-#define CHANNELOFFSET 0x20	/* DUART+CHANNELOFFSET gets you to the ChanA
-				   register set of the 16552 Uart device.
-				   DUART+0 gets you to the ChanB register set.
-				 */
-#define DUART_DELTA 0x4
-#define FIFO_ENABLE 0x07
-#define INT_ENABLE  0x04	/* default interrupt mask */
-
-#define RBR 0x00
-#define THR 0x00
-#define DLL 0x00
-#define IER 0x01
-#define DLM 0x01
-#define IIR 0x02
-#define FCR 0x02
-#define LCR 0x03
-#define MCR 0x04
-#define LSR 0x05
-#define MSR 0x06
-#define SCR 0x07
-
-#define LCR_DLAB 0x80
-#define XTAL 1843200
-#define LSR_THRE 0x20
-#define LSR_BI   0x10
-#define LSR_DR   0x01
-#define MCR_LOOP 0x10
-#define ACCESS_DELAY 0x10000
-
-/******************************
- Routine:
- Description:
- ******************************/
-int inreg(int channel, int reg)
-{
-	int val;
-	val =
-	    *((volatile unsigned char *) DUART +
-	      (channel * CHANNELOFFSET) + (reg * DUART_DELTA));
-	return val;
-}
-
-/******************************
- Routine:
- Description:
- ******************************/
-void outreg(int channel, int reg, unsigned char val)
-{
-	*((volatile unsigned char *) DUART + (channel * CHANNELOFFSET)
-	  + (reg * DUART_DELTA)) = val;
-}
-
-/******************************
- Routine:
- Description:
-   Initialize the device driver.
- ******************************/
-void serial_init(int channel)
-{
-	/*
-	 * Configure active port, (CHANNELOFFSET already set.)
-	 *
-	 * Set 8 bits, 1 stop bit, no parity.
-	 *
-	 * LCR<7>       0       divisor latch access bit
-	 * LCR<6>       0       break control (1=send break)
-	 * LCR<5>       0       stick parity (0=space, 1=mark)
-	 * LCR<4>       0       parity even (0=odd, 1=even)
-	 * LCR<3>       0       parity enable (1=enabled)
-	 * LCR<2>       0       # stop bits (0=1, 1=1.5)
-	 * LCR<1:0>     11      bits per character(00=5, 01=6, 10=7, 11=8)
-	 */
-	outreg(channel, LCR, 0x3);
-
-	outreg(channel, FCR, FIFO_ENABLE);	/* Enable the FIFO */
-
-	outreg(channel, IER, INT_ENABLE);	/* Enable appropriate interrupts */
-}
-
-/******************************
- Routine:
- Description:
-   Set the baud rate.
- ******************************/
-void serial_set(int channel, unsigned long baud)
-{
-	unsigned char sav_lcr;
-
-	/*
-	 * Enable access to the divisor latches by setting DLAB in LCR.
-	 *
-	 */
-	sav_lcr = inreg(channel, LCR);
-
-#if 0
-	/*
-	 * Set baud rate
-	 */
-	outreg(channel, LCR, LCR_DLAB | sav_lcr);
-	//  outreg(DLL,(XTAL/(16*2*(baud))-2));
-	outreg(channel, DLL, XTAL / (16 * baud));
-	//  outreg(DLM,(XTAL/(16*2*(baud))-2)>>8);
-	outreg(channel, DLM, (XTAL / (16 * baud)) >> 8);
-#else
-	/*
-	 * Note: Set baud rate, hardcoded here for rate of 115200
-	 * since became unsure of above "baud rate" algorithm (??).
-	 */
-	outreg(channel, LCR, 0x83);
-	outreg(channel, DLM, 0x00);	// See note above
-	outreg(channel, DLL, 0x02);	// See note above.
-	outreg(channel, LCR, 0x03);
-#endif
-
-	/*
-	 * Restore line control register
-	 */
-	outreg(channel, LCR, sav_lcr);
-}
-
-
-/******************************
- Routine:
- Description:
-   Transmit a character.
- ******************************/
-void serial_putc(int channel, int c)
-{
-	while ((inreg(channel, LSR) & LSR_THRE) == 0);
-	outreg(channel, THR, c);
-}
-
-/******************************
- Routine:
- Description:
-    Read a received character if one is
-    available.  Return -1 otherwise.
- ******************************/
-int serial_getc(int channel)
-{
-	if (inreg(channel, LSR) & LSR_DR) {
-		return inreg(channel, RBR);
-	}
-	return -1;
-}
-
-/******************************
- Routine:
- Description:
-   Used by embedded gdb client. (example; gdb-stub.c)
- ******************************/
-char getDebugChar()
-{
-	int val;
-	while ((val = serial_getc(DEBUG_CHANNEL)) == -1);	// loop until we get a character in.
-	return (char) val;
-}
-
-/******************************
- Routine:
- Description:
-   Used by embedded gdb target. (example; gdb-stub.c)
- ******************************/
-void putDebugChar(char c)
-{
-	serial_putc(DEBUG_CHANNEL, (int) c);
-}
diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c
deleted file mode 100644
index 477848c..0000000
--- a/arch/mips/gt64120/ev64120/setup.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/timex.h>
-#include <linux/pm.h>
-
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/time.h>
-#include <asm/reboot.h>
-#include <asm/traps.h>
-#include <linux/bootmem.h>
-
-unsigned long gt64120_base = KSEG1ADDR(0x14000000);
-
-/* These functions are used for rebooting or halting the machine*/
-extern void galileo_machine_restart(char *command);
-extern void galileo_machine_halt(void);
-extern void galileo_machine_power_off(void);
-/*
- *This structure holds pointers to the pci configuration space accesses
- *and interrupts allocating routine for device over the PCI
- */
-extern struct pci_ops galileo_pci_ops;
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-/*
- * Initializes basic routines and structures pointers, memory size (as
- * given by the bios and saves the command line.
- */
-
-void __init plat_mem_setup(void)
-{
-	_machine_restart = galileo_machine_restart;
-	_machine_halt = galileo_machine_halt;
-	pm_power_off = galileo_machine_power_off;
-
-	set_io_port_base(KSEG1);
-}
-
-const char *get_system_type(void)
-{
-	return "Galileo EV64120A";
-}
-
-/*
- * Kernel arguments passed by the firmware
- *
- * $a0 - nothing
- * $a1 - holds a pointer to the eprom parameters
- * $a2 - nothing
- */
-
-void __init prom_init(void)
-{
-	mips_machgroup = MACH_GROUP_GALILEO;
-	mips_machtype = MACH_EV64120A;
-
-	add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/gt64120/momenco_ocelot/Makefile b/arch/mips/gt64120/momenco_ocelot/Makefile
index 9f9a33f..1df5fe2 100644
--- a/arch/mips/gt64120/momenco_ocelot/Makefile
+++ b/arch/mips/gt64120/momenco_ocelot/Makefile
@@ -2,6 +2,6 @@
 # Makefile for Momentum's Ocelot board.
 #
 
-obj-y	 		+= irq.o prom.o reset.o setup.o
+obj-y	 		+= irq.o ocelot-platform.o prom.o reset.o setup.o
 
 obj-$(CONFIG_KGDB)	+= dbg_io.o
diff --git a/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c b/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c
new file mode 100644
index 0000000..81d9031
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c
@@ -0,0 +1,46 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * A NS16552 DUART with a 20MHz crystal.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define OCELOT_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+static struct plat_serial8250_port uart8250_data[] = {
+	{
+		.mapbase	= 0xe0001020,
+		.irq		= 4,
+		.uartclk	= 20000000,
+		.iotype		= UPIO_MEM,
+		.flags		= OCELOT_UART_FLAGS,
+		.regshift	= 2,
+	},
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Momenco Ocelot");
diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c
index 121188d..ea96552 100644
--- a/arch/mips/gt64120/wrppmc/setup.c
+++ b/arch/mips/gt64120/wrppmc/setup.c
@@ -158,8 +158,8 @@
  */
 void __init prom_init(void)
 {
-	mips_machgroup = MACH_GROUP_GALILEO;
-	mips_machtype = MACH_EV64120A;
+	mips_machgroup = MACH_GROUP_WINDRIVER;
+	mips_machtype = MACH_WRPPMC;
 
 	add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM);
 	add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA);
diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile
index dd9d99b..ae4c402 100644
--- a/arch/mips/jazz/Makefile
+++ b/arch/mips/jazz/Makefile
@@ -2,4 +2,4 @@
 # Makefile for the Jazz family specific parts of the kernel
 #
 
-obj-y	 	:= irq.o jazzdma.o reset.o setup.o
+obj-y	 	:= irq.o jazzdma.o jazz-platform.o reset.o setup.o
diff --git a/arch/mips/jazz/jazz-platform.c b/arch/mips/jazz/jazz-platform.c
new file mode 100644
index 0000000..fd73670
--- /dev/null
+++ b/arch/mips/jazz/jazz-platform.c
@@ -0,0 +1,60 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+
+#include <asm/jazz.h>
+
+/*
+ * Confusion ...  It seems the original Microsoft Jazz machine used to have a
+ * 4.096MHz clock for its UART while the MIPS Magnum and Millenium systems
+ * had 8MHz.  The Olivetti M700-10 and the Acer PICA have 1.8432MHz like PCs.
+ */
+#ifdef CONFIG_OLIVETTI_M700
+#define JAZZ_BASE_BAUD 1843200
+#else
+#define JAZZ_BASE_BAUD	8000000	/* 3072000 */
+#endif
+
+#define JAZZ_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+#define JAZZ_PORT(base, int)						\
+{									\
+	.mapbase	= base,						\
+	.irq		= int,						\
+	.uartclk	= JAZZ_BASE_BAUD,				\
+	.iotype		= UPIO_MEM,					\
+	.flags		= JAZZ_UART_FLAGS,				\
+	.regshift	= 0,						\
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+	JAZZ_PORT(JAZZ_SERIAL1_BASE, JAZZ_SERIAL1_IRQ),
+	JAZZ_PORT(JAZZ_SERIAL2_BASE, JAZZ_SERIAL2_IRQ),
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Jazz family");
diff --git a/arch/mips/kernel/8250-platform.c b/arch/mips/kernel/8250-platform.c
new file mode 100644
index 0000000..cbf3fe2
--- /dev/null
+++ b/arch/mips/kernel/8250-platform.c
@@ -0,0 +1,47 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(base, int)							\
+{									\
+	.iobase		= base,						\
+	.irq		= int,						\
+	.uartclk	= 1843200,					\
+	.iotype		= UPIO_PORT,					\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,		\
+	.regshift	= 0,						\
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+	PORT(0x3F8, 4),
+	PORT(0x2F8, 3),
+	PORT(0x3E8, 4),
+	PORT(0x2E8, 3),
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250 UART probe driver");
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 4924626..961594c 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -14,14 +14,15 @@
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 
+obj-$(CONFIG_CPU_LOONGSON2)	+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_MIPS32)	+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_MIPS64)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R3000)		+= r2300_fpu.o r2300_switch.o
-obj-$(CONFIG_CPU_TX39XX)	+= r2300_fpu.o r2300_switch.o
-obj-$(CONFIG_CPU_TX49XX)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R4000)		+= r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_VR41XX)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R4300)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R4X00)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R5000)		+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R6000)		+= r6000_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R5432)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R8000)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_RM7000)	+= r4k_fpu.o r4k_switch.o
@@ -29,13 +30,14 @@
 obj-$(CONFIG_CPU_NEVADA)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_R10000)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_SB1)		+= r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_MIPS32)	+= r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_MIPS64)	+= r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_R6000)		+= r6000_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_TX39XX)	+= r2300_fpu.o r2300_switch.o
+obj-$(CONFIG_CPU_TX49XX)	+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_VR41XX)	+= r4k_fpu.o r4k_switch.o
 
 obj-$(CONFIG_SMP)		+= smp.o
 
 obj-$(CONFIG_MIPS_MT)		+= mips-mt.o
+obj-$(CONFIG_MIPS_MT_FPAFF)	+= mips-mt-fpaff.o
 obj-$(CONFIG_MIPS_MT_SMTC)	+= smtc.o smtc-asm.o smtc-proc.o
 obj-$(CONFIG_MIPS_MT_SMP)	+= smp-mt.o
 
@@ -47,7 +49,6 @@
 obj-$(CONFIG_IRQ_CPU)		+= irq_cpu.o
 obj-$(CONFIG_IRQ_CPU_RM7K)	+= irq-rm7000.o
 obj-$(CONFIG_IRQ_CPU_RM9K)	+= irq-rm9000.o
-obj-$(CONFIG_IRQ_MV64340)	+= irq-mv6434x.o
 obj-$(CONFIG_MIPS_BOARDS_GEN)	+= irq-msc01.o
 
 obj-$(CONFIG_32BIT)		+= scall32-o32.o
@@ -68,3 +69,5 @@
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 
 CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
+
+obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT)	+= 8250-platform.o
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index b12eeee..c6b8b07 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -186,9 +186,29 @@
 	}
 }
 
+static inline void check_errata(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+
+	switch (c->cputype) {
+	case CPU_34K:
+		/*
+		 * Erratum "RPS May Cause Incorrect Instruction Execution"
+		 * This code only handles VPE0, any SMP/SMTC/RTOS code
+		 * making use of VPE1 will be responsable for that VPE.
+		 */
+		if ((c->processor_id & PRID_REV_MASK) <= PRID_REV_34K_V1_0_2)
+			write_c0_config7(read_c0_config7() | MIPS_CONF7_RPS);
+		break;
+	default:
+		break;
+	}
+}
+
 void __init check_bugs32(void)
 {
 	check_wait();
+	check_errata();
 }
 
 /*
@@ -485,6 +505,14 @@
 		             MIPS_CPU_LLSC;
 		c->tlbsize = 64;
 		break;
+	case PRID_IMP_LOONGSON2:
+		c->cputype = CPU_LOONGSON2;
+		c->isa_level = MIPS_CPU_ISA_III;
+		c->options = R4K_OPTS |
+			     MIPS_CPU_FPU | MIPS_CPU_LLSC |
+			     MIPS_CPU_32FPR;
+		c->tlbsize = 64;
+		break;
 	}
 }
 
@@ -588,6 +616,8 @@
 		c->options |= MIPS_CPU_VEIC;
 	if (config3 & MIPS_CONF3_MT)
 	        c->ases |= MIPS_ASE_MIPSMT;
+	if (config3 & MIPS_CONF3_ULRI)
+		c->options |= MIPS_CPU_ULRI;
 
 	return config3 & MIPS_CONF_M;
 }
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 6f57ca4..f78538e 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/threads.h>
 
+#include <asm/addrspace.h>
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
 #include <asm/irqflags.h>
@@ -129,24 +130,25 @@
 #endif
 	.endm
 
+#ifndef CONFIG_NO_EXCEPT_FILL
 	/*
 	 * Reserved space for exception handlers.
 	 * Necessary for machines which link their kernels at KSEG0.
 	 */
 	.fill	0x400
+#endif
 
 EXPORT(stext)					# used for profiling
 EXPORT(_stext)
 
-#ifdef CONFIG_MIPS_SIM
+#ifdef CONFIG_BOOT_RAW
 	/*
 	 * Give us a fighting chance of running if execution beings at the
 	 * kernel load address.  This is needed because this platform does
 	 * not have a ELF loader yet.
 	 */
-	j	kernel_entry
-#endif
 	__INIT
+#endif
 
 NESTED(kernel_entry, 16, sp)			# kernel entry point
 
@@ -197,9 +199,7 @@
 	j		start_kernel
 	END(kernel_entry)
 
-#ifdef CONFIG_QEMU
 	__INIT
-#endif
 
 #ifdef CONFIG_SMP
 /*
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c
deleted file mode 100644
index 3dd5618..0000000
--- a/arch/mips/kernel/irq-mv6434x.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/mv643xx.h>
-#include <linux/sched.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/marvell.h>
-
-static unsigned int irq_base;
-
-static inline int ls1bit32(unsigned int x)
-{
-	int b = 31, s;
-
-	s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
-	s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
-	s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
-	s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
-	s =  1; if (x <<  1 == 0) s = 0; b -= s;
-
-        return b;
-}
-
-/* mask off an interrupt -- 1 is enable, 0 is disable */
-static inline void mask_mv64340_irq(unsigned int irq)
-{
-	uint32_t value;
-
-	if (irq < (irq_base + 32)) {
-		value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
-		value &= ~(1 << (irq - irq_base));
-		MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
-	} else {
-		value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
-		value &= ~(1 << (irq - irq_base - 32));
-		MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
-	}
-}
-
-/* unmask an interrupt -- 1 is enable, 0 is disable */
-static inline void unmask_mv64340_irq(unsigned int irq)
-{
-	uint32_t value;
-
-	if (irq < (irq_base + 32)) {
-		value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
-		value |= 1 << (irq - irq_base);
-		MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
-	} else {
-		value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
-		value |= 1 << (irq - irq_base - 32);
-		MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
-	}
-}
-
-/*
- * Interrupt handler for interrupts coming from the Marvell chip.
- * It could be built in ethernet ports etc...
- */
-void ll_mv64340_irq(void)
-{
-	unsigned int irq_src_low, irq_src_high;
- 	unsigned int irq_mask_low, irq_mask_high;
-
-	/* read the interrupt status registers */
-	irq_mask_low = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
-	irq_mask_high = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
-	irq_src_low = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_LOW);
-	irq_src_high = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_HIGH);
-
-	/* mask for just the interrupts we want */
-	irq_src_low &= irq_mask_low;
-	irq_src_high &= irq_mask_high;
-
-	if (irq_src_low)
-		do_IRQ(ls1bit32(irq_src_low) + irq_base);
-	else
-		do_IRQ(ls1bit32(irq_src_high) + irq_base + 32);
-}
-
-struct irq_chip mv64340_irq_type = {
-	.name = "MV-64340",
-	.ack = mask_mv64340_irq,
-	.mask = mask_mv64340_irq,
-	.mask_ack = mask_mv64340_irq,
-	.unmask = unmask_mv64340_irq,
-};
-
-void __init mv64340_irq_init(unsigned int base)
-{
-	int i;
-
-	for (i = base; i < base + 64; i++)
-		set_irq_chip_and_handler(i, &mv64340_irq_type,
-					 handle_level_irq);
-
-	irq_base = base;
-}
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
new file mode 100644
index 0000000..ede5d73d
--- /dev/null
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -0,0 +1,176 @@
+/*
+ * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/security.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+
+/*
+ * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
+ */
+cpumask_t mt_fpu_cpumask;
+
+static int fpaff_threshold = -1;
+unsigned long mt_fpemul_threshold = 0;
+
+/*
+ * Replacement functions for the sys_sched_setaffinity() and
+ * sys_sched_getaffinity() system calls, so that we can integrate
+ * FPU affinity with the user's requested processor affinity.
+ * This code is 98% identical with the sys_sched_setaffinity()
+ * and sys_sched_getaffinity() system calls, and should be
+ * updated when kernel/sched.c changes.
+ */
+
+/*
+ * find_process_by_pid - find a process with a matching PID value.
+ * used in sys_sched_set/getaffinity() in kernel/sched.c, so
+ * cloned here.
+ */
+static inline struct task_struct *find_process_by_pid(pid_t pid)
+{
+	return pid ? find_task_by_pid(pid) : current;
+}
+
+
+/*
+ * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
+				      unsigned long __user *user_mask_ptr)
+{
+	cpumask_t new_mask;
+	cpumask_t effective_mask;
+	int retval;
+	struct task_struct *p;
+
+	if (len < sizeof(new_mask))
+		return -EINVAL;
+
+	if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
+		return -EFAULT;
+
+	lock_cpu_hotplug();
+	read_lock(&tasklist_lock);
+
+	p = find_process_by_pid(pid);
+	if (!p) {
+		read_unlock(&tasklist_lock);
+		unlock_cpu_hotplug();
+		return -ESRCH;
+	}
+
+	/*
+	 * It is not safe to call set_cpus_allowed with the
+	 * tasklist_lock held.  We will bump the task_struct's
+	 * usage count and drop tasklist_lock before invoking
+	 * set_cpus_allowed.
+	 */
+	get_task_struct(p);
+
+	retval = -EPERM;
+	if ((current->euid != p->euid) && (current->euid != p->uid) &&
+			!capable(CAP_SYS_NICE)) {
+		read_unlock(&tasklist_lock);
+		goto out_unlock;
+	}
+
+	retval = security_task_setscheduler(p, 0, NULL);
+	if (retval)
+		goto out_unlock;
+
+	/* Record new user-specified CPU set for future reference */
+	p->thread.user_cpus_allowed = new_mask;
+
+	/* Unlock the task list */
+	read_unlock(&tasklist_lock);
+
+	/* Compute new global allowed CPU set if necessary */
+	if ((p->thread.mflags & MF_FPUBOUND)
+	&& cpus_intersects(new_mask, mt_fpu_cpumask)) {
+		cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
+		retval = set_cpus_allowed(p, effective_mask);
+	} else {
+		p->thread.mflags &= ~MF_FPUBOUND;
+		retval = set_cpus_allowed(p, new_mask);
+	}
+
+
+out_unlock:
+	put_task_struct(p);
+	unlock_cpu_hotplug();
+	return retval;
+}
+
+/*
+ * mipsmt_sys_sched_getaffinity - get the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
+				      unsigned long __user *user_mask_ptr)
+{
+	unsigned int real_len;
+	cpumask_t mask;
+	int retval;
+	struct task_struct *p;
+
+	real_len = sizeof(mask);
+	if (len < real_len)
+		return -EINVAL;
+
+	lock_cpu_hotplug();
+	read_lock(&tasklist_lock);
+
+	retval = -ESRCH;
+	p = find_process_by_pid(pid);
+	if (!p)
+		goto out_unlock;
+	retval = security_task_getscheduler(p);
+	if (retval)
+		goto out_unlock;
+
+	cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
+
+out_unlock:
+	read_unlock(&tasklist_lock);
+	unlock_cpu_hotplug();
+	if (retval)
+		return retval;
+	if (copy_to_user(user_mask_ptr, &mask, real_len))
+		return -EFAULT;
+	return real_len;
+}
+
+
+static int __init fpaff_thresh(char *str)
+{
+	get_option(&str, &fpaff_threshold);
+	return 1;
+}
+__setup("fpaff=", fpaff_thresh);
+
+/*
+ * FPU Use Factor empirically derived from experiments on 34K
+ */
+#define FPUSEFACTOR 333
+
+static __init int mt_fp_affinity_init(void)
+{
+	if (fpaff_threshold >= 0) {
+		mt_fpemul_threshold = fpaff_threshold;
+	} else {
+		mt_fpemul_threshold =
+			(FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
+	}
+	printk(KERN_DEBUG "FPU Affinity set after %ld emulations\n",
+	       mt_fpemul_threshold);
+
+	return 0;
+}
+arch_initcall(mt_fp_affinity_init);
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index ba01800..1a7d892 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -6,7 +6,6 @@
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/cpumask.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/security.h>
@@ -23,149 +22,6 @@
 #include <asm/cacheflush.h>
 
 /*
- * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
- */
-
-cpumask_t mt_fpu_cpumask;
-
-#ifdef CONFIG_MIPS_MT_FPAFF
-
-#include <linux/cpu.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-
-unsigned long mt_fpemul_threshold = 0;
-
-/*
- * Replacement functions for the sys_sched_setaffinity() and
- * sys_sched_getaffinity() system calls, so that we can integrate
- * FPU affinity with the user's requested processor affinity.
- * This code is 98% identical with the sys_sched_setaffinity()
- * and sys_sched_getaffinity() system calls, and should be
- * updated when kernel/sched.c changes.
- */
-
-/*
- * find_process_by_pid - find a process with a matching PID value.
- * used in sys_sched_set/getaffinity() in kernel/sched.c, so
- * cloned here.
- */
-static inline struct task_struct *find_process_by_pid(pid_t pid)
-{
-	return pid ? find_task_by_pid(pid) : current;
-}
-
-
-/*
- * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
- */
-asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
-				      unsigned long __user *user_mask_ptr)
-{
-	cpumask_t new_mask;
-	cpumask_t effective_mask;
-	int retval;
-	struct task_struct *p;
-
-	if (len < sizeof(new_mask))
-		return -EINVAL;
-
-	if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
-		return -EFAULT;
-
-	lock_cpu_hotplug();
-	read_lock(&tasklist_lock);
-
-	p = find_process_by_pid(pid);
-	if (!p) {
-		read_unlock(&tasklist_lock);
-		unlock_cpu_hotplug();
-		return -ESRCH;
-	}
-
-	/*
-	 * It is not safe to call set_cpus_allowed with the
-	 * tasklist_lock held.  We will bump the task_struct's
-	 * usage count and drop tasklist_lock before invoking
-	 * set_cpus_allowed.
-	 */
-	get_task_struct(p);
-
-	retval = -EPERM;
-	if ((current->euid != p->euid) && (current->euid != p->uid) &&
-			!capable(CAP_SYS_NICE)) {
-		read_unlock(&tasklist_lock);
-		goto out_unlock;
-	}
-
-	retval = security_task_setscheduler(p, 0, NULL);
-	if (retval)
-		goto out_unlock;
-
-	/* Record new user-specified CPU set for future reference */
-	p->thread.user_cpus_allowed = new_mask;
-
-	/* Unlock the task list */
-	read_unlock(&tasklist_lock);
-
-	/* Compute new global allowed CPU set if necessary */
-	if( (p->thread.mflags & MF_FPUBOUND)
-	&& cpus_intersects(new_mask, mt_fpu_cpumask)) {
-		cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
-		retval = set_cpus_allowed(p, effective_mask);
-	} else {
-		p->thread.mflags &= ~MF_FPUBOUND;
-		retval = set_cpus_allowed(p, new_mask);
-	}
-
-
-out_unlock:
-	put_task_struct(p);
-	unlock_cpu_hotplug();
-	return retval;
-}
-
-/*
- * mipsmt_sys_sched_getaffinity - get the cpu affinity of a process
- */
-asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
-				      unsigned long __user *user_mask_ptr)
-{
-	unsigned int real_len;
-	cpumask_t mask;
-	int retval;
-	struct task_struct *p;
-
-	real_len = sizeof(mask);
-	if (len < real_len)
-		return -EINVAL;
-
-	lock_cpu_hotplug();
-	read_lock(&tasklist_lock);
-
-	retval = -ESRCH;
-	p = find_process_by_pid(pid);
-	if (!p)
-		goto out_unlock;
-	retval = security_task_getscheduler(p);
-	if (retval)
-		goto out_unlock;
-
-	cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
-
-out_unlock:
-	read_unlock(&tasklist_lock);
-	unlock_cpu_hotplug();
-	if (retval)
-		return retval;
-	if (copy_to_user(user_mask_ptr, &mask, real_len))
-		return -EFAULT;
-	return real_len;
-}
-
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
-/*
  * Dump new MIPS MT state for the core. Does not leave TCs halted.
  * Takes an argument which taken to be a pre-call MVPControl value.
  */
@@ -195,27 +51,31 @@
 	nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
 	ntc = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
 	printk("-- per-VPE State --\n");
-	for(i = 0; i < nvpe; i++) {
-	    for(tc = 0; tc < ntc; tc++) {
+	for (i = 0; i < nvpe; i++) {
+		for (tc = 0; tc < ntc; tc++) {
 			settc(tc);
-		if((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
-		    printk("  VPE %d\n", i);
-		    printk("   VPEControl : %08lx\n", read_vpe_c0_vpecontrol());
-		    printk("   VPEConf0 : %08lx\n", read_vpe_c0_vpeconf0());
-		    printk("   VPE%d.Status : %08lx\n",
-				i, read_vpe_c0_status());
-		    printk("   VPE%d.EPC : %08lx\n", i, read_vpe_c0_epc());
-		    printk("   VPE%d.Cause : %08lx\n", i, read_vpe_c0_cause());
-		    printk("   VPE%d.Config7 : %08lx\n",
-				i, read_vpe_c0_config7());
-		    break; /* Next VPE */
+			if ((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
+				printk("  VPE %d\n", i);
+				printk("   VPEControl : %08lx\n",
+				       read_vpe_c0_vpecontrol());
+				printk("   VPEConf0 : %08lx\n",
+				       read_vpe_c0_vpeconf0());
+				printk("   VPE%d.Status : %08lx\n",
+				       i, read_vpe_c0_status());
+				printk("   VPE%d.EPC : %08lx\n",
+				       i, read_vpe_c0_epc());
+				printk("   VPE%d.Cause : %08lx\n",
+				       i, read_vpe_c0_cause());
+				printk("   VPE%d.Config7 : %08lx\n",
+				       i, read_vpe_c0_config7());
+				break; /* Next VPE */
+			}
 		}
-	    }
 	}
 	printk("-- per-TC State --\n");
-	for(tc = 0; tc < ntc; tc++) {
+	for (tc = 0; tc < ntc; tc++) {
 		settc(tc);
-		if(read_tc_c0_tcbind() == read_c0_tcbind()) {
+		if (read_tc_c0_tcbind() == read_c0_tcbind()) {
 			/* Are we dumping ourself?  */
 			haltval = 0; /* Then we're not halted, and mustn't be */
 			tcstatval = flags; /* And pre-dump TCStatus is flags */
@@ -310,17 +170,6 @@
 	return 1;
 }
 __setup("ndflush=", ndflush);
-#ifdef CONFIG_MIPS_MT_FPAFF
-static int fpaff_threshold = -1;
-
-static int __init fpaff_thresh(char *str)
-{
-	get_option(&str, &fpaff_threshold);
-	return 1;
-}
-
-__setup("fpaff=", fpaff_thresh);
-#endif /* CONFIG_MIPS_MT_FPAFF */
 
 static unsigned int itc_base = 0;
 
@@ -376,20 +225,6 @@
 	if (mt_n_dflushes != 1)
 		printk("D-Cache Flushes Repeated %d times\n", mt_n_dflushes);
 
-#ifdef CONFIG_MIPS_MT_FPAFF
-	/* FPU Use Factor empirically derived from experiments on 34K */
-#define FPUSEFACTOR 333
-
-	if (fpaff_threshold >= 0) {
-		mt_fpemul_threshold = fpaff_threshold;
-	} else {
-		mt_fpemul_threshold =
-			(FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
-	}
-	printk("FPU Affinity set after %ld emulations\n",
-			mt_fpemul_threshold);
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
 	if (itc_base != 0) {
 		/*
 		 * Configure ITC mapping.  This code is very
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 5ddc2e9..ec04f5a 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -14,7 +14,6 @@
 #include <asm/cpu-features.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
-#include <asm/watch.h>
 
 unsigned int vced_count, vcei_count;
 
@@ -84,6 +83,7 @@
 	[CPU_VR4181A]	= "NEC VR4181A",
 	[CPU_SR71000]	= "Sandcraft SR71000",
 	[CPU_PR4450]	= "Philips PR4450",
+	[CPU_LOONGSON2]	= "ICT Loongson-2",
 };
 
 
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 6bdfb5a..8f4cf27c 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -46,7 +46,7 @@
  * power and have a low exit latency (ie sit in a loop waiting for somebody to
  * say that they'd like to reschedule)
  */
-ATTRIB_NORET void cpu_idle(void)
+void __noreturn cpu_idle(void)
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
@@ -213,7 +213,7 @@
 /*
  * Create a kernel thread
  */
-static ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *))
+static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
 {
 	do_exit(fn(arg));
 }
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 4975da0..316685f 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -20,6 +20,7 @@
 #include <linux/highmem.h>
 #include <linux/console.h>
 #include <linux/pfn.h>
+#include <linux/debugfs.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
@@ -574,3 +575,18 @@
 
 unsigned long kernelsp[NR_CPUS];
 unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *mips_debugfs_dir;
+static int __init debugfs_mips(void)
+{
+	struct dentry *d;
+
+	d = debugfs_create_dir("mips", NULL);
+	if (IS_ERR(d))
+		return PTR_ERR(d);
+	mips_debugfs_dir = d;
+	return 0;
+}
+arch_initcall(debugfs_mips);
+#endif
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 67edfa7..be7362b 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -51,18 +51,8 @@
 EXPORT_SYMBOL(phys_cpu_present_map);
 EXPORT_SYMBOL(cpu_online_map);
 
-/* This happens early in bootup, can't really do it better */
-static void smp_tune_scheduling (void)
-{
-	struct cache_desc *cd = &current_cpu_data.scache;
-	unsigned long cachesize = cd->linesz * cd->sets * cd->ways;
-
-	if (cachesize > max_cache_size)
-		max_cache_size = cachesize;
-}
-
 extern void __init calibrate_delay(void);
-extern ATTRIB_NORET void cpu_idle(void);
+extern void cpu_idle(void);
 
 /*
  * First C code run on the secondary CPUs after being started up by
@@ -228,7 +218,6 @@
 {
 	init_new_context(current, &init_mm);
 	current_thread_info()->cpu = 0;
-	smp_tune_scheduling();
 	plat_prepare_cpus(max_cpus);
 #ifndef CONFIG_HOTPLUG_CPU
 	cpu_present_map = cpu_possible_map;
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 046b03b..342d873 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1104,7 +1104,7 @@
 	mtflags = dmt();
 	pdb_msg = &id_ho_db_msg[0];
 	im = read_c0_status();
-	vpe = cpu_data[smp_processor_id()].vpe_id;
+	vpe = current_cpu_data.vpe_id;
 	for (bit = 0; bit < 8; bit++) {
 		/*
 		 * In current prototype, I/O interrupts
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 9dd5a2d..b947c61 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -272,9 +272,8 @@
 	struct thread_info *ti = task_thread_info(current);
 
 	ti->tp_value = addr;
-
-	/* If some future MIPS implementation has this register in hardware,
-	 * we will need to update it here (and in context switches).  */
+	if (cpu_has_userlocal)
+		write_c0_userlocal(addr);
 
 	return 0;
 }
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 3ea7863..80ea4fa 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -39,7 +39,6 @@
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
-#include <asm/watch.h>
 #include <asm/types.h>
 #include <asm/stacktrace.h>
 
@@ -70,6 +69,7 @@
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
 	struct mips_fpu_struct *ctx, int has_fpu);
 
+void (*board_watchpoint_handler)(struct pt_regs *regs);
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
 void (*board_nmi_handler_setup)(void);
@@ -311,7 +311,7 @@
 
 static DEFINE_SPINLOCK(die_lock);
 
-NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
+void __noreturn die(const char * str, struct pt_regs * regs)
 {
 	static int die_counter;
 #ifdef CONFIG_MIPS_MT_SMTC
@@ -753,6 +753,33 @@
 	force_sig(SIGILL, current);
 }
 
+/*
+ * MIPS MT processors may have fewer FPU contexts than CPU threads. If we've
+ * emulated more than some threshold number of instructions, force migration to
+ * a "CPU" that has FP support.
+ */
+static void mt_ase_fp_affinity(void)
+{
+#ifdef CONFIG_MIPS_MT_FPAFF
+	if (mt_fpemul_threshold > 0 &&
+	     ((current->thread.emulated_fp++ > mt_fpemul_threshold))) {
+		/*
+		 * If there's no FPU present, or if the application has already
+		 * restricted the allowed set to exclude any CPUs with FPUs,
+		 * we'll skip the procedure.
+		 */
+		if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) {
+			cpumask_t tmask;
+
+			cpus_and(tmask, current->thread.user_cpus_allowed,
+			         mt_fpu_cpumask);
+			set_cpus_allowed(current, tmask);
+			current->thread.mflags |= MF_FPUBOUND;
+		}
+	}
+#endif /* CONFIG_MIPS_MT_FPAFF */
+}
+
 asmlinkage void do_cpu(struct pt_regs *regs)
 {
 	unsigned int cpid;
@@ -786,36 +813,8 @@
 						&current->thread.fpu, 0);
 			if (sig)
 				force_sig(sig, current);
-#ifdef CONFIG_MIPS_MT_FPAFF
-			else {
-			/*
-			 * MIPS MT processors may have fewer FPU contexts
-			 * than CPU threads. If we've emulated more than
-			 * some threshold number of instructions, force
-			 * migration to a "CPU" that has FP support.
-			 */
-			 if(mt_fpemul_threshold > 0
-			 && ((current->thread.emulated_fp++
-			    > mt_fpemul_threshold))) {
-			  /*
-			   * If there's no FPU present, or if the
-			   * application has already restricted
-			   * the allowed set to exclude any CPUs
-			   * with FPUs, we'll skip the procedure.
-			   */
-			  if (cpus_intersects(current->cpus_allowed,
-			  			mt_fpu_cpumask)) {
-			    cpumask_t tmask;
-
-			    cpus_and(tmask,
-					current->thread.user_cpus_allowed,
-					mt_fpu_cpumask);
-			    set_cpus_allowed(current, tmask);
-			    current->thread.mflags |= MF_FPUBOUND;
-			  }
-			 }
-			}
-#endif /* CONFIG_MIPS_MT_FPAFF */
+			else
+				mt_ase_fp_affinity();
 		}
 
 		return;
@@ -835,6 +834,11 @@
 
 asmlinkage void do_watch(struct pt_regs *regs)
 {
+	if (board_watchpoint_handler) {
+		(*board_watchpoint_handler)(regs);
+		return;
+	}
+
 	/*
 	 * We use the watch exception where available to detect stack
 	 * overflows.
@@ -1343,7 +1347,14 @@
 		set_c0_status(ST0_MX);
 
 #ifdef CONFIG_CPU_MIPSR2
-	write_c0_hwrena (0x0000000f); /* Allow rdhwr to all registers */
+	if (cpu_has_mips_r2) {
+		unsigned int enable = 0x0000000f;
+
+		if (cpu_has_userlocal)
+			enable |= (1 << 29);
+
+		write_c0_hwrena(enable);
+	}
 #endif
 
 #ifdef CONFIG_MIPS_MT_SMTC
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 18c4a3c..8b9c34f 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -77,6 +77,7 @@
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/sched.h>
+#include <linux/debugfs.h>
 #include <asm/asm.h>
 #include <asm/branch.h>
 #include <asm/byteorder.h>
@@ -87,9 +88,18 @@
 #define STR(x)  __STR(x)
 #define __STR(x)  #x
 
-#ifdef CONFIG_PROC_FS
-unsigned long unaligned_instructions;
+enum {
+	UNALIGNED_ACTION_QUIET,
+	UNALIGNED_ACTION_SIGNAL,
+	UNALIGNED_ACTION_SHOW,
+};
+#ifdef CONFIG_DEBUG_FS
+static u32 unaligned_instructions;
+static u32 unaligned_action;
+#else
+#define unaligned_action UNALIGNED_ACTION_QUIET
 #endif
+extern void show_registers(struct pt_regs *regs);
 
 static inline int emulate_load_store_insn(struct pt_regs *regs,
 	void __user *addr, unsigned int __user *pc,
@@ -459,7 +469,7 @@
 		goto sigill;
 	}
 
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_DEBUG_FS
 	unaligned_instructions++;
 #endif
 
@@ -516,6 +526,10 @@
 	pc = (unsigned int __user *) exception_epc(regs);
 	if (user_mode(regs) && (current->thread.mflags & MF_FIXADE) == 0)
 		goto sigbus;
+	if (unaligned_action == UNALIGNED_ACTION_SIGNAL)
+		goto sigbus;
+	else if (unaligned_action == UNALIGNED_ACTION_SHOW)
+		show_registers(regs);
 
 	/*
 	 * Do branch emulation only if we didn't forward the exception.
@@ -546,3 +560,24 @@
 	 * XXX On return from the signal handler we should advance the epc
 	 */
 }
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *mips_debugfs_dir;
+static int __init debugfs_unaligned(void)
+{
+	struct dentry *d;
+
+	if (!mips_debugfs_dir)
+		return -ENODEV;
+	d = debugfs_create_u32("unaligned_instructions", S_IRUGO,
+			       mips_debugfs_dir, &unaligned_instructions);
+	if (IS_ERR(d))
+		return PTR_ERR(d);
+	d = debugfs_create_u32("unaligned_action", S_IRUGO | S_IWUSR,
+			       mips_debugfs_dir, &unaligned_action);
+	if (IS_ERR(d))
+		return PTR_ERR(d);
+	return 0;
+}
+__initcall(debugfs_unaligned);
+#endif
diff --git a/arch/mips/lasat/Kconfig b/arch/mips/lasat/Kconfig
deleted file mode 100644
index 1d2ee8a..0000000
--- a/arch/mips/lasat/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-config PICVUE
-	tristate "PICVUE LCD display driver"
-	depends on LASAT
-
-config PICVUE_PROC
-	tristate "PICVUE LCD display driver /proc interface"
-	depends on PICVUE
-
-config DS1603
-	bool "DS1603 RTC driver"
-	depends on LASAT
-
-config LASAT_SYSCTL
-	bool "LASAT sysctl interface"
-	depends on LASAT
diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile
deleted file mode 100644
index 99f5046..0000000
--- a/arch/mips/lasat/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for the LASAT specific kernel interface routines under Linux.
-#
-
-obj-y	 			+= reset.o setup.o prom.o lasat_board.o \
-				   at93c.o interrupt.o
-
-obj-$(CONFIG_LASAT_SYSCTL)	+= sysctl.o
-obj-$(CONFIG_DS1603)		+= ds1603.o
-obj-$(CONFIG_PICVUE)		+= picvue.o
-obj-$(CONFIG_PICVUE_PROC)	+= picvue_proc.o
-
-clean:
-	make -C image clean
diff --git a/arch/mips/lasat/at93c.c b/arch/mips/lasat/at93c.c
deleted file mode 100644
index ca26e55..0000000
--- a/arch/mips/lasat/at93c.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Atmel AT93C46 serial eeprom driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/lasat/lasat.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "at93c.h"
-
-#define AT93C_ADDR_SHIFT	7
-#define AT93C_ADDR_MAX		((1 << AT93C_ADDR_SHIFT) - 1)
-#define AT93C_RCMD		(0x6 << AT93C_ADDR_SHIFT)
-#define AT93C_WCMD		(0x5 << AT93C_ADDR_SHIFT)
-#define AT93C_WENCMD		0x260
-#define AT93C_WDSCMD		0x200
-
-struct at93c_defs *at93c;
-
-static void at93c_reg_write(u32 val)
-{
-	*at93c->reg = val;
-}
-
-static u32 at93c_reg_read(void)
-{
-	u32 tmp = *at93c->reg;
-	return tmp;
-}
-
-static u32 at93c_datareg_read(void)
-{
-	u32 tmp = *at93c->rdata_reg;
-	return tmp;
-}
-
-static void at93c_cycle_clk(u32 data)
-{
-	at93c_reg_write(data | at93c->clk);
-	lasat_ndelay(250);
-	at93c_reg_write(data & ~at93c->clk);
-	lasat_ndelay(250);
-}
-
-static void at93c_write_databit(u8 bit)
-{
-	u32 data = at93c_reg_read();
-	if (bit)
-		data |= 1 << at93c->wdata_shift;
-	else
-		data &= ~(1 << at93c->wdata_shift);
-
-	at93c_reg_write(data);
-	lasat_ndelay(100);
-	at93c_cycle_clk(data);
-}
-
-static unsigned int at93c_read_databit(void)
-{
-	u32 data;
-
-	at93c_cycle_clk(at93c_reg_read());
-	data = (at93c_datareg_read() >> at93c->rdata_shift) & 1;
-	return data;
-}
-
-static u8 at93c_read_byte(void)
-{
-	int i;
-	u8 data = 0;
-
-	for (i = 0; i<=7; i++) {
-		data <<= 1;
-		data |= at93c_read_databit();
-	}
-	return data;
-}
-
-static void at93c_write_bits(u32 data, int size)
-{
-	int i;
-	int shift = size - 1;
-	u32 mask = (1 << shift);
-
-	for (i = 0; i < size; i++) {
-		at93c_write_databit((data & mask) >> shift);
-		data <<= 1;
-	}
-}
-
-static void at93c_init_op(void)
-{
-	at93c_reg_write((at93c_reg_read() | at93c->cs) & ~at93c->clk & ~(1 << at93c->rdata_shift));
-	lasat_ndelay(50);
-}
-
-static void at93c_end_op(void)
-{
-	at93c_reg_write(at93c_reg_read() & ~at93c->cs);
-	lasat_ndelay(250);
-}
-
-static void at93c_wait(void)
-{
-	at93c_init_op();
-	while (!at93c_read_databit())
-		;
-	at93c_end_op();
-};
-
-static void at93c_disable_wp(void)
-{
-	at93c_init_op();
-	at93c_write_bits(AT93C_WENCMD, 10);
-	at93c_end_op();
-}
-
-static void at93c_enable_wp(void)
-{
-	at93c_init_op();
-	at93c_write_bits(AT93C_WDSCMD, 10);
-	at93c_end_op();
-}
-
-u8 at93c_read(u8 addr)
-{
-	u8 byte;
-	at93c_init_op();
-	at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_RCMD, 10);
-	byte = at93c_read_byte();
-	at93c_end_op();
-	return byte;
-}
-
-void at93c_write(u8 addr, u8 data)
-{
-	at93c_disable_wp();
-	at93c_init_op();
-	at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_WCMD, 10);
-	at93c_write_bits(data, 8);
-	at93c_end_op();
-	at93c_wait();
-	at93c_enable_wp();
-}
diff --git a/arch/mips/lasat/at93c.h b/arch/mips/lasat/at93c.h
deleted file mode 100644
index cfe2f99..0000000
--- a/arch/mips/lasat/at93c.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Atmel AT93C46 serial eeprom driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-
-extern struct at93c_defs {
-	volatile u32 *reg;
-	volatile u32 *rdata_reg;
-	int rdata_shift;
-	int wdata_shift;
-	u32 cs;
-	u32 clk;
-} *at93c;
-
-u8 at93c_read(u8 addr);
-void at93c_write(u8 addr, u8 data);
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c
deleted file mode 100644
index 7dced67..0000000
--- a/arch/mips/lasat/ds1603.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Dallas Semiconductors 1603 RTC driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#include <linux/kernel.h>
-#include <asm/lasat/lasat.h>
-#include <linux/delay.h>
-#include <asm/lasat/ds1603.h>
-#include <asm/time.h>
-
-#include "ds1603.h"
-
-#define READ_TIME_CMD 0x81
-#define SET_TIME_CMD 0x80
-#define TRIMMER_SET_CMD 0xC0
-#define TRIMMER_VALUE_MASK 0x38
-#define TRIMMER_SHIFT 3
-
-struct ds_defs *ds1603 = NULL;
-
-/* HW specific register functions */
-static void rtc_reg_write(unsigned long val)
-{
-	*ds1603->reg = val;
-}
-
-static unsigned long rtc_reg_read(void)
-{
-	unsigned long tmp = *ds1603->reg;
-	return tmp;
-}
-
-static unsigned long rtc_datareg_read(void)
-{
-	unsigned long tmp = *ds1603->data_reg;
-	return tmp;
-}
-
-static void rtc_nrst_high(void)
-{
-	rtc_reg_write(rtc_reg_read() | ds1603->rst);
-}
-
-static void rtc_nrst_low(void)
-{
-	rtc_reg_write(rtc_reg_read() & ~ds1603->rst);
-}
-
-static void rtc_cycle_clock(unsigned long data)
-{
-	data |= ds1603->clk;
-	rtc_reg_write(data);
-	lasat_ndelay(250);
-	if (ds1603->data_reversed)
-		data &= ~ds1603->data;
-	else
-		data |= ds1603->data;
-	data &= ~ds1603->clk;
-	rtc_reg_write(data);
-	lasat_ndelay(250 + ds1603->huge_delay);
-}
-
-static void rtc_write_databit(unsigned int bit)
-{
-	unsigned long data = rtc_reg_read();
-	if (ds1603->data_reversed)
-		bit = !bit;
-	if (bit)
-		data |= ds1603->data;
-	else
-		data &= ~ds1603->data;
-
-	rtc_reg_write(data);
-	lasat_ndelay(50 + ds1603->huge_delay);
-	rtc_cycle_clock(data);
-}
-
-static unsigned int rtc_read_databit(void)
-{
-	unsigned int data;
-
-	data = (rtc_datareg_read() & (1 << ds1603->data_read_shift))
-		>> ds1603->data_read_shift;
-	rtc_cycle_clock(rtc_reg_read());
-	return data;
-}
-
-static void rtc_write_byte(unsigned int byte)
-{
-	int i;
-
-	for (i = 0; i<=7; i++) {
-		rtc_write_databit(byte & 1L);
-		byte >>= 1;
-	}
-}
-
-static void rtc_write_word(unsigned long word)
-{
-	int i;
-
-	for (i = 0; i<=31; i++) {
-		rtc_write_databit(word & 1L);
-		word >>= 1;
-	}
-}
-
-static unsigned long rtc_read_word(void)
-{
-	int i;
-	unsigned long word = 0;
-	unsigned long shift = 0;
-
-	for (i = 0; i<=31; i++) {
-		word |= rtc_read_databit() << shift;
-		shift++;
-	}
-	return word;
-}
-
-static void rtc_init_op(void)
-{
-	rtc_nrst_high();
-
-	rtc_reg_write(rtc_reg_read() & ~ds1603->clk);
-
-	lasat_ndelay(50);
-}
-
-static void rtc_end_op(void)
-{
-	rtc_nrst_low();
-	lasat_ndelay(1000);
-}
-
-/* interface */
-unsigned long ds1603_read(void)
-{
-	unsigned long word;
-	unsigned long flags;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	rtc_init_op();
-	rtc_write_byte(READ_TIME_CMD);
-	word = rtc_read_word();
-	rtc_end_op();
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return word;
-}
-
-int ds1603_set(unsigned long time)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	rtc_init_op();
-	rtc_write_byte(SET_TIME_CMD);
-	rtc_write_word(time);
-	rtc_end_op();
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return 0;
-}
-
-void ds1603_set_trimmer(unsigned int trimval)
-{
-	rtc_init_op();
-	rtc_write_byte(((trimval << TRIMMER_SHIFT) & TRIMMER_VALUE_MASK)
-			| (TRIMMER_SET_CMD));
-	rtc_end_op();
-}
-
-void ds1603_disable(void)
-{
-	ds1603_set_trimmer(TRIMMER_DISABLE_RTC);
-}
-
-void ds1603_enable(void)
-{
-	ds1603_set_trimmer(TRIMMER_DEFAULT);
-}
diff --git a/arch/mips/lasat/ds1603.h b/arch/mips/lasat/ds1603.h
deleted file mode 100644
index c2e5c76..0000000
--- a/arch/mips/lasat/ds1603.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Dallas Semiconductors 1603 RTC driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#ifndef __DS1603_H
-#define __DS1603_H
-
-struct ds_defs {
-	volatile u32 *reg;
-	volatile u32 *data_reg;
-	u32 rst;
-	u32 clk;
-	u32 data;
-	u32 data_read_shift;
-	char data_reversed;
-	u32 huge_delay;
-};
-
-extern struct ds_defs *ds1603;
-
-unsigned long ds1603_read(void);
-int ds1603_set(unsigned long);
-void ds1603_set_trimmer(unsigned int);
-void ds1603_enable(void);
-void ds1603_disable(void);
-void ds1603_init(struct ds_defs *);
-
-#define TRIMMER_DEFAULT	3
-#define TRIMMER_DISABLE_RTC 0
-
-#endif
diff --git a/arch/mips/lasat/image/Makefile b/arch/mips/lasat/image/Makefile
deleted file mode 100644
index 35ecd64..0000000
--- a/arch/mips/lasat/image/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# MAKEFILE FOR THE MIPS LINUX BOOTLOADER AND ROM DEBUGGER
-#
-# i-data Networks
-#
-# Author: Thomas Horsten <thh@i-data.com>
-#
-
-ifndef Version
- Version = "$(USER)-test"
-endif
-
-MKLASATIMG = mklasatimg
-MKLASATIMG_ARCH = mq2,mqpro,sp100,sp200
-KERNEL_IMAGE = $(TOPDIR)/vmlinux
-KERNEL_START = $(shell $(NM) $(KERNEL_IMAGE) | grep " _text" | cut -f1 -d\ )
-KERNEL_ENTRY = $(shell $(NM) $(KERNEL_IMAGE) | grep kernel_entry | cut -f1 -d\ )
-
-LDSCRIPT= -L$(obj) -Tromscript.normal
-
-HEAD_DEFINES := -D_kernel_start=0x$(KERNEL_START) \
-		-D_kernel_entry=0x$(KERNEL_ENTRY) \
-		-D VERSION="\"$(Version)\"" \
-		-D TIMESTAMP=$(shell date +%s)
-
-$(obj)/head.o: $(obj)/head.S $(KERNEL_IMAGE)
-	$(CC) -fno-pic $(HEAD_DEFINES) -I$(TOPDIR)/include -c -o $@ $<
-
-OBJECTS = head.o kImage.o
-
-rom.sw:	$(obj)/rom.sw
-
-$(obj)/rom.sw:	$(obj)/rom.bin
-	$(MKLASATIMG) -o $@ -k $^ -m $(MKLASATIMG_ARCH)
-
-$(obj)/rom.bin: $(obj)/rom
-	$(OBJCOPY) -O binary -S $^ $@
-
-# Rule to make the bootloader
-$(obj)/rom: $(addprefix $(obj)/,$(OBJECTS))
-	$(LD) $(LDFLAGS) $(LDSCRIPT) -o $@ $^
-
-$(obj)/%.o: $(obj)/%.gz
-	$(LD) -r -o $@ -b binary $<
-
-$(obj)/%.gz: $(obj)/%.bin
-	gzip -cf -9 $< > $@
-
-$(obj)/kImage.bin: $(KERNEL_IMAGE)
-	$(OBJCOPY) -O binary -S $^ $@
-
-clean:
-	rm -f rom rom.bin rom.sw kImage.bin kImage.o
diff --git a/arch/mips/lasat/image/head.S b/arch/mips/lasat/image/head.S
deleted file mode 100644
index efb95f2..0000000
--- a/arch/mips/lasat/image/head.S
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <asm/lasat/head.h>
-
-	.text
-	.section .text.start, "ax"
-	.set noreorder
-	.set mips3
-
-	/* Magic words identifying a software image */
-	.word	LASAT_K_MAGIC0_VAL
-	.word 	LASAT_K_MAGIC1_VAL
-
-	/* Image header version */
-	.word	0x00000002
-
-	/* image start and size */
-	.word	_image_start
-	.word	_image_size
-
-	/* start of kernel and entrypoint in uncompressed image */
-	.word	_kernel_start
-	.word	_kernel_entry
-
-	/* Here we have room for future flags */
-
-	.org	0x40
-reldate:
-	.word	TIMESTAMP
-
-	.org	0x50
-release:
-	.string VERSION
diff --git a/arch/mips/lasat/image/romscript.normal b/arch/mips/lasat/image/romscript.normal
deleted file mode 100644
index 988f8ad..0000000
--- a/arch/mips/lasat/image/romscript.normal
+++ /dev/null
@@ -1,23 +0,0 @@
-OUTPUT_ARCH(mips)
-
-SECTIONS
-{
-  .text :
-  {
-    *(.text.start)
-  }
-
-  /* Data in ROM */
-
-  .data ALIGN(0x10) :
-  {
-    *(.data)
-  }
-  _image_start = ADDR(.data);
-  _image_size = SIZEOF(.data);
-
-  .other :
-  {
-    *(.*)
-  }
-}
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
deleted file mode 100644
index 9a622b9..0000000
--- a/arch/mips/lasat/interrupt.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Routines for generic manipulation of the interrupts found on the
- * Lasat boards.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/lasat/lasatint.h>
-#include <asm/time.h>
-#include <asm/gdb-stub.h>
-
-static volatile int *lasat_int_status = NULL;
-static volatile int *lasat_int_mask = NULL;
-static volatile int lasat_int_mask_shift;
-
-void disable_lasat_irq(unsigned int irq_nr)
-{
-	*lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift;
-}
-
-void enable_lasat_irq(unsigned int irq_nr)
-{
-	*lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift;
-}
-
-static struct irq_chip lasat_irq_type = {
-	.name = "Lasat",
-	.ack = disable_lasat_irq,
-	.mask = disable_lasat_irq,
-	.mask_ack = disable_lasat_irq,
-	.unmask = enable_lasat_irq,
-};
-
-static inline int ls1bit32(unsigned int x)
-{
-	int b = 31, s;
-
-	s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
-	s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
-	s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
-	s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
-	s =  1; if (x <<  1 == 0) s = 0; b -= s;
-
-	return b;
-}
-
-static unsigned long (* get_int_status)(void);
-
-static unsigned long get_int_status_100(void)
-{
-	return *lasat_int_status & *lasat_int_mask;
-}
-
-static unsigned long get_int_status_200(void)
-{
-	unsigned long int_status;
-
-	int_status = *lasat_int_status;
-	int_status &= (int_status >> LASATINT_MASK_SHIFT_200) & 0xffff;
-	return int_status;
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned long int_status;
-	unsigned int cause = read_c0_cause();
-	int irq;
-
-	if (cause & CAUSEF_IP7) {	/* R4000 count / compare IRQ */
-		ll_timer_interrupt(7);
-		return;
-	}
-
-	int_status = get_int_status();
-
-	/* if int_status == 0, then the interrupt has already been cleared */
-	if (int_status) {
-		irq = ls1bit32(int_status);
-
-		do_IRQ(irq);
-	}
-}
-
-void __init arch_init_irq(void)
-{
-	int i;
-
-	switch (mips_machtype) {
-	case MACH_LASAT_100:
-		lasat_int_status = (void *)LASAT_INT_STATUS_REG_100;
-		lasat_int_mask = (void *)LASAT_INT_MASK_REG_100;
-		lasat_int_mask_shift = LASATINT_MASK_SHIFT_100;
-		get_int_status = get_int_status_100;
-		*lasat_int_mask = 0;
-		break;
-	case MACH_LASAT_200:
-		lasat_int_status = (void *)LASAT_INT_STATUS_REG_200;
-		lasat_int_mask = (void *)LASAT_INT_MASK_REG_200;
-		lasat_int_mask_shift = LASATINT_MASK_SHIFT_200;
-		get_int_status = get_int_status_200;
-		*lasat_int_mask &= 0xffff;
-		break;
-	default:
-		panic("arch_init_irq: mips_machtype incorrect");
-	}
-
-	for (i = 0; i <= LASATINT_END; i++)
-		set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/lasat/lasat_board.c b/arch/mips/lasat/lasat_board.c
deleted file mode 100644
index fbe9a87..0000000
--- a/arch/mips/lasat/lasat_board.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Routines specific to the LASAT boards
- */
-#include <linux/types.h>
-#include <linux/crc32.h>
-#include <asm/lasat/lasat.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <asm/bootinfo.h>
-#include <asm/addrspace.h>
-#include "at93c.h"
-/* New model description table */
-#include "lasat_models.h"
-
-#define EEPROM_CRC(data, len) (~0 ^ crc32(~0, data, len))
-
-struct lasat_info lasat_board_info;
-
-void update_bcastaddr(void);
-
-int EEPROMRead(unsigned int pos, unsigned char *data, int len)
-{
-	int i;
-
-	for (i=0; i<len; i++)
-		*data++ = at93c_read(pos++);
-
-	return 0;
-}
-int EEPROMWrite(unsigned int pos, unsigned char *data, int len)
-{
-	int i;
-
-	for (i=0; i<len; i++)
-		at93c_write(pos++, *data++);
-
-	return 0;
-}
-
-static void init_flash_sizes(void)
-{
-	int i;
-	unsigned long *lb = lasat_board_info.li_flashpart_base;
-	unsigned long *ls = lasat_board_info.li_flashpart_size;
-
-	ls[LASAT_MTD_BOOTLOADER] = 0x40000;
-	ls[LASAT_MTD_SERVICE] = 0xC0000;
-	ls[LASAT_MTD_NORMAL] = 0x100000;
-
-	if (mips_machtype == MACH_LASAT_100) {
-		lasat_board_info.li_flash_base = 0x1e000000;
-
-		lb[LASAT_MTD_BOOTLOADER] = 0x1e400000;
-
-		if (lasat_board_info.li_flash_size > 0x200000) {
-			ls[LASAT_MTD_CONFIG] = 0x100000;
-			ls[LASAT_MTD_FS] = 0x500000;
-		}
-	} else {
-		lasat_board_info.li_flash_base = 0x10000000;
-
-		if (lasat_board_info.li_flash_size < 0x1000000) {
-			lb[LASAT_MTD_BOOTLOADER] = 0x10000000;
-			ls[LASAT_MTD_CONFIG] = 0x100000;
-			if (lasat_board_info.li_flash_size >= 0x400000) {
-				ls[LASAT_MTD_FS] = lasat_board_info.li_flash_size - 0x300000;
-			}
-		}
-	}
-
-	for (i = 1; i < LASAT_MTD_LAST; i++)
-		lb[i] = lb[i-1] + ls[i-1];
-}
-
-int lasat_init_board_info(void)
-{
-	int c;
-	unsigned long crc;
-	unsigned long cfg0, cfg1;
-	const product_info_t   *ppi;
-	int i_n_base_models = N_BASE_MODELS;
-	const char * const * i_txt_base_models = txt_base_models;
-	int i_n_prids = N_PRIDS;
-
-	memset(&lasat_board_info, 0, sizeof(lasat_board_info));
-
-	/* First read the EEPROM info */
-	EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
-		   sizeof(struct lasat_eeprom_struct));
-
-	/* Check the CRC */
-	crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
-		    sizeof(struct lasat_eeprom_struct) - 4);
-
-	if (crc != lasat_board_info.li_eeprom_info.crc32) {
-		printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM CRC does "
-		       "not match calculated, attempting to soldier on...\n");
-	}
-
-	if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION) {
-		printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM version "
-		       "%d, wanted version %d, attempting to soldier on...\n",
-		       (unsigned int)lasat_board_info.li_eeprom_info.version,
-		       LASAT_EEPROM_VERSION);
-	}
-
-	cfg0 = lasat_board_info.li_eeprom_info.cfg[0];
-	cfg1 = lasat_board_info.li_eeprom_info.cfg[1];
-
-	if ( LASAT_W0_DSCTYPE(cfg0) != 1) {
-		printk(KERN_WARNING "WARNING...\nWARNING...\n"
-		       "Invalid configuration read from EEPROM, attempting to "
-		       "soldier on...");
-	}
-	/* We have a valid configuration */
-
-	switch (LASAT_W0_SDRAMBANKSZ(cfg0)) {
-	case 0:
-		lasat_board_info.li_memsize = 0x0800000;
-		break;
-	case 1:
-		lasat_board_info.li_memsize = 0x1000000;
-		break;
-	case 2:
-		lasat_board_info.li_memsize = 0x2000000;
-		break;
-	case 3:
-		lasat_board_info.li_memsize = 0x4000000;
-		break;
-	case 4:
-		lasat_board_info.li_memsize = 0x8000000;
-		break;
-	default:
-		lasat_board_info.li_memsize = 0;
-	}
-
-	switch (LASAT_W0_SDRAMBANKS(cfg0)) {
-	case 0:
-		break;
-	case 1:
-		lasat_board_info.li_memsize *= 2;
-		break;
-	default:
-		break;
-	}
-
-	switch (LASAT_W0_BUSSPEED(cfg0)) {
-	case 0x0:
-		lasat_board_info.li_bus_hz = 60000000;
-		break;
-	case 0x1:
-		lasat_board_info.li_bus_hz = 66000000;
-		break;
-	case 0x2:
-		lasat_board_info.li_bus_hz = 66666667;
-		break;
-	case 0x3:
-		lasat_board_info.li_bus_hz = 80000000;
-		break;
-	case 0x4:
-		lasat_board_info.li_bus_hz = 83333333;
-		break;
-	case 0x5:
-		lasat_board_info.li_bus_hz = 100000000;
-		break;
-	}
-
-	switch (LASAT_W0_CPUCLK(cfg0)) {
-	case 0x0:
-		lasat_board_info.li_cpu_hz =
-			lasat_board_info.li_bus_hz;
-		break;
-	case 0x1:
-		lasat_board_info.li_cpu_hz =
-			lasat_board_info.li_bus_hz +
-			(lasat_board_info.li_bus_hz >> 1);
-		break;
-	case 0x2:
-		lasat_board_info.li_cpu_hz =
-			lasat_board_info.li_bus_hz +
-			lasat_board_info.li_bus_hz;
-		break;
-	case 0x3:
-		lasat_board_info.li_cpu_hz =
-			lasat_board_info.li_bus_hz +
-			lasat_board_info.li_bus_hz +
-			(lasat_board_info.li_bus_hz >> 1);
-		break;
-	case 0x4:
-		lasat_board_info.li_cpu_hz =
-			lasat_board_info.li_bus_hz +
-			lasat_board_info.li_bus_hz +
-			lasat_board_info.li_bus_hz;
-		break;
-	}
-
-	/* Flash size */
-	switch (LASAT_W1_FLASHSIZE(cfg1)) {
-	case 0:
-		lasat_board_info.li_flash_size = 0x200000;
-		break;
-	case 1:
-		lasat_board_info.li_flash_size = 0x400000;
-		break;
-	case 2:
-		lasat_board_info.li_flash_size = 0x800000;
-		break;
-	case 3:
-		lasat_board_info.li_flash_size = 0x1000000;
-		break;
-	case 4:
-		lasat_board_info.li_flash_size = 0x2000000;
-		break;
-	}
-
-	init_flash_sizes();
-
-	lasat_board_info.li_bmid = LASAT_W0_BMID(cfg0);
-	lasat_board_info.li_prid = lasat_board_info.li_eeprom_info.prid;
-	if (lasat_board_info.li_prid == 0xffff || lasat_board_info.li_prid == 0)
-		lasat_board_info.li_prid = lasat_board_info.li_bmid;
-
-	/* Base model stuff */
-	if (lasat_board_info.li_bmid > i_n_base_models)
-		lasat_board_info.li_bmid = i_n_base_models;
-	strcpy(lasat_board_info.li_bmstr, i_txt_base_models[lasat_board_info.li_bmid]);
-
-	/* Product ID dependent values */
-	c = lasat_board_info.li_prid;
-	if (c >= i_n_prids) {
-		strcpy(lasat_board_info.li_namestr, "Unknown Model");
-		strcpy(lasat_board_info.li_typestr, "Unknown Type");
-	} else {
-		ppi = &vendor_info_table[0].vi_product_info[c];
-		strcpy(lasat_board_info.li_namestr, ppi->pi_name);
-		if (ppi->pi_type)
-			strcpy(lasat_board_info.li_typestr, ppi->pi_type);
-		else
-			sprintf(lasat_board_info.li_typestr, "%d",10*c);
-	}
-
-#if defined(CONFIG_INET) && defined(CONFIG_SYSCTL)
-	update_bcastaddr();
-#endif
-
-	return 0;
-}
-
-void lasat_write_eeprom_info(void)
-{
-	unsigned long crc;
-
-	/* Generate the CRC */
-	crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
-		    sizeof(struct lasat_eeprom_struct) - 4);
-	lasat_board_info.li_eeprom_info.crc32 = crc;
-
-	/* Write the EEPROM info */
-	EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
-		    sizeof(struct lasat_eeprom_struct));
-}
-
diff --git a/arch/mips/lasat/lasat_models.h b/arch/mips/lasat/lasat_models.h
deleted file mode 100644
index ae0c5d0..0000000
--- a/arch/mips/lasat/lasat_models.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Model description tables
- */
-
-typedef struct product_info_t {
-	const char     *pi_name;
-	const char     *pi_type;
-} product_info_t;
-
-typedef struct vendor_info_t {
-	const char     *vi_name;
-	const product_info_t *vi_product_info;
-} vendor_info_t;
-
-/*
- * Base models
- */
-static const char * const txt_base_models[] = {
-  "MQ 2", "MQ Pro", "SP 25", "SP 50", "SP 100", "SP 5000", "SP 7000", "SP 1000", "Unknown"
-};
-#define N_BASE_MODELS (sizeof(txt_base_models)/sizeof(char*)-1)
-
-/*
- * Eicon Networks
- */
-static const char txt_en_mq[] = "Masquerade";
-static const char txt_en_sp[] = "Safepipe";
-
-static const product_info_t product_info_eicon[] = {
-  { txt_en_mq, "II"   }, /*  0 */
-  { txt_en_mq, "Pro"  }, /*  1 */
-  { txt_en_sp, "25"   }, /*  2 */
-  { txt_en_sp, "50"   }, /*  3 */
-  { txt_en_sp, "100"  }, /*  4 */
-  { txt_en_sp, "5000" }, /*  5 */
-  { txt_en_sp, "7000" }, /*  6 */
-  { txt_en_sp, "30"   }, /*  7 */
-  { txt_en_sp, "5100" }, /*  8 */
-  { txt_en_sp, "7100" }, /*  9 */
-  { txt_en_sp, "1110" }, /* 10 */
-  { txt_en_sp, "3020" }, /* 11 */
-  { txt_en_sp, "3030" }, /* 12 */
-  { txt_en_sp, "5020" }, /* 13 */
-  { txt_en_sp, "5030" }, /* 14 */
-  { txt_en_sp, "1120" }, /* 15 */
-  { txt_en_sp, "1130" }, /* 16 */
-  { txt_en_sp, "6010" }, /* 17 */
-  { txt_en_sp, "6110" }, /* 18 */
-  { txt_en_sp, "6210" }, /* 19 */
-  { txt_en_sp, "1020" }, /* 20 */
-  { txt_en_sp, "1040" }, /* 21 */
-  { txt_en_sp, "1050" }, /* 22 */
-  { txt_en_sp, "1060" }, /* 23 */
-};
-#define N_PRIDS (sizeof(product_info_eicon)/sizeof(product_info_t))
-
-/*
- * The vendor table
- */
-static vendor_info_t const vendor_info_table[] = {
-  { "Eicon Networks",	product_info_eicon   },
-};
-#define N_VENDORS (sizeof(vendor_info_table)/sizeof(vendor_info_t))
diff --git a/arch/mips/lasat/picvue.c b/arch/mips/lasat/picvue.c
deleted file mode 100644
index 9ae82c3..0000000
--- a/arch/mips/lasat/picvue.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/bootinfo.h>
-#include <asm/lasat/lasat.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-
-#include "picvue.h"
-
-#define PVC_BUSY		0x80
-#define PVC_NLINES		2
-#define PVC_DISPMEM		80
-#define PVC_LINELEN		PVC_DISPMEM / PVC_NLINES
-
-struct pvc_defs *picvue = NULL;
-
-DECLARE_MUTEX(pvc_sem);
-
-static void pvc_reg_write(u32 val)
-{
-	*picvue->reg = val;
-}
-
-static u32 pvc_reg_read(void)
-{
-	u32 tmp = *picvue->reg;
-	return tmp;
-}
-
-static void pvc_write_byte(u32 data, u8 byte)
-{
-	data |= picvue->e;
-	pvc_reg_write(data);
-	data &= ~picvue->data_mask;
-	data |= byte << picvue->data_shift;
-	pvc_reg_write(data);
-	ndelay(220);
-	pvc_reg_write(data & ~picvue->e);
-	ndelay(220);
-}
-
-static u8 pvc_read_byte(u32 data)
-{
-	u8 byte;
-
-	data |= picvue->e;
-	pvc_reg_write(data);
-	ndelay(220);
-	byte = (pvc_reg_read() & picvue->data_mask) >> picvue->data_shift;
-	data &= ~picvue->e;
-	pvc_reg_write(data);
-	ndelay(220);
-	return byte;
-}
-
-static u8 pvc_read_data(void)
-{
-	u32 data = pvc_reg_read();
-	u8 byte;
-	data |= picvue->rw;
-	data &= ~picvue->rs;
-	pvc_reg_write(data);
-	ndelay(40);
-	byte = pvc_read_byte(data);
-	data |= picvue->rs;
-	pvc_reg_write(data);
-	return byte;
-}
-
-#define TIMEOUT 1000
-static int pvc_wait(void)
-{
-	int i = TIMEOUT;
-	int err = 0;
-
-	while ((pvc_read_data() & PVC_BUSY) && i)
-		i--;
-	if (i == 0)
-		err = -ETIME;
-
-	return err;
-}
-
-#define MODE_INST 0
-#define MODE_DATA 1
-static void pvc_write(u8 byte, int mode)
-{
-	u32 data = pvc_reg_read();
-	data &= ~picvue->rw;
-	if (mode == MODE_DATA)
-		data |= picvue->rs;
-	else
-		data &= ~picvue->rs;
-	pvc_reg_write(data);
-	ndelay(40);
-	pvc_write_byte(data, byte);
-	if (mode == MODE_DATA)
-		data &= ~picvue->rs;
-	else
-		data |= picvue->rs;
-	pvc_reg_write(data);
-	pvc_wait();
-}
-
-void pvc_write_string(const unsigned char *str, u8 addr, int line)
-{
-	int i = 0;
-
-	if (line > 0 && (PVC_NLINES > 1))
-		addr += 0x40 * line;
-	pvc_write(0x80 | addr, MODE_INST);
-
-	while (*str != 0 && i < PVC_LINELEN) {
-		pvc_write(*str++, MODE_DATA);
-		i++;
-	}
-}
-
-void pvc_write_string_centered(const unsigned char *str, int line)
-{
-	int len = strlen(str);
-	u8 addr;
-
-	if (len > PVC_VISIBLE_CHARS)
-		addr = 0;
-	else
-		addr = (PVC_VISIBLE_CHARS - strlen(str))/2;
-
-	pvc_write_string(str, addr, line);
-}
-
-void pvc_dump_string(const unsigned char *str)
-{
-	int len = strlen(str);
-
-	pvc_write_string(str, 0, 0);
-	if (len > PVC_VISIBLE_CHARS)
-		pvc_write_string(&str[PVC_VISIBLE_CHARS], 0, 1);
-}
-
-#define BM_SIZE			8
-#define MAX_PROGRAMMABLE_CHARS	8
-int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE])
-{
-	int i;
-	int addr;
-
-	if (charnum > MAX_PROGRAMMABLE_CHARS)
-		return -ENOENT;
-
-	addr = charnum * 8;
-	pvc_write(0x40 | addr, MODE_INST);
-
-	for (i=0; i<BM_SIZE; i++)
-		pvc_write(bitmap[i], MODE_DATA);
-	return 0;
-}
-
-#define FUNC_SET_CMD	0x20
-#define  EIGHT_BYTE	(1 << 4)
-#define  FOUR_BYTE	0
-#define  TWO_LINES	(1 << 3)
-#define  ONE_LINE	0
-#define  LARGE_FONT	(1 << 2)
-#define  SMALL_FONT	0
-static void pvc_funcset(u8 cmd)
-{
-	pvc_write(FUNC_SET_CMD | (cmd & (EIGHT_BYTE|TWO_LINES|LARGE_FONT)), MODE_INST);
-}
-
-#define ENTRYMODE_CMD		0x4
-#define  AUTO_INC		(1 << 1)
-#define  AUTO_DEC		0
-#define  CURSOR_FOLLOWS_DISP	(1 << 0)
-static void pvc_entrymode(u8 cmd)
-{
-	pvc_write(ENTRYMODE_CMD | (cmd & (AUTO_INC|CURSOR_FOLLOWS_DISP)), MODE_INST);
-}
-
-#define DISP_CNT_CMD	0x08
-#define  DISP_OFF	0
-#define  DISP_ON	(1 << 2)
-#define  CUR_ON		(1 << 1)
-#define  CUR_BLINK	(1 << 0)
-void pvc_dispcnt(u8 cmd)
-{
-	pvc_write(DISP_CNT_CMD | (cmd & (DISP_ON|CUR_ON|CUR_BLINK)), MODE_INST);
-}
-
-#define MOVE_CMD	0x10
-#define  DISPLAY	(1 << 3)
-#define  CURSOR		0
-#define  RIGHT		(1 << 2)
-#define  LEFT		0
-void pvc_move(u8 cmd)
-{
-	pvc_write(MOVE_CMD | (cmd & (DISPLAY|RIGHT)), MODE_INST);
-}
-
-#define CLEAR_CMD	0x1
-void pvc_clear(void)
-{
-	pvc_write(CLEAR_CMD, MODE_INST);
-}
-
-#define HOME_CMD	0x2
-void pvc_home(void)
-{
-	pvc_write(HOME_CMD, MODE_INST);
-}
-
-int pvc_init(void)
-{
-	u8 cmd = EIGHT_BYTE;
-
-	if (PVC_NLINES == 2)
-		cmd |= (SMALL_FONT|TWO_LINES);
-	else
-		cmd |= (LARGE_FONT|ONE_LINE);
-	pvc_funcset(cmd);
-	pvc_dispcnt(DISP_ON);
-	pvc_entrymode(AUTO_INC);
-
-	pvc_clear();
-	pvc_write_string_centered("Display", 0);
-	pvc_write_string_centered("Initialized", 1);
-
-	return 0;
-}
-
-module_init(pvc_init);
-MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/picvue.h b/arch/mips/lasat/picvue.h
deleted file mode 100644
index 2a96bf9..0000000
--- a/arch/mips/lasat/picvue.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <asm/semaphore.h>
-
-struct pvc_defs {
-	volatile u32 *reg;
-	u32 data_shift;
-	u32 data_mask;
-	u32 e;
-	u32 rw;
-	u32 rs;
-};
-
-extern struct pvc_defs *picvue;
-
-#define PVC_NLINES		2
-#define PVC_DISPMEM		80
-#define PVC_LINELEN		PVC_DISPMEM / PVC_NLINES
-#define PVC_VISIBLE_CHARS	16
-
-void pvc_write_string(const unsigned char *str, u8 addr, int line);
-void pvc_write_string_centered(const unsigned char *str, int line);
-void pvc_dump_string(const unsigned char *str);
-
-#define BM_SIZE			8
-#define MAX_PROGRAMMABLE_CHARS	8
-int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE]);
-
-void pvc_dispcnt(u8 cmd);
-#define  DISP_OFF	0
-#define  DISP_ON	(1 << 2)
-#define  CUR_ON		(1 << 1)
-#define  CUR_BLINK	(1 << 0)
-
-void pvc_move(u8 cmd);
-#define  DISPLAY	(1 << 3)
-#define  CURSOR		0
-#define  RIGHT		(1 << 2)
-#define  LEFT		0
-
-void pvc_clear(void);
-void pvc_home(void);
-
-extern struct semaphore pvc_sem;
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c
deleted file mode 100644
index cce7cdd..0000000
--- a/arch/mips/lasat/picvue_proc.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-
-#include <linux/proc_fs.h>
-#include <linux/interrupt.h>
-
-#include <linux/timer.h>
-
-#include "picvue.h"
-
-static char pvc_lines[PVC_NLINES][PVC_LINELEN+1];
-static int pvc_linedata[PVC_NLINES];
-static struct proc_dir_entry *pvc_display_dir;
-static char *pvc_linename[PVC_NLINES] = {"line1", "line2"};
-#define DISPLAY_DIR_NAME "display"
-static int scroll_dir = 0, scroll_interval = 0;
-
-static struct timer_list timer;
-
-static void pvc_display(unsigned long data) {
-	int i;
-
-	pvc_clear();
-	for (i=0; i<PVC_NLINES; i++)
-		pvc_write_string(pvc_lines[i], 0, i);
-}
-
-static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0);
-
-static int pvc_proc_read_line(char *page, char **start,
-                             off_t off, int count,
-                             int *eof, void *data)
-{
-        char *origpage = page;
-	int lineno = *(int *)data;
-
-	if (lineno < 0 || lineno > PVC_NLINES) {
-		printk("proc_read_line: invalid lineno %d\n", lineno);
-		return 0;
-	}
-
-	down(&pvc_sem);
-        page += sprintf(page, "%s\n", pvc_lines[lineno]);
-	up(&pvc_sem);
-
-        return page - origpage;
-}
-
-static int pvc_proc_write_line(struct file *file, const char *buffer,
-                           unsigned long count, void *data)
-{
-        int origcount = count;
-	int lineno = *(int *)data;
-
-	if (lineno < 0 || lineno > PVC_NLINES) {
-		printk("proc_write_line: invalid lineno %d\n", lineno);
-		return origcount;
-	}
-
-	if (count > PVC_LINELEN)
-		count = PVC_LINELEN;
-
-	if (buffer[count-1] == '\n')
-		count--;
-
-	down(&pvc_sem);
-	strncpy(pvc_lines[lineno], buffer, count);
-	pvc_lines[lineno][count] = '\0';
-	up(&pvc_sem);
-
-	tasklet_schedule(&pvc_display_tasklet);
-
-        return origcount;
-}
-
-static int pvc_proc_write_scroll(struct file *file, const char *buffer,
-                           unsigned long count, void *data)
-{
-        int origcount = count;
-	int cmd = simple_strtol(buffer, NULL, 10);
-
-	down(&pvc_sem);
-	if (scroll_interval != 0)
-		del_timer(&timer);
-
-	if (cmd == 0) {
-		scroll_dir = 0;
-		scroll_interval = 0;
-	} else {
-		if (cmd < 0) {
-			scroll_dir = -1;
-			scroll_interval = -cmd;
-		} else {
-			scroll_dir = 1;
-			scroll_interval = cmd;
-		}
-		add_timer(&timer);
-	}
-	up(&pvc_sem);
-
-        return origcount;
-}
-
-static int pvc_proc_read_scroll(char *page, char **start,
-                             off_t off, int count,
-                             int *eof, void *data)
-{
-        char *origpage = page;
-
-	down(&pvc_sem);
-        page += sprintf(page, "%d\n", scroll_dir * scroll_interval);
-	up(&pvc_sem);
-
-        return page - origpage;
-}
-
-
-void pvc_proc_timerfunc(unsigned long data)
-{
-	if (scroll_dir < 0)
-		pvc_move(DISPLAY|RIGHT);
-	else if (scroll_dir > 0)
-		pvc_move(DISPLAY|LEFT);
-
-	timer.expires = jiffies + scroll_interval;
-	add_timer(&timer);
-}
-
-static void pvc_proc_cleanup(void)
-{
-	int i;
-	for (i=0; i<PVC_NLINES; i++)
-		remove_proc_entry(pvc_linename[i], pvc_display_dir);
-	remove_proc_entry("scroll", pvc_display_dir);
-	remove_proc_entry(DISPLAY_DIR_NAME, NULL);
-
-	del_timer(&timer);
-}
-
-static int __init pvc_proc_init(void)
-{
-	struct proc_dir_entry *proc_entry;
-	int i;
-
-	pvc_display_dir = proc_mkdir(DISPLAY_DIR_NAME, NULL);
-	if (pvc_display_dir == NULL)
-		goto error;
-
-	for (i=0; i<PVC_NLINES; i++) {
-		strcpy(pvc_lines[i], "");
-		pvc_linedata[i] = i;
-	}
-	for (i=0; i<PVC_NLINES; i++) {
-		proc_entry = create_proc_entry(pvc_linename[i], 0644, pvc_display_dir);
-		if (proc_entry == NULL)
-			goto error;
-		proc_entry->read_proc = pvc_proc_read_line;
-		proc_entry->write_proc = pvc_proc_write_line;
-		proc_entry->data = &pvc_linedata[i];
-	}
-	proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir);
-	if (proc_entry == NULL)
-		goto error;
-	proc_entry->write_proc = pvc_proc_write_scroll;
-	proc_entry->read_proc = pvc_proc_read_scroll;
-
-	init_timer(&timer);
-	timer.function = pvc_proc_timerfunc;
-
-	return 0;
-error:
-	pvc_proc_cleanup();
-	return -ENOMEM;
-}
-
-module_init(pvc_proc_init);
-module_exit(pvc_proc_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c
deleted file mode 100644
index 812c6ac3..0000000
--- a/arch/mips/lasat/prom.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * PROM interface routines.
- */
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/ioport.h>
-#include <asm/bootinfo.h>
-#include <asm/lasat/lasat.h>
-#include <asm/cpu.h>
-
-#include "at93c.h"
-#include <asm/lasat/eeprom.h>
-#include "prom.h"
-
-#define RESET_VECTOR	0xbfc00000
-#define PROM_JUMP_TABLE_ENTRY(n) (*((u32 *)(RESET_VECTOR + 0x20) + n))
-#define PROM_DISPLAY_ADDR	PROM_JUMP_TABLE_ENTRY(0)
-#define PROM_PUTC_ADDR		PROM_JUMP_TABLE_ENTRY(1)
-#define PROM_MONITOR_ADDR	PROM_JUMP_TABLE_ENTRY(2)
-
-static void null_prom_display(const char *string, int pos, int clear)
-{
-}
-
-static void null_prom_monitor(void)
-{
-}
-
-static void null_prom_putc(char c)
-{
-}
-
-/* these are functions provided by the bootloader */
-static void (* __prom_putc)(char c) = null_prom_putc;
-
-void prom_putchar(char c)
-{
-	__prom_putc(c);
-}
-
-void (* prom_display)(const char *string, int pos, int clear) =
-		null_prom_display;
-void (* prom_monitor)(void) = null_prom_monitor;
-
-unsigned int lasat_ndelay_divider;
-
-static void setup_prom_vectors(void)
-{
-	u32 version = *(u32 *)(RESET_VECTOR + 0x90);
-
-	if (version >= 307) {
-		prom_display = (void *)PROM_DISPLAY_ADDR;
-		__prom_putc = (void *)PROM_PUTC_ADDR;
-		prom_monitor = (void *)PROM_MONITOR_ADDR;
-	}
-	printk("prom vectors set up\n");
-}
-
-static struct at93c_defs at93c_defs[N_MACHTYPES] = {
-	{(void *)AT93C_REG_100, (void *)AT93C_RDATA_REG_100, AT93C_RDATA_SHIFT_100,
-	AT93C_WDATA_SHIFT_100, AT93C_CS_M_100, AT93C_CLK_M_100},
-	{(void *)AT93C_REG_200, (void *)AT93C_RDATA_REG_200, AT93C_RDATA_SHIFT_200,
-	AT93C_WDATA_SHIFT_200, AT93C_CS_M_200, AT93C_CLK_M_200},
-};
-
-void __init prom_init(void)
-{
-	int argc = fw_arg0;
-	char **argv = (char **) fw_arg1;
-
-	setup_prom_vectors();
-
-	if (current_cpu_data.cputype == CPU_R5000) {
-	        printk("LASAT 200 board\n");
-		mips_machtype = MACH_LASAT_200;
-                lasat_ndelay_divider = LASAT_200_DIVIDER;
-        } else {
-	        printk("LASAT 100 board\n");
-		mips_machtype = MACH_LASAT_100;
-                lasat_ndelay_divider = LASAT_100_DIVIDER;
-        }
-
-	at93c = &at93c_defs[mips_machtype];
-
-	lasat_init_board_info();		/* Read info from EEPROM */
-
-	mips_machgroup = MACH_GROUP_LASAT;
-
-	/* Get the command line */
-	if (argc > 0) {
-		strncpy(arcs_cmdline, argv[0], CL_SIZE-1);
-		arcs_cmdline[CL_SIZE-1] = '\0';
-	}
-
-	/* Set the I/O base address */
-	set_io_port_base(KSEG1);
-
-	/* Set memory regions */
-	ioport_resource.start = 0;
-	ioport_resource.end = 0xffffffff;	/* Wrong, fixme.  */
-
-	add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM);
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-const char *get_system_type(void)
-{
-	return lasat_board_info.li_bmstr;
-}
diff --git a/arch/mips/lasat/prom.h b/arch/mips/lasat/prom.h
deleted file mode 100644
index 019d45f..0000000
--- a/arch/mips/lasat/prom.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef PROM_H
-#define PROM_H
-extern void (* prom_display)(const char *string, int pos, int clear);
-extern void (* prom_monitor)(void);
-#endif
diff --git a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c
deleted file mode 100644
index 9e22acf..0000000
--- a/arch/mips/lasat/reset.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Reset the LASAT board.
- */
-#include <linux/kernel.h>
-#include <linux/pm.h>
-
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <asm/lasat/lasat.h>
-
-#include "picvue.h"
-#include "prom.h"
-
-static void lasat_machine_restart(char *command);
-static void lasat_machine_halt(void);
-
-/* Used to set machine to boot in service mode via /proc interface */
-int lasat_boot_to_service = 0;
-
-static void lasat_machine_restart(char *command)
-{
-	local_irq_disable();
-
-	if (lasat_boot_to_service) {
-		printk("machine_restart: Rebooting to service mode\n");
-		*(volatile unsigned int *)0xa0000024 = 0xdeadbeef;
-		*(volatile unsigned int *)0xa00000fc = 0xfedeabba;
-	}
-	*lasat_misc->reset_reg = 0xbedead;
-	for (;;) ;
-}
-
-#define MESSAGE "System halted"
-static void lasat_machine_halt(void)
-{
-	local_irq_disable();
-
-	/* Disable interrupts and loop forever */
-	printk(KERN_NOTICE MESSAGE "\n");
-#ifdef CONFIG_PICVUE
-	pvc_clear();
-	pvc_write_string(MESSAGE, 0, 0);
-#endif
-	prom_monitor();
-	for (;;) ;
-}
-
-void lasat_reboot_setup(void)
-{
-	_machine_restart = lasat_machine_restart;
-	_machine_halt = lasat_machine_halt;
-	pm_power_off = lasat_machine_halt;
-}
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
deleted file mode 100644
index 488007f..0000000
--- a/arch/mips/lasat/setup.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999 MIPS Technologies, Inc.  All rights reserved.
- *
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * Brian Murphy <brian@murphy.dk>
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Lasat specific setup.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-
-#include <asm/time.h>
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/lasat/lasat.h>
-#include <asm/lasat/serial.h>
-
-#ifdef CONFIG_PICVUE
-#include <linux/notifier.h>
-#endif
-
-#include "ds1603.h"
-#include <asm/lasat/ds1603.h>
-#include <asm/lasat/picvue.h>
-#include <asm/lasat/eeprom.h>
-
-#include "prom.h"
-
-int lasat_command_line = 0;
-void lasatint_init(void);
-
-extern void lasat_reboot_setup(void);
-extern void pcisetup(void);
-extern void edhac_init(void *, void *, void *);
-extern void addrflt_init(void);
-
-struct lasat_misc lasat_misc_info[N_MACHTYPES] = {
-	{(void *)KSEG1ADDR(0x1c840000), (void *)KSEG1ADDR(0x1c800000), 2},
-	{(void *)KSEG1ADDR(0x11080000), (void *)KSEG1ADDR(0x11000000), 6}
-};
-
-struct lasat_misc *lasat_misc = NULL;
-
-#ifdef CONFIG_DS1603
-static struct ds_defs ds_defs[N_MACHTYPES] = {
-	{ (void *)DS1603_REG_100, (void *)DS1603_REG_100,
-		DS1603_RST_100, DS1603_CLK_100, DS1603_DATA_100,
-		DS1603_DATA_SHIFT_100, 0, 0 },
-	{ (void *)DS1603_REG_200, (void *)DS1603_DATA_REG_200,
-		DS1603_RST_200, DS1603_CLK_200, DS1603_DATA_200,
-		DS1603_DATA_READ_SHIFT_200, 1, 2000 }
-};
-#endif
-
-#ifdef CONFIG_PICVUE
-#include "picvue.h"
-static struct pvc_defs pvc_defs[N_MACHTYPES] = {
-	{ (void *)PVC_REG_100, PVC_DATA_SHIFT_100, PVC_DATA_M_100,
-		PVC_E_100, PVC_RW_100, PVC_RS_100 },
-	{ (void *)PVC_REG_200, PVC_DATA_SHIFT_200, PVC_DATA_M_200,
-		PVC_E_200, PVC_RW_200, PVC_RS_200 }
-};
-#endif
-
-static int lasat_panic_display(struct notifier_block *this,
-			     unsigned long event, void *ptr)
-{
-#ifdef CONFIG_PICVUE
-	unsigned char *string = ptr;
-	if (string == NULL)
-		string = "Kernel Panic";
-	pvc_dump_string(string);
-#endif
-	return NOTIFY_DONE;
-}
-
-static int lasat_panic_prom_monitor(struct notifier_block *this,
-			     unsigned long event, void *ptr)
-{
-	prom_monitor();
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block lasat_panic_block[] =
-{
-	{ lasat_panic_display, NULL, INT_MAX },
-	{ lasat_panic_prom_monitor, NULL, INT_MIN }
-};
-
-static void lasat_time_init(void)
-{
-	mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
-	change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5);
-}
-
-#define DYNAMIC_SERIAL_INIT
-#ifdef DYNAMIC_SERIAL_INIT
-void __init serial_init(void)
-{
-#ifdef CONFIG_SERIAL_8250
-	struct uart_port s;
-
-	memset(&s, 0, sizeof(s));
-
-	s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-	s.iotype = UPIO_MEM;
-
-	if (mips_machtype == MACH_LASAT_100) {
-		s.uartclk = LASAT_BASE_BAUD_100 * 16;
-		s.irq = LASATINT_UART_100;
-		s.regshift = LASAT_UART_REGS_SHIFT_100;
-		s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_100);
-	} else {
-		s.uartclk = LASAT_BASE_BAUD_200 * 16;
-		s.irq = LASATINT_UART_200;
-		s.regshift = LASAT_UART_REGS_SHIFT_200;
-		s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_200);
-	}
-
-	if (early_serial_setup(&s) != 0)
-		printk(KERN_ERR "Serial setup failed!\n");
-#endif
-}
-#endif
-
-void __init plat_mem_setup(void)
-{
-	int i;
-	lasat_misc  = &lasat_misc_info[mips_machtype];
-#ifdef CONFIG_PICVUE
-	picvue = &pvc_defs[mips_machtype];
-#endif
-
-	/* Set up panic notifier */
-	for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++)
-		atomic_notifier_chain_register(&panic_notifier_list,
-				&lasat_panic_block[i]);
-
-	lasat_reboot_setup();
-
-	board_time_init = lasat_time_init;
-
-#ifdef CONFIG_DS1603
-	ds1603 = &ds_defs[mips_machtype];
-	rtc_mips_get_time = ds1603_read;
-	rtc_mips_set_time = ds1603_set;
-#endif
-
-#ifdef DYNAMIC_SERIAL_INIT
-	serial_init();
-#endif
-	/* Switch from prom exception handler to normal mode */
-	change_c0_status(ST0_BEV,0);
-
-	pr_info("Lasat specific initialization complete\n");
-}
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
deleted file mode 100644
index 699ab18..0000000
--- a/arch/mips/lasat/sysctl.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Routines specific to the LASAT boards
- */
-#include <linux/types.h>
-#include <asm/lasat/lasat.h>
-
-#include <linux/module.h>
-#include <linux/sysctl.h>
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/net.h>
-#include <linux/inet.h>
-#include <linux/mutex.h>
-#include <asm/uaccess.h>
-
-#include "sysctl.h"
-#include "ds1603.h"
-
-static DEFINE_MUTEX(lasat_info_mutex);
-
-/* Strategy function to write EEPROM after changing string entry */
-int sysctl_lasatstring(ctl_table *table, int *name, int nlen,
-		void *oldval, size_t *oldlenp,
-		void *newval, size_t newlen)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	r = sysctl_string(table, name,
-			  nlen, oldval, oldlenp, newval, newlen);
-	if (r < 0) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	if (newval && newlen) {
-		lasat_write_eeprom_info();
-	}
-	mutex_unlock(&lasat_info_mutex);
-	return 1;
-}
-
-
-/* And the same for proc */
-int proc_dolasatstring(ctl_table *table, int write, struct file *filp,
-		       void *buffer, size_t *lenp, loff_t *ppos)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	r = proc_dostring(table, write, filp, buffer, lenp, ppos);
-	if ( (!write) || r) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	lasat_write_eeprom_info();
-	mutex_unlock(&lasat_info_mutex);
-	return 0;
-}
-
-/* proc function to write EEPROM after changing int entry */
-int proc_dolasatint(ctl_table *table, int write, struct file *filp,
-		       void *buffer, size_t *lenp, loff_t *ppos)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
-	if ( (!write) || r) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	lasat_write_eeprom_info();
-	mutex_unlock(&lasat_info_mutex);
-	return 0;
-}
-
-static int rtctmp;
-
-#ifdef CONFIG_DS1603
-/* proc function to read/write RealTime Clock */
-int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
-		       void *buffer, size_t *lenp, loff_t *ppos)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	if (!write) {
-		rtctmp = ds1603_read();
-		/* check for time < 0 and set to 0 */
-		if (rtctmp < 0)
-			rtctmp = 0;
-	}
-	r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
-	if ( (!write) || r) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	ds1603_set(rtctmp);
-	mutex_unlock(&lasat_info_mutex);
-	return 0;
-}
-#endif
-
-/* Sysctl for setting the IP addresses */
-int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
-		    void *oldval, size_t *oldlenp,
-		    void *newval, size_t newlen)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
-	if (r < 0) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	if (newval && newlen) {
-		lasat_write_eeprom_info();
-	}
-	mutex_unlock(&lasat_info_mutex);
-	return 1;
-}
-
-#ifdef CONFIG_DS1603
-/* Same for RTC */
-int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
-		    void *oldval, size_t *oldlenp,
-		    void *newval, size_t newlen)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	rtctmp = ds1603_read();
-	if (rtctmp < 0)
-		rtctmp = 0;
-	r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
-	if (r < 0) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	if (newval && newlen) {
-		ds1603_set(rtctmp);
-	}
-	mutex_unlock(&lasat_info_mutex);
-	return 1;
-}
-#endif
-
-#ifdef CONFIG_INET
-static char lasat_bcastaddr[16];
-
-void update_bcastaddr(void)
-{
-	unsigned int ip;
-
-	ip = (lasat_board_info.li_eeprom_info.ipaddr &
-		lasat_board_info.li_eeprom_info.netmask) |
-		~lasat_board_info.li_eeprom_info.netmask;
-
-	sprintf(lasat_bcastaddr, "%d.%d.%d.%d",
-			(ip      ) & 0xff,
-			(ip >>  8) & 0xff,
-			(ip >> 16) & 0xff,
-			(ip >> 24) & 0xff);
-}
-
-static char proc_lasat_ipbuf[32];
-/* Parsing of IP address */
-int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
-		       void *buffer, size_t *lenp, loff_t *ppos)
-{
-	int len;
-        unsigned int ip;
-	char *p, c;
-
-	if (!table->data || !table->maxlen || !*lenp ||
-	    (*ppos && !write)) {
-		*lenp = 0;
-		return 0;
-	}
-
-	mutex_lock(&lasat_info_mutex);
-	if (write) {
-		len = 0;
-		p = buffer;
-		while (len < *lenp) {
-			if(get_user(c, p++)) {
-				mutex_unlock(&lasat_info_mutex);
-				return -EFAULT;
-			}
-			if (c == 0 || c == '\n')
-				break;
-			len++;
-		}
-		if (len >= sizeof(proc_lasat_ipbuf)-1)
-			len = sizeof(proc_lasat_ipbuf) - 1;
-		if (copy_from_user(proc_lasat_ipbuf, buffer, len))
-		{
-			mutex_unlock(&lasat_info_mutex);
-			return -EFAULT;
-		}
-		proc_lasat_ipbuf[len] = 0;
-		*ppos += *lenp;
-		/* Now see if we can convert it to a valid IP */
-		ip = in_aton(proc_lasat_ipbuf);
-		*(unsigned int *)(table->data) = ip;
-		lasat_write_eeprom_info();
-	} else {
-		ip = *(unsigned int *)(table->data);
-		sprintf(proc_lasat_ipbuf, "%d.%d.%d.%d",
-			(ip      ) & 0xff,
-			(ip >>  8) & 0xff,
-			(ip >> 16) & 0xff,
-			(ip >> 24) & 0xff);
-		len = strlen(proc_lasat_ipbuf);
-		if (len > *lenp)
-			len = *lenp;
-		if (len)
-			if(copy_to_user(buffer, proc_lasat_ipbuf, len)) {
-				mutex_unlock(&lasat_info_mutex);
-				return -EFAULT;
-			}
-		if (len < *lenp) {
-			if(put_user('\n', ((char *) buffer) + len)) {
-				mutex_unlock(&lasat_info_mutex);
-				return -EFAULT;
-			}
-			len++;
-		}
-		*lenp = len;
-		*ppos += len;
-	}
-	update_bcastaddr();
-	mutex_unlock(&lasat_info_mutex);
-	return 0;
-}
-#endif /* defined(CONFIG_INET) */
-
-static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
-				     void *oldval, size_t *oldlenp,
-				     void *newval, size_t newlen)
-{
-	int r;
-
-	mutex_lock(&lasat_info_mutex);
-	r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
-	if (r < 0) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-
-	if (newval && newlen)
-	{
-		if (name && *name == LASAT_PRID)
-			lasat_board_info.li_eeprom_info.prid = *(int*)newval;
-
-		lasat_write_eeprom_info();
-		lasat_init_board_info();
-	}
-	mutex_unlock(&lasat_info_mutex);
-
-	return 0;
-}
-
-int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
-		       void *buffer, size_t *lenp, loff_t *ppos)
-{
-	int r;
-	mutex_lock(&lasat_info_mutex);
-	r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
-	if ( (!write) || r) {
-		mutex_unlock(&lasat_info_mutex);
-		return r;
-	}
-	if (filp && filp->f_path.dentry)
-	{
-		if (!strcmp(filp->f_path.dentry->d_name.name, "prid"))
-			lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid;
-		if (!strcmp(filp->f_path.dentry->d_name.name, "debugaccess"))
-			lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess;
-	}
-	lasat_write_eeprom_info();
-	mutex_unlock(&lasat_info_mutex);
-	return 0;
-}
-
-extern int lasat_boot_to_service;
-
-#ifdef CONFIG_SYSCTL
-
-static ctl_table lasat_table[] = {
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "cpu-hz",
-		.data		= &lasat_board_info.li_cpu_hz,
-		.maxlen		= sizeof(int),
-		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "bus-hz",
-		.data		= &lasat_board_info.li_bus_hz,
-		.maxlen		= sizeof(int),
-		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "bmid",
-		.data		= &lasat_board_info.li_bmid,
-		.maxlen		= sizeof(int),
-		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "prid",
-		.data		= &lasat_board_info.li_prid,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_lasat_eeprom_value,
-		.strategy	= &sysctl_lasat_eeprom_value
-	},
-#ifdef CONFIG_INET
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "ipaddr",
-		.data		= &lasat_board_info.li_eeprom_info.ipaddr,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_lasat_ip,
-		.strategy	= &sysctl_lasat_intvec
-	},
-	{
-		.ctl_name	= LASAT_NETMASK,
-		.procname	= "netmask",
-		.data		= &lasat_board_info.li_eeprom_info.netmask,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_lasat_ip,
-		.strategy	= &sysctl_lasat_intvec
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "bcastaddr",
-		.data		= &lasat_bcastaddr,
-		.maxlen		= sizeof(lasat_bcastaddr),
-		.mode		= 0600,
-		.proc_handler	= &proc_dostring,
-		.strategy	= &sysctl_string
-	},
-#endif
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "passwd_hash",
-		.data		= &lasat_board_info.li_eeprom_info.passwd_hash,
-		.maxlen		= sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
-		.mode		= 0600,
-		.proc_handler	= &proc_dolasatstring,
-		.strategy	= &sysctl_lasatstring
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "boot-service",
-		.data		= &lasat_boot_to_service,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-		.strategy	= &sysctl_intvec
-	},
-#ifdef CONFIG_DS1603
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "rtc",
-		.data		= &rtctmp,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dolasatrtc,
-		.strategy	= &sysctl_lasat_rtc
-	},
-#endif
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "namestr",
-		.data		= &lasat_board_info.li_namestr,
-		.maxlen		= sizeof(lasat_board_info.li_namestr),
-		.mode		= 0444,
-		.proc_handler	=  &proc_dostring,
-		.strategy	= &sysctl_string
-	},
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "typestr",
-		.data		= &lasat_board_info.li_typestr,
-		.maxlen		= sizeof(lasat_board_info.li_typestr),
-		.mode		= 0444,
-		.proc_handler	= &proc_dostring,
-		.strategy	= &sysctl_string
-	},
-	{}
-};
-
-static ctl_table lasat_root_table[] = {
-	{
-		.ctl_name	= CTL_UNNUMBERED,
-		.procname	= "lasat",
-		.mode		=  0555,
-		.child		= lasat_table
-	},
-	{}
-};
-
-static int __init lasat_register_sysctl(void)
-{
-	struct ctl_table_header *lasat_table_header;
-
-	lasat_table_header =
-		register_sysctl_table(lasat_root_table);
-
-	return 0;
-}
-
-__initcall(lasat_register_sysctl);
-#endif /* CONFIG_SYSCTL */
diff --git a/arch/mips/lasat/sysctl.h b/arch/mips/lasat/sysctl.h
deleted file mode 100644
index 4d139d2..0000000
--- a/arch/mips/lasat/sysctl.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * LASAT sysctl values
- */
-
-#ifndef _LASAT_SYSCTL_H
-#define _LASAT_SYSCTL_H
-
-/* /proc/sys/lasat */
-enum {
-	LASAT_CPU_HZ=1,
-	LASAT_BUS_HZ,
-	LASAT_MODEL,
-	LASAT_PRID,
-	LASAT_IPADDR,
-	LASAT_NETMASK,
-	LASAT_BCAST,
-	LASAT_PASSWORD,
-	LASAT_SBOOT,
-	LASAT_RTC,
-	LASAT_NAMESTR,
-	LASAT_TYPESTR,
-};
-
-#endif /* _LASAT_SYSCTL_H */
diff --git a/arch/mips/lemote/lm2e/Makefile b/arch/mips/lemote/lm2e/Makefile
new file mode 100644
index 0000000..fb1b48c
--- /dev/null
+++ b/arch/mips/lemote/lm2e/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Lemote Fulong mini-PC board.
+#
+
+obj-y += setup.o prom.o reset.o irq.o pci.o bonito-irq.o dbg_io.o mem.o
+EXTRA_AFLAGS := $(CFLAGS)
+
diff --git a/arch/mips/lemote/lm2e/bonito-irq.c b/arch/mips/lemote/lm2e/bonito-irq.c
new file mode 100644
index 0000000..8fc3bce
--- /dev/null
+++ b/arch/mips/lemote/lm2e/bonito-irq.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/mips-boards/bonito64.h>
+
+
+static inline void bonito_irq_enable(unsigned int irq)
+{
+	BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE));
+	mmiowb();
+}
+
+static inline void bonito_irq_disable(unsigned int irq)
+{
+	BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE));
+	mmiowb();
+}
+
+static struct irq_chip bonito_irq_type = {
+	.name	= "bonito_irq",
+	.ack	= bonito_irq_disable,
+	.mask	= bonito_irq_disable,
+	.mask_ack = bonito_irq_disable,
+	.unmask	= bonito_irq_enable,
+};
+
+static struct irqaction dma_timeout_irqaction = {
+	.handler	= no_action,
+	.name		= "dma_timeout",
+};
+
+void bonito_irq_init(void)
+{
+	u32 i;
+
+	for (i = BONITO_IRQ_BASE; i < BONITO_IRQ_BASE + 32; i++) {
+		set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq);
+	}
+
+	setup_irq(BONITO_IRQ_BASE + 10, &dma_timeout_irqaction);
+}
diff --git a/arch/mips/lemote/lm2e/dbg_io.c b/arch/mips/lemote/lm2e/dbg_io.c
new file mode 100644
index 0000000..6c95da3
--- /dev/null
+++ b/arch/mips/lemote/lm2e/dbg_io.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include <asm/serial.h>
+
+#define         UART16550_BAUD_2400             2400
+#define         UART16550_BAUD_4800             4800
+#define         UART16550_BAUD_9600             9600
+#define         UART16550_BAUD_19200            19200
+#define         UART16550_BAUD_38400            38400
+#define         UART16550_BAUD_57600            57600
+#define         UART16550_BAUD_115200           115200
+
+#define         UART16550_PARITY_NONE           0
+#define         UART16550_PARITY_ODD            0x08
+#define         UART16550_PARITY_EVEN           0x18
+#define         UART16550_PARITY_MARK           0x28
+#define         UART16550_PARITY_SPACE          0x38
+
+#define         UART16550_DATA_5BIT             0x0
+#define         UART16550_DATA_6BIT             0x1
+#define         UART16550_DATA_7BIT             0x2
+#define         UART16550_DATA_8BIT             0x3
+
+#define         UART16550_STOP_1BIT             0x0
+#define         UART16550_STOP_2BIT             0x4
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+#ifdef CONFIG_64BIT
+#define         BASE                    (0xffffffffbfd003f8)
+#else
+#define         BASE                    (0xbfd003f8)
+#endif
+
+#define         MAX_BAUD                BASE_BAUD
+/* === END OF CONFIG === */
+
+#define         REG_OFFSET              1
+
+/* register offset */
+#define         OFS_RCV_BUFFER          0
+#define         OFS_TRANS_HOLD          0
+#define         OFS_SEND_BUFFER         0
+#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
+#define         OFS_INTR_ID             (2*REG_OFFSET)
+#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
+#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
+#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
+#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
+#define         OFS_LINE_STATUS         (5*REG_OFFSET)
+#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
+#define         OFS_RS232_INPUT         (6*REG_OFFSET)
+#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
+
+#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
+#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
+
+/* memory-mapped read/write of the port */
+#define         UART16550_READ(y)	readb((char *)BASE + (y))
+#define         UART16550_WRITE(y, z)	writeb(z, (char *)BASE + (y))
+
+void debugInit(u32 baud, u8 data, u8 parity, u8 stop)
+{
+	u32 divisor;
+
+	/* disable interrupts */
+	UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+	/* set up buad rate */
+	/* set DIAB bit */
+	UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+	/* set divisor */
+	divisor = MAX_BAUD / baud;
+	UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+	UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+	/* clear DIAB bit */
+	UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+
+	/* set data format */
+	UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized;
+
+u8 getDebugChar(void)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(UART16550_BAUD_115200,
+			  UART16550_DATA_8BIT,
+			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+	}
+
+	while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0) ;
+	return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+int putDebugChar(u8 byte)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		/*
+		   debugInit(UART16550_BAUD_115200,
+		   UART16550_DATA_8BIT,
+		   UART16550_PARITY_NONE, UART16550_STOP_1BIT); */
+	}
+
+	while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0) ;
+	UART16550_WRITE(OFS_SEND_BUFFER, byte);
+	return 1;
+}
diff --git a/arch/mips/lemote/lm2e/irq.c b/arch/mips/lemote/lm2e/irq.c
new file mode 100644
index 0000000..05693bc
--- /dev/null
+++ b/arch/mips/lemote/lm2e/irq.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+#include <asm/mips-boards/bonito64.h>
+
+
+/*
+ * the first level int-handler will jump here if it is a bonito irq
+ */
+static void bonito_irqdispatch(void)
+{
+	u32 int_status;
+	int i;
+
+	/* workaround the IO dma problem: let cpu looping to allow DMA finish */
+	int_status = BONITO_INTISR;
+	if (int_status & (1 << 10)) {
+		while (int_status & (1 << 10)) {
+			udelay(1);
+			int_status = BONITO_INTISR;
+		}
+	}
+
+	/* Get pending sources, masked by current enables */
+	int_status = BONITO_INTISR & BONITO_INTEN;
+
+	if (int_status != 0) {
+		i = __ffs(int_status);
+		int_status &= ~(1 << i);
+		do_IRQ(BONITO_IRQ_BASE + i);
+	}
+}
+
+static void i8259_irqdispatch(void)
+{
+	int irq;
+
+	irq = i8259_irq();
+	if (irq >= 0) {
+		do_IRQ(irq);
+	} else {
+		spurious_interrupt();
+	}
+
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+	if (pending & CAUSEF_IP7) {
+		do_IRQ(MIPS_CPU_IRQ_BASE + 7);
+	} else if (pending & CAUSEF_IP5) {
+		i8259_irqdispatch();
+	} else if (pending & CAUSEF_IP2) {
+		bonito_irqdispatch();
+	} else {
+		spurious_interrupt();
+	}
+}
+
+static struct irqaction cascade_irqaction = {
+	.handler = no_action,
+	.mask = CPU_MASK_NONE,
+	.name = "cascade",
+};
+
+void __init arch_init_irq(void)
+{
+	extern void bonito_irq_init(void);
+
+	/*
+	 * Clear all of the interrupts while we change the able around a bit.
+	 * int-handler is not on bootstrap
+	 */
+	clear_c0_status(ST0_IM | ST0_BEV);
+	local_irq_disable();
+
+	/* most bonito irq should be level triggered */
+	BONITO_INTEDGE = BONITO_ICU_SYSTEMERR | BONITO_ICU_MASTERERR |
+		BONITO_ICU_RETRYERR | BONITO_ICU_MBOXES;
+	BONITO_INTSTEER = 0;
+
+	/*
+	 * Mask out all interrupt by writing "1" to all bit position in
+	 * the interrupt reset reg.
+	 */
+	BONITO_INTENCLR = ~0;
+
+	/* init all controller
+	 *   0-15         ------> i8259 interrupt
+	 *   16-23        ------> mips cpu interrupt
+	 *   32-63        ------> bonito irq
+	 */
+
+	/* Sets the first-level interrupt dispatcher. */
+	mips_cpu_irq_init();
+	init_i8259_irqs();
+	bonito_irq_init();
+
+	/*
+	printk("GPIODATA=%x, GPIOIE=%x\n", BONITO_GPIODATA, BONITO_GPIOIE);
+	printk("INTEN=%x, INTSET=%x, INTCLR=%x, INTISR=%x\n",
+			BONITO_INTEN, BONITO_INTENSET,
+			BONITO_INTENCLR, BONITO_INTISR);
+	*/
+
+	/* bonito irq at IP2 */
+	setup_irq(MIPS_CPU_IRQ_BASE + 2, &cascade_irqaction);
+	/* 8259 irq at IP5 */
+	setup_irq(MIPS_CPU_IRQ_BASE + 5, &cascade_irqaction);
+
+}
diff --git a/arch/mips/lemote/lm2e/mem.c b/arch/mips/lemote/lm2e/mem.c
new file mode 100644
index 0000000..16cd215
--- /dev/null
+++ b/arch/mips/lemote/lm2e/mem.c
@@ -0,0 +1,23 @@
+/*
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+
+/* override of arch/mips/mm/cache.c: __uncached_access */
+int __uncached_access(struct file *file, unsigned long addr)
+{
+	if (file->f_flags & O_SYNC)
+		return 1;
+
+	/*
+	 * On the Lemote Loongson 2e system, the peripheral registers
+	 * reside between 0x1000:0000 and 0x2000:0000.
+	 */
+	return addr >= __pa(high_memory) ||
+		((addr >= 0x10000000) && (addr < 0x20000000));
+}
diff --git a/arch/mips/lemote/lm2e/pci.c b/arch/mips/lemote/lm2e/pci.c
new file mode 100644
index 0000000..1ade1ce
--- /dev/null
+++ b/arch/mips/lemote/lm2e/pci.c
@@ -0,0 +1,93 @@
+/*
+ * pci.c
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/mips-boards/bonito64.h>
+
+extern struct pci_ops bonito64_pci_ops;
+
+static struct resource loongson2e_pci_mem_resource = {
+	.name   = "LOONGSON2E PCI MEM",
+	.start  = 0x14000000UL,
+	.end    = 0x1fffffffUL,
+	.flags  = IORESOURCE_MEM,
+};
+
+static struct resource loongson2e_pci_io_resource = {
+	.name   = "LOONGSON2E PCI IO MEM",
+	.start  = 0x00004000UL,
+	.end    = IO_SPACE_LIMIT,
+	.flags  = IORESOURCE_IO,
+};
+
+static struct pci_controller  loongson2e_pci_controller = {
+	.pci_ops        = &bonito64_pci_ops,
+	.io_resource    = &loongson2e_pci_io_resource,
+	.mem_resource   = &loongson2e_pci_mem_resource,
+	.mem_offset     = 0x00000000UL,
+	.io_offset      = 0x00000000UL,
+};
+
+static void __init ict_pcimap(void)
+{
+	/*
+	 * local to PCI mapping: [256M,512M] -> [256M,512M]; differ from PMON
+	 *
+	 * CPU address space [256M,448M] is window for accessing pci space
+	 * we set pcimap_lo[0,1,2] to map it to pci space [256M,448M]
+	 * pcimap: bit18,pcimap_2; bit[17-12],lo2;bit[11-6],lo1;bit[5-0],lo0
+	 */
+	/* 1,00 0110 ,0001 01,00 0000 */
+	BONITO_PCIMAP = 0x46140;
+
+	/* 1, 00 0010, 0000,01, 00 0000 */
+	/* BONITO_PCIMAP = 0x42040; */
+
+	/*
+	 * PCI to local mapping: [2G,2G+256M] -> [0,256M]
+	 */
+	BONITO_PCIBASE0 = 0x80000000;
+	BONITO_PCIBASE1 = 0x00800000;
+	BONITO_PCIBASE2 = 0x90000000;
+
+}
+
+static int __init pcibios_init(void)
+{
+	extern int pci_probe_only;
+	pci_probe_only = 0;
+
+	ict_pcimap();
+	register_pci_controller(&loongson2e_pci_controller);
+
+	return 0;
+}
+
+arch_initcall(pcibios_init);
diff --git a/arch/mips/lemote/lm2e/prom.c b/arch/mips/lemote/lm2e/prom.c
new file mode 100644
index 0000000..67312d7
--- /dev/null
+++ b/arch/mips/lemote/lm2e/prom.c
@@ -0,0 +1,104 @@
+/*
+ * Based on Ocelot Linux port, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright 2003 ICT CAS
+ * Author: Michael Guo <guoyi@ict.ac.cn>
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+extern unsigned long bus_clock;
+extern unsigned long cpu_clock;
+extern unsigned int memsize, highmemsize;
+extern int putDebugChar(unsigned char byte);
+
+static int argc;
+/* pmon passes arguments in 32bit pointers */
+static int *arg;
+static int *env;
+
+const char *get_system_type(void)
+{
+	return "lemote-fulong";
+}
+
+void __init prom_init_cmdline(void)
+{
+	int i;
+	long l;
+
+	/* arg[0] is "g", the rest is boot parameters */
+	arcs_cmdline[0] = '\0';
+	for (i = 1; i < argc; i++) {
+		l = (long)arg[i];
+		if (strlen(arcs_cmdline) + strlen(((char *)l) + 1)
+		    >= sizeof(arcs_cmdline))
+			break;
+		strcat(arcs_cmdline, ((char *)l));
+		strcat(arcs_cmdline, " ");
+	}
+}
+
+void __init prom_init(void)
+{
+	long l;
+	argc = fw_arg0;
+	arg = (int *)fw_arg1;
+	env = (int *)fw_arg2;
+
+	mips_machgroup = MACH_GROUP_LEMOTE;
+	mips_machtype = MACH_LEMOTE_FULONG;
+
+	prom_init_cmdline();
+
+	if ((strstr(arcs_cmdline, "console=")) == NULL)
+		strcat(arcs_cmdline, " console=ttyS0,115200");
+	if ((strstr(arcs_cmdline, "root=")) == NULL)
+		strcat(arcs_cmdline, " root=/dev/hda1");
+
+#define parse_even_earlier(res, option, p)				\
+do {									\
+	if (strncmp(option, (char *)p, strlen(option)) == 0)		\
+		res = simple_strtol((char *)p + strlen(option"="),	\
+				    NULL, 10);				\
+} while (0)
+
+	l = (long)*env;
+	while (l != 0) {
+		parse_even_earlier(bus_clock, "busclock", l);
+		parse_even_earlier(cpu_clock, "cpuclock", l);
+		parse_even_earlier(memsize, "memsize", l);
+		parse_even_earlier(highmemsize, "highmemsize", l);
+		env++;
+		l = (long)*env;
+	}
+	if (memsize == 0)
+		memsize = 256;
+
+	pr_info("busclock=%ld, cpuclock=%ld,memsize=%d,highmemsize=%d\n",
+	       bus_clock, cpu_clock, memsize, highmemsize);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void prom_putchar(char c)
+{
+	putDebugChar(c);
+}
diff --git a/arch/mips/lemote/lm2e/reset.c b/arch/mips/lemote/lm2e/reset.c
new file mode 100644
index 0000000..099387a
--- /dev/null
+++ b/arch/mips/lemote/lm2e/reset.c
@@ -0,0 +1,41 @@
+/*
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ */
+#include <linux/pm.h>
+
+#include <asm/reboot.h>
+
+static void loongson2e_restart(char *command)
+{
+#ifdef CONFIG_32BIT
+	*(unsigned long *)0xbfe00104 &= ~(1 << 2);
+	*(unsigned long *)0xbfe00104 |= (1 << 2);
+#else
+	*(unsigned long *)0xffffffffbfe00104 &= ~(1 << 2);
+	*(unsigned long *)0xffffffffbfe00104 |= (1 << 2);
+#endif
+	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+static void loongson2e_halt(void)
+{
+	while (1) ;
+}
+
+static void loongson2e_power_off(void)
+{
+	loongson2e_halt();
+}
+
+void mips_reboot_setup(void)
+{
+	_machine_restart = loongson2e_restart;
+	_machine_halt = loongson2e_halt;
+	pm_power_off = loongson2e_power_off;
+}
diff --git a/arch/mips/lemote/lm2e/setup.c b/arch/mips/lemote/lm2e/setup.c
new file mode 100644
index 0000000..0e4d1fa
--- /dev/null
+++ b/arch/mips/lemote/lm2e/setup.c
@@ -0,0 +1,134 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * setup.c - board dependent boot routines
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+
+#include <asm/bootinfo.h>
+#include <asm/mc146818-time.h>
+#include <asm/time.h>
+#include <asm/wbflush.h>
+
+#ifdef CONFIG_VT
+#include <linux/console.h>
+#include <linux/screen_info.h>
+#endif
+
+extern void mips_reboot_setup(void);
+
+#ifdef CONFIG_64BIT
+#define PTR_PAD(p) ((0xffffffff00000000)|((unsigned long long)(p)))
+#else
+#define PTR_PAD(p) (p)
+#endif
+
+unsigned long cpu_clock;
+unsigned long bus_clock;
+unsigned int memsize;
+unsigned int highmemsize = 0;
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+	setup_irq(MIPS_CPU_IRQ_BASE + 7, irq);
+}
+
+static void __init loongson2e_time_init(void)
+{
+	/* setup mips r4k timer */
+	mips_hpt_frequency = cpu_clock / 2;
+}
+
+static unsigned long __init mips_rtc_get_time(void)
+{
+	return mc146818_get_cmos_time();
+}
+
+void (*__wbflush)(void);
+EXPORT_SYMBOL(__wbflush);
+
+static void wbflush_loongson2e(void)
+{
+	asm(".set\tpush\n\t"
+	    ".set\tnoreorder\n\t"
+	    ".set mips3\n\t"
+	    "sync\n\t"
+	    "nop\n\t"
+	    ".set\tpop\n\t"
+	    ".set mips0\n\t");
+}
+
+void __init plat_mem_setup(void)
+{
+	set_io_port_base(PTR_PAD(0xbfd00000));
+
+	mips_reboot_setup();
+
+	board_time_init = loongson2e_time_init;
+	rtc_mips_get_time = mips_rtc_get_time;
+
+	__wbflush = wbflush_loongson2e;
+
+	add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
+#ifdef CONFIG_64BIT
+	if (highmemsize > 0) {
+		add_memory_region(0x20000000, highmemsize << 20, BOOT_MEM_RAM);
+	}
+#endif
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+	conswitchp = &vga_con;
+
+	screen_info = (struct screen_info) {
+		0, 25,		/* orig-x, orig-y */
+		    0,		/* unused */
+		    0,		/* orig-video-page */
+		    0,		/* orig-video-mode */
+		    80,		/* orig-video-cols */
+		    0, 0, 0,	/* ega_ax, ega_bx, ega_cx */
+		    25,		/* orig-video-lines */
+		    VIDEO_TYPE_VGAC,	/* orig-video-isVGA */
+		    16		/* orig-video-points */
+	};
+#elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+#endif
+
+}
diff --git a/arch/mips/lib-32/Makefile b/arch/mips/lib-32/Makefile
deleted file mode 100644
index 8b94d4c..0000000
--- a/arch/mips/lib-32/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile for MIPS-specific library files..
-#
-
-lib-y	+= watch.o
-
-obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
-obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o
-obj-$(CONFIG_CPU_NEVADA)	+= dump_tlb.o
-obj-$(CONFIG_CPU_R10000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_R3000)		+= r3k_dump_tlb.o
-obj-$(CONFIG_CPU_R4300)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R4X00)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R5000)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R5432)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R6000)		+=
-obj-$(CONFIG_CPU_R8000)		+=
-obj-$(CONFIG_CPU_RM7000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_RM9000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_SB1)		+= dump_tlb.o
-obj-$(CONFIG_CPU_TX39XX)	+= r3k_dump_tlb.o
-obj-$(CONFIG_CPU_TX49XX)	+= dump_tlb.o
-obj-$(CONFIG_CPU_VR41XX)	+= dump_tlb.o
diff --git a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c
deleted file mode 100644
index 6a68deb..0000000
--- a/arch/mips/lib-32/dump_tlb.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Dump R4x00 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-static inline const char *msk2str(unsigned int mask)
-{
-	switch (mask) {
-	case PM_4K:
-		return "4kb";
-	case PM_16K:
-		return "16kb";
-	case PM_64K:
-		return "64kb";
-	case PM_256K:
-		return "256kb";
-#ifndef CONFIG_CPU_VR41XX
-	case PM_1M:
-		return "1Mb";
-	case PM_4M:
-		return "4Mb";
-	case PM_16M:
-		return "16Mb";
-	case PM_64M:
-		return "64Mb";
-	case PM_256M:
-		return "256Mb";
-#endif
-	}
-
-	return "unknown";
-}
-
-#define BARRIER()					\
-	__asm__ __volatile__(				\
-		".set\tnoreorder\n\t"			\
-		"nop;nop;nop;nop;nop;nop;nop\n\t"	\
-		".set\treorder");
-
-void dump_tlb(int first, int last)
-{
-	unsigned int pagemask, c0, c1, asid;
-	unsigned long long entrylo0, entrylo1;
-	unsigned long entryhi;
-	int i;
-
-	asid = read_c0_entryhi() & 0xff;
-
-	printk("\n");
-	for (i = first; i <= last; i++) {
-		write_c0_index(i);
-		BARRIER();
-		tlb_read();
-		BARRIER();
-		pagemask = read_c0_pagemask();
-		entryhi = read_c0_entryhi();
-		entrylo0 = read_c0_entrylo0();
-		entrylo1 = read_c0_entrylo1();
-
-		/* Unused entries have a virtual address in KSEG0.  */
-		if ((entryhi & 0xf0000000) != 0x80000000
-		    && (entryhi & 0xff) == asid) {
-			/*
-			 * Only print entries in use
-			 */
-			printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
-
-			c0 = (entrylo0 >> 3) & 7;
-			c1 = (entrylo1 >> 3) & 7;
-
-			printk("va=%08lx asid=%02lx\n",
-			       (entryhi & 0xffffe000), (entryhi & 0xff));
-			printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
-			       (entrylo0 << 6) & PAGE_MASK, c0,
-			       (entrylo0 & 4) ? 1 : 0,
-			       (entrylo0 & 2) ? 1 : 0, (entrylo0 & 1));
-			printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
-			       (entrylo1 << 6) & PAGE_MASK, c1,
-			       (entrylo1 & 4) ? 1 : 0,
-			       (entrylo1 & 2) ? 1 : 0, (entrylo1 & 1));
-			printk("\n");
-		}
-	}
-
-	write_c0_entryhi(asid);
-}
-
-void dump_tlb_all(void)
-{
-	dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
-	int wired;
-
-	wired = read_c0_wired();
-	printk("Wired: %d", wired);
-	dump_tlb(0, read_c0_wired());
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
-	unsigned int flags, oldpid;
-	int index;
-
-	local_irq_save(flags);
-	oldpid = read_c0_entryhi() & 0xff;
-	BARRIER();
-	write_c0_entryhi((addr & PAGE_MASK) | oldpid);
-	BARRIER();
-	tlb_probe();
-	BARRIER();
-	index = read_c0_index();
-	write_c0_entryhi(oldpid);
-	local_irq_restore(flags);
-
-	if (index < 0) {
-		printk("No entry for address 0x%08lx in TLB\n", addr);
-		return;
-	}
-
-	printk("Entry %d maps address 0x%08lx\n", index, addr);
-	dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
-	dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
-	pgd_t *page_dir, *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte, page;
-	unsigned long addr, val;
-
-	addr = (unsigned long) address;
-
-	printk("Addr                 == %08lx\n", addr);
-	printk("task                 == %8p\n", t);
-	printk("task->mm             == %8p\n", t->mm);
-	//printk("tasks->mm.pgd        == %08x\n", (unsigned int) t->mm->pgd);
-
-	if (addr > KSEG0) {
-		page_dir = pgd_offset_k(0);
-		pgd = pgd_offset_k(addr);
-	} else if (t->mm) {
-		page_dir = pgd_offset(t->mm, 0);
-		pgd = pgd_offset(t->mm, addr);
-	} else {
-		printk("Current thread has no mm\n");
-		return;
-	}
-	printk("page_dir == %08x\n", (unsigned int) page_dir);
-	printk("pgd == %08x, ", (unsigned int) pgd);
-	pud = pud_offset(pgd, addr);
-	printk("pud == %08x, ", (unsigned int) pud);
-
-	pmd = pmd_offset(pud, addr);
-	printk("pmd == %08x, ", (unsigned int) pmd);
-
-	pte = pte_offset(pmd, addr);
-	printk("pte == %08x, ", (unsigned int) pte);
-
-	page = *pte;
-#ifdef CONFIG_64BIT_PHYS_ADDR
-	printk("page == %08Lx\n", pte_val(page));
-#else
-	printk("page == %08lx\n", pte_val(page));
-#endif
-
-	val = pte_val(page);
-	if (val & _PAGE_PRESENT)
-		printk("present ");
-	if (val & _PAGE_READ)
-		printk("read ");
-	if (val & _PAGE_WRITE)
-		printk("write ");
-	if (val & _PAGE_ACCESSED)
-		printk("accessed ");
-	if (val & _PAGE_MODIFIED)
-		printk("modified ");
-	if (val & _PAGE_R4KBUG)
-		printk("r4kbug ");
-	if (val & _PAGE_GLOBAL)
-		printk("global ");
-	if (val & _PAGE_VALID)
-		printk("valid ");
-	printk("\n");
-}
-
-void dump_list_current(void *address)
-{
-	dump_list_process(current, address);
-}
-
-unsigned int vtop(void *address)
-{
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-	unsigned int addr, paddr;
-
-	addr = (unsigned long) address;
-	pgd = pgd_offset(current->mm, addr);
-	pud = pud_offset(pgd, addr);
-	pmd = pmd_offset(pud, addr);
-	pte = pte_offset(pmd, addr);
-	paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
-	paddr |= (addr & ~PAGE_MASK);
-
-	return paddr;
-}
-
-void dump16(unsigned long *p)
-{
-	int i;
-
-	for (i = 0; i < 8; i++) {
-		printk("*%08lx == %08lx, ", (unsigned long) p, *p);
-		p++;
-		printk("*%08lx == %08lx\n", (unsigned long) p, *p);
-		p++;
-	}
-}
diff --git a/arch/mips/lib-32/r3k_dump_tlb.c b/arch/mips/lib-32/r3k_dump_tlb.c
deleted file mode 100644
index 4f2cb74..0000000
--- a/arch/mips/lib-32/r3k_dump_tlb.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Dump R3000 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- * Copyright (C) 1999 by Harald Koerfgen
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-extern int r3k_have_wired_reg;	/* defined in tlb-r3k.c */
-
-void dump_tlb(int first, int last)
-{
-	int	i;
-	unsigned int asid;
-	unsigned long entryhi, entrylo0;
-
-	asid = read_c0_entryhi() & 0xfc0;
-
-	for (i = first; i <= last; i++) {
-		write_c0_index(i<<8);
-		__asm__ __volatile__(
-			".set\tnoreorder\n\t"
-			"tlbr\n\t"
-			"nop\n\t"
-			".set\treorder");
-		entryhi  = read_c0_entryhi();
-		entrylo0 = read_c0_entrylo0();
-
-		/* Unused entries have a virtual address of KSEG0.  */
-		if ((entryhi & 0xffffe000) != 0x80000000
-		    && (entryhi & 0xfc0) == asid) {
-			/*
-			 * Only print entries in use
-			 */
-			printk("Index: %2d ", i);
-
-			printk("va=%08lx asid=%08lx"
-			       "  [pa=%06lx n=%d d=%d v=%d g=%d]",
-			       (entryhi & 0xffffe000),
-			       entryhi & 0xfc0,
-			       entrylo0 & PAGE_MASK,
-			       (entrylo0 & (1 << 11)) ? 1 : 0,
-			       (entrylo0 & (1 << 10)) ? 1 : 0,
-			       (entrylo0 & (1 << 9)) ? 1 : 0,
-			       (entrylo0 & (1 << 8)) ? 1 : 0);
-		}
-	}
-	printk("\n");
-
-	write_c0_entryhi(asid);
-}
-
-void dump_tlb_all(void)
-{
-	dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
-	int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
-
-	printk("Wired: %d", wired);
-	dump_tlb(0, wired - 1);
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
-	unsigned long flags, oldpid;
-	int index;
-
-	local_irq_save(flags);
-	oldpid = read_c0_entryhi() & 0xff;
-	write_c0_entryhi((addr & PAGE_MASK) | oldpid);
-	tlb_probe();
-	index = read_c0_index();
-	write_c0_entryhi(oldpid);
-	local_irq_restore(flags);
-
-	if (index < 0) {
-		printk("No entry for address 0x%08lx in TLB\n", addr);
-		return;
-	}
-
-	printk("Entry %d maps address 0x%08lx\n", index, addr);
-	dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
-	int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
-	dump_tlb(wired, current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
-	pgd_t	*page_dir, *pgd;
-	pud_t	*pud;
-	pmd_t	*pmd;
-	pte_t	*pte, page;
-	unsigned int addr;
-	unsigned long val;
-
-	addr = (unsigned int) address;
-
-	printk("Addr                 == %08x\n", addr);
-	printk("tasks->mm.pgd        == %08x\n", (unsigned int) t->mm->pgd);
-
-	page_dir = pgd_offset(t->mm, 0);
-	printk("page_dir == %08x\n", (unsigned int) page_dir);
-
-	pgd = pgd_offset(t->mm, addr);
-	printk("pgd == %08x, ", (unsigned int) pgd);
-
-	pud = pud_offset(pgd, addr);
-	printk("pud == %08x, ", (unsigned int) pud);
-
-	pmd = pmd_offset(pud, addr);
-	printk("pmd == %08x, ", (unsigned int) pmd);
-
-	pte = pte_offset(pmd, addr);
-	printk("pte == %08x, ", (unsigned int) pte);
-
-	page = *pte;
-	printk("page == %08x\n", (unsigned int) pte_val(page));
-
-	val = pte_val(page);
-	if (val & _PAGE_PRESENT) printk("present ");
-	if (val & _PAGE_READ) printk("read ");
-	if (val & _PAGE_WRITE) printk("write ");
-	if (val & _PAGE_ACCESSED) printk("accessed ");
-	if (val & _PAGE_MODIFIED) printk("modified ");
-	if (val & _PAGE_GLOBAL) printk("global ");
-	if (val & _PAGE_VALID) printk("valid ");
-	printk("\n");
-}
-
-void dump_list_current(void *address)
-{
-	dump_list_process(current, address);
-}
-
-unsigned int vtop(void *address)
-{
-	pgd_t	*pgd;
-	pud_t	*pud;
-	pmd_t	*pmd;
-	pte_t	*pte;
-	unsigned int addr, paddr;
-
-	addr = (unsigned long) address;
-	pgd = pgd_offset(current->mm, addr);
-	pud = pud_offset(pgd, addr);
-	pmd = pmd_offset(pud, addr);
-	pte = pte_offset(pmd, addr);
-	paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
-	paddr |= (addr & ~PAGE_MASK);
-
-	return paddr;
-}
-
-void dump16(unsigned long *p)
-{
-	int i;
-
-	for (i = 0; i < 8; i++) {
-		printk("*%08lx == %08lx, ", (unsigned long)p, *p);
-		p++;
-		printk("*%08lx == %08lx\n", (unsigned long)p, *p);
-		p++;
-	}
-}
diff --git a/arch/mips/lib-32/watch.S b/arch/mips/lib-32/watch.S
deleted file mode 100644
index 808b3af..0000000
--- a/arch/mips/lib-32/watch.S
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Kernel debug stuff to use the Watch registers.
- * Useful to find stack overflows, dangling pointers etc.
- *
- * Copyright (C) 1995, 1996, 1999 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-
-		.set	noreorder
-/*
- * Parameter: a0 - logic address to watch
- *                 Currently only KSEG0 addresses are allowed!
- *            a1 - set bit #1 to trap on load references
- *                     bit #0 to trap on store references
- * Results  : none
- */
-		LEAF(__watch_set)
-		li	t0, 0x80000000
-		subu	a0, t0
-		ori	a0, 7
-		xori	a0, 7
-		or	a0, a1
-		mtc0	a0, CP0_WATCHLO
-		sw	a0, watch_savelo
-
-		jr	ra
-		 mtc0	zero, CP0_WATCHHI
-		END(__watch_set)
-
-/*
- * Parameter: none
- * Results  : none
- */
-		LEAF(__watch_clear)
-		jr	ra
-		 mtc0	zero, CP0_WATCHLO
-		END(__watch_clear)
-
-/*
- * Parameter: none
- * Results  : none
- */
-		LEAF(__watch_reenable)
-		lw	t0, watch_savelo
-		jr	ra
-		 mtc0	t0, CP0_WATCHLO
-		END(__watch_reenable)
-
-/*
- * Saved value of the c0_watchlo register for watch_reenable()
- */
-		.data
-watch_savelo:	.word	0
-		.text
diff --git a/arch/mips/lib-64/Makefile b/arch/mips/lib-64/Makefile
deleted file mode 100644
index 8b94d4c..0000000
--- a/arch/mips/lib-64/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile for MIPS-specific library files..
-#
-
-lib-y	+= watch.o
-
-obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
-obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o
-obj-$(CONFIG_CPU_NEVADA)	+= dump_tlb.o
-obj-$(CONFIG_CPU_R10000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_R3000)		+= r3k_dump_tlb.o
-obj-$(CONFIG_CPU_R4300)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R4X00)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R5000)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R5432)		+= dump_tlb.o
-obj-$(CONFIG_CPU_R6000)		+=
-obj-$(CONFIG_CPU_R8000)		+=
-obj-$(CONFIG_CPU_RM7000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_RM9000)	+= dump_tlb.o
-obj-$(CONFIG_CPU_SB1)		+= dump_tlb.o
-obj-$(CONFIG_CPU_TX39XX)	+= r3k_dump_tlb.o
-obj-$(CONFIG_CPU_TX49XX)	+= dump_tlb.o
-obj-$(CONFIG_CPU_VR41XX)	+= dump_tlb.o
diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c
deleted file mode 100644
index 594df1a..0000000
--- a/arch/mips/lib-64/dump_tlb.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Dump R4x00 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-static inline const char *msk2str(unsigned int mask)
-{
-	switch (mask) {
-	case PM_4K:	return "4kb";
-	case PM_16K:	return "16kb";
-	case PM_64K:	return "64kb";
-	case PM_256K:	return "256kb";
-#ifndef CONFIG_CPU_VR41XX
-	case PM_1M:	return "1Mb";
-	case PM_4M:	return "4Mb";
-	case PM_16M:	return "16Mb";
-	case PM_64M:	return "64Mb";
-	case PM_256M:	return "256Mb";
-#endif
-	}
-
-	return "unknown";
-}
-
-#define BARRIER()					\
-	__asm__ __volatile__(				\
-		".set\tnoreorder\n\t"			\
-		"nop;nop;nop;nop;nop;nop;nop\n\t"	\
-		".set\treorder");
-
-void dump_tlb(int first, int last)
-{
-	unsigned long s_entryhi, entryhi, entrylo0, entrylo1, asid;
-	unsigned int s_index, pagemask, c0, c1, i;
-
-	s_entryhi = read_c0_entryhi();
-	s_index = read_c0_index();
-	asid = s_entryhi & 0xff;
-
-	for (i = first; i <= last; i++) {
-		write_c0_index(i);
-		BARRIER();
-		tlb_read();
-		BARRIER();
-		pagemask = read_c0_pagemask();
-		entryhi  = read_c0_entryhi();
-		entrylo0 = read_c0_entrylo0();
-		entrylo1 = read_c0_entrylo1();
-
-		/* Unused entries have a virtual address of CKSEG0.  */
-		if ((entryhi & ~0x1ffffUL) != CKSEG0
-		    && (entryhi & 0xff) == asid) {
-			/*
-			 * Only print entries in use
-			 */
-			printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
-
-			c0 = (entrylo0 >> 3) & 7;
-			c1 = (entrylo1 >> 3) & 7;
-
-			printk("va=%011lx asid=%02lx\n",
-			       (entryhi & ~0x1fffUL),
-			       entryhi & 0xff);
-			printk("\t[pa=%011lx c=%d d=%d v=%d g=%ld] ",
-			       (entrylo0 << 6) & PAGE_MASK, c0,
-			       (entrylo0 & 4) ? 1 : 0,
-			       (entrylo0 & 2) ? 1 : 0,
-			       (entrylo0 & 1));
-			printk("[pa=%011lx c=%d d=%d v=%d g=%ld]\n",
-			       (entrylo1 << 6) & PAGE_MASK, c1,
-			       (entrylo1 & 4) ? 1 : 0,
-			       (entrylo1 & 2) ? 1 : 0,
-			       (entrylo1 & 1));
-		}
-	}
-	printk("\n");
-
-	write_c0_entryhi(s_entryhi);
-	write_c0_index(s_index);
-}
-
-void dump_tlb_all(void)
-{
-	dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
-	int	wired;
-
-	wired = read_c0_wired();
-	printk("Wired: %d", wired);
-	dump_tlb(0, read_c0_wired());
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
-	unsigned int flags, oldpid;
-	int index;
-
-	local_irq_save(flags);
-	oldpid = read_c0_entryhi() & 0xff;
-	BARRIER();
-	write_c0_entryhi((addr & PAGE_MASK) | oldpid);
-	BARRIER();
-	tlb_probe();
-	BARRIER();
-	index = read_c0_index();
-	write_c0_entryhi(oldpid);
-	local_irq_restore(flags);
-
-	if (index < 0) {
-		printk("No entry for address 0x%08lx in TLB\n", addr);
-		return;
-	}
-
-	printk("Entry %d maps address 0x%08lx\n", index, addr);
-	dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
-	dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
-	pgd_t	*page_dir, *pgd;
-	pud_t	*pud;
-	pmd_t	*pmd;
-	pte_t	*pte, page;
-	unsigned long addr, val;
-
-	addr = (unsigned long) address;
-
-	printk("Addr                 == %08lx\n", addr);
-	printk("tasks->mm.pgd        == %08lx\n", (unsigned long) t->mm->pgd);
-
-	page_dir = pgd_offset(t->mm, 0UL);
-	printk("page_dir == %016lx\n", (unsigned long) page_dir);
-
-	pgd = pgd_offset(t->mm, addr);
-	printk("pgd == %016lx\n", (unsigned long) pgd);
-
-	pud = pud_offset(pgd, addr);
-	printk("pud == %016lx\n", (unsigned long) pud);
-
-	pmd = pmd_offset(pud, addr);
-	printk("pmd == %016lx\n", (unsigned long) pmd);
-
-	pte = pte_offset(pmd, addr);
-	printk("pte == %016lx\n", (unsigned long) pte);
-
-	page = *pte;
-	printk("page == %08lx\n", pte_val(page));
-
-	val = pte_val(page);
-	if (val & _PAGE_PRESENT) printk("present ");
-	if (val & _PAGE_READ) printk("read ");
-	if (val & _PAGE_WRITE) printk("write ");
-	if (val & _PAGE_ACCESSED) printk("accessed ");
-	if (val & _PAGE_MODIFIED) printk("modified ");
-	if (val & _PAGE_R4KBUG) printk("r4kbug ");
-	if (val & _PAGE_GLOBAL) printk("global ");
-	if (val & _PAGE_VALID) printk("valid ");
-	printk("\n");
-}
-
-void dump_list_current(void *address)
-{
-	dump_list_process(current, address);
-}
-
-unsigned long vtop(void *address)
-{
-	pgd_t	*pgd;
-	pud_t	*pud;
-	pmd_t	*pmd;
-	pte_t	*pte;
-	unsigned long addr, paddr;
-
-	addr = (unsigned long) address;
-	pgd = pgd_offset(current->mm, addr);
-	pud = pud_offset(pgd, addr);
-	pmd = pmd_offset(pud, addr);
-	pte = pte_offset(pmd, addr);
-	paddr = (CKSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
-	paddr |= (addr & ~PAGE_MASK);
-
-	return paddr;
-}
-
-void dump16(unsigned long *p)
-{
-	int i;
-
-	for (i = 0; i < 8; i++) {
-		printk("*%08lx == %08lx, ", (unsigned long)p, *p);
-		p++;
-		printk("*%08lx == %08lx\n", (unsigned long)p, *p);
-		p++;
-	}
-}
diff --git a/arch/mips/lib-64/watch.S b/arch/mips/lib-64/watch.S
deleted file mode 100644
index f914340..0000000
--- a/arch/mips/lib-64/watch.S
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Kernel debug stuff to use the Watch registers.
- * Useful to find stack overflows, dangling pointers etc.
- *
- * Copyright (C) 1995, 1996, 1999, 2001 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-
-		.set	noreorder
-/*
- * Parameter: a0 - physical address to watch
- *            a1 - set bit #1 to trap on load references
- *                     bit #0 to trap on store references
- * Results  : none
- */
-		LEAF(__watch_set)
-		ori	a0, 7
-		xori	a0, 7
-		or	a0, a1
-		mtc0	a0, CP0_WATCHLO
-		sd	a0, watch_savelo
-		dsrl32	a0, a0, 0
-
-		jr	ra
-		 mtc0	zero, CP0_WATCHHI
-		END(__watch_set)
-
-/*
- * Parameter: none
- * Results  : none
- */
-		LEAF(__watch_clear)
-		jr	ra
-		 mtc0	zero, CP0_WATCHLO
-		END(__watch_clear)
-
-/*
- * Parameter: none
- * Results  : none
- */
-		LEAF(__watch_reenable)
-		ld	t0, watch_savelo
-		jr	ra
-		 mtc0	t0, CP0_WATCHLO
-		END(__watch_reenable)
-
-/*
- * Saved value of the c0_watchlo register for watch_reenable()
- */
-		.local	watch_savelo
-		.comm	watch_savelo, 8, 8
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 1c1aa9f..91ed1eb 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -8,5 +8,24 @@
 obj-y			+= iomap.o
 obj-$(CONFIG_PCI)	+= iomap-pci.o
 
+obj-$(CONFIG_CPU_LOONGSON2)	+= dump_tlb.o
+obj-$(CONFIG_CPU_MIPS32)	+= dump_tlb.o
+obj-$(CONFIG_CPU_MIPS64)	+= dump_tlb.o
+obj-$(CONFIG_CPU_NEVADA)	+= dump_tlb.o
+obj-$(CONFIG_CPU_R10000)	+= dump_tlb.o
+obj-$(CONFIG_CPU_R3000)		+= r3k_dump_tlb.o
+obj-$(CONFIG_CPU_R4300)		+= dump_tlb.o
+obj-$(CONFIG_CPU_R4X00)		+= dump_tlb.o
+obj-$(CONFIG_CPU_R5000)		+= dump_tlb.o
+obj-$(CONFIG_CPU_R5432)		+= dump_tlb.o
+obj-$(CONFIG_CPU_R6000)		+=
+obj-$(CONFIG_CPU_R8000)		+=
+obj-$(CONFIG_CPU_RM7000)	+= dump_tlb.o
+obj-$(CONFIG_CPU_RM9000)	+= dump_tlb.o
+obj-$(CONFIG_CPU_SB1)		+= dump_tlb.o
+obj-$(CONFIG_CPU_TX39XX)	+= r3k_dump_tlb.o
+obj-$(CONFIG_CPU_TX49XX)	+= dump_tlb.o
+obj-$(CONFIG_CPU_VR41XX)	+= dump_tlb.o
+
 # libgcc-style stuff needed in the kernel
 obj-y += ashldi3.o ashrdi3.o lshrdi3.o ucmpdi2.o
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c
new file mode 100644
index 0000000..1a4db7d
--- /dev/null
+++ b/arch/mips/lib/dump_tlb.c
@@ -0,0 +1,100 @@
+/*
+ * Dump R4x00 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+static inline const char *msk2str(unsigned int mask)
+{
+	switch (mask) {
+	case PM_4K:	return "4kb";
+	case PM_16K:	return "16kb";
+	case PM_64K:	return "64kb";
+	case PM_256K:	return "256kb";
+#ifndef CONFIG_CPU_VR41XX
+	case PM_1M:	return "1Mb";
+	case PM_4M:	return "4Mb";
+	case PM_16M:	return "16Mb";
+	case PM_64M:	return "64Mb";
+	case PM_256M:	return "256Mb";
+#endif
+	}
+	return "";
+}
+
+#define BARRIER()					\
+	__asm__ __volatile__(				\
+		".set\tnoreorder\n\t"			\
+		"nop;nop;nop;nop;nop;nop;nop\n\t"	\
+		".set\treorder");
+
+static void dump_tlb(int first, int last)
+{
+	unsigned long s_entryhi, entryhi, asid;
+	unsigned long long entrylo0, entrylo1;
+	unsigned int s_index, pagemask, c0, c1, i;
+
+	s_entryhi = read_c0_entryhi();
+	s_index = read_c0_index();
+	asid = s_entryhi & 0xff;
+
+	for (i = first; i <= last; i++) {
+		write_c0_index(i);
+		BARRIER();
+		tlb_read();
+		BARRIER();
+		pagemask = read_c0_pagemask();
+		entryhi  = read_c0_entryhi();
+		entrylo0 = read_c0_entrylo0();
+		entrylo1 = read_c0_entrylo1();
+
+		/* Unused entries have a virtual address of CKSEG0.  */
+		if ((entryhi & ~0x1ffffUL) != CKSEG0
+		    && (entryhi & 0xff) == asid) {
+#ifdef CONFIG_32BIT
+			int width = 8;
+#else
+			int width = 11;
+#endif
+			/*
+			 * Only print entries in use
+			 */
+			printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
+
+			c0 = (entrylo0 >> 3) & 7;
+			c1 = (entrylo1 >> 3) & 7;
+
+			printk("va=%0*lx asid=%02lx\n",
+			       width, (entryhi & ~0x1fffUL),
+			       entryhi & 0xff);
+			printk("\t[pa=%0*llx c=%d d=%d v=%d g=%d] ",
+			       width,
+			       (entrylo0 << 6) & PAGE_MASK, c0,
+			       (entrylo0 & 4) ? 1 : 0,
+			       (entrylo0 & 2) ? 1 : 0,
+			       (entrylo0 & 1) ? 1 : 0);
+			printk("[pa=%0*llx c=%d d=%d v=%d g=%d]\n",
+			       width,
+			       (entrylo1 << 6) & PAGE_MASK, c1,
+			       (entrylo1 & 4) ? 1 : 0,
+			       (entrylo1 & 2) ? 1 : 0,
+			       (entrylo1 & 1) ? 1 : 0);
+		}
+	}
+	printk("\n");
+
+	write_c0_entryhi(s_entryhi);
+	write_c0_index(s_index);
+}
+
+void dump_tlb_all(void)
+{
+	dump_tlb(0, current_cpu_data.tlbsize - 1);
+}
diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c
new file mode 100644
index 0000000..52f8779
--- /dev/null
+++ b/arch/mips/lib/r3k_dump_tlb.c
@@ -0,0 +1,62 @@
+/*
+ * Dump R3000 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ * Copyright (C) 1999 by Harald Koerfgen
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+extern int r3k_have_wired_reg;	/* defined in tlb-r3k.c */
+
+static void dump_tlb(int first, int last)
+{
+	int	i;
+	unsigned int asid;
+	unsigned long entryhi, entrylo0;
+
+	asid = read_c0_entryhi() & 0xfc0;
+
+	for (i = first; i <= last; i++) {
+		write_c0_index(i<<8);
+		__asm__ __volatile__(
+			".set\tnoreorder\n\t"
+			"tlbr\n\t"
+			"nop\n\t"
+			".set\treorder");
+		entryhi  = read_c0_entryhi();
+		entrylo0 = read_c0_entrylo0();
+
+		/* Unused entries have a virtual address of KSEG0.  */
+		if ((entryhi & 0xffffe000) != 0x80000000
+		    && (entryhi & 0xfc0) == asid) {
+			/*
+			 * Only print entries in use
+			 */
+			printk("Index: %2d ", i);
+
+			printk("va=%08lx asid=%08lx"
+			       "  [pa=%06lx n=%d d=%d v=%d g=%d]",
+			       (entryhi & 0xffffe000),
+			       entryhi & 0xfc0,
+			       entrylo0 & PAGE_MASK,
+			       (entrylo0 & (1 << 11)) ? 1 : 0,
+			       (entrylo0 & (1 << 10)) ? 1 : 0,
+			       (entrylo0 & (1 << 9)) ? 1 : 0,
+			       (entrylo0 & (1 << 8)) ? 1 : 0);
+		}
+	}
+	printk("\n");
+
+	write_c0_entryhi(asid);
+}
+
+void dump_tlb_all(void)
+{
+	dump_tlb(0, current_cpu_data.tlbsize - 1);
+}
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 80531b3..d7f05b0 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -35,6 +35,7 @@
  * better performance by compiling with -msoft-float!
  */
 #include <linux/sched.h>
+#include <linux/debugfs.h>
 
 #include <asm/inst.h>
 #include <asm/bootinfo.h>
@@ -1277,3 +1278,36 @@
 
 	return sig;
 }
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *mips_debugfs_dir;
+static int __init debugfs_fpuemu(void)
+{
+	struct dentry *d, *dir;
+	int i;
+	static struct {
+		const char *name;
+		unsigned int *v;
+	} vars[] __initdata = {
+		{ "emulated", &fpuemustats.emulated },
+		{ "loads",    &fpuemustats.loads },
+		{ "stores",   &fpuemustats.stores },
+		{ "cp1ops",   &fpuemustats.cp1ops },
+		{ "cp1xops",  &fpuemustats.cp1xops },
+		{ "errors",   &fpuemustats.errors },
+	};
+
+	if (!mips_debugfs_dir)
+		return -ENODEV;
+	dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
+	if (IS_ERR(dir))
+		return PTR_ERR(dir);
+	for (i = 0; i < ARRAY_SIZE(vars); i++) {
+		d = debugfs_create_u32(vars[i].name, S_IRUGO, dir, vars[i].v);
+		if (IS_ERR(d))
+			return PTR_ERR(d);
+	}
+	return 0;
+}
+__initcall(debugfs_fpuemu);
+#endif
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index 377d9e8..a242b0f 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -19,6 +19,7 @@
 # under Linux.
 #
 
-obj-y := malta_int.o malta_setup.o
+obj-y := malta_int.o malta_platform.o malta_setup.o
+
 obj-$(CONFIG_MTD) += malta_mtd.o
 obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o
diff --git a/arch/mips/mips-boards/malta/malta_platform.c b/arch/mips/mips-boards/malta/malta_platform.c
new file mode 100644
index 0000000..83b9bab
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_platform.c
@@ -0,0 +1,65 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ *   written by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * Probe driver for the Malta's UART ports:
+ *
+ *   o 2 ports in the SMC SuperIO
+ *   o 1 port in the CBUS UART, a discrete 16550 which normally is only used
+ *     for bringups.
+ *
+ * We don't use 8250_platform.c on Malta as it would result in the CBUS
+ * UART becoming ttyS0.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define SMC_PORT(base, int)						\
+{									\
+	.iobase		= base,						\
+	.irq		= int,						\
+	.uartclk	= 1843200,					\
+	.iotype		= UPIO_PORT,					\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,		\
+	.regshift	= 0,						\
+}
+
+#define CBUS_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+static struct plat_serial8250_port uart8250_data[] = {
+	SMC_PORT(0x3F8, 4),
+	SMC_PORT(0x2F8, 3),
+	{
+		.mapbase	= 0x1f000900,	/* The CBUS UART */
+		.irq		= MIPS_CPU_IRQ_BASE + 2,
+		.uartclk	= 3686400,	/* Twice the usual clk! */
+		.iotype		= UPIO_MEM32,
+		.flags		= CBUS_UART_FLAGS,
+		.regshift	= 3,
+	},
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM2,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Malta CBUS UART");
diff --git a/arch/mips/mips-boards/sim/Makefile b/arch/mips/mipssim/Makefile
similarity index 100%
rename from arch/mips/mips-boards/sim/Makefile
rename to arch/mips/mipssim/Makefile
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mipssim/sim_cmdline.c
similarity index 100%
rename from arch/mips/mips-boards/sim/sim_cmdline.c
rename to arch/mips/mipssim/sim_cmdline.c
diff --git a/arch/mips/mips-boards/sim/sim_console.c b/arch/mips/mipssim/sim_console.c
similarity index 97%
rename from arch/mips/mips-boards/sim/sim_console.c
rename to arch/mips/mipssim/sim_console.c
index de595a9..a2f4167 100644
--- a/arch/mips/mips-boards/sim/sim_console.c
+++ b/arch/mips/mipssim/sim_console.c
@@ -18,8 +18,8 @@
  *   written by Ralf Baechle
  */
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/serial_reg.h>
-#include <asm/io.h>
 
 static inline unsigned int serial_in(int offset)
 {
diff --git a/arch/mips/mipssim/sim_int.c b/arch/mips/mipssim/sim_int.c
new file mode 100644
index 0000000..d86b372
--- /dev/null
+++ b/arch/mips/mipssim/sim_int.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 1999, 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <asm/mips-boards/simint.h>
+#include <asm/irq_cpu.h>
+
+static inline int clz(unsigned long x)
+{
+	__asm__ (
+	"	.set	push					\n"
+	"	.set	mips32					\n"
+	"	clz	%0, %1					\n"
+	"	.set	pop					\n"
+	: "=r" (x)
+	: "r" (x));
+
+	return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+	return -clz(pending) + 31 - CAUSEB_IP;
+#else
+	unsigned int a0 = 7;
+	unsigned int t0;
+
+	t0 = s0 & 0xf000;
+	t0 = t0 < 1;
+	t0 = t0 << 2;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0xc000;
+	t0 = t0 < 1;
+	t0 = t0 << 1;
+	a0 = a0 - t0;
+	s0 = s0 << t0;
+
+	t0 = s0 & 0x8000;
+	t0 = t0 < 1;
+	/* t0 = t0 << 2; */
+	a0 = a0 - t0;
+	/* s0 = s0 << t0; */
+
+	return a0;
+#endif
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	irq = irq_ffs(pending);
+
+	if (irq > 0)
+		do_IRQ(MIPSCPU_INT_BASE + irq);
+	else
+		spurious_interrupt();
+}
+
+void __init arch_init_irq(void)
+{
+	mips_cpu_irq_init();
+}
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mipssim/sim_mem.c
similarity index 98%
rename from arch/mips/mips-boards/sim/sim_mem.c
rename to arch/mips/mipssim/sim_mem.c
index e408ef0b..2312483 100644
--- a/arch/mips/mips-boards/sim/sim_mem.c
+++ b/arch/mips/mipssim/sim_mem.c
@@ -95,7 +95,7 @@
 		size = p->size;
 
 		add_memory_region(base, size, type);
-                p++;
+		p++;
 	}
 }
 
diff --git a/arch/mips/mips-boards/sim/sim_platform.c b/arch/mips/mipssim/sim_platform.c
similarity index 100%
rename from arch/mips/mips-boards/sim/sim_platform.c
rename to arch/mips/mipssim/sim_platform.c
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mipssim/sim_setup.c
similarity index 95%
rename from arch/mips/mips-boards/sim/sim_setup.c
rename to arch/mips/mipssim/sim_setup.c
index b705f09..3643582 100644
--- a/arch/mips/mips-boards/sim/sim_setup.c
+++ b/arch/mips/mipssim/sim_setup.c
@@ -19,18 +19,18 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/ioport.h>
+#include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 
 #include <asm/cpu.h>
 #include <asm/bootinfo.h>
-#include <asm/irq.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/prom.h>
-#include <asm/serial.h>
-#include <asm/io.h>
 #include <asm/time.h>
 #include <asm/mips-boards/sim.h>
 #include <asm/mips-boards/simint.h>
@@ -62,7 +62,7 @@
 #endif
 }
 
-void prom_init(void)
+void __init prom_init(void)
 {
 	set_io_port_base(0xbfd00000);
 
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mipssim/sim_smp.c
similarity index 89%
rename from arch/mips/mips-boards/sim/sim_smp.c
rename to arch/mips/mipssim/sim_smp.c
index cb47863..38fa807 100644
--- a/arch/mips/mips-boards/sim/sim_smp.c
+++ b/arch/mips/mipssim/sim_smp.c
@@ -22,13 +22,13 @@
 #include <linux/sched.h>
 #include <linux/cpumask.h>
 #include <linux/interrupt.h>
+#include <linux/smp.h>
+
 #include <asm/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/system.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
-#include <asm/smp.h>
 #ifdef CONFIG_MIPS_MT_SMTC
 #include <asm/smtc_ipi.h>
 #endif /* CONFIG_MIPS_MT_SMTC */
@@ -73,11 +73,19 @@
 #endif /* CONFIG_MIPS_MT_SMTC */
 }
 
+void plat_smp_setup(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+	if (read_c0_config3() & (1 << 2))
+		mipsmt_build_cpu_map(0);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
 /*
  * Platform SMP pre-initialization
  */
 
-void prom_prepare_cpus(unsigned int max_cpus)
+void plat_prepare_cpus(unsigned int max_cpus)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
 	/*
@@ -85,8 +93,8 @@
 	 * but it may be multithreaded.
 	 */
 
-	if (read_c0_config3() & (1<<2)) {
-		mipsmt_prepare_cpus(max_cpus);
+	if (read_c0_config3() & (1 << 2)) {
+		mipsmt_prepare_cpus();
 	}
 #endif /* CONFIG_MIPS_MT_SMTC */
 }
diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mipssim/sim_time.c
similarity index 91%
rename from arch/mips/mips-boards/sim/sim_time.c
rename to arch/mips/mipssim/sim_time.c
index 7224ffe..874a18e 100644
--- a/arch/mips/mips-boards/sim/sim_time.c
+++ b/arch/mips/mipssim/sim_time.c
@@ -5,10 +5,10 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
+#include <linux/mipsregs.h>
+#include <linux/smp.h>
 #include <linux/timex.h>
 
-#include <asm/mipsregs.h>
-#include <asm/ptrace.h>
 #include <asm/hardirq.h>
 #include <asm/div64.h>
 #include <asm/cpu.h>
@@ -16,7 +16,6 @@
 #include <asm/irq.h>
 #include <asm/mc146818-time.h>
 #include <asm/msc01_ic.h>
-#include <asm/smp.h>
 
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/prom.h>
@@ -37,8 +36,7 @@
 #ifndef CONFIG_MIPS_MT_SMTC
 	if (cpu == 0) {
 		timer_interrupt(irq, dev_id);
-	}
-	else {
+	} else {
 		/* Everyone else needs to reset the timer int here as
 		   ll_local_timer_interrupt doesn't */
 		/*
@@ -76,8 +74,10 @@
 	irq_enable_hazard();
 	evpe(vpflags);
 
-	if(cpu_data[cpu].vpe_id == 0) timer_interrupt(irq, dev_id);
-	else write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+	if (cpu_data[cpu].vpe_id == 0)
+		timer_interrupt(irq, dev_id);
+	else
+		write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
 	smtc_timer_broadcast(cpu_data[cpu].vpe_id);
 
 #endif /* CONFIG_MIPS_MT_SMTC */
@@ -85,7 +85,8 @@
 	/*
 	 * every CPU should do profiling and process accounting
 	 */
- 	local_timer_interrupt (irq, dev_id);
+	local_timer_interrupt (irq, dev_id);
+
 	return IRQ_HANDLED;
 #else
 	return timer_interrupt (irq, dev_id);
@@ -152,17 +153,15 @@
 
 	local_irq_save(flags);
 
-
-        /* Set Data mode - binary. */
+	/* Set Data mode - binary. */
 	CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
 
-
 	est_freq = estimate_cpu_frequency ();
 
-	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
-	       (est_freq%1000000)*100/1000000);
+	printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000,
+	       (est_freq % 1000000) * 100 / 1000000);
 
-        cpu_khz = est_freq / 1000;
+	cpu_khz = est_freq / 1000;
 
 	local_irq_restore(flags);
 }
@@ -180,8 +179,7 @@
 	if (cpu_has_veic) {
 		set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
 		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
-	}
-	else {
+	} else {
 		if (cpu_has_vint)
 			set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
 		mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 293697b..19a0e54 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_64BIT)		+= pgtable-64.o
 obj-$(CONFIG_HIGHMEM)		+= highmem.o
 
+obj-$(CONFIG_CPU_LOONGSON2)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_MIPS32)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_MIPS64)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
 obj-$(CONFIG_CPU_NEVADA)	+= c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index df04a31..be96231 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -335,6 +335,10 @@
 
 static inline void local_r4k___flush_cache_all(void * args)
 {
+#if defined(CONFIG_CPU_LOONGSON2)
+	r4k_blast_scache();
+	return;
+#endif
 	r4k_blast_dcache();
 	r4k_blast_icache();
 
@@ -848,6 +852,24 @@
 		c->options |= MIPS_CPU_PREFETCH;
 		break;
 
+	case CPU_LOONGSON2:
+		icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
+		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
+		if (prid & 0x3)
+			c->icache.ways = 4;
+		else
+			c->icache.ways = 2;
+		c->icache.waybit = 0;
+
+		dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
+		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
+		if (prid & 0x3)
+			c->dcache.ways = 4;
+		else
+			c->dcache.ways = 2;
+		c->dcache.waybit = 0;
+		break;
+
 	default:
 		if (!(config & MIPS_CONF_M))
 			panic("Don't know how to probe P-caches on this cpu.");
@@ -963,6 +985,14 @@
 		break;
 	}
 
+#ifdef  CONFIG_CPU_LOONGSON2
+	/*
+	 * LOONGSON2 has 4 way icache, but when using indexed cache op,
+	 * one op will act on all 4 ways
+	 */
+	c->icache.ways = 1;
+#endif
+
 	printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
 	       icache_size >> 10,
 	       cpu_has_vtag_icache ? "virtually tagged" : "physically tagged",
@@ -1036,6 +1066,24 @@
 	return 1;
 }
 
+#if defined(CONFIG_CPU_LOONGSON2)
+static void __init loongson2_sc_init(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+
+	scache_size = 512*1024;
+	c->scache.linesz = 32;
+	c->scache.ways = 4;
+	c->scache.waybit = 0;
+	c->scache.waysize = scache_size / (c->scache.ways);
+	c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
+	pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
+	       scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
+
+	c->options |= MIPS_CPU_INCLUSIVE_CACHES;
+}
+#endif
+
 extern int r5k_sc_init(void);
 extern int rm7k_sc_init(void);
 extern int mips_sc_init(void);
@@ -1085,6 +1133,12 @@
 #endif
 		return;
 
+#if defined(CONFIG_CPU_LOONGSON2)
+	case CPU_LOONGSON2:
+		loongson2_sc_init();
+		return;
+#endif
+
 	default:
 		if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
 		    c->isa_level == MIPS_CPU_ISA_M32R2 ||
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 9ea460b..6f9bd7f 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -476,7 +476,7 @@
  * memory management function pointers, as well as initialize
  * the caches and tlbs
  */
-void sb1_cache_init(void)
+void __init sb1_cache_init(void)
 {
 	extern char except_vec2_sb1;
 
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index abf99b1..81f925a 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -6,6 +6,8 @@
  * Copyright (C) 1994 - 2003, 07 by Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 2007 MIPS Technologies, Inc.
  */
+#include <linux/fs.h>
+#include <linux/fcntl.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -164,3 +166,11 @@
 
 	panic(cache_panic);
 }
+
+int __weak __uncached_access(struct file *file, unsigned long addr)
+{
+	if (file->f_flags & O_SYNC)
+		return 1;
+
+	return addr >= __pa(high_memory);
+}
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 65160d4..dcd6913 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -48,6 +48,22 @@
 
 #endif /* CONFIG_MIPS_MT_SMTC */
 
+#if defined(CONFIG_CPU_LOONGSON2)
+/*
+ * LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
+ * unfortrunately, itlb is not totally transparent to software.
+ */
+#define FLUSH_ITLB write_c0_diag(4);
+
+#define FLUSH_ITLB_VM(vma) { if ((vma)->vm_flags & VM_EXEC)  write_c0_diag(4); }
+
+#else
+
+#define FLUSH_ITLB
+#define FLUSH_ITLB_VM(vma)
+
+#endif
+
 void local_flush_tlb_all(void)
 {
 	unsigned long flags;
@@ -73,6 +89,7 @@
 	}
 	tlbw_use_hazard();
 	write_c0_entryhi(old_ctx);
+	FLUSH_ITLB;
 	EXIT_CRITICAL(flags);
 }
 
@@ -136,6 +153,7 @@
 		} else {
 			drop_mmu_context(mm, cpu);
 		}
+		FLUSH_ITLB;
 		EXIT_CRITICAL(flags);
 	}
 }
@@ -178,6 +196,7 @@
 	} else {
 		local_flush_tlb_all();
 	}
+	FLUSH_ITLB;
 	EXIT_CRITICAL(flags);
 }
 
@@ -210,6 +229,7 @@
 
 	finish:
 		write_c0_entryhi(oldpid);
+		FLUSH_ITLB_VM(vma);
 		EXIT_CRITICAL(flags);
 	}
 }
@@ -241,7 +261,7 @@
 		tlbw_use_hazard();
 	}
 	write_c0_entryhi(oldpid);
-
+	FLUSH_ITLB;
 	EXIT_CRITICAL(flags);
 }
 
@@ -293,6 +313,7 @@
 	else
 		tlb_write_indexed();
 	tlbw_use_hazard();
+	FLUSH_ITLB_VM(vma);
 	EXIT_CRITICAL(flags);
 }
 
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index e714929..4ec0964 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -893,6 +893,7 @@
 	case CPU_4KSC:
 	case CPU_20KC:
 	case CPU_25KF:
+	case CPU_LOONGSON2:
 		tlbw(p);
 		break;
 
@@ -1276,7 +1277,8 @@
 	 * need three, with the second nop'ed and the third being
 	 * unused.
 	 */
-#ifdef CONFIG_32BIT
+	/* Loongson2 ebase is different than r4k, we have more space */
+#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
 	if ((p - tlb_handler) > 64)
 		panic("TLB refill handler space exceeded");
 #else
@@ -1289,7 +1291,7 @@
 	/*
 	 * Now fold the handler in the TLB refill handler space.
 	 */
-#ifdef CONFIG_32BIT
+#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
 	f = final_handler;
 	/* Simplest case, just copy the handler. */
 	copy_handler(relocs, labels, tlb_handler, p, f);
@@ -1336,7 +1338,7 @@
 		final_len);
 
 	f = final_handler;
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && !defined(CONFIG_CPU_LOONGSON2)
 	if (final_len > 32)
 		final_len = 64;
 	else
diff --git a/arch/mips/momentum/ocelot_3/Makefile b/arch/mips/momentum/ocelot_3/Makefile
deleted file mode 100644
index d5a090a..0000000
--- a/arch/mips/momentum/ocelot_3/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for Momentum Computer's Ocelot-3 board.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-obj-y	 += irq.o platform.o prom.o reset.o setup.o
diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c
deleted file mode 100644
index 3862d1d..0000000
--- a/arch/mips/momentum/ocelot_3/irq.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Copyright (C) 2004 MontaVista Software Inc.
- *  Author: Manish Lachwani, mlachwani@mvista.com
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-
-static struct irqaction cascade_mv64340 = {
-	no_action, IRQF_DISABLED, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
-};
-
-void __init arch_init_irq(void)
-{
-	/*
-	 * Clear all of the interrupts while we change the able around a bit.
-	 * int-handler is not on bootstrap
-	 */
-	clear_c0_status(ST0_IM | ST0_BEV);
-
-	rm7k_cpu_irq_init();
-
-	/* set up the cascading interrupts */
-	setup_irq(8, &cascade_mv64340);		/* unmask intControl IM8, IRQ 9 */
-	mv64340_irq_init(16);
-
-	set_c0_status(ST0_IM); /* IE in the status register */
-
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status();
-
-	if (pending & STATUSF_IP0)
-		do_IRQ(0);
-	else if (pending & STATUSF_IP1)
-		do_IRQ(1);
-	else if (pending & STATUSF_IP2)
-		do_IRQ(2);
-	else if (pending & STATUSF_IP3)
-		do_IRQ(3);
-	else if (pending & STATUSF_IP4)
-		do_IRQ(4);
-	else if (pending & STATUSF_IP5)
-		do_IRQ(5);
-	else if (pending & STATUSF_IP6)
-		do_IRQ(6);
-	else if (pending & STATUSF_IP7)
-		do_IRQ(7);
-	else {
-		/*
-		 * Now look at the extended interrupts
-		 */
-		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
-
-		if (pending & STATUSF_IP8)
-			ll_mv64340_irq();
-		else
-			spurious_interrupt();
-	}
-}
diff --git a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h b/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h
deleted file mode 100644
index 5710a90..0000000
--- a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Ocelot-3 Board Register Definitions
- *
- * (C) 2002 Momentum Computer Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Louis Hamilton, Red Hat, Inc.
- *    hamilton@redhat.com  [MIPS64 modifications]
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- */
-
-#ifndef __OCELOT_3_FPGA_H__
-#define __OCELOT_3_FPGA_H__
-
-#define OCELOT_3_REG_BOARDREV		0x0
-#define OCELOT_3_REG_FPGA_REV		0x1
-#define OCELOT_3_REG_FPGA_TYPE		0x2
-#define OCELOT_3_REG_RESET_STATUS	0x3
-#define OCELOT_3_REG_BOARD_STATUS	0x4
-#define OCELOT_3_REG_CPCI_ID		0x5
-#define OCELOT_3_REG_SET		0x6
-#define OCELOT_3_REG_CLR		0x7
-#define OCELOT_3_REG_EEPROM_MODE	0x9
-#define OCELOT_3_REG_INTMASK		0xa
-#define OCELOT_3_REG_INTSTAT		0xb
-#define OCELOT_3_REG_UART_INTMASK	0xc
-#define OCELOT_3_REG_UART_INTSTAT	0xd
-#define OCELOT_3_REG_INTSET		0xe
-#define OCELOT_3_REG_INTCLR		0xf
-
-extern unsigned long ocelot_fpga_base;
-
-#define __FPGA_REG_TO_ADDR(reg)						\
-	((void *) ocelot_fpga_base + OCELOT_3_REG_##reg)
-#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
-#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
-
-#endif
diff --git a/arch/mips/momentum/ocelot_3/platform.c b/arch/mips/momentum/ocelot_3/platform.c
deleted file mode 100644
index 44e4c3f..0000000
--- a/arch/mips/momentum/ocelot_3/platform.c
+++ /dev/null
@@ -1,208 +0,0 @@
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/mv643xx.h>
-#include <linux/platform_device.h>
-
-#include "ocelot_3_fpga.h"
-
-#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
-
-static struct resource mv643xx_eth_shared_resources[] = {
-	[0] = {
-		.name   = "ethernet shared base",
-		.start  = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
-		.end    = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
-		                       MV643XX_ETH_SHARED_REGS_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
-	.name		= MV643XX_ETH_SHARED_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv643xx_eth_shared_resources),
-	.resource	= mv643xx_eth_shared_resources,
-};
-
-#define MV_SRAM_BASE			0xfe000000UL
-#define MV_SRAM_SIZE			(256 * 1024)
-
-#define MV_SRAM_RXRING_SIZE		(MV_SRAM_SIZE / 4)
-#define MV_SRAM_TXRING_SIZE		(MV_SRAM_SIZE / 4)
-
-#define MV_SRAM_BASE_ETH0		MV_SRAM_BASE
-#define MV_SRAM_BASE_ETH1		(MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
-
-#define MV64x60_IRQ_ETH_0 48
-#define MV64x60_IRQ_ETH_1 49
-#define MV64x60_IRQ_ETH_2 50
-
-static struct resource mv64x60_eth0_resources[] = {
-	[0] = {
-		.name	= "eth0 irq",
-		.start	= MV64x60_IRQ_ETH_0,
-		.end	= MV64x60_IRQ_ETH_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth0_pd = {
-	.port_number	= 0,
-
-	.tx_sram_addr	= MV_SRAM_BASE_ETH0,
-	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
-	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
-
-	.rx_sram_addr	= MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
-	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
-	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth0_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth0_resources),
-	.resource	= mv64x60_eth0_resources,
-	.dev = {
-		.platform_data = &eth0_pd,
-	},
-};
-
-static struct resource mv64x60_eth1_resources[] = {
-	[0] = {
-		.name	= "eth1 irq",
-		.start	= MV64x60_IRQ_ETH_1,
-		.end	= MV64x60_IRQ_ETH_1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
-	.port_number	= 1,
-
-	.tx_sram_addr	= MV_SRAM_BASE_ETH1,
-	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
-	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
-
-	.rx_sram_addr	= MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
-	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
-	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth1_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth1_resources),
-	.resource	= mv64x60_eth1_resources,
-	.dev = {
-		.platform_data = &eth1_pd,
-	},
-};
-
-static struct resource mv64x60_eth2_resources[] = {
-	[0] = {
-		.name	= "eth2 irq",
-		.start	= MV64x60_IRQ_ETH_2,
-		.end	= MV64x60_IRQ_ETH_2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth2_pd = {
-	.port_number	= 2,
-};
-
-static struct platform_device eth2_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth2_resources),
-	.resource	= mv64x60_eth2_resources,
-	.dev = {
-		.platform_data = &eth2_pd,
-	},
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
-	&mv643xx_eth_shared_device,
-	&eth0_device,
-	&eth1_device,
-	&eth2_device,
-};
-
-static u8 __init exchange_bit(u8 val, u8 cs)
-{
-	/* place the data */
-	OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
-	udelay(1);
-
-	/* turn the clock on */
-	OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
-	udelay(1);
-
-	/* turn the clock off and read-strobe */
-	OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
-	/* return the data */
-	return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
-}
-
-static void __init get_mac(char dest[6])
-{
-	u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	int i,j;
-
-	for (i = 0; i < 12; i++)
-		exchange_bit(read_opcode[i], 1);
-
-	for (j = 0; j < 6; j++) {
-		dest[j] = 0;
-		for (i = 0; i < 8; i++) {
-			dest[j] <<= 1;
-			dest[j] |= exchange_bit(0, 1);
-		}
-	}
-
-	/* turn off CS */
-	exchange_bit(0,0);
-}
-
-/*
- * Copy and increment ethernet MAC address by a small value.
- *
- * This is useful for systems where the only one MAC address is stored in
- * non-volatile memory for multiple ports.
- */
-static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
-	unsigned int add)
-{
-	int i;
-
-	BUG_ON(add >= 256);
-
-	for (i = ETH_ALEN; i >= 0; i--) {
-		dst[i] = src[i] + add;
-		add = dst[i] < src[i];		/* compute carry */
-	}
-
-	WARN_ON(add);
-}
-
-static int __init mv643xx_eth_add_pds(void)
-{
-	unsigned char mac[ETH_ALEN];
-	int ret;
-
-	get_mac(mac);
-	eth_mac_add(eth0_pd.mac_addr, mac, 0);
-	eth_mac_add(eth1_pd.mac_addr, mac, 1);
-	eth_mac_add(eth2_pd.mac_addr, mac, 2);
-	ret = platform_add_devices(mv643xx_eth_pd_devs,
-			ARRAY_SIZE(mv643xx_eth_pd_devs));
-
-	return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
-
-#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
diff --git a/arch/mips/momentum/ocelot_3/prom.c b/arch/mips/momentum/ocelot_3/prom.c
deleted file mode 100644
index 8e02df6..0000000
--- a/arch/mips/momentum/ocelot_3/prom.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- *   hamilton@redhat.com  [MIPS64 modifications]
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- */
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-#include "ocelot_3_fpga.h"
-
-struct callvectors* debug_vectors;
-extern unsigned long marvell_base;
-extern unsigned long cpu_clock;
-
-const char *get_system_type(void)
-{
-	return "Momentum Ocelot-3";
-}
-
-#ifdef CONFIG_64BIT
-
-unsigned long signext(unsigned long addr)
-{
-	addr &= 0xffffffff;
-	return (unsigned long)((int)addr);
-}
-
-void *get_arg(unsigned long args, int arc)
-{
-	unsigned long ul;
-	unsigned char *puc, uc;
-
-	args += (arc * 4);
-	ul = (unsigned long)signext(args);
-	puc = (unsigned char *)ul;
-	if (puc == 0)
-		return (void *)0;
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
-	uc = *puc++;
-	ul = (unsigned long)uc;
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 8);
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 16);
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 24);
-#else  /* CONFIG_CPU_LITTLE_ENDIAN */
-	uc = *puc++;
-	ul = ((unsigned long)uc) << 24;
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 16);
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 8);
-	uc = *puc++;
-	ul |= ((unsigned long)uc);
-#endif  /* CONFIG_CPU_LITTLE_ENDIAN */
-	ul = signext(ul);
-	return (void *)ul;
-}
-
-char *arg64(unsigned long addrin, int arg_index)
-{
-	unsigned long args;
-	char *p;
-
-	args = signext(addrin);
-	p = (char *)get_arg(args, arg_index);
-
-	return p;
-}
-#endif  /* CONFIG_64BIT */
-
-void __init prom_init(void)
-{
-	int argc = fw_arg0;
-	char **arg = (char **) fw_arg1;
-	char **env = (char **) fw_arg2;
-	struct callvectors *cv = (struct callvectors *) fw_arg3;
-	int i;
-
-#ifdef CONFIG_64BIT
-	char *ptr;
-	printk("prom_init - MIPS64\n");
-
-	/* save the PROM vectors for debugging use */
-	debug_vectors = (struct callvectors *)signext((unsigned long)cv);
-
-	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
-
-	for (i = 1; i < argc; i++) {
-		ptr = (char *)arg64((unsigned long)arg, i);
-		if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
-		    sizeof(arcs_cmdline))
-			break;
-		strcat(arcs_cmdline, ptr);
-		strcat(arcs_cmdline, " ");
-	}
-	i = 0;
-
-	while (1) {
-		ptr = (char *)arg64((unsigned long)env, i);
-		if (! ptr)
-			break;
-
-		if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
-			marvell_base = simple_strtol(ptr + strlen("gtbase="),
-							NULL, 16);
-
-			if ((marvell_base & 0xffffffff00000000) == 0)
-				marvell_base |= 0xffffffff00000000;
-
-			printk("marvell_base set to 0x%016lx\n", marvell_base);
-		}
-		if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
-			cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
-							NULL, 10);
-			printk("cpu_clock set to %d\n", cpu_clock);
-		}
-		i++;
-	}
-	printk("arcs_cmdline: %s\n", arcs_cmdline);
-
-#else   /* CONFIG_64BIT */
-
-	/* save the PROM vectors for debugging use */
-	debug_vectors = cv;
-
-	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
-	for (i = 1; i < argc; i++) {
-		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
-		    >= sizeof(arcs_cmdline))
-			break;
-		strcat(arcs_cmdline, arg[i]);
-		strcat(arcs_cmdline, " ");
-	}
-
-	while (*env) {
-		if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
-			marvell_base = simple_strtol(*env + strlen("gtbase="),
-							NULL, 16);
-		}
-		if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
-			cpu_clock = simple_strtol(*env + strlen("cpuclock="),
-							NULL, 10);
-		}
-		env++;
-	}
-#endif /* CONFIG_64BIT */
-
-	mips_machgroup = MACH_GROUP_MOMENCO;
-	mips_machtype = MACH_MOMENCO_OCELOT_3;
-
-#ifndef CONFIG_64BIT
-	debug_vectors->printf("Booting Linux kernel...\n");
-#endif
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
-}
diff --git a/arch/mips/momentum/ocelot_3/reset.c b/arch/mips/momentum/ocelot_3/reset.c
deleted file mode 100644
index 9d86d24..0000000
--- a/arch/mips/momentum/ocelot_3/reset.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 01, 05 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com  [MIPS64 modifications]
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void momenco_ocelot_restart(char *command)
-{
-	/* base address of timekeeper portion of part */
-	void *nvram = (void *) 0xfc807000L;
-
-	/* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
-	writeb(0x84, nvram + 0xff7);
-
-	/* wait for the watchdog to go off */
-	mdelay(100+(1000/16));
-
-	/* if the watchdog fails for some reason, let people know */
-	printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_ocelot_halt(void)
-{
-	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
-	while (1)
-		__asm__(".set\tmips3\n\t"
-	                "wait\n\t"
-			".set\tmips0");
-}
-
-void momenco_ocelot_power_off(void)
-{
-	momenco_ocelot_halt();
-}
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
deleted file mode 100644
index ff0829f..0000000
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * setup.c
- *
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Ocelot-3 board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 01, 05 - 06  Ralf Baechle
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- *   mdharm@momenco.com
- *
- * Louis Hamilton, Red Hat, Inc.
- *   hamilton@redhat.com  [MIPS64 modifications]
- *
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mc146818rtc.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/timex.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-#include <linux/pm.h>
-#include <linux/bcd.h>
-
-#include <asm/time.h>
-#include <asm/page.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/mc146818rtc.h>
-#include <asm/tlbflush.h>
-#include "ocelot_3_fpga.h"
-
-/* Marvell Discovery Register Base */
-unsigned long marvell_base = (signed)0xf4000000;
-
-/* CPU clock */
-unsigned long cpu_clock;
-
-/* RTC/NVRAM */
-unsigned char* rtc_base = (unsigned char*)(signed)0xfc800000;
-
-/* FPGA Base */
-unsigned long ocelot_fpga_base = (signed)0xfc000000;
-
-/* Serial base */
-unsigned long uart_base = (signed)0xfd000000;
-
-/*
- * Marvell Discovery SRAM. This is one place where Ethernet
- * Tx and Rx descriptors can be placed to improve performance
- */
-extern unsigned long mv64340_sram_base;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_ocelot_restart(char *command);
-extern void momenco_ocelot_halt(void);
-extern void momenco_ocelot_power_off(void);
-
-void momenco_time_init(void);
-static char reset_reason;
-
-void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
-		     unsigned long entryhi, unsigned long pagemask);
-
-static inline unsigned long ENTRYLO(unsigned long paddr)
-{
-	return ((paddr & PAGE_MASK) |
-		(_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
-		_CACHE_UNCACHED)) >> 6;
-}
-
-void __init bus_error_init(void)
-{
-	/* nothing */
-}
-
-/*
- * setup code for a handoff from a version 2 PMON 2000 PROM
- */
-void setup_wired_tlb_entries(void)
-{
-	write_c0_wired(0);
-	local_flush_tlb_all();
-
-	/* marvell and extra space */
-	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), (signed)0xf4000000, PM_64K);
-
-	/* fpga, rtc, and uart */
-	add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), (signed)0xfc000000, PM_16M);
-}
-
-unsigned long m48t37y_get_time(void)
-{
-	unsigned int year, month, day, hour, min, sec;
-	unsigned long flags;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	/* stop the update */
-	rtc_base[0x7ff8] = 0x40;
-
-	year = BCD2BIN(rtc_base[0x7fff]);
-	year += BCD2BIN(rtc_base[0x7ff1]) * 100;
-
-	month = BCD2BIN(rtc_base[0x7ffe]);
-
-	day = BCD2BIN(rtc_base[0x7ffd]);
-
-	hour = BCD2BIN(rtc_base[0x7ffb]);
-	min = BCD2BIN(rtc_base[0x7ffa]);
-	sec = BCD2BIN(rtc_base[0x7ff9]);
-
-	/* start the update */
-	rtc_base[0x7ff8] = 0x00;
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return mktime(year, month, day, hour, min, sec);
-}
-
-int m48t37y_set_time(unsigned long sec)
-{
-	struct rtc_time tm;
-	unsigned long flags;
-
-	/* convert to a more useful format -- note months count from 0 */
-	to_tm(sec, &tm);
-	tm.tm_mon += 1;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	/* enable writing */
-	rtc_base[0x7ff8] = 0x80;
-
-	/* year */
-	rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
-	rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
-
-	/* month */
-	rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
-
-	/* day */
-	rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
-
-	/* hour/min/sec */
-	rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
-	rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
-	rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
-
-	/* day of week -- not really used, but let's keep it up-to-date */
-	rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
-
-	/* disable writing */
-	rtc_base[0x7ff8] = 0x00;
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return 0;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
-	setup_irq(7, irq);	/* Timer interrupt, unmask status IM7 */
-}
-
-void momenco_time_init(void)
-{
-	setup_wired_tlb_entries();
-
-	/*
-	 * Ocelot-3 board has been built with both
-	 * the Rm7900 and the Rm7065C
-	 */
-	mips_hpt_frequency = cpu_clock / 2;
-
-	rtc_mips_get_time = m48t37y_get_time;
-	rtc_mips_set_time = m48t37y_set_time;
-}
-
-/*
- * PCI Support for Ocelot-3
- */
-
-/* Bus #0 IO and MEM space */
-#define	OCELOT_3_PCI_IO_0_START		0xe0000000
-#define	OCELOT_3_PCI_IO_0_SIZE		0x08000000
-#define	OCELOT_3_PCI_MEM_0_START	0xc0000000
-#define	OCELOT_3_PCI_MEM_0_SIZE		0x10000000
-
-/* Bus #1 IO and MEM space */
-#define	OCELOT_3_PCI_IO_1_START		0xe8000000
-#define	OCELOT_3_PCI_IO_1_SIZE		0x08000000
-#define	OCELOT_3_PCI_MEM_1_START	0xd0000000
-#define	OCELOT_3_PCI_MEM_1_SIZE		0x10000000
-
-static struct resource mv_pci_io_mem0_resource = {
-	.name	= "MV64340 PCI0 IO MEM",
-	.start	= OCELOT_3_PCI_IO_0_START,
-	.end	= OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE - 1,
-	.flags  = IORESOURCE_IO,
-};
-
-static struct resource mv_pci_io_mem1_resource = {
-	.name	= "MV64340 PCI1 IO MEM",
-	.start	= OCELOT_3_PCI_IO_1_START,
-	.end	= OCELOT_3_PCI_IO_1_START + OCELOT_3_PCI_IO_1_SIZE - 1,
-	.flags	= IORESOURCE_IO,
-};
-
-static struct resource mv_pci_mem0_resource = {
-	.name	= "MV64340 PCI0 MEM",
-	.start	= OCELOT_3_PCI_MEM_0_START,
-	.end	= OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct resource mv_pci_mem1_resource = {
-	.name	= "MV64340 PCI1 MEM",
-	.start	= OCELOT_3_PCI_MEM_1_START,
-	.end	= OCELOT_3_PCI_MEM_1_START + OCELOT_3_PCI_MEM_1_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct mv_pci_controller mv_bus0_controller = {
-	.pcic = {
-		 .pci_ops	= &mv_pci_ops,
-		 .mem_resource	= &mv_pci_mem0_resource,
-		 .io_resource	= &mv_pci_io_mem0_resource,
-	},
-	.config_addr	= MV64340_PCI_0_CONFIG_ADDR,
-	.config_vreg	= MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static struct mv_pci_controller mv_bus1_controller = {
-	.pcic = {
-		 .pci_ops	= &mv_pci_ops,
-		 .mem_resource	= &mv_pci_mem1_resource,
-		 .io_resource	= &mv_pci_io_mem1_resource,
-	},
-	.config_addr	= MV64340_PCI_1_CONFIG_ADDR,
-	.config_vreg	= MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static __init int __init ja_pci_init(void)
-{
-	uint32_t enable;
-	extern int pci_probe_only;
-
-	/* PMON will assign PCI resources */
-	pci_probe_only = 1;
-
-	enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
-	/*
-	 * We require at least one enabled I/O or PCI memory window or we
-	 * will ignore this PCI bus.  We ignore PCI windows 1, 2 and 3.
-	 */
-	if (enable & (0x01 <<  9) || enable & (0x01 << 10))
-		register_pci_controller(&mv_bus0_controller.pcic);
-
-	if (enable & (0x01 << 14) || enable & (0x01 << 15))
-		register_pci_controller(&mv_bus1_controller.pcic);
-
-	ioport_resource.end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE +
-					OCELOT_3_PCI_IO_1_SIZE - 1;
-
-	iomem_resource.end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE +
-					OCELOT_3_PCI_MEM_1_SIZE - 1;
-
-	set_io_port_base(OCELOT_3_PCI_IO_0_START); /* mips_io_port_base */
-
-	return 0;
-}
-
-arch_initcall(ja_pci_init);
-
-void __init plat_mem_setup(void)
-{
-	unsigned int tmpword;
-
-	board_time_init = momenco_time_init;
-
-	_machine_restart = momenco_ocelot_restart;
-	_machine_halt = momenco_ocelot_halt;
-	pm_power_off = momenco_ocelot_power_off;
-
-	/* Wired TLB entries */
-	setup_wired_tlb_entries();
-
-	/* shut down ethernet ports, just to be sure our memory doesn't get
-	 * corrupted by random ethernet traffic.
-	 */
-	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
-	do {}
-	  while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
-	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
-		 MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
-	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
-		 MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
-
-	/* Turn off the Bit-Error LED */
-	OCELOT_FPGA_WRITE(0x80, CLR);
-
-	tmpword = OCELOT_FPGA_READ(BOARDREV);
-	if (tmpword < 26)
-		printk("Momenco Ocelot-3: Board Assembly Rev. %c\n",
-			'A'+tmpword);
-	else
-		printk("Momenco Ocelot-3: Board Assembly Revision #0x%x\n",
-			tmpword);
-
-	tmpword = OCELOT_FPGA_READ(FPGA_REV);
-	printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
-	tmpword = OCELOT_FPGA_READ(RESET_STATUS);
-	printk("Reset reason: 0x%x\n", tmpword);
-	switch (tmpword) {
-		case 0x1:
-			printk("  - Power-up reset\n");
-			break;
-		case 0x2:
-			printk("  - Push-button reset\n");
-			break;
-		case 0x4:
-			printk("  - cPCI bus reset\n");
-			break;
-		case 0x8:
-			printk("  - Watchdog reset\n");
-			break;
-		case 0x10:
-			printk("  - Software reset\n");
-			break;
-		default:
-			printk("  - Unknown reset cause\n");
-	}
-	reset_reason = tmpword;
-	OCELOT_FPGA_WRITE(0xff, RESET_STATUS);
-
-	tmpword = OCELOT_FPGA_READ(CPCI_ID);
-	printk("cPCI ID register: 0x%02x\n", tmpword);
-	printk("  - Slot number: %d\n", tmpword & 0x1f);
-	printk("  - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no");
-	printk("  - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no");
-
-	tmpword = OCELOT_FPGA_READ(BOARD_STATUS);
-	printk("Board Status register: 0x%02x\n", tmpword);
-	printk("  - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
-	printk("  - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
-	printk("  - L3 cache size: %d MB\n", (1<<((tmpword&12) >> 2))&~1);
-
-	/* Support for 128 MB memory */
-	add_memory_region(0x0, 0x08000000, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile
deleted file mode 100644
index d69161a..0000000
--- a/arch/mips/momentum/ocelot_c/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for Momentum Computer's Ocelot-C and -CS boards.
-#
-
-obj-y	 		+= cpci-irq.o irq.o platform.o prom.o reset.o \
-			   setup.o uart-irq.o
-
-obj-$(CONFIG_KGDB)	+= dbg_io.o
diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c
deleted file mode 100644
index 186a140..0000000
--- a/arch/mips/momentum/ocelot_c/cpci-irq.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- *
- * arch/mips/momentum/ocelot_c/cpci-irq.c
- *     Interrupt routines for cpci.  Interrupt numbers are assigned from
- *     CPCI_IRQ_BASE to CPCI_IRQ_BASE+8 (8 interrupt sources).
- *
- * Note that the high-level software will need to be careful about using
- * these interrupts.  If this board is asserting a cPCI interrupt, it will
- * also see the asserted interrupt.  Care must be taken to avoid an
- * interrupt flood.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/io.h>
-#include "ocelot_c_fpga.h"
-
-#define CPCI_IRQ_BASE	8
-
-static inline int ls1bit8(unsigned int x)
-{
-        int b = 7, s;
-
-        s =  4; if (((unsigned char)(x <<  4)) == 0) s = 0; b -= s; x <<= s;
-        s =  2; if (((unsigned char)(x <<  2)) == 0) s = 0; b -= s; x <<= s;
-        s =  1; if (((unsigned char)(x <<  1)) == 0) s = 0; b -= s;
-
-        return b;
-}
-
-/* mask off an interrupt -- 0 is enable, 1 is disable */
-static inline void mask_cpci_irq(unsigned int irq)
-{
-	uint32_t value;
-
-	value = OCELOT_FPGA_READ(INTMASK);
-	value |= 1 << (irq - CPCI_IRQ_BASE);
-	OCELOT_FPGA_WRITE(value, INTMASK);
-
-	/* read the value back to assure that it's really been written */
-	value = OCELOT_FPGA_READ(INTMASK);
-}
-
-/* unmask an interrupt -- 0 is enable, 1 is disable */
-static inline void unmask_cpci_irq(unsigned int irq)
-{
-	uint32_t value;
-
-	value = OCELOT_FPGA_READ(INTMASK);
-	value &= ~(1 << (irq - CPCI_IRQ_BASE));
-	OCELOT_FPGA_WRITE(value, INTMASK);
-
-	/* read the value back to assure that it's really been written */
-	value = OCELOT_FPGA_READ(INTMASK);
-}
-
-/*
- * Interrupt handler for interrupts coming from the FPGA chip.
- * It could be built in ethernet ports etc...
- */
-void ll_cpci_irq(void)
-{
-	unsigned int irq_src, irq_mask;
-
-	/* read the interrupt status registers */
-	irq_src = OCELOT_FPGA_READ(INTSTAT);
-	irq_mask = OCELOT_FPGA_READ(INTMASK);
-
-	/* mask for just the interrupts we want */
-	irq_src &= ~irq_mask;
-
-	do_IRQ(ls1bit8(irq_src) + CPCI_IRQ_BASE);
-}
-
-struct irq_chip cpci_irq_type = {
-	.name = "CPCI/FPGA",
-	.ack = mask_cpci_irq,
-	.mask = mask_cpci_irq,
-	.mask_ack = mask_cpci_irq,
-	.unmask = unmask_cpci_irq,
-};
-
-void cpci_irq_init(void)
-{
-	int i;
-
-	for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++)
-		set_irq_chip_and_handler(i, &cpci_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/momentum/ocelot_c/dbg_io.c b/arch/mips/momentum/ocelot_c/dbg_io.c
deleted file mode 100644
index 32d6fb4..0000000
--- a/arch/mips/momentum/ocelot_c/dbg_io.c
+++ /dev/null
@@ -1,121 +0,0 @@
-
-#include <asm/serial.h> /* For the serial port location and base baud */
-
-/* --- CONFIG --- */
-
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-
-/* --- END OF CONFIG --- */
-
-#define         UART16550_BAUD_2400             2400
-#define         UART16550_BAUD_4800             4800
-#define         UART16550_BAUD_9600             9600
-#define         UART16550_BAUD_19200            19200
-#define         UART16550_BAUD_38400            38400
-#define         UART16550_BAUD_57600            57600
-#define         UART16550_BAUD_115200           115200
-
-#define         UART16550_PARITY_NONE           0
-#define         UART16550_PARITY_ODD            0x08
-#define         UART16550_PARITY_EVEN           0x18
-#define         UART16550_PARITY_MARK           0x28
-#define         UART16550_PARITY_SPACE          0x38
-
-#define         UART16550_DATA_5BIT             0x0
-#define         UART16550_DATA_6BIT             0x1
-#define         UART16550_DATA_7BIT             0x2
-#define         UART16550_DATA_8BIT             0x3
-
-#define         UART16550_STOP_1BIT             0x0
-#define         UART16550_STOP_2BIT             0x4
-
-/* ----------------------------------------------------- */
-
-/* === CONFIG === */
-
-/* [jsun] we use the second serial port for kdb */
-#define         BASE                    OCELOT_SERIAL1_BASE
-#define         MAX_BAUD                OCELOT_BASE_BAUD
-
-/* === END OF CONFIG === */
-
-#define         REG_OFFSET              4
-
-/* register offset */
-#define         OFS_RCV_BUFFER          0
-#define         OFS_TRANS_HOLD          0
-#define         OFS_SEND_BUFFER         0
-#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
-#define         OFS_INTR_ID             (2*REG_OFFSET)
-#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
-#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
-#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
-#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
-#define         OFS_LINE_STATUS         (5*REG_OFFSET)
-#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
-#define         OFS_RS232_INPUT         (6*REG_OFFSET)
-#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
-
-#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
-#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
-
-
-/* memory-mapped read/write of the port */
-#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
-#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
-
-void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
-{
-	/* disable interrupts */
-	UART16550_WRITE(OFS_INTR_ENABLE, 0);
-
-	/* set up baud rate */
-	{
-		uint32 divisor;
-
-		/* set DIAB bit */
-		UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-
-		/* set divisor */
-		divisor = MAX_BAUD / baud;
-		UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
-		UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
-
-		/* clear DIAB bit */
-		UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
-	}
-
-	/* set data format */
-	UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-}
-
-static int remoteDebugInitialized = 0;
-
-uint8 getDebugChar(void)
-{
-	if (!remoteDebugInitialized) {
-		remoteDebugInitialized = 1;
-		debugInit(UART16550_BAUD_38400,
-			  UART16550_DATA_8BIT,
-			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-	}
-
-	while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
-	return UART16550_READ(OFS_RCV_BUFFER);
-}
-
-
-int putDebugChar(uint8 byte)
-{
-	if (!remoteDebugInitialized) {
-		remoteDebugInitialized = 1;
-		debugInit(UART16550_BAUD_38400,
-			  UART16550_DATA_8BIT,
-			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-	}
-
-	while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
-	UART16550_WRITE(OFS_SEND_BUFFER, byte);
-	return 1;
-}
diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c
deleted file mode 100644
index 844d566..0000000
--- a/arch/mips/momentum/ocelot_c/irq.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <linux/mv643xx.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-
-extern void uart_irq_init(void);
-extern void cpci_irq_init(void);
-
-static struct irqaction cascade_fpga = {
-	no_action, IRQF_DISABLED, CPU_MASK_NONE, "cascade via FPGA", NULL, NULL
-};
-
-static struct irqaction cascade_mv64340 = {
-	no_action, IRQF_DISABLED, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL
-};
-
-extern void ll_uart_irq(void);
-extern void ll_cpci_irq(void);
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
-
-	if (pending & STATUSF_IP0)
-		do_IRQ(0);
-	else if (pending & STATUSF_IP1)
-		do_IRQ(1);
-	else if (pending & STATUSF_IP2)
-		do_IRQ(2);
-	else if (pending & STATUSF_IP3)
-		ll_uart_irq();
-	else if (pending & STATUSF_IP4)
-		do_IRQ(4);
-	else if (pending & STATUSF_IP5)
-		ll_cpci_irq();
-	else if (pending & STATUSF_IP6)
-		ll_mv64340_irq();
-	else if (pending & STATUSF_IP7)
-		do_IRQ(7);
-	else
-		spurious_interrupt();
-}
-
-void __init arch_init_irq(void)
-{
-	/*
-	 * Clear all of the interrupts while we change the able around a bit.
-	 * int-handler is not on bootstrap
-	 */
-	clear_c0_status(ST0_IM);
-
-	mips_cpu_irq_init();
-
-	/* set up the cascading interrupts */
-	setup_irq(3, &cascade_fpga);
-	setup_irq(5, &cascade_fpga);
-	setup_irq(6, &cascade_mv64340);
-
-	mv64340_irq_init(16);
-	uart_irq_init();
-	cpci_irq_init();
-}
diff --git a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h
deleted file mode 100644
index f0f5581..0000000
--- a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Ocelot-C Board Register Definitions
- *
- * (C) 2002 Momentum Computer Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Louis Hamilton, Red Hat, Inc.
- *    hamilton@redhat.com  [MIPS64 modifications]
- */
-
-#ifndef __OCELOT_C_FPGA_H__
-#define __OCELOT_C_FPGA_H__
-
-
-#ifdef CONFIG_64BIT
-#define OCELOT_C_CS0_ADDR       (0xfffffffffc000000)
-#else
-#define OCELOT_C_CS0_ADDR               (0xfc000000)
-#endif
-
-#define OCELOT_C_REG_BOARDREV		0x0
-#define OCELOT_C_REG_FPGA_REV		0x1
-#define OCELOT_C_REG_FPGA_TYPE		0x2
-#define OCELOT_C_REG_RESET_STATUS	0x3
-#define OCELOT_C_REG_BOARD_STATUS	0x4
-#define OCELOT_C_REG_CPCI_ID		0x5
-#define OCELOT_C_REG_SET		0x6
-#define OCELOT_C_REG_CLR		0x7
-#define OCELOT_C_REG_EEPROM_MODE	0x9
-#define OCELOT_C_REG_INTMASK		0xa
-#define OCELOT_C_REG_INTSTAT		0xb
-#define OCELOT_C_REG_UART_INTMASK	0xc
-#define OCELOT_C_REG_UART_INTSTAT	0xd
-#define OCELOT_C_REG_INTSET		0xe
-#define OCELOT_C_REG_INTCLR		0xf
-
-#define __FPGA_REG_TO_ADDR(reg)						\
-	((void *) OCELOT_C_CS0_ADDR + OCELOT_C_REG_##reg)
-#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
-#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
-
-#endif
diff --git a/arch/mips/momentum/ocelot_c/platform.c b/arch/mips/momentum/ocelot_c/platform.c
deleted file mode 100644
index 7780aa0..0000000
--- a/arch/mips/momentum/ocelot_c/platform.c
+++ /dev/null
@@ -1,183 +0,0 @@
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/mv643xx.h>
-#include <linux/platform_device.h>
-
-#include "ocelot_c_fpga.h"
-
-#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
-
-static struct resource mv643xx_eth_shared_resources[] = {
-	[0] = {
-		.name   = "ethernet shared base",
-		.start  = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
-		.end    = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
-		                       MV643XX_ETH_SHARED_REGS_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
-	.name		= MV643XX_ETH_SHARED_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv643xx_eth_shared_resources),
-	.resource	= mv643xx_eth_shared_resources,
-};
-
-#define MV_SRAM_BASE			0xfe000000UL
-#define MV_SRAM_SIZE			(256 * 1024)
-
-#define MV_SRAM_RXRING_SIZE		(MV_SRAM_SIZE / 4)
-#define MV_SRAM_TXRING_SIZE		(MV_SRAM_SIZE / 4)
-
-#define MV_SRAM_BASE_ETH0		MV_SRAM_BASE
-#define MV_SRAM_BASE_ETH1		(MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
-
-#define MV64x60_IRQ_ETH_0 48
-#define MV64x60_IRQ_ETH_1 49
-
-static struct resource mv64x60_eth0_resources[] = {
-	[0] = {
-		.name	= "eth0 irq",
-		.start	= MV64x60_IRQ_ETH_0,
-		.end	= MV64x60_IRQ_ETH_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth0_pd = {
-	.port_number	= 0,
-
-	.tx_sram_addr	= MV_SRAM_BASE_ETH0,
-	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
-	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
-
-	.rx_sram_addr	= MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
-	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
-	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth0_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth0_resources),
-	.resource	= mv64x60_eth0_resources,
-	.dev = {
-		.platform_data = &eth0_pd,
-	},
-};
-
-static struct resource mv64x60_eth1_resources[] = {
-	[0] = {
-		.name	= "eth1 irq",
-		.start	= MV64x60_IRQ_ETH_1,
-		.end	= MV64x60_IRQ_ETH_1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
-	.port_number	= 1,
-
-	.tx_sram_addr	= MV_SRAM_BASE_ETH1,
-	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
-	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
-
-	.rx_sram_addr	= MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
-	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
-	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth1_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth1_resources),
-	.resource	= mv64x60_eth1_resources,
-	.dev = {
-		.platform_data = &eth1_pd,
-	},
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
-	&mv643xx_eth_shared_device,
-	&eth0_device,
-	&eth1_device,
-	/* The third port is not wired up on the Ocelot C */
-};
-
-static u8 __init exchange_bit(u8 val, u8 cs)
-{
-	/* place the data */
-	OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
-	udelay(1);
-
-	/* turn the clock on */
-	OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
-	udelay(1);
-
-	/* turn the clock off and read-strobe */
-	OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
-	/* return the data */
-	return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
-}
-
-static void __init get_mac(char dest[6])
-{
-	u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	int i,j;
-
-	for (i = 0; i < 12; i++)
-		exchange_bit(read_opcode[i], 1);
-
-	for (j = 0; j < 6; j++) {
-		dest[j] = 0;
-		for (i = 0; i < 8; i++) {
-			dest[j] <<= 1;
-			dest[j] |= exchange_bit(0, 1);
-		}
-	}
-
-	/* turn off CS */
-	exchange_bit(0,0);
-}
-
-/*
- * Copy and increment ethernet MAC address by a small value.
- *
- * This is useful for systems where the only one MAC address is stored in
- * non-volatile memory for multiple ports.
- */
-static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
-	unsigned int add)
-{
-	int i;
-
-	BUG_ON(add >= 256);
-
-	for (i = ETH_ALEN; i >= 0; i--) {
-		dst[i] = src[i] + add;
-		add = dst[i] < src[i];		/* compute carry */
-	}
-
-	WARN_ON(add);
-}
-
-static int __init mv643xx_eth_add_pds(void)
-{
-	unsigned char mac[ETH_ALEN];
-	int ret;
-
-	get_mac(mac);
-	eth_mac_add(eth0_pd.mac_addr, mac, 0);
-	eth_mac_add(eth1_pd.mac_addr, mac, 1);
-	ret = platform_add_devices(mv643xx_eth_pd_devs,
-			ARRAY_SIZE(mv643xx_eth_pd_devs));
-
-	return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
-
-#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c
deleted file mode 100644
index b689cee..0000000
--- a/arch/mips/momentum/ocelot_c/prom.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- *   hamilton@redhat.com  [MIPS64 modifications]
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-
-#include "ocelot_c_fpga.h"
-
-struct callvectors* debug_vectors;
-
-extern unsigned long marvell_base;
-extern unsigned int cpu_clock;
-
-const char *get_system_type(void)
-{
-#ifdef CONFIG_CPU_SR71000
-	return "Momentum Ocelot-CS";
-#else
-	return "Momentum Ocelot-C";
-#endif
-}
-
-#ifdef CONFIG_64BIT
-
-unsigned long signext(unsigned long addr)
-{
-  addr &= 0xffffffff;
-  return (unsigned long)((int)addr);
-}
-
-void *get_arg(unsigned long args, int arc)
-{
-  unsigned long ul;
-  unsigned char *puc, uc;
-
-  args += (arc * 4);
-  ul = (unsigned long)signext(args);
-  puc = (unsigned char *)ul;
-  if (puc == 0)
-    return (void *)0;
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
-  uc = *puc++;
-  ul = (unsigned long)uc;
-  uc = *puc++;
-  ul |= (((unsigned long)uc) << 8);
-  uc = *puc++;
-  ul |= (((unsigned long)uc) << 16);
-  uc = *puc++;
-  ul |= (((unsigned long)uc) << 24);
-#else  /* CONFIG_CPU_LITTLE_ENDIAN */
-  uc = *puc++;
-  ul = ((unsigned long)uc) << 24;
-  uc = *puc++;
-  ul |= (((unsigned long)uc) << 16);
-  uc = *puc++;
-  ul |= (((unsigned long)uc) << 8);
-  uc = *puc++;
-  ul |= ((unsigned long)uc);
-#endif  /* CONFIG_CPU_LITTLE_ENDIAN */
-  ul = signext(ul);
-  return (void *)ul;
-}
-
-char *arg64(unsigned long addrin, int arg_index)
-{
-  unsigned long args;
-  char *p;
-  args = signext(addrin);
-  p = (char *)get_arg(args, arg_index);
-  return p;
-}
-#endif  /* CONFIG_64BIT */
-
-
-void __init prom_init(void)
-{
-	int argc = fw_arg0;
-	char **arg = (char **) fw_arg1;
-	char **env = (char **) fw_arg2;
-	struct callvectors *cv = (struct callvectors *) fw_arg3;
-	int i;
-
-#ifdef CONFIG_64BIT
-	char *ptr;
-
-	printk("prom_init - MIPS64\n");
-	/* save the PROM vectors for debugging use */
-	debug_vectors = (struct callvectors *)signext((unsigned long)cv);
-
-	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
-
-	for (i = 1; i < argc; i++) {
-		ptr = (char *)arg64((unsigned long)arg, i);
-		if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
-		    sizeof(arcs_cmdline))
-			break;
-		strcat(arcs_cmdline, ptr);
-		strcat(arcs_cmdline, " ");
-	}
-	i = 0;
-	while (1) {
-		ptr = (char *)arg64((unsigned long)env, i);
-		if (! ptr)
-			break;
-
-		if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
-			marvell_base = simple_strtol(ptr + strlen("gtbase="),
-							NULL, 16);
-
-			if ((marvell_base & 0xffffffff00000000) == 0)
-				marvell_base |= 0xffffffff00000000;
-
-			printk("marvell_base set to 0x%016lx\n", marvell_base);
-		}
-		if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
-			cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
-							NULL, 10);
-			printk("cpu_clock set to %d\n", cpu_clock);
-		}
-		i++;
-	}
-	printk("arcs_cmdline: %s\n", arcs_cmdline);
-
-#else   /* CONFIG_64BIT */
-	/* save the PROM vectors for debugging use */
-	debug_vectors = cv;
-
-	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
-	for (i = 1; i < argc; i++) {
-		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
-		    >= sizeof(arcs_cmdline))
-			break;
-		strcat(arcs_cmdline, arg[i]);
-		strcat(arcs_cmdline, " ");
-	}
-
-	while (*env) {
-		if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
-			marvell_base = simple_strtol(*env + strlen("gtbase="),
-							NULL, 16);
-		}
-		if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
-			cpu_clock = simple_strtol(*env + strlen("cpuclock="),
-							NULL, 10);
-		}
-		env++;
-	}
-#endif /* CONFIG_64BIT */
-
-	mips_machgroup = MACH_GROUP_MOMENCO;
-	mips_machtype = MACH_MOMENCO_OCELOT_C;
-
-#ifndef CONFIG_64BIT
-	debug_vectors->printf("Booting Linux kernel...\n");
-#endif
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
diff --git a/arch/mips/momentum/ocelot_c/reset.c b/arch/mips/momentum/ocelot_c/reset.c
deleted file mode 100644
index 3fdcb64..0000000
--- a/arch/mips/momentum/ocelot_c/reset.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 2001 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com  [MIPS64 modifications]
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <linux/delay.h>
-
-void momenco_ocelot_restart(char *command)
-{
-	/* base address of timekeeper portion of part */
-	void *nvram = (void *)
-#ifdef CONFIG_64BIT
-		0xfffffffffc807000;
-#else
-		0xfc807000;
-#endif
-
-	/* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
-	writeb(0x84, nvram + 0xff7);
-
-	/* wait for the watchdog to go off */
-	mdelay(100+(1000/16));
-
-	/* if the watchdog fails for some reason, let people know */
-	printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_ocelot_halt(void)
-{
-	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
-	while (1)
-		__asm__(".set\tmips3\n\t"
-	                "wait\n\t"
-			".set\tmips0");
-}
-
-void momenco_ocelot_power_off(void)
-{
-	momenco_ocelot_halt();
-}
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
deleted file mode 100644
index 0b6b233..0000000
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Ocelot-C and -CS board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 2001  Ralf Baechle
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- *   mdharm@momenco.com
- *
- * Louis Hamilton, Red Hat, Inc.
- *   hamilton@redhat.com  [MIPS64 modifications]
- *
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/bcd.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/pm.h>
-#include <linux/timex.h>
-#include <linux/vmalloc.h>
-#include <linux/mv643xx.h>
-
-#include <asm/time.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/marvell.h>
-#include <linux/bootmem.h>
-#include <linux/blkdev.h>
-#include "ocelot_c_fpga.h"
-
-unsigned long marvell_base;
-unsigned int cpu_clock;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_ocelot_restart(char *command);
-extern void momenco_ocelot_halt(void);
-extern void momenco_ocelot_power_off(void);
-
-void momenco_time_init(void);
-
-static char reset_reason;
-
-void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask);
-
-static unsigned long ENTRYLO(unsigned long paddr)
-{
-	return ((paddr & PAGE_MASK) |
-	       (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
-		_CACHE_UNCACHED)) >> 6;
-}
-
-/* setup code for a handoff from a version 2 PMON 2000 PROM */
-void PMON_v2_setup(void)
-{
-	/* Some wired TLB entries for the MV64340 and perhiperals. The
-	   MV64340 is going to be hit on every IRQ anyway - there's
-	   absolutely no point in letting it be a random TLB entry, as
-	   it'll just cause needless churning of the TLB. And we use
-	   the other half for the serial port, which is just a PITA
-	   otherwise :)
-
-		Device			Physical	Virtual
-		MV64340 Internal Regs	0xf4000000	0xf4000000
-		Ocelot-C[S] PLD (CS0)	0xfc000000	0xfc000000
-		NVRAM (CS1)		0xfc800000	0xfc800000
-		UARTs (CS2)		0xfd000000	0xfd000000
-		Internal SRAM		0xfe000000	0xfe000000
-		M-Systems DOC (CS3)	0xff000000	0xff000000
-	*/
-  printk("PMON_v2_setup\n");
-
-#ifdef CONFIG_64BIT
-	/* marvell and extra space */
-	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xfffffffff4000000, PM_64K);
-	/* fpga, rtc, and uart */
-	add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfffffffffc000000, PM_16M);
-	/* m-sys and internal SRAM */
-	add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M);
-
-	marvell_base = 0xfffffffff4000000;
-#else
-	/* marvell and extra space */
-	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K);
-	/* fpga, rtc, and uart */
-	add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfc000000, PM_16M);
-	/* m-sys and internal SRAM */
-	add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M);
-
-	marvell_base = 0xf4000000;
-#endif
-}
-
-unsigned long m48t37y_get_time(void)
-{
-#ifdef CONFIG_64BIT
-	unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000;
-#else
-	unsigned char* rtc_base = (unsigned char*)0xfc800000;
-#endif
-	unsigned int year, month, day, hour, min, sec;
-	unsigned long flags;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	/* stop the update */
-	rtc_base[0x7ff8] = 0x40;
-
-	year = BCD2BIN(rtc_base[0x7fff]);
-	year += BCD2BIN(rtc_base[0x7ff1]) * 100;
-
-	month = BCD2BIN(rtc_base[0x7ffe]);
-
-	day = BCD2BIN(rtc_base[0x7ffd]);
-
-	hour = BCD2BIN(rtc_base[0x7ffb]);
-	min = BCD2BIN(rtc_base[0x7ffa]);
-	sec = BCD2BIN(rtc_base[0x7ff9]);
-
-	/* start the update */
-	rtc_base[0x7ff8] = 0x00;
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return mktime(year, month, day, hour, min, sec);
-}
-
-int m48t37y_set_time(unsigned long sec)
-{
-#ifdef CONFIG_64BIT
-	unsigned char* rtc_base = (unsigned char*)0xfffffffffc800000;
-#else
-	unsigned char* rtc_base = (unsigned char*)0xfc800000;
-#endif
-	struct rtc_time tm;
-	unsigned long flags;
-
-	/* convert to a more useful format -- note months count from 0 */
-	to_tm(sec, &tm);
-	tm.tm_mon += 1;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	/* enable writing */
-	rtc_base[0x7ff8] = 0x80;
-
-	/* year */
-	rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
-	rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
-
-	/* month */
-	rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
-
-	/* day */
-	rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
-
-	/* hour/min/sec */
-	rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
-	rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
-	rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
-
-	/* day of week -- not really used, but let's keep it up-to-date */
-	rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
-
-	/* disable writing */
-	rtc_base[0x7ff8] = 0x00;
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return 0;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
-	setup_irq(7, irq);
-}
-
-void momenco_time_init(void)
-{
-#ifdef CONFIG_CPU_SR71000
-	mips_hpt_frequency = cpu_clock;
-#elif defined(CONFIG_CPU_RM7000)
-	mips_hpt_frequency = cpu_clock / 2;
-#else
-#error Unknown CPU for this board
-#endif
-	printk("momenco_time_init cpu_clock=%d\n", cpu_clock);
-
-	rtc_mips_get_time = m48t37y_get_time;
-	rtc_mips_set_time = m48t37y_set_time;
-}
-
-void __init plat_mem_setup(void)
-{
-	unsigned int tmpword;
-
-	board_time_init = momenco_time_init;
-
-	_machine_restart = momenco_ocelot_restart;
-	_machine_halt = momenco_ocelot_halt;
-	pm_power_off = momenco_ocelot_power_off;
-
-	/*
-	 * initrd_start = (unsigned long)ocelot_initrd_start;
-	 * initrd_end = (unsigned long)ocelot_initrd_start + (ulong)ocelot_initrd_size;
-	 * initrd_below_start_ok = 1;
-	 */
-
-	/* do handoff reconfiguration */
-	PMON_v2_setup();
-
-	/* shut down ethernet ports, just to be sure our memory doesn't get
-	 * corrupted by random ethernet traffic.
-	 */
-	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
-	do {}
-	  while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
-	do {}
-	  while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
-	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
-	         MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
-	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
-	         MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
-
-	/* Turn off the Bit-Error LED */
-	OCELOT_FPGA_WRITE(0x80, CLR);
-
-	tmpword = OCELOT_FPGA_READ(BOARDREV);
-#ifdef CONFIG_CPU_SR71000
-	if (tmpword < 26)
-		printk("Momenco Ocelot-CS: Board Assembly Rev. %c\n",
-			'A'+tmpword);
-	else
-		printk("Momenco Ocelot-CS: Board Assembly Revision #0x%x\n",
-			tmpword);
-#else
-	if (tmpword < 26)
-		printk("Momenco Ocelot-C: Board Assembly Rev. %c\n",
-			'A'+tmpword);
-	else
-		printk("Momenco Ocelot-C: Board Assembly Revision #0x%x\n",
-			tmpword);
-#endif
-
-	tmpword = OCELOT_FPGA_READ(FPGA_REV);
-	printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
-	tmpword = OCELOT_FPGA_READ(RESET_STATUS);
-	printk("Reset reason: 0x%x\n", tmpword);
-	switch (tmpword) {
-		case 0x1:
-			printk("  - Power-up reset\n");
-			break;
-		case 0x2:
-			printk("  - Push-button reset\n");
-			break;
-		case 0x4:
-			printk("  - cPCI bus reset\n");
-			break;
-		case 0x8:
-			printk("  - Watchdog reset\n");
-			break;
-		case 0x10:
-			printk("  - Software reset\n");
-			break;
-		default:
-			printk("  - Unknown reset cause\n");
-	}
-	reset_reason = tmpword;
-	OCELOT_FPGA_WRITE(0xff, RESET_STATUS);
-
-	tmpword = OCELOT_FPGA_READ(CPCI_ID);
-	printk("cPCI ID register: 0x%02x\n", tmpword);
-	printk("  - Slot number: %d\n", tmpword & 0x1f);
-	printk("  - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no");
-	printk("  - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no");
-
-	tmpword = OCELOT_FPGA_READ(BOARD_STATUS);
-	printk("Board Status register: 0x%02x\n", tmpword);
-	printk("  - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
-	printk("  - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
-	printk("  - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1);
-	printk("  - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3)));
-
-	switch(tmpword &3) {
-	case 3:
-		/* 512MiB */
-		add_memory_region(0x0, 0x200<<20, BOOT_MEM_RAM);
-		break;
-	case 2:
-		/* 256MiB */
-		add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM);
-		break;
-	case 1:
-		/* 128MiB */
-		add_memory_region(0x0,  0x80<<20, BOOT_MEM_RAM);
-		break;
-	case 0:
-		/* 1GiB -- needs CONFIG_HIGHMEM */
-		add_memory_region(0x0, 0x400<<20, BOOT_MEM_RAM);
-		break;
-	}
-}
-
-/*
- * This needs to be one of the first initcalls, because no I/O port access
- * can work before this
- */
-static int io_base_ioremap(void)
-{
-	void __iomem * io_remap_range = ioremap(0xc0000000UL, 0x10000);
-
-	if (!io_remap_range)
-		panic("Could not ioremap I/O port range");
-
-	set_io_port_base((unsigned long) io_remap_range);
-
-	return 0;
-}
-
-module_init(io_base_ioremap);
diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c
deleted file mode 100644
index de1a31e..0000000
--- a/arch/mips/momentum/ocelot_c/uart-irq.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- *
- * arch/mips/momentum/ocelot_c/uart-irq.c
- *     Interrupt routines for UARTs.  Interrupt numbers are assigned from
- *     80 to 81 (2 interrupt sources).
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include "ocelot_c_fpga.h"
-
-static inline int ls1bit8(unsigned int x)
-{
-        int b = 7, s;
-
-        s =  4; if (((unsigned char)(x << 4)) == 0) s = 0; b -= s; x <<= s;
-        s =  2; if (((unsigned char)(x << 2)) == 0) s = 0; b -= s; x <<= s;
-        s =  1; if (((unsigned char)(x << 1)) == 0) s = 0; b -= s;
-
-        return b;
-}
-
-/* mask off an interrupt -- 0 is enable, 1 is disable */
-static inline void mask_uart_irq(unsigned int irq)
-{
-	uint8_t value;
-
-	value = OCELOT_FPGA_READ(UART_INTMASK);
-	value |= 1 << (irq - 74);
-	OCELOT_FPGA_WRITE(value, UART_INTMASK);
-
-	/* read the value back to assure that it's really been written */
-	value = OCELOT_FPGA_READ(UART_INTMASK);
-}
-
-/* unmask an interrupt -- 0 is enable, 1 is disable */
-static inline void unmask_uart_irq(unsigned int irq)
-{
-	uint8_t value;
-
-	value = OCELOT_FPGA_READ(UART_INTMASK);
-	value &= ~(1 << (irq - 74));
-	OCELOT_FPGA_WRITE(value, UART_INTMASK);
-
-	/* read the value back to assure that it's really been written */
-	value = OCELOT_FPGA_READ(UART_INTMASK);
-}
-
-/*
- * Interrupt handler for interrupts coming from the FPGA chip.
- */
-void ll_uart_irq(void)
-{
-	unsigned int irq_src, irq_mask;
-
-	/* read the interrupt status registers */
-	irq_src = OCELOT_FPGA_READ(UART_INTSTAT);
-	irq_mask = OCELOT_FPGA_READ(UART_INTMASK);
-
-	/* mask for just the interrupts we want */
-	irq_src &= ~irq_mask;
-
-	do_IRQ(ls1bit8(irq_src) + 74);
-}
-
-struct irq_chip uart_irq_type = {
-	.name = "UART/FPGA",
-	.ack = mask_uart_irq,
-	.mask = mask_uart_irq,
-	.mask_ack = mask_uart_irq,
-	.unmask = unmask_uart_irq,
-};
-
-void uart_irq_init(void)
-{
-	set_irq_chip_and_handler(80, &uart_irq_type, handle_level_irq);
-	set_irq_chip_and_handler(81, &uart_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index aba3dbf..f26ede0 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -9,9 +9,7 @@
 #
 obj-$(CONFIG_MIPS_BONITO64)	+= ops-bonito64.o
 obj-$(CONFIG_PCI_GT64XXX_PCI0)	+= ops-gt64xxx_pci0.o
-obj-$(CONFIG_PCI_MARVELL)	+= ops-marvell.o
 obj-$(CONFIG_MIPS_MSC)		+= ops-msc.o
-obj-$(CONFIG_MIPS_NILE4)	+= ops-nile4.o
 obj-$(CONFIG_MIPS_TX3927)	+= ops-tx3927.o
 obj-$(CONFIG_PCI_VR41XX)	+= ops-vr41xx.o pci-vr41xx.o
 obj-$(CONFIG_NEC_CMBVR4133)	+= fixup-vr4133.o
@@ -22,17 +20,17 @@
 #
 obj-$(CONFIG_BASLER_EXCITE)	+= ops-titan.o pci-excite.o fixup-excite.o
 obj-$(CONFIG_DDB5477)		+= fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o
-obj-$(CONFIG_LASAT)		+= pci-lasat.o
 obj-$(CONFIG_MIPS_ATLAS)	+= fixup-atlas.o
 obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o
-obj-$(CONFIG_MIPS_EV64120)	+= pci-ev64120.o
 obj-$(CONFIG_SOC_AU1500)	+= fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_AU1550)	+= fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_PNX8550)	+= fixup-pnx8550.o ops-pnx8550.o
+obj-$(CONFIG_LEMOTE_FULONG)	+= fixup-lm2e.o ops-bonito64.o
 obj-$(CONFIG_MIPS_MALTA)	+= fixup-malta.o
 obj-$(CONFIG_MOMENCO_OCELOT)	+= fixup-ocelot.o pci-ocelot.o
-obj-$(CONFIG_MOMENCO_OCELOT_3)	+= fixup-ocelot3.o
-obj-$(CONFIG_MOMENCO_OCELOT_C)	+= fixup-ocelot-c.o pci-ocelot-c.o
+obj-$(CONFIG_PMC_MSP7120_GW)	+= fixup-pmcmsp.o ops-pmcmsp.o
+obj-$(CONFIG_PMC_MSP7120_EVAL)	+= fixup-pmcmsp.o ops-pmcmsp.o
+obj-$(CONFIG_PMC_MSP7120_FPGA)	+= fixup-pmcmsp.o ops-pmcmsp.o
 obj-$(CONFIG_PMC_YOSEMITE)	+= fixup-yosemite.o ops-titan.o ops-titan-ht.o \
 				   pci-yosemite.o
 obj-$(CONFIG_SGI_IP27)		+= ops-bridge.o pci-ip27.o
diff --git a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c
index c6cd6e9..45224fd 100644
--- a/arch/mips/pci/fixup-atlas.c
+++ b/arch/mips/pci/fixup-atlas.c
@@ -58,7 +58,7 @@
 	{0,	0,	0,	0,	0 }	/* 21: Unused */
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_tab[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c
index c2f8304..ca0276c 100644
--- a/arch/mips/pci/fixup-au1000.c
+++ b/arch/mips/pci/fixup-au1000.c
@@ -35,7 +35,7 @@
 
 extern char irq_tab_alchemy[][5];
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_tab_alchemy[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c
index 1e53075..1416bca 100644
--- a/arch/mips/pci/fixup-capcella.c
+++ b/arch/mips/pci/fixup-capcella.c
@@ -38,7 +38,7 @@
  [14] = { -1, INTA, INTB, INTC, INTD }
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_tab_capcella[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index d57ffd7..7fc475f 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -161,7 +161,7 @@
   [COBALT_PCICONF_ETH1]    = COBALT_ETH1_IRQ
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (cobalt_board_id < COBALT_BRD_ID_QUBE2)
 		return irq_tab_qube1[slot];
diff --git a/arch/mips/pci/fixup-emma2rh.c b/arch/mips/pci/fixup-emma2rh.c
index 7abcfd1..a270589 100644
--- a/arch/mips/pci/fixup-emma2rh.c
+++ b/arch/mips/pci/fixup-emma2rh.c
@@ -89,7 +89,7 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH,
 			 emma2rh_pci_host_fixup);
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_map[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-excite.c b/arch/mips/pci/fixup-excite.c
index 1da696d..cd64d9f 100644
--- a/arch/mips/pci/fixup-excite.c
+++ b/arch/mips/pci/fixup-excite.c
@@ -21,7 +21,7 @@
 #include <linux/pci.h>
 #include <excite.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (pin == 0)
 		return -1;
diff --git a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c
index 3e66b0a..190fffd 100644
--- a/arch/mips/pci/fixup-ip32.c
+++ b/arch/mips/pci/fixup-ip32.c
@@ -39,7 +39,7 @@
  * irqs.  I suppose a device without a pin A will thank us for doing it
  * right if there exists such a broken piece of crap.
  */
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_tab_mace[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-jmr3927.c b/arch/mips/pci/fixup-jmr3927.c
index 73d1850..e974394 100644
--- a/arch/mips/pci/fixup-jmr3927.c
+++ b/arch/mips/pci/fixup-jmr3927.c
@@ -33,7 +33,7 @@
 
 #include <asm/jmr3927/jmr3927.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	unsigned char irq = pin;
 
diff --git a/arch/mips/pci/fixup-lm2e.c b/arch/mips/pci/fixup-lm2e.c
new file mode 100644
index 0000000..e18ae4f
--- /dev/null
+++ b/arch/mips/pci/fixup-lm2e.c
@@ -0,0 +1,242 @@
+/*
+ * fixup-lm2e.c
+ *
+ * Copyright (C) 2004 ICT CAS
+ * Author: Li xiaoyu, ICT CAS
+ *   lixy@ict.ac.cn
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/mips-boards/bonito64.h>
+
+/* South bridge slot number is set by the pci probe process */
+static u8 sb_slot = 5;
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq = 0;
+
+	if (slot == sb_slot) {
+		switch (PCI_FUNC(dev->devfn)) {
+		case 2:
+			irq = 10;
+			break;
+		case 3:
+			irq = 11;
+			break;
+		case 5:
+			irq = 9;
+			break;
+		}
+	} else {
+		irq = BONITO_IRQ_BASE + 25 + pin;
+	}
+	return irq;
+
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
+
+static void __init loongson2e_nec_fixup(struct pci_dev *pdev)
+{
+	unsigned int val;
+
+	/* Configues port 1, 2, 3, 4 to be validate*/
+	pci_read_config_dword(pdev, 0xe0, &val);
+	pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x4);
+
+	/* System clock is 48-MHz Oscillator. */
+	pci_write_config_dword(pdev, 0xe4, 1 << 5);
+}
+
+static void __init loongson2e_686b_func0_fixup(struct pci_dev *pdev)
+{
+	unsigned char c;
+
+	sb_slot = PCI_SLOT(pdev->devfn);
+
+	printk(KERN_INFO "via686b fix: ISA bridge\n");
+
+	/*  Enable I/O Recovery time */
+	pci_write_config_byte(pdev, 0x40, 0x08);
+
+	/*  Enable ISA refresh */
+	pci_write_config_byte(pdev, 0x41, 0x01);
+
+	/*  disable ISA line buffer */
+	pci_write_config_byte(pdev, 0x45, 0x00);
+
+	/*  Gate INTR, and flush line buffer */
+	pci_write_config_byte(pdev, 0x46, 0xe0);
+
+	/*  Disable PCI Delay Transaction, Enable EISA ports 4D0/4D1. */
+	/* pci_write_config_byte(pdev, 0x47, 0x20); */
+
+	/*
+	 *  enable PCI Delay Transaction, Enable EISA ports 4D0/4D1.
+	 *  enable time-out timer
+	 */
+	pci_write_config_byte(pdev, 0x47, 0xe6);
+
+	/*
+	 * enable level trigger on pci irqs: 9,10,11,13
+	 * important! without this PCI interrupts won't work
+	 */
+	outb(0x2e, 0x4d1);
+
+	/*  512 K PCI Decode */
+	pci_write_config_byte(pdev, 0x48, 0x01);
+
+	/*  Wait for PGNT before grant to ISA Master/DMA */
+	pci_write_config_byte(pdev, 0x4a, 0x84);
+
+	/*
+	 * Plug'n'Play
+	 *
+	 *  Parallel DRQ 3, Floppy DRQ 2 (default)
+	 */
+	pci_write_config_byte(pdev, 0x50, 0x0e);
+
+	/*
+	 * IRQ Routing for Floppy and Parallel port
+	 *
+	 *  IRQ 6 for floppy, IRQ 7 for parallel port
+	 */
+	pci_write_config_byte(pdev, 0x51, 0x76);
+
+	/* IRQ Routing for serial ports (take IRQ 3 and 4) */
+	pci_write_config_byte(pdev, 0x52, 0x34);
+
+	/*  All IRQ's level triggered. */
+	pci_write_config_byte(pdev, 0x54, 0x00);
+
+	/* route PIRQA-D irq */
+	pci_write_config_byte(pdev, 0x55, 0x90);	/* bit 7-4, PIRQA */
+	pci_write_config_byte(pdev, 0x56, 0xba);	/* bit 7-4, PIRQC; */
+							/* 3-0, PIRQB */
+	pci_write_config_byte(pdev, 0x57, 0xd0);	/* bit 7-4, PIRQD */
+
+	/* enable function 5/6, audio/modem */
+	pci_read_config_byte(pdev, 0x85, &c);
+	c &= ~(0x3 << 2);
+	pci_write_config_byte(pdev, 0x85, c);
+
+	printk(KERN_INFO"via686b fix: ISA bridge done\n");
+}
+
+static void __init loongson2e_686b_func1_fixup(struct pci_dev *pdev)
+{
+	printk(KERN_INFO"via686b fix: IDE\n");
+
+	/* Modify IDE controller setup */
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 48);
+	pci_write_config_byte(pdev, PCI_COMMAND,
+			      PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+			      PCI_COMMAND_MASTER);
+	pci_write_config_byte(pdev, 0x40, 0x0b);
+	/* legacy mode */
+	pci_write_config_byte(pdev, 0x42, 0x09);
+
+#if 1/* play safe, otherwise we may see notebook's usb keyboard lockup */
+	/* disable read prefetch/write post buffers */
+	pci_write_config_byte(pdev, 0x41, 0x02);
+
+	/* use 3/4 as fifo thresh hold  */
+	pci_write_config_byte(pdev, 0x43, 0x0a);
+	pci_write_config_byte(pdev, 0x44, 0x00);
+
+	pci_write_config_byte(pdev, 0x45, 0x00);
+#else
+	pci_write_config_byte(pdev, 0x41, 0xc2);
+	pci_write_config_byte(pdev, 0x43, 0x35);
+	pci_write_config_byte(pdev, 0x44, 0x1c);
+
+	pci_write_config_byte(pdev, 0x45, 0x10);
+#endif
+
+	printk(KERN_INFO"via686b fix: IDE done\n");
+}
+
+static void __init loongson2e_686b_func2_fixup(struct pci_dev *pdev)
+{
+	/* irq routing */
+	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 10);
+}
+
+static void __init loongson2e_686b_func3_fixup(struct pci_dev *pdev)
+{
+	/* irq routing */
+	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 11);
+}
+
+static void __init loongson2e_686b_func5_fixup(struct pci_dev *pdev)
+{
+	unsigned int val;
+	unsigned char c;
+
+	/* enable IO */
+	pci_write_config_byte(pdev, PCI_COMMAND,
+			      PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+			      PCI_COMMAND_MASTER);
+	pci_read_config_dword(pdev, 0x4, &val);
+	pci_write_config_dword(pdev, 0x4, val | 1);
+
+	/* route ac97 IRQ */
+	pci_write_config_byte(pdev, 0x3c, 9);
+
+	pci_read_config_byte(pdev, 0x8, &c);
+
+	/* link control: enable link & SGD PCM output */
+	pci_write_config_byte(pdev, 0x41, 0xcc);
+
+	/* disable game port, FM, midi, sb, enable write to reg2c-2f */
+	pci_write_config_byte(pdev, 0x42, 0x20);
+
+	/* we are using Avance logic codec */
+	pci_write_config_word(pdev, 0x2c, 0x1005);
+	pci_write_config_word(pdev, 0x2e, 0x4710);
+	pci_read_config_dword(pdev, 0x2c, &val);
+
+	pci_write_config_byte(pdev, 0x42, 0x0);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686,
+			 loongson2e_686b_func0_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
+			 loongson2e_686b_func1_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2,
+			 loongson2e_686b_func2_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3,
+			 loongson2e_686b_func3_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5,
+			 loongson2e_686b_func5_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+			 loongson2e_nec_fixup);
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
index bf2c41d..0f48498 100644
--- a/arch/mips/pci/fixup-malta.c
+++ b/arch/mips/pci/fixup-malta.c
@@ -36,7 +36,7 @@
 	{0,	PCID,	PCIA,	PCIB,	PCIC }	/* 21: PCI Slot 4 */
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int virq;
 	virq = irq_tab[slot][pin];
diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c
index 3c9ae41..5911596 100644
--- a/arch/mips/pci/fixup-mpc30x.c
+++ b/arch/mips/pci/fixup-mpc30x.c
@@ -34,7 +34,7 @@
  [29] = MQ200_IRQ,
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (slot == 30)
 		return internal_func_irqs[PCI_FUNC(dev->devfn)];
diff --git a/arch/mips/pci/fixup-ocelot-c.c b/arch/mips/pci/fixup-ocelot-c.c
deleted file mode 100644
index d454948..0000000
--- a/arch/mips/pci/fixup-ocelot-c.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Based on work for the Linux port to the Ocelot board, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * arch/mips/momentum/ocelot_g/pci.c
- *     Board-specific PCI routines for mv64340 controller.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int bus = dev->bus->number;
-
-	if (bus == 0 && slot == 1)
-		return 2;       /* PCI-X A */
-	if (bus == 1 && slot == 1)
-		return 12;      /* PCI-X B */
-	if (bus == 1 && slot == 2)
-		return 4;       /* PCI B */
-
-return 0;
-	panic("Whooops in pcibios_map_irq");
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
diff --git a/arch/mips/pci/fixup-ocelot3.c b/arch/mips/pci/fixup-ocelot3.c
deleted file mode 100644
index ececc03..0000000
--- a/arch/mips/pci/fixup-ocelot3.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 Montavista Software Inc.
- * Author: Manish Lachwani (mlachwani@mvista.com)
- *
- * Looking at the schematics for the Ocelot-3 board, there are
- * two PCI busses and each bus has two PCI slots.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/mipsregs.h>
-
-/*
- * Do platform specific device initialization at
- * pci_enable_device() time
- */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int bus = dev->bus->number;
-
-	if (bus == 0 && slot == 1)
-		return 2;	/* PCI-X A */
-	if (bus == 0 && slot == 2)
-		return 3;	/* PCI-X B */
-	if (bus == 1 && slot == 1)
-		return 4;	/* PCI A */
-	if (bus == 1 && slot == 2)
-		return 5;	/* PCI B */
-
-return 0;
-	panic("Whooops in pcibios_map_irq");
-}
diff --git a/arch/mips/pci/fixup-pmcmsp.c b/arch/mips/pci/fixup-pmcmsp.c
new file mode 100644
index 0000000..0026121
--- /dev/null
+++ b/arch/mips/pci/fixup-pmcmsp.c
@@ -0,0 +1,216 @@
+/*
+ * PMC-Sierra MSP board specific pci fixups.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Copyright 2005-2007 PMC-Sierra, Inc
+ *
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef CONFIG_PCI
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/byteorder.h>
+
+#include <msp_pci.h>
+#include <msp_cic_int.h>
+
+/* PCI interrupt pins */
+#define IRQ4	MSP_INT_EXT4
+#define IRQ5	MSP_INT_EXT5
+#define IRQ6	MSP_INT_EXT6
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+/* Garibaldi Board IRQ wiring to PCI slots */
+static char irq_tab[][5] __initdata = {
+	/* INTA    INTB    INTC    INTD */
+	{0,     0,      0,      0,      0 },    /*    (AD[0]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[1]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[2]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[3]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[4]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[5]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[6]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[7]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[8]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[9]): Unused */
+	{0,     0,      0,      0,      0 },    /*  0 (AD[10]): Unused */
+	{0,     0,      0,      0,      0 },    /*  1 (AD[11]): Unused */
+	{0,     0,      0,      0,      0 },    /*  2 (AD[12]): Unused */
+	{0,     0,      0,      0,      0 },    /*  3 (AD[13]): Unused */
+	{0,     0,      0,      0,      0 },    /*  4 (AD[14]): Unused */
+	{0,     0,      0,      0,      0 },    /*  5 (AD[15]): Unused */
+	{0,     0,      0,      0,      0 },    /*  6 (AD[16]): Unused */
+	{0,     0,      0,      0,      0 },    /*  7 (AD[17]): Unused */
+	{0,     0,      0,      0,      0 },    /*  8 (AD[18]): Unused */
+	{0,     0,      0,      0,      0 },    /*  9 (AD[19]): Unused */
+	{0,     0,      0,      0,      0 },    /* 10 (AD[20]): Unused */
+	{0,     0,      0,      0,      0 },    /* 11 (AD[21]): Unused */
+	{0,     0,      0,      0,      0 },    /* 12 (AD[22]): Unused */
+	{0,     0,      0,      0,      0 },    /* 13 (AD[23]): Unused */
+	{0,     0,      0,      0,      0 },    /* 14 (AD[24]): Unused */
+	{0,     0,      0,      0,      0 },    /* 15 (AD[25]): Unused */
+	{0,     0,      0,      0,      0 },    /* 16 (AD[26]): Unused */
+	{0,     0,      0,      0,      0 },    /* 17 (AD[27]): Unused */
+	{0,     IRQ4,   IRQ4,   0,      0 },    /* 18 (AD[28]): slot 0 */
+	{0,     0,      0,      0,      0 },    /* 19 (AD[29]): Unused */
+	{0,     IRQ5,   IRQ5,   0,      0 },    /* 20 (AD[30]): slot 1 */
+	{0,     IRQ6,   IRQ6,   0,      0 }     /* 21 (AD[31]): slot 2 */
+};
+
+#elif defined(CONFIG_PMC_MSP7120_EVAL)
+
+/* MSP7120 Eval Board IRQ wiring to PCI slots */
+static char irq_tab[][5] __initdata = {
+	/* INTA    INTB    INTC    INTD */
+	{0,     0,      0,      0,      0 },    /*    (AD[0]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[1]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[2]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[3]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[4]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[5]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[6]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[7]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[8]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[9]): Unused */
+	{0,     0,      0,      0,      0 },    /*  0 (AD[10]): Unused */
+	{0,     0,      0,      0,      0 },    /*  1 (AD[11]): Unused */
+	{0,     0,      0,      0,      0 },    /*  2 (AD[12]): Unused */
+	{0,     0,      0,      0,      0 },    /*  3 (AD[13]): Unused */
+	{0,     0,      0,      0,      0 },    /*  4 (AD[14]): Unused */
+	{0,     0,      0,      0,      0 },    /*  5 (AD[15]): Unused */
+	{0,     IRQ6,   IRQ6,   0,      0 },    /*  6 (AD[16]): slot 3 (mini) */
+	{0,     IRQ5,   IRQ5,   0,      0 },    /*  7 (AD[17]): slot 2 (mini) */
+	{0,     IRQ4,   IRQ4,   IRQ4,   IRQ4},  /*  8 (AD[18]): slot 0 (PCI) */
+	{0,     IRQ5,   IRQ5,   IRQ5,   IRQ5},  /*  9 (AD[19]): slot 1 (PCI) */
+	{0,     0,      0,      0,      0 },    /* 10 (AD[20]): Unused */
+	{0,     0,      0,      0,      0 },    /* 11 (AD[21]): Unused */
+	{0,     0,      0,      0,      0 },    /* 12 (AD[22]): Unused */
+	{0,     0,      0,      0,      0 },    /* 13 (AD[23]): Unused */
+	{0,     0,      0,      0,      0 },    /* 14 (AD[24]): Unused */
+	{0,     0,      0,      0,      0 },    /* 15 (AD[25]): Unused */
+	{0,     0,      0,      0,      0 },    /* 16 (AD[26]): Unused */
+	{0,     0,      0,      0,      0 },    /* 17 (AD[27]): Unused */
+	{0,     0,      0,      0,      0 },    /* 18 (AD[28]): Unused */
+	{0,     0,      0,      0,      0 },    /* 19 (AD[29]): Unused */
+	{0,     0,      0,      0,      0 },    /* 20 (AD[30]): Unused */
+	{0,     0,      0,      0,      0 }     /* 21 (AD[31]): Unused */
+};
+
+#else
+
+/* Unknown board -- don't assign any IRQs */
+static char irq_tab[][5] __initdata = {
+	/* INTA    INTB    INTC    INTD */
+	{0,     0,      0,      0,      0 },    /*    (AD[0]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[1]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[2]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[3]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[4]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[5]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[6]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[7]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[8]): Unused */
+	{0,     0,      0,      0,      0 },    /*    (AD[9]): Unused */
+	{0,     0,      0,      0,      0 },    /*  0 (AD[10]): Unused */
+	{0,     0,      0,      0,      0 },    /*  1 (AD[11]): Unused */
+	{0,     0,      0,      0,      0 },    /*  2 (AD[12]): Unused */
+	{0,     0,      0,      0,      0 },    /*  3 (AD[13]): Unused */
+	{0,     0,      0,      0,      0 },    /*  4 (AD[14]): Unused */
+	{0,     0,      0,      0,      0 },    /*  5 (AD[15]): Unused */
+	{0,     0,      0,      0,      0 },    /*  6 (AD[16]): Unused */
+	{0,     0,      0,      0,      0 },    /*  7 (AD[17]): Unused */
+	{0,     0,      0,      0,      0 },    /*  8 (AD[18]): Unused */
+	{0,     0,      0,      0,      0 },    /*  9 (AD[19]): Unused */
+	{0,     0,      0,      0,      0 },    /* 10 (AD[20]): Unused */
+	{0,     0,      0,      0,      0 },    /* 11 (AD[21]): Unused */
+	{0,     0,      0,      0,      0 },    /* 12 (AD[22]): Unused */
+	{0,     0,      0,      0,      0 },    /* 13 (AD[23]): Unused */
+	{0,     0,      0,      0,      0 },    /* 14 (AD[24]): Unused */
+	{0,     0,      0,      0,      0 },    /* 15 (AD[25]): Unused */
+	{0,     0,      0,      0,      0 },    /* 16 (AD[26]): Unused */
+	{0,     0,      0,      0,      0 },    /* 17 (AD[27]): Unused */
+	{0,     0,      0,      0,      0 },    /* 18 (AD[28]): Unused */
+	{0,     0,      0,      0,      0 },    /* 19 (AD[29]): Unused */
+	{0,     0,      0,      0,      0 },    /* 20 (AD[30]): Unused */
+	{0,     0,      0,      0,      0 }     /* 21 (AD[31]): Unused */
+};
+#endif
+
+/*****************************************************************************
+ *
+ *  FUNCTION: pcibios_plat_dev_init
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Perform platform specific device initialization at
+ *               pci_enable_device() time.
+ *               None are needed for the MSP7120 PCI Controller.
+ *
+ *  INPUTS:      dev     - structure describing the PCI device
+ *
+ *  OUTPUTS:     none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL
+ *
+ ****************************************************************************/
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: pcibios_map_irq
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Perform board supplied PCI IRQ mapping routine.
+ *
+ *  INPUTS:      dev     - unused
+ *               slot    - PCI slot. Identified by which bit of the AD[] bus
+ *                         drives the IDSEL line. AD[10] is 0, AD[31] is
+ *                         slot 21.
+ *               pin     - numbered using the scheme of the PCI_INTERRUPT_PIN
+ *                         field of the config header.
+ *
+ *  OUTPUTS:     none
+ *
+ *  RETURNS:     IRQ number
+ *
+ ****************************************************************************/
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+#if !defined(CONFIG_PMC_MSP7120_GW) && !defined(CONFIG_PMC_MSP7120_EVAL)
+	printk(KERN_WARNING "PCI: unknown board, no PCI IRQs assigned.\n");
+#endif
+	printk(KERN_WARNING "PCI: irq_tab returned %d for slot=%d pin=%d\n",
+		irq_tab[slot][pin], slot, pin);
+
+	return irq_tab[slot][pin];
+}
+
+#endif	/* CONFIG_PCI */
diff --git a/arch/mips/pci/fixup-pnx8550.c b/arch/mips/pci/fixup-pnx8550.c
index 50546da..96857ac 100644
--- a/arch/mips/pci/fixup-pnx8550.c
+++ b/arch/mips/pci/fixup-pnx8550.c
@@ -45,7 +45,7 @@
 	/* nothing to do here */
 }
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return pnx8550_irq_tab[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-rbtx4927.c b/arch/mips/pci/fixup-rbtx4927.c
index ceeb186..3cdbecb 100644
--- a/arch/mips/pci/fixup-rbtx4927.c
+++ b/arch/mips/pci/fixup-rbtx4927.c
@@ -119,7 +119,7 @@
 	return irq;
 }
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	unsigned char irq;
 
diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c
index 36e5fb1..a45bedd 100644
--- a/arch/mips/pci/fixup-sni.c
+++ b/arch/mips/pci/fixup-sni.c
@@ -120,7 +120,7 @@
 	return (csmsr & 0xa0) == 0x20;
 }
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	switch (sni_brd_type) {
 	case SNI_BRD_PCI_TOWER:
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
index 734f2b7..720a2b7 100644
--- a/arch/mips/pci/fixup-tb0219.c
+++ b/arch/mips/pci/fixup-tb0219.c
@@ -23,7 +23,7 @@
 
 #include <asm/vr41xx/tb0219.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq = -1;
 
diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c
index c9e7cb4..e3eedf4 100644
--- a/arch/mips/pci/fixup-tb0226.c
+++ b/arch/mips/pci/fixup-tb0226.c
@@ -23,7 +23,7 @@
 #include <asm/vr41xx/giu.h>
 #include <asm/vr41xx/tb0226.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq = -1;
 
diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c
index fbe6bcb..267ab3d 100644
--- a/arch/mips/pci/fixup-tb0287.c
+++ b/arch/mips/pci/fixup-tb0287.c
@@ -22,7 +22,7 @@
 
 #include <asm/vr41xx/tb0287.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	unsigned char bus;
 	int irq = -1;
diff --git a/arch/mips/pci/fixup-tx4938.c b/arch/mips/pci/fixup-tx4938.c
index f455520..2485f47 100644
--- a/arch/mips/pci/fixup-tx4938.c
+++ b/arch/mips/pci/fixup-tx4938.c
@@ -69,7 +69,7 @@
 	return irq;
 }
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	unsigned char irq = 0;
 
diff --git a/arch/mips/pci/fixup-vr4133.c b/arch/mips/pci/fixup-vr4133.c
index a8d9d22..de5e5f6 100644
--- a/arch/mips/pci/fixup-vr4133.c
+++ b/arch/mips/pci/fixup-vr4133.c
@@ -169,7 +169,7 @@
 }
 #endif
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	extern int pci_probe_only;
 	pci_probe_only = 1;
diff --git a/arch/mips/pci/fixup-wrppmc.c b/arch/mips/pci/fixup-wrppmc.c
index 3357c13..3d27754 100644
--- a/arch/mips/pci/fixup-wrppmc.c
+++ b/arch/mips/pci/fixup-wrppmc.c
@@ -25,7 +25,7 @@
 	[6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0},
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return pci_irq_tab[slot][pin];
 }
diff --git a/arch/mips/pci/fixup-yosemite.c b/arch/mips/pci/fixup-yosemite.c
index 81d77a5..fdafb13 100644
--- a/arch/mips/pci/fixup-yosemite.c
+++ b/arch/mips/pci/fixup-yosemite.c
@@ -26,7 +26,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (pin == 0)
 		return -1;
diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c
index dc35270..f742c51 100644
--- a/arch/mips/pci/ops-bonito64.c
+++ b/arch/mips/pci/ops-bonito64.c
@@ -29,83 +29,60 @@
 #define PCI_ACCESS_READ  0
 #define PCI_ACCESS_WRITE 1
 
-/*
- *  PCI configuration cycle AD bus definition
- */
-/* Type 0 */
-#define PCI_CFG_TYPE0_REG_SHF           0
-#define PCI_CFG_TYPE0_FUNC_SHF          8
+#ifdef CONFIG_LEMOTE_FULONG
+#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(BONITO_PCICFG_BASE | (offset))
+#define ID_SEL_BEGIN 11
+#else
+#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(_pcictrl_bonito_pcicfg + (offset))
+#define ID_SEL_BEGIN 10
+#endif
+#define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
 
-/* Type 1 */
-#define PCI_CFG_TYPE1_REG_SHF           0
-#define PCI_CFG_TYPE1_FUNC_SHF          8
-#define PCI_CFG_TYPE1_DEV_SHF           11
-#define PCI_CFG_TYPE1_BUS_SHF           16
 
 static int bonito64_pcibios_config_access(unsigned char access_type,
 				      struct pci_bus *bus,
 				      unsigned int devfn, int where,
 				      u32 * data)
 {
-	unsigned char busnum = bus->number;
+	u32 busnum = bus->number;
+	u32 addr, type;
 	u32 dummy;
-	u64 pci_addr;
-
-	/* Algorithmics Bonito64 system controller. */
-
-	if ((busnum == 0) && (PCI_SLOT(devfn) > 21)) {
-		/* We number bus 0 devices from 0..21 */
-		return -1;
-	}
-
-	/* Clear cause register bits */
-	BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
-			  BONITO_PCICMD_MTABORT_CLR);
-
-	/*
-	 * Setup pattern to be used as PCI "address" for
-	 * Type 0 cycle
-	 */
-	if (busnum == 0) {
-		/* IDSEL */
-		pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10);
-	} else {
-		/* Bus number */
-		pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF;
-
-		/* Device number */
-		pci_addr |=
-		    PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF;
-	}
-
-	/* Function (same for Type 0/1) */
-	pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF;
-
-	/* Register number (same for Type 0/1) */
-	pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF;
+	void *addrp;
+	int device = PCI_SLOT(devfn);
+	int function = PCI_FUNC(devfn);
+	int reg = where & ~3;
 
 	if (busnum == 0) {
-		/* Type 0 */
-		BONITO_PCIMAP_CFG = pci_addr >> 16;
+		/* Type 0 configuration for onboard PCI bus */
+		if (device > MAX_DEV_NUM)
+			return -1;
+
+		addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg;
+		type = 0;
 	} else {
-		/* Type 1 */
-		BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000;
+		/* Type 1 configuration for offboard PCI bus */
+		addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
+		type = 0x10000;
 	}
 
-	pci_addr &= 0xffff;
+	/* Clear aborts */
+	BONITO_PCICMD |= BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR;
+
+	BONITO_PCIMAP_CFG = (addr >> 16) | type;
 
 	/* Flush Bonito register block */
 	dummy = BONITO_PCIMAP_CFG;
-	iob();		/* sync */
+	mmiowb();
 
-	/* Perform access */
+	addrp = CFG_SPACE_REG(addr & 0xffff);
 	if (access_type == PCI_ACCESS_WRITE) {
-		*(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr) = *(u32 *) data;
-
+		writel(cpu_to_le32(*data), addrp);
+#ifndef CONFIG_LEMOTE_FULONG
 		/* Wait till done */
 		while (BONITO_PCIMSTAT & 0xF);
+#endif
 	} else {
-		*(u32 *) data = *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr);
+		*data = le32_to_cpu(readl(addrp));
 	}
 
 	/* Detect Master/Target abort */
@@ -121,6 +98,7 @@
 	}
 
 	return 0;
+
 }
 
 
diff --git a/arch/mips/pci/ops-marvell.c b/arch/mips/pci/ops-marvell.c
deleted file mode 100644
index 1ac5c59..0000000
--- a/arch/mips/pci/ops-marvell.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include <asm/marvell.h>
-
-static int mv_read_config(struct pci_bus *bus, unsigned int devfn,
-	int where, int size, u32 * val)
-{
-	struct mv_pci_controller *mvbc = bus->sysdata;
-	unsigned long address_reg, data_reg;
-	u32 address;
-
-	address_reg = mvbc->config_addr;
-	data_reg = mvbc->config_vreg;
-
-	/* Accessing device 31 crashes those Marvells.  Since years.
-	   Will they ever make sane controllers ... */
-	if (PCI_SLOT(devfn) == 31)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	address = (bus->number << 16) | (devfn << 8) |
-	          (where & 0xfc) | 0x80000000;
-
-	/* start the configuration cycle */
-	MV_WRITE(address_reg, address);
-
-	switch (size) {
-	case 1:
-		*val = MV_READ_8(data_reg + (where & 0x3));
-		break;
-
-	case 2:
-		*val = MV_READ_16(data_reg + (where & 0x3));
-		break;
-
-	case 4:
-		*val = MV_READ(data_reg);
-		break;
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int mv_write_config(struct pci_bus *bus, unsigned int devfn,
-	int where, int size, u32 val)
-{
-	struct mv_pci_controller *mvbc = bus->sysdata;
-	unsigned long address_reg, data_reg;
-	u32 address;
-
-	address_reg = mvbc->config_addr;
-	data_reg = mvbc->config_vreg;
-
-	/* Accessing device 31 crashes those Marvells.  Since years.
-	   Will they ever make sane controllers ... */
-	if (PCI_SLOT(devfn) == 31)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	address = (bus->number << 16) | (devfn << 8) |
-	          (where & 0xfc) | 0x80000000;
-
-	/* start the configuration cycle */
-	MV_WRITE(address_reg, address);
-
-	switch (size) {
-	case 1:
-		MV_WRITE_8(data_reg + (where & 0x3), val);
-		break;
-
-	case 2:
-		MV_WRITE_16(data_reg + (where & 0x3), val);
-		break;
-
-	case 4:
-		MV_WRITE(data_reg, val);
-		break;
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops mv_pci_ops = {
-	.read	= mv_read_config,
-	.write	= mv_write_config
-};
diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c
deleted file mode 100644
index a8d38dc..0000000
--- a/arch/mips/pci/ops-nile4.c
+++ /dev/null
@@ -1,147 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/bootinfo.h>
-
-#include <asm/lasat/lasat.h>
-#include <asm/gt64120.h>
-#include <asm/nile4.h>
-
-#define PCI_ACCESS_READ  0
-#define PCI_ACCESS_WRITE 1
-
-#define LO(reg) (reg / 4)
-#define HI(reg) (reg / 4 + 1)
-
-volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE;
-
-static DEFINE_SPINLOCK(nile4_pci_lock);
-
-static int nile4_pcibios_config_access(unsigned char access_type,
-	struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
-{
-	unsigned char busnum = bus->number;
-	u32 adr, mask, err;
-
-	if ((busnum == 0) && (PCI_SLOT(devfn) > 8))
-		/* The addressing scheme chosen leaves room for just
-		 * 8 devices on the first busnum (besides the PCI
-		 * controller itself) */
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) {
-		/* Access controller registers directly */
-		if (access_type == PCI_ACCESS_WRITE) {
-			vrc_pciregs[(0x200 + where) >> 2] = *val;
-		} else {
-			*val = vrc_pciregs[(0x200 + where) >> 2];
-		}
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	/* Temporarily map PCI Window 1 to config space */
-	mask = vrc_pciregs[LO(NILE4_PCIINIT1)];
-	vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0);
-
-	/* Clear PCI Error register. This also clears the Error Type
-	 * bits in the Control register */
-	vrc_pciregs[LO(NILE4_PCIERR)] = 0;
-	vrc_pciregs[HI(NILE4_PCIERR)] = 0;
-
-	/* Setup address */
-	if (busnum == 0)
-		adr =
-		    KSEG1ADDR(PCI_WINDOW1) +
-		    ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8)
-		     | (where & ~3));
-	else
-		adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) |
-		      (where & ~3);
-
-	if (access_type == PCI_ACCESS_WRITE)
-		*(u32 *) adr = *val;
-	else
-		*val = *(u32 *) adr;
-
-	/* Check for master or target abort */
-	err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7;
-
-	/* Restore PCI Window 1 */
-	vrc_pciregs[LO(NILE4_PCIINIT1)] = mask;
-
-	if (err)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn,
-	int where, int size, u32 * val)
-{
-	unsigned long flags;
-	u32 data = 0;
-	int err;
-
-	if ((size == 2) && (where & 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	else if ((size == 4) && (where & 3))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	spin_lock_irqsave(&nile4_pci_lock, flags);
-	err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
-					&data);
-	spin_unlock_irqrestore(&nile4_pci_lock, flags);
-
-	if (err)
-		return err;
-
-	if (size == 1)
-		*val = (data >> ((where & 3) << 3)) & 0xff;
-	else if (size == 2)
-		*val = (data >> ((where & 3) << 3)) & 0xffff;
-	else
-		*val = data;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn,
-	int where, int size, u32 val)
-{
-	unsigned long flags;
-	u32 data = 0;
-	int err;
-
-	if ((size == 2) && (where & 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	else if ((size == 4) && (where & 3))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	spin_lock_irqsave(&nile4_pci_lock, flags);
-	err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
-	                                  &data);
-	spin_unlock_irqrestore(&nile4_pci_lock, flags);
-
-	if (err)
-		return err;
-
-	if (size == 1)
-		data = (data & ~(0xff << ((where & 3) << 3))) |
-		    (val << ((where & 3) << 3));
-	else if (size == 2)
-		data = (data & ~(0xffff << ((where & 3) << 3))) |
-		    (val << ((where & 3) << 3));
-	else
-		data = val;
-
-	if (nile4_pcibios_config_access
-	    (PCI_ACCESS_WRITE, bus, devfn, where, &data))
-		return -1;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops nile4_pci_ops = {
-	.read = nile4_pcibios_read,
-	.write = nile4_pcibios_write,
-};
diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c
new file mode 100644
index 0000000..09fa007
--- /dev/null
+++ b/arch/mips/pci/ops-pmcmsp.c
@@ -0,0 +1,994 @@
+/*
+ * PMC-Sierra MSP board specific pci_ops
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Copyright 2005-2007 PMC-Sierra, Inc
+ *
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * Much of the code is derived from the original DDB5074 port by
+ * Geert Uytterhoeven <geert@sonycom.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#define PCI_COUNTERS	1
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/byteorder.h>
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+#include <asm/mipsmtregs.h>
+#endif
+
+#include <msp_prom.h>
+#include <msp_cic_int.h>
+#include <msp_pci.h>
+#include <msp_regs.h>
+#include <msp_regops.h>
+
+#define PCI_ACCESS_READ		0
+#define PCI_ACCESS_WRITE	1
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+static char proc_init;
+extern struct proc_dir_entry *proc_bus_pci_dir;
+unsigned int pci_int_count[32];
+
+static void pci_proc_init(void);
+
+/*****************************************************************************
+ *
+ *  FUNCTION: read_msp_pci_counts
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Prints the count of how many times each PCI
+ *               interrupt has asserted. Can be invoked by the
+ *               /proc filesystem.
+ *
+ *  INPUTS:      page    - part of STDOUT calculation
+ *               off     - part of STDOUT calculation
+ *               count   - part of STDOUT calculation
+ *               data    - unused
+ *
+ *  OUTPUTS:     start   - new start location
+ *               eof     - end of file pointer
+ *
+ *  RETURNS:     len     - STDOUT length
+ *
+ ****************************************************************************/
+static int read_msp_pci_counts(char *page, char **start, off_t off,
+				int count, int *eof, void *data)
+{
+	int i;
+	int len = 0;
+	unsigned int intcount, total = 0;
+
+	for (i = 0; i < 32; ++i) {
+		intcount = pci_int_count[i];
+		if (intcount != 0) {
+			len += sprintf(page + len, "[%d] = %u\n", i, intcount);
+			total += intcount;
+		}
+	}
+
+	len += sprintf(page + len, "total = %u\n", total);
+	if (len <= off+count)
+		*eof = 1;
+
+	*start = page + off;
+	len -= off;
+	if (len > count)
+		len = count;
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: gen_pci_cfg_wr
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Generates a configuration write cycle for debug purposes.
+ *               The IDSEL line asserted and location and data written are
+ *               immaterial. Just want to be able to prove that a
+ *               configuration write can be correctly generated on the
+ *               PCI bus.  Intent is that this function by invocable from
+ *               the /proc filesystem.
+ *
+ *  INPUTS:      page    - part of STDOUT calculation
+ *               off     - part of STDOUT calculation
+ *               count   - part of STDOUT calculation
+ *               data    - unused
+ *
+ *  OUTPUTS:     start   - new start location
+ *               eof     - end of file pointer
+ *
+ *  RETURNS:     len     - STDOUT length
+ *
+ ****************************************************************************/
+static int gen_pci_cfg_wr(char *page, char **start, off_t off,
+				int count, int *eof, void *data)
+{
+	unsigned char where = 0; /* Write to static Device/Vendor ID */
+	unsigned char bus_num = 0; /* Bus 0 */
+	unsigned char dev_fn = 0xF; /* Arbitrary device number */
+	u32 wr_data = 0xFF00AA00; /* Arbitrary data */
+	struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+	int len = 0;
+	unsigned long value;
+	int intr;
+
+	len += sprintf(page + len, "PMC MSP PCI: Beginning\n");
+
+	if (proc_init == 0) {
+		pci_proc_init();
+		proc_init = ~0;
+	}
+
+	len += sprintf(page + len, "PMC MSP PCI: Before Cfg Wr\n");
+
+	/*
+	 * Generate PCI Configuration Write Cycle
+	 */
+
+	/* Clear cause register bits */
+	preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+	/* Setup address that is to appear on PCI bus */
+	preg->config_addr = BPCI_CFGADDR_ENABLE |
+		(bus_num << BPCI_CFGADDR_BUSNUM_SHF) |
+		(dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) |
+		(where & 0xFC);
+
+	value = cpu_to_le32(wr_data);
+
+	/* Launch the PCI configuration write cycle */
+	*PCI_CONFIG_SPACE_REG = value;
+
+	/*
+	 * Check if the PCI configuration cycle (rd or wr) succeeded, by
+	 * checking the status bits for errors like master or target abort.
+	 */
+	intr = preg->if_status;
+
+	len += sprintf(page + len, "PMC MSP PCI: After Cfg Wr\n");
+
+	/* Handle STDOUT calculations */
+	if (len <= off+count)
+		*eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len > count)
+		len = count;
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: pci_proc_init
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Create entries in the /proc filesystem for debug access.
+ *
+ *  INPUTS:      none
+ *
+ *  OUTPUTS:     none
+ *
+ *  RETURNS:     none
+ *
+ ****************************************************************************/
+static void pci_proc_init(void)
+{
+	create_proc_read_entry("pmc_msp_pci_rd_cnt", 0, NULL,
+				read_msp_pci_counts, NULL);
+	create_proc_read_entry("pmc_msp_pci_cfg_wr", 0, NULL,
+				gen_pci_cfg_wr, NULL);
+}
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+spinlock_t bpci_lock = SPIN_LOCK_UNLOCKED;
+
+/*****************************************************************************
+ *
+ *  STRUCT: pci_io_resource
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Defines the address range that pciauto() will use to
+ *               assign to the I/O BARs of PCI devices.
+ *
+ *               Use the start and end addresses of the MSP7120 PCI Host
+ *               Controller I/O space, in the form that they appear on the
+ *               PCI bus AFTER MSP7120 has performed address translation.
+ *
+ *               For I/O accesses, MSP7120 ignores OATRAN and maps I/O
+ *               accesses into the bottom 0xFFF region of address space,
+ *               so that is the range to put into the pci_io_resource
+ *               struct.
+ *
+ *               In MSP4200, the start address was 0x04 instead of the
+ * 		 expected 0x00. Will just assume there was a good reason
+ * 		 for this!
+ *
+ *  NOTES:       Linux, by default, will assign I/O space to the lowest
+ *               region of address space. Since MSP7120 and Linux,
+ *               by default, have no offset in between how they map, the
+ *               io_offset element of pci_controller struct should be set
+ *               to zero.
+ *  ELEMENTS:
+ *    name       - String used for a meaningful name.
+ *
+ *    start      - Start address of MSP7120's I/O space, as MSP7120 presents
+ *                 the address on the PCI bus.
+ *
+ *    end        - End address of MSP7120's I/O space, as MSP7120 presents
+ *                 the address on the PCI bus.
+ *
+ *    flags      - Attributes indicating the type of resource. In this case,
+ *                 indicate I/O space.
+ *
+ ****************************************************************************/
+static struct resource pci_io_resource = {
+	.name	= "pci IO space",
+	.start	= 0x04,
+	.end	= 0x0FFF,
+	.flags	= IORESOURCE_IO	/* I/O space */
+};
+
+/*****************************************************************************
+ *
+ *  STRUCT: pci_mem_resource
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Defines the address range that pciauto() will use to
+ *               assign to the memory BARs of PCI devices.
+ *
+ *               The .start and .end values are dependent upon how address
+ *               translation is performed by the OATRAN regiser.
+ *
+ *               The values to use for .start and .end are the values
+ *               in the form they appear on the PCI bus AFTER MSP7120 has
+ *               performed OATRAN address translation.
+ *
+ *  ELEMENTS:
+ *    name       - String used for a meaningful name.
+ *
+ *    start      - Start address of MSP7120's memory space, as MSP7120 presents
+ *                 the address on the PCI bus.
+ *
+ *    end        - End address of MSP7120's memory space, as MSP7120 presents
+ *                 the address on the PCI bus.
+ *
+ *    flags      - Attributes indicating the type of resource. In this case,
+ *                 indicate memory space.
+ *
+ ****************************************************************************/
+static struct resource pci_mem_resource = {
+	.name	= "pci memory space",
+	.start	= MSP_PCI_SPACE_BASE,
+	.end	= MSP_PCI_SPACE_END,
+	.flags	= IORESOURCE_MEM	 /* memory space */
+};
+
+/*****************************************************************************
+ *
+ *  FUNCTION: bpci_interrupt
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: PCI status interrupt handler. Updates the count of how
+ *               many times each status bit has been set, then clears
+ *               the status bits. If the appropriate macros are defined,
+ *               these counts can be viewed via the /proc filesystem.
+ *
+ *  INPUTS:      irq     - unused
+ *               dev_id  - unused
+ *               pt_regs - unused
+ *
+ *  OUTPUTS:     none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL  - success
+ *
+ ****************************************************************************/
+static int bpci_interrupt(int irq, void *dev_id)
+{
+	struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+	unsigned int stat = preg->if_status;
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+	int i;
+	for (i = 0; i < 32; ++i) {
+		if ((1 << i) & stat)
+			++pci_int_count[i];
+	}
+#endif /* PROC_FS && PCI_COUNTERS */
+
+	/* printk("PCI ISR: Status=%08X\n", stat); */
+
+	/* write to clear all asserted interrupts */
+	preg->if_status = stat;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_config_access
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Performs a PCI configuration access (rd or wr), then
+ *               checks that the access succeeded by querying MSP7120's
+ *               PCI status bits.
+ *
+ *  INPUTS:
+ *               access_type  - kind of PCI configuration cycle to perform
+ *                              (read or write). Legal values are
+ *                              PCI_ACCESS_WRITE and PCI_ACCESS_READ.
+ *
+ *               bus          - pointer to the bus number of the device to
+ *                              be targetted for the configuration cycle.
+ *                              The only element of the pci_bus structure
+ *                              used is bus->number. This argument determines
+ *                              if the configuration access will be Type 0 or
+ *                              Type 1. Since MSP7120 assumes itself to be the
+ *                              PCI Host, any non-zero bus->number generates
+ *                              a Type 1 access.
+ *
+ *               devfn        - this is an 8-bit field. The lower three bits
+ *                              specify the function number of the device to
+ *                              be targetted for the configuration cycle, with
+ *                              all three-bit combinations being legal. The
+ *                              upper five bits specify the device number,
+ *                              with legal values being 10 to 31.
+ *
+ *               where        - address within the Configuration Header
+ *                              space to access.
+ *
+ *               data         - for write accesses, contains the data to
+ *                              write.
+ *
+ *  OUTPUTS:
+ *               data         - for read accesses, contains the value read.
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL  - success
+ *               -1                  - access failure
+ *
+ ****************************************************************************/
+int msp_pcibios_config_access(unsigned char access_type,
+				struct pci_bus *bus,
+				unsigned int devfn,
+				unsigned char where,
+				u32 *data)
+{
+	struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+	unsigned char bus_num = bus->number;
+	unsigned char dev_fn = (unsigned char)devfn;
+	unsigned long flags;
+	unsigned long intr;
+	unsigned long value;
+	static char pciirqflag;
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+	unsigned int	vpe_status;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+	if (proc_init == 0) {
+		pci_proc_init();
+		proc_init = ~0;
+	}
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+	/*
+	 * Just the first time this function invokes, allocate
+	 * an interrupt line for PCI host status interrupts. The
+	 * allocation assigns an interrupt handler to the interrupt.
+	 */
+	if (pciirqflag == 0) {
+		request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */
+				bpci_interrupt,
+				SA_SHIRQ | SA_INTERRUPT,
+				"PMC MSP PCI Host",
+				preg);
+		pciirqflag = ~0;
+	}
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+	local_irq_save(flags);
+	vpe_status = dvpe();
+#else
+	spin_lock_irqsave(&bpci_lock, flags);
+#endif
+
+	/*
+	 * Clear PCI cause register bits.
+	 *
+	 * In Polo, the PCI Host had a dedicated DMA called the
+	 * Block Copy (not to be confused with the general purpose Block
+	 * Copy Engine block). There appear to have been special interrupts
+	 * for this Block Copy, called Block Copy 0 Fault (BC0F) and
+	 * Block Copy 1 Fault (BC1F). MSP4200 and MSP7120 don't have this
+	 * dedicated Block Copy block, so these two interrupts are now
+	 * marked reserved. In case the  Block Copy is resurrected in a
+	 * future design, maintain the code that treats these two interrupts
+	 * specially.
+	 *
+	 * Write to clear all interrupts in the PCI status register, aside
+	 * from BC0F and BC1F.
+	 */
+	preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+	/* Setup address that is to appear on PCI bus */
+	preg->config_addr = BPCI_CFGADDR_ENABLE	|
+		(bus_num << BPCI_CFGADDR_BUSNUM_SHF) |
+		(dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) |
+		(where & 0xFC);
+
+	/* IF access is a PCI configuration write */
+	if (access_type == PCI_ACCESS_WRITE) {
+		value = cpu_to_le32(*data);
+		*PCI_CONFIG_SPACE_REG = value;
+	} else {
+		/* ELSE access is a PCI configuration read */
+		value = le32_to_cpu(*PCI_CONFIG_SPACE_REG);
+		*data = value;
+	}
+
+	/*
+	 * Check if the PCI configuration cycle (rd or wr) succeeded, by
+	 * checking the status bits for errors like master or target abort.
+	 */
+	intr = preg->if_status;
+
+	/* Clear config access */
+	preg->config_addr = 0;
+
+	/* IF error occurred */
+	if (intr & ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F)) {
+		/* Clear status bits */
+		preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+		evpe(vpe_status);
+		local_irq_restore(flags);
+#else
+		spin_unlock_irqrestore(&bpci_lock, flags);
+#endif
+
+		return -1;
+	}
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+	evpe(vpe_status);
+	local_irq_restore(flags);
+#else
+	spin_unlock_irqrestore(&bpci_lock, flags);
+#endif
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_read_config_byte
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Read a byte from PCI configuration address spac
+ *               Since the hardware can't address 8 bit chunks
+ *               directly, read a 32-bit chunk, then mask off extraneous
+ *               bits.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the read is destined for.
+ *               devfn  - device/function combination that the read is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *
+ *  OUTPUTS      val    - read data
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL  - success
+ *               -1                  - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_byte(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u32 *val)
+{
+	u32 data = 0;
+
+	/*
+	 * If the config access did not complete normally (e.g., underwent
+	 * master abort) do the PCI compliant thing, which is to supply an
+	 * all ones value.
+	 */
+	if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+					where, &data)) {
+		*val = 0xFFFFFFFF;
+		return -1;
+	}
+
+	*val = (data >> ((where & 3) << 3)) & 0x0ff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_read_config_word
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Read a word (16 bits) from PCI configuration address space.
+ *               Since the hardware can't address 16 bit chunks
+ *               directly, read a 32-bit chunk, then mask off extraneous
+ *               bits.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the read is destined for.
+ *               devfn  - device/function combination that the read is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *
+ *  OUTPUTS      val    - read data
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL           - success
+ *               PCIBIOS_BAD_REGISTER_NUMBER  - bad register address
+ *               -1                           - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_word(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u32 *val)
+{
+	u32 data = 0;
+
+	/* if (where & 1) */	/* Commented out non-compliant code.
+				 * Should allow word access to configuration
+				 * registers, with only exception being when
+				 * the word access would wrap around into
+				 * the next dword.
+				 */
+	if ((where & 3) == 3) {
+		*val = 0xFFFFFFFF;
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	/*
+	 * If the config access did not complete normally (e.g., underwent
+	 * master abort) do the PCI compliant thing, which is to supply an
+	 * all ones value.
+	 */
+	if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+					where, &data)) {
+		*val = 0xFFFFFFFF;
+		return -1;
+	}
+
+	*val = (data >> ((where & 3) << 3)) & 0x0ffff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_read_config_dword
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Read a double word (32 bits) from PCI configuration
+ *               address space.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the read is destined for.
+ *               devfn  - device/function combination that the read is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *
+ *  OUTPUTS      val    - read data
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL           - success
+ *               PCIBIOS_BAD_REGISTER_NUMBER  - bad register address
+ *               -1                           - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_dword(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u32 *val)
+{
+	u32 data = 0;
+
+	/* Address must be dword aligned. */
+	if (where & 3) {
+		*val = 0xFFFFFFFF;
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	/*
+	 * If the config access did not complete normally (e.g., underwent
+	 * master abort) do the PCI compliant thing, which is to supply an
+	 * all ones value.
+	 */
+	if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+					where, &data)) {
+		*val = 0xFFFFFFFF;
+		return -1;
+	}
+
+	*val = data;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_write_config_byte
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Write a byte to PCI configuration address space.
+ *               Since the hardware can't address 8 bit chunks
+ *               directly, a read-modify-write is performed.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the write is destined for.
+ *               devfn  - device/function combination that the write is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *               val    - value to write
+ *
+ *  OUTPUTS      none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL  - success
+ *               -1                  - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_byte(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u8 val)
+{
+	u32 data = 0;
+
+	/* read config space */
+	if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+					where, &data))
+		return -1;
+
+	/* modify the byte within the dword */
+	data = (data & ~(0xff << ((where & 3) << 3))) |
+			(val << ((where & 3) << 3));
+
+	/* write back the full dword */
+	if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+					where, &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_write_config_word
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Write a word (16-bits) to PCI configuration address space.
+ *               Since the hardware can't address 16 bit chunks
+ *               directly, a read-modify-write is performed.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the write is destined for.
+ *               devfn  - device/function combination that the write is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *               val    - value to write
+ *
+ *  OUTPUTS      none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL           - success
+ *               PCIBIOS_BAD_REGISTER_NUMBER  - bad register address
+ *               -1                           - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_word(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u16 val)
+{
+	u32 data = 0;
+
+	/* Fixed non-compliance: if (where & 1) */
+	if ((where & 3) == 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	/* read config space */
+	if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+					where, &data))
+		return -1;
+
+	/* modify the word within the dword */
+	data = (data & ~(0xffff << ((where & 3) << 3))) |
+			(val << ((where & 3) << 3));
+
+	/* write back the full dword */
+	if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+					where, &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_write_config_dword
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Write a double word (32-bits) to PCI configuration address
+ *               space.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the write is destined for.
+ *               devfn  - device/function combination that the write is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *               val    - value to write
+ *
+ *  OUTPUTS      none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL           - success
+ *               PCIBIOS_BAD_REGISTER_NUMBER  - bad register address
+ *               -1                           - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_dword(struct pci_bus *bus,
+				unsigned int devfn,
+				int where,
+				u32 val)
+{
+	/* check that address is dword aligned */
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	/* perform write */
+	if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+					where, &val))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_read_config
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Interface the PCI configuration read request with
+ *               the appropriate function, based on how many bytes
+ *               the read request is.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the write is destined for.
+ *               devfn  - device/function combination that the write is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *               size   - in units of bytes, should be 1, 2, or 4.
+ *
+ *  OUTPUTS      val    - value read, with any extraneous bytes masked
+ *                        to zero.
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL   - success
+ *               -1                   - failure
+ *
+ ****************************************************************************/
+int
+msp_pcibios_read_config(struct pci_bus *bus,
+			unsigned int	devfn,
+			int where,
+			int size,
+			u32 *val)
+{
+	if (size == 1) {
+		if (msp_pcibios_read_config_byte(bus, devfn, where, val)) {
+			return -1;
+		}
+	} else if (size == 2) {
+		if (msp_pcibios_read_config_word(bus, devfn, where, val)) {
+			return -1;
+		}
+	} else if (size == 4) {
+		if (msp_pcibios_read_config_dword(bus, devfn, where, val)) {
+			return -1;
+		}
+	} else {
+		*val = 0xFFFFFFFF;
+		return -1;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pcibios_write_config
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Interface the PCI configuration write request with
+ *               the appropriate function, based on how many bytes
+ *               the read request is.
+ *
+ *  INPUTS       bus    - structure containing attributes for the PCI bus
+ *                        that the write is destined for.
+ *               devfn  - device/function combination that the write is
+ *                        destined for.
+ *               where  - register within the Configuration Header space
+ *                        to access.
+ *               size   - in units of bytes, should be 1, 2, or 4.
+ *               val    - value to write
+ *
+ *  OUTPUTS:     none
+ *
+ *  RETURNS:     PCIBIOS_SUCCESSFUL   - success
+ *               -1                   - failure
+ *
+ ****************************************************************************/
+int
+msp_pcibios_write_config(struct pci_bus *bus,
+			unsigned int devfn,
+			int where,
+			int size,
+			u32 val)
+{
+	if (size == 1) {
+		if (msp_pcibios_write_config_byte(bus, devfn,
+						where, (u8)(0xFF & val))) {
+			return -1;
+		}
+	} else if (size == 2) {
+		if (msp_pcibios_write_config_word(bus, devfn,
+						where, (u16)(0xFFFF & val))) {
+			return -1;
+		}
+	} else if (size == 4) {
+		if (msp_pcibios_write_config_dword(bus, devfn, where, val)) {
+			return -1;
+		}
+	} else {
+		return -1;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ *  STRUCTURE: msp_pci_ops
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: structure to abstract the hardware specific PCI
+ *               configuration accesses.
+ *
+ *  ELEMENTS:
+ *    read      - function for Linux to generate PCI Configuration reads.
+ *    write     - function for Linux to generate PCI Configuration writes.
+ *
+ ****************************************************************************/
+struct pci_ops msp_pci_ops = {
+	.read = msp_pcibios_read_config,
+	.write = msp_pcibios_write_config
+};
+
+/*****************************************************************************
+ *
+ *  STRUCTURE: msp_pci_controller
+ *  _________________________________________________________________________
+ *
+ *  Describes the attributes of the MSP7120 PCI Host Controller
+ *
+ *  ELEMENTS:
+ *    pci_ops      - abstracts the hardware specific PCI configuration
+ *                   accesses.
+ *
+ *    mem_resource - address range pciauto() uses to assign to PCI device
+ *                   memory BARs.
+ *
+ *    mem_offset   - offset between how MSP7120 outbound PCI memory
+ *                   transaction addresses appear on the PCI bus and how Linux
+ *                   wants to configure memory BARs of the PCI devices.
+ *                   MSP7120 does nothing funky, so just set to zero.
+ *
+ *    io_resource  - address range pciauto() uses to assign to PCI device
+ *                   I/O BARs.
+ *
+ *    io_offset    - offset between how MSP7120 outbound PCI I/O
+ *                   transaction addresses appear on the PCI bus and how
+ *                   Linux defaults to configure I/O BARs of the PCI devices.
+ *                   MSP7120 maps outbound I/O accesses into the bottom
+ *                   bottom 4K of PCI address space (and ignores OATRAN).
+ *                   Since the Linux default is to configure I/O BARs to the
+ *                   bottom 4K, no special offset is needed. Just set to zero.
+ *
+ ****************************************************************************/
+static struct pci_controller msp_pci_controller = {
+	.pci_ops	= &msp_pci_ops,
+	.mem_resource	= &pci_mem_resource,
+	.mem_offset	= 0,
+	.io_resource	= &pci_io_resource,
+	.io_offset	= 0
+};
+
+/*****************************************************************************
+ *
+ *  FUNCTION: msp_pci_init
+ *  _________________________________________________________________________
+ *
+ *  DESCRIPTION: Initialize the PCI Host Controller and register it with
+ *               Linux so Linux can seize control of the PCI bus.
+ *
+ ****************************************************************************/
+void __init msp_pci_init(void)
+{
+	struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+	u32 id;
+
+	/* Extract Device ID */
+	id = read_reg32(PCI_JTAG_DEVID_REG, 0xFFFF) >> 12;
+
+	/* Check if JTAG ID identifies MSP7120 */
+	if (!MSP_HAS_PCI(id)) {
+		printk(KERN_WARNING "PCI: No PCI; id reads as %x\n", id);
+		goto no_pci;
+	}
+
+	/*
+	 * Enable flushing of the PCI-SDRAM queue upon a read
+	 * of the SDRAM's Memory Configuration Register.
+	 */
+	*(unsigned long *)QFLUSH_REG_1 = 3;
+
+	/* Configure PCI Host Controller. */
+	preg->if_status	= ~0;		/* Clear cause register bits */
+	preg->config_addr = 0;		/* Clear config access */
+	preg->oatran	= MSP_PCI_OATRAN; /* PCI outbound addr translation */
+	preg->if_mask	= 0xF8BF87C0;	/* Enable all PCI status interrupts */
+
+	/* configure so inb(), outb(), and family are functional */
+	set_io_port_base(MSP_PCI_IOSPACE_BASE);
+
+	/* Tell Linux the details of the MSP7120 PCI Host Controller */
+	register_pci_controller(&msp_pci_controller);
+
+	return;
+
+no_pci:
+	/* Disable PCI channel */
+	printk(KERN_WARNING "PCI: no host PCI bus detected\n");
+}
diff --git a/arch/mips/pci/ops-tx4938.c b/arch/mips/pci/ops-tx4938.c
index 4450070..a450c40 100644
--- a/arch/mips/pci/ops-tx4938.c
+++ b/arch/mips/pci/ops-tx4938.c
@@ -46,50 +46,63 @@
 	.flags	= IORESOURCE_MEM
 };
 
-static int mkaddr(int bus, int dev_fn, int where, int *flagsp)
+static int mkaddr(int bus, int dev_fn, int where,
+		  struct tx4938_pcic_reg *pcicptr)
 {
 	if (bus > 0) {
 		/* Type 1 configuration */
-		tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+		pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
 		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1;
 	} else {
 		if (dev_fn >= PCI_DEVFN(TX4938_PCIC_MAX_DEVNU, 0))
 			return -1;
 
 		/* Type 0 configuration */
-		tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+		pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
 		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc);
 	}
 	/* clear M_ABORT and Disable M_ABORT Int. */
-	tx4938_pcicptr->pcistatus =
-	    (tx4938_pcicptr->pcistatus & 0x0000ffff) |
+	pcicptr->pcistatus =
+	    (pcicptr->pcistatus & 0x0000ffff) |
 	    (PCI_STATUS_REC_MASTER_ABORT << 16);
-	tx4938_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
+	pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
 
 	return 0;
 }
 
-static int check_abort(int flags)
+static int check_abort(struct tx4938_pcic_reg *pcicptr)
 {
 	int code = PCIBIOS_SUCCESSFUL;
 	/* wait write cycle completion before checking error status */
-	while (tx4938_pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
+	while (pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
 				;
-	if (tx4938_pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
-		tx4938_pcicptr->pcistatus =
-		    (tx4938_pcicptr->
+	if (pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
+		pcicptr->pcistatus =
+		    (pcicptr->
 		     pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT
 						<< 16);
-		tx4938_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
+		pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
 		code = PCIBIOS_DEVICE_NOT_FOUND;
 	}
 	return code;
 }
 
+extern struct pci_controller tx4938_pci_controller[];
+extern struct tx4938_pcic_reg *get_tx4938_pcicptr(int ch);
+
+static struct tx4938_pcic_reg *pci_bus_to_pcicptr(struct pci_bus *bus)
+{
+	struct pci_controller *channel = bus->sysdata;
+	return get_tx4938_pcicptr(channel - &tx4938_pci_controller[0]);
+}
+
 static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn,
 					int where, int size, u32 * val)
 {
-	int flags, retval, dev, busno, func;
+	int retval, dev, busno, func;
+	struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus);
+	void __iomem *cfgdata =
+		(void __iomem *)(unsigned long)&pcicptr->g2pcfgdata;
 
 	dev = PCI_SLOT(devfn);
 	func = PCI_FUNC(devfn);
@@ -101,32 +114,32 @@
 		busno = 0;
 	}
 
-	if (mkaddr(busno, devfn, where, &flags))
+	if (mkaddr(busno, devfn, where, pcicptr))
 		return -1;
 
 	switch (size) {
 	case 1:
-		*val = *(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
-			      ((where & 3) ^ 3));
+		cfgdata += (where & 3) ^ 3;
 #else
-			      (where & 3));
+		cfgdata += where & 3;
 #endif
+		*val = __raw_readb(cfgdata);
 		break;
 	case 2:
-		*val = *(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
-				((where & 3) ^ 2));
+		cfgdata += (where & 2) ^ 2;
 #else
-				(where & 3));
+		cfgdata += where & 2;
 #endif
+		*val = __raw_readw(cfgdata);
 		break;
 	case 4:
-		*val = tx4938_pcicptr->g2pcfgdata;
+		*val = __raw_readl(cfgdata);
 		break;
 	}
 
-	retval = check_abort(flags);
+	retval = check_abort(pcicptr);
 	if (retval == PCIBIOS_DEVICE_NOT_FOUND)
 		*val = 0xffffffff;
 
@@ -136,7 +149,10 @@
 static int tx4938_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, int where,
 						int size, u32 val)
 {
-	int flags, dev, busno, func;
+	int dev, busno, func;
+	struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus);
+	void __iomem *cfgdata =
+		(void __iomem *)(unsigned long)&pcicptr->g2pcfgdata;
 
 	busno = bus->number;
 	dev = PCI_SLOT(devfn);
@@ -149,32 +165,32 @@
 		busno = 0;
 	}
 
-	if (mkaddr(busno, devfn, where, &flags))
+	if (mkaddr(busno, devfn, where, pcicptr))
 		return -1;
 
 	switch (size) {
 	case 1:
-		*(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
-			  ((where & 3) ^ 3)) = val;
+		cfgdata += (where & 3) ^ 3;
 #else
-			  (where & 3)) = val;
+		cfgdata += where & 3;
 #endif
+		__raw_writeb(val, cfgdata);
 		break;
 	case 2:
-		*(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
-			((where & 0x3) ^ 0x2)) = val;
+		cfgdata += (where & 2) ^ 2;
 #else
-			(where & 3)) = val;
+		cfgdata += where & 2;
 #endif
+		__raw_writew(val, cfgdata);
 		break;
 	case 4:
-		tx4938_pcicptr->g2pcfgdata = val;
+		__raw_writel(val, cfgdata);
 		break;
 	}
 
-	return check_abort(flags);
+	return check_abort(pcicptr);
 }
 
 struct pci_ops tx4938_pci_ops = {
diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c
index d7b9e13..2b4e30c 100644
--- a/arch/mips/pci/pci-bcm1480.c
+++ b/arch/mips/pci/pci-bcm1480.c
@@ -74,8 +74,9 @@
 	*(u32 *)(cfg_space + (addr & ~3)) = data;
 }
 
-int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
+	This is b0rked.
 	return dev->irq;
 }
 
diff --git a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c
index d071bc3..7363e18 100644
--- a/arch/mips/pci/pci-ddb5477.c
+++ b/arch/mips/pci/pci-ddb5477.c
@@ -131,7 +131,7 @@
 	/* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */
 };
 
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int slot_num;
 	unsigned char *slot_irq_map;
diff --git a/arch/mips/pci/pci-ev64120.c b/arch/mips/pci/pci-ev64120.c
deleted file mode 100644
index a84f594..0000000
--- a/arch/mips/pci/pci-ev64120.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <linux/pci.h>
-#include <asm/irq.h>
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int irq;
-
-	if (!pin)
-		return 0;
-
-	irq = allocate_irqno();
-	if (irq < 0)
-		return 0;
-
-	return irq;
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
index 405ce01..a322543 100644
--- a/arch/mips/pci/pci-ip27.c
+++ b/arch/mips/pci/pci-ip27.c
@@ -134,7 +134,7 @@
  * A given PCI device, in general, should be able to intr any of the cpus
  * on any one of the hubs connected to its xbow.
  */
-int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
 	int irq = bc->pci_int[slot];
diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c
deleted file mode 100644
index 985784a..0000000
--- a/arch/mips/pci/pci-lasat.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000, 2001, 04 Keith M Wesolowski
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <asm/bootinfo.h>
-
-extern struct pci_ops nile4_pci_ops;
-extern struct pci_ops gt64xxx_pci0_ops;
-static struct resource lasat_pci_mem_resource = {
-	.name	= "LASAT PCI MEM",
-	.start	= 0x18000000,
-	.end	= 0x19ffffff,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct resource lasat_pci_io_resource = {
-	.name	= "LASAT PCI IO",
-	.start	= 0x1a000000,
-	.end	= 0x1bffffff,
-	.flags	= IORESOURCE_IO,
-};
-
-static struct pci_controller lasat_pci_controller = {
-	.mem_resource	= &lasat_pci_mem_resource,
-	.io_resource	= &lasat_pci_io_resource,
-};
-
-static int __init lasat_pci_setup(void)
-{
-	printk("PCI: starting\n");
-
-	switch (mips_machtype) {
-	case MACH_LASAT_100:
-                lasat_pci_controller.pci_ops = &gt64xxx_pci0_ops;
-                break;
-	case MACH_LASAT_200:
-                lasat_pci_controller.pci_ops = &nile4_pci_ops;
-                break;
-	default:
-                panic("pcibios_init: mips_machtype incorrect");
-        }
-
-	register_pci_controller(&lasat_pci_controller);
-
-	return 0;
-}
-
-arch_initcall(lasat_pci_setup);
-
-#define LASATINT_ETH1   0
-#define LASATINT_ETH0   1
-#define LASATINT_HDC    2
-#define LASATINT_COMP   3
-#define LASATINT_HDLC   4
-#define LASATINT_PCIA   5
-#define LASATINT_PCIB   6
-#define LASATINT_PCIC   7
-#define LASATINT_PCID   8
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	switch (slot) {
-	case 1:
-	case 2:
-	case 3:
-		return LASATINT_PCIA + (((slot-1) + (pin-1)) % 4);
-	case 4:
-		return LASATINT_ETH1;   /* Ethernet 1 (LAN 2) */
-	case 5:
-		return LASATINT_ETH0;   /* Ethernet 0 (LAN 1) */
-	case 6:
-		return LASATINT_HDC;    /* IDE controller */
-	default:
-		return 0xff;            /* Illegal */
-	}
-
-	return -1;
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
diff --git a/arch/mips/pci/pci-ocelot-c.c b/arch/mips/pci/pci-ocelot-c.c
deleted file mode 100644
index 027759f..0000000
--- a/arch/mips/pci/pci-ocelot-c.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004, 06 by Ralf Baechle (ralf@linux-mips.org)
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/mv643xx.h>
-
-#include <linux/init.h>
-
-#include <asm/marvell.h>
-
-/*
- * We assume the address ranges have already been setup appropriately by
- * the firmware.  PMON in case of the Ocelot C does that.
- */
-static struct resource mv_pci_io_mem0_resource = {
-	.name	= "MV64340 PCI0 IO MEM",
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem0_resource = {
-	.name	= "MV64340 PCI0 MEM",
-	.flags	= IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus0_controller = {
-	.pcic = {
-		.pci_ops	= &mv_pci_ops,
-		.mem_resource	= &mv_pci_mem0_resource,
-		.io_resource	= &mv_pci_io_mem0_resource,
-	},
-	.config_addr	= MV64340_PCI_0_CONFIG_ADDR,
-	.config_vreg	= MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static uint32_t mv_io_base, mv_io_size;
-
-static void mv64340_pci0_init(void)
-{
-	uint32_t mem0_base, mem0_size;
-	uint32_t io_base, io_size;
-
-	io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
-	io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
-	mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
-	mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
-
-	mv_pci_io_mem0_resource.start		= 0;
-	mv_pci_io_mem0_resource.end		= io_size - 1;
-	mv_pci_mem0_resource.start		= mem0_base;
-	mv_pci_mem0_resource.end		= mem0_base + mem0_size - 1;
-	mv_bus0_controller.pcic.mem_offset	= mem0_base;
-	mv_bus0_controller.pcic.io_offset	= 0;
-
-	ioport_resource.end		= io_size - 1;
-
-	register_pci_controller(&mv_bus0_controller.pcic);
-
-	mv_io_base = io_base;
-	mv_io_size = io_size;
-}
-
-static struct resource mv_pci_io_mem1_resource = {
-	.name	= "MV64340 PCI1 IO MEM",
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem1_resource = {
-	.name	= "MV64340 PCI1 MEM",
-	.flags	= IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus1_controller = {
-	.pcic = {
-		.pci_ops	= &mv_pci_ops,
-		.mem_resource	= &mv_pci_mem1_resource,
-		.io_resource	= &mv_pci_io_mem1_resource,
-	},
-	.config_addr	= MV64340_PCI_1_CONFIG_ADDR,
-	.config_vreg	= MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static __init void mv64340_pci1_init(void)
-{
-	uint32_t mem0_base, mem0_size;
-	uint32_t io_base, io_size;
-
-	io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
-	io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
-	mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
-	mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
-
-	/*
-	 * Here we assume the I/O window of second bus to be contiguous with
-	 * the first.  A gap is no problem but would waste address space for
-	 * remapping the port space.
-	 */
-	mv_pci_io_mem1_resource.start		= mv_io_size;
-	mv_pci_io_mem1_resource.end		= mv_io_size + io_size - 1;
-	mv_pci_mem1_resource.start		= mem0_base;
-	mv_pci_mem1_resource.end		= mem0_base + mem0_size - 1;
-	mv_bus1_controller.pcic.mem_offset	= mem0_base;
-	mv_bus1_controller.pcic.io_offset	= 0;
-
-	ioport_resource.end		= io_base + io_size -mv_io_base - 1;
-
-	register_pci_controller(&mv_bus1_controller.pcic);
-
-	mv_io_size = io_base + io_size - mv_io_base;
-}
-
-static __init int __init ocelot_c_pci_init(void)
-{
-	unsigned long io_v_base;
-	uint32_t enable;
-
-	enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
-
-	/*
-	 * We require at least one enabled I/O or PCI memory window or we
-	 * will ignore this PCI bus.  We ignore PCI windows 1, 2 and 3.
-	 */
-	if (enable & (0x01 <<  9) || enable & (0x01 << 10))
-		mv64340_pci0_init();
-
-	if (enable & (0x01 << 14) || enable & (0x01 << 15))
-		mv64340_pci1_init();
-
-	if (mv_io_size) {
-		io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
-		if (!io_v_base)
-			panic("Could not ioremap I/O port range");
-
-		set_io_port_base(io_v_base);
-	}
-
-	return 0;
-}
-
-arch_initcall(ocelot_c_pci_init);
diff --git a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c
index 75c1246..c1ac649 100644
--- a/arch/mips/pci/pci-sb1250.c
+++ b/arch/mips/pci/pci-sb1250.c
@@ -84,7 +84,7 @@
 	*(u32 *) (cfg_space + (addr & ~3)) = data;
 }
 
-int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return dev->irq;
 }
diff --git a/arch/mips/philips/pnx8550/common/platform.c b/arch/mips/philips/pnx8550/common/platform.c
index d43f56e..c839436 100644
--- a/arch/mips/philips/pnx8550/common/platform.c
+++ b/arch/mips/philips/pnx8550/common/platform.c
@@ -123,7 +123,7 @@
 	&pnx8550_uart_device,
 };
 
-int pnx8550_platform_init(void)
+static int __init pnx8550_platform_init(void)
 {
 	return platform_add_devices(pnx8550_platform_devices,
 			            ARRAY_SIZE(pnx8550_platform_devices));
diff --git a/arch/mips/philips/pnx8550/common/proc.c b/arch/mips/philips/pnx8550/common/proc.c
index 3f09755..92311e9 100644
--- a/arch/mips/philips/pnx8550/common/proc.c
+++ b/arch/mips/philips/pnx8550/common/proc.c
@@ -78,29 +78,33 @@
 {
 
 	// Create /proc/pnx8550
-        pnx8550_dir = create_proc_entry("pnx8550", S_IFDIR|S_IRUGO, NULL);
+        pnx8550_dir = proc_mkdir("pnx8550", NULL);
         if (!pnx8550_dir) {
                 printk(KERN_ERR "Can't create pnx8550 proc dir\n");
                 return -1;
         }
 
 	// Create /proc/pnx8550/timers
-        pnx8550_timers = create_proc_entry("timers", S_IFREG|S_IRUGO, pnx8550_dir );
-        if (pnx8550_timers){
-                pnx8550_timers->read_proc = pnx8550_timers_read;
-        }
-        else {
+        pnx8550_timers = create_proc_read_entry(
+		"timers",
+		0,
+		pnx8550_dir,
+		pnx8550_timers_read,
+		NULL);
+
+        if (!pnx8550_timers)
                 printk(KERN_ERR "Can't create pnx8550 timers proc file\n");
-        }
 
 	// Create /proc/pnx8550/registers
-        pnx8550_registers = create_proc_entry("registers", S_IFREG|S_IRUGO, pnx8550_dir );
-        if (pnx8550_registers){
-                pnx8550_registers->read_proc = pnx8550_registers_read;
-        }
-        else {
+        pnx8550_registers = create_proc_read_entry(
+		"registers",
+		0,
+		pnx8550_dir,
+		pnx8550_registers_read,
+		NULL);
+
+        if (!pnx8550_registers)
                 printk(KERN_ERR "Can't create pnx8550 registers proc file\n");
-        }
 
 	return 0;
 }
diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig
index 24d514c..abbd0bb 100644
--- a/arch/mips/pmc-sierra/Kconfig
+++ b/arch/mips/pmc-sierra/Kconfig
@@ -1,3 +1,49 @@
+choice
+	prompt "PMC-Sierra MSP SOC type"
+	depends on PMC_MSP
+
+config PMC_MSP4200_EVAL
+	bool "PMC-Sierra MSP4200 Eval Board"
+	select IRQ_MSP_SLP
+	select HW_HAS_PCI
+
+config PMC_MSP4200_GW
+	bool "PMC-Sierra MSP4200 VoIP Gateway"
+	select IRQ_MSP_SLP
+	select HW_HAS_PCI
+
+config PMC_MSP7120_EVAL
+	bool "PMC-Sierra MSP7120 Eval Board"
+	select SYS_SUPPORTS_MULTITHREADING
+	select IRQ_MSP_CIC
+	select HW_HAS_PCI
+
+config PMC_MSP7120_GW
+	bool "PMC-Sierra MSP7120 Residential Gateway"
+	select SYS_SUPPORTS_MULTITHREADING
+	select IRQ_MSP_CIC
+	select HW_HAS_PCI
+
+config PMC_MSP7120_FPGA
+	bool "PMC-Sierra MSP7120 FPGA"
+	select SYS_SUPPORTS_MULTITHREADING
+	select IRQ_MSP_CIC
+	select HW_HAS_PCI
+
+endchoice
+
+menu "Options for PMC-Sierra MSP chipsets"
+	depends on PMC_MSP
+
+config PMC_MSP_EMBEDDED_ROOTFS
+	bool "Root filesystem embedded in kernel image"
+	select MTD
+	select MTD_BLOCK
+	select MTD_PMC_MSP_RAMROOT
+	select MTD_RAM
+
+endmenu
+
 config HYPERTRANSPORT
 	bool "Hypertransport Support for PMC-Sierra Yosemite"
 	depends on PMC_YOSEMITE
diff --git a/arch/mips/pmc-sierra/msp71xx/Makefile b/arch/mips/pmc-sierra/msp71xx/Makefile
new file mode 100644
index 0000000..4bba79c
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the PMC-Sierra MSP SOCs
+#
+obj-y += msp_prom.o msp_setup.o msp_irq.o \
+	 msp_time.o msp_serial.o msp_elb.o
+obj-$(CONFIG_PMC_MSP7120_GW) += msp_hwbutton.o
+obj-$(CONFIG_IRQ_MSP_SLP) += msp_irq_slp.o
+obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o
+obj-$(CONFIG_PCI) += msp_pci.o
+obj-$(CONFIG_MSPETH) += msp_eth.o
+obj-$(CONFIG_USB_MSP71XX) += msp_usb.o
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_elb.c b/arch/mips/pmc-sierra/msp71xx/msp_elb.c
new file mode 100644
index 0000000..3e96410
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_elb.c
@@ -0,0 +1,46 @@
+/*
+ * Sets up the proper Chip Select configuration registers.  It is assumed that
+ * PMON sets up the ADDR and MASK registers properly.
+ *
+ * Copyright 2005-2006 PMC-Sierra, Inc.
+ * Author: Marc St-Jean, Marc_St-Jean@pmc-sierra.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <msp_regs.h>
+
+static int __init msp_elb_setup(void)
+{
+#if defined(CONFIG_PMC_MSP7120_GW) \
+ || defined(CONFIG_PMC_MSP7120_EVAL)
+	/*
+	 * Force all CNFG to be identical and equal to CS0,
+	 * according to OPS doc
+	 */
+	*CS1_CNFG_REG = *CS2_CNFG_REG = *CS3_CNFG_REG = *CS0_CNFG_REG;
+#endif
+	return 0;
+}
+
+subsys_initcall(msp_elb_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c
new file mode 100644
index 0000000..6fa8572
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c
@@ -0,0 +1,179 @@
+/*
+ * Sets up interrupt handlers for various hardware switches which are
+ * connected to interrupt lines.
+ *
+ * Copyright 2005-2207 PMC-Sierra, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <msp_int.h>
+#include <msp_regs.h>
+#include <msp_regops.h>
+#ifdef CONFIG_PMCTWILED
+#include <msp_led_macros.h>
+#endif
+
+/* For hwbutton_interrupt->initial_state */
+#define HWBUTTON_HI	0x1
+#define HWBUTTON_LO	0x2
+
+/*
+ * This struct describes a hardware button
+ */
+struct hwbutton_interrupt {
+	char *name;			/* Name of button */
+	int irq;			/* Actual LINUX IRQ */
+	int eirq;			/* Extended IRQ number (0-7) */
+	int initial_state;		/* The "normal" state of the switch */
+	void (*handle_hi)(void *);	/* Handler: switch input has gone HI */
+	void (*handle_lo)(void *);	/* Handler: switch input has gone LO */
+	void *data;			/* Optional data to pass to handler */
+};
+
+#ifdef CONFIG_PMC_MSP7120_GW
+extern void msp_restart(char *);
+
+static void softreset_push(void *data)
+{
+	printk(KERN_WARNING "SOFTRESET switch was pushed\n");
+
+	/*
+	 * In the future you could move this to the release handler,
+	 * timing the difference between the 'push' and 'release', and only
+	 * doing this ungraceful restart if the button has been down for
+	 * a certain amount of time; otherwise doing a graceful restart.
+	 */
+
+	msp_restart(NULL);
+}
+
+static void softreset_release(void *data)
+{
+	printk(KERN_WARNING "SOFTRESET switch was released\n");
+
+	/* Do nothing */
+}
+
+static void standby_on(void *data)
+{
+	printk(KERN_WARNING "STANDBY switch was set to ON (not implemented)\n");
+
+	/* TODO: Put board in standby mode */
+#ifdef CONFIG_PMCTWILED
+	msp_led_turn_off(MSP_LED_PWRSTANDBY_GREEN);
+	msp_led_turn_on(MSP_LED_PWRSTANDBY_RED);
+#endif
+}
+
+static void standby_off(void *data)
+{
+	printk(KERN_WARNING
+		"STANDBY switch was set to OFF (not implemented)\n");
+
+	/* TODO: Take out of standby mode */
+#ifdef CONFIG_PMCTWILED
+	msp_led_turn_on(MSP_LED_PWRSTANDBY_GREEN);
+	msp_led_turn_off(MSP_LED_PWRSTANDBY_RED);
+#endif
+}
+
+static struct hwbutton_interrupt softreset_sw = {
+	.name = "Softreset button",
+	.irq = MSP_INT_EXT0,
+	.eirq = 0,
+	.initial_state = HWBUTTON_HI,
+	.handle_hi = softreset_release,
+	.handle_lo = softreset_push,
+	.data = NULL,
+};
+
+static struct hwbutton_interrupt standby_sw = {
+	.name = "Standby switch",
+	.irq = MSP_INT_EXT1,
+	.eirq = 1,
+	.initial_state = HWBUTTON_HI,
+	.handle_hi = standby_off,
+	.handle_lo = standby_on,
+	.data = NULL,
+};
+#endif /* CONFIG_PMC_MSP7120_GW */
+
+static irqreturn_t hwbutton_handler(int irq, void *data)
+{
+	struct hwbutton_interrupt *hirq = data;
+	unsigned long cic_ext = *CIC_EXT_CFG_REG;
+
+	if (irq != hirq->irq)
+		return IRQ_NONE;
+
+	if (CIC_EXT_IS_ACTIVE_HI(cic_ext, hirq->eirq)) {
+		/* Interrupt: pin is now HI */
+		CIC_EXT_SET_ACTIVE_LO(cic_ext, hirq->eirq);
+		hirq->handle_hi(hirq->data);
+	} else {
+		/* Interrupt: pin is now LO */
+		CIC_EXT_SET_ACTIVE_HI(cic_ext, hirq->eirq);
+		hirq->handle_lo(hirq->data);
+	}
+
+	/*
+	 * Invert the POLARITY of this level interrupt to ack the interrupt
+	 * Thus next state change will invoke the opposite message
+	 */
+	*CIC_EXT_CFG_REG = cic_ext;
+
+	return IRQ_HANDLED;
+}
+
+static int msp_hwbutton_register(struct hwbutton_interrupt *hirq)
+{
+	unsigned long cic_ext;
+
+	if (hirq->handle_hi == NULL || hirq->handle_lo == NULL)
+		return -EINVAL;
+
+	cic_ext = *CIC_EXT_CFG_REG;
+	CIC_EXT_SET_TRIGGER_LEVEL(cic_ext, hirq->eirq);
+	if (hirq->initial_state == HWBUTTON_HI)
+		CIC_EXT_SET_ACTIVE_LO(cic_ext, hirq->eirq);
+	else
+		CIC_EXT_SET_ACTIVE_HI(cic_ext, hirq->eirq);
+	*CIC_EXT_CFG_REG = cic_ext;
+
+	return request_irq(hirq->irq, hwbutton_handler, SA_INTERRUPT,
+				hirq->name, (void *)hirq);
+}
+
+static int __init msp_hwbutton_setup(void)
+{
+#ifdef CONFIG_PMC_MSP7120_GW
+	msp_hwbutton_register(&softreset_sw);
+	msp_hwbutton_register(&standby_sw);
+#endif
+	return 0;
+}
+
+subsys_initcall(msp_hwbutton_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq.c b/arch/mips/pmc-sierra/msp71xx/msp_irq.c
new file mode 100644
index 0000000..734d598
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq.c
@@ -0,0 +1,124 @@
+/*
+ * IRQ vector handles
+ *
+ * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/time.h>
+
+#include <asm/irq_cpu.h>
+
+#include <msp_int.h>
+
+extern void msp_int_handle(void);
+
+/* SLP bases systems */
+extern void msp_slp_irq_init(void);
+extern void msp_slp_irq_dispatch(void);
+
+/* CIC based systems */
+extern void msp_cic_irq_init(void);
+extern void msp_cic_irq_dispatch(void);
+
+/*
+ * The PMC-Sierra MSP interrupts are arranged in a 3 level cascaded
+ * hierarchical system.  The first level are the direct MIPS interrupts
+ * and are assigned the interrupt range 0-7.  The second level is the SLM
+ * interrupt controller and is assigned the range 8-39.  The third level
+ * comprises the Peripherial block, the PCI block, the PCI MSI block and
+ * the SLP.  The PCI interrupts and the SLP errors are handled by the
+ * relevant subsystems so the core interrupt code needs only concern
+ * itself with the Peripheral block.  These are assigned interrupts in
+ * the range 40-71.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	u32 pending;
+
+	pending = read_c0_status() & read_c0_cause();
+
+	/*
+	 * jump to the correct interrupt routine
+	 * These are arranged in priority order and the timer
+	 * comes first!
+	 */
+
+#ifdef CONFIG_IRQ_MSP_CIC	/* break out the CIC stuff for now */
+	if (pending & C_IRQ4)	/* do the peripherals first, that's the timer */
+		msp_cic_irq_dispatch();
+
+	else if (pending & C_IRQ0)
+		do_IRQ(MSP_INT_MAC0);
+
+	else if (pending & C_IRQ1)
+		do_IRQ(MSP_INT_MAC1);
+
+	else if (pending & C_IRQ2)
+		do_IRQ(MSP_INT_USB);
+
+	else if (pending & C_IRQ3)
+		do_IRQ(MSP_INT_SAR);
+
+	else if (pending & C_IRQ5)
+		do_IRQ(MSP_INT_SEC);
+
+#else
+	if (pending & C_IRQ5)
+		do_IRQ(MSP_INT_TIMER);
+
+	else if (pending & C_IRQ0)
+		do_IRQ(MSP_INT_MAC0);
+
+	else if (pending & C_IRQ1)
+		do_IRQ(MSP_INT_MAC1);
+
+	else if (pending & C_IRQ3)
+		do_IRQ(MSP_INT_VE);
+
+	else if (pending & C_IRQ4)
+		msp_slp_irq_dispatch();
+#endif
+
+	else if (pending & C_SW0)	/* do software after hardware */
+		do_IRQ(MSP_INT_SW0);
+
+	else if (pending & C_SW1)
+		do_IRQ(MSP_INT_SW1);
+}
+
+static struct irqaction cascade_msp = {
+	.handler = no_action,
+	.name	 = "MSP cascade"
+};
+
+
+void __init arch_init_irq(void)
+{
+	/* initialize the 1st-level CPU based interrupt controller */
+	mips_cpu_irq_init();
+
+#ifdef CONFIG_IRQ_MSP_CIC
+	msp_cic_irq_init();
+
+	/* setup the cascaded interrupts */
+	setup_irq(MSP_INT_CIC, &cascade_msp);
+	setup_irq(MSP_INT_PER, &cascade_msp);
+#else
+	/* setup the 2nd-level SLP register based interrupt controller */
+	msp_slp_irq_init();
+
+	/* setup the cascaded SLP/PER interrupts */
+	setup_irq(MSP_INT_SLP, &cascade_msp);
+	setup_irq(MSP_INT_PER, &cascade_msp);
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
new file mode 100644
index 0000000..5175357
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
@@ -0,0 +1,134 @@
+/*
+ * This file define the irq handler for MSP SLM subsystem interrupts.
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc, derived from irq_cpu.c
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+
+#include <msp_cic_int.h>
+#include <msp_regs.h>
+
+/*
+ * NOTE: We are only enabling support for VPE0 right now.
+ */
+
+static inline void unmask_msp_cic_irq(unsigned int irq)
+{
+
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*CIC_VPE0_MSK_REG |= (1 << (irq - MSP_CIC_INTBASE));
+	else
+		*PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE));
+}
+
+static inline void mask_msp_cic_irq(unsigned int irq)
+{
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*CIC_VPE0_MSK_REG &= ~(1 << (irq - MSP_CIC_INTBASE));
+	else
+		*PER_INT_MSK_REG &= ~(1 << (irq - MSP_PER_INTBASE));
+}
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues.  Same for msp_cic_irq_end.
+ */
+static inline void ack_msp_cic_irq(unsigned int irq)
+{
+	mask_msp_cic_irq(irq);
+
+	/*
+	 * only really necessary for 18, 16-14 and sometimes 3:0 (since
+	 * these can be edge sensitive) but it doesn't hurt for the others.
+	 */
+
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*CIC_STS_REG = (1 << (irq - MSP_CIC_INTBASE));
+	else
+		*PER_INT_STS_REG = (1 << (irq - MSP_PER_INTBASE));
+}
+
+static struct irq_chip msp_cic_irq_controller = {
+	.name = "MSP_CIC",
+	.ack = ack_msp_cic_irq,
+	.mask = ack_msp_cic_irq,
+	.mask_ack = ack_msp_cic_irq,
+	.unmask = unmask_msp_cic_irq,
+};
+
+
+void __init msp_cic_irq_init(void)
+{
+	int i;
+
+	/* Mask/clear interrupts. */
+	*CIC_VPE0_MSK_REG = 0x00000000;
+	*PER_INT_MSK_REG  = 0x00000000;
+	*CIC_STS_REG      = 0xFFFFFFFF;
+	*PER_INT_STS_REG  = 0xFFFFFFFF;
+
+#if defined(CONFIG_PMC_MSP7120_GW) || \
+    defined(CONFIG_PMC_MSP7120_EVAL)
+	/*
+	 * The MSP7120 RG and EVBD boards use IRQ[6:4] for PCI.
+	 * These inputs map to EXT_INT_POL[6:4] inside the CIC.
+	 * They are to be active low, level sensitive.
+	 */
+	*CIC_EXT_CFG_REG &= 0xFFFF8F8F;
+#endif
+
+	/* initialize all the IRQ descriptors */
+	for (i = MSP_CIC_INTBASE; i < MSP_PER_INTBASE + 32; i++)
+		set_irq_chip_and_handler(i, &msp_cic_irq_controller,
+					 handle_level_irq);
+}
+
+void msp_cic_irq_dispatch(void)
+{
+	u32 pending;
+	int intbase;
+
+	intbase = MSP_CIC_INTBASE;
+	pending = *CIC_STS_REG & *CIC_VPE0_MSK_REG;
+
+	/* check for PER interrupt */
+	if (pending == (1 << (MSP_INT_PER - MSP_CIC_INTBASE))) {
+		intbase = MSP_PER_INTBASE;
+		pending = *PER_INT_STS_REG & *PER_INT_MSK_REG;
+	}
+
+	/* check for spurious interrupt */
+	if (pending == 0x00000000) {
+		printk(KERN_ERR
+			"Spurious %s interrupt? status %08x, mask %08x\n",
+			(intbase == MSP_CIC_INTBASE) ? "CIC" : "PER",
+			(intbase == MSP_CIC_INTBASE) ?
+				*CIC_STS_REG : *PER_INT_STS_REG,
+			(intbase == MSP_CIC_INTBASE) ?
+				*CIC_VPE0_MSK_REG : *PER_INT_MSK_REG);
+		return;
+	}
+
+	/* check for the timer and dispatch it first */
+	if ((intbase == MSP_CIC_INTBASE) &&
+	    (pending & (1 << (MSP_INT_VPE0_TIMER - MSP_CIC_INTBASE))))
+		do_IRQ(MSP_INT_VPE0_TIMER);
+	else
+		do_IRQ(ffs(pending) + intbase - 1);
+}
+
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c b/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
new file mode 100644
index 0000000..f5f1b8d
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
@@ -0,0 +1,109 @@
+/*
+ * This file define the irq handler for MSP SLM subsystem interrupts.
+ *
+ * Copyright 2005-2006 PMC-Sierra, Inc, derived from irq_cpu.c
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <msp_slp_int.h>
+#include <msp_regs.h>
+
+static inline void unmask_msp_slp_irq(unsigned int irq)
+{
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*SLP_INT_MSK_REG |= (1 << (irq - MSP_SLP_INTBASE));
+	else
+		*PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE));
+}
+
+static inline void mask_msp_slp_irq(unsigned int irq)
+{
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*SLP_INT_MSK_REG &= ~(1 << (irq - MSP_SLP_INTBASE));
+	else
+		*PER_INT_MSK_REG &= ~(1 << (irq - MSP_PER_INTBASE));
+}
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues.  Same for msp_slp_irq_end.
+ */
+static inline void ack_msp_slp_irq(unsigned int irq)
+{
+	mask_slp_irq(irq);
+
+	/*
+	 * only really necessary for 18, 16-14 and sometimes 3:0 (since
+	 * these can be edge sensitive) but it doesn't hurt  for the others.
+	 */
+
+	/* check for PER interrupt range */
+	if (irq < MSP_PER_INTBASE)
+		*SLP_INT_STS_REG = (1 << (irq - MSP_SLP_INTBASE));
+	else
+		*PER_INT_STS_REG = (1 << (irq - MSP_PER_INTBASE));
+}
+
+static struct irq_chip msp_slp_irq_controller = {
+	.name = "MSP_SLP",
+	.ack = ack_msp_slp_irq,
+	.mask = ack_msp_slp_irq,
+	.mask_ack = ack_msp_slp_irq,
+	.unmask = unmask_msp_slp_irq,
+};
+
+void __init msp_slp_irq_init(void)
+{
+	int i;
+
+	/* Mask/clear interrupts. */
+	*SLP_INT_MSK_REG = 0x00000000;
+	*PER_INT_MSK_REG = 0x00000000;
+	*SLP_INT_STS_REG = 0xFFFFFFFF;
+	*PER_INT_STS_REG = 0xFFFFFFFF;
+
+	/* initialize all the IRQ descriptors */
+	for (i = MSP_SLP_INTBASE; i < MSP_PER_INTBASE + 32; i++)
+		set_irq_chip_and_handler(i, &msp_slp_irq_controller
+					 handle_level_irq);
+}
+
+void msp_slp_irq_dispatch(void)
+{
+	u32 pending;
+	int intbase;
+
+	intbase = MSP_SLP_INTBASE;
+	pending = *SLP_INT_STS_REG & *SLP_INT_MSK_REG;
+
+	/* check for PER interrupt */
+	if (pending == (1 << (MSP_INT_PER - MSP_SLP_INTBASE))) {
+		intbase = MSP_PER_INTBASE;
+		pending = *PER_INT_STS_REG & *PER_INT_MSK_REG;
+	}
+
+	/* check for spurious interrupt */
+	if (pending == 0x00000000) {
+		printk(KERN_ERR "Spurious %s interrupt?\n",
+			(intbase == MSP_SLP_INTBASE) ? "SLP" : "PER");
+		return;
+	}
+
+	/* dispatch the irq */
+	do_IRQ(ffs(pending) + intbase - 1);
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_pci.c b/arch/mips/pmc-sierra/msp71xx/msp_pci.c
new file mode 100644
index 0000000..f764fe7
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_pci.c
@@ -0,0 +1,50 @@
+/*
+ * The setup file for PCI related hardware on PMC-Sierra MSP processors.
+ *
+ * Copyright 2005-2006 PMC-Sierra, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+extern void msp_pci_init(void);
+
+static int __init msp_pci_setup(void)
+{
+#if 0 /* Linux 2.6 initialization code to be completed */
+	if (getdeviceid() & DEV_ID_SINGLE_PC) {
+		/* If single card mode */
+		slmRegs	*sreg = (slmRegs *) SREG_BASE;
+
+		sreg->single_pc_enable = SINGLE_PCCARD;
+	}
+#endif
+
+	msp_pci_init();
+
+	return 0;
+}
+
+subsys_initcall(msp_pci_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_prom.c b/arch/mips/pmc-sierra/msp71xx/msp_prom.c
new file mode 100644
index 0000000..e5bd548
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_prom.c
@@ -0,0 +1,566 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *    PROM library initialisation code, assuming a version of
+ *    pmon is the boot code.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#ifdef CONFIG_CRAMFS
+#include <linux/cramfs_fs.h>
+#endif
+#ifdef CONFIG_SQUASHFS
+#include <linux/squashfs_fs.h>
+#endif
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm-generic/sections.h>
+#include <asm/page.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+/* global PROM environment variables and pointers */
+int prom_argc;
+char **prom_argv, **prom_envp;
+int *prom_vec;
+
+/* debug flag */
+int init_debug = 1;
+
+/* memory blocks */
+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
+
+/* default feature sets */
+static char msp_default_features[] =
+#if defined(CONFIG_PMC_MSP4200_EVAL) \
+ || defined(CONFIG_PMC_MSP4200_GW)
+	"ERER";
+#elif defined(CONFIG_PMC_MSP7120_EVAL) \
+ || defined(CONFIG_PMC_MSP7120_GW)
+	"EMEMSP";
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+	"EMEM";
+#endif
+
+/* conversion functions */
+static inline unsigned char str2hexnum(unsigned char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	return 0; /* foo */
+}
+
+static inline int str2eaddr(unsigned char *ea, unsigned char *str)
+{
+	int index = 0;
+	unsigned char num = 0;
+
+	while (*str != '\0') {
+		if ((*str == '.') || (*str == ':')) {
+			ea[index++] = num;
+			num = 0;
+			str++;
+		} else {
+			num = num << 4;
+			num |= str2hexnum(*str++);
+		}
+	}
+
+	if (index == 5)	{
+		ea[index++] = num;
+		return 0;
+	} else
+		return -1;
+}
+EXPORT_SYMBOL(str2eaddr);
+
+static inline unsigned long str2hex(unsigned char *str)
+{
+	int value = 0;
+
+	while (*str) {
+		value = value << 4;
+		value |= str2hexnum(*str++);
+	}
+
+	return value;
+}
+
+/* function to query the system information */
+const char *get_system_type(void)
+{
+#if defined(CONFIG_PMC_MSP4200_EVAL)
+	return "PMC-Sierra MSP4200 Eval Board";
+#elif defined(CONFIG_PMC_MSP4200_GW)
+	return "PMC-Sierra MSP4200 VoIP Gateway";
+#elif defined(CONFIG_PMC_MSP7120_EVAL)
+	return "PMC-Sierra MSP7120 Eval Board";
+#elif defined(CONFIG_PMC_MSP7120_GW)
+	return "PMC-Sierra MSP7120 Residential Gateway";
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+	return "PMC-Sierra MSP7120 FPGA";
+#else
+	#error "What is the type of *your* MSP?"
+#endif
+}
+
+int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr)
+{
+	char *ethaddr_str;
+
+	ethaddr_str = prom_getenv(ethaddr_name);
+	if (!ethaddr_str) {
+		printk(KERN_WARNING "%s not set in boot prom\n", ethaddr_name);
+		return -1;
+	}
+
+	if (str2eaddr(ethernet_addr, ethaddr_str) == -1) {
+		printk(KERN_WARNING "%s badly formatted-<%s>\n",
+			ethaddr_name, ethaddr_str);
+		return -1;
+	}
+
+	if (init_debug > 1) {
+		int i;
+		printk(KERN_DEBUG "get_ethernet_addr: for %s ", ethaddr_name);
+		for (i = 0; i < 5; i++)
+			printk(KERN_DEBUG "%02x:",
+				(unsigned char)*(ethernet_addr+i));
+		printk(KERN_DEBUG "%02x\n", *(ethernet_addr+i));
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(get_ethernet_addr);
+
+static char *get_features(void)
+{
+	char *feature = prom_getenv(FEATURES);
+
+	if (feature == NULL) {
+		/* default features based on MACHINE_TYPE */
+		feature = msp_default_features;
+	}
+
+	return feature;
+}
+
+static char test_feature(char c)
+{
+	char *feature = get_features();
+
+	while (*feature) {
+		if (*feature++ == c)
+			return *feature;
+		feature++;
+	}
+
+	return FEATURE_NOEXIST;
+}
+
+unsigned long get_deviceid(void)
+{
+	char *deviceid = prom_getenv(DEVICEID);
+
+	if (deviceid == NULL)
+		return *DEV_ID_REG;
+	else
+		return str2hex(deviceid);
+}
+
+char identify_pci(void)
+{
+	return test_feature(PCI_KEY);
+}
+EXPORT_SYMBOL(identify_pci);
+
+char identify_pcimux(void)
+{
+	return test_feature(PCIMUX_KEY);
+}
+
+char identify_sec(void)
+{
+	return test_feature(SEC_KEY);
+}
+EXPORT_SYMBOL(identify_sec);
+
+char identify_spad(void)
+{
+	return test_feature(SPAD_KEY);
+}
+EXPORT_SYMBOL(identify_spad);
+
+char identify_tdm(void)
+{
+	return test_feature(TDM_KEY);
+}
+EXPORT_SYMBOL(identify_tdm);
+
+char identify_zsp(void)
+{
+	return test_feature(ZSP_KEY);
+}
+EXPORT_SYMBOL(identify_zsp);
+
+static char identify_enetfeature(char key, unsigned long interface_num)
+{
+	char *feature = get_features();
+
+	while (*feature) {
+		if (*feature++ == key && interface_num-- == 0)
+			return *feature;
+		feature++;
+	}
+
+	return FEATURE_NOEXIST;
+}
+
+char identify_enet(unsigned long interface_num)
+{
+	return identify_enetfeature(ENET_KEY, interface_num);
+}
+EXPORT_SYMBOL(identify_enet);
+
+char identify_enetTxD(unsigned long interface_num)
+{
+	return identify_enetfeature(ENETTXD_KEY, interface_num);
+}
+EXPORT_SYMBOL(identify_enetTxD);
+
+unsigned long identify_family(void)
+{
+	unsigned long deviceid;
+
+	deviceid = get_deviceid();
+
+	return deviceid & CPU_DEVID_FAMILY;
+}
+EXPORT_SYMBOL(identify_family);
+
+unsigned long identify_revision(void)
+{
+	unsigned long deviceid;
+
+	deviceid = get_deviceid();
+
+	return deviceid & CPU_DEVID_REVISION;
+}
+EXPORT_SYMBOL(identify_revision);
+
+/* PROM environment functions */
+char *prom_getenv(char *env_name)
+{
+	/*
+	 * Return a pointer to the given environment variable.  prom_envp
+	 * points to a null terminated array of pointers to variables.
+	 * Environment variables are stored in the form of "memsize=64"
+	 */
+
+	char **var = prom_envp;
+	int i = strlen(env_name);
+
+	while (*var) {
+		if (strncmp(env_name, *var, i) == 0) {
+			return (*var + strlen(env_name) + 1);
+		}
+		var++;
+	}
+
+	return NULL;
+}
+
+/* PROM commandline functions */
+char *prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
+EXPORT_SYMBOL(prom_getcmdline);
+
+void  __init prom_init_cmdline(void)
+{
+	char *cp;
+	int actr;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	cp = &(arcs_cmdline[0]);
+	while (actr < prom_argc) {
+		strcpy(cp, prom_argv[actr]);
+		cp += strlen(prom_argv[actr]);
+		*cp++ = ' ';
+		actr++;
+	}
+	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+		--cp;
+	*cp = '\0';
+}
+
+/* memory allocation functions */
+static int __init prom_memtype_classify(unsigned int type)
+{
+	switch (type) {
+	case yamon_free:
+		return BOOT_MEM_RAM;
+	case yamon_prom:
+		return BOOT_MEM_ROM_DATA;
+	default:
+		return BOOT_MEM_RESERVED;
+	}
+}
+
+void __init prom_meminit(void)
+{
+	struct prom_pmemblock *p;
+
+	p = prom_getmdesc();
+
+	while (p->size) {
+		long type;
+		unsigned long base, size;
+
+		type = prom_memtype_classify(p->type);
+		base = p->base;
+		size = p->size;
+
+		add_memory_region(base, size, type);
+		p++;
+	}
+}
+
+void __init prom_free_prom_memory(void)
+{
+	int	argc;
+	char	**argv;
+	char	**envp;
+	char	*ptr;
+	int	len = 0;
+	int	i;
+	unsigned long addr;
+
+	/*
+	 * preserve environment variables and command line from pmon/bbload
+	 * first preserve the command line
+	 */
+	for (argc = 0; argc < prom_argc; argc++) {
+		len += sizeof(char *);			/* length of pointer */
+		len += strlen(prom_argv[argc]) + 1;	/* length of string */
+	}
+	len += sizeof(char *);		/* plus length of null pointer */
+
+	argv = kmalloc(len, GFP_KERNEL);
+	ptr = (char *) &argv[prom_argc + 1];	/* strings follow array */
+
+	for (argc = 0; argc < prom_argc; argc++) {
+		argv[argc] = ptr;
+		strcpy(ptr, prom_argv[argc]);
+		ptr += strlen(prom_argv[argc]) + 1;
+	}
+	argv[prom_argc] = NULL;		/* end array with null pointer */
+	prom_argv = argv;
+
+	/* next preserve the environment variables */
+	len = 0;
+	i = 0;
+	for (envp = prom_envp; *envp != NULL; envp++) {
+		i++;		/* count number of environment variables */
+		len += sizeof(char *);		/* length of pointer */
+		len += strlen(*envp) + 1;	/* length of string */
+	}
+	len += sizeof(char *);		/* plus length of null pointer */
+
+	envp = kmalloc(len, GFP_KERNEL);
+	ptr = (char *) &envp[i+1];
+
+	for (argc = 0; argc < i; argc++) {
+		envp[argc] = ptr;
+		strcpy(ptr, prom_envp[argc]);
+		ptr += strlen(prom_envp[argc]) + 1;
+	}
+	envp[i] = NULL;			/* end array with null pointer */
+	prom_envp = envp;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+			continue;
+
+		addr = boot_mem_map.map[i].addr;
+		free_init_pages("prom memory",
+				addr, addr + boot_mem_map.map[i].size);
+	}
+}
+
+struct prom_pmemblock *__init prom_getmdesc(void)
+{
+	static char	memsz_env[] __initdata = "memsize";
+	static char	heaptop_env[] __initdata = "heaptop";
+	char		*str;
+	unsigned int	memsize;
+	unsigned int	heaptop;
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+	void		*ramroot_start;
+	unsigned long	ramroot_size;
+#endif
+	int i;
+
+	str = prom_getenv(memsz_env);
+	if (!str) {
+		ppfinit("memsize not set in boot prom, "
+			"set to default (32Mb)\n");
+		memsize = 0x02000000;
+	} else {
+		memsize = simple_strtol(str, NULL, 0);
+
+		if (memsize == 0) {
+			/* if memsize is a bad size, use reasonable default */
+			memsize = 0x02000000;
+		}
+
+		/* convert to physical address (removing caching bits, etc) */
+		memsize = CPHYSADDR(memsize);
+	}
+
+	str = prom_getenv(heaptop_env);
+	if (!str) {
+		heaptop = CPHYSADDR((u32)&_text);
+		ppfinit("heaptop not set in boot prom, "
+			"set to default 0x%08x\n", heaptop);
+	} else {
+		heaptop = simple_strtol(str, NULL, 16);
+		if (heaptop == 0) {
+			/* heaptop conversion bad, might have 0xValue */
+			heaptop = simple_strtol(str, NULL, 0);
+
+			if (heaptop == 0) {
+				/* heaptop still bad, use reasonable default */
+				heaptop = CPHYSADDR((u32)&_text);
+			}
+		}
+
+		/* convert to physical address (removing caching bits, etc) */
+		heaptop = CPHYSADDR((u32)heaptop);
+	}
+
+	/* the base region */
+	i = 0;
+	mdesc[i].type = BOOT_MEM_RESERVED;
+	mdesc[i].base = 0x00000000;
+	mdesc[i].size = PAGE_ALIGN(0x300 + 0x80);
+		/* jtag interrupt vector + sizeof vector */
+
+	/* PMON data */
+	if (heaptop > mdesc[i].base + mdesc[i].size) {
+		i++;			/* 1 */
+		mdesc[i].type = BOOT_MEM_ROM_DATA;
+		mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
+		mdesc[i].size = heaptop - mdesc[i].base;
+	}
+
+	/* end of PMON data to start of kernel -- probably zero .. */
+	if (heaptop != CPHYSADDR((u32)_text)) {
+		i++;	/* 2 */
+		mdesc[i].type = BOOT_MEM_RAM;
+		mdesc[i].base = heaptop;
+		mdesc[i].size = CPHYSADDR((u32)_text) - mdesc[i].base;
+	}
+
+	/*  kernel proper */
+	i++;			/* 3 */
+	mdesc[i].type = BOOT_MEM_RESERVED;
+	mdesc[i].base = CPHYSADDR((u32)_text);
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+	if (get_ramroot(&ramroot_start, &ramroot_size)) {
+		/*
+		 * Rootfs in RAM -- follows kernel
+		 * Combine rootfs image with kernel block so a
+		 * page (4k) isn't wasted between memory blocks
+		 */
+		mdesc[i].size = CPHYSADDR(PAGE_ALIGN(
+			(u32)ramroot_start + ramroot_size)) - mdesc[i].base;
+	} else
+#endif
+		mdesc[i].size = CPHYSADDR(PAGE_ALIGN(
+			(u32)_end)) - mdesc[i].base;
+
+	/* Remainder of RAM -- under memsize */
+	i++;			/* 5 */
+	mdesc[i].type = yamon_free;
+	mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
+	mdesc[i].size = memsize - mdesc[i].base;
+
+	return &mdesc[0];
+}
+
+/* rootfs functions */
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+bool get_ramroot(void **start, unsigned long *size)
+{
+	extern char _end[];
+
+	/* Check for start following the end of the kernel */
+	void *check_start = (void *)_end;
+
+	/* Check for supported rootfs types */
+#ifdef CONFIG_CRAMFS
+	if (*(__u32 *)check_start == CRAMFS_MAGIC) {
+		/* Get CRAMFS size */
+		*start = check_start;
+		*size = PAGE_ALIGN(((struct cramfs_super *)
+				   check_start)->size);
+
+		return true;
+	}
+#endif
+#ifdef CONFIG_SQUASHFS
+	if (*((unsigned int *)check_start) == SQUASHFS_MAGIC) {
+		/* Get SQUASHFS size */
+		*start = check_start;
+		*size = PAGE_ALIGN(((struct squashfs_super_block *)
+				   check_start)->bytes_used);
+
+		return true;
+	}
+#endif
+
+	return false;
+}
+EXPORT_SYMBOL(get_ramroot);
+#endif
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
new file mode 100644
index 0000000..8f69b78
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
@@ -0,0 +1,256 @@
+/*
+ * The generic setup file for PMC-Sierra MSP processors
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc,
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/bootinfo.h>
+#include <asm/cacheflush.h>
+#include <asm/r4kcache.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+#include <msp_regops.h>
+#include <msp_gpio.h>
+#define MSP_BOARD_RESET_GPIO	9
+#endif
+
+extern void msp_timer_init(void);
+extern void msp_serial_setup(void);
+extern void pmctwiled_setup(void);
+
+#if defined(CONFIG_PMC_MSP7120_EVAL) || \
+    defined(CONFIG_PMC_MSP7120_GW) || \
+    defined(CONFIG_PMC_MSP7120_FPGA)
+/*
+ * Performs the reset for MSP7120-based boards
+ */
+void msp7120_reset(void)
+{
+	void *start, *end, *iptr;
+	register int i;
+
+	/* Diasble all interrupts */
+	local_irq_disable();
+#ifdef CONFIG_SYS_SUPPORTS_MULTITHREADING
+	dvpe();
+#endif
+
+	/* Cache the reset code of this function */
+	__asm__ __volatile__ (
+		"	.set	push				\n"
+		"	.set	mips3				\n"
+		"	la	%0,startpoint			\n"
+		"	la	%1,endpoint			\n"
+		"	.set	pop				\n"
+		: "=r" (start), "=r" (end)
+		:
+	);
+
+	for (iptr = (void *)((unsigned int)start & ~(L1_CACHE_BYTES - 1));
+	     iptr < end; iptr += L1_CACHE_BYTES)
+		cache_op(Fill, iptr);
+
+	__asm__ __volatile__ (
+		"startpoint:					\n"
+	);
+
+	/* Put the DDRC into self-refresh mode */
+	DDRC_INDIRECT_WRITE(DDRC_CTL(10), 0xb, 1 << 16);
+
+	/*
+	 * IMPORTANT!
+	 * DO NOT do anything from here on out that might even
+	 * think about fetching from RAM - i.e., don't call any
+	 * non-inlined functions, and be VERY sure that any inline
+	 * functions you do call do NOT access any sort of RAM
+	 * anywhere!
+	 */
+
+	/* Wait a bit for the DDRC to settle */
+	for (i = 0; i < 100000000; i++);
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+	/*
+	 * Set GPIO 9 HI, (tied to board reset logic)
+	 * GPIO 9 is the 4th GPIO of register 3
+	 *
+	 * NOTE: We cannot use the higher-level msp_gpio_mode()/out()
+	 * as GPIO char driver may not be enabled and it would look up
+	 * data inRAM!
+	 */
+	set_value_reg32(GPIO_CFG3_REG,
+			basic_mode_mask(MSP_BOARD_RESET_GPIO),
+			basic_mode(MSP_GPIO_OUTPUT, MSP_BOARD_RESET_GPIO));
+	set_reg32(GPIO_DATA3_REG,
+			basic_data_mask(MSP_BOARD_RESET_GPIO));
+
+	/*
+	 * In case GPIO9 doesn't reset the board (jumper configurable!)
+	 * fallback to device reset below.
+	 */
+#endif
+	/* Set bit 1 of the MSP7120 reset register */
+	*RST_SET_REG = 0x00000001;
+
+	__asm__ __volatile__ (
+		"endpoint:					\n"
+	);
+}
+#endif
+
+void msp_restart(char *command)
+{
+	printk(KERN_WARNING "Now rebooting .......\n");
+
+#if defined(CONFIG_PMC_MSP7120_EVAL) || \
+    defined(CONFIG_PMC_MSP7120_GW) || \
+    defined(CONFIG_PMC_MSP7120_FPGA)
+	msp7120_reset();
+#else
+	/* No chip-specific reset code, just jump to the ROM reset vector */
+	set_c0_status(ST0_BEV | ST0_ERL);
+	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+	flush_cache_all();
+	write_c0_wired(0);
+
+	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+#endif
+}
+
+void msp_halt(void)
+{
+	printk(KERN_WARNING "\n** You can safely turn off the power\n");
+	while (1)
+		/* If possible call official function to get CPU WARs */
+		if (cpu_wait)
+			(*cpu_wait)();
+		else
+			__asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0");
+}
+
+void msp_power_off(void)
+{
+	msp_halt();
+}
+
+void __init plat_mem_setup(void)
+{
+	_machine_restart = msp_restart;
+	_machine_halt = msp_halt;
+	pm_power_off = msp_power_off;
+
+	board_time_init = msp_timer_init;
+}
+
+void __init prom_init(void)
+{
+	unsigned long family;
+	unsigned long revision;
+
+	prom_argc = fw_arg0;
+	prom_argv = (char **)fw_arg1;
+	prom_envp = (char **)fw_arg2;
+
+	/*
+	 * Someday we can use this with PMON2000 to get a
+	 * platform call prom routines for output etc. without
+	 * having to use grody hacks.  For now it's unused.
+	 *
+	 * struct callvectors *cv = (struct callvectors *) fw_arg3;
+	 */
+	family = identify_family();
+	revision = identify_revision();
+
+	switch (family)	{
+	case FAMILY_FPGA:
+		if (FPGA_IS_MSP4200(revision)) {
+			/* Old-style revision ID */
+			mips_machgroup = MACH_GROUP_MSP;
+			mips_machtype = MACH_MSP4200_FPGA;
+		} else {
+			mips_machgroup = MACH_GROUP_MSP;
+			mips_machtype = MACH_MSP_OTHER;
+		}
+		break;
+
+	case FAMILY_MSP4200:
+		mips_machgroup = MACH_GROUP_MSP;
+#if defined(CONFIG_PMC_MSP4200_EVAL)
+		mips_machtype  = MACH_MSP4200_EVAL;
+#elif defined(CONFIG_PMC_MSP4200_GW)
+		mips_machtype  = MACH_MSP4200_GW;
+#else
+		mips_machtype = MACH_MSP_OTHER;
+#endif
+		break;
+
+	case FAMILY_MSP4200_FPGA:
+		mips_machgroup = MACH_GROUP_MSP;
+		mips_machtype  = MACH_MSP4200_FPGA;
+		break;
+
+	case FAMILY_MSP7100:
+		mips_machgroup = MACH_GROUP_MSP;
+#if defined(CONFIG_PMC_MSP7120_EVAL)
+		mips_machtype = MACH_MSP7120_EVAL;
+#elif defined(CONFIG_PMC_MSP7120_GW)
+		mips_machtype = MACH_MSP7120_GW;
+#else
+		mips_machtype = MACH_MSP_OTHER;
+#endif
+		break;
+
+	case FAMILY_MSP7100_FPGA:
+		mips_machgroup = MACH_GROUP_MSP;
+		mips_machtype  = MACH_MSP7120_FPGA;
+		break;
+
+	default:
+		/* we don't recognize the machine */
+		mips_machgroup = MACH_GROUP_UNKNOWN;
+		mips_machtype  = MACH_UNKNOWN;
+		break;
+	}
+
+	/* make sure we have the right initialization routine - sanity */
+	if (mips_machgroup != MACH_GROUP_MSP) {
+		ppfinit("Unknown machine group in a "
+			"MSP initialization routine\n");
+		panic("***Bogosity factor five***, exiting\n");
+	}
+
+	prom_init_cmdline();
+
+	prom_meminit();
+
+	/*
+	 * Sub-system setup follows.
+	 * Setup functions can  either be called here or using the
+	 * subsys_initcall mechanism (i.e. see msp_pci_setup). The
+	 * order in which they are called can be changed by using the
+	 * link order in arch/mips/pmc-sierra/msp71xx/Makefile.
+	 *
+	 * NOTE: Please keep sub-system specific initialization code
+	 * in separate specific files.
+	 */
+	msp_serial_setup();
+
+#ifdef CONFIG_PMCTWILED
+	/*
+	 * Setup LED states before the subsys_initcall loads other
+	 * dependant drivers/modules.
+	 */
+	pmctwiled_setup();
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_time.c b/arch/mips/pmc-sierra/msp71xx/msp_time.c
new file mode 100644
index 0000000..2a2beac5
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_time.c
@@ -0,0 +1,94 @@
+/*
+ * Setting up the clock on MSP SOCs.  No RTC typically.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+
+#include <asm/mipsregs.h>
+#include <asm/time.h>
+
+#include <msp_prom.h>
+#include <msp_int.h>
+#include <msp_regs.h>
+
+void __init msp_timer_init(void)
+{
+	char    *endp, *s;
+	unsigned long cpu_rate = 0;
+
+	if (cpu_rate == 0) {
+		s = prom_getenv("clkfreqhz");
+		cpu_rate = simple_strtoul(s, &endp, 10);
+		if (endp != NULL && *endp != 0) {
+			printk(KERN_ERR
+				"Clock rate in Hz parse error: %s\n", s);
+			cpu_rate = 0;
+		}
+	}
+
+	if (cpu_rate == 0) {
+		s = prom_getenv("clkfreq");
+		cpu_rate = 1000 * simple_strtoul(s, &endp, 10);
+		if (endp != NULL && *endp != 0) {
+			printk(KERN_ERR
+				"Clock rate in MHz parse error: %s\n", s);
+			cpu_rate = 0;
+		}
+	}
+
+	if (cpu_rate == 0) {
+#if defined(CONFIG_PMC_MSP7120_EVAL) \
+ || defined(CONFIG_PMC_MSP7120_GW)
+		cpu_rate = 400000000;
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+		cpu_rate = 25000000;
+#else
+		cpu_rate = 150000000;
+#endif
+		printk(KERN_ERR
+			"Failed to determine CPU clock rate, "
+			"assuming %ld hz ...\n", cpu_rate);
+	}
+
+	printk(KERN_WARNING "Clock rate set to %ld\n", cpu_rate);
+
+	/* timer frequency is 1/2 clock rate */
+	mips_hpt_frequency = cpu_rate/2;
+}
+
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+#ifdef CONFIG_IRQ_MSP_CIC
+	/* we are using the vpe0 counter for timer interrupts */
+	setup_irq(MSP_INT_VPE0_TIMER, irq);
+#else
+	/* we are using the mips counter for timer interrupts */
+	setup_irq(MSP_INT_TIMER, irq);
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_usb.c b/arch/mips/pmc-sierra/msp71xx/msp_usb.c
new file mode 100644
index 0000000..21f9c70
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_usb.c
@@ -0,0 +1,150 @@
+/*
+ * The setup file for USB related hardware on PMC-Sierra MSP processors.
+ *
+ * Copyright 2006-2007 PMC-Sierra, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/mipsregs.h>
+
+#include <msp_regs.h>
+#include <msp_int.h>
+#include <msp_prom.h>
+
+#if defined(CONFIG_USB_EHCI_HCD)
+static struct resource msp_usbhost_resources [] = {
+	[0] = {
+		.start	= MSP_USB_BASE_START,
+		.end	= MSP_USB_BASE_END,
+		.flags 	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= MSP_INT_USB,
+		.end	= MSP_INT_USB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 msp_usbhost_dma_mask = DMA_32BIT_MASK;
+
+static struct platform_device msp_usbhost_device = {
+	.name	= "pmcmsp-ehci",
+	.id	= 0,
+	.dev	= {
+		.dma_mask = &msp_usbhost_dma_mask,
+		.coherent_dma_mask = DMA_32BIT_MASK,
+	},
+	.num_resources 	= ARRAY_SIZE (msp_usbhost_resources),
+	.resource	= msp_usbhost_resources,
+};
+#endif /* CONFIG_USB_EHCI_HCD */
+
+#if defined(CONFIG_USB_GADGET)
+static struct resource msp_usbdev_resources [] = {
+	[0] = {
+		.start	= MSP_USB_BASE,
+		.end	= MSP_USB_BASE_END,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= MSP_INT_USB,
+		.end	= MSP_INT_USB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 msp_usbdev_dma_mask = DMA_32BIT_MASK;
+
+static struct platform_device msp_usbdev_device = {
+	.name	= "msp71xx_udc",
+	.id	= 0,
+	.dev	= {
+		.dma_mask = &msp_usbdev_dma_mask,
+		.coherent_dma_mask = DMA_32BIT_MASK,
+	},
+	.num_resources	= ARRAY_SIZE (msp_usbdev_resources),
+	.resource	= msp_usbdev_resources,
+};
+#endif /* CONFIG_USB_GADGET */
+
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
+static struct platform_device *msp_devs[1];
+#endif
+
+
+static int __init msp_usb_setup(void)
+{
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
+	char *strp;
+	char envstr[32];
+	unsigned int val = 0;
+	int result = 0;
+
+	/*
+	 * construct environment name usbmode
+	 * set usbmode <host/device> as pmon environment var
+	 */
+	snprintf((char *)&envstr[0], sizeof(envstr), "usbmode");
+
+#if defined(CONFIG_USB_EHCI_HCD)
+	/* default to host mode */
+	val = 1;
+#endif
+
+	/* get environment string */
+	strp = prom_getenv((char *)&envstr[0]);
+	if (strp) {
+		if (!strcmp(strp, "device"))
+			val = 0;
+	}
+
+	if (val) {
+#if defined(CONFIG_USB_EHCI_HCD)
+		/* get host mode device */
+		msp_devs[0] = &msp_usbhost_device;
+		ppfinit("platform add USB HOST done %s.\n",
+			    msp_devs[0]->name);
+
+		result = platform_add_devices(msp_devs, ARRAY_SIZE (msp_devs));
+#endif /* CONFIG_USB_EHCI_HCD */
+	}
+#if defined(CONFIG_USB_GADGET)
+	else {
+		/* get device mode structure */
+		msp_devs[0] = &msp_usbdev_device;
+		ppfinit("platform add USB DEVICE done %s.\n",
+			    msp_devs[0]->name);
+
+		result = platform_add_devices(msp_devs, ARRAY_SIZE (msp_devs));
+	}
+#endif /* CONFIG_USB_GADGET */
+#endif /* CONFIG_USB_EHCI_HCD || CONFIG_USB_GADGET */
+
+	return result;
+}
+
+subsys_initcall(msp_usb_setup);
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
index 305491e..d83c4ad 100644
--- a/arch/mips/pmc-sierra/yosemite/smp.c
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -77,7 +77,7 @@
  * stack so the first thing we do is throw away that stuff and load useful
  * values into the registers ...
  */
-void prom_boot_secondary(int cpu, struct task_struct *idle)
+void __init prom_boot_secondary(int cpu, struct task_struct *idle)
 {
 	unsigned long gp = (unsigned long) task_thread_info(idle);
 	unsigned long sp = __KSTK_TOS(idle);
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index 66df5ac..63afd7e 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -46,7 +46,7 @@
 
 static int machine_state;
 
-static void ATTRIB_NORET sgi_machine_power_off(void)
+static void __noreturn sgi_machine_power_off(void)
 {
 	unsigned int tmp;
 
@@ -68,7 +68,7 @@
 	}
 }
 
-static void ATTRIB_NORET sgi_machine_restart(char *command)
+static void __noreturn sgi_machine_restart(char *command)
 {
 	if (machine_state & MACHINE_SHUTTING_DOWN)
 		sgi_machine_power_off();
@@ -76,7 +76,7 @@
 	while (1);
 }
 
-static void ATTRIB_NORET sgi_machine_halt(void)
+static void __noreturn sgi_machine_halt(void)
 {
 	if (machine_state & MACHINE_SHUTTING_DOWN)
 		sgi_machine_power_off();
diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c
index ce907ed..123141a 100644
--- a/arch/mips/sgi-ip27/ip27-berr.c
+++ b/arch/mips/sgi-ip27/ip27-berr.c
@@ -21,7 +21,6 @@
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 
-extern void dump_tlb_addr(unsigned long addr);
 extern void dump_tlb_all(void);
 
 static void dump_hub_information(unsigned long errst0, unsigned long errst1)
diff --git a/arch/mips/sgi-ip32/ip32-platform.c b/arch/mips/sgi-ip32/ip32-platform.c
index 120b159..ba3697e 100644
--- a/arch/mips/sgi-ip32/ip32-platform.c
+++ b/arch/mips/sgi-ip32/ip32-platform.c
@@ -1,5 +1,53 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <asm/ip32/mace.h>
+#include <asm/ip32/ip32_ints.h>
+
+/*
+ * .iobase isn't a constant (in the sense of C) so we fill it in at runtime.
+ */
+#define MACE_PORT(int)							\
+{									\
+	.irq		= int,						\
+	.uartclk	= 1843200,					\
+	.iotype		= UPIO_MEM,					\
+	.flags		= UPF_SKIP_TEST,				\
+	.regshift	= 8,						\
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+	MACE_PORT(MACEISA_SERIAL1_IRQ),
+	MACE_PORT(MACEISA_SERIAL2_IRQ),
+	{ },
+};
+
+static struct platform_device uart8250_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= uart8250_data,
+	},
+};
+
+static int __init uart8250_init(void)
+{
+	uart8250_data[0].iobase = (unsigned long) &mace->isa.serial1;
+	uart8250_data[1].iobase = (unsigned long) &mace->isa.serial1;
+
+	return platform_device_register(&uart8250_device);
+}
+
+device_initcall(uart8250_init);
 
 static __init int meth_devinit(void)
 {
@@ -18,3 +66,7 @@
 }
 
 device_initcall(meth_devinit);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for SGI IP32 aka O2");
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index 57708fe..bbba066 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -62,12 +62,6 @@
 }
 #endif
 
-#ifdef CONFIG_SERIAL_8250
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#endif /* CONFIG_SERIAL_8250 */
-
 /* An arbitrary time; this can be decreased if reliability looks good */
 #define WAIT_MS 10
 
@@ -96,36 +90,6 @@
 
 	board_time_init = ip32_time_init;
 
-#ifdef CONFIG_SERIAL_8250
-	{
-		static struct uart_port o2_serial[2];
-
-		memset(o2_serial, 0, sizeof(o2_serial));
-		o2_serial[0].type	= PORT_16550A;
-		o2_serial[0].line	= 0;
-		o2_serial[0].irq	= MACEISA_SERIAL1_IRQ;
-		o2_serial[0].flags	= UPF_SKIP_TEST;
-		o2_serial[0].uartclk	= 1843200;
-		o2_serial[0].iotype	= UPIO_MEM;
-		o2_serial[0].membase	= (char *)&mace->isa.serial1;
-		o2_serial[0].fifosize	= 14;
-                /* How much to shift register offset by. Each UART register
-		 * is replicated over 256 byte space */
-		o2_serial[0].regshift	= 8;
-		o2_serial[1].type	= PORT_16550A;
-		o2_serial[1].line	= 1;
-		o2_serial[1].irq	= MACEISA_SERIAL2_IRQ;
-		o2_serial[1].flags	= UPF_SKIP_TEST;
-		o2_serial[1].uartclk	= 1843200;
-		o2_serial[1].iotype	= UPIO_MEM;
-		o2_serial[1].membase	= (char *)&mace->isa.serial2;
-		o2_serial[1].fifosize	= 14;
-		o2_serial[1].regshift	= 8;
-
-		early_serial_setup(&o2_serial[0]);
-		early_serial_setup(&o2_serial[1]);
-	}
-#endif
 #ifdef CONFIG_SGI_O2MACE_ETH
 	{
 		char *mac = ArcGetEnvironmentVariable("eaddr");
diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c
index ae4a92c..51898dd 100644
--- a/arch/mips/sibyte/cfe/setup.c
+++ b/arch/mips/sibyte/cfe/setup.c
@@ -62,7 +62,7 @@
 extern int kgdb_port;
 #endif
 
-static void ATTRIB_NORET cfe_linux_exit(void *arg)
+static void __noreturn cfe_linux_exit(void *arg)
 {
 	int warm = *(int *)arg;
 
@@ -83,14 +83,14 @@
 	while (1);
 }
 
-static void ATTRIB_NORET cfe_linux_restart(char *command)
+static void __noreturn cfe_linux_restart(char *command)
 {
 	static const int zero;
 
 	cfe_linux_exit((void *)&zero);
 }
 
-static void ATTRIB_NORET cfe_linux_halt(void)
+static void __noreturn cfe_linux_halt(void)
 {
 	static const int one = 1;
 
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
index e5777b7..471418e 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -2,5 +2,5 @@
 # Makefile for the SNI specific part of the kernel
 #
 
-obj-y += irq.o reset.o setup.o ds1216.o a20r.o rm200.o pcimt.o pcit.o time.o
+obj-y += irq.o reset.o setup.o a20r.o rm200.o pcimt.o pcit.o time.o
 obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index 31ab80f..6850a29 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -15,7 +15,6 @@
 
 #include <asm/sni.h>
 #include <asm/time.h>
-#include <asm/ds1216.h>
 
 #define PORT(_base,_irq)				\
 	{						\
@@ -40,20 +39,34 @@
 	},
 };
 
+static struct resource a20r_ds1216_rsrc[] = {
+        {
+                .start = 0x1c081ffc,
+                .end   = 0x1c081fff,
+                .flags = IORESOURCE_MEM
+        }
+};
+
+static struct platform_device a20r_ds1216_device = {
+        .name           = "rtc-ds1216",
+        .num_resources  = ARRAY_SIZE(a20r_ds1216_rsrc),
+        .resource       = a20r_ds1216_rsrc
+};
+
 static struct resource snirm_82596_rsrc[] = {
 	{
-		.start = 0xb8000000,
-		.end   = 0xb8000004,
+		.start = 0x18000000,
+		.end   = 0x18000004,
 		.flags = IORESOURCE_MEM
 	},
 	{
-		.start = 0xb8010000,
-		.end   = 0xb8010004,
+		.start = 0x18010000,
+		.end   = 0x18010004,
 		.flags = IORESOURCE_MEM
 	},
 	{
-		.start = 0xbff00000,
-		.end   = 0xbff00020,
+		.start = 0x1ff00000,
+		.end   = 0x1ff00020,
 		.flags = IORESOURCE_MEM
 	},
 	{
@@ -205,8 +218,7 @@
 
 void sni_a20r_init(void)
 {
-	ds1216_base = (volatile unsigned char *) SNI_DS1216_A20R_BASE;
-	rtc_mips_get_time = ds1216_get_cmos_time;
+	/* FIXME, remove if not needed */
 }
 
 static int __init snirm_a20r_setup_devinit(void)
@@ -218,6 +230,7 @@
 	        platform_device_register(&snirm_53c710_pdev);
 	        platform_device_register(&sc26xx_pdev);
 	        platform_device_register(&a20r_serial8250_device);
+	        platform_device_register(&a20r_ds1216_device);
 	        break;
 	}
 
diff --git a/arch/mips/sni/ds1216.c b/arch/mips/sni/ds1216.c
deleted file mode 100644
index 1d92732..0000000
--- a/arch/mips/sni/ds1216.c
+++ /dev/null
@@ -1,81 +0,0 @@
-
-#include <linux/bcd.h>
-#include <linux/time.h>
-
-#include <asm/ds1216.h>
-
-volatile unsigned char *ds1216_base;
-
-/*
- * Read the 64 bit we'd like to have - It a series
- * of 64 bits showing up in the LSB of the base register.
- *
- */
-static unsigned char *ds1216_read(void)
-{
-	static unsigned char	rdbuf[8];
-	unsigned char		c;
-	int			i, j;
-
-	for (i = 0; i < 8; i++) {
-		c = 0x0;
-		for (j = 0; j < 8; j++) {
-			c |= (*ds1216_base & 0x1) << j;
-		}
-		rdbuf[i] = c;
-	}
-
-	return rdbuf;
-}
-
-static void ds1216_switch_ds_to_clock(void)
-{
-	unsigned char magic[] = {
-		0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
-	};
-	int i,j,c;
-
-	/* Reset magic pointer */
-	c = *ds1216_base;
-
-	/* Write 64 bit magic to DS1216 */
-	for (i = 0; i < 8; i++) {
-		c = magic[i];
-		for (j = 0; j < 8; j++) {
-			*ds1216_base = c;
-			c = c >> 1;
-		}
-	}
-}
-
-unsigned long ds1216_get_cmos_time(void)
-{
-	unsigned char	*rdbuf;
-	unsigned int	year, month, date, hour, min, sec;
-
-	ds1216_switch_ds_to_clock();
-	rdbuf = ds1216_read();
-
-	sec = BCD2BIN(DS1216_SEC(rdbuf));
-	min = BCD2BIN(DS1216_MIN(rdbuf));
-	hour = BCD2BIN(DS1216_HOUR(rdbuf));
-	date = BCD2BIN(DS1216_DATE(rdbuf));
-	month = BCD2BIN(DS1216_MONTH(rdbuf));
-	year = BCD2BIN(DS1216_YEAR(rdbuf));
-
-	if (DS1216_1224(rdbuf) && DS1216_AMPM(rdbuf))
-		hour+=12;
-
-	if (year < 70)
-		year += 2000;
-	else
-		year += 1900;
-
-	return mktime(year, month, date, hour, min, sec);
-}
-
-int ds1216_set_rtc_mmss(unsigned long nowtime)
-{
-	printk("ds1216_set_rtc_mmss called but not implemented\n");
-	return -1;
-}
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 97b2343..44b1ae6 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -14,7 +14,6 @@
 #include <linux/pci.h>
 #include <linux/serial_8250.h>
 
-#include <asm/mc146818-time.h>
 #include <asm/sni.h>
 #include <asm/time.h>
 #include <asm/i8259.h>
@@ -90,6 +89,26 @@
 	},
 };
 
+static struct resource pcimt_cmos_rsrc[] = {
+        {
+                .start = 0x70,
+                .end   = 0x71,
+                .flags = IORESOURCE_IO
+        },
+        {
+                .start = 8,
+                .end   = 8,
+                .flags = IORESOURCE_IRQ
+        }
+};
+
+static struct platform_device pcimt_cmos_device = {
+        .name           = "rtc_cmos",
+        .num_resources  = ARRAY_SIZE(pcimt_cmos_rsrc),
+        .resource       = pcimt_cmos_rsrc
+};
+
+
 static struct resource sni_io_resource = {
 	.start	= 0x00000000UL,
 	.end	= 0x03bfffffUL,
@@ -290,12 +309,10 @@
 	change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3);
 }
 
-void sni_pcimt_init(void)
+void __init sni_pcimt_init(void)
 {
 	sni_pcimt_detect();
 	sni_pcimt_sc_init();
-	rtc_mips_get_time = mc146818_get_cmos_time;
-	rtc_mips_set_time = mc146818_set_rtc_mmss;
 	board_time_init = sni_cpu_time_init;
 	ioport_resource.end = sni_io_resource.end;
 #ifdef CONFIG_PCI
@@ -312,6 +329,7 @@
 	case SNI_BRD_PCI_DESKTOP:
 	case SNI_BRD_PCI_MTOWER_CPLUS:
 	        platform_device_register(&pcimt_serial8250_device);
+	        platform_device_register(&pcimt_cmos_device);
 	        break;
 	}
 
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
index 00d151f..2480c47 100644
--- a/arch/mips/sni/pcit.c
+++ b/arch/mips/sni/pcit.c
@@ -13,7 +13,6 @@
 #include <linux/pci.h>
 #include <linux/serial_8250.h>
 
-#include <asm/mc146818-time.h>
 #include <asm/sni.h>
 #include <asm/time.h>
 #include <asm/irq_cpu.h>
@@ -58,6 +57,25 @@
 	},
 };
 
+static struct resource pcit_cmos_rsrc[] = {
+        {
+                .start = 0x70,
+                .end   = 0x71,
+                .flags = IORESOURCE_IO
+        },
+        {
+                .start = 8,
+                .end   = 8,
+                .flags = IORESOURCE_IRQ
+        }
+};
+
+static struct platform_device pcit_cmos_device = {
+        .name           = "rtc_cmos",
+        .num_resources  = ARRAY_SIZE(pcit_cmos_rsrc),
+        .resource       = pcit_cmos_rsrc
+};
+
 static struct resource sni_io_resource = {
 	.start	= 0x00000000UL,
 	.end	= 0x03bfffffUL,
@@ -243,10 +261,8 @@
 	setup_irq (MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq);
 }
 
-void sni_pcit_init(void)
+void __init sni_pcit_init(void)
 {
-	rtc_mips_get_time = mc146818_get_cmos_time;
-	rtc_mips_set_time = mc146818_set_rtc_mmss;
 	board_time_init = sni_cpu_time_init;
 	ioport_resource.end = sni_io_resource.end;
 #ifdef CONFIG_PCI
@@ -261,10 +277,12 @@
 	switch (sni_brd_type) {
 	case SNI_BRD_PCI_TOWER:
 	        platform_device_register(&pcit_serial8250_device);
+	        platform_device_register(&pcit_cmos_device);
 	        break;
 
 	case SNI_BRD_PCI_TOWER_CPLUS:
 	        platform_device_register(&pcit_cplus_serial8250_device);
+	        platform_device_register(&pcit_cmos_device);
 	        break;
 	}
 	return 0;
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
index b82ff12..4bfda02 100644
--- a/arch/mips/sni/rm200.c
+++ b/arch/mips/sni/rm200.c
@@ -15,7 +15,6 @@
 
 #include <asm/sni.h>
 #include <asm/time.h>
-#include <asm/ds1216.h>
 #include <asm/irq_cpu.h>
 
 #define PORT(_base,_irq)				\
@@ -41,20 +40,34 @@
 	},
 };
 
+static struct resource rm200_ds1216_rsrc[] = {
+        {
+                .start = 0x1cd41ffc,
+                .end   = 0x1cd41fff,
+                .flags = IORESOURCE_MEM
+        }
+};
+
+static struct platform_device rm200_ds1216_device = {
+        .name           = "rtc-ds1216",
+        .num_resources  = ARRAY_SIZE(rm200_ds1216_rsrc),
+        .resource       = rm200_ds1216_rsrc
+};
+
 static struct resource snirm_82596_rm200_rsrc[] = {
 	{
-		.start = 0xb8000000,
-		.end   = 0xb80fffff,
+		.start = 0x18000000,
+		.end   = 0x180fffff,
 		.flags = IORESOURCE_MEM
 	},
 	{
-		.start = 0xbb000000,
-		.end   = 0xbb000004,
+		.start = 0x1b000000,
+		.end   = 0x1b000004,
 		.flags = IORESOURCE_MEM
 	},
 	{
-		.start = 0xbff00000,
-		.end   = 0xbff00020,
+		.start = 0x1ff00000,
+		.end   = 0x1ff00020,
 		.flags = IORESOURCE_MEM
 	},
 	{
@@ -96,6 +109,7 @@
 {
 	if (sni_brd_type == SNI_BRD_RM200) {
 		platform_device_register(&rm200_serial8250_device);
+		platform_device_register(&rm200_ds1216_device);
 		platform_device_register(&snirm_82596_rm200_pdev);
 		platform_device_register(&snirm_53c710_rm200_pdev);
 	}
@@ -176,11 +190,9 @@
 	setup_irq (SNI_RM200_INT_START + 0, &sni_isa_irq);
 }
 
-void sni_rm200_init(void)
+void __init sni_rm200_init(void)
 {
 	set_io_port_base(SNI_PORT_BASE + 0x02000000);
 	ioport_resource.end += 0x02000000;
-	ds1216_base = (volatile unsigned char *) SNI_DS1216_RM200_BASE;
-	rtc_mips_get_time = ds1216_get_cmos_time;
 	board_time_init = sni_cpu_time_init;
 }
diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c
index 643366e..00a03a6 100644
--- a/arch/mips/sni/sniprom.c
+++ b/arch/mips/sni/sniprom.c
@@ -146,7 +146,10 @@
 		}
 		if (baud)
 			strcpy(options, baud);
-		add_preferred_console("ttyS", port, baud ? options : NULL);
+		if (strncmp (cdev, "tty552", 6) == 0)
+			add_preferred_console("ttyS", port, baud ? options : NULL);
+		else
+			add_preferred_console("ttySC", port, baud ? options : NULL);
 	}
 }
 
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile
index 2033ae7..83cda51 100644
--- a/arch/mips/tx4938/common/Makefile
+++ b/arch/mips/tx4938/common/Makefile
@@ -6,6 +6,6 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y	+= prom.o setup.o irq.o rtc_rx5c348.o
+obj-y	+= prom.o setup.o irq.o
 obj-$(CONFIG_KGDB) += dbgio.o
 
diff --git a/arch/mips/tx4938/common/rtc_rx5c348.c b/arch/mips/tx4938/common/rtc_rx5c348.c
deleted file mode 100644
index 07f782f..0000000
--- a/arch/mips/tx4938/common/rtc_rx5c348.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * RTC routines for RICOH Rx5C348 SPI chip.
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
- * terms of the GNU General Public License version 2. This program is
- * licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/rtc.h>
-#include <linux/time.h>
-#include <linux/bcd.h>
-#include <asm/time.h>
-#include <asm/tx4938/spi.h>
-
-#define	EPOCH		2000
-
-/* registers */
-#define Rx5C348_REG_SECOND	0
-#define Rx5C348_REG_MINUTE	1
-#define Rx5C348_REG_HOUR	2
-#define Rx5C348_REG_WEEK	3
-#define Rx5C348_REG_DAY	4
-#define Rx5C348_REG_MONTH	5
-#define Rx5C348_REG_YEAR	6
-#define Rx5C348_REG_ADJUST	7
-#define Rx5C348_REG_ALARM_W_MIN	8
-#define Rx5C348_REG_ALARM_W_HOUR	9
-#define Rx5C348_REG_ALARM_W_WEEK	10
-#define Rx5C348_REG_ALARM_D_MIN	11
-#define Rx5C348_REG_ALARM_D_HOUR	12
-#define Rx5C348_REG_CTL1	14
-#define Rx5C348_REG_CTL2	15
-
-/* register bits */
-#define Rx5C348_BIT_PM	0x20	/* REG_HOUR */
-#define Rx5C348_BIT_Y2K	0x80	/* REG_MONTH */
-#define Rx5C348_BIT_24H	0x20	/* REG_CTL1 */
-#define Rx5C348_BIT_XSTP	0x10	/* REG_CTL2 */
-
-/* commands */
-#define Rx5C348_CMD_W(addr)	(((addr) << 4) | 0x08)	/* single write */
-#define Rx5C348_CMD_R(addr)	(((addr) << 4) | 0x0c)	/* single read */
-#define Rx5C348_CMD_MW(addr)	(((addr) << 4) | 0x00)	/* burst write */
-#define Rx5C348_CMD_MR(addr)	(((addr) << 4) | 0x04)	/* burst read */
-
-static struct spi_dev_desc srtc_dev_desc = {
-	.baud 		= 1000000,	/* 1.0Mbps @ Vdd 2.0V */
-	.tcss		= 31,
-	.tcsh		= 1,
-	.tcsr		= 62,
-	/* 31us for Tcss (62us for Tcsr) is required for carry operation) */
-	.byteorder	= 1,		/* MSB-First */
-	.polarity	= 0,		/* High-Active */
-	.phase		= 1,		/* Shift-Then-Sample */
-
-};
-static int srtc_chipid;
-static int srtc_24h;
-
-static inline int
-spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count)
-{
-	unsigned char *inbufs[1], *outbufs[1];
-	unsigned int incounts[2], outcounts[2];
-	inbufs[0] = inbuf;
-	incounts[0] = count;
-	incounts[1] = 0;
-	outbufs[0] = outbuf;
-	outcounts[0] = count;
-	outcounts[1] = 0;
-	return txx9_spi_io(srtc_chipid, &srtc_dev_desc,
-			   inbufs, incounts, outbufs, outcounts, 0);
-}
-
-/* RTC-dependent code for time.c */
-
-static int
-rtc_rx5c348_set_time(unsigned long t)
-{
-	unsigned char inbuf[8];
-	struct rtc_time tm;
-	u8 year, month, day, hour, minute, second, century;
-
-	/* convert */
-	to_tm(t, &tm);
-
-	year = tm.tm_year % 100;
-	month = tm.tm_mon+1;	/* tm_mon starts from 0 to 11 */
-	day = tm.tm_mday;
-	hour = tm.tm_hour;
-	minute = tm.tm_min;
-	second = tm.tm_sec;
-	century = tm.tm_year / 100;
-
-	inbuf[0] = Rx5C348_CMD_MW(Rx5C348_REG_SECOND);
-	BIN_TO_BCD(second);
-	inbuf[1] = second;
-	BIN_TO_BCD(minute);
-	inbuf[2] = minute;
-
-	if (srtc_24h) {
-		BIN_TO_BCD(hour);
-		inbuf[3] = hour;
-	} else {
-		/* hour 0 is AM12, noon is PM12 */
-		inbuf[3] = 0;
-		if (hour >= 12)
-			inbuf[3] = Rx5C348_BIT_PM;
-		hour = (hour + 11) % 12 + 1;
-		BIN_TO_BCD(hour);
-		inbuf[3] |= hour;
-	}
-	inbuf[4] = 0;	/* ignore week */
-	BIN_TO_BCD(day);
-	inbuf[5] = day;
-	BIN_TO_BCD(month);
-	inbuf[6] = month;
-	if (century >= 20)
-		inbuf[6] |= Rx5C348_BIT_Y2K;
-	BIN_TO_BCD(year);
-	inbuf[7] = year;
-	/* write in one transfer to avoid data inconsistency */
-	return spi_rtc_io(inbuf, NULL, 8);
-}
-
-static unsigned long
-rtc_rx5c348_get_time(void)
-{
-	unsigned char inbuf[8], outbuf[8];
-	unsigned int year, month, day, hour, minute, second;
-
-	inbuf[0] = Rx5C348_CMD_MR(Rx5C348_REG_SECOND);
-	memset(inbuf + 1, 0, 7);
-	/* read in one transfer to avoid data inconsistency */
-	if (spi_rtc_io(inbuf, outbuf, 8))
-		return 0;
-	second = outbuf[1];
-	BCD_TO_BIN(second);
-	minute = outbuf[2];
-	BCD_TO_BIN(minute);
-	if (srtc_24h) {
-		hour = outbuf[3];
-		BCD_TO_BIN(hour);
-	} else {
-		hour = outbuf[3] & ~Rx5C348_BIT_PM;
-		BCD_TO_BIN(hour);
-		hour %= 12;
-		if (outbuf[3] & Rx5C348_BIT_PM)
-			hour += 12;
-	}
-	day = outbuf[5];
-	BCD_TO_BIN(day);
-	month = outbuf[6] & ~Rx5C348_BIT_Y2K;
-	BCD_TO_BIN(month);
-	year = outbuf[7];
-	BCD_TO_BIN(year);
-	year += EPOCH;
-
-	return mktime(year, month, day, hour, minute, second);
-}
-
-void __init
-rtc_rx5c348_init(int chipid)
-{
-	unsigned char inbuf[2], outbuf[2];
-	srtc_chipid = chipid;
-	/* turn on RTC if it is not on */
-	inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL2);
-	inbuf[1] = 0;
-	spi_rtc_io(inbuf, outbuf, 2);
-	if (outbuf[1] & Rx5C348_BIT_XSTP) {
-		inbuf[0] = Rx5C348_CMD_W(Rx5C348_REG_CTL2);
-		inbuf[1] = 0;
-		spi_rtc_io(inbuf, NULL, 2);
-	}
-
-	inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL1);
-	inbuf[1] = 0;
-	spi_rtc_io(inbuf, outbuf, 2);
-	if (outbuf[1] & Rx5C348_BIT_24H)
-		srtc_24h = 1;
-
-	/* set the function pointers */
-	rtc_mips_get_time = rtc_rx5c348_get_time;
-	rtc_mips_set_time = rtc_rx5c348_set_time;
-}
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/Makefile b/arch/mips/tx4938/toshiba_rbtx4938/Makefile
index 2269412..10c94e6 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/Makefile
+++ b/arch/mips/tx4938/toshiba_rbtx4938/Makefile
@@ -6,4 +6,4 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y	+= prom.o setup.o irq.o spi_eeprom.o spi_txx9.o
+obj-y	+= prom.o setup.o irq.o spi_eeprom.o
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
index 2e96dbb..91aea7af 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
@@ -165,8 +165,6 @@
 	TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
 }
 
-extern void __init txx9_spi_irqinit(int irc_irq);
-
 void __init arch_init_irq(void)
 {
 	extern void tx4938_irq_init(void);
@@ -185,9 +183,5 @@
 	/* Onboard 10M Ether: High Active */
 	TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM0), 0x00000040);
 
-	if (tx4938_ccfgptr->pcfg & TX4938_PCFG_SPI_SEL) {
-		txx9_spi_irqinit(RBTX4938_IRQ_IRC_SPI);
-        }
-
 	wbflush();
 }
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
index f5d1ce7..6ed39a5 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
@@ -14,13 +14,13 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
-#include <linux/proc_fs.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/console.h>
 #include <linux/pci.h>
 #include <linux/pm.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 
 #include <asm/wbflush.h>
 #include <asm/reboot.h>
@@ -35,6 +35,9 @@
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #endif
+#include <linux/spi/spi.h>
+#include <asm/tx4938/spi.h>
+#include <asm/gpio.h>
 
 extern void rbtx4938_time_init(void) __init;
 extern char * __init prom_getcmdline(void);
@@ -349,7 +352,7 @@
 	static struct pci_dev dev;
 	static struct pci_bus bus;
 
-	dev.sysdata = (void *)hose;
+	dev.sysdata = bus.sysdata = hose;
 	dev.devfn = devfn;
 	bus.number = busnr;
 	bus.ops = hose->pci_ops;
@@ -382,8 +385,10 @@
 	printk("PCI: Checking 66MHz capabilities...\n");
 
 	for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
-		early_read_config_word(hose, top_bus, current_bus, pci_devfn,
-				       PCI_VENDOR_ID, &vid);
+		if (early_read_config_word(hose, top_bus, current_bus,
+					   pci_devfn, PCI_VENDOR_ID,
+					   &vid) != PCIBIOS_SUCCESSFUL)
+			continue;
 
 		if (vid == 0xffff) continue;
 
@@ -460,7 +465,6 @@
 	int extarb = !(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIXARB);
 
 	PCIBIOS_MIN_IO = 0x00001000UL;
-	PCIBIOS_MIN_MEM = 0x01000000UL;
 
 	mem_base[0] = txboard_request_phys_region_shrink(&mem_size[0]);
 	io_base[0] = txboard_request_phys_region_shrink(&io_size[0]);
@@ -574,82 +578,43 @@
 #define	SEEPROM3_CS	1	/* IOC */
 #define	SRTC_CS	2	/* IOC */
 
-static int rbtx4938_spi_cs_func(int chipid, int on)
-{
-	unsigned char bit;
-	switch (chipid) {
-	case RBTX4938_SEEPROM1_CHIPID:
-		if (on)
-			tx4938_pioptr->dout &= ~(1 << SEEPROM1_CS);
-		else
-			tx4938_pioptr->dout |= (1 << SEEPROM1_CS);
-		return 0;
-		break;
-	case RBTX4938_SEEPROM2_CHIPID:
-		bit = (1 << SEEPROM2_CS);
-		break;
-	case RBTX4938_SEEPROM3_CHIPID:
-		bit = (1 << SEEPROM3_CS);
-		break;
-	case RBTX4938_SRTC_CHIPID:
-		bit = (1 << SRTC_CS);
-		break;
-	default:
-		return -ENODEV;
-	}
-	/* bit1,2,4 are low active, bit3 is high active */
-	*rbtx4938_spics_ptr =
-		(*rbtx4938_spics_ptr & ~bit) |
-		((on ? (bit ^ 0x0b) : ~(bit ^ 0x0b)) & bit);
-	return 0;
-}
-
 #ifdef CONFIG_PCI
-extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len);
-
-int rbtx4938_get_tx4938_ethaddr(struct pci_dev *dev, unsigned char *addr)
+static int __init rbtx4938_ethaddr_init(void)
 {
-	struct pci_controller *channel = (struct pci_controller *)dev->bus->sysdata;
-	static unsigned char dat[17];
-	static int read_dat = 0;
-	int ch = 0;
+	unsigned char dat[17];
+	unsigned char sum;
+	int i;
 
-	if (channel != &tx4938_pci_controller[1])
+	/* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */
+	if (spi_eeprom_read(SEEPROM1_CS, 0, dat, sizeof(dat))) {
+		printk(KERN_ERR "seeprom: read error.\n");
 		return -ENODEV;
-	/* TX4938 PCIC1 */
-	switch (PCI_SLOT(dev->devfn)) {
-	case TX4938_PCIC_IDSEL_AD_TO_SLOT(31):
-		ch = 0;
-		break;
-	case TX4938_PCIC_IDSEL_AD_TO_SLOT(30):
-		ch = 1;
-		break;
-	default:
-		return -ENODEV;
+	} else {
+		if (strcmp(dat, "MAC") != 0)
+			printk(KERN_WARNING "seeprom: bad signature.\n");
+		for (i = 0, sum = 0; i < sizeof(dat); i++)
+			sum += dat[i];
+		if (sum)
+			printk(KERN_WARNING "seeprom: bad checksum.\n");
 	}
-	if (!read_dat) {
-		unsigned char sum;
-		int i;
-		read_dat = 1;
-		/* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */
-		if (spi_eeprom_read(RBTX4938_SEEPROM1_CHIPID,
-				    0, dat, sizeof(dat))) {
-			printk(KERN_ERR "seeprom: read error.\n");
-		} else {
-			if (strcmp(dat, "MAC") != 0)
-				printk(KERN_WARNING "seeprom: bad signature.\n");
-			for (i = 0, sum = 0; i < sizeof(dat); i++)
-				sum += dat[i];
-			if (sum)
-				printk(KERN_WARNING "seeprom: bad checksum.\n");
-		}
+	for (i = 0; i < 2; i++) {
+		unsigned int slot = TX4938_PCIC_IDSEL_AD_TO_SLOT(31 - i);
+		unsigned int id = (1 << 8) | PCI_DEVFN(slot, 0); /* bus 1 */
+		struct platform_device *pdev;
+		if (!(tx4938_ccfgptr->pcfg &
+		      (i ? TX4938_PCFG_ETH1_SEL : TX4938_PCFG_ETH0_SEL)))
+			continue;
+		pdev = platform_device_alloc("tc35815-mac", id);
+		if (!pdev ||
+		    platform_device_add_data(pdev, &dat[4 + 6 * i], 6) ||
+		    platform_device_add(pdev))
+			platform_device_put(pdev);
 	}
-	memcpy(addr, &dat[4 + 6 * ch], 6);
 	return 0;
 }
+device_initcall(rbtx4938_ethaddr_init);
 #endif /* CONFIG_PCI */
 
-extern void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on));
 static void __init rbtx4938_spi_setup(void)
 {
 	/* set SPI_SEL */
@@ -657,7 +622,6 @@
 	/* chip selects for SPI devices */
 	tx4938_pioptr->dout |= (1 << SEEPROM1_CS);
 	tx4938_pioptr->dir |= (1 << SEEPROM1_CS);
-	txx9_spi_init(TX4938_SPI_REG, rbtx4938_spi_cs_func);
 }
 
 static struct resource rbtx4938_fpga_resource;
@@ -896,10 +860,8 @@
 /* We use onchip r4k counter or TMR timer as our system wide timer
  * interrupt running at 100HZ. */
 
-extern void __init rtc_rx5c348_init(int chipid);
 void __init rbtx4938_time_init(void)
 {
-	rtc_rx5c348_init(RBTX4938_SRTC_CHIPID);
 	mips_hpt_frequency = txx9_cpu_clock / 2;
 }
 
@@ -1016,29 +978,6 @@
 	       *rbtx4938_dipsw_ptr, *rbtx4938_bdipsw_ptr);
 }
 
-#ifdef CONFIG_PROC_FS
-extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid);
-static int __init tx4938_spi_proc_setup(void)
-{
-	struct proc_dir_entry *tx4938_spi_eeprom_dir;
-
-	tx4938_spi_eeprom_dir = proc_mkdir("spi_eeprom", 0);
-
-	if (!tx4938_spi_eeprom_dir)
-		return -ENOMEM;
-
-	/* don't allow user access to RBTX4938_SEEPROM1_CHIPID
-	 * as it contains eth0 and eth1 MAC addresses
-	 */
-	spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM2_CHIPID);
-	spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM3_CHIPID);
-
-	return 0;
-}
-
-__initcall(tx4938_spi_proc_setup);
-#endif
-
 static int __init rbtx4938_ne_init(void)
 {
 	struct resource res[] = {
@@ -1057,3 +996,176 @@
 	return IS_ERR(dev) ? PTR_ERR(dev) : 0;
 }
 device_initcall(rbtx4938_ne_init);
+
+/* GPIO support */
+
+static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock);
+
+static void rbtx4938_spi_gpio_set(unsigned gpio, int value)
+{
+	u8 val;
+	unsigned long flags;
+	gpio -= 16;
+	spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags);
+	val = *rbtx4938_spics_ptr;
+	if (value)
+		val |= 1 << gpio;
+	else
+		val &= ~(1 << gpio);
+	*rbtx4938_spics_ptr = val;
+	mmiowb();
+	spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags);
+}
+
+static int rbtx4938_spi_gpio_dir_out(unsigned gpio, int value)
+{
+	rbtx4938_spi_gpio_set(gpio, value);
+	return 0;
+}
+
+static DEFINE_SPINLOCK(tx4938_gpio_lock);
+
+static int tx4938_gpio_get(unsigned gpio)
+{
+	return tx4938_pioptr->din & (1 << gpio);
+}
+
+static void tx4938_gpio_set_raw(unsigned gpio, int value)
+{
+	u32 val;
+	val = tx4938_pioptr->dout;
+	if (value)
+		val |= 1 << gpio;
+	else
+		val &= ~(1 << gpio);
+	tx4938_pioptr->dout = val;
+}
+
+static void tx4938_gpio_set(unsigned gpio, int value)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&tx4938_gpio_lock, flags);
+	tx4938_gpio_set_raw(gpio, value);
+	mmiowb();
+	spin_unlock_irqrestore(&tx4938_gpio_lock, flags);
+}
+
+static int tx4938_gpio_dir_in(unsigned gpio)
+{
+	spin_lock_irq(&tx4938_gpio_lock);
+	tx4938_pioptr->dir &= ~(1 << gpio);
+	mmiowb();
+	spin_unlock_irq(&tx4938_gpio_lock);
+	return 0;
+}
+
+static int tx4938_gpio_dir_out(unsigned int gpio, int value)
+{
+	spin_lock_irq(&tx4938_gpio_lock);
+	tx4938_gpio_set_raw(gpio, value);
+	tx4938_pioptr->dir |= 1 << gpio;
+	mmiowb();
+	spin_unlock_irq(&tx4938_gpio_lock);
+	return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+	if (gpio < 16)
+		return tx4938_gpio_dir_in(gpio);
+	return -EINVAL;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+	if (gpio < 16)
+		return tx4938_gpio_dir_out(gpio, value);
+	if (gpio < 16 + 3)
+		return rbtx4938_spi_gpio_dir_out(gpio, value);
+	return -EINVAL;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+	if (gpio < 16)
+		return tx4938_gpio_get(gpio);
+	return 0;
+}
+
+void gpio_set_value(unsigned gpio, int value)
+{
+	if (gpio < 16)
+		tx4938_gpio_set(gpio, value);
+	else
+		rbtx4938_spi_gpio_set(gpio, value);
+}
+
+/* SPI support */
+
+static void __init txx9_spi_init(unsigned long base, int irq)
+{
+	struct resource res[] = {
+		{
+			.start	= base,
+			.end	= base + 0x20 - 1,
+			.flags	= IORESOURCE_MEM,
+			.parent	= &tx4938_reg_resource,
+		}, {
+			.start	= irq,
+			.flags	= IORESOURCE_IRQ,
+		},
+	};
+	platform_device_register_simple("txx9spi", 0,
+					res, ARRAY_SIZE(res));
+}
+
+static int __init rbtx4938_spi_init(void)
+{
+	struct spi_board_info srtc_info = {
+		.modalias = "rs5c348",
+		.max_speed_hz = 1000000, /* 1.0Mbps @ Vdd 2.0V */
+		.bus_num = 0,
+		.chip_select = 16 + SRTC_CS,
+		/* Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS  */
+		.mode = SPI_MODE_1 | SPI_CS_HIGH,
+	};
+	spi_register_board_info(&srtc_info, 1);
+	spi_eeprom_register(SEEPROM1_CS);
+	spi_eeprom_register(16 + SEEPROM2_CS);
+	spi_eeprom_register(16 + SEEPROM3_CS);
+	txx9_spi_init(TX4938_SPI_REG & 0xfffffffffULL, RBTX4938_IRQ_IRC_SPI);
+	return 0;
+}
+arch_initcall(rbtx4938_spi_init);
+
+/* Minimum CLK support */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	if (!strcmp(id, "spi-baseclk"))
+		return (struct clk *)(txx9_gbus_clock / 2 / 4);
+	return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return (unsigned long)clk;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
index 89596e6..4d6b4ad 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
@@ -10,209 +10,90 @@
  * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
  */
 #include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
 #include <asm/tx4938/spi.h>
-#include <asm/tx4938/tx4938.h>
 
-/* ATMEL 250x0 instructions */
-#define	ATMEL_WREN	0x06
-#define	ATMEL_WRDI	0x04
-#define ATMEL_RDSR	0x05
-#define ATMEL_WRSR	0x01
-#define	ATMEL_READ	0x03
-#define	ATMEL_WRITE	0x02
+#define AT250X0_PAGE_SIZE	8
 
-#define ATMEL_SR_BSY	0x01
-#define ATMEL_SR_WEN	0x02
-#define ATMEL_SR_BP0	0x04
-#define ATMEL_SR_BP1	0x08
+/* register board information for at25 driver */
+int __init spi_eeprom_register(int chipid)
+{
+	static struct spi_eeprom eeprom = {
+		.name = "at250x0",
+		.byte_len = 128,
+		.page_size = AT250X0_PAGE_SIZE,
+		.flags = EE_ADDR1,
+	};
+	struct spi_board_info info = {
+		.modalias = "at25",
+		.max_speed_hz = 1500000,	/* 1.5Mbps */
+		.bus_num = 0,
+		.chip_select = chipid,
+		.platform_data = &eeprom,
+		/* Mode 0: High-Active, Sample-Then-Shift */
+	};
 
-DEFINE_SPINLOCK(spi_eeprom_lock);
+	return spi_register_board_info(&info, 1);
+}
 
-static struct spi_dev_desc seeprom_dev_desc = {
-	.baud 		= 1500000,	/* 1.5Mbps */
-	.tcss		= 1,
-	.tcsh		= 1,
-	.tcsr		= 1,
-	.byteorder	= 1,		/* MSB-First */
-	.polarity	= 0,		/* High-Active */
-	.phase		= 0,		/* Sample-Then-Shift */
+/* simple temporary spi driver to provide early access to seeprom. */
 
+static struct read_param {
+	int chipid;
+	int address;
+	unsigned char *buf;
+	int len;
+} *read_param;
+
+static int __init early_seeprom_probe(struct spi_device *spi)
+{
+	int stat = 0;
+	u8 cmd[2];
+	int len = read_param->len;
+	char *buf = read_param->buf;
+	int address = read_param->address;
+
+	dev_info(&spi->dev, "spiclk %u KHz.\n",
+		 (spi->max_speed_hz + 500) / 1000);
+	if (read_param->chipid != spi->chip_select)
+		return -ENODEV;
+	while (len > 0) {
+		/* spi_write_then_read can only work with small chunk */
+		int c = len < AT250X0_PAGE_SIZE ? len : AT250X0_PAGE_SIZE;
+		cmd[0] = 0x03;	/* AT25_READ */
+		cmd[1] = address;
+		stat = spi_write_then_read(spi, cmd, sizeof(cmd), buf, c);
+		buf += c;
+		len -= c;
+		address += c;
+	}
+	return stat;
+}
+
+static struct spi_driver early_seeprom_driver __initdata = {
+	.driver = {
+		.name	= "at25",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= early_seeprom_probe,
 };
-static inline int
-spi_eeprom_io(int chipid,
-	      unsigned char **inbufs, unsigned int *incounts,
-	      unsigned char **outbufs, unsigned int *outcounts)
+
+int __init spi_eeprom_read(int chipid, int address,
+			   unsigned char *buf, int len)
 {
-	return txx9_spi_io(chipid, &seeprom_dev_desc,
-			   inbufs, incounts, outbufs, outcounts, 0);
+	int ret;
+	struct read_param param = {
+		.chipid = chipid,
+		.address = address,
+		.buf = buf,
+		.len = len
+	};
+
+	read_param = &param;
+	ret = spi_register_driver(&early_seeprom_driver);
+	if (!ret)
+		spi_unregister_driver(&early_seeprom_driver);
+	return ret;
 }
-
-int spi_eeprom_write_enable(int chipid, int enable)
-{
-	unsigned char inbuf[1];
-	unsigned char *inbufs[1];
-	unsigned int incounts[2];
-	unsigned long flags;
-	int stat;
-	inbuf[0] = enable ? ATMEL_WREN : ATMEL_WRDI;
-	inbufs[0] = inbuf;
-	incounts[0] = sizeof(inbuf);
-	incounts[1] = 0;
-	spin_lock_irqsave(&spi_eeprom_lock, flags);
-	stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
-	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
-	return stat;
-}
-
-static int spi_eeprom_read_status_nolock(int chipid)
-{
-	unsigned char inbuf[2], outbuf[2];
-	unsigned char *inbufs[1], *outbufs[1];
-	unsigned int incounts[2], outcounts[2];
-	int stat;
-	inbuf[0] = ATMEL_RDSR;
-	inbuf[1] = 0;
-	inbufs[0] = inbuf;
-	incounts[0] = sizeof(inbuf);
-	incounts[1] = 0;
-	outbufs[0] = outbuf;
-	outcounts[0] = sizeof(outbuf);
-	outcounts[1] = 0;
-	stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
-	if (stat < 0)
-		return stat;
-	return outbuf[1];
-}
-
-int spi_eeprom_read_status(int chipid)
-{
-	unsigned long flags;
-	int stat;
-	spin_lock_irqsave(&spi_eeprom_lock, flags);
-	stat = spi_eeprom_read_status_nolock(chipid);
-	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
-	return stat;
-}
-
-int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len)
-{
-	unsigned char inbuf[2];
-	unsigned char *inbufs[2], *outbufs[2];
-	unsigned int incounts[2], outcounts[3];
-	unsigned long flags;
-	int stat;
-	inbuf[0] = ATMEL_READ;
-	inbuf[1] = address;
-	inbufs[0] = inbuf;
-	inbufs[1] = NULL;
-	incounts[0] = sizeof(inbuf);
-	incounts[1] = 0;
-	outbufs[0] = NULL;
-	outbufs[1] = buf;
-	outcounts[0] = 2;
-	outcounts[1] = len;
-	outcounts[2] = 0;
-	spin_lock_irqsave(&spi_eeprom_lock, flags);
-	stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
-	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
-	return stat;
-}
-
-int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len)
-{
-	unsigned char inbuf[2];
-	unsigned char *inbufs[2];
-	unsigned int incounts[3];
-	unsigned long flags;
-	int i, stat;
-
-	if (address / 8 != (address + len - 1) / 8)
-		return -EINVAL;
-	stat = spi_eeprom_write_enable(chipid, 1);
-	if (stat < 0)
-		return stat;
-	stat = spi_eeprom_read_status(chipid);
-	if (stat < 0)
-		return stat;
-	if (!(stat & ATMEL_SR_WEN))
-		return -EPERM;
-
-	inbuf[0] = ATMEL_WRITE;
-	inbuf[1] = address;
-	inbufs[0] = inbuf;
-	inbufs[1] = buf;
-	incounts[0] = sizeof(inbuf);
-	incounts[1] = len;
-	incounts[2] = 0;
-	spin_lock_irqsave(&spi_eeprom_lock, flags);
-	stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
-	if (stat < 0)
-		goto unlock_return;
-
-	/* write start.  max 10ms */
-	for (i = 10; i > 0; i--) {
-		int stat = spi_eeprom_read_status_nolock(chipid);
-		if (stat < 0)
-			goto unlock_return;
-		if (!(stat & ATMEL_SR_BSY))
-			break;
-		mdelay(1);
-	}
-	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
-	if (i == 0)
-		return -EIO;
-	return len;
- unlock_return:
-	spin_unlock_irqrestore(&spi_eeprom_lock, flags);
-	return stat;
-}
-
-#ifdef CONFIG_PROC_FS
-#define MAX_SIZE	0x80	/* for ATMEL 25010 */
-static int spi_eeprom_read_proc(char *page, char **start, off_t off,
-				int count, int *eof, void *data)
-{
-	unsigned int size = MAX_SIZE;
-	if (spi_eeprom_read((int)data, 0, (unsigned char *)page, size) < 0)
-		size = 0;
-	return size;
-}
-
-static int spi_eeprom_write_proc(struct file *file, const char *buffer,
-				 unsigned long count, void *data)
-{
-	unsigned int size = MAX_SIZE;
-	int i;
-	if (file->f_pos >= size)
-		return -EIO;
-	if (file->f_pos + count > size)
-		count = size - file->f_pos;
-	for (i = 0; i < count; i += 8) {
-		int len = count - i < 8 ? count - i : 8;
-		if (spi_eeprom_write((int)data, file->f_pos,
-				     (unsigned char *)buffer, len) < 0) {
-			count = -EIO;
-			break;
-		}
-		buffer += len;
-		file->f_pos += len;
-	}
-	return count;
-}
-
-__init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid)
-{
-	struct proc_dir_entry *entry;
-	char name[128];
-	sprintf(name, "seeprom-%d", chipid);
-	entry = create_proc_entry(name, 0600, dir);
-	if (entry) {
-		entry->read_proc = spi_eeprom_read_proc;
-		entry->write_proc = spi_eeprom_write_proc;
-		entry->data = (void *)chipid;
-	}
-}
-#endif /* CONFIG_PROC_FS */
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
deleted file mode 100644
index 08b20cd..0000000
--- a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
- * terms of the GNU General Public License version 2. This program is
- * licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- */
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <asm/tx4938/spi.h>
-#include <asm/tx4938/tx4938.h>
-
-static int (*txx9_spi_cs_func)(int chipid, int on);
-static DEFINE_SPINLOCK(txx9_spi_lock);
-
-extern unsigned int txx9_gbus_clock;
-
-#define SPI_FIFO_SIZE	4
-
-void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on))
-{
-	txx9_spi_cs_func = cs_func;
-	/* enter config mode */
-	tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
-}
-
-static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait);
-
-static irqreturn_t txx9_spi_interrupt(int irq, void *dev_id)
-{
-	/* disable rx intr */
-	tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE;
-	wake_up(&txx9_spi_wait);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction txx9_spi_action = {
-	.handler	= txx9_spi_interrupt,
-	.name		= "spi",
-};
-
-void __init txx9_spi_irqinit(int irc_irq)
-{
-	setup_irq(irc_irq, &txx9_spi_action);
-}
-
-int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
-		unsigned char **inbufs, unsigned int *incounts,
-		unsigned char **outbufs, unsigned int *outcounts,
-		int cansleep)
-{
-	unsigned int incount, outcount;
-	unsigned char *inp, *outp;
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&txx9_spi_lock, flags);
-	if ((tx4938_spiptr->mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE) {
-		spin_unlock_irqrestore(&txx9_spi_lock, flags);
-		return -EBUSY;
-	}
-	/* enter config mode */
-	tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
-	tx4938_spiptr->cr0 =
-		(desc->byteorder ? TXx9_SPCR0_SBOS : 0) |
-		(desc->polarity ? TXx9_SPCR0_SPOL : 0) |
-		(desc->phase ? TXx9_SPCR0_SPHA : 0) |
-		0x08;
-	tx4938_spiptr->cr1 =
-		(((TXX9_IMCLK + desc->baud) / (2 * desc->baud) - 1) << 8) |
-		0x08 /* 8 bit only */;
-	/* enter active mode */
-	tx4938_spiptr->mcr = TXx9_SPMCR_ACTIVE;
-	spin_unlock_irqrestore(&txx9_spi_lock, flags);
-
-	/* CS ON */
-	if ((ret = txx9_spi_cs_func(chipid, 1)) < 0) {
-		spin_unlock_irqrestore(&txx9_spi_lock, flags);
-		return ret;
-	}
-	udelay(desc->tcss);
-
-	/* do scatter IO */
-	inp = inbufs ? *inbufs : NULL;
-	outp = outbufs ? *outbufs : NULL;
-	incount = 0;
-	outcount = 0;
-	while (1) {
-		unsigned char data;
-		unsigned int count;
-		int i;
-		if (!incount) {
-			incount = incounts ? *incounts++ : 0;
-			inp = (incount && inbufs) ? *inbufs++ : NULL;
-		}
-		if (!outcount) {
-			outcount = outcounts ? *outcounts++ : 0;
-			outp = (outcount && outbufs) ? *outbufs++ : NULL;
-		}
-		if (!inp && !outp)
-			break;
-		count = SPI_FIFO_SIZE;
-		if (incount)
-			count = min(count, incount);
-		if (outcount)
-			count = min(count, outcount);
-
-		/* now tx must be idle... */
-		while (!(tx4938_spiptr->sr & TXx9_SPSR_SIDLE))
-			;
-
-		tx4938_spiptr->cr0 =
-			(tx4938_spiptr->cr0 & ~TXx9_SPCR0_RXIFL_MASK) |
-			((count - 1) << 12);
-		if (cansleep) {
-			/* enable rx intr */
-			tx4938_spiptr->cr0 |= TXx9_SPCR0_RBSIE;
-		}
-		/* send */
-		for (i = 0; i < count; i++)
-			tx4938_spiptr->dr = inp ? *inp++ : 0;
-		/* wait all rx data */
-		if (cansleep) {
-			wait_event(txx9_spi_wait,
-				   tx4938_spiptr->sr & TXx9_SPSR_SRRDY);
-		} else {
-			while (!(tx4938_spiptr->sr & TXx9_SPSR_RBSI))
-				;
-		}
-		/* receive */
-		for (i = 0; i < count; i++) {
-			data = tx4938_spiptr->dr;
-			if (outp)
-				*outp++ = data;
-		}
-		if (incount)
-			incount -= count;
-		if (outcount)
-			outcount -= count;
-	}
-
-	/* CS OFF */
-	udelay(desc->tcsh);
-	txx9_spi_cs_func(chipid, 0);
-	udelay(desc->tcsr);
-
-	spin_lock_irqsave(&txx9_spi_lock, flags);
-	/* enter config mode */
-	tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
-	spin_unlock_irqrestore(&txx9_spi_lock, flags);
-
-	return 0;
-}
diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
index 4c0a7d7..615b658 100644
--- a/arch/ppc/8260_io/enet.c
+++ b/arch/ppc/8260_io/enet.c
@@ -477,9 +477,9 @@
 		}
 		else {
 			skb_put(skb,pkt_len-4);	/* Make room */
-			eth_copy_and_sum(skb,
+			skb_copy_to_linear_data(skb,
 				(unsigned char *)__va(bdp->cbd_bufaddr),
-				pkt_len-4, 0);
+				pkt_len-4);
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb);
 		}
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index cab395d..6f3ed6a 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -734,9 +734,9 @@
 		}
 		else {
 			skb_put(skb,pkt_len);	/* Make room */
-			eth_copy_and_sum(skb,
+			skb_copy_to_linear_data(skb,
 				(unsigned char *)__va(bdp->cbd_bufaddr),
-				pkt_len, 0);
+				pkt_len);
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb);
 		}
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
index e58288e..703d47e 100644
--- a/arch/ppc/8xx_io/enet.c
+++ b/arch/ppc/8xx_io/enet.c
@@ -506,9 +506,9 @@
 		}
 		else {
 			skb_put(skb,pkt_len-4);	/* Make room */
-			eth_copy_and_sum(skb,
+			skb_copy_to_linear_data(skb,
 				cep->rx_vaddr[bdp - cep->rx_bd_base],
-				pkt_len-4, 0);
+				pkt_len-4);
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb);
 		}
diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
index d38335d..0288279 100644
--- a/arch/ppc/8xx_io/fec.c
+++ b/arch/ppc/8xx_io/fec.c
@@ -725,7 +725,7 @@
 		fep->stats.rx_dropped++;
 	} else {
 		skb_put(skb,pkt_len-4);	/* Make room */
-		eth_copy_and_sum(skb, data, pkt_len-4, 0);
+		skb_copy_to_linear_data(skb, data, pkt_len-4);
 		skb->protocol=eth_type_trans(skb,dev);
 		netif_rx(skb);
 	}
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
index 2775d261..95f5160 100644
--- a/arch/s390/crypto/crypt_s390.h
+++ b/arch/s390/crypto/crypt_s390.h
@@ -24,7 +24,7 @@
 #define CRYPT_S390_PRIORITY 300
 #define CRYPT_S390_COMPOSITE_PRIORITY 400
 
-/* s930 cryptographic operations */
+/* s390 cryptographic operations */
 enum crypt_s390_operations {
 	CRYPT_S390_KM   = 0x0100,
 	CRYPT_S390_KMC  = 0x0200,
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 50538e5..e6289ee 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -171,37 +171,6 @@
 }
 #endif
 
-#define ADDR2G	(1UL << 31)
-
-static noinline __init unsigned long sclp_memory_detect(void)
-{
-	struct sclp_readinfo_sccb *sccb;
-	unsigned long long memsize;
-
-	sccb = &s390_readinfo_sccb;
-
-	if (sccb->header.response_code != 0x10)
-		return 0;
-
-	if (sccb->rnsize)
-		memsize = sccb->rnsize << 20;
-	else
-		memsize = sccb->rnsize2 << 20;
-	if (sccb->rnmax)
-		memsize *= sccb->rnmax;
-	else
-		memsize *= sccb->rnmax2;
-#ifndef CONFIG_64BIT
-	/*
-	 * Can't deal with more than 2G in 31 bit addressing mode, so
-	 * limit the value in order to avoid strange side effects.
-	 */
-	if (memsize > ADDR2G)
-		memsize = ADDR2G;
-#endif
-	return (unsigned long) memsize;
-}
-
 static inline __init unsigned long __tprot(unsigned long addr)
 {
 	int cc = -1;
@@ -218,6 +187,7 @@
 
 /* Checking memory in 128KB increments. */
 #define CHUNK_INCR	(1UL << 17)
+#define ADDR2G		(1UL << 31)
 
 static noinline __init void find_memory_chunks(unsigned long memsize)
 {
@@ -293,7 +263,7 @@
  */
 void __init startup_init(void)
 {
-	unsigned long memsize;
+	unsigned long long memsize;
 
 	ipl_save_parameters();
 	clear_bss_section();
@@ -305,8 +275,17 @@
 	sort_main_extable();
 	setup_lowcore_early();
 	sclp_readinfo_early();
+	sclp_facilities_detect();
 	memsize = sclp_memory_detect();
+#ifndef CONFIG_64BIT
+	/*
+	 * Can't deal with more than 2G in 31 bit addressing mode, so
+	 * limit the value in order to avoid strange side effects.
+	 */
+	if (memsize > ADDR2G)
+		memsize = ADDR2G;
+#endif
 	if (memory_fast_detect() < 0)
-		find_memory_chunks(memsize);
+		find_memory_chunks((unsigned long) memsize);
 	lockdep_on();
 }
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 6234c69..bc7ff36 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -107,6 +107,11 @@
 	l	%r13,__LC_SVC_NEW_PSW+4	# load &system_call to %r13
 	.endm
 
+	.macro	SAVE_ALL_SVC psworg,savearea
+	la	%r12,\psworg
+	l	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
+	.endm
+
 	.macro	SAVE_ALL_SYNC psworg,savearea
 	la	%r12,\psworg
 	tm	\psworg+1,0x01		# test problem state bit
@@ -218,7 +223,7 @@
 	STORE_TIMER __LC_SYNC_ENTER_TIMER
 sysc_saveall:
 	SAVE_ALL_BASE __LC_SAVE_AREA
-	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	lh	%r7,0x8a	  # get svc number from lowcore
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 685f11fa..2a7b130 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -99,6 +99,11 @@
 	larl	%r13,system_call
 	.endm
 
+	.macro	SAVE_ALL_SVC psworg,savearea
+	la	%r12,\psworg
+	lg	%r15,__LC_KERNEL_STACK	# problem state -> load ksp
+	.endm
+
 	.macro	SAVE_ALL_SYNC psworg,savearea
 	la	%r12,\psworg
 	tm	\psworg+1,0x01		# test problem state bit
@@ -207,7 +212,7 @@
 	STORE_TIMER __LC_SYNC_ENTER_TIMER
 sysc_saveall:
 	SAVE_ALL_BASE __LC_SAVE_AREA
-	SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+	SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	llgh	%r7,__LC_SVC_INT_CODE	# get svc number from lowcore
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 367caf9..82b131d 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -25,10 +25,6 @@
 
 #define IPL_PARM_BLOCK_VERSION 0
 
-#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
-#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
-#define SCCB_FLAG (s390_readinfo_sccb.flags)
-
 #define IPL_UNKNOWN_STR		"unknown"
 #define IPL_CCW_STR		"ccw"
 #define IPL_FCP_STR		"fcp"
@@ -146,6 +142,8 @@
 
 static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
 
+static struct sclp_ipl_info sclp_ipl_info;
+
 int diag308(unsigned long subcode, void *addr)
 {
 	register unsigned long _addr asm("0") = (unsigned long) addr;
@@ -375,9 +373,9 @@
 {
 	char loadparm[LOADPARM_LEN + 1] = {};
 
-	if (!SCCB_VALID)
+	if (!sclp_ipl_info.is_valid)
 		return sprintf(page, "#unknown#\n");
-	memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN);
+	memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
 	EBCASC(loadparm, LOADPARM_LEN);
 	strstrip(loadparm);
 	return sprintf(page, "%s\n", loadparm);
@@ -910,9 +908,9 @@
 	reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
 	reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
 	/* check if read scp info worked and set loadparm */
-	if (SCCB_VALID)
+	if (sclp_ipl_info.is_valid)
 		memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
-		       SCCB_LOADPARM, LOADPARM_LEN);
+		       &sclp_ipl_info.loadparm, LOADPARM_LEN);
 	else
 		/* read scp info failed: set empty loadparm (EBCDIC blanks) */
 		memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
@@ -1007,7 +1005,7 @@
 {
 	int rc;
 
-	if(!(SCCB_FLAG & 0x2) || !SCCB_VALID)
+	if (!sclp_ipl_info.has_dump)
 		return 0; /* LDIPL DUMP is not installed */
 	if (!diag308_set_works)
 		return 0;
@@ -1088,6 +1086,7 @@
 {
 	int rc;
 
+	sclp_get_ipl_info(&sclp_ipl_info);
 	reipl_probe();
 	rc = ipl_init();
 	if (rc)
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index eb43c3b..441975b 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -93,8 +93,8 @@
 	/* disable monitor call class 0 */
 	__ctl_clear_bit(8, 15);
 
-	atomic_notifier_call_chain(&idle_chain, CPU_NOT_IDLE,
-			    (void *)(long) smp_processor_id());
+	atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+				   (void *)(long) smp_processor_id());
 }
 
 extern void s390_handle_mcck(void);
@@ -115,7 +115,7 @@
 	}
 
 	rc = atomic_notifier_call_chain(&idle_chain,
-			CPU_IDLE, (void *)(long) cpu);
+					S390_CPU_IDLE, (void *)(long) cpu);
 	if (rc != NOTIFY_OK && rc != NOTIFY_DONE)
 		BUG();
 	if (rc != NOTIFY_OK) {
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 8ff2fea..182c085a 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -410,58 +410,40 @@
 unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \
 	__attribute__((__section__(".data")));
 
-static void __init smp_get_save_areas(void)
+static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
 {
-	unsigned int cpu, cpu_num, rc;
-	__u16 boot_cpu_addr;
-
 	if (ipl_info.type != IPL_TYPE_FCP_DUMP)
 		return;
-	boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
-	cpu_num = 1;
-	for (cpu = 0; cpu <= 65535; cpu++) {
-		if ((u16) cpu == boot_cpu_addr)
-			continue;
-		__cpu_logical_map[1] = (__u16) cpu;
-		if (signal_processor(1, sigp_sense) == sigp_not_operational)
-			continue;
-		if (cpu_num >= NR_CPUS) {
-			printk("WARNING: Registers for cpu %i are not "
-			       "saved, since dump kernel was compiled with"
-			       "NR_CPUS=%i!\n", cpu_num, NR_CPUS);
-			continue;
-		}
-		zfcpdump_save_areas[cpu_num] =
-			alloc_bootmem(sizeof(union save_area));
-		while (1) {
-			rc = signal_processor(1, sigp_stop_and_store_status);
-			if (rc != sigp_busy)
-				break;
-			cpu_relax();
-		}
-		memcpy(zfcpdump_save_areas[cpu_num],
-		       (void *)(unsigned long) store_prefix() +
-		       SAVE_AREA_BASE, SAVE_AREA_SIZE);
-#ifdef __s390x__
-		/* copy original prefix register */
-		zfcpdump_save_areas[cpu_num]->s390x.pref_reg =
-			zfcpdump_prefix_array[cpu_num];
-#endif
-		cpu_num++;
+	if (cpu >= NR_CPUS) {
+		printk(KERN_WARNING "Registers for cpu %i not saved since dump "
+		       "kernel was compiled with NR_CPUS=%i\n", cpu, NR_CPUS);
+		return;
 	}
+	zfcpdump_save_areas[cpu] = alloc_bootmem(sizeof(union save_area));
+	__cpu_logical_map[1] = (__u16) phy_cpu;
+	while (signal_processor(1, sigp_stop_and_store_status) == sigp_busy)
+		cpu_relax();
+	memcpy(zfcpdump_save_areas[cpu],
+	       (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
+	       SAVE_AREA_SIZE);
+#ifdef CONFIG_64BIT
+	/* copy original prefix register */
+	zfcpdump_save_areas[cpu]->s390x.pref_reg = zfcpdump_prefix_array[cpu];
+#endif
 }
 
 union save_area *zfcpdump_save_areas[NR_CPUS + 1];
 EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
 
 #else
-#define smp_get_save_areas() do { } while (0)
-#endif
+
+static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { }
+
+#endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */
 
 /*
  * Lets check how many CPUs we have.
  */
-
 static unsigned int __init smp_count_cpus(void)
 {
 	unsigned int cpu, num_cpus;
@@ -470,7 +452,6 @@
 	/*
 	 * cpu 0 is the boot cpu. See smp_prepare_boot_cpu.
 	 */
-
 	boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
 	current_thread_info()->cpu = 0;
 	num_cpus = 1;
@@ -480,12 +461,11 @@
 		__cpu_logical_map[1] = (__u16) cpu;
 		if (signal_processor(1, sigp_sense) == sigp_not_operational)
 			continue;
+		smp_get_save_area(num_cpus, cpu);
 		num_cpus++;
 	}
-
 	printk("Detected %d CPU's\n", (int) num_cpus);
 	printk("Boot cpu address %2X\n", boot_cpu_addr);
-
 	return num_cpus;
 }
 
@@ -606,7 +586,6 @@
 {
 	unsigned int phy_cpus, pos_cpus, cpu;
 
-	smp_get_save_areas();
 	phy_cpus = smp_count_cpus();
 	pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS);
 
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 9c2872a..48dae49 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -226,10 +226,10 @@
 			    unsigned long action, void *hcpu)
 {
 	switch (action) {
-	case CPU_IDLE:
+	case S390_CPU_IDLE:
 		stop_hz_timer();
 		break;
-	case CPU_NOT_IDLE:
+	case S390_CPU_NOT_IDLE:
 		start_hz_timer();
 		break;
 	}
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 1e1a6ee..b6ed143 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -545,10 +545,10 @@
 			      unsigned long action, void *hcpu)
 {
 	switch (action) {
-	case CPU_IDLE:
+	case S390_CPU_IDLE:
 		stop_cpu_timer();
 		break;
-	case CPU_NOT_IDLE:
+	case S390_CPU_NOT_IDLE:
 		start_cpu_timer();
 		break;
 	}
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index 59aea65..5208443 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -4,7 +4,7 @@
 
 EXTRA_AFLAGS := -traditional
 
-lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o
-obj-$(CONFIG_32BIT) += div64.o
+lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+obj-$(CONFIG_32BIT) += div64.o qrnnd.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 4d9ad590..4fea3ac 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -68,16 +68,6 @@
 	cpu_data(id).prom_node = cpu_node;
 	cpu_data(id).mid = cpu_get_hwmid(cpu_node);
 
-	/* this is required to tune the scheduler correctly */
-	/* is it possible to have CPUs with different cache sizes? */
-	if (id == boot_cpu_id) {
-		int cache_line,cache_nlines;
-		cache_line = 0x20;
-		cache_line = prom_getintdefault(cpu_node, "ecache-line-size", cache_line);
-		cache_nlines = 0x8000;
-		cache_nlines = prom_getintdefault(cpu_node, "ecache-nlines", cache_nlines);
-		max_cache_size = cache_line * cache_nlines;
-	}
 	if (cpu_data(id).mid < 0)
 		panic("No MID found for CPU%d at node 0x%08d", id, cpu_node);
 }
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 4dcd7d0..40e40f9 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -1163,32 +1163,6 @@
 	return -EINVAL;
 }
 
-static void __init smp_tune_scheduling(void)
-{
-	unsigned int smallest = ~0U;
-	int i;
-
-	for (i = 0; i < NR_CPUS; i++) {
-		unsigned int val = cpu_data(i).ecache_size;
-
-		if (val && val < smallest)
-			smallest = val;
-	}
-
-	/* Any value less than 256K is nonsense.  */
-	if (smallest < (256U * 1024U))
-		smallest = 256 * 1024;
-
-	max_cache_size = smallest;
-
-	if (smallest < 1U * 1024U * 1024U)
-		printk(KERN_INFO "Using max_cache_size of %uKB\n",
-		       smallest / 1024U);
-	else
-		printk(KERN_INFO "Using max_cache_size of %uMB\n",
-		       smallest / 1024U / 1024U);
-}
-
 /* Constrain the number of cpus to max_cpus.  */
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
@@ -1206,7 +1180,6 @@
 	}
 
 	cpu_data(boot_cpu_id).udelay_val = loops_per_jiffy;
-	smp_tune_scheduling();
 }
 
 void __devinit smp_prepare_boot_cpu(void)
diff --git a/block/Kconfig b/block/Kconfig
index a50f481..2859351 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -1,7 +1,7 @@
 #
 # Block layer core configuration
 #
-config BLOCK
+menuconfig BLOCK
        bool "Enable the block layer" if EMBEDDED
        default y
        help
@@ -49,6 +49,6 @@
 
 	  If unsure, say Y.
 
-endif
+endif # BLOCK
 
 source block/Kconfig.iosched
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index baef5fc..e0aa4da 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -92,6 +92,8 @@
 	struct cfq_queue *active_queue;
 	struct cfq_io_context *active_cic;
 
+	struct cfq_queue *async_cfqq[IOPRIO_BE_NR];
+
 	struct timer_list idle_class_timer;
 
 	sector_t last_position;
@@ -1351,8 +1353,8 @@
 }
 
 static struct cfq_queue *
-cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
-	      gfp_t gfp_mask)
+cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync,
+		     struct task_struct *tsk, gfp_t gfp_mask)
 {
 	struct cfq_queue *cfqq, *new_cfqq = NULL;
 	struct cfq_io_context *cic;
@@ -1405,12 +1407,35 @@
 	if (new_cfqq)
 		kmem_cache_free(cfq_pool, new_cfqq);
 
-	atomic_inc(&cfqq->ref);
 out:
 	WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
 	return cfqq;
 }
 
+static struct cfq_queue *
+cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
+	      gfp_t gfp_mask)
+{
+	const int ioprio = task_ioprio(tsk);
+	struct cfq_queue *cfqq = NULL;
+
+	if (!is_sync)
+		cfqq = cfqd->async_cfqq[ioprio];
+	if (!cfqq)
+		cfqq = cfq_find_alloc_queue(cfqd, is_sync, tsk, gfp_mask);
+
+	/*
+	 * pin the queue now that it's allocated, scheduler exit will prune it
+	 */
+	if (!is_sync && !cfqd->async_cfqq[ioprio]) {
+		atomic_inc(&cfqq->ref);
+		cfqd->async_cfqq[ioprio] = cfqq;
+	}
+
+	atomic_inc(&cfqq->ref);
+	return cfqq;
+}
+
 /*
  * We drop cfq io contexts lazily, so we may find a dead one.
  */
@@ -2019,6 +2044,7 @@
 {
 	struct cfq_data *cfqd = e->elevator_data;
 	request_queue_t *q = cfqd->queue;
+	int i;
 
 	cfq_shutdown_timer_wq(cfqd);
 
@@ -2035,6 +2061,13 @@
 		__cfq_exit_single_io_context(cfqd, cic);
 	}
 
+	/*
+	 * Put the async queues
+	 */
+	for (i = 0; i < IOPRIO_BE_NR; i++)
+		if (cfqd->async_cfqq[i])	
+			cfq_put_queue(cfqd->async_cfqq[i]);
+
 	spin_unlock_irq(q->queue_lock);
 
 	cfq_shutdown_timer_wq(cfqd);
diff --git a/block/elevator.c b/block/elevator.c
index ce866eb..4769a25 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -112,12 +112,8 @@
 static struct elevator_type *elevator_find(const char *name)
 {
 	struct elevator_type *e;
-	struct list_head *entry;
 
-	list_for_each(entry, &elv_list) {
-
-		e = list_entry(entry, struct elevator_type, list);
-
+	list_for_each_entry(e, &elv_list, list) {
 		if (!strcmp(e->elevator_name, name))
 			return e;
 	}
@@ -1116,14 +1112,11 @@
 {
 	elevator_t *e = q->elevator;
 	struct elevator_type *elv = e->elevator_type;
-	struct list_head *entry;
+	struct elevator_type *__e;
 	int len = 0;
 
 	spin_lock(&elv_list_lock);
-	list_for_each(entry, &elv_list) {
-		struct elevator_type *__e;
-
-		__e = list_entry(entry, struct elevator_type, list);
+	list_for_each_entry(__e, &elv_list, list) {
 		if (!strcmp(elv->elevator_name, __e->elevator_name))
 			len += sprintf(name+len, "[%s] ", elv->elevator_name);
 		else
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index c99b463..ef42bb2 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -527,8 +527,6 @@
 static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
 {
 	request_queue_t *q = bio->bi_private;
-	struct bio_vec *bvec;
-	int i;
 
 	/*
 	 * This is dry run, restore bio_sector and size.  We'll finish
@@ -540,13 +538,6 @@
 	if (bio->bi_size)
 		return 1;
 
-	/* Rewind bvec's */
-	bio->bi_idx = 0;
-	bio_for_each_segment(bvec, bio, i) {
-		bvec->bv_len += bvec->bv_offset;
-		bvec->bv_offset = 0;
-	}
-
 	/* Reset bio */
 	set_bit(BIO_UPTODATE, &bio->bi_flags);
 	bio->bi_size = q->bi_size;
@@ -1304,9 +1295,9 @@
 	if (unlikely(!bio_flagged(nxt, BIO_SEG_VALID)))
 		blk_recount_segments(q, nxt);
 	if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) ||
-	    BIOVEC_VIRT_OVERSIZE(bio->bi_hw_front_size + bio->bi_hw_back_size))
+	    BIOVEC_VIRT_OVERSIZE(bio->bi_hw_back_size + nxt->bi_hw_front_size))
 		return 0;
-	if (bio->bi_size + nxt->bi_size > q->max_segment_size)
+	if (bio->bi_hw_back_size + nxt->bi_hw_front_size > q->max_segment_size)
 		return 0;
 
 	return 1;
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 050323f..7916f4b 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -24,8 +24,6 @@
 
 source "drivers/ata/Kconfig"
 
-source "drivers/cdrom/Kconfig"
-
 source "drivers/md/Kconfig"
 
 source "drivers/message/fusion/Kconfig"
@@ -54,6 +52,8 @@
 
 source "drivers/w1/Kconfig"
 
+source "drivers/power/Kconfig"
+
 source "drivers/hwmon/Kconfig"
 
 source "drivers/mfd/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index adad2f3..503d825 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -61,6 +61,7 @@
 obj-$(CONFIG_RTC_LIB)		+= rtc/
 obj-y				+= i2c/
 obj-$(CONFIG_W1)		+= w1/
+obj-$(CONFIG_POWER_SUPPLY)	+= power/
 obj-$(CONFIG_HWMON)		+= hwmon/
 obj-$(CONFIG_PHONE)		+= telephony/
 obj-$(CONFIG_MD)		+= md/
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index 674bf81..423ed08 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -1246,7 +1246,7 @@
 	del_timer(&motor_off_timer);
 
 	ReqCnt = 0;
-	ReqCmd = CURRENT->cmd;
+	ReqCmd = rq_data_dir(CURRENT);
 	ReqBlock = CURRENT->sector;
 	ReqBuffer = CURRENT->buffer;
 	setup_req_params(drive);
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 689a4c3..d85520f 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -439,7 +439,7 @@
 	   a choice of command end or some data which is ready to be collected */
 	/* I think we have to transfer data while the interrupt line is on and its
 	   not any other type of interrupt */
-	if (CURRENT->cmd == WRITE) {
+	if (rq_data_dir(CURRENT) == WRITE) {
 		extern void hdc63463_writedma(void);
 		if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
 			printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n");
@@ -799,7 +799,7 @@
 	raw_cmd.head = start_head;
 	raw_cmd.cylinder = track / p->heads;
 	raw_cmd.cmdtype = CURRENT->cmd;
-	raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;
+	raw_cmd.cmdcode = rq_data_dir(CURRENT) == WRITE ? CMD_WD : CMD_RD;
 	raw_cmd.cmddata[0] = dev + 1;	/* DAG: +1 to get US */
 	raw_cmd.cmddata[1] = raw_cmd.head;
 	raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8;
@@ -830,7 +830,7 @@
 	hdc63463_dataleft = nsect * 256;	/* Better way? */
 
 	DBG("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n",
-	     raw_cmd.dev + 'a', (CURRENT->cmd == READ) ? "read" : "writ",
+	     raw_cmd.dev + 'a', rq_data_dir(CURRENT) == READ ? "read" : "writ",
 		       raw_cmd.cylinder,
 		       raw_cmd.head,
 	    raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT);
@@ -917,13 +917,6 @@
 
 		DBG("mfm_request: block after offset=%d\n", block);
 
-		if (CURRENT->cmd != READ && CURRENT->cmd != WRITE) {
-			printk("unknown mfm-command %d\n", CURRENT->cmd);
-			end_request(CURRENT, 0);
-			Busy = 0;
-			printk("mfm: continue 4\n");
-			continue;
-		}
 		issue_request(block, nsect, CURRENT);
 
 		break;
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index ca5229d..11e4eb9 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"ahci"
-#define DRV_VERSION	"2.2"
+#define DRV_VERSION	"2.3"
 
 
 enum {
@@ -54,7 +54,7 @@
 	AHCI_MAX_PORTS		= 32,
 	AHCI_MAX_SG		= 168, /* hardware max is 64K */
 	AHCI_DMA_BOUNDARY	= 0xffffffff,
-	AHCI_USE_CLUSTERING	= 0,
+	AHCI_USE_CLUSTERING	= 1,
 	AHCI_MAX_CMDS		= 32,
 	AHCI_CMD_SZ		= 32,
 	AHCI_CMD_SLOT_SZ	= AHCI_MAX_CMDS * AHCI_CMD_SZ,
@@ -81,6 +81,7 @@
 	board_ahci_vt8251	= 2,
 	board_ahci_ign_iferr	= 3,
 	board_ahci_sb600	= 4,
+	board_ahci_mv		= 5,
 
 	/* global controller registers */
 	HOST_CAP		= 0x00, /* host capabilities */
@@ -171,6 +172,8 @@
 	AHCI_FLAG_HONOR_PI		= (1 << 26), /* honor PORTS_IMPL */
 	AHCI_FLAG_IGN_SERR_INTERNAL	= (1 << 27), /* ignore SERR_INTERNAL */
 	AHCI_FLAG_32BIT_ONLY		= (1 << 28), /* force 32bit */
+	AHCI_FLAG_MV_PATA		= (1 << 29), /* PATA port */
+	AHCI_FLAG_NO_MSI		= (1 << 30), /* no PCI MSI */
 
 	AHCI_FLAG_COMMON		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 					  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
@@ -228,9 +231,12 @@
 static void ahci_error_handler(struct ata_port *ap);
 static void ahci_vt8251_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+static int ahci_port_resume(struct ata_port *ap);
+static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
+static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+			       u32 opts);
 #ifdef CONFIG_PM
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
-static int ahci_port_resume(struct ata_port *ap);
 static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 static int ahci_pci_device_resume(struct pci_dev *pdev);
 #endif
@@ -327,14 +333,14 @@
 	{
 		.flags		= AHCI_FLAG_COMMON,
 		.pio_mask	= 0x1f, /* pio0-4 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
 	/* board_ahci_pi */
 	{
 		.flags		= AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI,
 		.pio_mask	= 0x1f, /* pio0-4 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
 	/* board_ahci_vt8251 */
@@ -342,14 +348,14 @@
 		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_HRST_TO_RESUME |
 				  AHCI_FLAG_NO_NCQ,
 		.pio_mask	= 0x1f, /* pio0-4 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_vt8251_ops,
 	},
 	/* board_ahci_ign_iferr */
 	{
 		.flags		= AHCI_FLAG_COMMON | AHCI_FLAG_IGN_IRQ_IF_ERR,
 		.pio_mask	= 0x1f, /* pio0-4 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
 	/* board_ahci_sb600 */
@@ -358,7 +364,19 @@
 				  AHCI_FLAG_IGN_SERR_INTERNAL |
 				  AHCI_FLAG_32BIT_ONLY,
 		.pio_mask	= 0x1f, /* pio0-4 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_ops,
+	},
+	/* board_ahci_mv */
+	{
+		.sht		= &ahci_sht,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+				  ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI |
+				  AHCI_FLAG_NO_NCQ | AHCI_FLAG_NO_MSI |
+				  AHCI_FLAG_MV_PATA,
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
 };
@@ -456,6 +474,9 @@
 	{ PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */
 	{ PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
 
+	/* Marvell */
+	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */
+
 	/* Generic, PCI class code for AHCI */
 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
@@ -481,11 +502,17 @@
 	return (cap & 0x1f) + 1;
 }
 
+static inline void __iomem *__ahci_port_base(struct ata_host *host,
+					     unsigned int port_no)
+{
+	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
+
+	return mmio + 0x100 + (port_no * 0x80);
+}
+
 static inline void __iomem *ahci_port_base(struct ata_port *ap)
 {
-	void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
-
-	return mmio + 0x100 + (ap->port_no * 0x80);
+	return __ahci_port_base(ap->host, ap->port_no);
 }
 
 /**
@@ -535,6 +562,20 @@
 		hpriv->saved_port_map = port_map;
 	}
 
+	/*
+	 * Temporary Marvell 6145 hack: PATA port presence
+	 * is asserted through the standard AHCI port
+	 * presence register, as bit 4 (counting from 0)
+	 */
+	if (pi->flags & AHCI_FLAG_MV_PATA) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "MV_AHCI HACK: port_map %x -> %x\n",
+			   hpriv->port_map,
+			   hpriv->port_map & 0xf);
+
+		port_map &= 0xf;
+	}
+
 	/* cross check port_map and cap.n_ports */
 	if (pi->flags & AHCI_FLAG_HONOR_PI) {
 		u32 tmp_port_map = port_map;
@@ -740,7 +781,7 @@
 }
 #endif
 
-static void ahci_init_port(struct ata_port *ap)
+static void ahci_start_port(struct ata_port *ap)
 {
 	/* enable FIS reception */
 	ahci_start_fis_rx(ap);
@@ -814,39 +855,62 @@
 	return 0;
 }
 
+static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
+			   int port_no, void __iomem *mmio,
+			   void __iomem *port_mmio)
+{
+	const char *emsg = NULL;
+	int rc;
+	u32 tmp;
+
+	/* make sure port is not active */
+	rc = ahci_deinit_port(ap, &emsg);
+	if (rc)
+		dev_printk(KERN_WARNING, &pdev->dev,
+			   "%s (%d)\n", emsg, rc);
+
+	/* clear SError */
+	tmp = readl(port_mmio + PORT_SCR_ERR);
+	VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
+	writel(tmp, port_mmio + PORT_SCR_ERR);
+
+	/* clear port IRQ */
+	tmp = readl(port_mmio + PORT_IRQ_STAT);
+	VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
+	if (tmp)
+		writel(tmp, port_mmio + PORT_IRQ_STAT);
+
+	writel(1 << port_no, mmio + HOST_IRQ_STAT);
+}
+
 static void ahci_init_controller(struct ata_host *host)
 {
 	struct pci_dev *pdev = to_pci_dev(host->dev);
 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
-	int i, rc;
+	int i;
+	void __iomem *port_mmio;
 	u32 tmp;
 
-	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
-		void __iomem *port_mmio = ahci_port_base(ap);
-		const char *emsg = NULL;
+	if (host->ports[0]->flags & AHCI_FLAG_MV_PATA) {
+		port_mmio = __ahci_port_base(host, 4);
 
-		if (ata_port_is_dummy(ap))
-			continue;
-
-		/* make sure port is not active */
-		rc = ahci_deinit_port(ap, &emsg);
-		if (rc)
-			dev_printk(KERN_WARNING, &pdev->dev,
-				   "%s (%d)\n", emsg, rc);
-
-		/* clear SError */
-		tmp = readl(port_mmio + PORT_SCR_ERR);
-		VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
-		writel(tmp, port_mmio + PORT_SCR_ERR);
+		writel(0, port_mmio + PORT_IRQ_MASK);
 
 		/* clear port IRQ */
 		tmp = readl(port_mmio + PORT_IRQ_STAT);
 		VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
 		if (tmp)
 			writel(tmp, port_mmio + PORT_IRQ_STAT);
+	}
 
-		writel(1 << i, mmio + HOST_IRQ_STAT);
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_port *ap = host->ports[i];
+
+		port_mmio = ahci_port_base(ap);
+		if (ata_port_is_dummy(ap))
+			continue;
+
+		ahci_port_init(pdev, ap, i, mmio, port_mmio);
 	}
 
 	tmp = readl(mmio + HOST_CTL);
@@ -1232,7 +1296,7 @@
 		ata_port_abort(ap);
 }
 
-static void ahci_host_intr(struct ata_port *ap)
+static void ahci_port_intr(struct ata_port *ap)
 {
 	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
 	struct ata_eh_info *ehi = &ap->eh_info;
@@ -1358,7 +1422,7 @@
 
 		ap = host->ports[i];
 		if (ap) {
-			ahci_host_intr(ap);
+			ahci_port_intr(ap);
 			VPRINTK("port %u\n", i);
 		} else {
 			VPRINTK("port %u (no irq)\n", i);
@@ -1466,7 +1530,7 @@
 		ahci_power_down(ap);
 	else {
 		ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
-		ahci_init_port(ap);
+		ahci_start_port(ap);
 	}
 
 	return rc;
@@ -1475,7 +1539,7 @@
 static int ahci_port_resume(struct ata_port *ap)
 {
 	ahci_power_up(ap);
-	ahci_init_port(ap);
+	ahci_start_port(ap);
 
 	return 0;
 }
@@ -1573,13 +1637,8 @@
 
 	ap->private_data = pp;
 
-	/* power up port */
-	ahci_power_up(ap);
-
-	/* initialize port */
-	ahci_init_port(ap);
-
-	return 0;
+	/* engage engines, captain */
+	return ahci_port_resume(ap);
 }
 
 static void ahci_port_stop(struct ata_port *ap)
@@ -1724,7 +1783,7 @@
 	if (rc)
 		return rc;
 
-	if (pci_enable_msi(pdev))
+	if ((pi.flags & AHCI_FLAG_NO_MSI) || pci_enable_msi(pdev))
 		pci_intx(pdev, 1);
 
 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
@@ -1745,14 +1804,18 @@
 	host->private_data = hpriv;
 
 	for (i = 0; i < host->n_ports; i++) {
-		if (hpriv->port_map & (1 << i)) {
-			struct ata_port *ap = host->ports[i];
-			void __iomem *port_mmio = ahci_port_base(ap);
+		struct ata_port *ap = host->ports[i];
+		void __iomem *port_mmio = ahci_port_base(ap);
 
+		/* standard SATA port setup */
+		if (hpriv->port_map & (1 << i)) {
 			ap->ioaddr.cmd_addr = port_mmio;
 			ap->ioaddr.scr_addr = port_mmio + PORT_SCR;
-		} else
-			host->ports[i]->ops = &ata_dummy_port_ops;
+		}
+
+		/* disabled/not-implemented port */
+		else
+			ap->ops = &ata_dummy_port_ops;
 	}
 
 	/* initialize adapter */
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 4c6e95c..430fcf4 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -143,10 +143,10 @@
 	u16 command;
 	static const struct ata_port_info info = {
 		.sht = &generic_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &generic_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 9c07b886..6a3bfef 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -200,6 +200,8 @@
 	/* ICH7/7-R (i945, i975) UDMA 100*/
 	{ 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 },
 	{ 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+	/* ICH8 Mobile PATA Controller */
+	{ 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
 
 	/* NOTE: The following PCI ids must be kept in sync with the
 	 * list in drivers/pci/quirks.c.
@@ -495,7 +497,7 @@
 		.flags		= PIIX_SATA_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -505,7 +507,7 @@
 		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -516,7 +518,7 @@
 				  PIIX_FLAG_AHCI,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -527,7 +529,7 @@
 				  PIIX_FLAG_AHCI,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -538,7 +540,7 @@
 				  PIIX_FLAG_AHCI,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -685,8 +687,14 @@
 	if (adev->class == ATA_DEV_ATA)
 		control |= 4;	/* PPE enable */
 
+	/* PIO configuration clears DTE unconditionally.  It will be
+	 * programmed in set_dmamode which is guaranteed to be called
+	 * after set_piomode if any DMA mode is available.
+	 */
 	pci_read_config_word(dev, master_port, &master_data);
 	if (is_slave) {
+		/* clear TIME1|IE1|PPE1|DTE1 */
+		master_data &= 0xff0f;
 		/* Enable SITRE (seperate slave timing register) */
 		master_data |= 0x4000;
 		/* enable PPE1, IE1 and TIME1 as needed */
@@ -694,12 +702,14 @@
 		pci_read_config_byte(dev, slave_port, &slave_data);
 		slave_data &= (ap->port_no ? 0x0f : 0xf0);
 		/* Load the timing nibble for this slave */
-		slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
+		slave_data |= ((timings[pio][0] << 2) | timings[pio][1])
+						<< (ap->port_no ? 4 : 0);
 	} else {
-		/* Master keeps the bits in a different format */
-		master_data &= 0xccf8;
+		/* clear ISP|RCT|TIME0|IE0|PPE0|DTE0 */
+		master_data &= 0xccf0;
 		/* Enable PPE, IE and TIME as appropriate */
 		master_data |= control;
+		/* load ISP and RCT */
 		master_data |=
 			(timings[pio][0] << 12) |
 			(timings[pio][1] << 8);
@@ -816,7 +826,7 @@
 			master_data &= 0xFF4F;  /* Mask out IORDY|TIME1|DMAONLY */
 			master_data |= control << 4;
 			pci_read_config_byte(dev, 0x44, &slave_data);
-			slave_data &= (0x0F + 0xE1 * ap->port_no);
+			slave_data &= (ap->port_no ? 0x0f : 0xf0);
 			/* Load the matching timing */
 			slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
 			pci_write_config_byte(dev, 0x44, slave_data);
@@ -828,8 +838,11 @@
 				(timings[pio][0] << 12) |
 				(timings[pio][1] << 8);
 		}
-		udma_enable &= ~(1 << devid);
-		pci_write_config_word(dev, master_port, master_data);
+
+		if (ap->udma_mask) {
+			udma_enable &= ~(1 << devid);
+			pci_write_config_word(dev, master_port, master_data);
+		}
 	}
 	/* Don't scribble on 0x48 if the controller does not support UDMA */
 	if (ap->udma_mask)
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 0223673..c059f78 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -24,15 +24,13 @@
 #include <acpi/acmacros.h>
 #include <acpi/actypes.h>
 
-#define SATA_ROOT_PORT(x)	(((x) >> 16) & 0xffff)
-#define SATA_PORT_NUMBER(x)	((x) & 0xffff)	/* or NO_PORT_MULT */
 #define NO_PORT_MULT		0xffff
-#define SATA_ADR_RSVD		0xffffffff
+#define SATA_ADR(root,pmp)	(((root) << 16) | (pmp))
 
 #define REGS_PER_GTF		7
-struct taskfile_array {
-	u8	tfa[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */
-};
+struct ata_acpi_gtf {
+	u8	tf[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */
+} __packed;
 
 /*
  *	Helper - belongs in the PCI layer somewhere eventually
@@ -42,237 +40,173 @@
 	return (dev->bus == &pci_bus_type);
 }
 
-/**
- * sata_get_dev_handle - finds acpi_handle and PCI device.function
- * @dev: device to locate
- * @handle: returned acpi_handle for @dev
- * @pcidevfn: return PCI device.func for @dev
- *
- * This function is somewhat SATA-specific.  Or at least the
- * PATA & SATA versions of this function are different,
- * so it's not entirely generic code.
- *
- * Returns 0 on success, <0 on error.
- */
-static int sata_get_dev_handle(struct device *dev, acpi_handle *handle,
-					acpi_integer *pcidevfn)
+static void ata_acpi_associate_sata_port(struct ata_port *ap)
 {
-	struct pci_dev	*pci_dev;
-	acpi_integer	addr;
+	acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
 
-	if (!is_pci_dev(dev))
-		return -ENODEV;
+	ap->device->acpi_handle = acpi_get_child(ap->host->acpi_handle, adr);
+}
 
-	pci_dev = to_pci_dev(dev);	/* NOTE: PCI-specific */
-	/* Please refer to the ACPI spec for the syntax of _ADR. */
-	addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
-	*pcidevfn = addr;
-	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
-	if (!*handle)
-		return -ENODEV;
+static void ata_acpi_associate_ide_port(struct ata_port *ap)
+{
+	int max_devices, i;
+
+	ap->acpi_handle = acpi_get_child(ap->host->acpi_handle, ap->port_no);
+	if (!ap->acpi_handle)
+		return;
+
+	max_devices = 1;
+	if (ap->flags & ATA_FLAG_SLAVE_POSS)
+		max_devices++;
+
+	for (i = 0; i < max_devices; i++) {
+		struct ata_device *dev = &ap->device[i];
+
+		dev->acpi_handle = acpi_get_child(ap->acpi_handle, i);
+	}
+}
+
+/**
+ * ata_acpi_associate - associate ATA host with ACPI objects
+ * @host: target ATA host
+ *
+ * Look up ACPI objects associated with @host and initialize
+ * acpi_handle fields of @host, its ports and devices accordingly.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+void ata_acpi_associate(struct ata_host *host)
+{
+	int i;
+
+	if (!is_pci_dev(host->dev) || libata_noacpi)
+		return;
+
+	host->acpi_handle = DEVICE_ACPI_HANDLE(host->dev);
+	if (!host->acpi_handle)
+		return;
+
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_port *ap = host->ports[i];
+
+		if (host->ports[0]->flags & ATA_FLAG_ACPI_SATA)
+			ata_acpi_associate_sata_port(ap);
+		else
+			ata_acpi_associate_ide_port(ap);
+	}
+}
+
+/**
+ * ata_acpi_gtm - execute _GTM
+ * @ap: target ATA port
+ * @gtm: out parameter for _GTM result
+ *
+ * Evaluate _GTM and store the result in @gtm.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
+ */
+static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm)
+{
+	struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER };
+	union acpi_object *out_obj;
+	acpi_status status;
+	int rc = 0;
+
+	status = acpi_evaluate_object(ap->acpi_handle, "_GTM", NULL, &output);
+
+	rc = -ENOENT;
+	if (status == AE_NOT_FOUND)
+		goto out_free;
+
+	rc = -EINVAL;
+	if (ACPI_FAILURE(status)) {
+		ata_port_printk(ap, KERN_ERR,
+				"ACPI get timing mode failed (AE 0x%x)\n",
+				status);
+		goto out_free;
+	}
+
+	out_obj = output.pointer;
+	if (out_obj->type != ACPI_TYPE_BUFFER) {
+		ata_port_printk(ap, KERN_WARNING,
+				"_GTM returned unexpected object type 0x%x\n",
+				out_obj->type);
+
+		goto out_free;
+	}
+
+	if (out_obj->buffer.length != sizeof(struct ata_acpi_gtm)) {
+		ata_port_printk(ap, KERN_ERR,
+				"_GTM returned invalid length %d\n",
+				out_obj->buffer.length);
+		goto out_free;
+	}
+
+	memcpy(gtm, out_obj->buffer.pointer, sizeof(struct ata_acpi_gtm));
+	rc = 0;
+ out_free:
+	kfree(output.pointer);
+	return rc;
+}
+
+/**
+ * ata_acpi_stm - execute _STM
+ * @ap: target ATA port
+ * @stm: timing parameter to _STM
+ *
+ * Evaluate _STM with timing parameter @stm.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -ENOENT if _STM doesn't exist, -errno on failure.
+ */
+static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm)
+{
+	acpi_status status;
+	struct acpi_object_list         input;
+	union acpi_object               in_params[3];
+
+	in_params[0].type = ACPI_TYPE_BUFFER;
+	in_params[0].buffer.length = sizeof(struct ata_acpi_gtm);
+	in_params[0].buffer.pointer = (u8 *)stm;
+	/* Buffers for id may need byteswapping ? */
+	in_params[1].type = ACPI_TYPE_BUFFER;
+	in_params[1].buffer.length = 512;
+	in_params[1].buffer.pointer = (u8 *)ap->device[0].id;
+	in_params[2].type = ACPI_TYPE_BUFFER;
+	in_params[2].buffer.length = 512;
+	in_params[2].buffer.pointer = (u8 *)ap->device[1].id;
+
+	input.count = 3;
+	input.pointer = in_params;
+
+	status = acpi_evaluate_object(ap->acpi_handle, "_STM", &input, NULL);
+
+	if (status == AE_NOT_FOUND)
+		return -ENOENT;
+	if (ACPI_FAILURE(status)) {
+		ata_port_printk(ap, KERN_ERR,
+			"ACPI set timing mode failed (status=0x%x)\n", status);
+		return -EINVAL;
+	}
 	return 0;
 }
 
 /**
- * pata_get_dev_handle - finds acpi_handle and PCI device.function
- * @dev: device to locate
- * @handle: returned acpi_handle for @dev
- * @pcidevfn: return PCI device.func for @dev
- *
- * The PATA and SATA versions of this function are different.
- *
- * Returns 0 on success, <0 on error.
- */
-static int pata_get_dev_handle(struct device *dev, acpi_handle *handle,
-				acpi_integer *pcidevfn)
-{
-	unsigned int bus, devnum, func;
-	acpi_integer addr;
-	acpi_handle dev_handle, parent_handle;
-	struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER,
-					.pointer = NULL};
-	acpi_status status;
-	struct acpi_device_info	*dinfo = NULL;
-	int ret = -ENODEV;
-	struct pci_dev *pdev;
-
-	if (!is_pci_dev(dev))
-		return -ENODEV;
-
-	pdev = to_pci_dev(dev);
-
-	bus = pdev->bus->number;
-	devnum = PCI_SLOT(pdev->devfn);
-	func = PCI_FUNC(pdev->devfn);
-
-	dev_handle = DEVICE_ACPI_HANDLE(dev);
-	parent_handle = DEVICE_ACPI_HANDLE(dev->parent);
-
-	status = acpi_get_object_info(parent_handle, &buffer);
-	if (ACPI_FAILURE(status))
-		goto err;
-
-	dinfo = buffer.pointer;
-	if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
-	    dinfo->address == bus) {
-		/* ACPI spec for _ADR for PCI bus: */
-		addr = (acpi_integer)(devnum << 16 | func);
-		*pcidevfn = addr;
-		*handle = dev_handle;
-	} else {
-		goto err;
-	}
-
-	if (!*handle)
-		goto err;
-	ret = 0;
-err:
-	kfree(dinfo);
-	return ret;
-}
-
-struct walk_info {		/* can be trimmed some */
-	struct device	*dev;
-	struct acpi_device *adev;
-	acpi_handle	handle;
-	acpi_integer	pcidevfn;
-	unsigned int	drivenum;
-	acpi_handle	obj_handle;
-	struct ata_port *ataport;
-	struct ata_device *atadev;
-	u32		sata_adr;
-	int		status;
-	char		basepath[ACPI_PATHNAME_MAX];
-	int		basepath_len;
-};
-
-static acpi_status get_devices(acpi_handle handle,
-				u32 level, void *context, void **return_value)
-{
-	acpi_status		status;
-	struct walk_info	*winfo = context;
-	struct acpi_buffer	namebuf = {ACPI_ALLOCATE_BUFFER, NULL};
-	char			*pathname;
-	struct acpi_buffer	buffer;
-	struct acpi_device_info	*dinfo;
-
-	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &namebuf);
-	if (status)
-		goto ret;
-	pathname = namebuf.pointer;
-
-	buffer.length = ACPI_ALLOCATE_BUFFER;
-	buffer.pointer = NULL;
-	status = acpi_get_object_info(handle, &buffer);
-	if (ACPI_FAILURE(status))
-		goto out2;
-
-	dinfo = buffer.pointer;
-
-	/* find full device path name for pcidevfn */
-	if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
-	    dinfo->address == winfo->pcidevfn) {
-		if (ata_msg_probe(winfo->ataport))
-			ata_dev_printk(winfo->atadev, KERN_DEBUG,
-				":%s: matches pcidevfn (0x%llx)\n",
-				pathname, winfo->pcidevfn);
-		strlcpy(winfo->basepath, pathname,
-			sizeof(winfo->basepath));
-		winfo->basepath_len = strlen(pathname);
-		goto out;
-	}
-
-	/* if basepath is not yet known, ignore this object */
-	if (!winfo->basepath_len)
-		goto out;
-
-	/* if this object is in scope of basepath, maybe use it */
-	if (strncmp(pathname, winfo->basepath,
-	    winfo->basepath_len) == 0) {
-		if (!(dinfo->valid & ACPI_VALID_ADR))
-			goto out;
-		if (ata_msg_probe(winfo->ataport))
-			ata_dev_printk(winfo->atadev, KERN_DEBUG,
-				"GOT ONE: (%s) root_port = 0x%llx,"
-				" port_num = 0x%llx\n", pathname,
-				SATA_ROOT_PORT(dinfo->address),
-				SATA_PORT_NUMBER(dinfo->address));
-		/* heuristics: */
-		if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT)
-			if (ata_msg_probe(winfo->ataport))
-				ata_dev_printk(winfo->atadev,
-					KERN_DEBUG, "warning: don't"
-					" know how to handle SATA port"
-					" multiplier\n");
-		if (SATA_ROOT_PORT(dinfo->address) ==
-			winfo->ataport->port_no &&
-		    SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) {
-			if (ata_msg_probe(winfo->ataport))
-				ata_dev_printk(winfo->atadev,
-					KERN_DEBUG,
-					"THIS ^^^^^ is the requested"
-					" SATA drive (handle = 0x%p)\n",
-					handle);
-			winfo->sata_adr = dinfo->address;
-			winfo->obj_handle = handle;
-		}
-	}
-out:
-	kfree(dinfo);
-out2:
-	kfree(pathname);
-
-ret:
-	return status;
-}
-
-/* Get the SATA drive _ADR object. */
-static int get_sata_adr(struct device *dev, acpi_handle handle,
-			acpi_integer pcidevfn, unsigned int drive,
-			struct ata_port *ap,
-			struct ata_device *atadev, u32 *dev_adr)
-{
-	acpi_status	status;
-	struct walk_info *winfo;
-	int		err = -ENOMEM;
-
-	winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL);
-	if (!winfo)
-		goto out;
-
-	winfo->dev = dev;
-	winfo->atadev = atadev;
-	winfo->ataport = ap;
-	if (acpi_bus_get_device(handle, &winfo->adev) < 0)
-		if (ata_msg_probe(ap))
-			ata_dev_printk(winfo->atadev, KERN_DEBUG,
-				"acpi_bus_get_device failed\n");
-	winfo->handle = handle;
-	winfo->pcidevfn = pcidevfn;
-	winfo->drivenum = drive;
-
-	status = acpi_get_devices(NULL, get_devices, winfo, NULL);
-	if (ACPI_FAILURE(status)) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(winfo->atadev, KERN_DEBUG,
-				"%s: acpi_get_devices failed\n",
-				__FUNCTION__);
-		err = -ENODEV;
-	} else {
-		*dev_adr = winfo->sata_adr;
-		atadev->obj_handle = winfo->obj_handle;
-		err = 0;
-	}
-	kfree(winfo);
-out:
-	return err;
-}
-
-/**
- * do_drive_get_GTF - get the drive bootup default taskfile settings
+ * ata_dev_get_GTF - get the drive bootup default taskfile settings
  * @dev: target ATA device
- * @gtf_length: number of bytes of _GTF data returned at @gtf_address
- * @gtf_address: buffer containing _GTF taskfile arrays
+ * @gtf: output parameter for buffer containing _GTF taskfile arrays
+ * @ptr_to_free: pointer which should be freed
  *
  * This applies to both PATA and SATA drives.
  *
@@ -282,121 +216,41 @@
  * The <variable number> is not known in advance, so have ACPI-CA
  * allocate the buffer as needed and return it, then free it later.
  *
- * The returned @gtf_length and @gtf_address are only valid if the
- * function return value is 0.
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't
+ * contain valid data.  -errno on other errors.
  */
-static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length,
-			    unsigned long *gtf_address, unsigned long *obj_loc)
+static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
+			   void **ptr_to_free)
 {
 	struct ata_port *ap = dev->ap;
 	acpi_status status;
-	acpi_handle dev_handle = NULL;
-	acpi_handle chan_handle, drive_handle;
-	acpi_integer pcidevfn = 0;
-	u32 dev_adr;
 	struct acpi_buffer output;
 	union acpi_object *out_obj;
-	struct device *gdev = ap->host->dev;
-	int err = -ENODEV;
+	int rc = 0;
 
-	*gtf_length = 0;
-	*gtf_address = 0UL;
-	*obj_loc = 0UL;
-
-	if (libata_noacpi)
-		return 0;
+	/* set up output buffer */
+	output.length = ACPI_ALLOCATE_BUFFER;
+	output.pointer = NULL;	/* ACPI-CA sets this; save/free it later */
 
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
 			       __FUNCTION__, ap->port_no);
 
-	if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED)) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG, "%s: ERR: "
-				"ata_dev_present: %d, PORT_DISABLED: %lu\n",
-				__FUNCTION__, ata_dev_enabled(dev),
-				ap->flags & ATA_FLAG_DISABLED);
-		goto out;
-	}
-
-	/* Don't continue if device has no _ADR method.
-	 * _GTF is intended for known motherboard devices. */
-	if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
-		err = pata_get_dev_handle(gdev, &dev_handle, &pcidevfn);
-		if (err < 0) {
-			if (ata_msg_probe(ap))
-				ata_dev_printk(dev, KERN_DEBUG,
-					"%s: pata_get_dev_handle failed (%d)\n",
-					__FUNCTION__, err);
-			goto out;
-		}
-	} else {
-		err = sata_get_dev_handle(gdev, &dev_handle, &pcidevfn);
-		if (err < 0) {
-			if (ata_msg_probe(ap))
-				ata_dev_printk(dev, KERN_DEBUG,
-					"%s: sata_get_dev_handle failed (%d\n",
-					__FUNCTION__, err);
-			goto out;
-		}
-	}
-
-	/* Get this drive's _ADR info. if not already known. */
-	if (!dev->obj_handle) {
-		if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
-			/* get child objects of dev_handle == channel objects,
-	 		 * + _their_ children == drive objects */
-			/* channel is ap->port_no */
-			chan_handle = acpi_get_child(dev_handle,
-						ap->port_no);
-			if (ata_msg_probe(ap))
-				ata_dev_printk(dev, KERN_DEBUG,
-					"%s: chan adr=%d: chan_handle=0x%p\n",
-					__FUNCTION__, ap->port_no,
-					chan_handle);
-			if (!chan_handle) {
-				err = -ENODEV;
-				goto out;
-			}
-			/* TBD: could also check ACPI object VALID bits */
-			drive_handle = acpi_get_child(chan_handle, dev->devno);
-			if (!drive_handle) {
-				err = -ENODEV;
-				goto out;
-			}
-			dev_adr = dev->devno;
-			dev->obj_handle = drive_handle;
-		} else {	/* for SATA mode */
-			dev_adr = SATA_ADR_RSVD;
-			err = get_sata_adr(gdev, dev_handle, pcidevfn, 0,
-					ap, dev, &dev_adr);
-		}
-		if (err < 0 || dev_adr == SATA_ADR_RSVD ||
-		    !dev->obj_handle) {
-			if (ata_msg_probe(ap))
-				ata_dev_printk(dev, KERN_DEBUG,
-					"%s: get_sata/pata_adr failed: "
-					"err=%d, dev_adr=%u, obj_handle=0x%p\n",
-					__FUNCTION__, err, dev_adr,
-					dev->obj_handle);
-			goto out;
-		}
-	}
-
-	/* Setting up output buffer */
-	output.length = ACPI_ALLOCATE_BUFFER;
-	output.pointer = NULL;	/* ACPI-CA sets this; save/free it later */
-
 	/* _GTF has no input parameters */
-	err = -EIO;
-	status = acpi_evaluate_object(dev->obj_handle, "_GTF",
-					NULL, &output);
+	status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output);
+
 	if (ACPI_FAILURE(status)) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG,
-				"%s: Run _GTF error: status = 0x%x\n",
-				__FUNCTION__, status);
-		goto out;
+		if (status != AE_NOT_FOUND) {
+			ata_dev_printk(dev, KERN_WARNING,
+				       "_GTF evaluation failed (AE 0x%x)\n",
+				       status);
+			rc = -EIO;
+		}
+		goto out_free;
 	}
 
 	if (!output.length || !output.pointer) {
@@ -406,43 +260,39 @@
 				__FUNCTION__,
 				(unsigned long long)output.length,
 				output.pointer);
-		kfree(output.pointer);
-		goto out;
+		goto out_free;
 	}
 
 	out_obj = output.pointer;
 	if (out_obj->type != ACPI_TYPE_BUFFER) {
-		kfree(output.pointer);
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: "
-				"error: expected object type of "
-				" ACPI_TYPE_BUFFER, got 0x%x\n",
-				__FUNCTION__, out_obj->type);
-		err = -ENOENT;
-		goto out;
+		ata_dev_printk(dev, KERN_WARNING,
+			       "_GTF unexpected object type 0x%x\n",
+			       out_obj->type);
+		rc = -EINVAL;
+		goto out_free;
 	}
 
-	if (!out_obj->buffer.length || !out_obj->buffer.pointer ||
-	    out_obj->buffer.length % REGS_PER_GTF) {
-		if (ata_msg_drv(ap))
-			ata_dev_printk(dev, KERN_ERR,
-				"%s: unexpected GTF length (%d) or addr (0x%p)\n",
-				__FUNCTION__, out_obj->buffer.length,
-				out_obj->buffer.pointer);
-		err = -ENOENT;
-		goto out;
+	if (out_obj->buffer.length % REGS_PER_GTF) {
+		ata_dev_printk(dev, KERN_WARNING,
+			       "unexpected _GTF length (%d)\n",
+			       out_obj->buffer.length);
+		rc = -EINVAL;
+		goto out_free;
 	}
 
-	*gtf_length = out_obj->buffer.length;
-	*gtf_address = (unsigned long)out_obj->buffer.pointer;
-	*obj_loc = (unsigned long)out_obj;
+	*ptr_to_free = out_obj;
+	*gtf = (void *)out_obj->buffer.pointer;
+	rc = out_obj->buffer.length / REGS_PER_GTF;
+
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG, "%s: returning "
-			"gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n",
-			__FUNCTION__, *gtf_length, *gtf_address, *obj_loc);
-	err = 0;
-out:
-	return err;
+			"gtf=%p, gtf_count=%d, ptr_to_free=%p\n",
+			__FUNCTION__, *gtf, rc, *ptr_to_free);
+	return rc;
+
+ out_free:
+	kfree(output.pointer);
+	return rc;
 }
 
 /**
@@ -461,154 +311,99 @@
  * function also waits for idle after writing control and before
  * writing the remaining registers.
  *
- * LOCKING: TBD:
- * Inherited from caller.
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
  */
-static void taskfile_load_raw(struct ata_device *dev,
-			      const struct taskfile_array *gtf)
+static int taskfile_load_raw(struct ata_device *dev,
+			      const struct ata_acpi_gtf *gtf)
 {
 	struct ata_port *ap = dev->ap;
-	struct ata_taskfile tf;
-	unsigned int err;
+	struct ata_taskfile tf, rtf;
+	unsigned int err_mask;
 
-	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: "
-			"%02x %02x %02x %02x %02x %02x %02x\n",
-			__FUNCTION__,
-			gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
-			gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
-
-	if ((gtf->tfa[0] == 0) && (gtf->tfa[1] == 0) && (gtf->tfa[2] == 0)
-	    && (gtf->tfa[3] == 0) && (gtf->tfa[4] == 0) && (gtf->tfa[5] == 0)
-	    && (gtf->tfa[6] == 0))
-		return;
+	if ((gtf->tf[0] == 0) && (gtf->tf[1] == 0) && (gtf->tf[2] == 0)
+	    && (gtf->tf[3] == 0) && (gtf->tf[4] == 0) && (gtf->tf[5] == 0)
+	    && (gtf->tf[6] == 0))
+		return 0;
 
 	ata_tf_init(dev, &tf);
 
 	/* convert gtf to tf */
 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
 	tf.protocol = ATA_PROT_NODATA;
-	tf.feature = gtf->tfa[0];	/* 0x1f1 */
-	tf.nsect   = gtf->tfa[1];	/* 0x1f2 */
-	tf.lbal    = gtf->tfa[2];	/* 0x1f3 */
-	tf.lbam    = gtf->tfa[3];	/* 0x1f4 */
-	tf.lbah    = gtf->tfa[4];	/* 0x1f5 */
-	tf.device  = gtf->tfa[5];	/* 0x1f6 */
-	tf.command = gtf->tfa[6];	/* 0x1f7 */
-
-	err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
-	if (err && ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_ERR,
-			"%s: ata_exec_internal failed: %u\n",
-			__FUNCTION__, err);
-}
-
-/**
- * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
- * @dev: target ATA device
- * @gtf_length: total number of bytes of _GTF taskfiles
- * @gtf_address: location of _GTF taskfile arrays
- *
- * This applies to both PATA and SATA drives.
- *
- * Write {gtf_address, length gtf_length} in groups of
- * REGS_PER_GTF bytes.
- */
-static int do_drive_set_taskfiles(struct ata_device *dev,
-				  unsigned int gtf_length,
-				  unsigned long gtf_address)
-{
-	struct ata_port *ap = dev->ap;
-	int err = -ENODEV;
-	int gtf_count = gtf_length / REGS_PER_GTF;
-	int ix;
-	struct taskfile_array	*gtf;
+	tf.feature = gtf->tf[0];	/* 0x1f1 */
+	tf.nsect   = gtf->tf[1];	/* 0x1f2 */
+	tf.lbal    = gtf->tf[2];	/* 0x1f3 */
+	tf.lbam    = gtf->tf[3];	/* 0x1f4 */
+	tf.lbah    = gtf->tf[4];	/* 0x1f5 */
+	tf.device  = gtf->tf[5];	/* 0x1f6 */
+	tf.command = gtf->tf[6];	/* 0x1f7 */
 
 	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
-			       __FUNCTION__, ap->port_no);
+		ata_dev_printk(dev, KERN_DEBUG, "executing ACPI cmd "
+			       "%02x/%02x:%02x:%02x:%02x:%02x:%02x\n",
+			       tf.command, tf.feature, tf.nsect,
+			       tf.lbal, tf.lbam, tf.lbah, tf.device);
 
-	if (libata_noacpi || !(ap->flags & ATA_FLAG_ACPI_SATA))
-		return 0;
-
-	if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED))
-		goto out;
-	if (!gtf_count)		/* shouldn't be here */
-		goto out;
-
-	if (gtf_length % REGS_PER_GTF) {
-		if (ata_msg_drv(ap))
-			ata_dev_printk(dev, KERN_ERR,
-				"%s: unexpected GTF length (%d)\n",
-				__FUNCTION__, gtf_length);
-		goto out;
+	rtf = tf;
+	err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0);
+	if (err_mask) {
+		ata_dev_printk(dev, KERN_ERR,
+			"ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed "
+			"(Emask=0x%x Stat=0x%02x Err=0x%02x)\n",
+			tf.command, tf.feature, tf.nsect, tf.lbal, tf.lbam,
+			tf.lbah, tf.device, err_mask, rtf.command, rtf.feature);
+		return -EIO;
 	}
 
-	for (ix = 0; ix < gtf_count; ix++) {
-		gtf = (struct taskfile_array *)
-			(gtf_address + ix * REGS_PER_GTF);
-
-		/* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
-		taskfile_load_raw(dev, gtf);
-	}
-
-	err = 0;
-out:
-	return err;
+	return 0;
 }
 
 /**
  * ata_acpi_exec_tfs - get then write drive taskfile settings
- * @ap: the ata_port for the drive
+ * @dev: target ATA device
  *
- * This applies to both PATA and SATA drives.
+ * Evaluate _GTF and excute returned taskfiles.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Number of executed taskfiles on success, 0 if _GTF doesn't exist or
+ * doesn't contain valid data.  -errno on other errors.
  */
-int ata_acpi_exec_tfs(struct ata_port *ap)
+static int ata_acpi_exec_tfs(struct ata_device *dev)
 {
-	int ix;
-	int ret = 0;
-	unsigned int gtf_length;
-	unsigned long gtf_address;
-	unsigned long obj_loc;
+	struct ata_acpi_gtf *gtf = NULL;
+	void *ptr_to_free = NULL;
+	int gtf_count, i, rc;
 
-	if (libata_noacpi)
-		return 0;
-	/*
-	 * TBD - implement PATA support.  For now,
-	 * we should not run GTF on PATA devices since some
-	 * PATA require execution of GTM/STM before GTF.
-	 */
-	if (!(ap->flags & ATA_FLAG_ACPI_SATA))
-		return 0;
+	/* get taskfiles */
+	rc = ata_dev_get_GTF(dev, &gtf, &ptr_to_free);
+	if (rc < 0)
+		return rc;
+	gtf_count = rc;
 
-	for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
-		struct ata_device *dev = &ap->device[ix];
+	/* execute them */
+	for (i = 0, rc = 0; i < gtf_count; i++) {
+		int tmp;
 
-		if (!ata_dev_enabled(dev))
-			continue;
-
-		ret = do_drive_get_GTF(dev, &gtf_length, &gtf_address,
-				       &obj_loc);
-		if (ret < 0) {
-			if (ata_msg_probe(ap))
-				ata_port_printk(ap, KERN_DEBUG,
-					"%s: get_GTF error (%d)\n",
-					__FUNCTION__, ret);
-			break;
-		}
-
-		ret = do_drive_set_taskfiles(dev, gtf_length, gtf_address);
-		kfree((void *)obj_loc);
-		if (ret < 0) {
-			if (ata_msg_probe(ap))
-				ata_port_printk(ap, KERN_DEBUG,
-					"%s: set_taskfiles error (%d)\n",
-					__FUNCTION__, ret);
-			break;
-		}
+		/* ACPI errors are eventually ignored.  Run till the
+		 * end even after errors.
+		 */
+		tmp = taskfile_load_raw(dev, gtf++);
+		if (!rc)
+			rc = tmp;
 	}
 
-	return ret;
+	kfree(ptr_to_free);
+
+	if (rc == 0)
+		return gtf_count;
+	return rc;
 }
 
 /**
@@ -620,62 +415,25 @@
  * ATM this function never returns a failure.  It is an optional
  * method and if it fails for whatever reason, we should still
  * just keep going.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
  */
-int ata_acpi_push_id(struct ata_device *dev)
+static int ata_acpi_push_id(struct ata_device *dev)
 {
 	struct ata_port *ap = dev->ap;
-	acpi_handle handle;
-	acpi_integer pcidevfn;
 	int err;
-	struct device *gdev = ap->host->dev;
-	u32 dev_adr;
 	acpi_status status;
 	struct acpi_object_list input;
 	union acpi_object in_params[1];
 
-	if (libata_noacpi)
-		return 0;
-
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n",
 			       __FUNCTION__, dev->devno, ap->port_no);
 
-	/* Don't continue if not a SATA device. */
-	if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG,
-				"%s: Not a SATA device\n", __FUNCTION__);
-		goto out;
-	}
-
-	/* Don't continue if device has no _ADR method.
-	 * _SDD is intended for known motherboard devices. */
-	err = sata_get_dev_handle(gdev, &handle, &pcidevfn);
-	if (err < 0) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG,
-				"%s: sata_get_dev_handle failed (%d\n",
-				__FUNCTION__, err);
-		goto out;
-	}
-
-	/* Get this drive's _ADR info, if not already known */
-	if (!dev->obj_handle) {
-		dev_adr = SATA_ADR_RSVD;
-		err = get_sata_adr(gdev, handle, pcidevfn, dev->devno, ap, dev,
-					&dev_adr);
-		if (err < 0 || dev_adr == SATA_ADR_RSVD ||
-			!dev->obj_handle) {
-			if (ata_msg_probe(ap))
-				ata_dev_printk(dev, KERN_DEBUG,
-					"%s: get_sata_adr failed: "
-					"err=%d, dev_adr=%u, obj_handle=0x%p\n",
-					__FUNCTION__, err, dev_adr,
-					dev->obj_handle);
-			goto out;
-		}
-	}
-
 	/* Give the drive Identify data to the drive via the _SDD method */
 	/* _SDD: set up input parameters */
 	input.count = 1;
@@ -687,20 +445,150 @@
 
 	/* It's OK for _SDD to be missing too. */
 	swap_buf_le16(dev->id, ATA_ID_WORDS);
-	status = acpi_evaluate_object(dev->obj_handle, "_SDD", &input, NULL);
+	status = acpi_evaluate_object(dev->acpi_handle, "_SDD", &input, NULL);
 	swap_buf_le16(dev->id, ATA_ID_WORDS);
 
 	err = ACPI_FAILURE(status) ? -EIO : 0;
-	if (err < 0) {
-		if (ata_msg_probe(ap))
-			ata_dev_printk(dev, KERN_DEBUG,
-				       "%s _SDD error: status = 0x%x\n",
-				       __FUNCTION__, status);
-	}
+	if (err < 0)
+		ata_dev_printk(dev, KERN_WARNING,
+			       "ACPI _SDD failed (AE 0x%x)\n", status);
 
-	/* always return success */
-out:
-	return 0;
+	return err;
 }
 
+/**
+ * ata_acpi_on_suspend - ATA ACPI hook called on suspend
+ * @ap: target ATA port
+ *
+ * This function is called when @ap is about to be suspended.  All
+ * devices are already put to sleep but the port_suspend() callback
+ * hasn't been executed yet.  Error return from this function aborts
+ * suspend.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int ata_acpi_on_suspend(struct ata_port *ap)
+{
+	unsigned long flags;
+	int rc;
 
+	/* proceed iff per-port acpi_handle is valid */
+	if (!ap->acpi_handle)
+		return 0;
+	BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA);
+
+	/* store timing parameters */
+	rc = ata_acpi_gtm(ap, &ap->acpi_gtm);
+
+	spin_lock_irqsave(ap->lock, flags);
+	if (rc == 0)
+		ap->pflags |= ATA_PFLAG_GTM_VALID;
+	else
+		ap->pflags &= ~ATA_PFLAG_GTM_VALID;
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	if (rc == -ENOENT)
+		rc = 0;
+	return rc;
+}
+
+/**
+ * ata_acpi_on_resume - ATA ACPI hook called on resume
+ * @ap: target ATA port
+ *
+ * This function is called when @ap is resumed - right after port
+ * itself is resumed but before any EH action is taken.
+ *
+ * LOCKING:
+ * EH context.
+ */
+void ata_acpi_on_resume(struct ata_port *ap)
+{
+	int i;
+
+	if (ap->acpi_handle && (ap->pflags & ATA_PFLAG_GTM_VALID)) {
+		BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA);
+
+		/* restore timing parameters */
+		ata_acpi_stm(ap, &ap->acpi_gtm);
+	}
+
+	/* schedule _GTF */
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		ap->device[i].flags |= ATA_DFLAG_ACPI_PENDING;
+}
+
+/**
+ * ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration
+ * @dev: target ATA device
+ *
+ * This function is called when @dev is about to be configured.
+ * IDENTIFY data might have been modified after this hook is run.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Positive number if IDENTIFY data needs to be refreshed, 0 if not,
+ * -errno on failure.
+ */
+int ata_acpi_on_devcfg(struct ata_device *dev)
+{
+	struct ata_port *ap = dev->ap;
+	struct ata_eh_context *ehc = &ap->eh_context;
+	int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA;
+	int rc;
+
+	if (!dev->acpi_handle)
+		return 0;
+
+	/* do we need to do _GTF? */
+	if (!(dev->flags & ATA_DFLAG_ACPI_PENDING) &&
+	    !(acpi_sata && (ehc->i.flags & ATA_EHI_DID_HARDRESET)))
+		return 0;
+
+	/* do _SDD if SATA */
+	if (acpi_sata) {
+		rc = ata_acpi_push_id(dev);
+		if (rc)
+			goto acpi_err;
+	}
+
+	/* do _GTF */
+	rc = ata_acpi_exec_tfs(dev);
+	if (rc < 0)
+		goto acpi_err;
+
+	dev->flags &= ~ATA_DFLAG_ACPI_PENDING;
+
+	/* refresh IDENTIFY page if any _GTF command has been executed */
+	if (rc > 0) {
+		rc = ata_dev_reread_id(dev, 0);
+		if (rc < 0) {
+			ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY "
+				       "after ACPI commands\n");
+			return rc;
+		}
+	}
+
+	return 0;
+
+ acpi_err:
+	/* let EH retry on the first failure, disable ACPI on the second */
+	if (dev->flags & ATA_DFLAG_ACPI_FAILED) {
+		ata_dev_printk(dev, KERN_WARNING, "ACPI on devcfg failed the "
+			       "second time, disabling (errno=%d)\n", rc);
+
+		dev->acpi_handle = NULL;
+
+		/* if port is working, request IDENTIFY reload and continue */
+		if (!(ap->pflags & ATA_PFLAG_FROZEN))
+			rc = 1;
+	}
+	dev->flags |= ATA_DFLAG_ACPI_FAILED;
+	return rc;
+}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 981b397..5b25311 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1845,7 +1845,8 @@
 int ata_dev_configure(struct ata_device *dev)
 {
 	struct ata_port *ap = dev->ap;
-	int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO;
+	struct ata_eh_context *ehc = &ap->eh_context;
+	int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
 	const u16 *id = dev->id;
 	unsigned int xfer_mask;
 	char revbuf[7];		/* XYZ-99\0 */
@@ -1862,15 +1863,10 @@
 	if (ata_msg_probe(ap))
 		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
 
-	/* set _SDD */
-	rc = ata_acpi_push_id(dev);
-	if (rc) {
-		ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n",
-			rc);
-	}
-
-	/* retrieve and execute the ATA task file of _GTF */
-	ata_acpi_exec_tfs(ap);
+	/* let ACPI work its magic */
+	rc = ata_acpi_on_devcfg(dev);
+	if (rc)
+		return rc;
 
 	/* print device capabilities */
 	if (ata_msg_probe(ap))
@@ -3359,7 +3355,7 @@
 		return 0;
 
 	/* if SATA, resume phy */
-	if (ap->cbl == ATA_CBL_SATA) {
+	if (ap->flags & ATA_FLAG_SATA) {
 		rc = sata_phy_resume(ap, timing, deadline);
 		/* whine about phy resume failure but proceed */
 		if (rc && rc != -EOPNOTSUPP)
@@ -4107,6 +4103,68 @@
 }
 
 /**
+ *	ata_fill_sg_dumb - Fill PCI IDE PRD table
+ *	@qc: Metadata associated with taskfile to be transferred
+ *
+ *	Fill PCI IDE PRD (scatter-gather) table with segments
+ *	associated with the current disk command. Perform the fill
+ *	so that we avoid writing any length 64K records for
+ *	controllers that don't follow the spec.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host lock)
+ *
+ */
+static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct scatterlist *sg;
+	unsigned int idx;
+
+	WARN_ON(qc->__sg == NULL);
+	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+
+	idx = 0;
+	ata_for_each_sg(sg, qc) {
+		u32 addr, offset;
+		u32 sg_len, len, blen;
+
+ 		/* determine if physical DMA addr spans 64K boundary.
+		 * Note h/w doesn't support 64-bit, so we unconditionally
+		 * truncate dma_addr_t to u32.
+		 */
+		addr = (u32) sg_dma_address(sg);
+		sg_len = sg_dma_len(sg);
+
+		while (sg_len) {
+			offset = addr & 0xffff;
+			len = sg_len;
+			if ((offset + sg_len) > 0x10000)
+				len = 0x10000 - offset;
+
+			blen = len & 0xffff;
+			ap->prd[idx].addr = cpu_to_le32(addr);
+			if (blen == 0) {
+			   /* Some PATA chipsets like the CS5530 can't
+			      cope with 0x0000 meaning 64K as the spec says */
+				ap->prd[idx].flags_len = cpu_to_le32(0x8000);
+				blen = 0x8000;
+				ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000);
+			}
+			ap->prd[idx].flags_len = cpu_to_le32(blen);
+			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
+
+			idx++;
+			sg_len -= len;
+			addr += len;
+		}
+	}
+
+	if (idx)
+		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+}
+
+/**
  *	ata_check_atapi_dma - Check whether ATAPI DMA can be supported
  *	@qc: Metadata associated with taskfile to check
  *
@@ -4153,6 +4211,23 @@
 	ata_fill_sg(qc);
 }
 
+/**
+ *	ata_dumb_qc_prep - Prepare taskfile for submission
+ *	@qc: Metadata associated with taskfile to be prepared
+ *
+ *	Prepare ATA taskfile for submission.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host lock)
+ */
+void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
+{
+	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+		return;
+
+	ata_fill_sg_dumb(qc);
+}
+
 void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
 
 /**
@@ -5660,7 +5735,7 @@
  */
 int sata_scr_valid(struct ata_port *ap)
 {
-	return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read;
+	return (ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read;
 }
 
 /**
@@ -6293,6 +6368,9 @@
 	if (rc)
 		return rc;
 
+	/* associate with ACPI nodes */
+	ata_acpi_associate(host);
+
 	/* set cable, sata_spd_limit and report */
 	for (i = 0; i < host->n_ports; i++) {
 		struct ata_port *ap = host->ports[i];
@@ -6324,7 +6402,7 @@
 		if (!ata_port_is_dummy(ap))
 			ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%p "
 					"ctl 0x%p bmdma 0x%p irq %d\n",
-					ap->cbl == ATA_CBL_SATA ? 'S' : 'P',
+					(ap->flags & ATA_FLAG_SATA) ? 'S' : 'P',
 					ata_mode_string(xfer_mask),
 					ap->ioaddr.cmd_addr,
 					ap->ioaddr.ctl_addr,
@@ -6822,6 +6900,7 @@
 EXPORT_SYMBOL_GPL(ata_data_xfer);
 EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
 EXPORT_SYMBOL_GPL(ata_qc_prep);
+EXPORT_SYMBOL_GPL(ata_dumb_qc_prep);
 EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
 EXPORT_SYMBOL_GPL(ata_bmdma_setup);
 EXPORT_SYMBOL_GPL(ata_bmdma_start);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index f7582c9..9ee0a8c 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2154,19 +2154,25 @@
 
 	WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
 
+	/* tell ACPI we're suspending */
+	rc = ata_acpi_on_suspend(ap);
+	if (rc)
+		goto out;
+
 	/* suspend */
 	ata_eh_freeze_port(ap);
 
 	if (ap->ops->port_suspend)
 		rc = ap->ops->port_suspend(ap, ap->pm_mesg);
 
+ out:
 	/* report result */
 	spin_lock_irqsave(ap->lock, flags);
 
 	ap->pflags &= ~ATA_PFLAG_PM_PENDING;
 	if (rc == 0)
 		ap->pflags |= ATA_PFLAG_SUSPENDED;
-	else
+	else if (ap->pflags & ATA_PFLAG_FROZEN)
 		ata_port_schedule_eh(ap);
 
 	if (ap->pm_result) {
@@ -2207,6 +2213,9 @@
 	if (ap->ops->port_resume)
 		rc = ap->ops->port_resume(ap);
 
+	/* tell ACPI that we're resuming */
+	ata_acpi_on_resume(ap);
+
 	/* report result */
 	spin_lock_irqsave(ap->lock, flags);
 	ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 4ddf00c..cfde22d 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2620,7 +2620,7 @@
 			ata_dev_printk(dev, KERN_WARNING,
 				       "invalid multi_count %u ignored\n",
 				       multi_count);
-	}	
+	}
 
 	/* READ/WRITE LONG use a non-standard sect_size */
 	qc->sect_size = ATA_SECT_SIZE;
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 5e24666..ba17fc5 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -98,17 +98,15 @@
 
 /* libata-acpi.c */
 #ifdef CONFIG_ATA_ACPI
-extern int ata_acpi_exec_tfs(struct ata_port *ap);
-extern int ata_acpi_push_id(struct ata_device *dev);
+extern void ata_acpi_associate(struct ata_host *host);
+extern int ata_acpi_on_suspend(struct ata_port *ap);
+extern void ata_acpi_on_resume(struct ata_port *ap);
+extern int ata_acpi_on_devcfg(struct ata_device *adev);
 #else
-static inline int ata_acpi_exec_tfs(struct ata_port *ap)
-{
-	return 0;
-}
-static inline int ata_acpi_push_id(struct ata_device *dev)
-{
-	return 0;
-}
+static inline void ata_acpi_associate(struct ata_host *host) { }
+static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
+static inline void ata_acpi_on_resume(struct ata_port *ap) { }
+static inline int ata_acpi_on_devcfg(struct ata_device *adev) { return 0; }
 #endif
 
 /* libata-scsi.c */
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index 75e95bd..30c4276 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -520,14 +520,14 @@
 {
 	static const struct ata_port_info info_early = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &ali_early_port_ops
 	};
 	/* Revision 0x20 added DMA */
 	static const struct ata_port_info info_20 = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &ali_20_port_ops
@@ -535,7 +535,7 @@
 	/* Revision 0x20 with support logic added UDMA */
 	static const struct ata_port_info info_20_udma = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x07,	/* UDMA33 */
@@ -544,37 +544,37 @@
 	/* Revision 0xC2 adds UDMA66 */
 	static const struct ata_port_info info_c2 = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x1f,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &ali_c2_port_ops
 	};
 	/* Revision 0xC3 is UDMA66 for now */
 	static const struct ata_port_info info_c3 = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x1f,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &ali_c2_port_ops
 	};
 	/* Revision 0xC4 is UDMA100 */
 	static const struct ata_port_info info_c4 = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &ali_c2_port_ops
 	};
 	/* Revision 0xC5 is UDMA133 with LBA48 DMA */
 	static const struct ata_port_info info_c5 = {
 		.sht = &ali_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA6,
 		.port_ops = &ali_c5_port_ops
 	};
 
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index a16f629..b9c44c5 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -541,7 +541,7 @@
 	static const struct ata_port_info info[10] = {
 		{	/* 0: AMD 7401 */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,	/* No SWDMA */
 			.udma_mask = 0x07,	/* UDMA 33 */
@@ -549,74 +549,74 @@
 		},
 		{	/* 1: Early AMD7409 - no swdma */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x1f,	/* UDMA 66 */
+			.udma_mask = ATA_UDMA4,	/* UDMA 66 */
 			.port_ops = &amd66_port_ops
 		},
 		{	/* 2: AMD 7409, no swdma errata */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x1f,	/* UDMA 66 */
+			.udma_mask = ATA_UDMA4,	/* UDMA 66 */
 			.port_ops = &amd66_port_ops
 		},
 		{	/* 3: AMD 7411 */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,	/* UDMA 100 */
+			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
 			.port_ops = &amd100_port_ops
 		},
 		{	/* 4: AMD 7441 */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,	/* UDMA 100 */
+			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
 			.port_ops = &amd100_port_ops
 		},
 		{	/* 5: AMD 8111*/
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x7f,	/* UDMA 133, no swdma */
+			.udma_mask = ATA_UDMA6,	/* UDMA 133, no swdma */
 			.port_ops = &amd133_port_ops
 		},
 		{	/* 6: AMD 8111 UDMA 100 (Serenade) */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,	/* UDMA 100, no swdma */
+			.udma_mask = ATA_UDMA5,	/* UDMA 100, no swdma */
 			.port_ops = &amd133_port_ops
 		},
 		{	/* 7: Nvidia Nforce */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,	/* UDMA 100 */
+			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
 			.port_ops = &nv100_port_ops
 		},
 		{	/* 8: Nvidia Nforce2 and later */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x7f,	/* UDMA 133, no swdma */
+			.udma_mask = ATA_UDMA6,	/* UDMA 133, no swdma */
 			.port_ops = &nv133_port_ops
 		},
 		{	/* 9: AMD CS5536 (Geode companion) */
 			.sht = &amd_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,	/* UDMA 100 */
+			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
 			.port_ops = &amd100_port_ops
 		}
 	};
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 03b6ddd..ce589d9 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -416,7 +416,7 @@
 	static int printed_version;
 	static const struct ata_port_info info_6210 = {
 		.sht		= &artop_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask 	= ATA_UDMA2,
@@ -424,7 +424,7 @@
 	};
 	static const struct ata_port_info info_626x = {
 		.sht		= &artop_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask 	= ATA_UDMA4,
@@ -432,7 +432,7 @@
 	};
 	static const struct ata_port_info info_626x_fast = {
 		.sht		= &artop_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask 	= ATA_UDMA5,
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 8449146..80509be 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -270,7 +270,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &atiixp_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x06,	/* No MWDMA0 support */
 		.udma_mask = 0x3F,
@@ -285,6 +285,7 @@
 	{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), },
 	{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), },
 	{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), },
+	{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), },
 
 	{ },
 };
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index 31cbf8d..0feb5ae 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -251,7 +251,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &cmd640_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &cmd640_port_ops
 	};
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 320a5b1..dc443e7 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -380,21 +380,21 @@
 	static const struct ata_port_info cmd_info[6] = {
 		{	/* CMD 643 - no UDMA */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.port_ops = &cmd64x_port_ops
 		},
 		{	/* CMD 646 with broken UDMA */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.port_ops = &cmd64x_port_ops
 		},
 		{	/* CMD 646 with working UDMA */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA1,
@@ -402,14 +402,14 @@
 		},
 		{	/* CMD 646 rev 1  */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.port_ops = &cmd646r1_port_ops
 		},
 		{	/* CMD 648 */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA2,
@@ -417,7 +417,7 @@
 		},
 		{	/* CMD 649 */
 			.sht = &cmd64x_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA3,
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 00cf013..6bf037d 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -146,7 +146,7 @@
 	.queuecommand		= ata_scsi_queuecmd,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
-	.sg_tablesize		= LIBATA_MAX_PRD,
+	.sg_tablesize		= LIBATA_DUMB_MAX_PRD,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
 	.emulated		= ATA_SHT_EMULATED,
 	.use_clustering		= ATA_SHT_USE_CLUSTERING,
@@ -178,7 +178,7 @@
 	.bmdma_start		= ata_bmdma_start,
 	.bmdma_stop		= ata_bmdma_stop,
 	.bmdma_status		= ata_bmdma_status,
-	.qc_prep		= ata_qc_prep,
+	.qc_prep		= ata_dumb_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.data_xfer		= ata_data_xfer,
 
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index 848f030..3fca589 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -167,7 +167,7 @@
 	.queuecommand		= ata_scsi_queuecmd,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
-	.sg_tablesize		= LIBATA_MAX_PRD,
+	.sg_tablesize		= LIBATA_DUMB_MAX_PRD,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
 	.emulated		= ATA_SHT_EMULATED,
 	.use_clustering		= ATA_SHT_USE_CLUSTERING,
@@ -201,7 +201,7 @@
 	.post_internal_cmd = ata_bmdma_post_internal_cmd,
 	.cable_detect	= ata_cable_40wire,
 
-	.qc_prep 	= ata_qc_prep,
+	.qc_prep 	= ata_dumb_qc_prep,
 	.qc_issue	= cs5530_qc_issue_prot,
 
 	.data_xfer	= ata_data_xfer,
@@ -337,7 +337,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &cs5530_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x07,
@@ -346,7 +346,7 @@
 	/* The docking connector doesn't do UDMA, and it seems not MWDMA */
 	static const struct ata_port_info info_palmax_secondary = {
 		.sht = &cs5530_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &cs5530_port_ops
 	};
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index aa3256f..360b6f3 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -225,10 +225,10 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &cs5535_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x1f,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &cs5535_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index d41a769..6cbc877 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -167,7 +167,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &cy82c693_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &cy82c693_port_ops
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index 079248a..c8ba59c 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -303,7 +303,7 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht		= &efar_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma1-2 */
 		.udma_mask 	= 0x0f, /* UDMA 66 */
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 0c9cb60..6f7d34a 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -393,10 +393,10 @@
 {
 	static const struct ata_port_info info_hpt366 = {
 		.sht = &hpt36x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x1f,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &hpt366_port_ops
 	};
 	struct ata_port_info info = info_hpt366;
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index a8c0cbe..b0af65a 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -889,25 +889,25 @@
 	/* HPT370 - UDMA100 */
 	static const struct ata_port_info info_hpt370 = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt370_port_ops
 	};
 	/* HPT370A - UDMA100 */
 	static const struct ata_port_info info_hpt370a = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt370a_port_ops
 	};
 	/* HPT370 - UDMA100 */
 	static const struct ata_port_info info_hpt370_33 = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x0f,
@@ -916,7 +916,7 @@
 	/* HPT370A - UDMA100 */
 	static const struct ata_port_info info_hpt370a_33 = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x0f,
@@ -925,19 +925,19 @@
 	/* HPT371, 372 and friends - UDMA133 */
 	static const struct ata_port_info info_hpt372 = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA6,
 		.port_ops = &hpt372_port_ops
 	};
 	/* HPT374 - UDMA100 */
 	static const struct ata_port_info info_hpt374 = {
 		.sht = &hpt37x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &hpt374_port_ops
 	};
 
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index e947433..aa29cde 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -490,10 +490,10 @@
 	/* HPT372N and friends - UDMA133 */
 	static const struct ata_port_info info = {
 		.sht = &hpt3x2n_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA6,
 		.port_ops = &hpt3x2n_port_ops
 	};
 	struct ata_port_info port = info;
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index 8ce5e23..d928c91 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -173,7 +173,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &hpt3x3_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x07,
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index c791a46..321d98b 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -530,7 +530,7 @@
 
 		ap->pio_mask = 0x1f;
 		ap->mwdma_mask = info->mwdma_mask;
-		ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
+		ap->flags |= ATA_FLAG_SLAVE_POSS;
 		ap->ops = &pata_icside_port_ops;
 
 		pata_icside_setup_ioaddr(&ap->ioaddr, info->base, info->port[i]);
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index 95b0bb6..b8af55e 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -313,10 +313,10 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht		= &it8213_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask 	= 0x1f, /* UDMA 100 */
+		.udma_mask 	= ATA_UDMA4, /* FIXME: want UDMA 100? */
 		.port_ops	= &it8213_ops,
 	};
 	/* Current IT8213 stuff is single port */
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index 12c6e08..b67bbf6 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -714,17 +714,17 @@
 
 	static const struct ata_port_info info_smart = {
 		.sht = &it821x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &it821x_smart_port_ops
 	};
 	static const struct ata_port_info info_passthru = {
 		.sht = &it821x_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA6,
 		.port_ops = &it821x_passthru_port_ops
 	};
 
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index 8d2bc1e..4ca7fd6 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -1,13 +1,14 @@
 /*
  * ixp4xx PATA/Compact Flash driver
- * Copyright (c) 2006 Tower Technologies
+ * Copyright (C) 2006-07 Tower Technologies
  * Author: Alessandro Zummo <a.zummo@towertech.it>
  *
  * An ATA driver to handle a Compact Flash connected
  * to the ixp4xx expansion bus in TrueIDE mode. The CF
  * must have it chip selects connected to two CS lines
- * on the ixp4xx. The interrupt line is optional, if not
- * specified the driver will run in polling mode.
+ * on the ixp4xx. In the irq is not available, you might
+ * want to modify both this driver and libata to run in
+ * polling mode.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -23,7 +24,7 @@
 #include <scsi/scsi_host.h>
 
 #define DRV_NAME	"pata_ixp4xx_cf"
-#define DRV_VERSION	"0.1.3"
+#define DRV_VERSION	"0.2"
 
 static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error)
 {
@@ -42,13 +43,6 @@
 	return 0;
 }
 
-static void ixp4xx_phy_reset(struct ata_port *ap)
-{
-	ap->cbl = ATA_CBL_PATA40;
-	ata_port_probe(ap);
-	ata_bus_reset(ap);
-}
-
 static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
 				unsigned int buflen, int write_data)
 {
@@ -56,7 +50,7 @@
 	unsigned int words = buflen >> 1;
 	u16 *buf16 = (u16 *) buf;
 	struct ata_port *ap = adev->ap;
-	void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
+	void __iomem *mmio = ap->ioaddr.data_addr;
 	struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
 
 	/* set the expansion bus in 16bit mode and restore
@@ -92,10 +86,6 @@
 	*data->cs0_cfg |= 0x01;
 }
 
-static void ixp4xx_irq_clear(struct ata_port *ap)
-{
-}
-
 static struct scsi_host_template ixp4xx_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
@@ -115,29 +105,32 @@
 };
 
 static struct ata_port_operations ixp4xx_port_ops = {
-	.set_mode	= ixp4xx_set_mode,
-	.mode_filter	= ata_pci_default_filter,
+	.set_mode		= ixp4xx_set_mode,
+	.mode_filter		= ata_pci_default_filter,
 
-	.port_disable	= ata_port_disable,
-	.tf_load	= ata_tf_load,
-	.tf_read	= ata_tf_read,
-	.check_status 	= ata_check_status,
-	.exec_command	= ata_exec_command,
-	.dev_select 	= ata_std_dev_select,
+	.port_disable		= ata_port_disable,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.exec_command		= ata_exec_command,
+	.check_status 		= ata_check_status,
+	.dev_select 		= ata_std_dev_select,
 
-	.qc_prep 	= ata_qc_prep,
-	.qc_issue	= ata_qc_issue_prot,
-	.eng_timeout	= ata_eng_timeout,
-	.data_xfer	= ixp4xx_mmio_data_xfer,
-	.cable_detect	= ata_cable_40wire,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= ata_bmdma_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 
-	.irq_clear	= ixp4xx_irq_clear,
-	.irq_on		= ata_irq_on,
-	.irq_ack	= ata_irq_ack,
+	.qc_prep 		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ixp4xx_mmio_data_xfer,
+	.cable_detect		= ata_cable_40wire,
 
-	.port_start	= ata_port_start,
+	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+	.irq_on			= ata_irq_on,
+	.irq_ack		= ata_dummy_irq_ack,
 
-	.phy_reset	= ixp4xx_phy_reset,
+	.port_start		= ata_port_start,
 };
 
 static void ixp4xx_setup_port(struct ata_ioports *ioaddr,
@@ -178,7 +171,6 @@
 	struct ata_host *host;
 	struct ata_port *ap;
 	struct ixp4xx_pata_data *data = pdev->dev.platform_data;
-	int rc;
 
 	cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -211,10 +203,6 @@
 	ap->pio_mask = 0x1f; /* PIO4 */
 	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI;
 
-	/* run in polling mode if no irq has been assigned */
-	if (!irq)
-		ap->flags |= ATA_FLAG_PIO_POLLING;
-
 	ixp4xx_setup_port(&ap->ioaddr, data);
 
 	dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 2af7ff8..4d67f23 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -193,11 +193,11 @@
 {
 	static const struct ata_port_info info = {
 		.sht		= &jmicron_sht,
-		.flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags	= ATA_FLAG_SLAVE_POSS,
 
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask 	= 0x3f,
+		.udma_mask 	= ATA_UDMA5,
 
 		.port_ops	= &jmicron_ops,
 	};
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index edbfe0d..87594c0 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -163,22 +163,22 @@
 {
 	static const struct ata_port_info info = {
 		.sht		= &marvell_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask 	= 0x3f,
+		.udma_mask 	= ATA_UDMA5,
 
 		.port_ops	= &marvell_ops,
 	};
 	static const struct ata_port_info info_sata = {
 		.sht		= &marvell_sht,
 		/* Slave possible as its magically mapped not real */
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask 	= 0x7f,
+		.udma_mask 	= ATA_UDMA6,
 
 		.port_ops	= &marvell_ops,
 	};
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index 81f5634..40eb574 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -94,12 +94,12 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht		= &netcell_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		/* Actually we don't really care about these as the
 		   firmware deals with it */
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask 	= 0x3f, /* UDMA 133 */
+		.udma_mask 	= ATA_UDMA5, /* UDMA 133 */
 		.port_ops	= &netcell_ops,
 	};
 	const struct ata_port_info *port_info[] = { &info, NULL };
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index ea70ec7..2f5d714 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -193,7 +193,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &ns87410_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x0F,
 		.port_ops = &ns87410_port_ops
 	};
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index 29c23dd..091a70a 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -291,7 +291,7 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht		= &oldpiix_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma1-2 */
 		.port_ops	= &oldpiix_pata_ops,
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index 1c44653..458bf67 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -218,7 +218,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &opti_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &opti_port_ops
 	};
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 3093b02..f89bdfd 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -484,14 +484,14 @@
 {
 	static const struct ata_port_info info_82c700 = {
 		.sht = &optidma_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &optidma_port_ops
 	};
 	static const struct ata_port_info info_82c700_udma = {
 		.sht = &optidma_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x07,
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index d277246..92447bed 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -320,7 +320,7 @@
 	static const struct ata_port_info info[3] = {
 		{
 			.sht = &pdc202xx_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA2,
@@ -328,7 +328,7 @@
 		},
 		{
 			.sht = &pdc202xx_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA4,
@@ -336,7 +336,7 @@
 		},
 		{
 			.sht = &pdc202xx_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA5,
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index cbb7866..79f841b 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -139,6 +139,7 @@
 	struct resource *io_res, *ctl_res;
 	struct ata_host *host;
 	struct ata_port *ap;
+	struct pata_platform_info *pp_info;
 	unsigned int mmio;
 
 	/*
@@ -208,11 +209,12 @@
 
 	ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
 
-	pata_platform_setup_port(&ap->ioaddr, pdev->dev.platform_data);
+	pp_info = (struct pata_platform_info *)(pdev->dev.platform_data);
+	pata_platform_setup_port(&ap->ioaddr, pp_info);
 
 	/* activate */
 	return ata_host_activate(host, platform_get_irq(pdev, 0), ata_interrupt,
-				 0, &pata_platform_sht);
+				 pp_info->irq_flags, &pata_platform_sht);
 }
 
 /**
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index ba96b54..7d1aabe 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -257,7 +257,7 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht		= &radisys_sht,
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma1-2 */
 		.udma_mask	= 0x14, /* UDMA33/66 only */
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index a3488b4..7632fcb 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -133,7 +133,7 @@
 	static int printed_version;
 	static const struct ata_port_info info = {
 		.sht = &rz1000_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &rz1000_port_ops
 	};
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 1233063..b8b2d11 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -185,7 +185,7 @@
 	.queuecommand		= ata_scsi_queuecmd,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
-	.sg_tablesize		= LIBATA_MAX_PRD,
+	.sg_tablesize		= LIBATA_DUMB_MAX_PRD,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
 	.emulated		= ATA_SHT_EMULATED,
 	.use_clustering		= ATA_SHT_USE_CLUSTERING,
@@ -219,7 +219,7 @@
 	.bmdma_stop	= ata_bmdma_stop,
 	.bmdma_status 	= ata_bmdma_status,
 
-	.qc_prep 	= ata_qc_prep,
+	.qc_prep 	= ata_dumb_qc_prep,
 	.qc_issue	= sc1200_qc_issue_prot,
 
 	.data_xfer	= ata_data_xfer,
@@ -245,7 +245,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &sc1200_sht,
-		.flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.udma_mask = 0x07,
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index 1e8f421..0231aba 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -478,31 +478,31 @@
 	static const struct ata_port_info info[4] = {
 		{ /* OSB4 */
 			.sht = &serverworks_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = 0x07,
 			.port_ops = &serverworks_osb4_port_ops
 		}, { /* OSB4 no UDMA */
 			.sht = &serverworks_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = 0x00,
 			.port_ops = &serverworks_osb4_port_ops
 		}, { /* CSB5 */
 			.sht = &serverworks_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x1f,
+			.udma_mask = ATA_UDMA4,
 			.port_ops = &serverworks_csb_port_ops
 		}, { /* CSB5 - later revisions*/
 			.sht = &serverworks_sht,
-			.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+			.flags = ATA_FLAG_SLAVE_POSS,
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
-			.udma_mask = 0x3f,
+			.udma_mask = ATA_UDMA5,
 			.port_ops = &serverworks_csb_port_ops
 		}
 	};
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 440e2cb..b0cd52d 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -35,6 +35,8 @@
 #define DRV_NAME "pata_sil680"
 #define DRV_VERSION "0.4.6"
 
+#define SIL680_MMIO_BAR		5
+
 /**
  *	sil680_selreg		-	return register base
  *	@hwif: interface
@@ -293,8 +295,8 @@
 
 	pci_read_config_byte(pdev, 0x8A, &tmpbyte);
 
-	printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
-			tmpbyte & 1, tmpbyte & 0x30);
+	dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n",
+		tmpbyte & 1, tmpbyte & 0x30);
 
 	switch(tmpbyte & 0x30) {
 		case 0x00:
@@ -315,8 +317,8 @@
 	}
 
 	pci_read_config_byte(pdev,   0x8A, &tmpbyte);
-	printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
-			tmpbyte & 1, tmpbyte & 0x30);
+	dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n",
+		tmpbyte & 1, tmpbyte & 0x30);
 
 	pci_write_config_byte(pdev,  0xA1, 0x72);
 	pci_write_config_word(pdev,  0xA2, 0x328A);
@@ -339,22 +341,23 @@
 	return tmpbyte & 0x30;
 }
 
-static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit sil680_init_one(struct pci_dev *pdev,
+				     const struct pci_device_id *id)
 {
 	static const struct ata_port_info info = {
 		.sht = &sil680_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,
+		.udma_mask = ATA_UDMA6,
 		.port_ops = &sil680_port_ops
 	};
 	static const struct ata_port_info info_slow = {
 		.sht = &sil680_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &sil680_port_ops
 	};
 	const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index cfe4ec6..2b45082 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -732,7 +732,7 @@
 
 static const struct ata_port_info sis_info = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.mwdma_mask	= 0x07,
 	.udma_mask	= 0,
@@ -740,7 +740,7 @@
 };
 static const struct ata_port_info sis_info33 = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.mwdma_mask	= 0x07,
 	.udma_mask	= ATA_UDMA2,	/* UDMA 33 */
@@ -748,28 +748,28 @@
 };
 static const struct ata_port_info sis_info66 = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.udma_mask	= ATA_UDMA4,	/* UDMA 66 */
 	.port_ops	= &sis_66_ops,
 };
 static const struct ata_port_info sis_info100 = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.udma_mask	= ATA_UDMA5,
 	.port_ops	= &sis_100_ops,
 };
 static const struct ata_port_info sis_info100_early = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.udma_mask	= ATA_UDMA5,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.port_ops	= &sis_66_ops,
 };
 static const struct ata_port_info sis_info133 = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_133_ops,
@@ -783,7 +783,7 @@
 };
 static const struct ata_port_info sis_info133_early = {
 	.sht		= &sis_sht,
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= 0x1f,	/* pio0-4 */
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_133_early_ops,
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index e5aaec4..bde7341 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -303,14 +303,14 @@
 {
 	static const struct ata_port_info info_dma = {
 		.sht = &sl82c105_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &sl82c105_port_ops
 	};
 	static const struct ata_port_info info_early = {
 		.sht = &sl82c105_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.port_ops = &sl82c105_port_ops
 	};
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index b1d3076..af21f44 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -235,7 +235,7 @@
 {
 	static const struct ata_port_info info = {
 		.sht = &triflex_sht,
-		.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
 		.port_ops = &triflex_port_ops
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 63eca29..f0cadbe 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -471,7 +471,7 @@
 		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7,
+		.udma_mask = ATA_UDMA2,
 		.port_ops = &via_port_ops
 	};
 	/* VIA UDMA 66 devices */
@@ -480,7 +480,7 @@
 		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x1f,
+		.udma_mask = ATA_UDMA4,
 		.port_ops = &via_port_ops
 	};
 	/* VIA UDMA 100 devices */
@@ -489,7 +489,7 @@
 		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x3f,
+		.udma_mask = ATA_UDMA5,
 		.port_ops = &via_port_ops
 	};
 	/* UDMA133 with bad AST (All current 133) */
@@ -498,7 +498,7 @@
 		.flags = ATA_FLAG_SLAVE_POSS,
 		.pio_mask = 0x1f,
 		.mwdma_mask = 0x07,
-		.udma_mask = 0x7f,	/* FIXME: should check north bridge */
+		.udma_mask = ATA_UDMA6,	/* FIXME: should check north bridge */
 		.port_ops = &via_port_ops
 	};
 	struct ata_port_info type;
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index f12c2b6..bec1de5 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -145,32 +145,32 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.can_queue		= ATA_DEF_QUEUE,
-	.this_id		= ATA_SHT_THIS_ID,
-	.sg_tablesize		= LIBATA_MAX_PRD,
-	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
-	.emulated		= ATA_SHT_EMULATED,
-	.use_clustering		= ENABLE_CLUSTERING,
-	.proc_name		= DRV_NAME,
-	.dma_boundary		= ADMA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.proc_name		= DRV_NAME,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.dma_boundary		= ADMA_DMA_BOUNDARY,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.emulated		= ATA_SHT_EMULATED,
 };
 
 static const struct ata_port_operations adma_ata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
-	.check_status		= ata_check_status,
-	.check_atapi_dma	= adma_check_atapi_dma,
 	.exec_command		= ata_exec_command,
+	.check_status		= ata_check_status,
 	.dev_select		= ata_std_dev_select,
 	.phy_reset		= adma_phy_reset,
+	.check_atapi_dma	= adma_check_atapi_dma,
+	.data_xfer		= ata_data_xfer,
 	.qc_prep		= adma_qc_prep,
 	.qc_issue		= adma_qc_issue,
 	.eng_timeout		= adma_eng_timeout,
-	.data_xfer		= ata_data_xfer,
 	.irq_clear		= adma_irq_clear,
 	.irq_on			= ata_irq_on,
 	.irq_ack		= ata_irq_ack,
@@ -188,7 +188,7 @@
 				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
 				  ATA_FLAG_PIO_POLLING,
 		.pio_mask	= 0x10, /* pio4 */
-		.udma_mask	= 0x1f, /* udma0-4 */
+		.udma_mask	= ATA_UDMA4,
 		.port_ops	= &adma_ata_ops,
 	},
 };
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index dc3bbce..3de1834 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -192,7 +192,7 @@
 
 static u32 inic_scr_read(struct ata_port *ap, unsigned sc_reg)
 {
-	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+	void __iomem *scr_addr = ap->ioaddr.scr_addr;
 	void __iomem *addr;
 	u32 val;
 
@@ -210,7 +210,7 @@
 
 static void inic_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
 {
-	void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+	void __iomem *scr_addr = ap->ioaddr.scr_addr;
 	void __iomem *addr;
 
 	if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
@@ -594,7 +594,7 @@
 	.flags			= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
 	.pio_mask		= 0x1f,	/* pio0-4 */
 	.mwdma_mask		= 0x07, /* mwdma0-2 */
-	.udma_mask		= 0x7f,	/* udma0-6 */
+	.udma_mask		= ATA_UDMA6,
 	.port_ops		= &inic_port_ops
 };
 
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 590f2f9..3873b29 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -526,44 +526,44 @@
 	{  /* chip_504x */
 		.flags		= MV_COMMON_FLAGS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv5_ops,
 	},
 	{  /* chip_508x */
 		.flags		= (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv5_ops,
 	},
 	{  /* chip_5080 */
 		.flags		= (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv5_ops,
 	},
 	{  /* chip_604x */
 		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv6_ops,
 	},
 	{  /* chip_608x */
 		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
 				   MV_FLAG_DUAL_HC),
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv6_ops,
 	},
 	{  /* chip_6042 */
 		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv_iie_ops,
 	},
 	{  /* chip_7042 */
 		.flags		= (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
 		.pio_mask	= 0x1f,	/* pio0-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv_iie_ops,
 	},
 };
@@ -2338,7 +2338,7 @@
 	struct pci_dev *pdev = to_pci_dev(host->dev);
 	struct mv_host_priv *hpriv = host->private_data;
 	u8 rev_id, scc;
-	const char *scc_s;
+	const char *scc_s, *gen;
 
 	/* Use this to determine the HW stepping of the chip so we know
 	 * what errata to workaround
@@ -2351,11 +2351,20 @@
 	else if (scc == 0x01)
 		scc_s = "RAID";
 	else
-		scc_s = "unknown";
+		scc_s = "?";
+
+	if (IS_GEN_I(hpriv))
+		gen = "I";
+	else if (IS_GEN_II(hpriv))
+		gen = "II";
+	else if (IS_GEN_IIE(hpriv))
+		gen = "IIE";
+	else
+		gen = "?";
 
 	dev_printk(KERN_INFO, &pdev->dev,
-	       "%u slots %u ports %s mode IRQ via %s\n",
-	       (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
+	       "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
+	       gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
 	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
 }
 
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 6dc0b01..2ad5872 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -45,8 +45,7 @@
 #include "sata_promise.h"
 
 #define DRV_NAME	"sata_promise"
-#define DRV_VERSION	"2.07"
-
+#define DRV_VERSION	"2.08"
 
 enum {
 	PDC_MAX_PORTS		= 4,
@@ -94,7 +93,7 @@
 	board_20319		= 2,	/* FastTrak S150 TX4 */
 	board_20619		= 3,	/* FastTrak TX4000 */
 	board_2057x		= 4,	/* SATAII150 Tx2plus */
-	board_2057x_pata	= 5,	/* SATAII150 Tx2plus */
+	board_2057x_pata	= 5,	/* SATAII150 Tx2plus PATA port */
 	board_40518		= 6,	/* SATAII150 Tx4 */
 
 	PDC_HAS_PATA		= (1 << 1), /* PDC20375/20575 has PATA */
@@ -124,7 +123,6 @@
 	PDC_FLAG_4_PORTS	= (1 << 26), /* 4 ports */
 };
 
-
 struct pdc_port_priv {
 	u8			*pkt;
 	dma_addr_t		pkt_dma;
@@ -252,7 +250,7 @@
 				  PDC_FLAG_SATA_PATA,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_old_sata_ops,
 	},
 
@@ -261,7 +259,7 @@
 		.flags		= PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_pata_ops,
 	},
 
@@ -271,7 +269,7 @@
 				  PDC_FLAG_4_PORTS,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_old_sata_ops,
 	},
 
@@ -281,7 +279,7 @@
 				  PDC_FLAG_4_PORTS,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_pata_ops,
 	},
 
@@ -291,7 +289,7 @@
 				  PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_sata_ops,
 	},
 
@@ -301,7 +299,7 @@
 				  PDC_FLAG_GEN_II,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_pata_ops,
 	},
 
@@ -311,7 +309,7 @@
 				  PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_sata_ops,
 	},
 };
@@ -340,7 +338,6 @@
 	{ }	/* terminate list */
 };
 
-
 static struct pci_driver pdc_ata_pci_driver = {
 	.name			= DRV_NAME,
 	.id_table		= pdc_ata_pci_tbl,
@@ -348,7 +345,6 @@
 	.remove			= ata_pci_remove_one,
 };
 
-
 static int pdc_common_port_start(struct ata_port *ap)
 {
 	struct device *dev = ap->host->dev;
@@ -382,7 +378,7 @@
 
 	/* fix up PHYMODE4 align timing */
 	if (ap->flags & PDC_FLAG_GEN_II) {
-		void __iomem *mmio = (void __iomem *) ap->ioaddr.scr_addr;
+		void __iomem *mmio = ap->ioaddr.scr_addr;
 		unsigned int tmp;
 
 		tmp = readl(mmio + 0x014);
@@ -418,7 +414,7 @@
 static int pdc_pata_cable_detect(struct ata_port *ap)
 {
 	u8 tmp;
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
+	void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
 
 	tmp = readb(mmio);
 	if (tmp & 0x01)
@@ -438,7 +434,6 @@
 	return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-
 static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
 			       u32 val)
 {
@@ -573,7 +568,7 @@
 
 static void pdc_freeze(struct ata_port *ap)
 {
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+	void __iomem *mmio = ap->ioaddr.cmd_addr;
 	u32 tmp;
 
 	tmp = readl(mmio + PDC_CTLSTAT);
@@ -585,7 +580,7 @@
 
 static void pdc_thaw(struct ata_port *ap)
 {
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+	void __iomem *mmio = ap->ioaddr.cmd_addr;
 	u32 tmp;
 
 	/* clear IRQ */
@@ -657,8 +652,8 @@
 	ata_port_abort(ap);
 }
 
-static inline unsigned int pdc_host_intr( struct ata_port *ap,
-                                          struct ata_queued_cmd *qc)
+static inline unsigned int pdc_host_intr(struct ata_port *ap,
+					 struct ata_queued_cmd *qc)
 {
 	unsigned int handled = 0;
 	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
@@ -685,10 +680,10 @@
 		handled = 1;
 		break;
 
-        default:
+	default:
 		ap->stats.idle_irq++;
 		break;
-        }
+	}
 
 	return handled;
 }
@@ -701,6 +696,18 @@
 	readl(mmio + PDC_INT_SEQMASK);
 }
 
+static inline int pdc_is_sataii_tx4(unsigned long flags)
+{
+	const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS;
+	return (flags & mask) == mask;
+}
+
+static inline unsigned int pdc_port_no_to_ata_no(unsigned int port_no, int is_sataii_tx4)
+{
+	static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
+	return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no;
+}
+
 static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
@@ -807,7 +814,6 @@
 	ata_tf_load(ap, tf);
 }
 
-
 static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
 {
 	WARN_ON (tf->protocol == ATA_PROT_DMA ||
@@ -867,7 +873,6 @@
 	ap->ioaddr.scr_addr		= scr_addr;
 }
 
-
 static void pdc_host_init(struct ata_host *host)
 {
 	void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
@@ -955,10 +960,8 @@
 
 	if (pi->flags & PDC_FLAG_SATA_PATA) {
 		u8 tmp = readb(base + PDC_FLASH_CTL+1);
-		if (!(tmp & 0x80)) {
+		if (!(tmp & 0x80))
 			ppi[n_ports++] = pi + 1;
-			dev_printk(KERN_INFO, &pdev->dev, "PATA port found\n");
-		}
 	}
 
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
@@ -968,22 +971,12 @@
 	}
 	host->iomap = pcim_iomap_table(pdev);
 
-	is_sataii_tx4 = 0;
-	if ((pi->flags & (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) == (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) {
-		is_sataii_tx4 = 1;
-		dev_printk(KERN_INFO, &pdev->dev, "applying SATAII TX4 port numbering workaround\n");
-	}
+	is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags);
 	for (i = 0; i < host->n_ports; i++) {
-		static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
-		int ata_nr;
-
-		ata_nr = i;
-		if (is_sataii_tx4)
-			ata_nr = sataii_tx4_port_remap[i];
-
+		unsigned int ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
 		pdc_ata_setup_port(host->ports[i],
-				   base + 0x200 + ata_nr * 0x80,
-				   base + 0x400 + ata_nr * 0x100);
+				   base + 0x200 + ata_no * 0x80,
+				   base + 0x400 + ata_no * 0x100);
 	}
 
 	/* initialize adapter */
@@ -1002,19 +995,16 @@
 				 &pdc_ata_sht);
 }
 
-
 static int __init pdc_ata_init(void)
 {
 	return pci_register_driver(&pdc_ata_pci_driver);
 }
 
-
 static void __exit pdc_ata_exit(void)
 {
 	pci_unregister_driver(&pdc_ata_pci_driver);
 }
 
-
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index 6688ccb..9ab554d 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -176,7 +176,7 @@
 				  //FIXME ATA_FLAG_SRST |
 				  ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
 		.pio_mask	= 0x10, /* pio4 */
-		.udma_mask	= 0x7f, /* udma0-6 */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &qs_ata_ops,
 	},
 };
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index a3b339b..2a86dc4 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -218,7 +218,7 @@
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
 	/* sil_3112_no_sata_irq */
@@ -227,7 +227,7 @@
 				  SIL_FLAG_NO_SATA_IRQ,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
 	/* sil_3512 */
@@ -235,7 +235,7 @@
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
 	/* sil_3114 */
@@ -243,7 +243,7 @@
 		.flags		= SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,
 		.port_ops	= &sil_ops,
 	},
 };
@@ -262,8 +262,9 @@
 	unsigned long sfis_cfg;	/* SATA FIS reception config register */
 } sil_port[] = {
 	/* port 0 ... */
-	{ 0x80, 0x8A, 0x00, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c },
-	{ 0xC0, 0xCA, 0x08, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
+	/*   tf    ctl  bmdma  bmdma2  fifo    scr   sien   mode   sfis */
+	{  0x80,  0x8A,   0x0,  0x10,  0x40, 0x100, 0x148,  0xb4, 0x14c },
+	{  0xC0,  0xCA,   0x8,  0x18,  0x44, 0x180, 0x1c8,  0xf4, 0x1cc },
 	{ 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
 	{ 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
 	/* ... port 3 */
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 0ddfae9..ac43a30 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -426,7 +426,7 @@
 				  SIL24_FLAG_PCIX_IRQ_WOC,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
 		.port_ops	= &sil24_ops,
 	},
 	/* sil_3132 */
@@ -434,7 +434,7 @@
 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
 		.port_ops	= &sil24_ops,
 	},
 	/* sil_3131/sil_3531 */
@@ -442,7 +442,7 @@
 		.flags		= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
-		.udma_mask	= 0x3f,			/* udma0-5 */
+		.udma_mask	= ATA_UDMA5,		/* udma0-5 */
 		.port_ops	= &sil24_ops,
 	},
 };
@@ -888,7 +888,7 @@
 		if (status & (1 << i)) {
 			struct ata_port *ap = host->ports[i];
 			if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
-				sil24_host_intr(host->ports[i]);
+				sil24_host_intr(ap);
 				handled++;
 			} else
 				printk(KERN_ERR DRV_NAME
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index f111c98..fd80bcf 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -133,7 +133,7 @@
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
 	.pio_mask	= 0x1f,
 	.mwdma_mask	= 0x7,
-	.udma_mask	= 0x7f,
+	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &sis_ops,
 };
 
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index bcb2cd8..63fe99af 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -107,7 +107,7 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return 0xffffffffU;
-	return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -116,7 +116,7 @@
 {
 	if (sc_reg > SCR_CONTROL)
 		return;
-	writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+	writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
 
@@ -197,7 +197,8 @@
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 dmactl;
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
 	/* load PRD table addr. */
 	mb();	/* make sure PRD table writes are visible to controller */
 	writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
@@ -225,7 +226,7 @@
 static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = ap->ioaddr.bmdma_addr;
 	u8 dmactl;
 
 	/* start host DMA transaction */
@@ -253,7 +254,7 @@
 
 static u8 k2_stat_check_status(struct ata_port *ap)
 {
-       	return readl((void __iomem *) ap->ioaddr.status_addr);
+       	return readl(ap->ioaddr.status_addr);
 }
 
 #ifdef CONFIG_PPC_OF
@@ -360,7 +361,7 @@
 				  ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA,
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask	= 0x7f,
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &k2_sata_ops,
 	},
 	/* board_svw8 */
@@ -370,7 +371,7 @@
 				  K2_FLAG_SATA_8_PORTS,
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask	= 0x7f,
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &k2_sata_ops,
 	},
 };
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 2d14f3d..5193bd8 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -30,6 +30,54 @@
  *
  */
 
+/*
+	Theory of operation
+	-------------------
+
+	The SX4 (PDC20621) chip features a single Host DMA (HDMA) copy
+	engine, DIMM memory, and four ATA engines (one per SATA port).
+	Data is copied to/from DIMM memory by the HDMA engine, before
+	handing off to one (or more) of the ATA engines.  The ATA
+	engines operate solely on DIMM memory.
+
+	The SX4 behaves like a PATA chip, with no SATA controls or
+	knowledge whatsoever, leading to the presumption that
+	PATA<->SATA bridges exist on SX4 boards, external to the
+	PDC20621 chip itself.
+
+	The chip is quite capable, supporting an XOR engine and linked
+	hardware commands (permits a string to transactions to be
+	submitted and waited-on as a single unit), and an optional
+	microprocessor.
+
+	The limiting factor is largely software.  This Linux driver was
+	written to multiplex the single HDMA engine to copy disk
+	transactions into a fixed DIMM memory space, from where an ATA
+	engine takes over.  As a result, each WRITE looks like this:
+
+		submit HDMA packet to hardware
+		hardware copies data from system memory to DIMM
+		hardware raises interrupt
+
+		submit ATA packet to hardware
+		hardware executes ATA WRITE command, w/ data in DIMM
+		hardware raises interrupt
+	
+	and each READ looks like this:
+
+		submit ATA packet to hardware
+		hardware executes ATA READ command, w/ data in DIMM
+		hardware raises interrupt
+	
+		submit HDMA packet to hardware
+		hardware copies data from DIMM to system memory
+		hardware raises interrupt
+
+	This is a very slow, lock-step way of doing things that can
+	certainly be improved by motivated kernel hackers.
+
+ */
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -58,6 +106,8 @@
 	PDC_INT_SEQMASK		= 0x40,	/* Mask of asserted SEQ INTs */
 	PDC_HDMA_CTLSTAT	= 0x12C, /* Host DMA control / status */
 
+	PDC_CTLSTAT		= 0x60,	/* IDEn control / status */
+
 	PDC_20621_SEQCTL	= 0x400,
 	PDC_20621_SEQMASK	= 0x480,
 	PDC_20621_GENERAL_CTL	= 0x484,
@@ -87,48 +137,60 @@
 
 	board_20621		= 0,	/* FastTrak S150 SX4 */
 
-	PDC_RESET		= (1 << 11), /* HDMA reset */
+	PDC_MASK_INT		= (1 << 10), /* HDMA/ATA mask int */
+	PDC_RESET		= (1 << 11), /* HDMA/ATA reset */
+	PDC_DMA_ENABLE		= (1 << 7),  /* DMA start/stop */
 
 	PDC_MAX_HDMA		= 32,
 	PDC_HDMA_Q_MASK		= (PDC_MAX_HDMA - 1),
 
-	PDC_DIMM0_SPD_DEV_ADDRESS     = 0x50,
-	PDC_DIMM1_SPD_DEV_ADDRESS     = 0x51,
-	PDC_MAX_DIMM_MODULE           = 0x02,
-	PDC_I2C_CONTROL_OFFSET        = 0x48,
-	PDC_I2C_ADDR_DATA_OFFSET      = 0x4C,
-	PDC_DIMM0_CONTROL_OFFSET      = 0x80,
-	PDC_DIMM1_CONTROL_OFFSET      = 0x84,
-	PDC_SDRAM_CONTROL_OFFSET      = 0x88,
-	PDC_I2C_WRITE                 = 0x00000000,
-	PDC_I2C_READ                  = 0x00000040,
-	PDC_I2C_START                 = 0x00000080,
-	PDC_I2C_MASK_INT              = 0x00000020,
-	PDC_I2C_COMPLETE              = 0x00010000,
-	PDC_I2C_NO_ACK                = 0x00100000,
-	PDC_DIMM_SPD_SUBADDRESS_START = 0x00,
-	PDC_DIMM_SPD_SUBADDRESS_END   = 0x7F,
-	PDC_DIMM_SPD_ROW_NUM          = 3,
-	PDC_DIMM_SPD_COLUMN_NUM       = 4,
-	PDC_DIMM_SPD_MODULE_ROW       = 5,
-	PDC_DIMM_SPD_TYPE             = 11,
-	PDC_DIMM_SPD_FRESH_RATE       = 12,
-	PDC_DIMM_SPD_BANK_NUM         = 17,
-	PDC_DIMM_SPD_CAS_LATENCY      = 18,
-	PDC_DIMM_SPD_ATTRIBUTE        = 21,
-	PDC_DIMM_SPD_ROW_PRE_CHARGE   = 27,
-	PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
-	PDC_DIMM_SPD_RAS_CAS_DELAY    = 29,
-	PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
-	PDC_DIMM_SPD_SYSTEM_FREQ      = 126,
-	PDC_CTL_STATUS		      = 0x08,
-	PDC_DIMM_WINDOW_CTLR	      = 0x0C,
-	PDC_TIME_CONTROL              = 0x3C,
-	PDC_TIME_PERIOD               = 0x40,
-	PDC_TIME_COUNTER              = 0x44,
-	PDC_GENERAL_CTLR	      = 0x484,
-	PCI_PLL_INIT                  = 0x8A531824,
-	PCI_X_TCOUNT                  = 0xEE1E5CFF
+	PDC_DIMM0_SPD_DEV_ADDRESS	= 0x50,
+	PDC_DIMM1_SPD_DEV_ADDRESS	= 0x51,
+	PDC_I2C_CONTROL			= 0x48,
+	PDC_I2C_ADDR_DATA		= 0x4C,
+	PDC_DIMM0_CONTROL		= 0x80,
+	PDC_DIMM1_CONTROL		= 0x84,
+	PDC_SDRAM_CONTROL		= 0x88,
+	PDC_I2C_WRITE			= 0,		/* master -> slave */
+	PDC_I2C_READ			= (1 << 6),	/* master <- slave */
+	PDC_I2C_START			= (1 << 7),	/* start I2C proto */
+	PDC_I2C_MASK_INT		= (1 << 5),	/* mask I2C interrupt */
+	PDC_I2C_COMPLETE		= (1 << 16),	/* I2C normal compl. */
+	PDC_I2C_NO_ACK			= (1 << 20),	/* slave no-ack addr */
+	PDC_DIMM_SPD_SUBADDRESS_START	= 0x00,
+	PDC_DIMM_SPD_SUBADDRESS_END	= 0x7F,
+	PDC_DIMM_SPD_ROW_NUM		= 3,
+	PDC_DIMM_SPD_COLUMN_NUM		= 4,
+	PDC_DIMM_SPD_MODULE_ROW		= 5,
+	PDC_DIMM_SPD_TYPE		= 11,
+	PDC_DIMM_SPD_FRESH_RATE		= 12,
+	PDC_DIMM_SPD_BANK_NUM		= 17,
+	PDC_DIMM_SPD_CAS_LATENCY	= 18,
+	PDC_DIMM_SPD_ATTRIBUTE		= 21,
+	PDC_DIMM_SPD_ROW_PRE_CHARGE	= 27,
+	PDC_DIMM_SPD_ROW_ACTIVE_DELAY	= 28,
+	PDC_DIMM_SPD_RAS_CAS_DELAY	= 29,
+	PDC_DIMM_SPD_ACTIVE_PRECHARGE	= 30,
+	PDC_DIMM_SPD_SYSTEM_FREQ	= 126,
+	PDC_CTL_STATUS			= 0x08,
+	PDC_DIMM_WINDOW_CTLR		= 0x0C,
+	PDC_TIME_CONTROL		= 0x3C,
+	PDC_TIME_PERIOD			= 0x40,
+	PDC_TIME_COUNTER		= 0x44,
+	PDC_GENERAL_CTLR		= 0x484,
+	PCI_PLL_INIT			= 0x8A531824,
+	PCI_X_TCOUNT			= 0xEE1E5CFF,
+
+	/* PDC_TIME_CONTROL bits */
+	PDC_TIMER_BUZZER		= (1 << 10),
+	PDC_TIMER_MODE_PERIODIC		= 0,		/* bits 9:8 == 00 */
+	PDC_TIMER_MODE_ONCE		= (1 << 8),	/* bits 9:8 == 01 */
+	PDC_TIMER_ENABLE		= (1 << 7),
+	PDC_TIMER_MASK_INT		= (1 << 5),
+	PDC_TIMER_SEQ_MASK		= 0x1f,		/* SEQ ID for timer */
+	PDC_TIMER_DEFAULT		= PDC_TIMER_MODE_ONCE |
+					  PDC_TIMER_ENABLE |
+					  PDC_TIMER_MASK_INT,
 };
 
 
@@ -217,7 +279,7 @@
 				  ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &pdc_20621_ops,
 	},
 
@@ -999,17 +1061,17 @@
 	i2creg |= subaddr << 16;
 
 	/* Set the device and subaddress */
-	writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET);
-	readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+	writel(i2creg, mmio + PDC_I2C_ADDR_DATA);
+	readl(mmio + PDC_I2C_ADDR_DATA);
 
 	/* Write Control to perform read operation, mask int */
 	writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
-	       mmio + PDC_I2C_CONTROL_OFFSET);
+	       mmio + PDC_I2C_CONTROL);
 
 	for (count = 0; count <= 1000; count ++) {
-		status = readl(mmio + PDC_I2C_CONTROL_OFFSET);
+		status = readl(mmio + PDC_I2C_CONTROL);
 		if (status & PDC_I2C_COMPLETE) {
-			status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+			status = readl(mmio + PDC_I2C_ADDR_DATA);
 			break;
 		} else if (count == 1000)
 			return 0;
@@ -1099,8 +1161,8 @@
    	data |= (((size / 16) - 1) << 16);
    	data |= (0 << 23);
 	data |= 8;
-   	writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
-	readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
+   	writel(data, mmio + PDC_DIMM0_CONTROL);
+	readl(mmio + PDC_DIMM0_CONTROL);
    	return size;
 }
 
@@ -1122,27 +1184,27 @@
 	*/
 
 	data = 0x022259F1;
-	writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
-	readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+	writel(data, mmio + PDC_SDRAM_CONTROL);
+	readl(mmio + PDC_SDRAM_CONTROL);
 
 	/* Turn on for ECC */
 	pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
 			  PDC_DIMM_SPD_TYPE, &spd0);
 	if (spd0 == 0x02) {
 		data |= (0x01 << 16);
-		writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
-		readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+		writel(data, mmio + PDC_SDRAM_CONTROL);
+		readl(mmio + PDC_SDRAM_CONTROL);
 		printk(KERN_ERR "Local DIMM ECC Enabled\n");
    	}
 
    	/* DIMM Initialization Select/Enable (bit 18/19) */
    	data &= (~(1<<18));
    	data |= (1<<19);
-   	writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+   	writel(data, mmio + PDC_SDRAM_CONTROL);
 
    	error = 1;
    	for (i = 1; i <= 10; i++) {   /* polling ~5 secs */
-		data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+		data = readl(mmio + PDC_SDRAM_CONTROL);
 		if (!(data & (1<<19))) {
 	   		error = 0;
 	   		break;
@@ -1176,7 +1238,7 @@
 	VPRINTK("Time Period Register (0x40): 0x%x\n", time_period);
 
 	/* Enable timer */
-	writel(0x00001a0, mmio + PDC_TIME_CONTROL);
+	writel(PDC_TIMER_DEFAULT, mmio + PDC_TIME_CONTROL);
 	readl(mmio + PDC_TIME_CONTROL);
 
 	/* Wait 3 seconds */
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 6815de7..aca7181 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -129,7 +129,7 @@
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 			  ATA_FLAG_IGN_SIMPLEX,
 	.pio_mask       = 0x1f,		/* pio0-4 */
-	.udma_mask      = 0x7f,		/* udma0-6 */
+	.udma_mask      = ATA_UDMA6,
 	.port_ops       = &uli_ops,
 };
 
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index e8b90e7..a4c0832 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -223,7 +223,7 @@
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
 	.pio_mask	= 0x1f,
 	.mwdma_mask	= 0x07,
-	.udma_mask	= 0x7f,
+	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &vt6420_sata_ops,
 };
 
@@ -231,7 +231,7 @@
 	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
 	.pio_mask	= 0x1f,
 	.mwdma_mask	= 0x07,
-	.udma_mask	= 0x7f,
+	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &vt6421_sata_ops,
 };
 
@@ -239,7 +239,7 @@
 	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY,
 	.pio_mask	= 0x1f,
 	.mwdma_mask	= 0,
-	.udma_mask	= 0x7f,
+	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &vt6421_pata_ops,
 };
 
@@ -303,9 +303,7 @@
 	if (!(ap->pflags & ATA_PFLAG_LOADING))
 		goto skip_scr;
 
-	/* Resume phy.  This is the old resume sequence from
-	 * __sata_phy_reset().
-	 */
+	/* Resume phy.  This is the old SATA resume sequence */
 	svia_scr_write(ap, SCR_CONTROL, 0x300);
 	svia_scr_read(ap, SCR_CONTROL); /* flush */
 
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 8133017..1b5d81f 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -371,7 +371,7 @@
 				  ATA_FLAG_MMIO,
 		.pio_mask	= 0x1f,
 		.mwdma_mask	= 0x07,
-		.udma_mask	= 0x7f,
+		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &vsc_sata_ops,
 	};
 	const struct ata_port_info *ppi[] = { &pi, NULL };
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index b4c8319..6e23af1 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -2,9 +2,12 @@
 # Block device driver configuration
 #
 
-if BLOCK
+menuconfig BLK_DEV
+	bool "Block devices"
+	depends on BLOCK
+	default y
 
-menu "Block devices"
+if BLK_DEV
 
 config BLK_DEV_FD
 	tristate "Normal floppy disk support"
@@ -56,40 +59,9 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called z2ram.
 
-config ATARI_ACSI
-	tristate "Atari ACSI support"
-	depends on ATARI && BROKEN
-	---help---
-	  This enables support for the Atari ACSI interface. The driver
-	  supports hard disks and CD-ROMs, which have 512-byte sectors, or can
-	  be switched to that mode. Due to the ACSI command format, only disks
-	  up to 1 GB are supported. Special support for certain ACSI to SCSI
-	  adapters, which could relax that, isn't included yet. The ACSI
-	  driver is also the basis for certain other drivers for devices
-	  attached to the ACSI bus: Atari SLM laser printer, BioNet-100
-	  Ethernet, and PAMsNet Ethernet. If you want to use one of these
-	  devices, you need ACSI support, too.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called acsi.
-
-comment "Some devices (e.g. CD jukebox) support multiple LUNs"
-	depends on ATARI && ATARI_ACSI
-
-config ACSI_MULTI_LUN
-	bool "Probe all LUNs on each ACSI device"
-	depends on ATARI_ACSI
-	help
-	  If you have a ACSI device that supports more than one LUN (Logical
-	  Unit Number), e.g. a CD jukebox, you should say Y here so that all
-	  will be found by the ACSI driver. An ACSI device with multiple LUNs
-	  acts logically like multiple ACSI devices. The vast majority of ACSI
-	  devices have only one LUN, and so most people can say N here and
-	  should in fact do so, because it is safer.
-
 config ATARI_SLM
 	tristate "Atari SLM laser printer support"
-	depends on ATARI && ATARI_ACSI!=n
+	depends on ATARI
 	help
 	  If you have an Atari SLM laser printer, say Y to include support for
 	  it in the kernel. Otherwise, say N. This driver is also available as
@@ -453,6 +425,4 @@
 
 source "drivers/s390/block/Kconfig"
 
-endmenu
-
-endif
+endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index dd88e33..e5f98ac 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,7 +9,6 @@
 obj-$(CONFIG_BLK_DEV_FD)	+= floppy.o
 obj-$(CONFIG_AMIGA_FLOPPY)	+= amiflop.o
 obj-$(CONFIG_ATARI_FLOPPY)	+= ataflop.o
-obj-$(CONFIG_ATARI_ACSI)	+= acsi.o
 obj-$(CONFIG_ATARI_SLM)		+= acsi_slm.o
 obj-$(CONFIG_AMIGA_Z2RAM)	+= z2ram.o
 obj-$(CONFIG_BLK_DEV_RAM)	+= rd.o
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
deleted file mode 100644
index e3d9152..0000000
--- a/drivers/block/acsi.c
+++ /dev/null
@@ -1,1825 +0,0 @@
-/*
- * acsi.c -- Device driver for Atari ACSI hard disks
- *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * Some parts are based on hd.c by Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive for
- * more details.
- *
- */
-
-/*
- * Still to in this file:
- *  - If a command ends with an error status (!= 0), the following
- *    REQUEST SENSE commands (4 to fill the ST-DMA FIFO) are done by
- *    polling the _IRQ signal (not interrupt-driven). This should be
- *    avoided in future because it takes up a non-neglectible time in
- *    the interrupt service routine while interrupts are disabled.
- *    Maybe a timer interrupt will get lost :-(
- */
-
-/*
- * General notes:
- *
- *  - All ACSI devices (disks, CD-ROMs, ...) use major number 28.
- *    Minors are organized like it is with SCSI: The upper 4 bits
- *    identify the device, the lower 4 bits the partition.
- *    The device numbers (the upper 4 bits) are given in the same
- *    order as the devices are found on the bus.
- *  - Up to 8 LUNs are supported for each target (if CONFIG_ACSI_MULTI_LUN
- *    is defined), but only a total of 16 devices (due to minor
- *    numbers...). Note that Atari allows only a maximum of 4 targets
- *    (i.e. controllers, not devices) on the ACSI bus!
- *  - A optimizing scheme similar to SCSI scatter-gather is implemented.
- *  - Removable media are supported. After a medium change to device
- *    is reinitialized (partition check etc.). Also, if the device
- *    knows the PREVENT/ALLOW MEDIUM REMOVAL command, the door should
- *    be locked and unlocked when mounting the first or unmounting the
- *    last filesystem on the device. The code is untested, because I
- *    don't have a removable hard disk.
- *
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/genhd.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <scsi/scsi.h> /* for SCSI_IOCTL_GET_IDLUN */
-#include <scsi/scsi_ioctl.h>
-#include <linux/hdreg.h> /* for HDIO_GETGEO */
-#include <linux/blkpg.h>
-#include <linux/buffer_head.h>
-#include <linux/blkdev.h>
-
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_acsi.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-
-static void (*do_acsi)(void) = NULL;
-static struct request_queue *acsi_queue;
-#define QUEUE (acsi_queue)
-#define CURRENT elv_next_request(acsi_queue)
-
-#define DEBUG
-#undef DEBUG_DETECT
-#undef NO_WRITE
-
-#define MAX_ERRORS     		8	/* Max read/write errors/sector */
-#define MAX_LUN				8	/* Max LUNs per target */
-#define MAX_DEV		   		16
-
-#define ACSI_BUFFER_SIZE			(16*1024) /* "normal" ACSI buffer size */
-#define ACSI_BUFFER_MINSIZE			(2048) 	  /* min. buf size if ext. DMA */
-#define ACSI_BUFFER_SIZE_ORDER	 	2		  /* order size for above */
-#define ACSI_BUFFER_MINSIZE_ORDER	0 	  	  /* order size for above */
-#define ACSI_BUFFER_SECTORS	(ACSI_BUFFER_SIZE/512)
-
-#define ACSI_BUFFER_ORDER \
-	(ATARIHW_PRESENT(EXTD_DMA) ? \
-	 ACSI_BUFFER_MINSIZE_ORDER : \
-	 ACSI_BUFFER_SIZE_ORDER)
-
-#define ACSI_TIMEOUT		(4*HZ)
-
-/* minimum delay between two commands */
-
-#define COMMAND_DELAY 500
-
-typedef enum {
-	NONE, HARDDISK, CDROM
-} ACSI_TYPE;
-
-struct acsi_info_struct {
-	ACSI_TYPE		type;			/* type of device */
-	unsigned		target;			/* target number */
-	unsigned		lun;			/* LUN in target controller */
-	unsigned		removable : 1;	/* Flag for removable media */
-	unsigned		read_only : 1;	/* Flag for read only devices */
-	unsigned		old_atari_disk : 1; /* Is an old Atari disk       */
-	unsigned		changed : 1;	/* Medium has been changed */
-	unsigned long 	size;			/* #blocks */
-	int access_count;
-} acsi_info[MAX_DEV];
-
-/*
- *	SENSE KEYS
- */
-
-#define NO_SENSE		0x00
-#define RECOVERED_ERROR 	0x01
-#define NOT_READY		0x02
-#define MEDIUM_ERROR		0x03
-#define HARDWARE_ERROR		0x04
-#define ILLEGAL_REQUEST 	0x05
-#define UNIT_ATTENTION		0x06
-#define DATA_PROTECT		0x07
-#define BLANK_CHECK		0x08
-#define COPY_ABORTED		0x0a
-#define ABORTED_COMMAND 	0x0b
-#define VOLUME_OVERFLOW 	0x0d
-#define MISCOMPARE		0x0e
-
-
-/*
- *	DEVICE TYPES
- */
-
-#define TYPE_DISK	0x00
-#define TYPE_TAPE	0x01
-#define TYPE_WORM	0x04
-#define TYPE_ROM	0x05
-#define TYPE_MOD	0x07
-#define TYPE_NO_LUN	0x7f
-
-/* The data returned by MODE SENSE differ between the old Atari
- * hard disks and SCSI disks connected to ACSI. In the following, both
- * formats are defined and some macros to operate on them potably.
- */
-
-typedef struct {
-	unsigned long	dummy[2];
-	unsigned long	sector_size;
-	unsigned char	format_code;
-#define ATARI_SENSE_FORMAT_FIX	1	
-#define ATARI_SENSE_FORMAT_CHNG	2
-	unsigned char	cylinders_h;
-	unsigned char	cylinders_l;
-	unsigned char	heads;
-	unsigned char	reduced_h;
-	unsigned char	reduced_l;
-	unsigned char	precomp_h;
-	unsigned char	precomp_l;
-	unsigned char	landing_zone;
-	unsigned char	steprate;
-	unsigned char	type;
-#define ATARI_SENSE_TYPE_FIXCHNG_MASK		4
-#define ATARI_SENSE_TYPE_SOFTHARD_MASK		8
-#define ATARI_SENSE_TYPE_FIX				4
-#define ATARI_SENSE_TYPE_CHNG				0
-#define ATARI_SENSE_TYPE_SOFT				0
-#define ATARI_SENSE_TYPE_HARD				8
-	unsigned char	sectors;
-} ATARI_SENSE_DATA;
-
-#define ATARI_CAPACITY(sd) \
-	(((int)((sd).cylinders_h<<8)|(sd).cylinders_l) * \
-	 (sd).heads * (sd).sectors)
-
-
-typedef struct {
-	unsigned char   dummy1;
-	unsigned char   medium_type;
-	unsigned char   dummy2;
-	unsigned char   descriptor_size;
-	unsigned long   block_count;
-	unsigned long   sector_size;
-	/* Page 0 data */
-	unsigned char	page_code;
-	unsigned char	page_size;
-	unsigned char	page_flags;
-	unsigned char	qualifier;
-} SCSI_SENSE_DATA;
-
-#define SCSI_CAPACITY(sd) 	((sd).block_count & 0xffffff)
-
-
-typedef union {
-	ATARI_SENSE_DATA	atari;
-	SCSI_SENSE_DATA		scsi;
-} SENSE_DATA;
-
-#define SENSE_TYPE_UNKNOWN	0
-#define SENSE_TYPE_ATARI	1
-#define SENSE_TYPE_SCSI		2
-
-#define SENSE_TYPE(sd)										\
-	(((sd).atari.dummy[0] == 8 &&							\
-	  ((sd).atari.format_code == 1 ||						\
-	   (sd).atari.format_code == 2)) ? SENSE_TYPE_ATARI :	\
-	 ((sd).scsi.dummy1 >= 11) ? SENSE_TYPE_SCSI :			\
-	 SENSE_TYPE_UNKNOWN)
-	 
-#define CAPACITY(sd)							\
-	(SENSE_TYPE(sd) == SENSE_TYPE_ATARI ?		\
-	 ATARI_CAPACITY((sd).atari) :				\
-	 SCSI_CAPACITY((sd).scsi))
-
-#define SECTOR_SIZE(sd)							\
-	(SENSE_TYPE(sd) == SENSE_TYPE_ATARI ?		\
-	 (sd).atari.sector_size :					\
-	 (sd).scsi.sector_size & 0xffffff)
-
-/* Default size if capacity cannot be determined (1 GByte) */
-#define	DEFAULT_SIZE	0x1fffff
-
-#define CARTRCH_STAT(aip,buf)						\
-	(aip->old_atari_disk ?						\
-	 (((buf)[0] & 0x7f) == 0x28) :					\
-	 ((((buf)[0] & 0x70) == 0x70) ?					\
-	  (((buf)[2] & 0x0f) == 0x06) :					\
-	  (((buf)[0] & 0x0f) == 0x06)))					\
-
-/* These two are also exported to other drivers that work on the ACSI bus and
- * need an ST-RAM buffer. */
-char 			*acsi_buffer;
-unsigned long 	phys_acsi_buffer;
-
-static int NDevices;
-
-static int				CurrentNReq;
-static int				CurrentNSect;
-static char				*CurrentBuffer;
-
-static DEFINE_SPINLOCK(acsi_lock);
-
-
-#define SET_TIMER()	mod_timer(&acsi_timer, jiffies + ACSI_TIMEOUT)
-#define CLEAR_TIMER()	del_timer(&acsi_timer)
-
-static unsigned long	STramMask;
-#define STRAM_ADDR(a)	(((a) & STramMask) == 0)
-
-
-
-/* ACSI commands */
-
-static char tur_cmd[6]        = { 0x00, 0, 0, 0, 0, 0 };
-static char modesense_cmd[6]  = { 0x1a, 0, 0, 0, 24, 0 };
-static char modeselect_cmd[6] = { 0x15, 0, 0, 0, 12, 0 };
-static char inquiry_cmd[6]    = { 0x12, 0, 0, 0,255, 0 };
-static char reqsense_cmd[6]   = { 0x03, 0, 0, 0, 4, 0 };
-static char read_cmd[6]       = { 0x08, 0, 0, 0, 0, 0 };
-static char write_cmd[6]      = { 0x0a, 0, 0, 0, 0, 0 };
-static char pa_med_rem_cmd[6] = { 0x1e, 0, 0, 0, 0, 0 };
-
-#define CMDSET_TARG_LUN(cmd,targ,lun)			\
-    do {						\
-		cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5;	\
-		cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5;	\
-	} while(0)
-
-#define CMDSET_BLOCK(cmd,blk)						\
-    do {											\
-		unsigned long __blk = (blk);				\
-		cmd[3] = __blk; __blk >>= 8;				\
-		cmd[2] = __blk; __blk >>= 8;				\
-		cmd[1] = (cmd[1] & 0xe0) | (__blk & 0x1f);	\
-	} while(0)
-
-#define CMDSET_LEN(cmd,len)						\
-	do {										\
-		cmd[4] = (len);							\
-	} while(0)
-
-/* ACSI errors (from REQUEST SENSE); There are two tables, one for the
- * old Atari disks and one for SCSI on ACSI disks.
- */
-
-struct acsi_error {
-	unsigned char	code;
-	const char		*text;
-} atari_acsi_errors[] = {
-	{ 0x00, "No error (??)" },
-	{ 0x01, "No index pulses" },
-	{ 0x02, "Seek not complete" },
-	{ 0x03, "Write fault" },
-	{ 0x04, "Drive not ready" },
-	{ 0x06, "No Track 00 signal" },
-	{ 0x10, "ECC error in ID field" },
-	{ 0x11, "Uncorrectable data error" },
-	{ 0x12, "ID field address mark not found" },
-	{ 0x13, "Data field address mark not found" },
-	{ 0x14, "Record not found" },
-	{ 0x15, "Seek error" },
-	{ 0x18, "Data check in no retry mode" },
-	{ 0x19, "ECC error during verify" },
-	{ 0x1a, "Access to bad block" },
-	{ 0x1c, "Unformatted or bad format" },
-	{ 0x20, "Invalid command" },
-	{ 0x21, "Invalid block address" },
-	{ 0x23, "Volume overflow" },
-	{ 0x24, "Invalid argument" },
-	{ 0x25, "Invalid drive number" },
-	{ 0x26, "Byte zero parity check" },
-	{ 0x28, "Cartride changed" },
-	{ 0x2c, "Error count overflow" },
-	{ 0x30, "Controller selftest failed" }
-},
-
-	scsi_acsi_errors[] = {
-	{ 0x00, "No error (??)" },
-	{ 0x01, "Recovered error" },
-	{ 0x02, "Drive not ready" },
-	{ 0x03, "Uncorrectable medium error" },
-	{ 0x04, "Hardware error" },
-	{ 0x05, "Illegal request" },
-	{ 0x06, "Unit attention (Reset or cartridge changed)" },
-	{ 0x07, "Data protection" },
-	{ 0x08, "Blank check" },
-	{ 0x0b, "Aborted Command" },
-	{ 0x0d, "Volume overflow" }
-};
-
-
-
-/***************************** Prototypes *****************************/
-
-static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int
-                        rwflag, int enable);
-static int acsi_reqsense( char *buffer, int targ, int lun);
-static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip);
-static irqreturn_t acsi_interrupt (int irq, void *data);
-static void unexpected_acsi_interrupt( void );
-static void bad_rw_intr( void );
-static void read_intr( void );
-static void write_intr( void);
-static void acsi_times_out( unsigned long dummy );
-static void copy_to_acsibuffer( void );
-static void copy_from_acsibuffer( void );
-static void do_end_requests( void );
-static void do_acsi_request( request_queue_t * );
-static void redo_acsi_request( void );
-static int acsi_ioctl( struct inode *inode, struct file *file, unsigned int
-                       cmd, unsigned long arg );
-static int acsi_open( struct inode * inode, struct file * filp );
-static int acsi_release( struct inode * inode, struct file * file );
-static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag );
-static int acsi_change_blk_size( int target, int lun);
-static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd );
-static int acsi_revalidate (struct gendisk *disk);
-
-/************************* End of Prototypes **************************/
-
-
-DEFINE_TIMER(acsi_timer, acsi_times_out, 0, 0);
-
-
-#ifdef CONFIG_ATARI_SLM
-
-extern int attach_slm( int target, int lun );
-extern int slm_init( void );
-
-#endif
-
-
-
-/***********************************************************************
- *
- *   ACSI primitives
- *
- **********************************************************************/
-
-
-/*
- * The following two functions wait for _IRQ to become Low or High,
- * resp., with a timeout. The 'timeout' parameter is in jiffies
- * (10ms).
- * If the functions are called with timer interrupts on (int level <
- * 6), the timeout is based on the 'jiffies' variable to provide exact
- * timeouts for device probing etc.
- * If interrupts are disabled, the number of tries is based on the
- * 'loops_per_jiffy' variable. A rough estimation is sufficient here...
- */
-
-#define INT_LEVEL													\
-	({	unsigned __sr;												\
-		__asm__ __volatile__ ( "movew	%/sr,%0" : "=dm" (__sr) );	\
-		(__sr >> 8) & 7;											\
-	})
-
-int acsi_wait_for_IRQ( unsigned timeout )
-
-{
-	if (INT_LEVEL < 6) {
-		unsigned long maxjif = jiffies + timeout;
-		while (time_before(jiffies, maxjif))
-			if (!(mfp.par_dt_reg & 0x20)) return( 1 );
-	}
-	else {
-		long tries = loops_per_jiffy / 8 * timeout;
-		while( --tries >= 0 )
-			if (!(mfp.par_dt_reg & 0x20)) return( 1 );
-	}		
-	return( 0 ); /* timeout! */
-}
-
-
-int acsi_wait_for_noIRQ( unsigned timeout )
-
-{
-	if (INT_LEVEL < 6) {
-		unsigned long maxjif = jiffies + timeout;
-		while (time_before(jiffies, maxjif))
-			if (mfp.par_dt_reg & 0x20) return( 1 );
-	}
-	else {
-		long tries = loops_per_jiffy * timeout / 8;
-		while( tries-- >= 0 )
-			if (mfp.par_dt_reg & 0x20) return( 1 );
-	}		
-	return( 0 ); /* timeout! */
-}
-
-static struct timeval start_time;
-
-void
-acsi_delay_start(void)
-{
-	do_gettimeofday(&start_time);
-}
-
-/* wait from acsi_delay_start to now usec (<1E6) usec */
-
-void
-acsi_delay_end(long usec)
-{
-	struct timeval end_time;
-	long deltau,deltas;
-	do_gettimeofday(&end_time);
-	deltau=end_time.tv_usec - start_time.tv_usec;
-	deltas=end_time.tv_sec - start_time.tv_sec;
-	if (deltas > 1 || deltas < 0)
-		return;
-	if (deltas > 0)
-		deltau += 1000*1000;
-	if (deltau >= usec)
-		return;
-	udelay(usec-deltau);
-}
-
-/* acsicmd_dma() sends an ACSI command and sets up the DMA to transfer
- * 'blocks' blocks of 512 bytes from/to 'buffer'.
- * Because the _IRQ signal is used for handshaking the command bytes,
- * the ACSI interrupt has to be disabled in this function. If the end
- * of the operation should be signalled by a real interrupt, it has to be
- * reenabled afterwards.
- */
-
-static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int rwflag, int enable)
-
-{	unsigned long	flags, paddr;
-	int				i;
-
-#ifdef NO_WRITE
-	if (rwflag || *cmd == 0x0a) {
-		printk( "ACSI: Write commands disabled!\n" );
-		return( 0 );
-	}
-#endif
-	
-	rwflag = rwflag ? 0x100 : 0;
-	paddr = virt_to_phys( buffer );
-
-	acsi_delay_end(COMMAND_DELAY);
-	DISABLE_IRQ();
-
-	local_irq_save(flags);
-	/* Low on A1 */
-	dma_wd.dma_mode_status = 0x88 | rwflag;
-	MFPDELAY();
-
-	/* set DMA address */
-	dma_wd.dma_lo = (unsigned char)paddr;
-	paddr >>= 8;
-	MFPDELAY();
-	dma_wd.dma_md = (unsigned char)paddr;
-	paddr >>= 8;
-	MFPDELAY();
-	if (ATARIHW_PRESENT(EXTD_DMA))
-		st_dma_ext_dmahi = (unsigned short)paddr;
-	else
-		dma_wd.dma_hi = (unsigned char)paddr;
-	MFPDELAY();
-	local_irq_restore(flags);
-
-	/* send the command bytes except the last */
-	for( i = 0; i < 5; ++i ) {
-		DMA_LONG_WRITE( *cmd++, 0x8a | rwflag );
-		udelay(20);
-		if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
-	}
-
-	/* Clear FIFO and switch DMA to correct direction */  
-	dma_wd.dma_mode_status = 0x92 | (rwflag ^ 0x100);  
-	MFPDELAY();
-	dma_wd.dma_mode_status = 0x92 | rwflag;
-	MFPDELAY();
-
-	/* How many sectors for DMA */
-	dma_wd.fdc_acces_seccount = blocks;
-	MFPDELAY();
-	
-	/* send last command byte */
-	dma_wd.dma_mode_status = 0x8a | rwflag;
-	MFPDELAY();
-	DMA_LONG_WRITE( *cmd++, 0x0a | rwflag );
-	if (enable)
-		ENABLE_IRQ();
-	udelay(80);
-
-	return( 1 );
-}
-
-
-/*
- * acsicmd_nodma() sends an ACSI command that requires no DMA.
- */
-
-int acsicmd_nodma( const char *cmd, int enable)
-
-{	int	i;
-
-	acsi_delay_end(COMMAND_DELAY);
-	DISABLE_IRQ();
-
-	/* send first command byte */
-	dma_wd.dma_mode_status = 0x88;
-	MFPDELAY();
-	DMA_LONG_WRITE( *cmd++, 0x8a );
-	udelay(20);
-	if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
-
-	/* send the intermediate command bytes */
-	for( i = 0; i < 4; ++i ) {
-		DMA_LONG_WRITE( *cmd++, 0x8a );
-		udelay(20);
-		if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
-	}
-
-	/* send last command byte */
-	DMA_LONG_WRITE( *cmd++, 0x0a );
-	if (enable)
-		ENABLE_IRQ();
-	udelay(80);
-	
-	return( 1 );
-	/* Note that the ACSI interrupt is still disabled after this
-	 * function. If you want to get the IRQ delivered, enable it manually!
-	 */
-}
-
-
-static int acsi_reqsense( char *buffer, int targ, int lun)
-
-{
-	CMDSET_TARG_LUN( reqsense_cmd, targ, lun);
-	if (!acsicmd_dma( reqsense_cmd, buffer, 1, 0, 0 )) return( 0 );
-	if (!acsi_wait_for_IRQ( 10 )) return( 0 );
-	acsi_getstatus();
-	if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
-	if (!acsi_wait_for_IRQ( 10 )) return( 0 );
-	acsi_getstatus();
-	if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
-	if (!acsi_wait_for_IRQ( 10 )) return( 0 );
-	acsi_getstatus();
-	if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
-	if (!acsi_wait_for_IRQ( 10 )) return( 0 );
-	acsi_getstatus();
-	dma_cache_maintenance( virt_to_phys(buffer), 16, 0 );
-	
-	return( 1 );
-}	
-
-
-/*
- * ACSI status phase: get the status byte from the bus
- *
- * I've seen several times that a 0xff status is read, propably due to
- * a timing error. In this case, the procedure is repeated after the
- * next _IRQ edge.
- */
-
-int acsi_getstatus( void )
-
-{	int	status;
-
-	DISABLE_IRQ();
-	for(;;) {
-		if (!acsi_wait_for_IRQ( 100 )) {
-			acsi_delay_start();
-			return( -1 );
-		}
-		dma_wd.dma_mode_status = 0x8a;
-		MFPDELAY();
-		status = dma_wd.fdc_acces_seccount;
-		if (status != 0xff) break;
-#ifdef DEBUG
-		printk("ACSI: skipping 0xff status byte\n" );
-#endif
-		udelay(40);
-		acsi_wait_for_noIRQ( 20 );
-	}
-	dma_wd.dma_mode_status = 0x80;
-	udelay(40);
-	acsi_wait_for_noIRQ( 20 );
-
-	acsi_delay_start();
-	return( status & 0x1f ); /* mask of the device# */
-}
-
-
-#if (defined(CONFIG_ATARI_SLM) || defined(CONFIG_ATARI_SLM_MODULE))
-
-/* Receive data in an extended status phase. Needed by SLM printer. */
-
-int acsi_extstatus( char *buffer, int cnt )
-
-{	int	status;
-
-	DISABLE_IRQ();
-	udelay(80);
-	while( cnt-- > 0 ) {
-		if (!acsi_wait_for_IRQ( 40 )) return( 0 );
-		dma_wd.dma_mode_status = 0x8a;
-		MFPDELAY();
-		status = dma_wd.fdc_acces_seccount;
-		MFPDELAY();
-		*buffer++ = status & 0xff;
-		udelay(40);
-	}
-	return( 1 );
-}
-
-
-/* Finish an extended status phase */
-
-void acsi_end_extstatus( void )
-
-{
-	dma_wd.dma_mode_status = 0x80;
-	udelay(40);
-	acsi_wait_for_noIRQ( 20 );
-	acsi_delay_start();
-}
-
-
-/* Send data in an extended command phase */
-
-int acsi_extcmd( unsigned char *buffer, int cnt )
-
-{
-	while( cnt-- > 0 ) {
-		DMA_LONG_WRITE( *buffer++, 0x8a );
-		udelay(20);
-		if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
-	}
-	return( 1 );
-}
-
-#endif
-
-
-static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip)
-
-{	int atari_err, i, errcode;
-	struct acsi_error *arr;
-
-	atari_err = aip->old_atari_disk;
-	if (atari_err)
-		errcode = errblk[0] & 0x7f;
-	else
-		if ((errblk[0] & 0x70) == 0x70)
-			errcode = errblk[2] & 0x0f;
-		else
-			errcode = errblk[0] & 0x0f;
-	
-	printk( KERN_ERR "ACSI error 0x%02x", errcode );
-
-	if (errblk[0] & 0x80)
-		printk( " for sector %d",
-				((errblk[1] & 0x1f) << 16) |
-				(errblk[2] << 8) | errblk[0] );
-
-	arr = atari_err ? atari_acsi_errors : scsi_acsi_errors;
-	i = atari_err ? sizeof(atari_acsi_errors)/sizeof(*atari_acsi_errors) :
-		            sizeof(scsi_acsi_errors)/sizeof(*scsi_acsi_errors);
-	
-	for( --i; i >= 0; --i )
-		if (arr[i].code == errcode) break;
-	if (i >= 0)
-		printk( ": %s\n", arr[i].text );
-}
-
-/*******************************************************************
- *
- * ACSI interrupt routine
- *   Test, if this is a ACSI interrupt and call the irq handler
- *   Otherwise ignore this interrupt.
- *
- *******************************************************************/
-
-static irqreturn_t acsi_interrupt(int irq, void *data )
-
-{	void (*acsi_irq_handler)(void) = do_acsi;
-
-	do_acsi = NULL;
-	CLEAR_TIMER();
-
-	if (!acsi_irq_handler)
-		acsi_irq_handler = unexpected_acsi_interrupt;
-	acsi_irq_handler();
-	return IRQ_HANDLED;
-}
-
-
-/******************************************************************
- *
- * The Interrupt handlers
- *
- *******************************************************************/
-
-
-static void unexpected_acsi_interrupt( void )
-
-{
-	printk( KERN_WARNING "Unexpected ACSI interrupt\n" );
-}
-
-
-/* This function is called in case of errors. Because we cannot reset
- * the ACSI bus or a single device, there is no other choice than
- * retrying several times :-(
- */
-
-static void bad_rw_intr( void )
-
-{
-	if (!CURRENT)
-		return;
-
-	if (++CURRENT->errors >= MAX_ERRORS)
-		end_request(CURRENT, 0);
-	/* Otherwise just retry */
-}
-
-
-static void read_intr( void )
-
-{	int		status;
-	
-	status = acsi_getstatus();
-	if (status != 0) {
-		struct gendisk *disk = CURRENT->rq_disk;
-		struct acsi_info_struct *aip = disk->private_data;
-		printk(KERN_ERR "%s: ", disk->disk_name);
-		if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun))
-			printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
-		else {
-			acsi_print_error(acsi_buffer, aip);
-			if (CARTRCH_STAT(aip, acsi_buffer))
-				aip->changed = 1;
-		}
-		ENABLE_IRQ();
-		bad_rw_intr();
-		redo_acsi_request();
-		return;
-	}
-
-	dma_cache_maintenance( virt_to_phys(CurrentBuffer), CurrentNSect*512, 0 );
-	if (CurrentBuffer == acsi_buffer)
-		copy_from_acsibuffer();
-
-	do_end_requests();
-	redo_acsi_request();
-}
-
-
-static void write_intr(void)
-
-{	int	status;
-
-	status = acsi_getstatus();
-	if (status != 0) {
-		struct gendisk *disk = CURRENT->rq_disk;
-		struct acsi_info_struct *aip = disk->private_data;
-		printk( KERN_ERR "%s: ", disk->disk_name);
-		if (!acsi_reqsense( acsi_buffer, aip->target, aip->lun))
-			printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
-		else {
-			acsi_print_error(acsi_buffer, aip);
-			if (CARTRCH_STAT(aip, acsi_buffer))
-				aip->changed = 1;
-		}
-		bad_rw_intr();
-		redo_acsi_request();
-		return;
-	}
-
-	do_end_requests();
-	redo_acsi_request();
-}
-
-
-static void acsi_times_out( unsigned long dummy )
-
-{
-	DISABLE_IRQ();
-	if (!do_acsi) return;
-
-	do_acsi = NULL;
-	printk( KERN_ERR "ACSI timeout\n" );
-	if (!CURRENT)
-	    return;
-	if (++CURRENT->errors >= MAX_ERRORS) {
-#ifdef DEBUG
-		printk( KERN_ERR "ACSI: too many errors.\n" );
-#endif
-		end_request(CURRENT, 0);
-	}
-
-	redo_acsi_request();
-}
-
-
-
-/***********************************************************************
- *
- *  Scatter-gather utility functions
- *
- ***********************************************************************/
-
-
-static void copy_to_acsibuffer( void )
-
-{	int					i;
-	char				*src, *dst;
-	struct buffer_head	*bh;
-	
-	src = CURRENT->buffer;
-	dst = acsi_buffer;
-	bh = CURRENT->bh;
-
-	if (!bh)
-		memcpy( dst, src, CurrentNSect*512 );
-	else
-		for( i = 0; i < CurrentNReq; ++i ) {
-			memcpy( dst, src, bh->b_size );
-			dst += bh->b_size;
-			if ((bh = bh->b_reqnext))
-				src = bh->b_data;
-		}
-}
-
-
-static void copy_from_acsibuffer( void )
-
-{	int					i;
-	char				*src, *dst;
-	struct buffer_head	*bh;
-	
-	dst = CURRENT->buffer;
-	src = acsi_buffer;
-	bh = CURRENT->bh;
-
-	if (!bh)
-		memcpy( dst, src, CurrentNSect*512 );
-	else
-		for( i = 0; i < CurrentNReq; ++i ) {
-			memcpy( dst, src, bh->b_size );
-			src += bh->b_size;
-			if ((bh = bh->b_reqnext))
-				dst = bh->b_data;
-		}
-}
-
-
-static void do_end_requests( void )
-
-{	int		i, n;
-
-	if (!CURRENT->bh) {
-		CURRENT->nr_sectors -= CurrentNSect;
-		CURRENT->current_nr_sectors -= CurrentNSect;
-		CURRENT->sector += CurrentNSect;
-		if (CURRENT->nr_sectors == 0)
-			end_request(CURRENT, 1);
-	}
-	else {
-		for( i = 0; i < CurrentNReq; ++i ) {
-			n = CURRENT->bh->b_size >> 9;
-			CURRENT->nr_sectors -= n;
-			CURRENT->current_nr_sectors -= n;
-			CURRENT->sector += n;
-			end_request(CURRENT, 1);
-		}
-	}
-}
-
-
-
-
-/***********************************************************************
- *
- *  do_acsi_request and friends
- *
- ***********************************************************************/
-
-static void do_acsi_request( request_queue_t * q )
-
-{
-	stdma_lock( acsi_interrupt, NULL );
-	redo_acsi_request();
-}
-
-
-static void redo_acsi_request( void )
-{
-	unsigned			block, target, lun, nsect;
-	char 				*buffer;
-	unsigned long		pbuffer;
-	struct buffer_head	*bh;
-	struct gendisk *disk;
-	struct acsi_info_struct *aip;
-
-  repeat:
-	CLEAR_TIMER();
-
-	if (do_acsi)
-		return;
-
-	if (!CURRENT) {
-		do_acsi = NULL;
-		ENABLE_IRQ();
-		stdma_release();
-		return;
-	}
-
-	disk = CURRENT->rq_disk;
-	aip = disk->private_data;
-	if (CURRENT->bh) {
-		if (!CURRENT->bh && !buffer_locked(CURRENT->bh))
-			panic("ACSI: block not locked");
-	}
-
-	block = CURRENT->sector;
-	if (block+CURRENT->nr_sectors >= get_capacity(disk)) {
-#ifdef DEBUG
-		printk( "%s: attempted access for blocks %d...%ld past end of device at block %ld.\n",
-		       disk->disk_name,
-		       block, block + CURRENT->nr_sectors - 1,
-		       get_capacity(disk));
-#endif
-		end_request(CURRENT, 0);
-		goto repeat;
-	}
-	if (aip->changed) {
-		printk( KERN_NOTICE "%s: request denied because cartridge has "
-				"been changed.\n", disk->disk_name);
-		end_request(CURRENT, 0);
-		goto repeat;
-	}
-	
-	target = aip->target;
-	lun    = aip->lun;
-
-	/* Find out how many sectors should be transferred from/to
-	 * consecutive buffers and thus can be done with a single command.
-	 */
-	buffer      = CURRENT->buffer;
-	pbuffer     = virt_to_phys(buffer);
-	nsect       = CURRENT->current_nr_sectors;
-	CurrentNReq = 1;
-
-	if ((bh = CURRENT->bh) && bh != CURRENT->bhtail) {
-		if (!STRAM_ADDR(pbuffer)) {
-			/* If transfer is done via the ACSI buffer anyway, we can
-			 * assemble as much bh's as fit in the buffer.
-			 */
-			while( (bh = bh->b_reqnext) ) {
-				if (nsect + (bh->b_size>>9) > ACSI_BUFFER_SECTORS) break;
-				nsect += bh->b_size >> 9;
-				++CurrentNReq;
-				if (bh == CURRENT->bhtail) break;
-			}
-			buffer = acsi_buffer;
-			pbuffer = phys_acsi_buffer;
-		}
-		else {
-			unsigned long pendadr, pnewadr;
-			pendadr = pbuffer + nsect*512;
-			while( (bh = bh->b_reqnext) ) {
-				pnewadr = virt_to_phys(bh->b_data);
-				if (!STRAM_ADDR(pnewadr) || pendadr != pnewadr) break;
-				nsect += bh->b_size >> 9;
-				pendadr = pnewadr + bh->b_size;
-				++CurrentNReq;
-				if (bh == CURRENT->bhtail) break;
-			}
-		}
-	}
-	else {
-		if (!STRAM_ADDR(pbuffer)) {
-			buffer = acsi_buffer;
-			pbuffer = phys_acsi_buffer;
-			if (nsect > ACSI_BUFFER_SECTORS)
-				nsect = ACSI_BUFFER_SECTORS;
-		}
-	}
-	CurrentBuffer = buffer;
-	CurrentNSect  = nsect;
-
-	if (rq_data_dir(CURRENT) == WRITE) {
-		CMDSET_TARG_LUN( write_cmd, target, lun );
-		CMDSET_BLOCK( write_cmd, block );
-		CMDSET_LEN( write_cmd, nsect );
-		if (buffer == acsi_buffer)
-			copy_to_acsibuffer();
-		dma_cache_maintenance( pbuffer, nsect*512, 1 );
-		do_acsi = write_intr;
-		if (!acsicmd_dma( write_cmd, buffer, nsect, 1, 1)) {
-			do_acsi = NULL;
-			printk( KERN_ERR "ACSI (write): Timeout in command block\n" );
-			bad_rw_intr();
-			goto repeat;
-		}
-		SET_TIMER();
-		return;
-	}
-	if (rq_data_dir(CURRENT) == READ) {
-		CMDSET_TARG_LUN( read_cmd, target, lun );
-		CMDSET_BLOCK( read_cmd, block );
-		CMDSET_LEN( read_cmd, nsect );
-		do_acsi = read_intr;
-		if (!acsicmd_dma( read_cmd, buffer, nsect, 0, 1)) {
-			do_acsi = NULL;
-			printk( KERN_ERR "ACSI (read): Timeout in command block\n" );
-			bad_rw_intr();
-			goto repeat;
-		}
-		SET_TIMER();
-		return;
-	}
-	panic("unknown ACSI command");
-}
-
-
-
-/***********************************************************************
- *
- *  Misc functions: ioctl, open, release, check_change, ...
- *
- ***********************************************************************/
-
-static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
-	struct acsi_info_struct *aip = bdev->bd_disk->private_data;
-
-	/*
-	 * Just fake some geometry here, it's nonsense anyway
-	 * To make it easy, use Adaptec's usual 64/32 mapping
-	 */
-	geo->heads = 64;
-	geo->sectors = 32;
-	geo->cylinders = aip->size >> 11;
-	return 0;
-}
-
-static int acsi_ioctl( struct inode *inode, struct file *file,
-					   unsigned int cmd, unsigned long arg )
-{
-	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct acsi_info_struct *aip = disk->private_data;
-	switch (cmd) {
-	  case SCSI_IOCTL_GET_IDLUN:
-		/* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
-		put_user( aip->target | (aip->lun << 8),
-				  &((Scsi_Idlun *) arg)->dev_id );
-		put_user( 0, &((Scsi_Idlun *) arg)->host_unique_id );
-		return 0;
-	  default:
-		return -EINVAL;
-	}
-}
-
-
-/*
- * Open a device, check for read-only and lock the medium if it is
- * removable.
- *
- * Changes by Martin Rogge, 9th Aug 1995:
- * Check whether check_disk_change (and therefore revalidate_acsidisk)
- * was successful. They fail when there is no medium in the drive.
- *
- * The problem of media being changed during an operation can be 
- * ignored because of the prevent_removal code.
- *
- * Added check for the validity of the device number.
- *
- */
-
-static int acsi_open( struct inode * inode, struct file * filp )
-{
-	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct acsi_info_struct *aip = disk->private_data;
-
-	if (aip->access_count == 0 && aip->removable) {
-#if 0
-		aip->changed = 1;	/* safety first */
-#endif
-		check_disk_change( inode->i_bdev );
-		if (aip->changed)	/* revalidate was not successful (no medium) */
-			return -ENXIO;
-		acsi_prevent_removal(aip, 1);
-	}
-	aip->access_count++;
-
-	if (filp && filp->f_mode) {
-		check_disk_change( inode->i_bdev );
-		if (filp->f_mode & 2) {
-			if (aip->read_only) {
-				acsi_release( inode, filp );
-				return -EROFS;
-			}
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Releasing a block device means we sync() it, so that it can safely
- * be forgotten about...
- */
-
-static int acsi_release( struct inode * inode, struct file * file )
-{
-	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct acsi_info_struct *aip = disk->private_data;
-	if (--aip->access_count == 0 && aip->removable)
-		acsi_prevent_removal(aip, 0);
-	return( 0 );
-}
-
-/*
- * Prevent or allow a media change for removable devices.
- */
-
-static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag)
-{
-	stdma_lock( NULL, NULL );
-	
-	CMDSET_TARG_LUN(pa_med_rem_cmd, aip->target, aip->lun);
-	CMDSET_LEN( pa_med_rem_cmd, flag );
-	
-	if (acsicmd_nodma(pa_med_rem_cmd, 0) && acsi_wait_for_IRQ(3*HZ))
-		acsi_getstatus();
-	/* Do not report errors -- some devices may not know this command. */
-
-	ENABLE_IRQ();
-	stdma_release();
-}
-
-static int acsi_media_change(struct gendisk *disk)
-{
-	struct acsi_info_struct *aip = disk->private_data;
-
-	if (!aip->removable) 
-		return 0;
-
-	if (aip->changed)
-		/* We can be sure that the medium has been changed -- REQUEST
-		 * SENSE has reported this earlier.
-		 */
-		return 1;
-
-	/* If the flag isn't set, make a test by reading block 0.
-	 * If errors happen, it seems to be better to say "changed"...
-	 */
-	stdma_lock( NULL, NULL );
-	CMDSET_TARG_LUN(read_cmd, aip->target, aip->lun);
-	CMDSET_BLOCK( read_cmd, 0 );
-	CMDSET_LEN( read_cmd, 1 );
-	if (acsicmd_dma(read_cmd, acsi_buffer, 1, 0, 0) &&
-	    acsi_wait_for_IRQ(3*HZ)) {
-		if (acsi_getstatus()) {
-			if (acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
-				if (CARTRCH_STAT(aip, acsi_buffer))
-					aip->changed = 1;
-			}
-			else {
-				printk( KERN_ERR "%s: REQUEST SENSE failed in test for "
-				       "medium change; assuming a change\n", disk->disk_name );
-				aip->changed = 1;
-			}
-		}
-	}
-	else {
-		printk( KERN_ERR "%s: Test for medium changed timed out; "
-				"assuming a change\n", disk->disk_name);
-		aip->changed = 1;
-	}
-	ENABLE_IRQ();
-	stdma_release();
-
-	/* Now, after reading a block, the changed status is surely valid. */
-	return aip->changed;
-}
-
-
-static int acsi_change_blk_size( int target, int lun)
-
-{	int i;
-
-	for (i=0; i<12; i++)
-		acsi_buffer[i] = 0;
-
-	acsi_buffer[3] = 8;
-	acsi_buffer[10] = 2;
-	CMDSET_TARG_LUN( modeselect_cmd, target, lun);
-
-	if (!acsicmd_dma( modeselect_cmd, acsi_buffer, 1,1,0) ||
-		!acsi_wait_for_IRQ( 3*HZ ) ||
-		acsi_getstatus() != 0 ) {
-		return(0);
-	}
-	return(1);
-}
-
-
-static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd )
-
-{
-	int page;
-
-	CMDSET_TARG_LUN( modesense_cmd, target, lun );
-	for (page=0; page<4; page++) {
-		modesense_cmd[2] = page;
-		if (!acsicmd_dma( modesense_cmd, acsi_buffer, 1, 0, 0 ) ||
-		    !acsi_wait_for_IRQ( 3*HZ ) ||
-		    acsi_getstatus())
-			continue;
-
-		/* read twice to jump over the second 16-byte border! */
-		udelay(300);
-		if (acsi_wait_for_noIRQ( 20 ) &&
-		    acsicmd_nodma( modesense_cmd, 0 ) &&
-		    acsi_wait_for_IRQ( 3*HZ ) &&
-		    acsi_getstatus() == 0)
-			break;
-	}
-	if (page == 4) {
-		return(0);
-	}
-
-	dma_cache_maintenance( phys_acsi_buffer, sizeof(SENSE_DATA), 0 );
-	*sd = *(SENSE_DATA *)acsi_buffer;
-
-	/* Validity check, depending on type of data */
-	
-	switch( SENSE_TYPE(*sd) ) {
-
-	  case SENSE_TYPE_ATARI:
-		if (CAPACITY(*sd) == 0)
-			goto invalid_sense;
-		break;
-
-	  case SENSE_TYPE_SCSI:
-		if (sd->scsi.descriptor_size != 8)
-			goto invalid_sense;
-		break;
-
-	  case SENSE_TYPE_UNKNOWN:
-
-		printk( KERN_ERR "ACSI target %d, lun %d: Cannot interpret "
-				"sense data\n", target, lun ); 
-		
-	  invalid_sense:
-
-#ifdef DEBUG
-		{	int i;
-		printk( "Mode sense data for ACSI target %d, lun %d seem not valid:",
-				target, lun );
-		for( i = 0; i < sizeof(SENSE_DATA); ++i )
-			printk( "%02x ", (unsigned char)acsi_buffer[i] );
-		printk( "\n" );
-		}
-#endif
-		return( 0 );
-	}
-		
-	return( 1 );
-}
-
-
-
-/*******************************************************************
- *
- *  Initialization
- *
- ********************************************************************/
-
-
-extern struct block_device_operations acsi_fops;
-
-static struct gendisk *acsi_gendisk[MAX_DEV];
-
-#define MAX_SCSI_DEVICE_CODE 10
-
-static const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
-{
- "Direct-Access    ",
- "Sequential-Access",
- "Printer          ",
- "Processor        ",
- "WORM             ",
- "CD-ROM           ",
- "Scanner          ",
- "Optical Device   ",
- "Medium Changer   ",
- "Communications   "
-};
-
-static void print_inquiry(unsigned char *data)
-{
-	int i;
-
-	printk(KERN_INFO "  Vendor: ");
-	for (i = 8; i < 16; i++)
-		{
-	        if (data[i] >= 0x20 && i < data[4] + 5)
-			printk("%c", data[i]);
-		else
-			printk(" ");
-		}
-
-	printk("  Model: ");
-	for (i = 16; i < 32; i++)
-		{
-	        if (data[i] >= 0x20 && i < data[4] + 5)
-			printk("%c", data[i]);
-		else
-			printk(" ");
-		}
-
-	printk("  Rev: ");
-	for (i = 32; i < 36; i++)
-		{
-	        if (data[i] >= 0x20 && i < data[4] + 5)
-			printk("%c", data[i]);
-		else
-			printk(" ");
-		}
-
-	printk("\n");
-
-	i = data[0] & 0x1f;
-
-	printk(KERN_INFO "  Type:   %s ", (i < MAX_SCSI_DEVICE_CODE
-									   ? scsi_device_types[i]
-									   : "Unknown          "));
-	printk("                 ANSI SCSI revision: %02x", data[2] & 0x07);
-	if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)
-	  printk(" CCS\n");
-	else
-	  printk("\n");
-}
-
-
-/* 
- * Changes by Martin Rogge, 9th Aug 1995: 
- * acsi_devinit has been taken out of acsi_geninit, because it needs 
- * to be called from revalidate_acsidisk. The result of request sense 
- * is now checked for DRIVE NOT READY.
- *
- * The structure *aip is only valid when acsi_devinit returns 
- * DEV_SUPPORTED. 
- *
- */
-	
-#define DEV_NONE	0
-#define DEV_UNKNOWN	1
-#define DEV_SUPPORTED	2
-#define DEV_SLM		3
-
-static int acsi_devinit(struct acsi_info_struct *aip)
-{
-	int status, got_inquiry;
-	SENSE_DATA sense;
-	unsigned char reqsense, extsense;
-
-	/*****************************************************************/
-	/* Do a TEST UNIT READY command to test the presence of a device */
-	/*****************************************************************/
-
-	CMDSET_TARG_LUN(tur_cmd, aip->target, aip->lun);
-	if (!acsicmd_nodma(tur_cmd, 0)) {
-		/* timed out -> no device here */
-#ifdef DEBUG_DETECT
-		printk("target %d lun %d: timeout\n", aip->target, aip->lun);
-#endif
-		return DEV_NONE;
-	}
-		
-	/*************************/
-	/* Read the ACSI status. */
-	/*************************/
-
-	status = acsi_getstatus();
-	if (status) {
-		if (status == 0x12) {
-			/* The SLM printer should be the only device that
-			 * responds with the error code in the status byte. In
-			 * correct status bytes, bit 4 is never set.
-			 */
-			printk( KERN_INFO "Detected SLM printer at id %d lun %d\n",
-			       aip->target, aip->lun);
-			return DEV_SLM;
-		}
-		/* ignore CHECK CONDITION, since some devices send a
-		   UNIT ATTENTION */
-		if ((status & 0x1e) != 0x2) {
-#ifdef DEBUG_DETECT
-			printk("target %d lun %d: status %d\n",
-			       aip->target, aip->lun, status);
-#endif
-			return DEV_UNKNOWN;
-		}
-	}
-
-	/*******************************/
-	/* Do a REQUEST SENSE command. */
-	/*******************************/
-
-	if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
-		printk( KERN_WARNING "acsi_reqsense failed\n");
-		acsi_buffer[0] = 0;
-		acsi_buffer[2] = UNIT_ATTENTION;
-	}
-	reqsense = acsi_buffer[0];
-	extsense = acsi_buffer[2] & 0xf;
-	if (status) {
-		if ((reqsense & 0x70) == 0x70) {	/* extended sense */
-			if (extsense != UNIT_ATTENTION &&
-			    extsense != NOT_READY) {
-#ifdef DEBUG_DETECT
-				printk("target %d lun %d: extended sense %d\n",
-				       aip->target, aip->lun, extsense);
-#endif
-				return DEV_UNKNOWN;
-			}
-		}
-		else {
-			if (reqsense & 0x7f) {
-#ifdef DEBUG_DETECT
-				printk("target %d lun %d: sense %d\n",
-				       aip->target, aip->lun, reqsense);
-#endif
-				return DEV_UNKNOWN;
-			}
-		}
-	}
-	else 
-		if (reqsense == 0x4) {	/* SH204 Bug workaround */
-#ifdef DEBUG_DETECT
-			printk("target %d lun %d status=0 sense=4\n",
-			       aip->target, aip->lun);
-#endif
-			return DEV_UNKNOWN;
-		}
-
-	/***********************************************************/
-	/* Do an INQUIRY command to get more infos on this device. */
-	/***********************************************************/
-
-	/* Assume default values */
-	aip->removable = 1;
-	aip->read_only = 0;
-	aip->old_atari_disk = 0;
-	aip->changed = (extsense == NOT_READY);	/* medium inserted? */
-	aip->size = DEFAULT_SIZE;
-	got_inquiry = 0;
-	/* Fake inquiry result for old atari disks */
-	memcpy(acsi_buffer, "\000\000\001\000    Adaptec 40xx"
-	       "                    ", 40);
-	CMDSET_TARG_LUN(inquiry_cmd, aip->target, aip->lun);
-	if (acsicmd_dma(inquiry_cmd, acsi_buffer, 1, 0, 0) &&
-	    acsi_getstatus() == 0) {
-		acsicmd_nodma(inquiry_cmd, 0);
-		acsi_getstatus();
-		dma_cache_maintenance( phys_acsi_buffer, 256, 0 );
-		got_inquiry = 1;
-		aip->removable = !!(acsi_buffer[1] & 0x80);
-	}
-	if (aip->type == NONE)	/* only at boot time */
-		print_inquiry(acsi_buffer);
-	switch(acsi_buffer[0]) {
-	  case TYPE_DISK:
-		aip->type = HARDDISK;
-		break;
-	  case TYPE_ROM:
-		aip->type = CDROM;
-		aip->read_only = 1;
-		break;
-	  default:
-		return DEV_UNKNOWN;
-	}
-	/****************************/
-	/* Do a MODE SENSE command. */
-	/****************************/
-
-	if (!acsi_mode_sense(aip->target, aip->lun, &sense)) {
-		printk( KERN_WARNING "No mode sense data.\n" );
-		return DEV_UNKNOWN;
-	}
-	if ((SECTOR_SIZE(sense) != 512) &&
-	    ((aip->type != CDROM) ||
-	     !acsi_change_blk_size(aip->target, aip->lun) ||
-	     !acsi_mode_sense(aip->target, aip->lun, &sense) ||
-	     (SECTOR_SIZE(sense) != 512))) {
-		printk( KERN_WARNING "Sector size != 512 not supported.\n" );
-		return DEV_UNKNOWN;
-	}
-	/* There are disks out there that claim to have 0 sectors... */
-	if (CAPACITY(sense))
-		aip->size = CAPACITY(sense);	/* else keep DEFAULT_SIZE */
-	if (!got_inquiry && SENSE_TYPE(sense) == SENSE_TYPE_ATARI) {
-		/* If INQUIRY failed and the sense data suggest an old
-		 * Atari disk (SH20x, Megafile), the disk is not removable
-		 */
-		aip->removable = 0;
-		aip->old_atari_disk = 1;
-	}
-	
-	/******************/
-	/* We've done it. */
-	/******************/
-	
-	return DEV_SUPPORTED;
-}
-
-EXPORT_SYMBOL(acsi_delay_start);
-EXPORT_SYMBOL(acsi_delay_end);
-EXPORT_SYMBOL(acsi_wait_for_IRQ);
-EXPORT_SYMBOL(acsi_wait_for_noIRQ);
-EXPORT_SYMBOL(acsicmd_nodma);
-EXPORT_SYMBOL(acsi_getstatus);
-EXPORT_SYMBOL(acsi_buffer);
-EXPORT_SYMBOL(phys_acsi_buffer);
-
-#ifdef CONFIG_ATARI_SLM_MODULE
-void acsi_attach_SLMs( int (*attach_func)( int, int ) );
-
-EXPORT_SYMBOL(acsi_extstatus);
-EXPORT_SYMBOL(acsi_end_extstatus);
-EXPORT_SYMBOL(acsi_extcmd);
-EXPORT_SYMBOL(acsi_attach_SLMs);
-
-/* to remember IDs of SLM devices, SLM module is loaded later
- * (index is target#, contents is lun#, -1 means "no SLM") */
-int SLM_devices[8];
-#endif
-
-static struct block_device_operations acsi_fops = {
-	.owner		= THIS_MODULE,
-	.open		= acsi_open,
-	.release	= acsi_release,
-	.ioctl		= acsi_ioctl,
-	.getgeo		= acsi_getgeo,
-	.media_changed	= acsi_media_change,
-	.revalidate_disk= acsi_revalidate,
-};
-
-#ifdef CONFIG_ATARI_SLM_MODULE
-/* call attach_slm() for each device that is a printer; needed for init of SLM
- * driver as a module, since it's not yet present if acsi.c is inited and thus
- * the bus gets scanned. */
-void acsi_attach_SLMs( int (*attach_func)( int, int ) )
-{
-	int i, n = 0;
-
-	for( i = 0; i < 8; ++i )
-		if (SLM_devices[i] >= 0)
-			n += (*attach_func)( i, SLM_devices[i] );
-	printk( KERN_INFO "Found %d SLM printer(s) total.\n", n );
-}
-#endif /* CONFIG_ATARI_SLM_MODULE */
-
-
-int acsi_init( void )
-{
-	int err = 0;
-	int i, target, lun;
-	struct acsi_info_struct *aip;
-#ifdef CONFIG_ATARI_SLM
-	int n_slm = 0;
-#endif
-	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))
-		return 0;
-	if (register_blkdev(ACSI_MAJOR, "ad")) {
-		err = -EBUSY;
-		goto out1;
-	}
-	if (!(acsi_buffer =
-		  (char *)atari_stram_alloc(ACSI_BUFFER_SIZE, "acsi"))) {
-		err = -ENOMEM;
-		printk( KERN_ERR "Unable to get ACSI ST-Ram buffer.\n" );
-		goto out2;
-	}
-	phys_acsi_buffer = virt_to_phys( acsi_buffer );
-	STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000;
-	
-	acsi_queue = blk_init_queue(do_acsi_request, &acsi_lock);
-	if (!acsi_queue) {
-		err = -ENOMEM;
-		goto out2a;
-	}
-#ifdef CONFIG_ATARI_SLM
-	err = slm_init();
-#endif
-	if (err)
-		goto out3;
-
-	printk( KERN_INFO "Probing ACSI devices:\n" );
-	NDevices = 0;
-#ifdef CONFIG_ATARI_SLM_MODULE
-	for( i = 0; i < 8; ++i )
-		SLM_devices[i] = -1;
-#endif
-	stdma_lock(NULL, NULL);
-
-	for (target = 0; target < 8 && NDevices < MAX_DEV; ++target) {
-		lun = 0;
-		do {
-			aip = &acsi_info[NDevices];
-			aip->type = NONE;
-			aip->target = target;
-			aip->lun = lun;
-			i = acsi_devinit(aip);
-			switch (i) {
-			  case DEV_SUPPORTED:
-				printk( KERN_INFO "Detected ");
-				switch (aip->type) {
-				  case HARDDISK:
-					printk("disk");
-					break;
-				  case CDROM:
-					printk("cdrom");
-					break;
-				  default:
-				}
-				printk(" ad%c at id %d lun %d ",
-				       'a' + NDevices, target, lun);
-				if (aip->removable) 
-					printk("(removable) ");
-				if (aip->read_only) 
-					printk("(read-only) ");
-				if (aip->size == DEFAULT_SIZE)
-					printk(" unkown size, using default ");
-				printk("%ld MByte\n",
-				       (aip->size*512+1024*1024/2)/(1024*1024));
-				NDevices++;
-				break;
-			  case DEV_SLM:
-#ifdef CONFIG_ATARI_SLM
-				n_slm += attach_slm( target, lun );
-				break;
-#endif
-#ifdef CONFIG_ATARI_SLM_MODULE
-				SLM_devices[target] = lun;
-				break;
-#endif
-				/* neither of the above: fall through to unknown device */
-			  case DEV_UNKNOWN:
-				printk( KERN_INFO "Detected unsupported device at "
-						"id %d lun %d\n", target, lun);
-				break;
-			}
-		}
-#ifdef CONFIG_ACSI_MULTI_LUN
-		while (i != DEV_NONE && ++lun < MAX_LUN);
-#else
-		while (0);
-#endif
-	}
-
-	/* reenable interrupt */
-	ENABLE_IRQ();
-	stdma_release();
-
-#ifndef CONFIG_ATARI_SLM
-	printk( KERN_INFO "Found %d ACSI device(s) total.\n", NDevices );
-#else
-	printk( KERN_INFO "Found %d ACSI device(s) and %d SLM printer(s) total.\n",
-			NDevices, n_slm );
-#endif
-	err = -ENOMEM;
-	for( i = 0; i < NDevices; ++i ) {
-		acsi_gendisk[i] = alloc_disk(16);
-		if (!acsi_gendisk[i])
-			goto out4;
-	}
-
-	for( i = 0; i < NDevices; ++i ) {
-		struct gendisk *disk = acsi_gendisk[i];
-		sprintf(disk->disk_name, "ad%c", 'a'+i);
-		aip = &acsi_info[NDevices];
-		disk->major = ACSI_MAJOR;
-		disk->first_minor = i << 4;
-		if (acsi_info[i].type != HARDDISK)
-			disk->minors = 1;
-		disk->fops = &acsi_fops;
-		disk->private_data = &acsi_info[i];
-		set_capacity(disk, acsi_info[i].size);
-		disk->queue = acsi_queue;
-		add_disk(disk);
-	}
-	return 0;
-out4:
-	while (i--)
-		put_disk(acsi_gendisk[i]);
-out3:
-	blk_cleanup_queue(acsi_queue);
-out2a:
-	atari_stram_free( acsi_buffer );
-out2:
-	unregister_blkdev( ACSI_MAJOR, "ad" );
-out1:
-	return err;
-}
-
-
-#ifdef MODULE
-
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	int err;
-
-	if ((err = acsi_init()))
-		return( err );
-	printk( KERN_INFO "ACSI driver loaded as module.\n");
-	return( 0 );
-}
-
-void cleanup_module(void)
-{
-	int i;
-	del_timer( &acsi_timer );
-	blk_cleanup_queue(acsi_queue);
-	atari_stram_free( acsi_buffer );
-
-	if (unregister_blkdev( ACSI_MAJOR, "ad" ) != 0)
-		printk( KERN_ERR "acsi: cleanup_module failed\n");
-
-	for (i = 0; i < NDevices; i++) {
-		del_gendisk(acsi_gendisk[i]);
-		put_disk(acsi_gendisk[i]);
-	}
-}
-#endif
-
-/*
- * This routine is called to flush all partitions and partition tables
- * for a changed scsi disk, and then re-read the new partition table.
- * If we are revalidating a disk because of a media change, then we
- * enter with usage == 0.  If we are using an ioctl, we automatically have
- * usage == 1 (we need an open channel to use an ioctl :-), so this
- * is our limit.
- *
- * Changes by Martin Rogge, 9th Aug 1995: 
- * got cd-roms to work by calling acsi_devinit. There are only two problems:
- * First, if there is no medium inserted, the status will remain "changed".
- * That is no problem at all, but our design of three-valued logic (medium
- * changed, medium not changed, no medium inserted).
- * Secondly the check could fail completely and the drive could deliver
- * nonsensical data, which could mess up the acsi_info[] structure. In
- * that case we try to make the entry safe.
- *
- */
-
-static int acsi_revalidate(struct gendisk *disk)
-{
-	struct acsi_info_struct *aip = disk->private_data;
-	stdma_lock( NULL, NULL );
-	if (acsi_devinit(aip) != DEV_SUPPORTED) {
-		printk( KERN_ERR "ACSI: revalidate failed for target %d lun %d\n",
-		       aip->target, aip->lun);
-		aip->size = 0;
-		aip->read_only = 1;
-		aip->removable = 1;
-		aip->changed = 1; /* next acsi_open will try again... */
-	}
-
-	ENABLE_IRQ();
-	stdma_release();
-	set_capacity(disk, aip->size);
-	return 0;
-}
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 27a1390..6ce8b89 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1363,7 +1363,7 @@
 #ifdef DEBUG
 		printk("fd: sector %ld + %d requested for %s\n",
 		       CURRENT->sector,cnt,
-		       (CURRENT->cmd==READ)?"read":"write");
+		       (rq_data_dir(CURRENT) == READ) ? "read" : "write");
 #endif
 		block = CURRENT->sector + cnt;
 		if ((int)block > floppy->blocks) {
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5acc6c4..0fcad43 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -87,6 +87,7 @@
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3214},
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3215},
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3237},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x323D},
 	{PCI_VENDOR_ID_HP,     PCI_ANY_ID,	PCI_ANY_ID, PCI_ANY_ID,
 		PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
 	{0,}
@@ -119,6 +120,7 @@
 	{0x3214103C, "Smart Array E200i", &SA5_access, 120},
 	{0x3215103C, "Smart Array E200i", &SA5_access, 120},
 	{0x3237103C, "Smart Array E500", &SA5_access, 512},
+	{0x323D103C, "Smart Array P700m", &SA5_access, 512},
 	{0xFFFF103C, "Unknown Smart Array", &SA5_access, 120},
 };
 
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 0ed5470..4503290 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -74,6 +74,7 @@
 #include <linux/highmem.h>
 #include <linux/gfp.h>
 #include <linux/kthread.h>
+#include <linux/splice.h>
 
 #include <asm/uaccess.h>
 
@@ -401,50 +402,73 @@
 };
 
 static int
-lo_read_actor(read_descriptor_t *desc, struct page *page,
-	      unsigned long offset, unsigned long size)
+lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+		struct splice_desc *sd)
 {
-	unsigned long count = desc->count;
-	struct lo_read_data *p = desc->arg.data;
+	struct lo_read_data *p = sd->u.data;
 	struct loop_device *lo = p->lo;
+	struct page *page = buf->page;
 	sector_t IV;
+	size_t size;
+	int ret;
 
-	IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
+	ret = buf->ops->confirm(pipe, buf);
+	if (unlikely(ret))
+		return ret;
 
-	if (size > count)
-		size = count;
+	IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) +
+							(buf->offset >> 9);
+	size = sd->len;
+	if (size > p->bsize)
+		size = p->bsize;
 
-	if (lo_do_transfer(lo, READ, page, offset, p->page, p->offset, size, IV)) {
-		size = 0;
+	if (lo_do_transfer(lo, READ, page, buf->offset, p->page, p->offset, size, IV)) {
 		printk(KERN_ERR "loop: transfer error block %ld\n",
 		       page->index);
-		desc->error = -EINVAL;
+		size = -EINVAL;
 	}
 
 	flush_dcache_page(p->page);
 
-	desc->count = count - size;
-	desc->written += size;
-	p->offset += size;
+	if (size > 0)
+		p->offset += size;
+
 	return size;
 }
 
 static int
+lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
+{
+	return __splice_from_pipe(pipe, sd, lo_splice_actor);
+}
+
+static int
 do_lo_receive(struct loop_device *lo,
 	      struct bio_vec *bvec, int bsize, loff_t pos)
 {
 	struct lo_read_data cookie;
+	struct splice_desc sd;
 	struct file *file;
-	int retval;
+	long retval;
 
 	cookie.lo = lo;
 	cookie.page = bvec->bv_page;
 	cookie.offset = bvec->bv_offset;
 	cookie.bsize = bsize;
+
+	sd.len = 0;
+	sd.total_len = bvec->bv_len;
+	sd.flags = 0;
+	sd.pos = pos;
+	sd.u.data = &cookie;
+
 	file = lo->lo_backing_file;
-	retval = file->f_op->sendfile(file, &pos, bvec->bv_len,
-			lo_read_actor, &cookie);
-	return (retval < 0)? retval: 0;
+	retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);
+
+	if (retval < 0)
+		return retval;
+
+	return 0;
 }
 
 static int
@@ -679,8 +703,8 @@
 	if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
 		goto out_putf;
 
-	/* new backing store needs to support loop (eg sendfile) */
-	if (!inode->i_fop->sendfile)
+	/* new backing store needs to support loop (eg splice_read) */
+	if (!inode->i_fop->splice_read)
 		goto out_putf;
 
 	/* size of the new backing store needs to be the same */
@@ -760,7 +784,7 @@
 		 * If we can't read - sorry. If we only can't write - well,
 		 * it's going to be read-only.
 		 */
-		if (!file->f_op->sendfile)
+		if (!file->f_op->splice_read)
 			goto out_putf;
 		if (aops->prepare_write && aops->commit_write)
 			lo_flags |= LO_FLAGS_USE_AOPS;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 069ae39..c575fb1 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -416,7 +416,7 @@
 /*
  * We always wait for result of write, for now. It would be nice to make it optional
  * in future
- * if ((req->cmd == WRITE) && (lo->flags & NBD_WRITE_NOCHK)) 
+ * if ((rq_data_dir(req) == WRITE) && (lo->flags & NBD_WRITE_NOCHK))
  *   { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
  */
 
diff --git a/drivers/cdrom/Kconfig b/drivers/cdrom/Kconfig
deleted file mode 100644
index 4b12e90..0000000
--- a/drivers/cdrom/Kconfig
+++ /dev/null
@@ -1,213 +0,0 @@
-#
-# CDROM driver configuration
-#
-
-menu "Old CD-ROM drivers (not SCSI, not IDE)"
-	depends on ISA && BLOCK
-
-config CD_NO_IDESCSI
-	bool "Support non-SCSI/IDE/ATAPI CDROM drives"
-	---help---
-	  If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y
-	  here, otherwise N. Read the CD-ROM-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  Note that the answer to this question doesn't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
-	  the questions about these CD-ROM drives. If you are unsure what you
-	  have, say Y and find out whether you have one of the following
-	  drives.
-
-	  For each of these drivers, a <file:Documentation/cdrom/{driver_name}>
-	  exists. Especially in cases where you do not know exactly which kind
-	  of drive you have you should read there. Most of these drivers use a
-	  file drivers/cdrom/{driver_name}.h where you can define your
-	  interface parameters and switch some internal goodies.
-
-	  To compile these CD-ROM drivers as a module, choose M instead of Y.
-
-	  If you want to use any of these CD-ROM drivers, you also have to
-	  answer Y or M to "ISO 9660 CD-ROM file system support" below (this
-	  answer will get "defaulted" for you if you enable any of the Linux
-	  CD-ROM drivers).
-
-config AZTCD
-	tristate "Aztech/Orchid/Okano/Wearnes/TXC/CyDROM  CDROM support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  This is your driver if you have an Aztech CDA268-01A, Orchid
-	  CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCD-ROM CR520 or
-	  CR540 CD-ROM drive.  This driver -- just like all these CD-ROM
-	  drivers -- is NOT for CD-ROM drives with IDE/ATAPI interfaces, such
-	  as Aztech CDA269-031SE. Please read the file
-	  <file:Documentation/cdrom/aztcd>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called aztcd.
-
-config GSCD
-	tristate "Goldstar R420 CDROM support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  If this is your CD-ROM drive, say Y here.  As described in the file
-	  <file:Documentation/cdrom/gscd>, you might have to change a setting
-	  in the file <file:drivers/cdrom/gscd.h> before compiling the
-	  kernel.  Please read the file <file:Documentation/cdrom/gscd>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called gscd.
-
-config SBPCD
-	tristate "Matsushita/Panasonic/Creative, Longshine, TEAC CDROM support"
-	depends on CD_NO_IDESCSI && BROKEN_ON_SMP
-	---help---
-	  This driver supports most of the drives which use the Panasonic or
-	  Sound Blaster interface.  Please read the file
-	  <file:Documentation/cdrom/sbpcd>.
-
-	  The Matsushita CR-521, CR-522, CR-523, CR-562, CR-563 drives
-	  (sometimes labeled "Creative"), the Creative Labs CD200, the
-	  Longshine LCS-7260, the "IBM External ISA CD-ROM" (in fact a CR-56x
-	  model), the TEAC CD-55A fall under this category.  Some other
-	  "electrically compatible" drives (Vertos, Genoa, some Funai models)
-	  are currently not supported; for the Sanyo H94A drive currently a
-	  separate driver (asked later) is responsible.  Most drives have a
-	  uniquely shaped faceplate, with a caddyless motorized drawer, but
-	  without external brand markings.  The older CR-52x drives have a
-	  caddy and manual loading/eject, but still no external markings.  The
-	  driver is able to do an extended auto-probing for interface
-	  addresses and drive types; this can help to find facts in cases you
-	  are not sure, but can consume some time during the boot process if
-	  none of the supported drives gets found.  Once your drive got found,
-	  you should enter the reported parameters into
-	  <file:drivers/cdrom/sbpcd.h> and set "DISTRIBUTION 0" there.
-
-	  This driver can support up to four CD-ROM controller cards, and each
-	  card can support up to four CD-ROM drives; if you say Y here, you
-	  will be asked how many controller cards you have.  If compiled as a
-	  module, only one controller card (but with up to four drives) is
-	  usable.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called sbpcd.
-
-config MCDX
-	tristate "Mitsumi CDROM support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  Use this driver if you want to be able to use your Mitsumi LU-005,
-	  FX-001 or FX-001D CD-ROM drive.
-
-	  Please read the file <file:Documentation/cdrom/mcdx>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called mcdx.
-
-config OPTCD
-	tristate "Optics Storage DOLPHIN 8000AT CDROM support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  This is the driver for the 'DOLPHIN' drive with a 34-pin Sony
-	  compatible interface. It also works with the Lasermate CR328A. If
-	  you have one of those, say Y. This driver does not work for the
-	  Optics Storage 8001 drive; use the IDE-ATAPI CD-ROM driver for that
-	  one. Please read the file <file:Documentation/cdrom/optcd>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called optcd.
-
-config CM206
-	tristate "Philips/LMS CM206 CDROM support"
-	depends on CD_NO_IDESCSI && BROKEN_ON_SMP
-	---help---
-	  If you have a Philips/LMS CD-ROM drive cm206 in combination with a
-	  cm260 host adapter card, say Y here. Please also read the file
-	  <file:Documentation/cdrom/cm206>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called cm206.
-
-config SJCD
-	tristate "Sanyo CDR-H94A CDROM support"
-	depends on CD_NO_IDESCSI
-	help
-	  If this is your CD-ROM drive, say Y here and read the file
-	  <file:Documentation/cdrom/sjcd>. You should then also say Y or M to
-	  "ISO 9660 CD-ROM file system support" below, because that's the
-	  file system used on CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called sjcd.
-
-config ISP16_CDI
-	tristate "ISP16/MAD16/Mozart soft configurable cdrom interface support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  These are sound cards with built-in cdrom interfaces using the OPTi
-	  82C928 or 82C929 chips. Say Y here to have them detected and
-	  possibly configured at boot time. In addition, You'll have to say Y
-	  to a driver for the particular cdrom drive you have attached to the
-	  card. Read <file:Documentation/cdrom/isp16> for details.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called isp16.
-
-config CDU31A
-	tristate "Sony CDU31A/CDU33A CDROM support"
-	depends on CD_NO_IDESCSI && BROKEN_ON_SMP
-	---help---
-	  These CD-ROM drives have a spring-pop-out caddyless drawer, and a
-	  rectangular green LED centered beneath it.  NOTE: these CD-ROM
-	  drives will not be auto detected by the kernel at boot time; you
-	  have to provide the interface address as an option to the kernel at
-	  boot time as described in <file:Documentation/cdrom/cdu31a> or fill
-	  in your parameters into <file:drivers/cdrom/cdu31a.c>.  Try "man
-	  bootparam" or see the documentation of your boot loader (lilo or
-	  loadlin) about how to pass options to the kernel.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called cdu31a.
-
-config CDU535
-	tristate "Sony CDU535 CDROM support"
-	depends on CD_NO_IDESCSI
-	---help---
-	  This is the driver for the older Sony CDU-535 and CDU-531 CD-ROM
-	  drives. Please read the file <file:Documentation/cdrom/sonycd535>.
-
-	  If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
-	  file system support" below, because that's the file system used on
-	  CD-ROMs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called sonycd535.
-
-endmenu
diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile
index d1d1e5a..774c180 100644
--- a/drivers/cdrom/Makefile
+++ b/drivers/cdrom/Makefile
@@ -10,14 +10,4 @@
 obj-$(CONFIG_PARIDE_PCD)	+=		cdrom.o
 obj-$(CONFIG_CDROM_PKTCDVD)	+=		cdrom.o
 
-obj-$(CONFIG_AZTCD)		+= aztcd.o
-obj-$(CONFIG_CDU31A)		+= cdu31a.o     cdrom.o
-obj-$(CONFIG_CM206)		+= cm206.o      cdrom.o
-obj-$(CONFIG_GSCD)		+= gscd.o
-obj-$(CONFIG_ISP16_CDI)		+= isp16.o
-obj-$(CONFIG_MCDX)		+= mcdx.o       cdrom.o
-obj-$(CONFIG_OPTCD)		+= optcd.o
-obj-$(CONFIG_SBPCD)		+= sbpcd.o      cdrom.o
-obj-$(CONFIG_SJCD)		+= sjcd.o
-obj-$(CONFIG_CDU535)		+= sonycd535.o
 obj-$(CONFIG_VIOCD)		+= viocd.o      cdrom.o
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
deleted file mode 100644
index 1f9fb7a..0000000
--- a/drivers/cdrom/aztcd.c
+++ /dev/null
@@ -1,2492 +0,0 @@
-#define AZT_VERSION "2.60"
-
-/*      $Id: aztcd.c,v 2.60 1997/11/29 09:51:19 root Exp root $
-	linux/drivers/block/aztcd.c - Aztech CD268 CDROM driver
-
-	Copyright (C) 1994-98 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de)
-
-	based on Mitsumi CDROM driver by  Martin Hariss and preworks by
-	Eberhard Moenkeberg; contains contributions by Joe Nardone and Robby 
-	Schirmer.
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2, or (at your option)
-	any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-	HISTORY
-	V0.0    Adaption to Aztech CD268-01A Version 1.3
-		Version is PRE_ALPHA, unresolved points:
-		1. I use busy wait instead of timer wait in STEN_LOW,DTEN_LOW
-		   thus driver causes CPU overhead and is very slow 
-		2. could not find a way to stop the drive, when it is
-		   in data read mode, therefore I had to set
-		   msf.end.min/sec/frame to 0:0:1 (in azt_poll); so only one
-		   frame can be read in sequence, this is also the reason for
-		3. getting 'timeout in state 4' messages, but nevertheless
-		   it works
-		W.Zimmermann, Oct. 31, 1994
-	V0.1    Version is ALPHA, problems #2 and #3 resolved.  
-		W.Zimmermann, Nov. 3, 1994
-	V0.2    Modification to some comments, debugging aids for partial test
-		with Borland C under DOS eliminated. Timer interrupt wait 
-		STEN_LOW_WAIT additionally to busy wait for STEN_LOW implemented; 
-		use it only for the 'slow' commands (ACMD_GET_Q_CHANNEL, ACMD_
-		SEEK_TO_LEAD_IN), all other commands are so 'fast', that busy 
-		waiting seems better to me than interrupt rescheduling.
-		Besides that, when used in the wrong place, STEN_LOW_WAIT causes
-		kernel panic.
-		In function aztPlay command ACMD_PLAY_AUDIO added, should make
-		audio functions work. The Aztech drive needs different commands
-		to read data tracks and play audio tracks.
-		W.Zimmermann, Nov. 8, 1994
-	V0.3    Recognition of missing drive during boot up improved (speeded up).
-		W.Zimmermann, Nov. 13, 1994
-	V0.35   Rewrote the control mechanism in azt_poll (formerly mcd_poll) 
-		including removal of all 'goto' commands. :-); 
-		J. Nardone, Nov. 14, 1994
-	V0.4    Renamed variables and constants to 'azt' instead of 'mcd'; had
-		to make some "compatibility" defines in azt.h; please note,
-		that the source file was renamed to azt.c, the include file to
-		azt.h                
-		Speeded up drive recognition during init (will be a little bit 
-		slower than before if no drive is installed!); suggested by
-		Robby Schirmer.
-		read_count declared volatile and set to AZT_BUF_SIZ to make
-		drive faster (now 300kB/sec, was 60kB/sec before, measured
-		by 'time dd if=/dev/cdrom of=/dev/null bs=2048 count=4096';
-		different AZT_BUF_SIZes were test, above 16 no further im-
-		provement seems to be possible; suggested by E.Moenkeberg.
-		W.Zimmermann, Nov. 18, 1994
-	V0.42   Included getAztStatus command in GetQChannelInfo() to allow
-		reading Q-channel info on audio disks, if drive is stopped, 
-		and some other bug fixes in the audio stuff, suggested by 
-		Robby Schirmer.
-		Added more ioctls (reading data in mode 1 and mode 2).
-		Completely removed the old azt_poll() routine.
-		Detection of ORCHID CDS-3110 in aztcd_init implemented.
-		Additional debugging aids (see the readme file).
-		W.Zimmermann, Dec. 9, 1994  
-	V0.50   Autodetection of drives implemented.
-		W.Zimmermann, Dec. 12, 1994
-	V0.52   Prepared for including in the standard kernel, renamed most
-		variables to contain 'azt', included autoconf.h
-		W.Zimmermann, Dec. 16, 1994        
-	V0.6    Version for being included in the standard Linux kernel.
-		Renamed source and header file to aztcd.c and aztcd.h
-		W.Zimmermann, Dec. 24, 1994
-	V0.7    Changed VERIFY_READ to VERIFY_WRITE in aztcd_ioctl, case
-		CDROMREADMODE1 and CDROMREADMODE2; bug fix in the ioctl,
-		which causes kernel crashes when playing audio, changed 
-		include-files (config.h instead of autoconf.h, removed
-		delay.h)
-		W.Zimmermann, Jan. 8, 1995
-	V0.72   Some more modifications for adaption to the standard kernel.
-		W.Zimmermann, Jan. 16, 1995
-        V0.80   aztcd is now part of the standard kernel since version 1.1.83.
-                Modified the SET_TIMER and CLEAR_TIMER macros to comply with
-                the new timer scheme.
-                W.Zimmermann, Jan. 21, 1995
-        V0.90   Included CDROMVOLCTRL, but with my Aztech drive I can only turn
-                the channels on and off. If it works better with your drive, 
-                please mail me. Also implemented ACMD_CLOSE for CDROMSTART.
-                W.Zimmermann, Jan. 24, 1995
-        V1.00   Implemented close and lock tray commands. Patches supplied by
-		Frank Racis        
-                Added support for loadable MODULEs, so aztcd can now also be
-                loaded by insmod and removed by rmmod during run time
-                Werner Zimmermann, Mar. 24, 95
-        V1.10   Implemented soundcard configuration for Orchid CDS-3110 drives
-                connected to Soundwave32 cards. Release for LST 2.1.
-                (still experimental)
-                Werner Zimmermann, May 8, 95
-        V1.20   Implemented limited support for DOSEMU0.60's cdrom.c. Now it works, but
-                sometimes DOSEMU may hang for 30 seconds or so. A fully functional ver-
-                sion needs an update of Dosemu0.60's cdrom.c, which will come with the 
-                next revision of Dosemu.
-                Also Soundwave32 support now works.
-                Werner Zimmermann, May 22, 95
-	V1.30   Auto-eject feature. Inspired by Franc Racis (racis@psu.edu)
-	        Werner Zimmermann, July 4, 95
-	V1.40   Started multisession support. Implementation copied from mcdx.c
-	        by Heiko Schlittermann. Not tested yet.
-	        Werner Zimmermann, July 15, 95
-        V1.50   Implementation of ioctl CDROMRESET, continued multisession, began
-                XA, but still untested. Heavy modifications to drive status de-
-                tection.
-                Werner Zimmermann, July 25, 95
-        V1.60   XA support now should work. Speeded up drive recognition in cases, 
-                where no drive is installed.
-                Werner Zimmermann, August 8, 1995
-        V1.70   Multisession support now is completed, but there is still not 
-                enough testing done. If you can test it, please contact me. For
-                details please read Documentation/cdrom/aztcd
-                Werner Zimmermann, August 19, 1995
-        V1.80   Modification to suit the new kernel boot procedure introduced
-                with kernel 1.3.33. Will definitely not work with older kernels.
-                Programming done by Linus himself.
-                Werner Zimmermann, October 11, 1995
-	V1.90   Support for Conrad TXC drives, thank's to Jochen Kunz and Olaf Kaluza.
-	        Werner Zimmermann, October 21, 1995
-        V2.00   Changed #include "blk.h" to <linux/blk.h> as the directory
-                structure was changed. README.aztcd is now /usr/src/docu-
-                mentation/cdrom/aztcd
-                Werner Zimmermann, November 10, 95
-        V2.10   Started to modify azt_poll to prevent reading beyond end of
-                tracks.
-                Werner Zimmermann, December 3, 95
-        V2.20   Changed some comments
-                Werner Zimmermann, April 1, 96
-        V2.30   Implemented support for CyCDROM CR520, CR940, Code for CR520 
-        	delivered by H.Berger with preworks by E.Moenkeberg.
-                Werner Zimmermann, April 29, 96
-        V2.40   Reorganized the placement of functions in the source code file
-                to reflect the layered approach; did not actually change code
-                Werner Zimmermann, May 1, 96
-        V2.50   Heiko Eissfeldt suggested to remove some VERIFY_READs in 
-                aztcd_ioctl; check_aztcd_media_change modified 
-                Werner Zimmermann, May 16, 96       
-	V2.60   Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize
-                Adaption to linux kernel > 2.1.0
-		Werner Zimmermann, Nov 29, 97
-		
-        November 1999 -- Make kernel-parameter implementation work with 2.3.x 
-	                 Removed init_module & cleanup_module in favor of 
-			 module_init & module_exit.
-			 Torben Mathiasen <tmm@image.dk>
-*/
-
-#include <linux/blkdev.h>
-#include "aztcd.h"
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/major.h>
-
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <asm/uaccess.h>
-
-/*###########################################################################
-  Defines
-  ###########################################################################
-*/
-
-#define MAJOR_NR AZTECH_CDROM_MAJOR
-#define QUEUE (azt_queue)
-#define CURRENT elv_next_request(azt_queue)
-#define SET_TIMER(func, jifs)   delay_timer.expires = jiffies + (jifs); \
-                                delay_timer.function = (void *) (func); \
-                                add_timer(&delay_timer);
-
-#define CLEAR_TIMER             del_timer(&delay_timer);
-
-#define RETURNM(message,value) {printk("aztcd: Warning: %s failed\n",message);\
-                                return value;}
-#define RETURN(message)        {printk("aztcd: Warning: %s failed\n",message);\
-                                return;}
-
-/* Macros to switch the IDE-interface to the slave device and back to the master*/
-#define SWITCH_IDE_SLAVE  outb_p(0xa0,azt_port+6); \
-	                  outb_p(0x10,azt_port+6); \
-	                  outb_p(0x00,azt_port+7); \
-	                  outb_p(0x10,azt_port+6);
-#define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6);
-
-
-#if 0
-#define AZT_TEST
-#define AZT_TEST1		/* <int-..> */
-#define AZT_TEST2		/* do_aztcd_request */
-#define AZT_TEST3		/* AZT_S_state */
-#define AZT_TEST4		/* QUICK_LOOP-counter */
-#define AZT_TEST5		/* port(1) state */
-#define AZT_DEBUG
-#define AZT_DEBUG_MULTISESSION
-#endif
-
-static struct request_queue *azt_queue;
-
-static int current_valid(void)
-{
-        return CURRENT &&
-		CURRENT->cmd == READ &&
-		CURRENT->sector != -1;
-}
-
-#define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA)
-#define AZT_BUF_SIZ 16
-
-#define READ_TIMEOUT 3000
-
-#define azt_port aztcd		/*needed for the modutils */
-
-/*##########################################################################
-  Type Definitions
-  ##########################################################################
-*/
-enum azt_state_e { AZT_S_IDLE,	/* 0 */
-	AZT_S_START,		/* 1 */
-	AZT_S_MODE,		/* 2 */
-	AZT_S_READ,		/* 3 */
-	AZT_S_DATA,		/* 4 */
-	AZT_S_STOP,		/* 5 */
-	AZT_S_STOPPING		/* 6 */
-};
-enum azt_read_modes { AZT_MODE_0,	/*read mode for audio disks, not supported by Aztech firmware */
-	AZT_MODE_1,		/*read mode for normal CD-ROMs */
-	AZT_MODE_2		/*read mode for XA CD-ROMs */
-};
-
-/*##########################################################################
-  Global Variables
-  ##########################################################################
-*/
-static int aztPresent = 0;
-
-static volatile int azt_transfer_is_active = 0;
-
-static char azt_buf[CD_FRAMESIZE_RAW * AZT_BUF_SIZ];	/*buffer for block size conversion */
-#if AZT_PRIVATE_IOCTLS
-static char buf[CD_FRAMESIZE_RAW];	/*separate buffer for the ioctls */
-#endif
-
-static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn;
-static volatile int azt_buf_in, azt_buf_out = -1;
-static volatile int azt_error = 0;
-static int azt_open_count = 0;
-static volatile enum azt_state_e azt_state = AZT_S_IDLE;
-#ifdef AZT_TEST3
-static volatile enum azt_state_e azt_state_old = AZT_S_STOP;
-static volatile int azt_st_old = 0;
-#endif
-static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1;
-
-static int azt_mode = -1;
-static volatile int azt_read_count = 1;
-
-static int azt_port = AZT_BASE_ADDR;
-
-module_param(azt_port, int, 0);
-
-static int azt_port_auto[16] = AZT_BASE_AUTO;
-
-static char azt_cont = 0;
-static char azt_init_end = 0;
-static char azt_auto_eject = AZT_AUTO_EJECT;
-
-static int AztTimeout, AztTries;
-static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
-static DEFINE_TIMER(delay_timer, NULL, 0, 0);
-
-static struct azt_DiskInfo DiskInfo;
-static struct azt_Toc Toc[MAX_TRACKS];
-static struct azt_Play_msf azt_Play;
-
-static int aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-static char aztDiskChanged = 1;
-static char aztTocUpToDate = 0;
-
-static unsigned char aztIndatum;
-static unsigned long aztTimeOutCount;
-static int aztCmd = 0;
-
-static DEFINE_SPINLOCK(aztSpin);
-
-/*###########################################################################
-   Function Prototypes
-  ###########################################################################
-*/
-/* CDROM Drive Low Level I/O Functions */
-static void aztStatTimer(void);
-
-/* CDROM Drive Command Functions */
-static int aztGetDiskInfo(void);
-#if AZT_MULTISESSION
-static int aztGetMultiDiskInfo(void);
-#endif
-static int aztGetToc(int multi);
-
-/* Kernel Interface Functions */
-static int check_aztcd_media_change(struct gendisk *disk);
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
-		       unsigned long arg);
-static int aztcd_open(struct inode *ip, struct file *fp);
-static int aztcd_release(struct inode *inode, struct file *file);
-
-static struct block_device_operations azt_fops = {
-	.owner		= THIS_MODULE,
-	.open		= aztcd_open,
-	.release	= aztcd_release,
-	.ioctl		= aztcd_ioctl,
-	.media_changed	= check_aztcd_media_change,
-};
-
-/* Aztcd State Machine: Controls Drive Operating State */
-static void azt_poll(void);
-
-/* Miscellaneous support functions */
-static void azt_hsg2msf(long hsg, struct msf *msf);
-static long azt_msf2hsg(struct msf *mp);
-static void azt_bin2bcd(unsigned char *p);
-static int azt_bcd2bin(unsigned char bcd);
-
-/*##########################################################################
-  CDROM Drive Low Level I/O Functions
-  ##########################################################################
-*/
-/* Macros for the drive hardware interface handshake, these macros use
-   busy waiting */
-/* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/
-# define OP_OK op_ok()
-static void op_ok(void)
-{
-	aztTimeOutCount = 0;
-	do {
-		aztIndatum = inb(DATA_PORT);
-		aztTimeOutCount++;
-		if (aztTimeOutCount >= AZT_TIMEOUT) {
-			printk("aztcd: Error Wait OP_OK\n");
-			break;
-		}
-	} while (aztIndatum != AFL_OP_OK);
-}
-
-/* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/
-#if 0
-# define PA_OK pa_ok()
-static void pa_ok(void)
-{
-	aztTimeOutCount = 0;
-	do {
-		aztIndatum = inb(DATA_PORT);
-		aztTimeOutCount++;
-		if (aztTimeOutCount >= AZT_TIMEOUT) {
-			printk("aztcd: Error Wait PA_OK\n");
-			break;
-		}
-	} while (aztIndatum != AFL_PA_OK);
-}
-#endif
-
-/* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/
-# define STEN_LOW  sten_low()
-static void sten_low(void)
-{
-	aztTimeOutCount = 0;
-	do {
-		aztIndatum = inb(STATUS_PORT);
-		aztTimeOutCount++;
-		if (aztTimeOutCount >= AZT_TIMEOUT) {
-			if (azt_init_end)
-				printk
-				    ("aztcd: Error Wait STEN_LOW commands:%x\n",
-				     aztCmd);
-			break;
-		}
-	} while (aztIndatum & AFL_STATUS);
-}
-
-/* Wait for DTEN=Low = handshake signal 'Data available'*/
-# define DTEN_LOW dten_low()
-static void dten_low(void)
-{
-	aztTimeOutCount = 0;
-	do {
-		aztIndatum = inb(STATUS_PORT);
-		aztTimeOutCount++;
-		if (aztTimeOutCount >= AZT_TIMEOUT) {
-			printk("aztcd: Error Wait DTEN_OK\n");
-			break;
-		}
-	} while (aztIndatum & AFL_DATA);
-}
-
-/* 
- * Macro for timer wait on STEN=Low, should only be used for 'slow' commands;
- * may cause kernel panic when used in the wrong place
-*/
-#define STEN_LOW_WAIT   statusAzt()
-static void statusAzt(void)
-{
-	AztTimeout = AZT_STATUS_DELAY;
-	SET_TIMER(aztStatTimer, HZ / 100);
-	sleep_on(&azt_waitq);
-	if (AztTimeout <= 0)
-		printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",
-		       aztCmd);
-	return;
-}
-
-static void aztStatTimer(void)
-{
-	if (!(inb(STATUS_PORT) & AFL_STATUS)) {
-		wake_up(&azt_waitq);
-		return;
-	}
-	AztTimeout--;
-	if (AztTimeout <= 0) {
-		wake_up(&azt_waitq);
-		printk("aztcd: Error aztStatTimer: Timeout\n");
-		return;
-	}
-	SET_TIMER(aztStatTimer, HZ / 100);
-}
-
-/*##########################################################################
-  CDROM Drive Command Functions
-  ##########################################################################
-*/
-/* 
- * Send a single command, return -1 on error, else 0
-*/
-static int aztSendCmd(int cmd)
-{
-	unsigned char data;
-	int retry;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: Executing command %x\n", cmd);
-#endif
-
-	if ((azt_port == 0x1f0) || (azt_port == 0x170))
-		SWITCH_IDE_SLAVE;	/*switch IDE interface to slave configuration */
-
-	aztCmd = cmd;
-	outb(POLLED, MODE_PORT);
-	do {
-		if (inb(STATUS_PORT) & AFL_STATUS)
-			break;
-		inb(DATA_PORT);	/* if status left from last command, read and */
-	} while (1);		/* discard it */
-	do {
-		if (inb(STATUS_PORT) & AFL_DATA)
-			break;
-		inb(DATA_PORT);	/* if data left from last command, read and */
-	} while (1);		/* discard it */
-	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-		outb((unsigned char) cmd, CMD_PORT);
-		STEN_LOW;
-		data = inb(DATA_PORT);
-		if (data == AFL_OP_OK) {
-			return 0;
-		}		/*OP_OK? */
-		if (data == AFL_OP_ERR) {
-			STEN_LOW;
-			data = inb(DATA_PORT);
-			printk
-			    ("### Error 1 aztcd: aztSendCmd %x  Error Code %x\n",
-			     cmd, data);
-		}
-	}
-	if (retry >= AZT_RETRY_ATTEMPTS) {
-		printk("### Error 2 aztcd: aztSendCmd %x \n", cmd);
-		azt_error = 0xA5;
-	}
-	RETURNM("aztSendCmd", -1);
-}
-
-/*
- * Send a play or read command to the drive, return -1 on error, else 0
-*/
-static int sendAztCmd(int cmd, struct azt_Play_msf *params)
-{
-	unsigned char data;
-	int retry;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: play start=%02x:%02x:%02x  end=%02x:%02x:%02x\n",
-	       params->start.min, params->start.sec, params->start.frame,
-	       params->end.min, params->end.sec, params->end.frame);
-#endif
-	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-		aztSendCmd(cmd);
-		outb(params->start.min, CMD_PORT);
-		outb(params->start.sec, CMD_PORT);
-		outb(params->start.frame, CMD_PORT);
-		outb(params->end.min, CMD_PORT);
-		outb(params->end.sec, CMD_PORT);
-		outb(params->end.frame, CMD_PORT);
-		STEN_LOW;
-		data = inb(DATA_PORT);
-		if (data == AFL_PA_OK) {
-			return 0;
-		}		/*PA_OK ? */
-		if (data == AFL_PA_ERR) {
-			STEN_LOW;
-			data = inb(DATA_PORT);
-			printk
-			    ("### Error 1 aztcd: sendAztCmd %x  Error Code %x\n",
-			     cmd, data);
-		}
-	}
-	if (retry >= AZT_RETRY_ATTEMPTS) {
-		printk("### Error 2 aztcd: sendAztCmd %x\n ", cmd);
-		azt_error = 0xA5;
-	}
-	RETURNM("sendAztCmd", -1);
-}
-
-/*
- * Send a seek command to the drive, return -1 on error, else 0
-*/
-static int aztSeek(struct azt_Play_msf *params)
-{
-	unsigned char data;
-	int retry;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: aztSeek %02x:%02x:%02x\n",
-	       params->start.min, params->start.sec, params->start.frame);
-#endif
-	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-		aztSendCmd(ACMD_SEEK);
-		outb(params->start.min, CMD_PORT);
-		outb(params->start.sec, CMD_PORT);
-		outb(params->start.frame, CMD_PORT);
-		STEN_LOW;
-		data = inb(DATA_PORT);
-		if (data == AFL_PA_OK) {
-			return 0;
-		}		/*PA_OK ? */
-		if (data == AFL_PA_ERR) {
-			STEN_LOW;
-			data = inb(DATA_PORT);
-			printk("### Error 1 aztcd: aztSeek\n");
-		}
-	}
-	if (retry >= AZT_RETRY_ATTEMPTS) {
-		printk("### Error 2 aztcd: aztSeek\n ");
-		azt_error = 0xA5;
-	}
-	RETURNM("aztSeek", -1);
-}
-
-/* Send a Set Disk Type command
-   does not seem to work with Aztech drives, behavior is completely indepen-
-   dent on which mode is set ???
-*/
-static int aztSetDiskType(int type)
-{
-	unsigned char data;
-	int retry;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: set disk type command: type= %i\n", type);
-#endif
-	for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
-		aztSendCmd(ACMD_SET_DISK_TYPE);
-		outb(type, CMD_PORT);
-		STEN_LOW;
-		data = inb(DATA_PORT);
-		if (data == AFL_PA_OK) {	/*PA_OK ? */
-			azt_read_mode = type;
-			return 0;
-		}
-		if (data == AFL_PA_ERR) {
-			STEN_LOW;
-			data = inb(DATA_PORT);
-			printk
-			    ("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n",
-			     type, data);
-		}
-	}
-	if (retry >= AZT_RETRY_ATTEMPTS) {
-		printk("### Error 2 aztcd: aztSetDiskType %x\n ", type);
-		azt_error = 0xA5;
-	}
-	RETURNM("aztSetDiskType", -1);
-}
-
-
-/* used in azt_poll to poll the status, expects another program to issue a 
- * ACMD_GET_STATUS directly before 
- */
-static int aztStatus(void)
-{
-	int st;
-/*	int i;
-
-	i = inb(STATUS_PORT) & AFL_STATUS;    is STEN=0?    ???
-	if (!i)
-*/ STEN_LOW;
-	if (aztTimeOutCount < AZT_TIMEOUT) {
-		st = inb(DATA_PORT) & 0xFF;
-		return st;
-	} else
-		RETURNM("aztStatus", -1);
-}
-
-/*
- * Get the drive status
- */
-static int getAztStatus(void)
-{
-	int st;
-
-	if (aztSendCmd(ACMD_GET_STATUS))
-		RETURNM("getAztStatus 1", -1);
-	STEN_LOW;
-	st = inb(DATA_PORT) & 0xFF;
-#ifdef AZT_DEBUG
-	printk("aztcd: Status = %x\n", st);
-#endif
-	if ((st == 0xFF) || (st & AST_CMD_CHECK)) {
-		printk
-		    ("aztcd: AST_CMD_CHECK error or no status available\n");
-		return -1;
-	}
-
-	if (((st & AST_MODE_BITS) != AST_BUSY)
-	    && (aztAudioStatus == CDROM_AUDIO_PLAY))
-		/* XXX might be an error? look at q-channel? */
-		aztAudioStatus = CDROM_AUDIO_COMPLETED;
-
-	if ((st & AST_DSK_CHG) || (st & AST_NOT_READY)) {
-		aztDiskChanged = 1;
-		aztTocUpToDate = 0;
-		aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-	}
-	return st;
-}
-
-
-/*
- * Send a 'Play' command and get the status.  Use only from the top half.
- */
-static int aztPlay(struct azt_Play_msf *arg)
-{
-	if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0)
-		RETURNM("aztPlay", -1);
-	return 0;
-}
-
-/*
- * Subroutines to automatically close the door (tray) and 
- * lock it closed when the cd is mounted.  Leave the tray
- * locking as an option
- */
-static void aztCloseDoor(void)
-{
-	aztSendCmd(ACMD_CLOSE);
-	STEN_LOW;
-	return;
-}
-
-static void aztLockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
-	aztSendCmd(ACMD_LOCK);
-	STEN_LOW;
-#endif
-	return;
-}
-
-static void aztUnlockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
-	aztSendCmd(ACMD_UNLOCK);
-	STEN_LOW;
-#endif
-	return;
-}
-
-/*
- * Read a value from the drive.  Should return quickly, so a busy wait
- * is used to avoid excessive rescheduling. The read command itself must
- * be issued with aztSendCmd() directly before
- */
-static int aztGetValue(unsigned char *result)
-{
-	int s;
-
-	STEN_LOW;
-	if (aztTimeOutCount >= AZT_TIMEOUT) {
-		printk("aztcd: aztGetValue timeout\n");
-		return -1;
-	}
-	s = inb(DATA_PORT) & 0xFF;
-	*result = (unsigned char) s;
-	return 0;
-}
-
-/*
- * Read the current Q-channel info.  Also used for reading the
- * table of contents.
- */
-static int aztGetQChannelInfo(struct azt_Toc *qp)
-{
-	unsigned char notUsed;
-	int st;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztGetQChannelInfo  Time:%li\n", jiffies);
-#endif
-	if ((st = getAztStatus()) == -1)
-		RETURNM("aztGetQChannelInfo 1", -1);
-	if (aztSendCmd(ACMD_GET_Q_CHANNEL))
-		RETURNM("aztGetQChannelInfo 2", -1);
-	/*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here */
-	if (aztGetValue(&notUsed))
-		RETURNM("aztGetQChannelInfo 3", -1);	/*??? Nullbyte einlesen */
-	if ((st & AST_MODE_BITS) == AST_INITIAL) {
-		qp->ctrl_addr = 0;	/* when audio stop ACMD_GET_Q_CHANNEL returns */
-		qp->track = 0;	/* only one byte with Aztech drives */
-		qp->pointIndex = 0;
-		qp->trackTime.min = 0;
-		qp->trackTime.sec = 0;
-		qp->trackTime.frame = 0;
-		qp->diskTime.min = 0;
-		qp->diskTime.sec = 0;
-		qp->diskTime.frame = 0;
-		return 0;
-	} else {
-		if (aztGetValue(&qp->ctrl_addr) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->track) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->pointIndex) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->trackTime.min) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->trackTime.sec) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->trackTime.frame) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&notUsed) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->diskTime.min) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->diskTime.sec) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-		if (aztGetValue(&qp->diskTime.frame) < 0)
-			RETURNM("aztGetQChannelInfo 4", -1);
-	}
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztGetQChannelInfo  Time:%li\n", jiffies);
-#endif
-	return 0;
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary
- */
-static int aztUpdateToc(void)
-{
-	int st;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztUpdateToc  Time:%li\n", jiffies);
-#endif
-	if (aztTocUpToDate)
-		return 0;
-
-	if (aztGetDiskInfo() < 0)
-		return -EIO;
-
-	if (aztGetToc(0) < 0)
-		return -EIO;
-
-	/*audio disk detection
-	   with my Aztech drive there is no audio status bit, so I use the copy
-	   protection bit of the first track. If this track is copy protected 
-	   (copy bit = 0), I assume, it's an audio  disk. Strange, but works ??? */
-	if (!(Toc[DiskInfo.first].ctrl_addr & 0x40))
-		DiskInfo.audio = 1;
-	else
-		DiskInfo.audio = 0;
-
-	/* XA detection */
-	if (!DiskInfo.audio) {
-		azt_Play.start.min = 0;	/*XA detection only seems to work */
-		azt_Play.start.sec = 2;	/*when we play a track */
-		azt_Play.start.frame = 0;
-		azt_Play.end.min = 0;
-		azt_Play.end.sec = 0;
-		azt_Play.end.frame = 1;
-		if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
-			return -1;
-		DTEN_LOW;
-		for (st = 0; st < CD_FRAMESIZE; st++)
-			inb(DATA_PORT);
-	}
-	DiskInfo.xa = getAztStatus() & AST_MODE;
-	if (DiskInfo.xa) {
-		printk
-		    ("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n");
-	}
-
-	/*multisession detection
-	   support for multisession CDs is done automatically with Aztech drives,
-	   we don't have to take care about TOC redirection; if we want the isofs
-	   to take care about redirection, we have to set AZT_MULTISESSION to 1 */
-	DiskInfo.multi = 0;
-#if AZT_MULTISESSION
-	if (DiskInfo.xa) {
-		aztGetMultiDiskInfo();	/*here Disk.Info.multi is set */
-	}
-#endif
-	if (DiskInfo.multi) {
-		DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min;
-		DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec;
-		DiskInfo.lastSession.frame =
-		    Toc[DiskInfo.next].diskTime.frame;
-		printk("aztcd: Multisession support experimental\n");
-	} else {
-		DiskInfo.lastSession.min =
-		    Toc[DiskInfo.first].diskTime.min;
-		DiskInfo.lastSession.sec =
-		    Toc[DiskInfo.first].diskTime.sec;
-		DiskInfo.lastSession.frame =
-		    Toc[DiskInfo.first].diskTime.frame;
-	}
-
-	aztTocUpToDate = 1;
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztUpdateToc  Time:%li\n", jiffies);
-#endif
-	return 0;
-}
-
-
-/* Read the table of contents header, i.e. no. of tracks and start of first 
- * track
- */
-static int aztGetDiskInfo(void)
-{
-	int limit;
-	unsigned char test;
-	struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztGetDiskInfo  Time:%li\n", jiffies);
-#endif
-	if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
-		RETURNM("aztGetDiskInfo 1", -1);
-	STEN_LOW_WAIT;
-	test = 0;
-	for (limit = 300; limit > 0; limit--) {
-		if (aztGetQChannelInfo(&qInfo) < 0)
-			RETURNM("aztGetDiskInfo 2", -1);
-		if (qInfo.pointIndex == 0xA0) {	/*Number of FirstTrack */
-			DiskInfo.first = qInfo.diskTime.min;
-			DiskInfo.first = azt_bcd2bin(DiskInfo.first);
-			test = test | 0x01;
-		}
-		if (qInfo.pointIndex == 0xA1) {	/*Number of LastTrack */
-			DiskInfo.last = qInfo.diskTime.min;
-			DiskInfo.last = azt_bcd2bin(DiskInfo.last);
-			test = test | 0x02;
-		}
-		if (qInfo.pointIndex == 0xA2) {	/*DiskLength */
-			DiskInfo.diskLength.min = qInfo.diskTime.min;
-			DiskInfo.diskLength.sec = qInfo.diskTime.sec;
-			DiskInfo.diskLength.frame = qInfo.diskTime.frame;
-			test = test | 0x04;
-		}
-		if ((qInfo.pointIndex == DiskInfo.first) && (test & 0x01)) {	/*StartTime of First Track */
-			DiskInfo.firstTrack.min = qInfo.diskTime.min;
-			DiskInfo.firstTrack.sec = qInfo.diskTime.sec;
-			DiskInfo.firstTrack.frame = qInfo.diskTime.frame;
-			test = test | 0x08;
-		}
-		if (test == 0x0F)
-			break;
-	}
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztGetDiskInfo  Time:%li\n", jiffies);
-	printk
-	    ("Disk Info: first %d last %d length %02X:%02X.%02X dez  first %02X:%02X.%02X dez\n",
-	     DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min,
-	     DiskInfo.diskLength.sec, DiskInfo.diskLength.frame,
-	     DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec,
-	     DiskInfo.firstTrack.frame);
-#endif
-	if (test != 0x0F)
-		return -1;
-	return 0;
-}
-
-#if AZT_MULTISESSION
-/*
- * Get Multisession Disk Info
- */
-static int aztGetMultiDiskInfo(void)
-{
-	int limit, k = 5;
-	unsigned char test;
-	struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztGetMultiDiskInfo\n");
-#endif
-
-	do {
-		azt_Play.start.min = Toc[DiskInfo.last + 1].diskTime.min;
-		azt_Play.start.sec = Toc[DiskInfo.last + 1].diskTime.sec;
-		azt_Play.start.frame =
-		    Toc[DiskInfo.last + 1].diskTime.frame;
-		test = 0;
-
-		for (limit = 30; limit > 0; limit--) {	/*Seek for LeadIn of next session */
-			if (aztSeek(&azt_Play))
-				RETURNM("aztGetMultiDiskInfo 1", -1);
-			if (aztGetQChannelInfo(&qInfo) < 0)
-				RETURNM("aztGetMultiDiskInfo 2", -1);
-			if ((qInfo.track == 0) && (qInfo.pointIndex))
-				break;	/*LeadIn found */
-			if ((azt_Play.start.sec += 10) > 59) {
-				azt_Play.start.sec = 0;
-				azt_Play.start.min++;
-			}
-		}
-		if (!limit)
-			break;	/*Check, if a leadin track was found, if not we're
-				   at the end of the disk */
-#ifdef AZT_DEBUG_MULTISESSION
-		printk("leadin found track %d  pointIndex %x  limit %d\n",
-		       qInfo.track, qInfo.pointIndex, limit);
-#endif
-		for (limit = 300; limit > 0; limit--) {
-			if (++azt_Play.start.frame > 74) {
-				azt_Play.start.frame = 0;
-				if (azt_Play.start.sec > 59) {
-					azt_Play.start.sec = 0;
-					azt_Play.start.min++;
-				}
-			}
-			if (aztSeek(&azt_Play))
-				RETURNM("aztGetMultiDiskInfo 3", -1);
-			if (aztGetQChannelInfo(&qInfo) < 0)
-				RETURNM("aztGetMultiDiskInfo 4", -1);
-			if (qInfo.pointIndex == 0xA0) {	/*Number of NextTrack */
-				DiskInfo.next = qInfo.diskTime.min;
-				DiskInfo.next = azt_bcd2bin(DiskInfo.next);
-				test = test | 0x01;
-			}
-			if (qInfo.pointIndex == 0xA1) {	/*Number of LastTrack */
-				DiskInfo.last = qInfo.diskTime.min;
-				DiskInfo.last = azt_bcd2bin(DiskInfo.last);
-				test = test | 0x02;
-			}
-			if (qInfo.pointIndex == 0xA2) {	/*DiskLength */
-				DiskInfo.diskLength.min =
-				    qInfo.diskTime.min;
-				DiskInfo.diskLength.sec =
-				    qInfo.diskTime.sec;
-				DiskInfo.diskLength.frame =
-				    qInfo.diskTime.frame;
-				test = test | 0x04;
-			}
-			if ((qInfo.pointIndex == DiskInfo.next) && (test & 0x01)) {	/*StartTime of Next Track */
-				DiskInfo.nextSession.min =
-				    qInfo.diskTime.min;
-				DiskInfo.nextSession.sec =
-				    qInfo.diskTime.sec;
-				DiskInfo.nextSession.frame =
-				    qInfo.diskTime.frame;
-				test = test | 0x08;
-			}
-			if (test == 0x0F)
-				break;
-		}
-#ifdef AZT_DEBUG_MULTISESSION
-		printk
-		    ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez  first %02x:%02x.%02x dez  next %02x:%02x.%02x dez\n",
-		     DiskInfo.first, DiskInfo.next, DiskInfo.last,
-		     DiskInfo.diskLength.min, DiskInfo.diskLength.sec,
-		     DiskInfo.diskLength.frame, DiskInfo.firstTrack.min,
-		     DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame,
-		     DiskInfo.nextSession.min, DiskInfo.nextSession.sec,
-		     DiskInfo.nextSession.frame);
-#endif
-		if (test != 0x0F)
-			break;
-		else
-			DiskInfo.multi = 1;	/*found TOC of more than one session */
-		aztGetToc(1);
-	} while (--k);
-
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztGetMultiDiskInfo  Time:%li\n", jiffies);
-#endif
-	return 0;
-}
-#endif
-
-/*
- * Read the table of contents (TOC)
- */
-static int aztGetToc(int multi)
-{
-	int i, px;
-	int limit;
-	struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztGetToc  Time:%li\n", jiffies);
-#endif
-	if (!multi) {
-		for (i = 0; i < MAX_TRACKS; i++)
-			Toc[i].pointIndex = 0;
-		i = DiskInfo.last + 3;
-	} else {
-		for (i = DiskInfo.next; i < MAX_TRACKS; i++)
-			Toc[i].pointIndex = 0;
-		i = DiskInfo.last + 4 - DiskInfo.next;
-	}
-
-/*Is there a good reason to stop motor before TOC read?
-  if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
-      STEN_LOW_WAIT;
-*/
-
-	if (!multi) {
-		azt_mode = 0x05;
-		if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
-			RETURNM("aztGetToc 2", -1);
-		STEN_LOW_WAIT;
-	}
-	for (limit = 300; limit > 0; limit--) {
-		if (multi) {
-			if (++azt_Play.start.sec > 59) {
-				azt_Play.start.sec = 0;
-				azt_Play.start.min++;
-			}
-			if (aztSeek(&azt_Play))
-				RETURNM("aztGetToc 3", -1);
-		}
-		if (aztGetQChannelInfo(&qInfo) < 0)
-			break;
-
-		px = azt_bcd2bin(qInfo.pointIndex);
-
-		if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
-			if (Toc[px].pointIndex == 0) {
-				Toc[px] = qInfo;
-				i--;
-			}
-
-		if (i <= 0)
-			break;
-	}
-
-	Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
-	Toc[DiskInfo.last].trackTime = DiskInfo.diskLength;
-
-#ifdef AZT_DEBUG_MULTISESSION
-	printk("aztcd: exiting aztGetToc\n");
-	for (i = 1; i <= DiskInfo.last + 1; i++)
-		printk
-		    ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez  %02X:%02X.%02X dez\n",
-		     i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
-		     Toc[i].trackTime.min, Toc[i].trackTime.sec,
-		     Toc[i].trackTime.frame, Toc[i].diskTime.min,
-		     Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-	for (i = 100; i < 103; i++)
-		printk
-		    ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez  %02X:%02X.%02X dez\n",
-		     i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
-		     Toc[i].trackTime.min, Toc[i].trackTime.sec,
-		     Toc[i].trackTime.frame, Toc[i].diskTime.min,
-		     Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-#endif
-
-	return limit > 0 ? 0 : -1;
-}
-
-
-/*##########################################################################
-  Kernel Interface Functions
-  ##########################################################################
-*/
-
-#ifndef MODULE
-static int __init aztcd_setup(char *str)
-{
-	int ints[4];
-
-	(void) get_options(str, ARRAY_SIZE(ints), ints);
-
-	if (ints[0] > 0)
-		azt_port = ints[1];
-	if (ints[1] > 1)
-		azt_cont = ints[2];
-	return 1;
-}
-
-__setup("aztcd=", aztcd_setup);
-
-#endif				/* !MODULE */
-
-/* 
- * Checking if the media has been changed
-*/
-static int check_aztcd_media_change(struct gendisk *disk)
-{
-	if (aztDiskChanged) {	/* disk changed */
-		aztDiskChanged = 0;
-		return 1;
-	} else
-		return 0;	/* no change */
-}
-
-/*
- * Kernel IO-controls
-*/
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
-		       unsigned long arg)
-{
-	int i;
-	struct azt_Toc qInfo;
-	struct cdrom_ti ti;
-	struct cdrom_tochdr tocHdr;
-	struct cdrom_msf msf;
-	struct cdrom_tocentry entry;
-	struct azt_Toc *tocPtr;
-	struct cdrom_subchnl subchnl;
-	struct cdrom_volctrl volctrl;
-	void __user *argp = (void __user *)arg;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztcd_ioctl - Command:%x   Time: %li\n",
-	       cmd, jiffies);
-	printk("aztcd Status %x\n", getAztStatus());
-#endif
-	if (!ip)
-		RETURNM("aztcd_ioctl 1", -EINVAL);
-	if (getAztStatus() < 0)
-		RETURNM("aztcd_ioctl 2", -EIO);
-	if ((!aztTocUpToDate) || (aztDiskChanged)) {
-		if ((i = aztUpdateToc()) < 0)
-			RETURNM("aztcd_ioctl 3", i);	/* error reading TOC */
-	}
-
-	switch (cmd) {
-	case CDROMSTART:	/* Spin up the drive. Don't know, what to do,
-				   at least close the tray */
-#if AZT_PRIVATE_IOCTLS
-		if (aztSendCmd(ACMD_CLOSE))
-			RETURNM("aztcd_ioctl 4", -1);
-		STEN_LOW_WAIT;
-#endif
-		break;
-	case CDROMSTOP:	/* Spin down the drive */
-		if (aztSendCmd(ACMD_STOP))
-			RETURNM("aztcd_ioctl 5", -1);
-		STEN_LOW_WAIT;
-		/* should we do anything if it fails? */
-		aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-		break;
-	case CDROMPAUSE:	/* Pause the drive */
-		if (aztAudioStatus != CDROM_AUDIO_PLAY)
-			return -EINVAL;
-
-		if (aztGetQChannelInfo(&qInfo) < 0) {	/* didn't get q channel info */
-			aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-			RETURNM("aztcd_ioctl 7", 0);
-		}
-		azt_Play.start = qInfo.diskTime;	/* remember restart point */
-
-		if (aztSendCmd(ACMD_PAUSE))
-			RETURNM("aztcd_ioctl 8", -1);
-		STEN_LOW_WAIT;
-		aztAudioStatus = CDROM_AUDIO_PAUSED;
-		break;
-	case CDROMRESUME:	/* Play it again, Sam */
-		if (aztAudioStatus != CDROM_AUDIO_PAUSED)
-			return -EINVAL;
-		/* restart the drive at the saved position. */
-		i = aztPlay(&azt_Play);
-		if (i < 0) {
-			aztAudioStatus = CDROM_AUDIO_ERROR;
-			return -EIO;
-		}
-		aztAudioStatus = CDROM_AUDIO_PLAY;
-		break;
-	case CDROMMULTISESSION:	/*multisession support -- experimental */
-		{
-			struct cdrom_multisession ms;
-#ifdef AZT_DEBUG
-			printk("aztcd ioctl MULTISESSION\n");
-#endif
-			if (copy_from_user(&ms, argp,
-			     sizeof(struct cdrom_multisession)))
-				return -EFAULT;
-			if (ms.addr_format == CDROM_MSF) {
-				ms.addr.msf.minute =
-				    azt_bcd2bin(DiskInfo.lastSession.min);
-				ms.addr.msf.second =
-				    azt_bcd2bin(DiskInfo.lastSession.sec);
-				ms.addr.msf.frame =
-				    azt_bcd2bin(DiskInfo.lastSession.
-						frame);
-			} else if (ms.addr_format == CDROM_LBA)
-				ms.addr.lba =
-				    azt_msf2hsg(&DiskInfo.lastSession);
-			else
-				return -EINVAL;
-			ms.xa_flag = DiskInfo.xa;
-			if (copy_to_user(argp, &ms,
-			     sizeof(struct cdrom_multisession)))
-				return -EFAULT;
-#ifdef AZT_DEBUG
-			if (ms.addr_format == CDROM_MSF)
-				printk
-				    ("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
-				     ms.xa_flag, ms.addr.msf.minute,
-				     ms.addr.msf.second, ms.addr.msf.frame,
-				     DiskInfo.lastSession.min,
-				     DiskInfo.lastSession.sec,
-				     DiskInfo.lastSession.frame);
-			else
-				printk
-				    ("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n",
-				     ms.xa_flag, ms.addr.lba,
-				     DiskInfo.lastSession.min,
-				     DiskInfo.lastSession.sec,
-				     DiskInfo.lastSession.frame);
-#endif
-			return 0;
-		}
-	case CDROMPLAYTRKIND:	/* Play a track.  This currently ignores index. */
-		if (copy_from_user(&ti, argp, sizeof ti))
-			return -EFAULT;
-		if (ti.cdti_trk0 < DiskInfo.first
-		    || ti.cdti_trk0 > DiskInfo.last
-		    || ti.cdti_trk1 < ti.cdti_trk0) {
-			return -EINVAL;
-		}
-		if (ti.cdti_trk1 > DiskInfo.last)
-			ti.cdti_trk1 = DiskInfo.last;
-		azt_Play.start = Toc[ti.cdti_trk0].diskTime;
-		azt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
-#ifdef AZT_DEBUG
-		printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
-		       azt_Play.start.min, azt_Play.start.sec,
-		       azt_Play.start.frame, azt_Play.end.min,
-		       azt_Play.end.sec, azt_Play.end.frame);
-#endif
-		i = aztPlay(&azt_Play);
-		if (i < 0) {
-			aztAudioStatus = CDROM_AUDIO_ERROR;
-			return -EIO;
-		}
-		aztAudioStatus = CDROM_AUDIO_PLAY;
-		break;
-	case CDROMPLAYMSF:	/* Play starting at the given MSF address. */
-/*              if (aztAudioStatus == CDROM_AUDIO_PLAY) 
-		{ if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1);
-		  STEN_LOW;
-		  aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-		}
-*/
-		if (copy_from_user(&msf, argp, sizeof msf))
-			return -EFAULT;
-		/* convert to bcd */
-		azt_bin2bcd(&msf.cdmsf_min0);
-		azt_bin2bcd(&msf.cdmsf_sec0);
-		azt_bin2bcd(&msf.cdmsf_frame0);
-		azt_bin2bcd(&msf.cdmsf_min1);
-		azt_bin2bcd(&msf.cdmsf_sec1);
-		azt_bin2bcd(&msf.cdmsf_frame1);
-		azt_Play.start.min = msf.cdmsf_min0;
-		azt_Play.start.sec = msf.cdmsf_sec0;
-		azt_Play.start.frame = msf.cdmsf_frame0;
-		azt_Play.end.min = msf.cdmsf_min1;
-		azt_Play.end.sec = msf.cdmsf_sec1;
-		azt_Play.end.frame = msf.cdmsf_frame1;
-#ifdef AZT_DEBUG
-		printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
-		       azt_Play.start.min, azt_Play.start.sec,
-		       azt_Play.start.frame, azt_Play.end.min,
-		       azt_Play.end.sec, azt_Play.end.frame);
-#endif
-		i = aztPlay(&azt_Play);
-		if (i < 0) {
-			aztAudioStatus = CDROM_AUDIO_ERROR;
-			return -EIO;
-		}
-		aztAudioStatus = CDROM_AUDIO_PLAY;
-		break;
-
-	case CDROMREADTOCHDR:	/* Read the table of contents header */
-		tocHdr.cdth_trk0 = DiskInfo.first;
-		tocHdr.cdth_trk1 = DiskInfo.last;
-		if (copy_to_user(argp, &tocHdr, sizeof tocHdr))
-			return -EFAULT;
-		break;
-	case CDROMREADTOCENTRY:	/* Read an entry in the table of contents */
-		if (copy_from_user(&entry, argp, sizeof entry))
-			return -EFAULT;
-		if ((!aztTocUpToDate) || aztDiskChanged)
-			aztUpdateToc();
-		if (entry.cdte_track == CDROM_LEADOUT)
-			tocPtr = &Toc[DiskInfo.last + 1];
-		else if (entry.cdte_track > DiskInfo.last
-			 || entry.cdte_track < DiskInfo.first) {
-			return -EINVAL;
-		} else
-			tocPtr = &Toc[entry.cdte_track];
-		entry.cdte_adr = tocPtr->ctrl_addr;
-		entry.cdte_ctrl = tocPtr->ctrl_addr >> 4;
-		if (entry.cdte_format == CDROM_LBA)
-			entry.cdte_addr.lba =
-			    azt_msf2hsg(&tocPtr->diskTime);
-		else if (entry.cdte_format == CDROM_MSF) {
-			entry.cdte_addr.msf.minute =
-			    azt_bcd2bin(tocPtr->diskTime.min);
-			entry.cdte_addr.msf.second =
-			    azt_bcd2bin(tocPtr->diskTime.sec);
-			entry.cdte_addr.msf.frame =
-			    azt_bcd2bin(tocPtr->diskTime.frame);
-		} else {
-			return -EINVAL;
-		}
-		if (copy_to_user(argp, &entry, sizeof entry))
-			return -EFAULT;
-		break;
-	case CDROMSUBCHNL:	/* Get subchannel info */
-		if (copy_from_user
-		    (&subchnl, argp, sizeof(struct cdrom_subchnl)))
-			return -EFAULT;
-		if (aztGetQChannelInfo(&qInfo) < 0) {
-#ifdef AZT_DEBUG
-			printk
-			    ("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n",
-			     cmd);
-#endif
-			return -EIO;
-		}
-		subchnl.cdsc_audiostatus = aztAudioStatus;
-		subchnl.cdsc_adr = qInfo.ctrl_addr;
-		subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
-		subchnl.cdsc_trk = azt_bcd2bin(qInfo.track);
-		subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex);
-		if (subchnl.cdsc_format == CDROM_LBA) {
-			subchnl.cdsc_absaddr.lba =
-			    azt_msf2hsg(&qInfo.diskTime);
-			subchnl.cdsc_reladdr.lba =
-			    azt_msf2hsg(&qInfo.trackTime);
-		} else {	/*default */
-			subchnl.cdsc_format = CDROM_MSF;
-			subchnl.cdsc_absaddr.msf.minute =
-			    azt_bcd2bin(qInfo.diskTime.min);
-			subchnl.cdsc_absaddr.msf.second =
-			    azt_bcd2bin(qInfo.diskTime.sec);
-			subchnl.cdsc_absaddr.msf.frame =
-			    azt_bcd2bin(qInfo.diskTime.frame);
-			subchnl.cdsc_reladdr.msf.minute =
-			    azt_bcd2bin(qInfo.trackTime.min);
-			subchnl.cdsc_reladdr.msf.second =
-			    azt_bcd2bin(qInfo.trackTime.sec);
-			subchnl.cdsc_reladdr.msf.frame =
-			    azt_bcd2bin(qInfo.trackTime.frame);
-		}
-		if (copy_to_user(argp, &subchnl, sizeof(struct cdrom_subchnl)))
-			return -EFAULT;
-		break;
-	case CDROMVOLCTRL:	/* Volume control 
-				   * With my Aztech CD268-01A volume control does not work, I can only
-				   turn the channels on (any value !=0) or off (value==0). Maybe it
-				   works better with your drive */
-		if (copy_from_user(&volctrl, argp, sizeof(volctrl)))
-			return -EFAULT;
-		azt_Play.start.min = 0x21;
-		azt_Play.start.sec = 0x84;
-		azt_Play.start.frame = volctrl.channel0;
-		azt_Play.end.min = volctrl.channel1;
-		azt_Play.end.sec = volctrl.channel2;
-		azt_Play.end.frame = volctrl.channel3;
-		sendAztCmd(ACMD_SET_VOLUME, &azt_Play);
-		STEN_LOW_WAIT;
-		break;
-	case CDROMEJECT:
-		aztUnlockDoor();	/* Assume user knows what they're doing */
-		/* all drives can at least stop! */
-		if (aztAudioStatus == CDROM_AUDIO_PLAY) {
-			if (aztSendCmd(ACMD_STOP))
-				RETURNM("azt_ioctl 10", -1);
-			STEN_LOW_WAIT;
-		}
-		if (aztSendCmd(ACMD_EJECT))
-			RETURNM("azt_ioctl 11", -1);
-		STEN_LOW_WAIT;
-		aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-		break;
-	case CDROMEJECT_SW:
-		azt_auto_eject = (char) arg;
-		break;
-	case CDROMRESET:
-		outb(ACMD_SOFT_RESET, CMD_PORT);	/*send reset */
-		STEN_LOW;
-		if (inb(DATA_PORT) != AFL_OP_OK) {	/*OP_OK? */
-			printk
-			    ("aztcd: AZTECH CD-ROM drive does not respond\n");
-		}
-		break;
-/*Take care, the following code is not compatible with other CD-ROM drivers,
-  use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h,
-  if you do not want to use it!
-*/
-#if AZT_PRIVATE_IOCTLS
-	case CDROMREADCOOKED:	/*read data in mode 1 (2048 Bytes) */
-	case CDROMREADRAW:	/*read data in mode 2 (2336 Bytes) */
-		{
-			if (copy_from_user(&msf, argp, sizeof msf))
-				return -EFAULT;
-			/* convert to bcd */
-			azt_bin2bcd(&msf.cdmsf_min0);
-			azt_bin2bcd(&msf.cdmsf_sec0);
-			azt_bin2bcd(&msf.cdmsf_frame0);
-			msf.cdmsf_min1 = 0;
-			msf.cdmsf_sec1 = 0;
-			msf.cdmsf_frame1 = 1;	/*read only one frame */
-			azt_Play.start.min = msf.cdmsf_min0;
-			azt_Play.start.sec = msf.cdmsf_sec0;
-			azt_Play.start.frame = msf.cdmsf_frame0;
-			azt_Play.end.min = msf.cdmsf_min1;
-			azt_Play.end.sec = msf.cdmsf_sec1;
-			azt_Play.end.frame = msf.cdmsf_frame1;
-			if (cmd == CDROMREADRAW) {
-				if (DiskInfo.xa) {
-					return -1;	/*XA Disks can't be read raw */
-				} else {
-					if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play))
-						return -1;
-					DTEN_LOW;
-					insb(DATA_PORT, buf, CD_FRAMESIZE_RAW);
-					if (copy_to_user(argp, &buf, CD_FRAMESIZE_RAW))
-						return -EFAULT;
-				}
-			} else
-				/*CDROMREADCOOKED*/ {
-				if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
-					return -1;
-				DTEN_LOW;
-				insb(DATA_PORT, buf, CD_FRAMESIZE);
-				if (copy_to_user(argp, &buf, CD_FRAMESIZE))
-					return -EFAULT;
-				}
-		}
-		break;
-	case CDROMSEEK:	/*seek msf address */
-		if (copy_from_user(&msf, argp, sizeof msf))
-			return -EFAULT;
-		/* convert to bcd */
-		azt_bin2bcd(&msf.cdmsf_min0);
-		azt_bin2bcd(&msf.cdmsf_sec0);
-		azt_bin2bcd(&msf.cdmsf_frame0);
-		azt_Play.start.min = msf.cdmsf_min0;
-		azt_Play.start.sec = msf.cdmsf_sec0;
-		azt_Play.start.frame = msf.cdmsf_frame0;
-		if (aztSeek(&azt_Play))
-			return -1;
-		break;
-#endif				/*end of incompatible code */
-	case CDROMREADMODE1:	/*set read data in mode 1 */
-		return aztSetDiskType(AZT_MODE_1);
-	case CDROMREADMODE2:	/*set read data in mode 2 */
-		return aztSetDiskType(AZT_MODE_2);
-	default:
-		return -EINVAL;
-	}
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztcd_ioctl Command:%x  Time:%li\n", cmd,
-	       jiffies);
-#endif
-	return 0;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-static void azt_transfer(void)
-{
-#ifdef AZT_TEST
-	printk("aztcd: executing azt_transfer Time:%li\n", jiffies);
-#endif
-	if (!current_valid())
-	        return;
-
-	while (CURRENT->nr_sectors) {
-		int bn = CURRENT->sector / 4;
-		int i;
-		for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; ++i);
-		if (i < AZT_BUF_SIZ) {
-			int offs = (i * 4 + (CURRENT->sector & 3)) * 512;
-			int nr_sectors = 4 - (CURRENT->sector & 3);
-			if (azt_buf_out != i) {
-				azt_buf_out = i;
-				if (azt_buf_bn[i] != bn) {
-					azt_buf_out = -1;
-					continue;
-				}
-			}
-			if (nr_sectors > CURRENT->nr_sectors)
-			    nr_sectors = CURRENT->nr_sectors;
-			memcpy(CURRENT->buffer, azt_buf + offs,
-				nr_sectors * 512);
-			CURRENT->nr_sectors -= nr_sectors;
-			CURRENT->sector += nr_sectors;
-			CURRENT->buffer += nr_sectors * 512;
-		} else {
-			azt_buf_out = -1;
-			break;
-		}
-	}
-}
-
-static void do_aztcd_request(request_queue_t * q)
-{
-#ifdef AZT_TEST
-	printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT->sector,
-	       CURRENT->nr_sectors, jiffies);
-#endif
-	if (DiskInfo.audio) {
-		printk("aztcd: Error, tried to mount an Audio CD\n");
-		end_request(CURRENT, 0);
-		return;
-	}
-	azt_transfer_is_active = 1;
-	while (current_valid()) {
-		azt_transfer();
-		if (CURRENT->nr_sectors == 0) {
-			end_request(CURRENT, 1);
-		} else {
-			azt_buf_out = -1;	/* Want to read a block not in buffer */
-			if (azt_state == AZT_S_IDLE) {
-				if ((!aztTocUpToDate) || aztDiskChanged) {
-					if (aztUpdateToc() < 0) {
-						while (current_valid())
-							end_request(CURRENT, 0);
-						break;
-					}
-				}
-				azt_state = AZT_S_START;
-				AztTries = 5;
-				SET_TIMER(azt_poll, HZ / 100);
-			}
-			break;
-		}
-	}
-	azt_transfer_is_active = 0;
-#ifdef AZT_TEST2
-	printk
-	    ("azt_next_bn:%x  azt_buf_in:%x azt_buf_out:%x  azt_buf_bn:%x\n",
-	     azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
-	printk(" do_aztcd_request ends  Time:%li\n", jiffies);
-#endif
-}
-
-
-static void azt_invalidate_buffers(void)
-{
-	int i;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: executing azt_invalidate_buffers\n");
-#endif
-	for (i = 0; i < AZT_BUF_SIZ; ++i)
-		azt_buf_bn[i] = -1;
-	azt_buf_out = -1;
-}
-
-/*
- * Open the device special file.  Check that a disk is in.
- */
-static int aztcd_open(struct inode *ip, struct file *fp)
-{
-	int st;
-
-#ifdef AZT_DEBUG
-	printk("aztcd: starting aztcd_open\n");
-#endif
-
-	if (aztPresent == 0)
-		return -ENXIO;	/* no hardware */
-
-	if (!azt_open_count && azt_state == AZT_S_IDLE) {
-		azt_invalidate_buffers();
-
-		st = getAztStatus();	/* check drive status */
-		if (st == -1)
-			goto err_out;	/* drive doesn't respond */
-
-		if (st & AST_DOOR_OPEN) {	/* close door, then get the status again. */
-			printk("aztcd: Door Open?\n");
-			aztCloseDoor();
-			st = getAztStatus();
-		}
-
-		if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) {	/*no disk in drive or changed */
-			printk
-			    ("aztcd: Disk Changed or No Disk in Drive?\n");
-			aztTocUpToDate = 0;
-		}
-		if (aztUpdateToc())
-			goto err_out;
-
-	}
-	++azt_open_count;
-	aztLockDoor();
-
-#ifdef AZT_DEBUG
-	printk("aztcd: exiting aztcd_open\n");
-#endif
-	return 0;
-
-      err_out:
-	return -EIO;
-}
-
-
-/*
- * On close, we flush all azt blocks from the buffer cache.
- */
-static int aztcd_release(struct inode *inode, struct file *file)
-{
-#ifdef AZT_DEBUG
-	printk("aztcd: executing aztcd_release\n");
-	printk("inode: %p, device: %s    file: %p\n", inode,
-	       inode->i_bdev->bd_disk->disk_name, file);
-#endif
-	if (!--azt_open_count) {
-		azt_invalidate_buffers();
-		aztUnlockDoor();
-		if (azt_auto_eject)
-			aztSendCmd(ACMD_EJECT);
-		CLEAR_TIMER;
-	}
-	return 0;
-}
-
-static struct gendisk *azt_disk;
-
-/*
- * Test for presence of drive and initialize it.  Called at boot time.
- */
-
-static int __init aztcd_init(void)
-{
-	long int count, max_count;
-	unsigned char result[50];
-	int st;
-	void* status = NULL;
-	int i = 0;
-	int ret = 0;
-
-	if (azt_port == 0) {
-		printk(KERN_INFO "aztcd: no Aztech CD-ROM Initialization");
-		return -EIO;
-	}
-
-	printk(KERN_INFO "aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM "
-	       "CD-ROM Driver\n");
-	printk(KERN_INFO "aztcd: (C) 1994-98 W.Zimmermann\n");
-	if (azt_port == -1) {
-		printk
-		    ("aztcd: DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",
-		     AZT_VERSION);
-	} else
-		printk
-		    ("aztcd: DriverVersion=%s BaseAddress=0x%x  For IDE/ATAPI-drives use ide-cd.c\n",
-		     AZT_VERSION, azt_port);
-	printk(KERN_INFO "aztcd: If you have problems, read /usr/src/linux/"
-	       "Documentation/cdrom/aztcd\n");
-
-
-#ifdef AZT_SW32			/*CDROM connected to Soundwave32 card */
-	if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) {
-		printk
-		    ("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n",
-		     AZT_SW32_BASE_ADDR, AZT_SW32_INIT,
-		     AZT_SW32_CONFIG_REG, AZT_SW32_ID_REG);
-		return -EIO;
-	} else {
-		printk(KERN_INFO
-		       "aztcd: Soundwave32 card detected at %x  Version %x\n",
-		       AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG));
-		outw(AZT_SW32_INIT, AZT_SW32_CONFIG_REG);
-		for (count = 0; count < 10000; count++);	/*delay a bit */
-	}
-#endif
-
-	/* check for presence of drive */
-
-	if (azt_port == -1) {	/* autoprobing for proprietary interface  */
-		for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) {
-			azt_port = azt_port_auto[i];
-			printk(KERN_INFO "aztcd: Autoprobing BaseAddress=0x%x"
-			       "\n", azt_port);
-			 /*proprietary interfaces need 4 bytes */
-			if (!request_region(azt_port, 4, "aztcd")) {
-				continue;
-			}
-			outb(POLLED, MODE_PORT);
-			inb(CMD_PORT);
-			inb(CMD_PORT);
-			outb(ACMD_GET_VERSION, CMD_PORT);	/*Try to get version info */
-
-			aztTimeOutCount = 0;
-			do {
-				aztIndatum = inb(STATUS_PORT);
-				aztTimeOutCount++;
-				if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-					break;
-			} while (aztIndatum & AFL_STATUS);
-			if (inb(DATA_PORT) == AFL_OP_OK) { /* OK drive found */
-				break;
-			}
-			else {  /* Drive not found on this port - try next one */
-				release_region(azt_port, 4);
-			}
-		}
-		if ((i == 16) || (azt_port_auto[i] == 0)) {
-			printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n");
-			return -EIO;
-		}
-	} else {		/* no autoprobing */
-		if ((azt_port == 0x1f0) || (azt_port == 0x170))
-			status = request_region(azt_port, 8, "aztcd");	/*IDE-interfaces need 8 bytes */
-		else
-			status = request_region(azt_port, 4, "aztcd");	/*proprietary interfaces need 4 bytes */
-		if (!status) {
-			printk(KERN_WARNING "aztcd: conflict, I/O port (%X) "
-			       "already used\n", azt_port);
-			return -EIO;
-		}
-
-		if ((azt_port == 0x1f0) || (azt_port == 0x170))
-			SWITCH_IDE_SLAVE;	/*switch IDE interface to slave configuration */
-
-		outb(POLLED, MODE_PORT);
-		inb(CMD_PORT);
-		inb(CMD_PORT);
-		outb(ACMD_GET_VERSION, CMD_PORT);	/*Try to get version info */
-
-		aztTimeOutCount = 0;
-		do {
-			aztIndatum = inb(STATUS_PORT);
-			aztTimeOutCount++;
-			if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-				break;
-		} while (aztIndatum & AFL_STATUS);
-
-		if (inb(DATA_PORT) != AFL_OP_OK) {	/*OP_OK? If not, reset and try again */
-#ifndef MODULE
-			if (azt_cont != 0x79) {
-				printk(KERN_WARNING "aztcd: no AZTECH CD-ROM "
-				       "drive found-Try boot parameter aztcd="
-				       "<BaseAddress>,0x79\n");
-				ret = -EIO;
-				goto err_out;
-			}
-#else
-			if (0) {
-			}
-#endif
-			else {
-				printk(KERN_INFO "aztcd: drive reset - "
-				       "please wait\n");
-				for (count = 0; count < 50; count++) {
-					inb(STATUS_PORT);	/*removing all data from earlier tries */
-					inb(DATA_PORT);
-				}
-				outb(POLLED, MODE_PORT);
-				inb(CMD_PORT);
-				inb(CMD_PORT);
-				getAztStatus();	/*trap errors */
-				outb(ACMD_SOFT_RESET, CMD_PORT);	/*send reset */
-				STEN_LOW;
-				if (inb(DATA_PORT) != AFL_OP_OK) {	/*OP_OK? */
-					printk(KERN_WARNING "aztcd: no AZTECH "
-					       "CD-ROM drive found\n");
-					ret = -EIO;
-					goto err_out;
-				}
-
-				for (count = 0; count < AZT_TIMEOUT;
-				     count++)
-					barrier();	/* Stop gcc 2.96 being smart */
-				/* use udelay(), damnit -- AV */
-
-				if ((st = getAztStatus()) == -1) {
-					printk(KERN_WARNING "aztcd: Drive Status"
-					       " Error Status=%x\n", st);
-					ret = -EIO;
-					goto err_out;
-				}
-#ifdef AZT_DEBUG
-				printk(KERN_DEBUG "aztcd: Status = %x\n", st);
-#endif
-				outb(POLLED, MODE_PORT);
-				inb(CMD_PORT);
-				inb(CMD_PORT);
-				outb(ACMD_GET_VERSION, CMD_PORT);	/*GetVersion */
-				STEN_LOW;
-				OP_OK;
-			}
-		}
-	}
-
-	azt_init_end = 1;
-	STEN_LOW;
-	result[0] = inb(DATA_PORT);	/*reading in a null byte??? */
-	for (count = 1; count < 50; count++) {	/*Reading version string */
-		aztTimeOutCount = 0;	/*here we must implement STEN_LOW differently */
-		do {
-			aztIndatum = inb(STATUS_PORT);	/*because we want to exit by timeout */
-			aztTimeOutCount++;
-			if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-				break;
-		} while (aztIndatum & AFL_STATUS);
-		if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
-			break;	/*all chars read? */
-		result[count] = inb(DATA_PORT);
-	}
-	if (count > 30)
-		max_count = 30;	/*print max.30 chars of the version string */
-	else
-		max_count = count;
-	printk(KERN_INFO "aztcd: FirmwareVersion=");
-	for (count = 1; count < max_count; count++)
-		printk("%c", result[count]);
-	printk("<<>> ");
-
-	if ((result[1] == 'A') && (result[2] == 'Z') && (result[3] == 'T')) {
-		printk("AZTECH drive detected\n");
-	/*AZTECH*/}
-		else if ((result[2] == 'C') && (result[3] == 'D')
-			 && (result[4] == 'D')) {
-		printk("ORCHID or WEARNES drive detected\n");	/*ORCHID or WEARNES */
-	} else if ((result[1] == 0x03) && (result[2] == '5')) {
-		printk("TXC or CyCDROM drive detected\n");	/*Conrad TXC, CyCDROM */
-	} else {		/*OTHERS or none */
-		printk("\nunknown drive or firmware version detected\n");
-		printk
-		    ("aztcd may not run stable, if you want to try anyhow,\n");
-		printk("boot with: aztcd=<BaseAddress>,0x79\n");
-		if ((azt_cont != 0x79)) {
-			printk("aztcd: FirmwareVersion=");
-			for (count = 1; count < 5; count++)
-				printk("%c", result[count]);
-			printk("<<>> ");
-			printk("Aborted\n");
-			ret = -EIO;
-			goto err_out;
-		}
-	}
-	azt_disk = alloc_disk(1);
-	if (!azt_disk)
-		goto err_out;
-
-	if (register_blkdev(MAJOR_NR, "aztcd")) {
-		ret = -EIO;
-		goto err_out2;
-	}
-
-	azt_queue = blk_init_queue(do_aztcd_request, &aztSpin);
-	if (!azt_queue) {
-		ret = -ENOMEM;
-		goto err_out3;
-	}
-
-	blk_queue_hardsect_size(azt_queue, 2048);
-	azt_disk->major = MAJOR_NR;
-	azt_disk->first_minor = 0;
-	azt_disk->fops = &azt_fops;
-	sprintf(azt_disk->disk_name, "aztcd");
-	azt_disk->queue = azt_queue;
-	add_disk(azt_disk);
-	azt_invalidate_buffers();
-	aztPresent = 1;
-	aztCloseDoor();
-	return 0;
-err_out3:
-	unregister_blkdev(MAJOR_NR, "aztcd");
-err_out2:
-	put_disk(azt_disk);
-err_out:
-	if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
-		SWITCH_IDE_MASTER;
-		release_region(azt_port, 8);	/*IDE-interface */
-	} else
-		release_region(azt_port, 4);	/*proprietary interface */
-	return ret;
-
-}
-
-static void __exit aztcd_exit(void)
-{
-	del_gendisk(azt_disk);
-	put_disk(azt_disk);
-	if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
-		printk("What's that: can't unregister aztcd\n");
-		return;
-	}
-	blk_cleanup_queue(azt_queue);
-	if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
-		SWITCH_IDE_MASTER;
-		release_region(azt_port, 8);	/*IDE-interface */
-	} else
-		release_region(azt_port, 4);	/*proprietary interface */
-	printk(KERN_INFO "aztcd module released.\n");
-}
-
-module_init(aztcd_init);
-module_exit(aztcd_exit);
-
-/*##########################################################################
-  Aztcd State Machine: Controls Drive Operating State
-  ##########################################################################
-*/
-static void azt_poll(void)
-{
-	int st = 0;
-	int loop_ctl = 1;
-	int skip = 0;
-
-	if (azt_error) {
-		if (aztSendCmd(ACMD_GET_ERROR))
-			RETURN("azt_poll 1");
-		STEN_LOW;
-		azt_error = inb(DATA_PORT) & 0xFF;
-		printk("aztcd: I/O error 0x%02x\n", azt_error);
-		azt_invalidate_buffers();
-#ifdef WARN_IF_READ_FAILURE
-		if (AztTries == 5)
-			printk
-			    ("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n",
-			     azt_next_bn);
-#endif
-		if (!AztTries--) {
-			printk
-			    ("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n",
-			     azt_next_bn);
-			if (azt_transfer_is_active) {
-				AztTries = 0;
-				loop_ctl = 0;
-			}
-			if (current_valid())
-				end_request(CURRENT, 0);
-			AztTries = 5;
-		}
-		azt_error = 0;
-		azt_state = AZT_S_STOP;
-	}
-
-	while (loop_ctl) {
-		loop_ctl = 0;	/* each case must flip this back to 1 if we want
-				   to come back up here */
-		switch (azt_state) {
-
-		case AZT_S_IDLE:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_IDLE\n");
-			}
-#endif
-			return;
-
-		case AZT_S_START:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_START\n");
-			}
-#endif
-			if (aztSendCmd(ACMD_GET_STATUS))
-				RETURN("azt_poll 2");	/*result will be checked by aztStatus() */
-			azt_state =
-			    azt_mode == 1 ? AZT_S_READ : AZT_S_MODE;
-			AztTimeout = 3000;
-			break;
-
-		case AZT_S_MODE:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_MODE\n");
-			}
-#endif
-			if (!skip) {
-				if ((st = aztStatus()) != -1) {
-					if ((st & AST_DSK_CHG)
-					    || (st & AST_NOT_READY)) {
-						aztDiskChanged = 1;
-						aztTocUpToDate = 0;
-						azt_invalidate_buffers();
-						end_request(CURRENT, 0);
-						printk
-						    ("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n");
-					}
-				} else
-					break;
-			}
-			skip = 0;
-
-			if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
-				aztDiskChanged = 1;
-				aztTocUpToDate = 0;
-				printk
-				    ("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n");
-				end_request(CURRENT, 0);
-				printk((st & AST_DOOR_OPEN) ?
-				       "aztcd: door open\n" :
-				       "aztcd: disk removed\n");
-				if (azt_transfer_is_active) {
-					azt_state = AZT_S_START;
-					loop_ctl = 1;	/* goto immediately */
-					break;
-				}
-				azt_state = AZT_S_IDLE;
-				while (current_valid())
-					end_request(CURRENT, 0);
-				return;
-			}
-
-/*	  if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3");
-	  outb(0x01, DATA_PORT);
-	  PA_OK;
-	  STEN_LOW;
-*/
-			if (aztSendCmd(ACMD_GET_STATUS))
-				RETURN("azt_poll 4");
-			STEN_LOW;
-			azt_mode = 1;
-			azt_state = AZT_S_READ;
-			AztTimeout = 3000;
-
-			break;
-
-
-		case AZT_S_READ:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_READ\n");
-			}
-#endif
-			if (!skip) {
-				if ((st = aztStatus()) != -1) {
-					if ((st & AST_DSK_CHG)
-					    || (st & AST_NOT_READY)) {
-						aztDiskChanged = 1;
-						aztTocUpToDate = 0;
-						azt_invalidate_buffers();
-						printk
-						    ("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n");
-						end_request(CURRENT, 0);
-					}
-				} else
-					break;
-			}
-
-			skip = 0;
-			if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
-				aztDiskChanged = 1;
-				aztTocUpToDate = 0;
-				printk((st & AST_DOOR_OPEN) ?
-				       "aztcd: door open\n" :
-				       "aztcd: disk removed\n");
-				if (azt_transfer_is_active) {
-					azt_state = AZT_S_START;
-					loop_ctl = 1;
-					break;
-				}
-				azt_state = AZT_S_IDLE;
-				while (current_valid())
-					end_request(CURRENT, 0);
-				return;
-			}
-
-			if (current_valid()) {
-				struct azt_Play_msf msf;
-				int i;
-				azt_next_bn = CURRENT->sector / 4;
-				azt_hsg2msf(azt_next_bn, &msf.start);
-				i = 0;
-				/* find out in which track we are */
-				while (azt_msf2hsg(&msf.start) >
-				       azt_msf2hsg(&Toc[++i].trackTime)) {
-				};
-				if (azt_msf2hsg(&msf.start) <
-				    azt_msf2hsg(&Toc[i].trackTime) -
-				    AZT_BUF_SIZ) {
-					azt_read_count = AZT_BUF_SIZ;	/*fast, because we read ahead */
-					/*azt_read_count=CURRENT->nr_sectors;    slow, no read ahead */
-				} else	/* don't read beyond end of track */
-#if AZT_MULTISESSION
-				{
-					azt_read_count =
-					    (azt_msf2hsg(&Toc[i].trackTime)
-					     / 4) * 4 -
-					    azt_msf2hsg(&msf.start);
-					if (azt_read_count < 0)
-						azt_read_count = 0;
-					if (azt_read_count > AZT_BUF_SIZ)
-						azt_read_count =
-						    AZT_BUF_SIZ;
-					printk
-					    ("aztcd: warning - trying to read beyond end of track\n");
-/*               printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime));
-*/ }
-#else
-				{
-					azt_read_count = AZT_BUF_SIZ;
-				}
-#endif
-				msf.end.min = 0;
-				msf.end.sec = 0;
-				msf.end.frame = azt_read_count;	/*Mitsumi here reads 0xffffff sectors */
-#ifdef AZT_TEST3
-				printk
-				    ("---reading msf-address %x:%x:%x  %x:%x:%x\n",
-				     msf.start.min, msf.start.sec,
-				     msf.start.frame, msf.end.min,
-				     msf.end.sec, msf.end.frame);
-				printk
-				    ("azt_next_bn:%x  azt_buf_in:%x azt_buf_out:%x  azt_buf_bn:%x\n",
-				     azt_next_bn, azt_buf_in, azt_buf_out,
-				     azt_buf_bn[azt_buf_in]);
-#endif
-				if (azt_read_mode == AZT_MODE_2) {
-					sendAztCmd(ACMD_PLAY_READ_RAW, &msf);	/*XA disks in raw mode */
-				} else {
-					sendAztCmd(ACMD_PLAY_READ, &msf);	/*others in cooked mode */
-				}
-				azt_state = AZT_S_DATA;
-				AztTimeout = READ_TIMEOUT;
-			} else {
-				azt_state = AZT_S_STOP;
-				loop_ctl = 1;
-				break;
-			}
-
-			break;
-
-
-		case AZT_S_DATA:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_DATA\n");
-			}
-#endif
-
-			st = inb(STATUS_PORT) & AFL_STATUSorDATA;
-
-			switch (st) {
-
-			case AFL_DATA:
-#ifdef AZT_TEST3
-				if (st != azt_st_old) {
-					azt_st_old = st;
-					printk("---AFL_DATA st:%x\n", st);
-				}
-#endif
-				if (!AztTries--) {
-					printk
-					    ("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n",
-					     azt_next_bn);
-					if (azt_transfer_is_active) {
-						AztTries = 0;
-						break;
-					}
-					if (current_valid())
-						end_request(CURRENT, 0);
-					AztTries = 5;
-				}
-				azt_state = AZT_S_START;
-				AztTimeout = READ_TIMEOUT;
-				loop_ctl = 1;
-				break;
-
-			case AFL_STATUSorDATA:
-#ifdef AZT_TEST3
-				if (st != azt_st_old) {
-					azt_st_old = st;
-					printk
-					    ("---AFL_STATUSorDATA st:%x\n",
-					     st);
-				}
-#endif
-				break;
-
-			default:
-#ifdef AZT_TEST3
-				if (st != azt_st_old) {
-					azt_st_old = st;
-					printk("---default: st:%x\n", st);
-				}
-#endif
-				AztTries = 5;
-				if (!current_valid() && azt_buf_in == azt_buf_out) {
-					azt_state = AZT_S_STOP;
-					loop_ctl = 1;
-					break;
-				}
-				if (azt_read_count <= 0)
-					printk
-					    ("aztcd: warning - try to read 0 frames\n");
-				while (azt_read_count) {	/*??? fast read ahead loop */
-					azt_buf_bn[azt_buf_in] = -1;
-					DTEN_LOW;	/*??? unsolved problem, very
-							   seldom we get timeouts
-							   here, don't now the real
-							   reason. With my drive this
-							   sometimes also happens with
-							   Aztech's original driver under
-							   DOS. Is it a hardware bug? 
-							   I tried to recover from such
-							   situations here. Zimmermann */
-					if (aztTimeOutCount >= AZT_TIMEOUT) {
-						printk
-						    ("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n",
-						     azt_read_count,
-						     CURRENT->nr_sectors,
-						     azt_buf_in);
-						printk
-						    ("azt_transfer_is_active:%x\n",
-						     azt_transfer_is_active);
-						azt_read_count = 0;
-						azt_state = AZT_S_STOP;
-						loop_ctl = 1;
-						end_request(CURRENT, 1);	/*should we have here (1) or (0)? */
-					} else {
-						if (azt_read_mode ==
-						    AZT_MODE_2) {
-							insb(DATA_PORT,
-							     azt_buf +
-							     CD_FRAMESIZE_RAW
-							     * azt_buf_in,
-							     CD_FRAMESIZE_RAW);
-						} else {
-							insb(DATA_PORT,
-							     azt_buf +
-							     CD_FRAMESIZE *
-							     azt_buf_in,
-							     CD_FRAMESIZE);
-						}
-						azt_read_count--;
-#ifdef AZT_TEST3
-						printk
-						    ("AZT_S_DATA; ---I've read data- read_count: %d\n",
-						     azt_read_count);
-						printk
-						    ("azt_next_bn:%d  azt_buf_in:%d azt_buf_out:%d  azt_buf_bn:%d\n",
-						     azt_next_bn,
-						     azt_buf_in,
-						     azt_buf_out,
-						     azt_buf_bn
-						     [azt_buf_in]);
-#endif
-						azt_buf_bn[azt_buf_in] =
-						    azt_next_bn++;
-						if (azt_buf_out == -1)
-							azt_buf_out =
-							    azt_buf_in;
-						azt_buf_in =
-						    azt_buf_in + 1 ==
-						    AZT_BUF_SIZ ? 0 :
-						    azt_buf_in + 1;
-					}
-				}
-				if (!azt_transfer_is_active) {
-					while (current_valid()) {
-						azt_transfer();
-						if (CURRENT->nr_sectors ==
-						    0)
-							end_request(CURRENT, 1);
-						else
-							break;
-					}
-				}
-
-				if (current_valid()
-				    && (CURRENT->sector / 4 < azt_next_bn
-					|| CURRENT->sector / 4 >
-					azt_next_bn + AZT_BUF_SIZ)) {
-					azt_state = AZT_S_STOP;
-					loop_ctl = 1;
-					break;
-				}
-				AztTimeout = READ_TIMEOUT;
-				if (azt_read_count == 0) {
-					azt_state = AZT_S_STOP;
-					loop_ctl = 1;
-					break;
-				}
-				break;
-			}
-			break;
-
-
-		case AZT_S_STOP:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_STOP\n");
-			}
-#endif
-			if (azt_read_count != 0)
-				printk("aztcd: discard data=%x frames\n",
-				       azt_read_count);
-			while (azt_read_count != 0) {
-				int i;
-				if (!(inb(STATUS_PORT) & AFL_DATA)) {
-					if (azt_read_mode == AZT_MODE_2)
-						for (i = 0;
-						     i < CD_FRAMESIZE_RAW;
-						     i++)
-							inb(DATA_PORT);
-					else
-						for (i = 0;
-						     i < CD_FRAMESIZE; i++)
-							inb(DATA_PORT);
-				}
-				azt_read_count--;
-			}
-			if (aztSendCmd(ACMD_GET_STATUS))
-				RETURN("azt_poll 5");
-			azt_state = AZT_S_STOPPING;
-			AztTimeout = 1000;
-			break;
-
-		case AZT_S_STOPPING:
-#ifdef AZT_TEST3
-			if (azt_state != azt_state_old) {
-				azt_state_old = azt_state;
-				printk("AZT_S_STOPPING\n");
-			}
-#endif
-
-			if ((st = aztStatus()) == -1 && AztTimeout)
-				break;
-
-			if ((st != -1)
-			    && ((st & AST_DSK_CHG)
-				|| (st & AST_NOT_READY))) {
-				aztDiskChanged = 1;
-				aztTocUpToDate = 0;
-				azt_invalidate_buffers();
-				printk
-				    ("aztcd: Disk Changed or Not Ready 4 - Unmount Disk!\n");
-				end_request(CURRENT, 0);
-			}
-
-#ifdef AZT_TEST3
-			printk("CURRENT_VALID %d azt_mode %d\n",
-			       current_valid(), azt_mode);
-#endif
-
-			if (current_valid()) {
-				if (st != -1) {
-					if (azt_mode == 1) {
-						azt_state = AZT_S_READ;
-						loop_ctl = 1;
-						skip = 1;
-						break;
-					} else {
-						azt_state = AZT_S_MODE;
-						loop_ctl = 1;
-						skip = 1;
-						break;
-					}
-				} else {
-					azt_state = AZT_S_START;
-					AztTimeout = 1;
-				}
-			} else {
-				azt_state = AZT_S_IDLE;
-				return;
-			}
-			break;
-
-		default:
-			printk("aztcd: invalid state %d\n", azt_state);
-			return;
-		}		/* case */
-	}			/* while */
-
-
-	if (!AztTimeout--) {
-		printk("aztcd: timeout in state %d\n", azt_state);
-		azt_state = AZT_S_STOP;
-		if (aztSendCmd(ACMD_STOP))
-			RETURN("azt_poll 6");
-		STEN_LOW_WAIT;
-	};
-
-	SET_TIMER(azt_poll, HZ / 100);
-}
-
-
-/*###########################################################################
- * Miscellaneous support functions
-  ###########################################################################
-*/
-static void azt_hsg2msf(long hsg, struct msf *msf)
-{
-	hsg += 150;
-	msf->min = hsg / 4500;
-	hsg %= 4500;
-	msf->sec = hsg / 75;
-	msf->frame = hsg % 75;
-#ifdef AZT_DEBUG
-	if (msf->min >= 70)
-		printk("aztcd: Error hsg2msf address Minutes\n");
-	if (msf->sec >= 60)
-		printk("aztcd: Error hsg2msf address Seconds\n");
-	if (msf->frame >= 75)
-		printk("aztcd: Error hsg2msf address Frames\n");
-#endif
-	azt_bin2bcd(&msf->min);	/* convert to BCD */
-	azt_bin2bcd(&msf->sec);
-	azt_bin2bcd(&msf->frame);
-}
-
-static long azt_msf2hsg(struct msf *mp)
-{
-	return azt_bcd2bin(mp->frame) + azt_bcd2bin(mp->sec) * 75
-	    + azt_bcd2bin(mp->min) * 4500 - CD_MSF_OFFSET;
-}
-
-static void azt_bin2bcd(unsigned char *p)
-{
-	int u, t;
-
-	u = *p % 10;
-	t = *p / 10;
-	*p = u | (t << 4);
-}
-
-static int azt_bcd2bin(unsigned char bcd)
-{
-	return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(AZTECH_CDROM_MAJOR);
diff --git a/drivers/cdrom/aztcd.h b/drivers/cdrom/aztcd.h
deleted file mode 100644
index 057501e..0000000
--- a/drivers/cdrom/aztcd.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/* $Id: aztcd.h,v 2.60 1997/11/29 09:51:22 root Exp root $
- *
- * Definitions for a AztechCD268 CD-ROM interface
- *	Copyright (C) 1994-98  Werner Zimmermann
- *
- *	based on Mitsumi CDROM driver by Martin Harriss
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  History:	W.Zimmermann adaption to Aztech CD268-01A Version 1.3
- *		October 1994 Email: Werner.Zimmermann@fht-esslingen.de
- */
-
-/* *** change this to set the I/O port address of your CD-ROM drive,
-       set to '-1', if you want autoprobing */
-#define AZT_BASE_ADDR		-1
-
-/* list of autoprobing addresses (not more than 15), last value must be 0x000
-   Note: Autoprobing is only enabled, if AZT_BASE_ADDR is set to '-1' ! */
-#define AZT_BASE_AUTO 		{ 0x320, 0x300, 0x310, 0x330, 0x000 }
-
-/* Uncomment this, if your CDROM is connected to a Soundwave32-soundcard
-   and configure AZT_BASE_ADDR and AZT_SW32_BASE_ADDR */
-/*#define AZT_SW32 1
-*/
-
-#ifdef AZT_SW32 
-#define AZT_SW32_BASE_ADDR      0x220  /*I/O port base address of your soundcard*/
-#endif
-
-/* Set this to 1, if you want your tray to be locked, set to 0 to prevent tray 
-   from locking */
-#define AZT_ALLOW_TRAY_LOCK	1
-
-/*Set this to 1 to allow auto-eject when unmounting a disk, set to 0, if you 
-  don't want the auto-eject feature*/
-#define AZT_AUTO_EJECT          0
-
-/*Set this to 1, if you want to use incompatible ioctls for reading in raw and
-  cooked mode */
-#define AZT_PRIVATE_IOCTLS      1
-
-/*Set this to 1, if you want multisession support by the ISO fs. Even if you set 
-  this value to '0' you can use multisession CDs. In that case the drive's firm-
-  ware will do the appropriate redirection automatically. The CD will then look
-  like a single session CD (but nevertheless all data may be read). Please read 
-  chapter '5.1 Multisession support' in README.aztcd for details. Normally it's 
-  uncritical to leave this setting untouched */
-#define AZT_MULTISESSION        1
-
-/*Uncomment this, if you are using a linux kernel version prior to 2.1.0 */
-/*#define AZT_KERNEL_PRIOR_2_1 */
-
-/*---------------------------------------------------------------------------*/
-/*-----nothing to be configured for normal applications below this line------*/
-
-
-/* Increase this if you get lots of timeouts; if you get kernel panic, replace
-   STEN_LOW_WAIT by STEN_LOW in the source code */
-#define AZT_STATUS_DELAY	400       /*for timer wait, STEN_LOW_WAIT*/
-#define AZT_TIMEOUT		8000000   /*for busy wait STEN_LOW, DTEN_LOW*/
-#define AZT_FAST_TIMEOUT	10000     /*for reading the version string*/
-
-/* number of times to retry a command before giving up */
-#define AZT_RETRY_ATTEMPTS	3
-
-/* port access macros */
-#define CMD_PORT		azt_port
-#define DATA_PORT		azt_port
-#define STATUS_PORT		azt_port+1
-#define MODE_PORT		azt_port+2
-#ifdef  AZT_SW32                
- #define AZT_SW32_INIT          (unsigned int) (0xFF00 & (AZT_BASE_ADDR*16))
- #define AZT_SW32_CONFIG_REG    AZT_SW32_BASE_ADDR+0x16  /*Soundwave32 Config. Register*/
- #define AZT_SW32_ID_REG        AZT_SW32_BASE_ADDR+0x04  /*Soundwave32 ID Version Register*/
-#endif
-
-/* status bits */
-#define AST_CMD_CHECK		0x80		/* 1 = command error */
-#define AST_DOOR_OPEN		0x40		/* 1 = door is open */
-#define AST_NOT_READY		0x20		/* 1 = no disk in the drive */
-#define AST_DSK_CHG		0x02		/* 1 = disk removed or changed */
-#define AST_MODE                0x01            /* 0=MODE1, 1=MODE2 */
-#define AST_MODE_BITS		0x1C		/* Mode Bits */
-#define AST_INITIAL		0x0C		/* initial, only valid ... */
-#define AST_BUSY		0x04		/* now playing, only valid
-						   in combination with mode
-						   bits */
-/* flag bits */
-#define AFL_DATA		0x02		/* data available if low */
-#define AFL_STATUS		0x04		/* status available if low */
-#define AFL_OP_OK		0x01		/* OP_OK command correct*/
-#define AFL_PA_OK		0x02		/* PA_OK parameter correct*/
-#define AFL_OP_ERR		0x05		/* error in command*/
-#define AFL_PA_ERR		0x06		/* error in parameters*/
-#define POLLED			0x04		/* polled mode */
-
-/* commands */
-#define ACMD_SOFT_RESET		0x10		/* reset drive */
-#define ACMD_PLAY_READ		0x20		/* read data track in cooked mode */
-#define ACMD_PLAY_READ_RAW      0x21		/* reading in raw mode*/
-#define ACMD_SEEK               0x30            /* seek msf address*/
-#define ACMD_SEEK_TO_LEADIN     0x31		/* seek to leadin track*/
-#define ACMD_GET_ERROR		0x40		/* get error code */
-#define ACMD_GET_STATUS		0x41		/* get status */
-#define ACMD_GET_Q_CHANNEL      0x50		/* read info from q channel */
-#define ACMD_EJECT		0x60		/* eject/open tray */
-#define ACMD_CLOSE              0x61            /* close tray */
-#define ACMD_LOCK		0x71		/* lock tray closed */
-#define ACMD_UNLOCK		0x72		/* unlock tray */
-#define ACMD_PAUSE		0x80		/* pause */
-#define ACMD_STOP		0x81		/* stop play */
-#define ACMD_PLAY_AUDIO		0x90		/* play audio track */
-#define ACMD_SET_VOLUME		0x93		/* set audio level */
-#define ACMD_GET_VERSION	0xA0		/* get firmware version */
-#define ACMD_SET_DISK_TYPE	0xA1		/* set disk data mode */
-
-#define MAX_TRACKS		104
-
-struct msf {
-	unsigned char	min;
-	unsigned char	sec;
-	unsigned char	frame;
-};
-
-struct azt_Play_msf {
-	struct msf	start;
-	struct msf	end;
-};
-
-struct azt_DiskInfo {
-	unsigned char	first;
-        unsigned char   next;
-	unsigned char	last;
-	struct msf	diskLength;
-	struct msf	firstTrack;
-        unsigned char   multi;
-        struct msf      nextSession;
-        struct msf      lastSession;
-        unsigned char   xa;
-        unsigned char   audio;
-};
-
-struct azt_Toc {
-	unsigned char	ctrl_addr;
-	unsigned char	track;
-	unsigned char	pointIndex;
-	struct msf	trackTime;
-	struct msf	diskTime;
-};
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 3625a05..aa5468f 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -302,7 +302,7 @@
 module_param(check_media_type, bool, 0);
 module_param(mrw_format_restart, bool, 0);
 
-static DEFINE_SPINLOCK(cdrom_lock);
+static DEFINE_MUTEX(cdrom_mutex);
 
 static const char *mrw_format_status[] = {
 	"not mrw",
@@ -438,10 +438,10 @@
 		cdo->generic_packet = cdrom_dummy_generic_packet;
 
 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
-	spin_lock(&cdrom_lock);
+	mutex_lock(&cdrom_mutex);
 	cdi->next = topCdromPtr; 	
 	topCdromPtr = cdi;
-	spin_unlock(&cdrom_lock);
+	mutex_unlock(&cdrom_mutex);
 	return 0;
 }
 #undef ENSURE
@@ -452,7 +452,7 @@
 	cdinfo(CD_OPEN, "entering unregister_cdrom\n"); 
 
 	prev = NULL;
-	spin_lock(&cdrom_lock);
+	mutex_lock(&cdrom_mutex);
 	cdi = topCdromPtr;
 	while (cdi && cdi != unreg) {
 		prev = cdi;
@@ -460,7 +460,7 @@
 	}
 
 	if (cdi == NULL) {
-		spin_unlock(&cdrom_lock);
+		mutex_unlock(&cdrom_mutex);
 		return -2;
 	}
 	if (prev)
@@ -468,7 +468,7 @@
 	else
 		topCdromPtr = cdi->next;
 
-	spin_unlock(&cdrom_lock);
+	mutex_unlock(&cdrom_mutex);
 
 	if (cdi->exit)
 		cdi->exit(cdi);
@@ -3289,103 +3289,137 @@
 	int	check;			/* check media type */
 } cdrom_sysctl_settings;
 
+enum cdrom_print_option {
+	CTL_NAME,
+	CTL_SPEED,
+	CTL_SLOTS,
+	CTL_CAPABILITY
+};
+
+static int cdrom_print_info(const char *header, int val, char *info,
+				int *pos, enum cdrom_print_option option)
+{
+	const int max_size = sizeof(cdrom_sysctl_settings.info);
+	struct cdrom_device_info *cdi;
+	int ret;
+
+	ret = scnprintf(info + *pos, max_size - *pos, header);
+	if (!ret)
+		return 1;
+
+	*pos += ret;
+
+	for (cdi = topCdromPtr; cdi; cdi = cdi->next) {
+		switch (option) {
+		case CTL_NAME:
+			ret = scnprintf(info + *pos, max_size - *pos,
+					"\t%s", cdi->name);
+			break;
+		case CTL_SPEED:
+			ret = scnprintf(info + *pos, max_size - *pos,
+					"\t%d", cdi->speed);
+			break;
+		case CTL_SLOTS:
+			ret = scnprintf(info + *pos, max_size - *pos,
+					"\t%d", cdi->capacity);
+			break;
+		case CTL_CAPABILITY:
+			ret = scnprintf(info + *pos, max_size - *pos,
+					"\t%d", CDROM_CAN(val) != 0);
+			break;
+		default:
+			printk(KERN_INFO "cdrom: invalid option%d\n", option);
+			return 1;
+		}
+		if (!ret)
+			return 1;
+		*pos += ret;
+	}
+
+	return 0;
+}
+
 static int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
                            void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-        int pos;
-	struct cdrom_device_info *cdi;
+	int pos;
 	char *info = cdrom_sysctl_settings.info;
+	const int max_size = sizeof(cdrom_sysctl_settings.info);
 	
 	if (!*lenp || (*ppos && !write)) {
 		*lenp = 0;
 		return 0;
 	}
 
+	mutex_lock(&cdrom_mutex);
+
 	pos = sprintf(info, "CD-ROM information, " VERSION "\n");
 	
-	pos += sprintf(info+pos, "\ndrive name:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%s", cdi->name);
-
-	pos += sprintf(info+pos, "\ndrive speed:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", cdi->speed);
-
-	pos += sprintf(info+pos, "\ndrive # of slots:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", cdi->capacity);
-
-	pos += sprintf(info+pos, "\nCan close tray:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CLOSE_TRAY) != 0);
-
-	pos += sprintf(info+pos, "\nCan open tray:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_OPEN_TRAY) != 0);
-
-	pos += sprintf(info+pos, "\nCan lock tray:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_LOCK) != 0);
-
-	pos += sprintf(info+pos, "\nCan change speed:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_SPEED) != 0);
-
-	pos += sprintf(info+pos, "\nCan select disk:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_DISC) != 0);
-
-	pos += sprintf(info+pos, "\nCan read multisession:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MULTI_SESSION) != 0);
-
-	pos += sprintf(info+pos, "\nCan read MCN:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MCN) != 0);
-
-	pos += sprintf(info+pos, "\nReports media changed:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MEDIA_CHANGED) != 0);
-
-	pos += sprintf(info+pos, "\nCan play audio:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_PLAY_AUDIO) != 0);
-
-	pos += sprintf(info+pos, "\nCan write CD-R:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_R) != 0);
-
-	pos += sprintf(info+pos, "\nCan write CD-RW:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_RW) != 0);
-
-	pos += sprintf(info+pos, "\nCan read DVD:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD) != 0);
-
-	pos += sprintf(info+pos, "\nCan write DVD-R:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_R) != 0);
-
-	pos += sprintf(info+pos, "\nCan write DVD-RAM:");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
-
-	pos += sprintf(info+pos, "\nCan read MRW:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW) != 0);
-
-	pos += sprintf(info+pos, "\nCan write MRW:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW_W) != 0);
-
-	pos += sprintf(info+pos, "\nCan write RAM:\t");
-	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
-	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_RAM) != 0);
-
-	strcpy(info+pos,"\n\n");
-		
-        return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+	if (cdrom_print_info("\ndrive name:\t", 0, info, &pos, CTL_NAME))
+		goto done;
+	if (cdrom_print_info("\ndrive speed:\t", 0, info, &pos, CTL_SPEED))
+		goto done;
+	if (cdrom_print_info("\ndrive # of slots:", 0, info, &pos, CTL_SLOTS))
+		goto done;
+	if (cdrom_print_info("\nCan close tray:\t",
+				CDC_CLOSE_TRAY, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan open tray:\t",
+				CDC_OPEN_TRAY, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan lock tray:\t",
+				CDC_LOCK, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan change speed:",
+				CDC_SELECT_SPEED, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan select disk:",
+				CDC_SELECT_DISC, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan read multisession:",
+				CDC_MULTI_SESSION, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan read MCN:\t",
+				CDC_MCN, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nReports media changed:",
+				CDC_MEDIA_CHANGED, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan play audio:\t",
+				CDC_PLAY_AUDIO, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write CD-R:\t",
+				CDC_CD_R, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write CD-RW:",
+				CDC_CD_RW, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan read DVD:\t",
+				CDC_DVD, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write DVD-R:",
+				CDC_DVD_R, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write DVD-RAM:",
+				CDC_DVD_RAM, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan read MRW:\t",
+				CDC_MRW, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write MRW:\t",
+				CDC_MRW_W, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (cdrom_print_info("\nCan write RAM:\t",
+				CDC_RAM, info, &pos, CTL_CAPABILITY))
+		goto done;
+	if (!scnprintf(info + pos, max_size - pos, "\n\n"))
+		goto done;
+doit:
+	mutex_unlock(&cdrom_mutex);
+	return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+done:
+	printk(KERN_INFO "cdrom: info buffer too small\n");
+	goto doit;
 }
 
 /* Unfortunately, per device settings are not implemented through
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
deleted file mode 100644
index 2157c58..0000000
--- a/drivers/cdrom/cdu31a.c
+++ /dev/null
@@ -1,3251 +0,0 @@
-/*
-* Sony CDU-31A CDROM interface device driver.
-*
-* Corey Minyard (minyard@wf-rch.cirr.com)
-*
-* Colossians 3:17
-*
-*  See Documentation/cdrom/cdu31a for additional details about this driver.
-* 
-* The Sony interface device driver handles Sony interface CDROM
-* drives and provides a complete block-level interface as well as an
-* ioctl() interface compatible with the Sun (as specified in
-* include/linux/cdrom.h).  With this interface, CDROMs can be
-* accessed and standard audio CDs can be played back normally.
-*
-* WARNING - 	All autoprobes have been removed from the driver.
-*		You MUST configure the CDU31A via a LILO config
-*		at boot time or in lilo.conf.  I have the
-*		following in my lilo.conf:
-*
-*                append="cdu31a=0x1f88,0,PAS"
-*
-*		The first number is the I/O base address of the
-*		card.  The second is the interrupt (0 means none).
- *		The third should be "PAS" if on a Pro-Audio
- *		spectrum, or nothing if on something else.
- *
- * This interface is (unfortunately) a polled interface.  This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables.  Some (like mine) do not even have the capability to
- * handle interrupts or DMA.  For this reason you will see a lot of
- * the following:
- *
- *   retry_count = jiffies+ SONY_JIFFIES_TIMEOUT;
- *   while (time_before(jiffies, retry_count) && (! <some condition to wait for))
- *   {
- *      while (handle_sony_cd_attention())
- *         ;
- *
- *      sony_sleep();
- *   }
- *   if (the condition not met)
- *   {
- *      return an error;
- *   }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try.  it also handles attentions, which are
- * asynchronous events from the drive informing the driver that a disk
- * has been inserted, removed, etc.
- *
- * NEWS FLASH - The driver now supports interrupts but they are
- * turned off by default.  Use of interrupts is highly encouraged, it
- * cuts CPU usage down to a reasonable level.  I had DMA in for a while
- * but PC DMA is just too slow.  Better to just insb() it.
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk.  The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal.  A lot of conversion goes on.
- *
- * DRIVER SPECIAL FEATURES
- * -----------------------
- *
- * This section describes features beyond the normal audio and CD-ROM
- * functions of the drive.
- *
- * XA compatibility
- *
- * The driver should support XA disks for both the CDU31A and CDU33A.
- * It does this transparently, the using program doesn't need to set it.
- *
- * Multi-Session
- *
- * A multi-session disk looks just like a normal disk to the user.
- * Just mount one normally, and all the data should be there.
- * A special thanks to Koen for help with this!
- * 
- * Raw sector I/O
- *
- * Using the CDROMREADAUDIO it is possible to read raw audio and data
- * tracks.  Both operations return 2352 bytes per sector.  On the data
- * tracks, the first 12 bytes is not returned by the drive and the value
- * of that data is indeterminate.
- *
- *
- *  Copyright (C) 1993  Corey Minyard
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * TODO: 
- *       CDs with form1 and form2 sectors cause problems
- *       with current read-ahead strategy.
- *
- * Credits:
- *    Heiko Eissfeldt <heiko@colossus.escape.de>
- *         For finding abug in the return of the track numbers.
- *         TOC processing redone for proper multisession support.
- *
- *
- *  It probably a little late to be adding a history, but I guess I
- *  will start.
- *
- *  10/24/95 - Added support for disabling the eject button when the
- *             drive is open.  Note that there is a small problem
- *             still here, if the eject button is pushed while the
- *             drive light is flashing, the drive will return a bad
- *             status and be reset.  It recovers, though.
- *
- *  03/07/97 - Fixed a problem with timers.
- *
- *
- *  18 Spetember 1997 -- Ported to Uniform CD-ROM driver by 
- *                 Heiko Eissfeldt <heiko@colossus.escape.de> with additional
- *                 changes by Erik Andersen <andersee@debian.org>
- *
- *  24 January 1998 -- Removed the scd_disc_status() function, which was now
- *                     just dead code left over from the port.
- *                          Erik Andersen <andersee@debian.org>
- *
- *  16 July 1998 -- Drive donated to Erik Andersen by John Kodis
- *                   <kodis@jagunet.com>.  Work begun on fixing driver to
- *                   work under 2.1.X.  Added temporary extra printks
- *                   which seem to slow it down enough to work.
- *
- *  9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	               Removed init_module & cleanup_module in favor of 
- *		       module_init & module_exit.
- *		       Torben Mathiasen <tmm@image.dk>
- *
- * 22 October 2004 -- Make the driver work in 2.6.X
- *		      Added workaround to fix hard lockups on eject
- *		      Fixed door locking problem after mounting empty drive
- *		      Set double-speed drives to double speed by default
- *		      Removed all readahead things - not needed anymore
- *			Ondrej Zary <rainbow@rainbow-software.org>
-*/
-
-#define DEBUG 1
-
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/cdrom.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/dma.h>
-
-#include "cdu31a.h"
-
-#define MAJOR_NR CDU31A_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
-
-#define PFX "CDU31A: "
-
-/*
-** Edit the following data to change interrupts, DMA channels, etc.
-** Default is polled and no DMA.  DMA is not recommended for double-speed
-** drives.
-*/
-static struct {
-	unsigned short base;	/* I/O Base Address */
-	short int_num;		/* Interrupt Number (-1 means scan for it,
-				   0 means don't use) */
-} cdu31a_addresses[] __initdata = {
-	{0}
-};
-
-static int handle_sony_cd_attention(void);
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int scd_spinup(void);
-/*static int scd_open(struct inode *inode, struct file *filp);*/
-static int scd_open(struct cdrom_device_info *, int);
-static void do_sony_cd_cmd(unsigned char cmd,
-			   unsigned char *params,
-			   unsigned int num_params,
-			   unsigned char *result_buffer,
-			   unsigned int *result_size);
-static void size_to_buf(unsigned int size, unsigned char *buf);
-
-/* Parameters for the read-ahead. */
-static unsigned int sony_next_block;	/* Next 512 byte block offset */
-static unsigned int sony_blocks_left = 0;	/* Number of 512 byte blocks left
-						   in the current read command. */
-
-
-/* The base I/O address of the Sony Interface.  This is a variable (not a
-   #define) so it can be easily changed via some future ioctl() */
-static unsigned int cdu31a_port = 0;
-module_param(cdu31a_port, uint, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive.  The
- * comment for the base address also applies here.
- */
-static volatile unsigned short sony_cd_cmd_reg;
-static volatile unsigned short sony_cd_param_reg;
-static volatile unsigned short sony_cd_write_reg;
-static volatile unsigned short sony_cd_control_reg;
-static volatile unsigned short sony_cd_status_reg;
-static volatile unsigned short sony_cd_result_reg;
-static volatile unsigned short sony_cd_read_reg;
-static volatile unsigned short sony_cd_fifost_reg;
-
-static struct request_queue *cdu31a_queue;
-static DEFINE_SPINLOCK(cdu31a_lock); /* queue lock */
-
-static int sony_spun_up = 0;	/* Has the drive been spun up? */
-
-static int sony_speed = 0;	/* Last wanted speed */
-
-static int sony_xa_mode = 0;	/* Is an XA disk in the drive
-				   and the drive a CDU31A? */
-
-static int sony_raw_data_mode = 1;	/* 1 if data tracks, 0 if audio.
-					   For raw data reads. */
-
-static unsigned int sony_usage = 0;	/* How many processes have the
-					   drive open. */
-
-static int sony_pas_init = 0;	/* Initialize the Pro-Audio
-				   Spectrum card? */
-
-static struct s_sony_session_toc single_toc;	/* Holds the
-						   table of
-						   contents. */
-
-static struct s_all_sessions_toc sony_toc;	/* entries gathered from all
-						   sessions */
-
-static int sony_toc_read = 0;	/* Has the TOC been read for
-				   the drive? */
-
-static struct s_sony_subcode last_sony_subcode;	/* Points to the last
-						   subcode address read */
-
-static DECLARE_MUTEX(sony_sem);		/* Semaphore for drive hardware access */
-
-static int is_double_speed = 0;	/* does the drive support double speed ? */
-
-static int is_auto_eject = 1;	/* Door has been locked? 1=No/0=Yes */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static volatile int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play.  The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over.  This holds the
- * position during a pause so a resume can restart it.  It uses the
- * audio status variable above to tell if it is paused.
- */
-static unsigned volatile char cur_pos_msf[3] = { 0, 0, 0 };
-static unsigned volatile char final_pos_msf[3] = { 0, 0, 0 };
-
-/* What IRQ is the drive using?  0 if none. */
-static int cdu31a_irq = 0;
-module_param(cdu31a_irq, int, 0);
-
-/* The interrupt handler will wake this queue up when it gets an
-   interrupts. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
-static int irq_flag = 0;
-
-static int curr_control_reg = 0;	/* Current value of the control register */
-
-/* A disk changed variable.  When a disk change is detected, it will
-   all be set to TRUE.  As the upper layers ask for disk_changed status
-   it will be cleared. */
-static char disk_changed;
-
-/* This was readahead_buffer once... Now it's used only for audio reads */
-static char audio_buffer[CD_FRAMESIZE_RAW];
-
-/* Used to time a short period to abort an operation after the
-   drive has been idle for a while.  This keeps the light on
-   the drive from flashing for very long. */
-static struct timer_list cdu31a_abort_timer;
-
-/* Marks if the timeout has started an abort read.  This is used
-   on entry to the drive to tell the code to read out the status
-   from the abort read. */
-static int abort_read_started = 0;
-
-/*
- * Uniform cdrom interface function
- * report back, if disc has changed from time of last request.
- */
-static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
-	int retval;
-
-	retval = disk_changed;
-	disk_changed = 0;
-
-	return retval;
-}
-
-/*
- * Uniform cdrom interface function
- * report back, if drive is ready
- */
-static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
-	if (CDSL_CURRENT != slot_nr)
-		/* we have no changer support */
-		return -EINVAL;
-	if (sony_spun_up)
-		return CDS_DISC_OK;
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	if (scd_spinup() == 0)
-		sony_spun_up = 1;
-	up(&sony_sem);
-	return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
-}
-
-static inline void enable_interrupts(void)
-{
-	curr_control_reg |= (SONY_ATTN_INT_EN_BIT
-			     | SONY_RES_RDY_INT_EN_BIT
-			     | SONY_DATA_RDY_INT_EN_BIT);
-	outb(curr_control_reg, sony_cd_control_reg);
-}
-
-static inline void disable_interrupts(void)
-{
-	curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
-			      | SONY_RES_RDY_INT_EN_BIT
-			      | SONY_DATA_RDY_INT_EN_BIT);
-	outb(curr_control_reg, sony_cd_control_reg);
-}
-
-/*
- * Wait a little while (used for polling the drive).  If in initialization,
- * setting a timeout doesn't work, so just loop for a while.
- */
-static inline void sony_sleep(void)
-{
-	if (cdu31a_irq <= 0) {
-		yield();
-	} else {		/* Interrupt driven */
-		DEFINE_WAIT(w);
-		int first = 1;
-
-		while (1) {
-			prepare_to_wait(&cdu31a_irq_wait, &w,
-					TASK_INTERRUPTIBLE);
-			if (first) {
-				enable_interrupts();
-				first = 0;
-			}
-
-			if (irq_flag != 0)
-				break;
-			if (!signal_pending(current)) {
-				schedule();
-				continue;
-			} else
-				disable_interrupts();
-			break;
-		}
-		finish_wait(&cdu31a_irq_wait, &w);
-		irq_flag = 0;
-	}
-}
-
-
-/*
- * The following are convenience routine to read various status and set
- * various conditions in the drive.
- */
-static inline int is_attention(void)
-{
-	return (inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0;
-}
-
-static inline int is_busy(void)
-{
-	return (inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0;
-}
-
-static inline int is_data_ready(void)
-{
-	return (inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0;
-}
-
-static inline int is_data_requested(void)
-{
-	return (inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0;
-}
-
-static inline int is_result_ready(void)
-{
-	return (inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0;
-}
-
-static inline int is_param_write_rdy(void)
-{
-	return (inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0;
-}
-
-static inline int is_result_reg_not_empty(void)
-{
-	return (inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0;
-}
-
-static inline void reset_drive(void)
-{
-	curr_control_reg = 0;
-	sony_toc_read = 0;
-	outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg);
-}
-
-/*
- * Uniform cdrom interface function
- * reset drive and return when it is ready
- */
-static int scd_reset(struct cdrom_device_info *cdi)
-{
-	unsigned long retry_count;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	reset_drive();
-
-	retry_count = jiffies + SONY_RESET_TIMEOUT;
-	while (time_before(jiffies, retry_count) && (!is_attention())) {
-		sony_sleep();
-	}
-
-	up(&sony_sem);
-	return 0;
-}
-
-static inline void clear_attention(void)
-{
-	outb(curr_control_reg | SONY_ATTN_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_result_ready(void)
-{
-	outb(curr_control_reg | SONY_RES_RDY_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_data_ready(void)
-{
-	outb(curr_control_reg | SONY_DATA_RDY_CLR_BIT,
-	     sony_cd_control_reg);
-}
-
-static inline void clear_param_reg(void)
-{
-	outb(curr_control_reg | SONY_PARAM_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline unsigned char read_status_register(void)
-{
-	return inb(sony_cd_status_reg);
-}
-
-static inline unsigned char read_result_register(void)
-{
-	return inb(sony_cd_result_reg);
-}
-
-static inline unsigned char read_data_register(void)
-{
-	return inb(sony_cd_read_reg);
-}
-
-static inline void write_param(unsigned char param)
-{
-	outb(param, sony_cd_param_reg);
-}
-
-static inline void write_cmd(unsigned char cmd)
-{
-	outb(curr_control_reg | SONY_RES_RDY_INT_EN_BIT,
-	     sony_cd_control_reg);
-	outb(cmd, sony_cd_cmd_reg);
-}
-
-static irqreturn_t cdu31a_interrupt(int irq, void *dev_id)
-{
-	unsigned char val;
-
-	if (abort_read_started) {
-		/* We might be waiting for an abort to finish.  Don't
-		   disable interrupts yet, though, because we handle
-		   this one here. */
-		/* Clear out the result registers. */
-		while (is_result_reg_not_empty()) {
-			val = read_result_register();
-		}
-		clear_data_ready();
-		clear_result_ready();
-
-		/* Clear out the data */
-		while (is_data_requested()) {
-			val = read_data_register();
-		}
-		abort_read_started = 0;
-
-		/* If something was waiting, wake it up now. */
-		if (waitqueue_active(&cdu31a_irq_wait)) {
-			disable_interrupts();
-			irq_flag = 1;
-			wake_up_interruptible(&cdu31a_irq_wait);
-		}
-	} else if (waitqueue_active(&cdu31a_irq_wait)) {
-		disable_interrupts();
-		irq_flag = 1;
-		wake_up_interruptible(&cdu31a_irq_wait);
-	} else {
-		disable_interrupts();
-		printk(KERN_NOTICE PFX
-				"Got an interrupt but nothing was waiting\n");
-	}
-	return IRQ_HANDLED;
-}
-
-/*
- * give more verbose error messages
- */
-static unsigned char *translate_error(unsigned char err_code)
-{
-	static unsigned char errbuf[80];
-
-	switch (err_code) {
-		case 0x10: return "illegal command ";
-		case 0x11: return "illegal parameter ";
-
-		case 0x20: return "not loaded ";
-		case 0x21: return "no disc ";
-		case 0x22: return "not spinning ";
-		case 0x23: return "spinning ";
-		case 0x25: return "spindle servo ";
-		case 0x26: return "focus servo ";
-		case 0x29: return "eject mechanism ";
-		case 0x2a: return "audio playing ";
-		case 0x2c: return "emergency eject ";
-
-		case 0x30: return "focus ";
-		case 0x31: return "frame sync ";
-		case 0x32: return "subcode address ";
-		case 0x33: return "block sync ";
-		case 0x34: return "header address ";
-
-		case 0x40: return "illegal track read ";
-		case 0x41: return "mode 0 read ";
-		case 0x42: return "illegal mode read ";
-		case 0x43: return "illegal block size read ";
-		case 0x44: return "mode read ";
-		case 0x45: return "form read ";
-		case 0x46: return "leadout read ";
-		case 0x47: return "buffer overrun ";
-
-		case 0x53: return "unrecoverable CIRC ";
-		case 0x57: return "unrecoverable LECC ";
-
-		case 0x60: return "no TOC ";
-		case 0x61: return "invalid subcode data ";
-		case 0x63: return "focus on TOC read ";
-		case 0x64: return "frame sync on TOC read ";
-		case 0x65: return "TOC data ";
-
-		case 0x70: return "hardware failure ";
-		case 0x91: return "leadin ";
-		case 0x92: return "leadout ";
-		case 0x93: return "data track ";
-	}
-	sprintf(errbuf, "unknown 0x%02x ", err_code);
-	return errbuf;
-}
-
-/*
- * Set the drive parameters so the drive will auto-spin-up when a
- * disk is inserted.
- */
-static void set_drive_params(int want_doublespeed)
-{
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	unsigned char params[3];
-
-
-	params[0] = SONY_SD_AUTO_SPIN_DOWN_TIME;
-	params[1] = 0x00;	/* Never spin down the drive. */
-	do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-		       params, 2, res_reg, &res_size);
-	if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-		printk(KERN_NOTICE PFX
-			"Unable to set spin-down time: 0x%2.2x\n", res_reg[1]);
-	}
-
-	params[0] = SONY_SD_MECH_CONTROL;
-	params[1] = SONY_AUTO_SPIN_UP_BIT;	/* Set auto spin up */
-
-	if (is_auto_eject)
-		params[1] |= SONY_AUTO_EJECT_BIT;
-
-	if (is_double_speed && want_doublespeed) {
-		params[1] |= SONY_DOUBLE_SPEED_BIT;	/* Set the drive to double speed if 
-							   possible */
-	}
-	do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-		       params, 2, res_reg, &res_size);
-	if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-		printk(KERN_NOTICE PFX "Unable to set mechanical "
-				"parameters: 0x%2.2x\n", res_reg[1]);
-	}
-}
-
-/*
- * Uniform cdrom interface function
- * select reading speed for data access
- */
-static int scd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
-	if (speed == 0)
-		sony_speed = 1;
-	else
-		sony_speed = speed - 1;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	set_drive_params(sony_speed);
-	up(&sony_sem);
-	return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * lock or unlock eject button
- */
-static int scd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
-	if (lock == 0) {
-		is_auto_eject = 1;
-	} else {
-		is_auto_eject = 0;
-	}
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	set_drive_params(sony_speed);
-	up(&sony_sem);
-	return 0;
-}
-
-/*
- * This code will reset the drive and attempt to restore sane parameters.
- */
-static void restart_on_error(void)
-{
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	unsigned long retry_count;
-
-
-	printk(KERN_NOTICE PFX "Resetting drive on error\n");
-	reset_drive();
-	retry_count = jiffies + SONY_RESET_TIMEOUT;
-	while (time_before(jiffies, retry_count) && (!is_attention())) {
-		sony_sleep();
-	}
-	set_drive_params(sony_speed);
-	do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
-	if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-		printk(KERN_NOTICE PFX "Unable to spin up drive: 0x%2.2x\n",
-		       res_reg[1]);
-	}
-
-	msleep(2000);
-
-	sony_get_toc();
-}
-
-/*
- * This routine writes data to the parameter register.  Since this should
- * happen fairly fast, it is polled with no OS waits between.
- */
-static int write_params(unsigned char *params, int num_params)
-{
-	unsigned int retry_count;
-
-
-	retry_count = SONY_READY_RETRIES;
-	while ((retry_count > 0) && (!is_param_write_rdy())) {
-		retry_count--;
-	}
-	if (!is_param_write_rdy()) {
-		return -EIO;
-	}
-
-	while (num_params > 0) {
-		write_param(*params);
-		params++;
-		num_params--;
-	}
-
-	return 0;
-}
-
-
-/*
- * The following reads data from the command result register.  It is a
- * fairly complex routine, all status info flows back through this
- * interface.  The algorithm is stolen directly from the flowcharts in
- * the drive manual.
- */
-static void
-get_result(unsigned char *result_buffer, unsigned int *result_size)
-{
-	unsigned char a, b;
-	int i;
-	unsigned long retry_count;
-
-
-	while (handle_sony_cd_attention());
-	/* Wait for the result data to be ready */
-	retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-	while (time_before(jiffies, retry_count)
-	       && (is_busy() || (!(is_result_ready())))) {
-		sony_sleep();
-
-		while (handle_sony_cd_attention());
-	}
-	if (is_busy() || (!(is_result_ready()))) {
-		pr_debug(PFX "timeout out %d\n", __LINE__);
-		result_buffer[0] = 0x20;
-		result_buffer[1] = SONY_TIMEOUT_OP_ERR;
-		*result_size = 2;
-		return;
-	}
-
-	/*
-	 * Get the first two bytes.  This determines what else needs
-	 * to be done.
-	 */
-	clear_result_ready();
-	a = read_result_register();
-	*result_buffer = a;
-	result_buffer++;
-
-	/* Check for block error status result. */
-	if ((a & 0xf0) == 0x50) {
-		*result_size = 1;
-		return;
-	}
-
-	b = read_result_register();
-	*result_buffer = b;
-	result_buffer++;
-	*result_size = 2;
-
-	/*
-	 * 0x20 means an error occurred.  Byte 2 will have the error code.
-	 * Otherwise, the command succeeded, byte 2 will have the count of
-	 * how many more status bytes are coming.
-	 *
-	 * The result register can be read 10 bytes at a time, a wait for
-	 * result ready to be asserted must be done between every 10 bytes.
-	 */
-	if ((a & 0xf0) != 0x20) {
-		if (b > 8) {
-			for (i = 0; i < 8; i++) {
-				*result_buffer = read_result_register();
-				result_buffer++;
-				(*result_size)++;
-			}
-			b = b - 8;
-
-			while (b > 10) {
-				retry_count = SONY_READY_RETRIES;
-				while ((retry_count > 0)
-				       && (!is_result_ready())) {
-					retry_count--;
-				}
-				if (!is_result_ready()) {
-					pr_debug(PFX "timeout out %d\n",
-					       __LINE__);
-					result_buffer[0] = 0x20;
-					result_buffer[1] =
-					    SONY_TIMEOUT_OP_ERR;
-					*result_size = 2;
-					return;
-				}
-
-				clear_result_ready();
-
-				for (i = 0; i < 10; i++) {
-					*result_buffer =
-					    read_result_register();
-					result_buffer++;
-					(*result_size)++;
-				}
-				b = b - 10;
-			}
-
-			if (b > 0) {
-				retry_count = SONY_READY_RETRIES;
-				while ((retry_count > 0)
-				       && (!is_result_ready())) {
-					retry_count--;
-				}
-				if (!is_result_ready()) {
-					pr_debug(PFX "timeout out %d\n",
-					       __LINE__);
-					result_buffer[0] = 0x20;
-					result_buffer[1] =
-					    SONY_TIMEOUT_OP_ERR;
-					*result_size = 2;
-					return;
-				}
-			}
-		}
-
-		while (b > 0) {
-			*result_buffer = read_result_register();
-			result_buffer++;
-			(*result_size)++;
-			b--;
-		}
-	}
-}
-
-/*
- * Do a command that does not involve data transfer.  This routine must
- * be re-entrant from the same task to support being called from the
- * data operation code when an error occurs.
- */
-static void
-do_sony_cd_cmd(unsigned char cmd,
-	       unsigned char *params,
-	       unsigned int num_params,
-	       unsigned char *result_buffer, unsigned int *result_size)
-{
-	unsigned long retry_count;
-	int num_retries = 0;
-
-retry_cd_operation:
-
-	while (handle_sony_cd_attention());
-
-	retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-	while (time_before(jiffies, retry_count) && (is_busy())) {
-		sony_sleep();
-
-		while (handle_sony_cd_attention());
-	}
-	if (is_busy()) {
-		pr_debug(PFX "timeout out %d\n", __LINE__);
-		result_buffer[0] = 0x20;
-		result_buffer[1] = SONY_TIMEOUT_OP_ERR;
-		*result_size = 2;
-	} else {
-		clear_result_ready();
-		clear_param_reg();
-
-		write_params(params, num_params);
-		write_cmd(cmd);
-
-		get_result(result_buffer, result_size);
-	}
-
-	if (((result_buffer[0] & 0xf0) == 0x20)
-	    && (num_retries < MAX_CDU31A_RETRIES)) {
-		num_retries++;
-		msleep(100);
-		goto retry_cd_operation;
-	}
-}
-
-
-/*
- * Handle an attention from the drive.  This will return 1 if it found one
- * or 0 if not (if one is found, the caller might want to call again).
- *
- * This routine counts the number of consecutive times it is called
- * (since this is always called from a while loop until it returns
- * a 0), and returns a 0 if it happens too many times.  This will help
- * prevent a lockup.
- */
-static int handle_sony_cd_attention(void)
-{
-	unsigned char atten_code;
-	static int num_consecutive_attentions = 0;
-	volatile int val;
-
-
-#if 0
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-#endif
-	if (is_attention()) {
-		if (num_consecutive_attentions >
-		    CDU31A_MAX_CONSECUTIVE_ATTENTIONS) {
-			printk(KERN_NOTICE PFX "Too many consecutive "
-				"attentions: %d\n", num_consecutive_attentions);
-			num_consecutive_attentions = 0;
-			pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__,
-			       __LINE__);
-			return 0;
-		}
-
-		clear_attention();
-		atten_code = read_result_register();
-
-		switch (atten_code) {
-			/* Someone changed the CD.  Mark it as changed */
-		case SONY_MECH_LOADED_ATTN:
-			disk_changed = 1;
-			sony_toc_read = 0;
-			sony_audio_status = CDROM_AUDIO_NO_STATUS;
-			sony_blocks_left = 0;
-			break;
-
-		case SONY_SPIN_DOWN_COMPLETE_ATTN:
-			/* Mark the disk as spun down. */
-			sony_spun_up = 0;
-			break;
-
-		case SONY_AUDIO_PLAY_DONE_ATTN:
-			sony_audio_status = CDROM_AUDIO_COMPLETED;
-			read_subcode();
-			break;
-
-		case SONY_EJECT_PUSHED_ATTN:
-			if (is_auto_eject) {
-				sony_audio_status = CDROM_AUDIO_INVALID;
-			}
-			break;
-
-		case SONY_LEAD_IN_ERR_ATTN:
-		case SONY_LEAD_OUT_ERR_ATTN:
-		case SONY_DATA_TRACK_ERR_ATTN:
-		case SONY_AUDIO_PLAYBACK_ERR_ATTN:
-			sony_audio_status = CDROM_AUDIO_ERROR;
-			break;
-		}
-
-		num_consecutive_attentions++;
-		pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-		return 1;
-	} else if (abort_read_started) {
-		while (is_result_reg_not_empty()) {
-			val = read_result_register();
-		}
-		clear_data_ready();
-		clear_result_ready();
-		/* Clear out the data */
-		while (is_data_requested()) {
-			val = read_data_register();
-		}
-		abort_read_started = 0;
-		pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-		return 1;
-	}
-
-	num_consecutive_attentions = 0;
-#if 0
-	pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-#endif
-	return 0;
-}
-
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int int_to_bcd(unsigned int val)
-{
-	int retval;
-
-
-	retval = (val / 10) << 4;
-	retval = retval | val % 10;
-	return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int bcd_to_int(unsigned int bcd)
-{
-	return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void log_to_msf(unsigned int log, unsigned char *msf)
-{
-	log = log + LOG_START_OFFSET;
-	msf[0] = int_to_bcd(log / 4500);
-	log = log % 4500;
-	msf[1] = int_to_bcd(log / 75);
-	msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int msf_to_log(unsigned char *msf)
-{
-	unsigned int log;
-
-
-	log = msf[2];
-	log += msf[1] * 75;
-	log += msf[0] * 4500;
-	log = log - LOG_START_OFFSET;
-
-	return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void size_to_buf(unsigned int size, unsigned char *buf)
-{
-	buf[0] = size / 65536;
-	size = size % 65536;
-	buf[1] = size / 256;
-	buf[2] = size % 256;
-}
-
-/* Starts a read operation. Returns 0 on success and 1 on failure. 
-   The read operation used here allows multiple sequential sectors 
-   to be read and status returned for each sector.  The driver will
-   read the output one at a time as the requests come and abort the
-   operation if the requested sector is not the next one from the
-   drive. */
-static int
-start_request(unsigned int sector, unsigned int nsect)
-{
-	unsigned char params[6];
-	unsigned long retry_count;
-
-
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-	log_to_msf(sector, params);
-	size_to_buf(nsect, &params[3]);
-
-	/*
-	 * Clear any outstanding attentions and wait for the drive to
-	 * complete any pending operations.
-	 */
-	while (handle_sony_cd_attention());
-
-	retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-	while (time_before(jiffies, retry_count) && (is_busy())) {
-		sony_sleep();
-
-		while (handle_sony_cd_attention());
-	}
-
-	if (is_busy()) {
-		printk(KERN_NOTICE PFX "Timeout while waiting "
-				"to issue command\n");
-		pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-		return 1;
-	} else {
-		/* Issue the command */
-		clear_result_ready();
-		clear_param_reg();
-
-		write_params(params, 6);
-		write_cmd(SONY_READ_BLKERR_STAT_CMD);
-
-		sony_blocks_left = nsect * 4;
-		sony_next_block = sector * 4;
-		pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-		return 0;
-	}
-	pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-/* Abort a pending read operation.  Clear all the drive status variables. */
-static void abort_read(void)
-{
-	unsigned char result_reg[2];
-	int result_size;
-	volatile int val;
-
-
-	do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size);
-	if ((result_reg[0] & 0xf0) == 0x20) {
-		printk(KERN_ERR PFX "Aborting read, %s error\n",
-		       translate_error(result_reg[1]));
-	}
-
-	while (is_result_reg_not_empty()) {
-		val = read_result_register();
-	}
-	clear_data_ready();
-	clear_result_ready();
-	/* Clear out the data */
-	while (is_data_requested()) {
-		val = read_data_register();
-	}
-
-	sony_blocks_left = 0;
-}
-
-/* Called when the timer times out.  This will abort the
-   pending read operation. */
-static void handle_abort_timeout(unsigned long data)
-{
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-	/* If it is in use, ignore it. */
-	if (down_trylock(&sony_sem) == 0) {
-		/* We can't use abort_read(), because it will sleep
-		   or schedule in the timer interrupt.  Just start
-		   the operation, finish it on the next access to
-		   the drive. */
-		clear_result_ready();
-		clear_param_reg();
-		write_cmd(SONY_ABORT_CMD);
-
-		sony_blocks_left = 0;
-		abort_read_started = 1;
-		up(&sony_sem);
-	}
-	pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* Actually get one sector of data from the drive. */
-static void
-input_data_sector(char *buffer)
-{
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-	/* If an XA disk on a CDU31A, skip the first 12 bytes of data from
-	   the disk.  The real data is after that. We can use audio_buffer. */
-	if (sony_xa_mode)
-		insb(sony_cd_read_reg, audio_buffer, CD_XA_HEAD);
-
-	clear_data_ready();
-
-	insb(sony_cd_read_reg, buffer, 2048);
-
-	/* If an XA disk, we have to clear out the rest of the unused
-	   error correction data. We can use audio_buffer for that. */
-	if (sony_xa_mode)
-		insb(sony_cd_read_reg, audio_buffer, CD_XA_TAIL);
-
-	pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* read data from the drive.  Note the nsect must be <= 4. */
-static void
-read_data_block(char *buffer,
-		unsigned int block,
-		unsigned int nblocks,
-		unsigned char res_reg[], int *res_size)
-{
-	unsigned long retry_count;
-
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-	res_reg[0] = 0;
-	res_reg[1] = 0;
-	*res_size = 0;
-
-	/* Wait for the drive to tell us we have something */
-	retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-	while (time_before(jiffies, retry_count) && !(is_data_ready())) {
-		while (handle_sony_cd_attention());
-
-		sony_sleep();
-	}
-	if (!(is_data_ready())) {
-		if (is_result_ready()) {
-			get_result(res_reg, res_size);
-			if ((res_reg[0] & 0xf0) != 0x20) {
-				printk(KERN_NOTICE PFX "Got result that should"
-					" have been error: %d\n", res_reg[0]);
-				res_reg[0] = 0x20;
-				res_reg[1] = SONY_BAD_DATA_ERR;
-				*res_size = 2;
-			}
-			abort_read();
-		} else {
-			pr_debug(PFX "timeout out %d\n", __LINE__);
-			res_reg[0] = 0x20;
-			res_reg[1] = SONY_TIMEOUT_OP_ERR;
-			*res_size = 2;
-			abort_read();
-		}
-	} else {
-		input_data_sector(buffer);
-		sony_blocks_left -= nblocks;
-		sony_next_block += nblocks;
-
-		/* Wait for the status from the drive. */
-		retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-		while (time_before(jiffies, retry_count)
-		       && !(is_result_ready())) {
-			while (handle_sony_cd_attention());
-
-			sony_sleep();
-		}
-
-		if (!is_result_ready()) {
-			pr_debug(PFX "timeout out %d\n", __LINE__);
-			res_reg[0] = 0x20;
-			res_reg[1] = SONY_TIMEOUT_OP_ERR;
-			*res_size = 2;
-			abort_read();
-		} else {
-			get_result(res_reg, res_size);
-
-			/* If we got a buffer status, handle that. */
-			if ((res_reg[0] & 0xf0) == 0x50) {
-
-				if ((res_reg[0] ==
-				     SONY_NO_CIRC_ERR_BLK_STAT)
-				    || (res_reg[0] ==
-					SONY_NO_LECC_ERR_BLK_STAT)
-				    || (res_reg[0] ==
-					SONY_RECOV_LECC_ERR_BLK_STAT)) {
-					/* nothing here */
-				} else {
-					printk(KERN_ERR PFX "Data block "
-						"error: 0x%x\n", res_reg[0]);
-					res_reg[0] = 0x20;
-					res_reg[1] = SONY_BAD_DATA_ERR;
-					*res_size = 2;
-				}
-
-				/* Final transfer is done for read command, get final result. */
-				if (sony_blocks_left == 0) {
-					get_result(res_reg, res_size);
-				}
-			} else if ((res_reg[0] & 0xf0) != 0x20) {
-				/* The drive gave me bad status, I don't know what to do.
-				   Reset the driver and return an error. */
-				printk(KERN_ERR PFX "Invalid block "
-					"status: 0x%x\n", res_reg[0]);
-				restart_on_error();
-				res_reg[0] = 0x20;
-				res_reg[1] = SONY_BAD_DATA_ERR;
-				*res_size = 2;
-			}
-		}
-	}
-	pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail.  Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations.  This especially helps since the OS
- * uses 1024 byte blocks and the drive uses 2048 byte blocks.  Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void do_cdu31a_request(request_queue_t * q)
-{
-	struct request *req;
-	int block, nblock, num_retries;
-	unsigned char res_reg[12];
-	unsigned int res_size;
-
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-	spin_unlock_irq(q->queue_lock);
-	if (down_interruptible(&sony_sem)) {
-		spin_lock_irq(q->queue_lock);
-		return;
-	}
-
-	/* Get drive status before doing anything. */
-	while (handle_sony_cd_attention());
-
-	/* Make sure we have a valid TOC. */
-	sony_get_toc();
-
-
-	/* Make sure the timer is cancelled. */
-	del_timer(&cdu31a_abort_timer);
-
-	while (1) {
-		/*
-		 * The beginning here is stolen from the hard disk driver.  I hope
-		 * it's right.
-		 */
-		req = elv_next_request(q);
-		if (!req)
-			goto end_do_cdu31a_request;
-
-		if (!sony_spun_up)
-			scd_spinup();
-
-		block = req->sector;
-		nblock = req->nr_sectors;
-		pr_debug(PFX "request at block %d, length %d blocks\n",
-			block, nblock);
-		if (!sony_toc_read) {
-			printk(KERN_NOTICE PFX "TOC not read\n");
-			end_request(req, 0);
-			continue;
-		}
-
-		/* WTF??? */
-		if (!blk_fs_request(req)) {
-			end_request(req, 0);
-			continue;
-		}
-		if (rq_data_dir(req) == WRITE) {
-			end_request(req, 0);
-			continue;
-		}
-
-		/*
-		 * If the block address is invalid or the request goes beyond the end of
-		 * the media, return an error.
-		 */
-		if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) {
-			printk(KERN_NOTICE PFX "Request past end of media\n");
-			end_request(req, 0);
-			continue;
-		}
-
-		if (nblock > 4)
-			nblock = 4;
-		num_retries = 0;
-
-	try_read_again:
-		while (handle_sony_cd_attention());
-
-		if (!sony_toc_read) {
-			printk(KERN_NOTICE PFX "TOC not read\n");
-			end_request(req, 0);
-			continue;
-		}
-
-		/* If no data is left to be read from the drive, start the
-		   next request. */
-		if (sony_blocks_left == 0) {
-			if (start_request(block / 4, nblock / 4)) {
-				end_request(req, 0);
-				continue;
-			}
-		}
-		/* If the requested block is not the next one waiting in
-		   the driver, abort the current operation and start a
-		   new one. */
-		else if (block != sony_next_block) {
-			pr_debug(PFX "Read for block %d, expected %d\n",
-				 block, sony_next_block);
-			abort_read();
-			if (!sony_toc_read) {
-				printk(KERN_NOTICE PFX "TOC not read\n");
-				end_request(req, 0);
-				continue;
-			}
-			if (start_request(block / 4, nblock / 4)) {
-				printk(KERN_NOTICE PFX "start request failed\n");
-				end_request(req, 0);
-				continue;
-			}
-		}
-
-		read_data_block(req->buffer, block, nblock, res_reg, &res_size);
-
-		if (res_reg[0] != 0x20) {
-			if (!end_that_request_first(req, 1, nblock)) {
-				spin_lock_irq(q->queue_lock);
-				blkdev_dequeue_request(req);
-				end_that_request_last(req, 1);
-				spin_unlock_irq(q->queue_lock);
-			}
-			continue;
-		}
-
-		if (num_retries > MAX_CDU31A_RETRIES) {
-			end_request(req, 0);
-			continue;
-		}
-
-		num_retries++;
-		if (res_reg[1] == SONY_NOT_SPIN_ERR) {
-			do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-					&res_size);
-		} else {
-			printk(KERN_NOTICE PFX "%s error for block %d, nblock %d\n",
-				 translate_error(res_reg[1]), block, nblock);
-		}
-		goto try_read_again;
-	}
-      end_do_cdu31a_request:
-#if 0
-	/* After finished, cancel any pending operations. */
-	abort_read();
-#else
-	/* Start a timer to time out after a while to disable
-	   the read. */
-	cdu31a_abort_timer.expires = jiffies + 2 * HZ;	/* Wait 2 seconds */
-	add_timer(&cdu31a_abort_timer);
-#endif
-
-	up(&sony_sem);
-	spin_lock_irq(q->queue_lock);
-	pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * Read the table of contents from the drive and set up TOC if
- * successful.
- */
-static void sony_get_toc(void)
-{
-	unsigned char res_reg[2];
-	unsigned int res_size;
-	unsigned char parms[1];
-	int session;
-	int num_spin_ups;
-	int totaltracks = 0;
-	int mint = 99;
-	int maxt = 0;
-
-	pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
-	num_spin_ups = 0;
-	if (!sony_toc_read) {
-	      respinup_on_gettoc:
-		/* Ignore the result, since it might error if spinning already. */
-		do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		/* The drive sometimes returns error 0.  I don't know why, but ignore
-		   it.  It seems to mean the drive has already done the operation. */
-		if ((res_size < 2)
-		    || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
-			/* If the drive is already playing, it's ok.  */
-			if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
-			    || (res_reg[1] == 0)) {
-				goto gettoc_drive_spinning;
-			}
-
-			/* If the drive says it is not spun up (even though we just did it!)
-			   then retry the operation at least a few times. */
-			if ((res_reg[1] == SONY_NOT_SPIN_ERR)
-			    && (num_spin_ups < MAX_CDU31A_RETRIES)) {
-				num_spin_ups++;
-				goto respinup_on_gettoc;
-			}
-
-			printk("cdu31a: Error reading TOC: %x %s\n",
-			       res_reg[0], translate_error(res_reg[1]));
-			return;
-		}
-
-	      gettoc_drive_spinning:
-
-		/* The idea here is we keep asking for sessions until the command
-		   fails.  Then we know what the last valid session on the disk is.
-		   No need to check session 0, since session 0 is the same as session
-		   1; the command returns different information if you give it 0. 
-		 */
-#if DEBUG
-		memset(&sony_toc, 0x0e, sizeof(sony_toc));
-		memset(&single_toc, 0x0f, sizeof(single_toc));
-#endif
-		session = 1;
-		while (1) {
-/* This seems to slow things down enough to make it work.  This
- * appears to be a problem in do_sony_cd_cmd.  This printk seems 
- * to address the symptoms...  -Erik */
-			pr_debug(PFX "Trying session %d\n", session);
-			parms[0] = session;
-			do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD,
-				       parms, 1, res_reg, &res_size);
-
-			pr_debug(PFX "%2.2x %2.2x\n", res_reg[0], res_reg[1]);
-
-			if ((res_size < 2)
-			    || ((res_reg[0] & 0xf0) == 0x20)) {
-				/* An error reading the TOC, this must be past the last session. */
-				if (session == 1)
-					printk
-					    ("Yikes! Couldn't read any sessions!");
-				break;
-			}
-			pr_debug(PFX "Reading session %d\n", session);
-
-			parms[0] = session;
-			do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD,
-				       parms,
-				       1,
-				       (unsigned char *) &single_toc,
-				       &res_size);
-			if ((res_size < 2)
-			    || ((single_toc.exec_status[0] & 0xf0) ==
-				0x20)) {
-				printk(KERN_ERR PFX "Error reading "
-						"session %d: %x %s\n",
-				     session, single_toc.exec_status[0],
-				     translate_error(single_toc.
-						     exec_status[1]));
-				/* An error reading the TOC.  Return without sony_toc_read
-				   set. */
-				return;
-			}
-			pr_debug(PFX "add0 %01x, con0 %01x, poi0 %02x, "
-					"1st trk %d, dsktyp %x, dum0 %x\n",
-			     single_toc.address0, single_toc.control0,
-			     single_toc.point0,
-			     bcd_to_int(single_toc.first_track_num),
-			     single_toc.disk_type, single_toc.dummy0);
-			pr_debug(PFX "add1 %01x, con1 %01x, poi1 %02x, "
-					"lst trk %d, dummy1 %x, dum2 %x\n",
-			     single_toc.address1, single_toc.control1,
-			     single_toc.point1,
-			     bcd_to_int(single_toc.last_track_num),
-			     single_toc.dummy1, single_toc.dummy2);
-			pr_debug(PFX "add2 %01x, con2 %01x, poi2 %02x "
-				"leadout start min %d, sec %d, frame %d\n",
-			     single_toc.address2, single_toc.control2,
-			     single_toc.point2,
-			     bcd_to_int(single_toc.lead_out_start_msf[0]),
-			     bcd_to_int(single_toc.lead_out_start_msf[1]),
-			     bcd_to_int(single_toc.lead_out_start_msf[2]));
-			if (res_size > 18 && single_toc.pointb0 > 0xaf)
-				pr_debug(PFX "addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"
-				     "#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n",
-				     single_toc.addressb0,
-				     single_toc.controlb0,
-				     single_toc.pointb0,
-				     bcd_to_int(single_toc.
-						next_poss_prog_area_msf
-						[0]),
-				     bcd_to_int(single_toc.
-						next_poss_prog_area_msf
-						[1]),
-				     bcd_to_int(single_toc.
-						next_poss_prog_area_msf
-						[2]),
-				     single_toc.num_mode_5_pointers,
-				     bcd_to_int(single_toc.
-						max_start_outer_leadout_msf
-						[0]),
-				     bcd_to_int(single_toc.
-						max_start_outer_leadout_msf
-						[1]),
-				     bcd_to_int(single_toc.
-						max_start_outer_leadout_msf
-						[2]));
-			if (res_size > 27 && single_toc.pointb1 > 0xaf)
-				pr_debug(PFX "addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",
-				     single_toc.addressb1,
-				     single_toc.controlb1,
-				     single_toc.pointb1,
-				     single_toc.dummyb0_1[0],
-				     single_toc.dummyb0_1[1],
-				     single_toc.dummyb0_1[2],
-				     single_toc.dummyb0_1[3],
-				     single_toc.num_skip_interval_pointers,
-				     single_toc.num_skip_track_assignments,
-				     single_toc.dummyb0_2);
-			if (res_size > 36 && single_toc.pointb2 > 0xaf)
-				pr_debug(PFX "addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-				     single_toc.addressb2,
-				     single_toc.controlb2,
-				     single_toc.pointb2,
-				     single_toc.tracksb2[0],
-				     single_toc.tracksb2[1],
-				     single_toc.tracksb2[2],
-				     single_toc.tracksb2[3],
-				     single_toc.tracksb2[4],
-				     single_toc.tracksb2[5],
-				     single_toc.tracksb2[6]);
-			if (res_size > 45 && single_toc.pointb3 > 0xaf)
-				pr_debug(PFX "addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-				     single_toc.addressb3,
-				     single_toc.controlb3,
-				     single_toc.pointb3,
-				     single_toc.tracksb3[0],
-				     single_toc.tracksb3[1],
-				     single_toc.tracksb3[2],
-				     single_toc.tracksb3[3],
-				     single_toc.tracksb3[4],
-				     single_toc.tracksb3[5],
-				     single_toc.tracksb3[6]);
-			if (res_size > 54 && single_toc.pointb4 > 0xaf)
-				pr_debug(PFX "addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-				     single_toc.addressb4,
-				     single_toc.controlb4,
-				     single_toc.pointb4,
-				     single_toc.tracksb4[0],
-				     single_toc.tracksb4[1],
-				     single_toc.tracksb4[2],
-				     single_toc.tracksb4[3],
-				     single_toc.tracksb4[4],
-				     single_toc.tracksb4[5],
-				     single_toc.tracksb4[6]);
-			if (res_size > 63 && single_toc.pointc0 > 0xaf)
-				pr_debug(PFX "addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
-				     single_toc.addressc0,
-				     single_toc.controlc0,
-				     single_toc.pointc0,
-				     single_toc.dummyc0[0],
-				     single_toc.dummyc0[1],
-				     single_toc.dummyc0[2],
-				     single_toc.dummyc0[3],
-				     single_toc.dummyc0[4],
-				     single_toc.dummyc0[5],
-				     single_toc.dummyc0[6]);
-#undef DEBUG
-#define DEBUG 0
-
-			sony_toc.lead_out_start_msf[0] =
-			    bcd_to_int(single_toc.lead_out_start_msf[0]);
-			sony_toc.lead_out_start_msf[1] =
-			    bcd_to_int(single_toc.lead_out_start_msf[1]);
-			sony_toc.lead_out_start_msf[2] =
-			    bcd_to_int(single_toc.lead_out_start_msf[2]);
-			sony_toc.lead_out_start_lba =
-			    single_toc.lead_out_start_lba =
-			    msf_to_log(sony_toc.lead_out_start_msf);
-
-			/* For points that do not exist, move the data over them
-			   to the right location. */
-			if (single_toc.pointb0 != 0xb0) {
-				memmove(((char *) &single_toc) + 27,
-					((char *) &single_toc) + 18,
-					res_size - 18);
-				res_size += 9;
-			} else if (res_size > 18) {
-				sony_toc.lead_out_start_msf[0] =
-				    bcd_to_int(single_toc.
-					       max_start_outer_leadout_msf
-					       [0]);
-				sony_toc.lead_out_start_msf[1] =
-				    bcd_to_int(single_toc.
-					       max_start_outer_leadout_msf
-					       [1]);
-				sony_toc.lead_out_start_msf[2] =
-				    bcd_to_int(single_toc.
-					       max_start_outer_leadout_msf
-					       [2]);
-				sony_toc.lead_out_start_lba =
-				    msf_to_log(sony_toc.
-					       lead_out_start_msf);
-			}
-			if (single_toc.pointb1 != 0xb1) {
-				memmove(((char *) &single_toc) + 36,
-					((char *) &single_toc) + 27,
-					res_size - 27);
-				res_size += 9;
-			}
-			if (single_toc.pointb2 != 0xb2) {
-				memmove(((char *) &single_toc) + 45,
-					((char *) &single_toc) + 36,
-					res_size - 36);
-				res_size += 9;
-			}
-			if (single_toc.pointb3 != 0xb3) {
-				memmove(((char *) &single_toc) + 54,
-					((char *) &single_toc) + 45,
-					res_size - 45);
-				res_size += 9;
-			}
-			if (single_toc.pointb4 != 0xb4) {
-				memmove(((char *) &single_toc) + 63,
-					((char *) &single_toc) + 54,
-					res_size - 54);
-				res_size += 9;
-			}
-			if (single_toc.pointc0 != 0xc0) {
-				memmove(((char *) &single_toc) + 72,
-					((char *) &single_toc) + 63,
-					res_size - 63);
-				res_size += 9;
-			}
-#if DEBUG
-			printk(PRINT_INFO PFX "start track lba %u,  "
-					"leadout start lba %u\n",
-			     single_toc.start_track_lba,
-			     single_toc.lead_out_start_lba);
-			{
-				int i;
-				for (i = 0;
-				     i <
-				     1 +
-				     bcd_to_int(single_toc.last_track_num)
-				     -
-				     bcd_to_int(single_toc.
-						first_track_num); i++) {
-					printk(KERN_INFO PFX "trk %02d: add 0x%01x, con 0x%01x,  track %02d, start min %02d, sec %02d, frame %02d\n",
-					     i,
-					     single_toc.tracks[i].address,
-					     single_toc.tracks[i].control,
-					     bcd_to_int(single_toc.
-							tracks[i].track),
-					     bcd_to_int(single_toc.
-							tracks[i].
-							track_start_msf
-							[0]),
-					     bcd_to_int(single_toc.
-							tracks[i].
-							track_start_msf
-							[1]),
-					     bcd_to_int(single_toc.
-							tracks[i].
-							track_start_msf
-							[2]));
-					if (mint >
-					    bcd_to_int(single_toc.
-						       tracks[i].track))
-						mint =
-						    bcd_to_int(single_toc.
-							       tracks[i].
-							       track);
-					if (maxt <
-					    bcd_to_int(single_toc.
-						       tracks[i].track))
-						maxt =
-						    bcd_to_int(single_toc.
-							       tracks[i].
-							       track);
-				}
-				printk(KERN_INFO PFX "min track number %d,  "
-						"max track number %d\n",
-				     mint, maxt);
-			}
-#endif
-
-			/* prepare a special table of contents for a CD-I disc. They don't have one. */
-			if (single_toc.disk_type == 0x10 &&
-			    single_toc.first_track_num == 2 &&
-			    single_toc.last_track_num == 2 /* CD-I */ ) {
-				sony_toc.tracks[totaltracks].address = 1;
-				sony_toc.tracks[totaltracks].control = 4;	/* force data tracks */
-				sony_toc.tracks[totaltracks].track = 1;
-				sony_toc.tracks[totaltracks].
-				    track_start_msf[0] = 0;
-				sony_toc.tracks[totaltracks].
-				    track_start_msf[1] = 2;
-				sony_toc.tracks[totaltracks].
-				    track_start_msf[2] = 0;
-				mint = maxt = 1;
-				totaltracks++;
-			} else
-				/* gather track entries from this session */
-			{
-				int i;
-				for (i = 0;
-				     i <
-				     1 +
-				     bcd_to_int(single_toc.last_track_num)
-				     -
-				     bcd_to_int(single_toc.
-						first_track_num);
-				     i++, totaltracks++) {
-					sony_toc.tracks[totaltracks].
-					    address =
-					    single_toc.tracks[i].address;
-					sony_toc.tracks[totaltracks].
-					    control =
-					    single_toc.tracks[i].control;
-					sony_toc.tracks[totaltracks].
-					    track =
-					    bcd_to_int(single_toc.
-						       tracks[i].track);
-					sony_toc.tracks[totaltracks].
-					    track_start_msf[0] =
-					    bcd_to_int(single_toc.
-						       tracks[i].
-						       track_start_msf[0]);
-					sony_toc.tracks[totaltracks].
-					    track_start_msf[1] =
-					    bcd_to_int(single_toc.
-						       tracks[i].
-						       track_start_msf[1]);
-					sony_toc.tracks[totaltracks].
-					    track_start_msf[2] =
-					    bcd_to_int(single_toc.
-						       tracks[i].
-						       track_start_msf[2]);
-					if (i == 0)
-						single_toc.
-						    start_track_lba =
-						    msf_to_log(sony_toc.
-							       tracks
-							       [totaltracks].
-							       track_start_msf);
-					if (mint >
-					    sony_toc.tracks[totaltracks].
-					    track)
-						mint =
-						    sony_toc.
-						    tracks[totaltracks].
-						    track;
-					if (maxt <
-					    sony_toc.tracks[totaltracks].
-					    track)
-						maxt =
-						    sony_toc.
-						    tracks[totaltracks].
-						    track;
-				}
-			}
-			sony_toc.first_track_num = mint;
-			sony_toc.last_track_num = maxt;
-			/* Disk type of last session wins. For example:
-			   CD-Extra has disk type 0 for the first session, so
-			   a dumb HiFi CD player thinks it is a plain audio CD.
-			   We are interested in the disk type of the last session,
-			   which is 0x20 (XA) for CD-Extra, so we can access the
-			   data track ... */
-			sony_toc.disk_type = single_toc.disk_type;
-			sony_toc.sessions = session;
-
-			/* don't believe everything :-) */
-			if (session == 1)
-				single_toc.start_track_lba = 0;
-			sony_toc.start_track_lba =
-			    single_toc.start_track_lba;
-
-			if (session > 1 && single_toc.pointb0 == 0xb0 &&
-			    sony_toc.lead_out_start_lba ==
-			    single_toc.lead_out_start_lba) {
-				break;
-			}
-
-			/* Let's not get carried away... */
-			if (session > 40) {
-				printk(KERN_NOTICE PFX "too many sessions: "
-						"%d\n", session);
-				break;
-			}
-			session++;
-		}
-		sony_toc.track_entries = totaltracks;
-		/* add one entry for the LAST track with track number CDROM_LEADOUT */
-		sony_toc.tracks[totaltracks].address = single_toc.address2;
-		sony_toc.tracks[totaltracks].control = single_toc.control2;
-		sony_toc.tracks[totaltracks].track = CDROM_LEADOUT;
-		sony_toc.tracks[totaltracks].track_start_msf[0] =
-		    sony_toc.lead_out_start_msf[0];
-		sony_toc.tracks[totaltracks].track_start_msf[1] =
-		    sony_toc.lead_out_start_msf[1];
-		sony_toc.tracks[totaltracks].track_start_msf[2] =
-		    sony_toc.lead_out_start_msf[2];
-
-		sony_toc_read = 1;
-
-		pr_debug(PFX "Disk session %d, start track: %d, "
-				"stop track: %d\n",
-		     session, single_toc.start_track_lba,
-		     single_toc.lead_out_start_lba);
-	}
-	pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-
-/*
- * Uniform cdrom interface function
- * return multisession offset and sector information
- */
-static int scd_get_last_session(struct cdrom_device_info *cdi,
-				struct cdrom_multisession *ms_info)
-{
-	if (ms_info == NULL)
-		return 1;
-
-	if (!sony_toc_read) {
-		if (down_interruptible(&sony_sem))
-			return -ERESTARTSYS;
-		sony_get_toc();
-		up(&sony_sem);
-	}
-
-	ms_info->addr_format = CDROM_LBA;
-	ms_info->addr.lba = sony_toc.start_track_lba;
-	ms_info->xa_flag = sony_toc.disk_type == SONY_XA_DISK_TYPE ||
-	    sony_toc.disk_type == 0x10 /* CDI */ ;
-
-	return 0;
-}
-
-/*
- * Search for a specific track in the table of contents.
- */
-static int find_track(int track)
-{
-	int i;
-
-	for (i = 0; i <= sony_toc.track_entries; i++) {
-		if (sony_toc.tracks[i].track == track) {
-			return i;
-		}
-	}
-
-	return -1;
-}
-
-
-/*
- * Read the subcode and put it in last_sony_subcode for future use.
- */
-static int read_subcode(void)
-{
-	unsigned int res_size;
-
-
-	do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD,
-		       NULL,
-		       0, (unsigned char *) &last_sony_subcode, &res_size);
-	if ((res_size < 2)
-	    || ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) {
-		printk(KERN_ERR PFX "Sony CDROM error %s (read_subcode)\n",
-		       translate_error(last_sony_subcode.exec_status[1]));
-		return -EIO;
-	}
-
-	last_sony_subcode.track_num =
-	    bcd_to_int(last_sony_subcode.track_num);
-	last_sony_subcode.index_num =
-	    bcd_to_int(last_sony_subcode.index_num);
-	last_sony_subcode.abs_msf[0] =
-	    bcd_to_int(last_sony_subcode.abs_msf[0]);
-	last_sony_subcode.abs_msf[1] =
-	    bcd_to_int(last_sony_subcode.abs_msf[1]);
-	last_sony_subcode.abs_msf[2] =
-	    bcd_to_int(last_sony_subcode.abs_msf[2]);
-
-	last_sony_subcode.rel_msf[0] =
-	    bcd_to_int(last_sony_subcode.rel_msf[0]);
-	last_sony_subcode.rel_msf[1] =
-	    bcd_to_int(last_sony_subcode.rel_msf[1]);
-	last_sony_subcode.rel_msf[2] =
-	    bcd_to_int(last_sony_subcode.rel_msf[2]);
-	return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * return the media catalog number found on some older audio cds
- */
-static int
-scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
-	unsigned char resbuffer[2 + 14];
-	unsigned char *mcnp = mcn->medium_catalog_number;
-	unsigned char *resp = resbuffer + 3;
-	unsigned int res_size;
-
-	memset(mcn->medium_catalog_number, 0, 14);
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD,
-		       NULL, 0, resbuffer, &res_size);
-	up(&sony_sem);
-	if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20));
-	else {
-		/* packed bcd to single ASCII digits */
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4) + '0';
-	}
-	*mcnp = '\0';
-	return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it.  If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing).  If the drive is paused or completed, the subcode information has
- * already been stored, just use that.  The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int sony_get_subchnl_info(struct cdrom_subchnl *schi)
-{
-	/* Get attention stuff */
-	while (handle_sony_cd_attention());
-
-	sony_get_toc();
-	if (!sony_toc_read) {
-		return -EIO;
-	}
-
-	switch (sony_audio_status) {
-	case CDROM_AUDIO_NO_STATUS:
-	case CDROM_AUDIO_PLAY:
-		if (read_subcode() < 0) {
-			return -EIO;
-		}
-		break;
-
-	case CDROM_AUDIO_PAUSED:
-	case CDROM_AUDIO_COMPLETED:
-		break;
-
-#if 0
-	case CDROM_AUDIO_NO_STATUS:
-		schi->cdsc_audiostatus = sony_audio_status;
-		return 0;
-		break;
-#endif
-	case CDROM_AUDIO_INVALID:
-	case CDROM_AUDIO_ERROR:
-	default:
-		return -EIO;
-	}
-
-	schi->cdsc_audiostatus = sony_audio_status;
-	schi->cdsc_adr = last_sony_subcode.address;
-	schi->cdsc_ctrl = last_sony_subcode.control;
-	schi->cdsc_trk = last_sony_subcode.track_num;
-	schi->cdsc_ind = last_sony_subcode.index_num;
-	if (schi->cdsc_format == CDROM_MSF) {
-		schi->cdsc_absaddr.msf.minute =
-		    last_sony_subcode.abs_msf[0];
-		schi->cdsc_absaddr.msf.second =
-		    last_sony_subcode.abs_msf[1];
-		schi->cdsc_absaddr.msf.frame =
-		    last_sony_subcode.abs_msf[2];
-
-		schi->cdsc_reladdr.msf.minute =
-		    last_sony_subcode.rel_msf[0];
-		schi->cdsc_reladdr.msf.second =
-		    last_sony_subcode.rel_msf[1];
-		schi->cdsc_reladdr.msf.frame =
-		    last_sony_subcode.rel_msf[2];
-	} else if (schi->cdsc_format == CDROM_LBA) {
-		schi->cdsc_absaddr.lba =
-		    msf_to_log(last_sony_subcode.abs_msf);
-		schi->cdsc_reladdr.lba =
-		    msf_to_log(last_sony_subcode.rel_msf);
-	}
-
-	return 0;
-}
-
-/* Get audio data from the drive.  This is fairly complex because I
-   am looking for status and data at the same time, but if I get status
-   then I just look for data.  I need to get the status immediately so
-   the switch from audio to data tracks will happen quickly. */
-static void
-read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
-{
-	unsigned long retry_count;
-	int result_read;
-
-
-	res_reg[0] = 0;
-	res_reg[1] = 0;
-	*res_size = 0;
-	result_read = 0;
-
-	/* Wait for the drive to tell us we have something */
-	retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-      continue_read_audio_wait:
-	while (time_before(jiffies, retry_count) && !(is_data_ready())
-	       && !(is_result_ready() || result_read)) {
-		while (handle_sony_cd_attention());
-
-		sony_sleep();
-	}
-	if (!(is_data_ready())) {
-		if (is_result_ready() && !result_read) {
-			get_result(res_reg, res_size);
-
-			/* Read block status and continue waiting for data. */
-			if ((res_reg[0] & 0xf0) == 0x50) {
-				result_read = 1;
-				goto continue_read_audio_wait;
-			}
-			/* Invalid data from the drive.  Shut down the operation. */
-			else if ((res_reg[0] & 0xf0) != 0x20) {
-				printk(KERN_WARNING PFX "Got result that "
-						"should have been error: %d\n",
-				     res_reg[0]);
-				res_reg[0] = 0x20;
-				res_reg[1] = SONY_BAD_DATA_ERR;
-				*res_size = 2;
-			}
-			abort_read();
-		} else {
-			pr_debug(PFX "timeout out %d\n", __LINE__);
-			res_reg[0] = 0x20;
-			res_reg[1] = SONY_TIMEOUT_OP_ERR;
-			*res_size = 2;
-			abort_read();
-		}
-	} else {
-		clear_data_ready();
-
-		/* If data block, then get 2340 bytes offset by 12. */
-		if (sony_raw_data_mode) {
-			insb(sony_cd_read_reg, buffer + CD_XA_HEAD,
-			     CD_FRAMESIZE_RAW1);
-		} else {
-			/* Audio gets the whole 2352 bytes. */
-			insb(sony_cd_read_reg, buffer, CD_FRAMESIZE_RAW);
-		}
-
-		/* If I haven't already gotten the result, get it now. */
-		if (!result_read) {
-			/* Wait for the drive to tell us we have something */
-			retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-			while (time_before(jiffies, retry_count)
-			       && !(is_result_ready())) {
-				while (handle_sony_cd_attention());
-
-				sony_sleep();
-			}
-
-			if (!is_result_ready()) {
-				pr_debug(PFX "timeout out %d\n", __LINE__);
-				res_reg[0] = 0x20;
-				res_reg[1] = SONY_TIMEOUT_OP_ERR;
-				*res_size = 2;
-				abort_read();
-				return;
-			} else {
-				get_result(res_reg, res_size);
-			}
-		}
-
-		if ((res_reg[0] & 0xf0) == 0x50) {
-			if ((res_reg[0] == SONY_NO_CIRC_ERR_BLK_STAT)
-			    || (res_reg[0] == SONY_NO_LECC_ERR_BLK_STAT)
-			    || (res_reg[0] == SONY_RECOV_LECC_ERR_BLK_STAT)
-			    || (res_reg[0] == SONY_NO_ERR_DETECTION_STAT)) {
-				/* Ok, nothing to do. */
-			} else {
-				printk(KERN_ERR PFX "Data block error: 0x%x\n",
-				       res_reg[0]);
-				res_reg[0] = 0x20;
-				res_reg[1] = SONY_BAD_DATA_ERR;
-				*res_size = 2;
-			}
-		} else if ((res_reg[0] & 0xf0) != 0x20) {
-			/* The drive gave me bad status, I don't know what to do.
-			   Reset the driver and return an error. */
-			printk(KERN_NOTICE PFX "Invalid block status: 0x%x\n",
-			       res_reg[0]);
-			restart_on_error();
-			res_reg[0] = 0x20;
-			res_reg[1] = SONY_BAD_DATA_ERR;
-			*res_size = 2;
-		}
-	}
-}
-
-/* Perform a raw data read.  This will automatically detect the
-   track type and read the proper data (audio or data). */
-static int read_audio(struct cdrom_read_audio *ra)
-{
-	int retval;
-	unsigned char params[2];
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	unsigned int cframe;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	if (!sony_spun_up)
-		scd_spinup();
-
-	/* Set the drive to do raw operations. */
-	params[0] = SONY_SD_DECODE_PARAM;
-	params[1] = 0x06 | sony_raw_data_mode;
-	do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-		       params, 2, res_reg, &res_size);
-	if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-		printk(KERN_ERR PFX "Unable to set decode params: 0x%2.2x\n",
-		       res_reg[1]);
-		retval = -EIO;
-		goto out_up;
-	}
-
-	/* From here down, we have to goto exit_read_audio instead of returning
-	   because the drive parameters have to be set back to data before
-	   return. */
-
-	retval = 0;
-	if (start_request(ra->addr.lba, ra->nframes)) {
-		retval = -EIO;
-		goto exit_read_audio;
-	}
-
-	/* For every requested frame. */
-	cframe = 0;
-	while (cframe < ra->nframes) {
-		read_audio_data(audio_buffer, res_reg, &res_size);
-		if ((res_reg[0] & 0xf0) == 0x20) {
-			if (res_reg[1] == SONY_BAD_DATA_ERR) {
-				printk(KERN_ERR PFX "Data error on audio "
-						"sector %d\n",
-				     ra->addr.lba + cframe);
-			} else if (res_reg[1] == SONY_ILL_TRACK_R_ERR) {
-				/* Illegal track type, change track types and start over. */
-				sony_raw_data_mode =
-				    (sony_raw_data_mode) ? 0 : 1;
-
-				/* Set the drive mode. */
-				params[0] = SONY_SD_DECODE_PARAM;
-				params[1] = 0x06 | sony_raw_data_mode;
-				do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-					       params,
-					       2, res_reg, &res_size);
-				if ((res_size < 2)
-				    || ((res_reg[0] & 0xf0) == 0x20)) {
-					printk(KERN_ERR PFX "Unable to set "
-						"decode params: 0x%2.2x\n",
-					     res_reg[1]);
-					retval = -EIO;
-					goto exit_read_audio;
-				}
-
-				/* Restart the request on the current frame. */
-				if (start_request
-				    (ra->addr.lba + cframe,
-				     ra->nframes - cframe)) {
-					retval = -EIO;
-					goto exit_read_audio;
-				}
-
-				/* Don't go back to the top because don't want to get into
-				   and infinite loop.  A lot of code gets duplicated, but
-				   that's no big deal, I don't guess. */
-				read_audio_data(audio_buffer, res_reg,
-						&res_size);
-				if ((res_reg[0] & 0xf0) == 0x20) {
-					if (res_reg[1] ==
-					    SONY_BAD_DATA_ERR) {
-						printk(KERN_ERR PFX "Data error"
-							" on audio sector %d\n",
-						     ra->addr.lba +
-						     cframe);
-					} else {
-						printk(KERN_ERR PFX "Error reading audio data on sector %d: %s\n",
-						     ra->addr.lba + cframe,
-						     translate_error
-						     (res_reg[1]));
-						retval = -EIO;
-						goto exit_read_audio;
-					}
-				} else if (copy_to_user(ra->buf +
-							       (CD_FRAMESIZE_RAW
-								* cframe),
-						        audio_buffer,
-							CD_FRAMESIZE_RAW)) {
-					retval = -EFAULT;
-					goto exit_read_audio;
-				}
-			} else {
-				printk(KERN_ERR PFX "Error reading audio "
-						"data on sector %d: %s\n",
-				     ra->addr.lba + cframe,
-				     translate_error(res_reg[1]));
-				retval = -EIO;
-				goto exit_read_audio;
-			}
-		} else if (copy_to_user(ra->buf + (CD_FRAMESIZE_RAW * cframe),
-					(char *)audio_buffer,
-					CD_FRAMESIZE_RAW)) {
-			retval = -EFAULT;
-			goto exit_read_audio;
-		}
-
-		cframe++;
-	}
-
-	get_result(res_reg, &res_size);
-	if ((res_reg[0] & 0xf0) == 0x20) {
-		printk(KERN_ERR PFX "Error return from audio read: %s\n",
-		       translate_error(res_reg[1]));
-		retval = -EIO;
-		goto exit_read_audio;
-	}
-
-      exit_read_audio:
-
-	/* Set the drive mode back to the proper one for the disk. */
-	params[0] = SONY_SD_DECODE_PARAM;
-	if (!sony_xa_mode) {
-		params[1] = 0x0f;
-	} else {
-		params[1] = 0x07;
-	}
-	do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-		       params, 2, res_reg, &res_size);
-	if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
-		printk(KERN_ERR PFX "Unable to reset decode params: 0x%2.2x\n",
-		       res_reg[1]);
-		retval = -EIO;
-	}
-
- out_up:
-	up(&sony_sem);
-
-	return retval;
-}
-
-static int
-do_sony_cd_cmd_chk(const char *name,
-		   unsigned char cmd,
-		   unsigned char *params,
-		   unsigned int num_params,
-		   unsigned char *result_buffer, unsigned int *result_size)
-{
-	do_sony_cd_cmd(cmd, params, num_params, result_buffer,
-		       result_size);
-	if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20)) {
-		printk(KERN_ERR PFX "Error %s (CDROM%s)\n",
-		       translate_error(result_buffer[1]), name);
-		return -EIO;
-	}
-	return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * open the tray
- */
-static int scd_tray_move(struct cdrom_device_info *cdi, int position)
-{
-	int retval;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	if (position == 1 /* open tray */ ) {
-		unsigned char res_reg[12];
-		unsigned int res_size;
-
-		do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
-			       &res_size);
-		do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		sony_audio_status = CDROM_AUDIO_INVALID;
-		retval = do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0,
-					  res_reg, &res_size);
-	} else {
-		if (0 == scd_spinup())
-			sony_spun_up = 1;
-		retval = 0;
-	}
-	up(&sony_sem);
-	return retval;
-}
-
-/*
- * The big ugly ioctl handler.
- */
-static int scd_audio_ioctl(struct cdrom_device_info *cdi,
-			   unsigned int cmd, void *arg)
-{
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	unsigned char params[7];
-	int i, retval;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	switch (cmd) {
-	case CDROMSTART:	/* Spin up the drive */
-		retval = do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL,
-					  0, res_reg, &res_size);
-		break;
-
-	case CDROMSTOP:	/* Spin down the drive */
-		do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		/*
-		 * Spin the drive down, ignoring the error if the disk was
-		 * already not spinning.
-		 */
-		sony_audio_status = CDROM_AUDIO_NO_STATUS;
-		retval = do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL,
-					  0, res_reg, &res_size);
-		break;
-
-	case CDROMPAUSE:	/* Pause the drive */
-		if (do_sony_cd_cmd_chk
-		    ("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
-		     &res_size)) {
-			retval = -EIO;
-			break;
-		}
-		/* Get the current position and save it for resuming */
-		if (read_subcode() < 0) {
-			retval = -EIO;
-			break;
-		}
-		cur_pos_msf[0] = last_sony_subcode.abs_msf[0];
-		cur_pos_msf[1] = last_sony_subcode.abs_msf[1];
-		cur_pos_msf[2] = last_sony_subcode.abs_msf[2];
-		sony_audio_status = CDROM_AUDIO_PAUSED;
-		retval = 0;
-		break;
-
-	case CDROMRESUME:	/* Start the drive after being paused */
-		if (sony_audio_status != CDROM_AUDIO_PAUSED) {
-			retval = -EINVAL;
-			break;
-		}
-
-		do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		/* Start the drive at the saved position. */
-		params[1] = int_to_bcd(cur_pos_msf[0]);
-		params[2] = int_to_bcd(cur_pos_msf[1]);
-		params[3] = int_to_bcd(cur_pos_msf[2]);
-		params[4] = int_to_bcd(final_pos_msf[0]);
-		params[5] = int_to_bcd(final_pos_msf[1]);
-		params[6] = int_to_bcd(final_pos_msf[2]);
-		params[0] = 0x03;
-		if (do_sony_cd_cmd_chk
-		    ("RESUME", SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg,
-		     &res_size) < 0) {
-			retval = -EIO;
-			break;
-		}
-		sony_audio_status = CDROM_AUDIO_PLAY;
-		retval = 0;
-		break;
-
-	case CDROMPLAYMSF:	/* Play starting at the given MSF address. */
-		do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		/* The parameters are given in int, must be converted */
-		for (i = 1; i < 7; i++) {
-			params[i] =
-			    int_to_bcd(((unsigned char *) arg)[i - 1]);
-		}
-		params[0] = 0x03;
-		if (do_sony_cd_cmd_chk
-		    ("PLAYMSF", SONY_AUDIO_PLAYBACK_CMD, params, 7,
-		     res_reg, &res_size) < 0) {
-			retval = -EIO;
-			break;
-		}
-
-		/* Save the final position for pauses and resumes */
-		final_pos_msf[0] = bcd_to_int(params[4]);
-		final_pos_msf[1] = bcd_to_int(params[5]);
-		final_pos_msf[2] = bcd_to_int(params[6]);
-		sony_audio_status = CDROM_AUDIO_PLAY;
-		retval = 0;
-		break;
-
-	case CDROMREADTOCHDR:	/* Read the table of contents header */
-		{
-			struct cdrom_tochdr *hdr;
-
-			sony_get_toc();
-			if (!sony_toc_read) {
-				retval = -EIO;
-				break;
-			}
-
-			hdr = (struct cdrom_tochdr *) arg;
-			hdr->cdth_trk0 = sony_toc.first_track_num;
-			hdr->cdth_trk1 = sony_toc.last_track_num;
-		}
-		retval = 0;
-		break;
-
-	case CDROMREADTOCENTRY:	/* Read a given table of contents entry */
-		{
-			struct cdrom_tocentry *entry;
-			int track_idx;
-			unsigned char *msf_val = NULL;
-
-			sony_get_toc();
-			if (!sony_toc_read) {
-				retval = -EIO;
-				break;
-			}
-
-			entry = (struct cdrom_tocentry *) arg;
-
-			track_idx = find_track(entry->cdte_track);
-			if (track_idx < 0) {
-				retval = -EINVAL;
-				break;
-			}
-
-			entry->cdte_adr =
-			    sony_toc.tracks[track_idx].address;
-			entry->cdte_ctrl =
-			    sony_toc.tracks[track_idx].control;
-			msf_val =
-			    sony_toc.tracks[track_idx].track_start_msf;
-
-			/* Logical buffer address or MSF format requested? */
-			if (entry->cdte_format == CDROM_LBA) {
-				entry->cdte_addr.lba = msf_to_log(msf_val);
-			} else if (entry->cdte_format == CDROM_MSF) {
-				entry->cdte_addr.msf.minute = *msf_val;
-				entry->cdte_addr.msf.second =
-				    *(msf_val + 1);
-				entry->cdte_addr.msf.frame =
-				    *(msf_val + 2);
-			}
-		}
-		retval = 0;
-		break;
-
-	case CDROMPLAYTRKIND:	/* Play a track.  This currently ignores index. */
-		{
-			struct cdrom_ti *ti = (struct cdrom_ti *) arg;
-			int track_idx;
-
-			sony_get_toc();
-			if (!sony_toc_read) {
-				retval = -EIO;
-				break;
-			}
-
-			if ((ti->cdti_trk0 < sony_toc.first_track_num)
-			    || (ti->cdti_trk0 > sony_toc.last_track_num)
-			    || (ti->cdti_trk1 < ti->cdti_trk0)) {
-				retval = -EINVAL;
-				break;
-			}
-
-			track_idx = find_track(ti->cdti_trk0);
-			if (track_idx < 0) {
-				retval = -EINVAL;
-				break;
-			}
-			params[1] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[0]);
-			params[2] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[1]);
-			params[3] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[2]);
-
-			/*
-			 * If we want to stop after the last track, use the lead-out
-			 * MSF to do that.
-			 */
-			if (ti->cdti_trk1 >= sony_toc.last_track_num) {
-				track_idx = find_track(CDROM_LEADOUT);
-			} else {
-				track_idx = find_track(ti->cdti_trk1 + 1);
-			}
-			if (track_idx < 0) {
-				retval = -EINVAL;
-				break;
-			}
-			params[4] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[0]);
-			params[5] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[1]);
-			params[6] =
-			    int_to_bcd(sony_toc.tracks[track_idx].
-				       track_start_msf[2]);
-			params[0] = 0x03;
-
-			do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
-				       &res_size);
-
-			do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7,
-				       res_reg, &res_size);
-
-			if ((res_size < 2)
-			    || ((res_reg[0] & 0xf0) == 0x20)) {
-				printk(KERN_ERR PFX
-					"Params: %x %x %x %x %x %x %x\n",
-				       params[0], params[1], params[2],
-				       params[3], params[4], params[5],
-				       params[6]);
-				printk(KERN_ERR PFX
-					"Error %s (CDROMPLAYTRKIND)\n",
-				     translate_error(res_reg[1]));
-				retval = -EIO;
-				break;
-			}
-
-			/* Save the final position for pauses and resumes */
-			final_pos_msf[0] = bcd_to_int(params[4]);
-			final_pos_msf[1] = bcd_to_int(params[5]);
-			final_pos_msf[2] = bcd_to_int(params[6]);
-			sony_audio_status = CDROM_AUDIO_PLAY;
-			retval = 0;
-			break;
-		}
-
-	case CDROMVOLCTRL:	/* Volume control.  What volume does this change, anyway? */
-		{
-			struct cdrom_volctrl *volctrl =
-			    (struct cdrom_volctrl *) arg;
-
-			params[0] = SONY_SD_AUDIO_VOLUME;
-			params[1] = volctrl->channel0;
-			params[2] = volctrl->channel1;
-			retval = do_sony_cd_cmd_chk("VOLCTRL",
-						  SONY_SET_DRIVE_PARAM_CMD,
-						  params, 3, res_reg,
-						  &res_size);
-			break;
-		}
-	case CDROMSUBCHNL:	/* Get subchannel info */
-		retval = sony_get_subchnl_info((struct cdrom_subchnl *) arg);
-		break;
-
-	default:
-		retval = -EINVAL;
-		break;
-	}
-	up(&sony_sem);
-	return retval;
-}
-
-static int scd_read_audio(struct cdrom_device_info *cdi,
-			 unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	int retval;
-
-	if (down_interruptible(&sony_sem))
-		return -ERESTARTSYS;
-	switch (cmd) {
-	case CDROMREADAUDIO:	/* Read 2352 byte audio tracks and 2340 byte
-				   raw data tracks. */
-		{
-			struct cdrom_read_audio ra;
-
-
-			sony_get_toc();
-			if (!sony_toc_read) {
-				retval = -EIO;
-				break;
-			}
-
-			if (copy_from_user(&ra, argp, sizeof(ra))) {
-				retval = -EFAULT;
-				break;
-			}
-
-			if (ra.nframes == 0) {
-				retval = 0;
-				break;
-			}
-
-			if (!access_ok(VERIFY_WRITE, ra.buf,
-					CD_FRAMESIZE_RAW * ra.nframes))
-				return -EFAULT;
-
-			if (ra.addr_format == CDROM_LBA) {
-				if ((ra.addr.lba >=
-				     sony_toc.lead_out_start_lba)
-				    || (ra.addr.lba + ra.nframes >=
-					sony_toc.lead_out_start_lba)) {
-					retval = -EINVAL;
-					break;
-				}
-			} else if (ra.addr_format == CDROM_MSF) {
-				if ((ra.addr.msf.minute >= 75)
-				    || (ra.addr.msf.second >= 60)
-				    || (ra.addr.msf.frame >= 75)) {
-					retval = -EINVAL;
-					break;
-				}
-
-				ra.addr.lba = ((ra.addr.msf.minute * 4500)
-					       + (ra.addr.msf.second * 75)
-					       + ra.addr.msf.frame);
-				if ((ra.addr.lba >=
-				     sony_toc.lead_out_start_lba)
-				    || (ra.addr.lba + ra.nframes >=
-					sony_toc.lead_out_start_lba)) {
-					retval = -EINVAL;
-					break;
-				}
-
-				/* I know, this can go negative on an unsigned.  However,
-				   the first thing done to the data is to add this value,
-				   so this should compensate and allow direct msf access. */
-				ra.addr.lba -= LOG_START_OFFSET;
-			} else {
-				retval = -EINVAL;
-				break;
-			}
-
-			retval = read_audio(&ra);
-			break;
-		}
-		retval = 0;
-		break;
-
-	default:
-		retval = -EINVAL;
-	}
-	up(&sony_sem);
-	return retval;
-}
-
-static int scd_spinup(void)
-{
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	int num_spin_ups;
-
-	num_spin_ups = 0;
-
-      respinup_on_open:
-	do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
-
-	/* The drive sometimes returns error 0.  I don't know why, but ignore
-	   it.  It seems to mean the drive has already done the operation. */
-	if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
-		printk(KERN_ERR PFX "%s error (scd_open, spin up)\n",
-		       translate_error(res_reg[1]));
-		return 1;
-	}
-
-	do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
-
-	/* The drive sometimes returns error 0.  I don't know why, but ignore
-	   it.  It seems to mean the drive has already done the operation. */
-	if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
-		/* If the drive is already playing, it's ok.  */
-		if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
-		    || (res_reg[1] == 0)) {
-			return 0;
-		}
-
-		/* If the drive says it is not spun up (even though we just did it!)
-		   then retry the operation at least a few times. */
-		if ((res_reg[1] == SONY_NOT_SPIN_ERR)
-		    && (num_spin_ups < MAX_CDU31A_RETRIES)) {
-			num_spin_ups++;
-			goto respinup_on_open;
-		}
-
-		printk(KERN_ERR PFX "Error %s (scd_open, read toc)\n",
-		       translate_error(res_reg[1]));
-		do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
-			       &res_size);
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Open the drive for operations.  Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int scd_open(struct cdrom_device_info *cdi, int purpose)
-{
-	unsigned char res_reg[12];
-	unsigned int res_size;
-	unsigned char params[2];
-
-	if (purpose == 1) {
-		/* Open for IOCTLs only - no media check */
-		sony_usage++;
-		return 0;
-	}
-
-	if (sony_usage == 0) {
-		if (scd_spinup() != 0)
-			return -EIO;
-		sony_get_toc();
-		if (!sony_toc_read) {
-			do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0,
-				       res_reg, &res_size);
-			return -EIO;
-		}
-
-		/* For XA on the CDU31A only, we have to do special reads.
-		   The CDU33A handles XA automagically. */
-		/* if (   (sony_toc.disk_type == SONY_XA_DISK_TYPE) */
-		if ((sony_toc.disk_type != 0x00)
-		    && (!is_double_speed)) {
-			params[0] = SONY_SD_DECODE_PARAM;
-			params[1] = 0x07;
-			do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-				       params, 2, res_reg, &res_size);
-			if ((res_size < 2)
-			    || ((res_reg[0] & 0xf0) == 0x20)) {
-				printk(KERN_WARNING PFX "Unable to set "
-					"XA params: 0x%2.2x\n", res_reg[1]);
-			}
-			sony_xa_mode = 1;
-		}
-		/* A non-XA disk.  Set the parms back if necessary. */
-		else if (sony_xa_mode) {
-			params[0] = SONY_SD_DECODE_PARAM;
-			params[1] = 0x0f;
-			do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
-				       params, 2, res_reg, &res_size);
-			if ((res_size < 2)
-			    || ((res_reg[0] & 0xf0) == 0x20)) {
-				printk(KERN_WARNING PFX "Unable to reset "
-					"XA params: 0x%2.2x\n", res_reg[1]);
-			}
-			sony_xa_mode = 0;
-		}
-
-		sony_spun_up = 1;
-	}
-
-	sony_usage++;
-
-	return 0;
-}
-
-
-/*
- * Close the drive.  Spin it down if no task is using it.  The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static void scd_release(struct cdrom_device_info *cdi)
-{
-	if (sony_usage == 1) {
-		unsigned char res_reg[12];
-		unsigned int res_size;
-
-		do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
-			       &res_size);
-
-		sony_spun_up = 0;
-	}
-	sony_usage--;
-}
-
-static struct cdrom_device_ops scd_dops = {
-	.open			= scd_open,
-	.release		= scd_release,
-	.drive_status		= scd_drive_status,
-	.media_changed		= scd_media_changed,
-	.tray_move		= scd_tray_move,
-	.lock_door		= scd_lock_door,
-	.select_speed		= scd_select_speed,
-	.get_last_session	= scd_get_last_session,
-	.get_mcn		= scd_get_mcn,
-	.reset			= scd_reset,
-	.audio_ioctl		= scd_audio_ioctl,
-	.capability		= CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK |
-				  CDC_SELECT_SPEED | CDC_MULTI_SESSION |
-				  CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
-				  CDC_RESET | CDC_DRIVE_STATUS,
-	.n_minors		= 1,
-};
-
-static struct cdrom_device_info scd_info = {
-	.ops		= &scd_dops,
-	.speed		= 2,
-	.capacity	= 1,
-	.name		= "cdu31a"
-};
-
-static int scd_block_open(struct inode *inode, struct file *file)
-{
-	return cdrom_open(&scd_info, inode, file);
-}
-
-static int scd_block_release(struct inode *inode, struct file *file)
-{
-	return cdrom_release(&scd_info, file);
-}
-
-static int scd_block_ioctl(struct inode *inode, struct file *file,
-				unsigned cmd, unsigned long arg)
-{
-	int retval;
-
-	/* The eject and close commands should be handled by Uniform CD-ROM
-	 * driver - but I always got hard lockup instead of eject
-	 * until I put this here.
-	 */
-	switch (cmd) {
-		case CDROMEJECT:
-			scd_lock_door(&scd_info, 0);
-			retval = scd_tray_move(&scd_info, 1);
-			break;
-		case CDROMCLOSETRAY:
-			retval = scd_tray_move(&scd_info, 0);
-			break;
-		case CDROMREADAUDIO:
-			retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg);
-			break;
-		default:
-			retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg);
-	}
-	return retval;
-}
-
-static int scd_block_media_changed(struct gendisk *disk)
-{
-	return cdrom_media_changed(&scd_info);
-}
-
-static struct block_device_operations scd_bdops =
-{
-	.owner		= THIS_MODULE,
-	.open		= scd_block_open,
-	.release	= scd_block_release,
-	.ioctl		= scd_block_ioctl,
-	.media_changed	= scd_block_media_changed,
-};
-
-static struct gendisk *scd_gendisk;
-
-/* The different types of disc loading mechanisms supported */
-static char *load_mech[] __initdata =
-    { "caddy", "tray", "pop-up", "unknown" };
-
-static int __init
-get_drive_configuration(unsigned short base_io,
-			unsigned char res_reg[], unsigned int *res_size)
-{
-	unsigned long retry_count;
-
-
-	if (!request_region(base_io, 4, "cdu31a"))
-		return 0;
-
-	/* Set the base address */
-	cdu31a_port = base_io;
-
-	/* Set up all the register locations */
-	sony_cd_cmd_reg = cdu31a_port + SONY_CMD_REG_OFFSET;
-	sony_cd_param_reg = cdu31a_port + SONY_PARAM_REG_OFFSET;
-	sony_cd_write_reg = cdu31a_port + SONY_WRITE_REG_OFFSET;
-	sony_cd_control_reg = cdu31a_port + SONY_CONTROL_REG_OFFSET;
-	sony_cd_status_reg = cdu31a_port + SONY_STATUS_REG_OFFSET;
-	sony_cd_result_reg = cdu31a_port + SONY_RESULT_REG_OFFSET;
-	sony_cd_read_reg = cdu31a_port + SONY_READ_REG_OFFSET;
-	sony_cd_fifost_reg = cdu31a_port + SONY_FIFOST_REG_OFFSET;
-
-	/*
-	 * Check to see if anything exists at the status register location.
-	 * I don't know if this is a good way to check, but it seems to work
-	 * ok for me.
-	 */
-	if (read_status_register() != 0xff) {
-		/*
-		 * Reset the drive and wait for attention from it (to say it's reset).
-		 * If you don't wait, the next operation will probably fail.
-		 */
-		reset_drive();
-		retry_count = jiffies + SONY_RESET_TIMEOUT;
-		while (time_before(jiffies, retry_count)
-		       && (!is_attention())) {
-			sony_sleep();
-		}
-
-#if 0
-		/* If attention is never seen probably not a CDU31a present */
-		if (!is_attention()) {
-			res_reg[0] = 0x20;
-			goto out_err;
-		}
-#endif
-
-		/*
-		 * Get the drive configuration.
-		 */
-		do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD,
-			       NULL,
-			       0, (unsigned char *) res_reg, res_size);
-		if (*res_size <= 2 || (res_reg[0] & 0xf0) != 0)
-			goto out_err;
-		return 1;
-	}
-
-	/* Return an error */
-	res_reg[0] = 0x20;
-out_err:
-	release_region(cdu31a_port, 4);
-	cdu31a_port = 0;
-	return 0;
-}
-
-#ifndef MODULE
-/*
- * Set up base I/O and interrupts, called from main.c.
- */
-
-static int __init cdu31a_setup(char *strings)
-{
-	int ints[4];
-
-	(void) get_options(strings, ARRAY_SIZE(ints), ints);
-
-	if (ints[0] > 0) {
-		cdu31a_port = ints[1];
-	}
-	if (ints[0] > 1) {
-		cdu31a_irq = ints[2];
-	}
-	if ((strings != NULL) && (*strings != '\0')) {
-		if (strcmp(strings, "PAS") == 0) {
-			sony_pas_init = 1;
-		} else {
-			printk(KERN_NOTICE PFX "Unknown interface type: %s\n",
-			       strings);
-		}
-	}
-
-	return 1;
-}
-
-__setup("cdu31a=", cdu31a_setup);
-
-#endif
-
-/*
- * Initialize the driver.
- */
-int __init cdu31a_init(void)
-{
-	struct s_sony_drive_config drive_config;
-	struct gendisk *disk;
-	int deficiency = 0;
-	unsigned int res_size;
-	char msg[255];
-	char buf[40];
-	int i;
-	int tmp_irq;
-
-	/*
-	 * According to Alex Freed (freed@europa.orion.adobe.com), this is
-	 * required for the Fusion CD-16 package.  If the sound driver is
-	 * loaded, it should work fine, but just in case...
-	 *
-	 * The following turn on the CD-ROM interface for a Fusion CD-16.
-	 */
-	if (sony_pas_init) {
-		outb(0xbc, 0x9a01);
-		outb(0xe2, 0x9a01);
-	}
-
-	/* Setting the base I/O address to 0xffff will disable it. */
-	if (cdu31a_port == 0xffff)
-		goto errout3;
-
-	if (cdu31a_port != 0) {
-		/* Need IRQ 0 because we can't sleep here. */
-		tmp_irq = cdu31a_irq;
-		cdu31a_irq = 0;
-		if (!get_drive_configuration(cdu31a_port,
-					    drive_config.exec_status,
-					    &res_size))
-			goto errout3;
-		cdu31a_irq = tmp_irq;
-	} else {
-		cdu31a_irq = 0;
-		for (i = 0; cdu31a_addresses[i].base; i++) {
-			if (get_drive_configuration(cdu31a_addresses[i].base,
-						     drive_config.exec_status,
-						     &res_size)) {
-				cdu31a_irq = cdu31a_addresses[i].int_num;
-				break;
-			}
-		}
-		if (!cdu31a_port)
-			goto errout3;
-	}
-
-	if (register_blkdev(MAJOR_NR, "cdu31a"))
-		goto errout2;
-
-	disk = alloc_disk(1);
-	if (!disk)
-		goto errout1;
-	disk->major = MAJOR_NR;
-	disk->first_minor = 0;
-	sprintf(disk->disk_name, "cdu31a");
-	disk->fops = &scd_bdops;
-	disk->flags = GENHD_FL_CD;
-
-	if (SONY_HWC_DOUBLE_SPEED(drive_config))
-		is_double_speed = 1;
-
-	tmp_irq = cdu31a_irq;	/* Need IRQ 0 because we can't sleep here. */
-	cdu31a_irq = 0;
-
-	sony_speed = is_double_speed; /* Set 2X drives to 2X by default */
-	set_drive_params(sony_speed);
-
-	cdu31a_irq = tmp_irq;
-
-	if (cdu31a_irq > 0) {
-		if (request_irq
-		    (cdu31a_irq, cdu31a_interrupt, IRQF_DISABLED,
-		     "cdu31a", NULL)) {
-			printk(KERN_WARNING PFX "Unable to grab IRQ%d for "
-					"the CDU31A driver\n", cdu31a_irq);
-			cdu31a_irq = 0;
-		}
-	}
-
-	sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n",
-		drive_config.vendor_id,
-		drive_config.product_id,
-		drive_config.product_rev_level);
-	sprintf(buf, "  Capabilities: %s",
-		load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]);
-	strcat(msg, buf);
-	if (SONY_HWC_AUDIO_PLAYBACK(drive_config))
-		strcat(msg, ", audio");
-	else
-		deficiency |= CDC_PLAY_AUDIO;
-	if (SONY_HWC_EJECT(drive_config))
-		strcat(msg, ", eject");
-	else
-		deficiency |= CDC_OPEN_TRAY;
-	if (SONY_HWC_LED_SUPPORT(drive_config))
-		strcat(msg, ", LED");
-	if (SONY_HWC_ELECTRIC_VOLUME(drive_config))
-		strcat(msg, ", elec. Vol");
-	if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config))
-		strcat(msg, ", sep. Vol");
-	if (is_double_speed)
-		strcat(msg, ", double speed");
-	else
-		deficiency |= CDC_SELECT_SPEED;
-	if (cdu31a_irq > 0) {
-		sprintf(buf, ", irq %d", cdu31a_irq);
-		strcat(msg, buf);
-	}
-	strcat(msg, "\n");
-	printk(KERN_INFO PFX "%s",msg);
-
-	cdu31a_queue = blk_init_queue(do_cdu31a_request, &cdu31a_lock);
-	if (!cdu31a_queue)
-		goto errout0;
-	blk_queue_hardsect_size(cdu31a_queue, 2048);
-
-	init_timer(&cdu31a_abort_timer);
-	cdu31a_abort_timer.function = handle_abort_timeout;
-
-	scd_info.mask = deficiency;
-	scd_gendisk = disk;
-	if (register_cdrom(&scd_info))
-		goto err;
-	disk->queue = cdu31a_queue;
-	add_disk(disk);
-
-	disk_changed = 1;
-	return 0;
-
-err:
-	blk_cleanup_queue(cdu31a_queue);
-errout0:
-	if (cdu31a_irq)
-		free_irq(cdu31a_irq, NULL);
-	printk(KERN_ERR PFX "Unable to register with Uniform cdrom driver\n");
-	put_disk(disk);
-errout1:
-	if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
-		printk(KERN_WARNING PFX "Can't unregister block device\n");
-	}
-errout2:
-	release_region(cdu31a_port, 4);
-errout3:
-	return -EIO;
-}
-
-
-static void __exit cdu31a_exit(void)
-{
-	del_gendisk(scd_gendisk);
-	put_disk(scd_gendisk);
-	if (unregister_cdrom(&scd_info)) {
-		printk(KERN_WARNING PFX "Can't unregister from Uniform "
-				"cdrom driver\n");
-		return;
-	}
-	if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) {
-		printk(KERN_WARNING PFX "Can't unregister\n");
-		return;
-	}
-
-	blk_cleanup_queue(cdu31a_queue);
-
-	if (cdu31a_irq > 0)
-		free_irq(cdu31a_irq, NULL);
-
-	release_region(cdu31a_port, 4);
-	printk(KERN_INFO PFX "module released.\n");
-}
-
-#ifdef MODULE
-module_init(cdu31a_init);
-#endif
-module_exit(cdu31a_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU31A_CDROM_MAJOR);
diff --git a/drivers/cdrom/cdu31a.h b/drivers/cdrom/cdu31a.h
deleted file mode 100644
index 61d4768..0000000
--- a/drivers/cdrom/cdu31a.h
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Definitions for a Sony interface CDROM drive.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com)
- *
- *  Copyright (C) 1993  Corey Minyard
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/*
- * General defines.
- */
-#define SONY_XA_DISK_TYPE 0x20
-
-/*
- * Offsets (from the base address) and bits for the various write registers
- * of the drive.
- */
-#define SONY_CMD_REG_OFFSET     0
-#define SONY_PARAM_REG_OFFSET   1
-#define SONY_WRITE_REG_OFFSET   2
-#define SONY_CONTROL_REG_OFFSET 3
-#       define SONY_ATTN_CLR_BIT        0x01
-#       define SONY_RES_RDY_CLR_BIT     0x02
-#       define SONY_DATA_RDY_CLR_BIT    0x04
-#       define SONY_ATTN_INT_EN_BIT     0x08
-#       define SONY_RES_RDY_INT_EN_BIT  0x10
-#       define SONY_DATA_RDY_INT_EN_BIT 0x20
-#       define SONY_PARAM_CLR_BIT       0x40
-#       define SONY_DRIVE_RESET_BIT     0x80
-
-/*
- * Offsets (from the base address) and bits for the various read registers
- * of the drive.
- */
-#define SONY_STATUS_REG_OFFSET  0
-#       define SONY_ATTN_BIT            0x01
-#       define SONY_RES_RDY_BIT         0x02
-#       define SONY_DATA_RDY_BIT        0x04
-#       define SONY_ATTN_INT_ST_BIT     0x08
-#       define SONY_RES_RDY_INT_ST_BIT  0x10
-#       define SONY_DATA_RDY_INT_ST_BIT 0x20
-#       define SONY_DATA_REQUEST_BIT    0x40
-#       define SONY_BUSY_BIT            0x80
-#define SONY_RESULT_REG_OFFSET  1
-#define SONY_READ_REG_OFFSET    2
-#define SONY_FIFOST_REG_OFFSET  3
-#       define SONY_PARAM_WRITE_RDY_BIT 0x01
-#       define SONY_PARAM_REG_EMPTY_BIT 0x02
-#       define SONY_RES_REG_NOT_EMP_BIT 0x04
-#       define SONY_RES_REG_FULL_BIT    0x08
-
-#define LOG_START_OFFSET        150     /* Offset of first logical sector */
-
-#define SONY_DETECT_TIMEOUT	(8*HZ/10) /* Maximum amount of time
-                                           that drive detection code
-                                           will wait for response
-                                           from drive (in 1/100th's
-                                           of seconds). */
- 
-#define SONY_JIFFIES_TIMEOUT    (10*HZ)	/* Maximum number of times the
-                                           drive will wait/try for an
-                                           operation */
-#define SONY_RESET_TIMEOUT      HZ	/* Maximum number of times the
-                                           drive will wait/try a reset
-                                           operation */
-#define SONY_READY_RETRIES      20000   /* How many times to retry a
-                                           spin waiting for a register
-                                           to come ready */
-
-#define MAX_CDU31A_RETRIES      3       /* How many times to retry an
-                                           operation */
-
-/* Commands to request or set drive control parameters and disc information */
-#define SONY_REQ_DRIVE_CONFIG_CMD       0x00    /* Returns s_sony_drive_config */
-#define SONY_REQ_DRIVE_MODE_CMD         0x01
-#define SONY_REQ_DRIVE_PARAM_CMD        0x02
-#define SONY_REQ_MECH_STATUS_CMD        0x03
-#define SONY_REQ_AUDIO_STATUS_CMD       0x04
-#define SONY_SET_DRIVE_PARAM_CMD        0x10
-#define SONY_REQ_TOC_DATA_CMD           0x20    /* Returns s_sony_toc */
-#define SONY_REQ_SUBCODE_ADDRESS_CMD    0x21    /* Returns s_sony_subcode */
-#define SONY_REQ_UPC_EAN_CMD            0x22
-#define SONY_REQ_ISRC_CMD               0x23
-#define SONY_REQ_TOC_DATA_SPEC_CMD      0x24    /* Returns s_sony_session_toc */
-
-/* Commands to request information from the drive */
-#define SONY_READ_TOC_CMD               0x30    /* let the drive firmware grab the TOC */
-#define SONY_SEEK_CMD                   0x31
-#define SONY_READ_CMD                   0x32
-#define SONY_READ_BLKERR_STAT_CMD       0x34
-#define SONY_ABORT_CMD                  0x35
-#define SONY_READ_TOC_SPEC_CMD          0x36
-
-/* Commands to control audio */
-#define SONY_AUDIO_PLAYBACK_CMD         0x40
-#define SONY_AUDIO_STOP_CMD             0x41
-#define SONY_AUDIO_SCAN_CMD             0x42
-
-/* Miscellaneous control commands */
-#define SONY_EJECT_CMD                  0x50
-#define SONY_SPIN_UP_CMD                0x51
-#define SONY_SPIN_DOWN_CMD              0x52
-
-/* Diagnostic commands */
-#define SONY_WRITE_BUFFER_CMD           0x60
-#define SONY_READ_BUFFER_CMD            0x61
-#define SONY_DIAGNOSTICS_CMD            0x62
-
-
-/*
- * The following are command parameters for the set drive parameter command
- */
-#define SONY_SD_DECODE_PARAM            0x00
-#define SONY_SD_INTERFACE_PARAM         0x01
-#define SONY_SD_BUFFERING_PARAM         0x02
-#define SONY_SD_AUDIO_PARAM             0x03
-#define SONY_SD_AUDIO_VOLUME            0x04
-#define SONY_SD_MECH_CONTROL            0x05
-#define SONY_SD_AUTO_SPIN_DOWN_TIME     0x06
-
-/*
- * The following are parameter bits for the mechanical control command
- */
-#define SONY_AUTO_SPIN_UP_BIT           0x01
-#define SONY_AUTO_EJECT_BIT             0x02
-#define SONY_DOUBLE_SPEED_BIT           0x04
-
-/*
- * The following extract information from the drive configuration about
- * the drive itself.
- */
-#define SONY_HWC_GET_LOAD_MECH(c)       (c.hw_config[0] & 0x03)
-#define SONY_HWC_EJECT(c)               (c.hw_config[0] & 0x04)
-#define SONY_HWC_LED_SUPPORT(c)         (c.hw_config[0] & 0x08)
-#define SONY_HWC_DOUBLE_SPEED(c)        (c.hw_config[0] & 0x10)
-#define SONY_HWC_GET_BUF_MEM_SIZE(c)    ((c.hw_config[0] & 0xc0) >> 6)
-#define SONY_HWC_AUDIO_PLAYBACK(c)      (c.hw_config[1] & 0x01)
-#define SONY_HWC_ELECTRIC_VOLUME(c)     (c.hw_config[1] & 0x02)
-#define SONY_HWC_ELECTRIC_VOLUME_CTL(c) (c.hw_config[1] & 0x04)
-
-#define SONY_HWC_CADDY_LOAD_MECH        0x00
-#define SONY_HWC_TRAY_LOAD_MECH         0x01
-#define SONY_HWC_POPUP_LOAD_MECH        0x02
-#define SONY_HWC_UNKWN_LOAD_MECH        0x03
-
-#define SONY_HWC_8KB_BUFFER             0x00
-#define SONY_HWC_32KB_BUFFER            0x01
-#define SONY_HWC_64KB_BUFFER            0x02
-#define SONY_HWC_UNKWN_BUFFER           0x03
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s_sony_drive_config
-{
-   unsigned char exec_status[2];
-   char vendor_id[8];
-   char product_id[16];
-   char product_rev_level[8];
-   unsigned char hw_config[2];
-};
-
-/* The following is returned from the request subcode address command */
-struct s_sony_subcode
-{
-   unsigned char exec_status[2];
-   unsigned char address        :4;
-   unsigned char control        :4;
-   unsigned char track_num;
-   unsigned char index_num;
-   unsigned char rel_msf[3];
-   unsigned char reserved1;
-   unsigned char abs_msf[3];
-};
-
-#define MAX_TRACKS 100	/* The maximum tracks a disk may have. */
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s_sony_toc
-{
-   unsigned char exec_status[2];
-   unsigned char address0       :4;
-   unsigned char control0       :4;
-   unsigned char point0;
-   unsigned char first_track_num;
-   unsigned char disk_type;
-   unsigned char dummy0;
-   unsigned char address1       :4;
-   unsigned char control1       :4;
-   unsigned char point1;
-   unsigned char last_track_num;
-   unsigned char dummy1;
-   unsigned char dummy2;
-   unsigned char address2       :4;
-   unsigned char control2       :4;
-   unsigned char point2;
-   unsigned char lead_out_start_msf[3];
-   struct
-   {
-      unsigned char address     :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[MAX_TRACKS];
-
-   unsigned int lead_out_start_lba;
-};
-
-struct s_sony_session_toc
-{
-   unsigned char exec_status[2];
-   unsigned char session_number;
-   unsigned char address0       :4;
-   unsigned char control0       :4;
-   unsigned char point0;
-   unsigned char first_track_num;
-   unsigned char disk_type;
-   unsigned char dummy0;
-   unsigned char address1       :4;
-   unsigned char control1       :4;
-   unsigned char point1;
-   unsigned char last_track_num;
-   unsigned char dummy1;
-   unsigned char dummy2;
-   unsigned char address2       :4;
-   unsigned char control2       :4;
-   unsigned char point2;
-   unsigned char lead_out_start_msf[3];
-   unsigned char addressb0      :4;
-   unsigned char controlb0      :4;
-   unsigned char pointb0;
-   unsigned char next_poss_prog_area_msf[3];
-   unsigned char num_mode_5_pointers;
-   unsigned char max_start_outer_leadout_msf[3];
-   unsigned char addressb1      :4;
-   unsigned char controlb1      :4;
-   unsigned char pointb1;
-   unsigned char dummyb0_1[4];
-   unsigned char num_skip_interval_pointers;
-   unsigned char num_skip_track_assignments;
-   unsigned char dummyb0_2;
-   unsigned char addressb2      :4;
-   unsigned char controlb2      :4;
-   unsigned char pointb2;
-   unsigned char tracksb2[7];
-   unsigned char addressb3      :4;
-   unsigned char controlb3      :4;
-   unsigned char pointb3;
-   unsigned char tracksb3[7];
-   unsigned char addressb4      :4;
-   unsigned char controlb4      :4;
-   unsigned char pointb4;
-   unsigned char tracksb4[7];
-   unsigned char addressc0      :4;
-   unsigned char controlc0      :4;
-   unsigned char pointc0;
-   unsigned char dummyc0[7];
-   struct
-   {
-      unsigned char address     :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[MAX_TRACKS];
-
-   unsigned int start_track_lba;
-   unsigned int lead_out_start_lba;
-   unsigned int mint;
-   unsigned int maxt;
-};
-
-struct s_all_sessions_toc
-{
-   unsigned char sessions;
-   unsigned int track_entries;
-   unsigned char first_track_num;
-   unsigned char last_track_num;
-   unsigned char disk_type;
-   unsigned char lead_out_start_msf[3];
-   struct
-   {
-      unsigned char address     :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[MAX_TRACKS];
-
-   unsigned int start_track_lba;
-   unsigned int lead_out_start_lba;
-};
-
-
-/*
- * The following are errors returned from the drive.
- */
-
-/* Command error group */
-#define SONY_ILL_CMD_ERR                0x10
-#define SONY_ILL_PARAM_ERR              0x11
-
-/* Mechanism group */
-#define SONY_NOT_LOAD_ERR               0x20
-#define SONY_NO_DISK_ERR                0x21
-#define SONY_NOT_SPIN_ERR               0x22
-#define SONY_SPIN_ERR                   0x23
-#define SONY_SPINDLE_SERVO_ERR          0x25
-#define SONY_FOCUS_SERVO_ERR            0x26
-#define SONY_EJECT_MECH_ERR             0x29
-#define SONY_AUDIO_PLAYING_ERR          0x2a
-#define SONY_EMERGENCY_EJECT_ERR        0x2c
-
-/* Seek error group */
-#define SONY_FOCUS_ERR                  0x30
-#define SONY_FRAME_SYNC_ERR             0x31
-#define SONY_SUBCODE_ADDR_ERR           0x32
-#define SONY_BLOCK_SYNC_ERR             0x33
-#define SONY_HEADER_ADDR_ERR            0x34
-
-/* Read error group */
-#define SONY_ILL_TRACK_R_ERR            0x40
-#define SONY_MODE_0_R_ERR               0x41
-#define SONY_ILL_MODE_R_ERR             0x42
-#define SONY_ILL_BLOCK_SIZE_R_ERR       0x43
-#define SONY_MODE_R_ERR                 0x44
-#define SONY_FORM_R_ERR                 0x45
-#define SONY_LEAD_OUT_R_ERR             0x46
-#define SONY_BUFFER_OVERRUN_R_ERR       0x47
-
-/* Data error group */
-#define SONY_UNREC_CIRC_ERR             0x53
-#define SONY_UNREC_LECC_ERR             0x57
-
-/* Subcode error group */
-#define SONY_NO_TOC_ERR                 0x60
-#define SONY_SUBCODE_DATA_NVAL_ERR      0x61
-#define SONY_FOCUS_ON_TOC_READ_ERR      0x63
-#define SONY_FRAME_SYNC_ON_TOC_READ_ERR 0x64
-#define SONY_TOC_DATA_ERR               0x65
-
-/* Hardware failure group */
-#define SONY_HW_FAILURE_ERR             0x70
-#define SONY_LEAD_IN_A_ERR              0x91
-#define SONY_LEAD_OUT_A_ERR             0x92
-#define SONY_DATA_TRACK_A_ERR           0x93
-
-/*
- * The following are returned from the Read With Block Error Status command.
- * They are not errors but information (Errors from the 0x5x group above may
- * also be returned
- */
-#define SONY_NO_CIRC_ERR_BLK_STAT       0x50
-#define SONY_NO_LECC_ERR_BLK_STAT       0x54
-#define SONY_RECOV_LECC_ERR_BLK_STAT    0x55
-#define SONY_NO_ERR_DETECTION_STAT      0x59
-
-/* 
- * The following is not an error returned by the drive, but by the code
- * that talks to the drive.  It is returned because of a timeout.
- */
-#define SONY_TIMEOUT_OP_ERR             0x01
-#define SONY_SIGNAL_OP_ERR              0x02
-#define SONY_BAD_DATA_ERR               0x03
-
-
-/*
- * The following are attention code for asynchronous events from the drive.
- */
-
-/* Standard attention group */
-#define SONY_EMER_EJECT_ATTN            0x2c
-#define SONY_HW_FAILURE_ATTN            0x70
-#define SONY_MECH_LOADED_ATTN           0x80
-#define SONY_EJECT_PUSHED_ATTN          0x81
-
-/* Audio attention group */
-#define SONY_AUDIO_PLAY_DONE_ATTN       0x90
-#define SONY_LEAD_IN_ERR_ATTN           0x91
-#define SONY_LEAD_OUT_ERR_ATTN          0x92
-#define SONY_DATA_TRACK_ERR_ATTN        0x93
-#define SONY_AUDIO_PLAYBACK_ERR_ATTN    0x94
-
-/* Auto spin up group */
-#define SONY_SPIN_UP_COMPLETE_ATTN      0x24
-#define SONY_SPINDLE_SERVO_ERR_ATTN     0x25
-#define SONY_FOCUS_SERVO_ERR_ATTN       0x26
-#define SONY_TOC_READ_DONE_ATTN         0x62
-#define SONY_FOCUS_ON_TOC_READ_ERR_ATTN 0x63
-#define SONY_SYNC_ON_TOC_READ_ERR_ATTN  0x65
-
-/* Auto eject group */
-#define SONY_SPIN_DOWN_COMPLETE_ATTN    0x27
-#define SONY_EJECT_COMPLETE_ATTN        0x28
-#define SONY_EJECT_MECH_ERR_ATTN        0x29
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
deleted file mode 100644
index 2301311..0000000
--- a/drivers/cdrom/cm206.c
+++ /dev/null
@@ -1,1594 +0,0 @@
-/* cm206.c. A linux-driver for the cm206 cdrom player with cm260 adapter card.
-   Copyright (c) 1995--1997 David A. van Leeuwen.
-   $Id: cm206.c,v 1.5 1997/12/26 11:02:51 david Exp $
-   
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published by
-     the Free Software Foundation; either version 2 of the License, or
-     (at your option) any later version.
-     
-     This program is distributed in the hope that it will be useful,
-     but WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-     GNU General Public License for more details.
-     
-     You should have received a copy of the GNU General Public License
-     along with this program; if not, write to the Free Software
-     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-History:
- Started 25 jan 1994. Waiting for documentation...
- 22 feb 1995: 0.1a first reasonably safe polling driver.
-	      Two major bugs, one in read_sector and one in 
-	      do_cm206_request, happened to cancel!
- 25 feb 1995: 0.2a first reasonable interrupt driven version of above.
-              uart writes are still done in polling mode. 
- 25 feb 1995: 0.21a writes also in interrupt mode, still some
-	      small bugs to be found... Larger buffer. 
-  2 mrt 1995: 0.22 Bug found (cd-> nowhere, interrupt was called in
-              initialization), read_ahead of 16. Timeouts implemented.
-	      unclear if they do something...
-  7 mrt 1995: 0.23 Start of background read-ahead.
- 18 mrt 1995: 0.24 Working background read-ahead. (still problems)
- 26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2).
-              Statistics implemented, though separate stats206.h.
-	      Accessible through ioctl 0x1000 (just a number).
-	      Hard to choose between v1.2 development and 1.1.75.
-	      Bottom-half doesn't work with 1.2...
-	      0.25a: fixed... typo. Still problems...
-  1 apr 1995: 0.26 Module support added. Most bugs found. Use kernel 1.2.n.
-  5 apr 1995: 0.27 Auto-probe for the adapter card base address.
-              Auto-probe for the adaptor card irq line.
-  7 apr 1995: 0.28 Added lilo setup support for base address and irq.
-              Use major number 32 (not in this source), officially
-	      assigned to this driver.
-  9 apr 1995: 0.29 Added very limited audio support. Toc_header, stop, pause,
-              resume, eject. Play_track ignores track info, because we can't 
-	      read a table-of-contents entry. Toc_entry is implemented
-	      as a `placebo' function: always returns start of disc. 
-  3 may 1995: 0.30 Audio support completed. The get_toc_entry function
-              is implemented as a binary search. 
- 15 may 1995: 0.31 More work on audio stuff. Workman is not easy to 
-              satisfy; changed binary search into linear search.
-	      Auto-probe for base address somewhat relaxed.
-  1 jun 1995: 0.32 Removed probe_irq_on/off for module version.
- 10 jun 1995: 0.33 Workman still behaves funny, but you should be
-              able to eject and substitute another disc.
-
- An adaptation of 0.33 is included in linux-1.3.7 by Eberhard Moenkeberg
-
- 18 jul 1995: 0.34 Patch by Heiko Eissfeldt included, mainly considering 
-              verify_area's in the ioctls. Some bugs introduced by 
-	      EM considering the base port and irq fixed. 
-
- 18 dec 1995: 0.35 Add some code for error checking... no luck...
-
- We jump to reach our goal: version 1.0 in the next stable linux kernel.
-
- 19 mar 1996: 0.95 Different implementation of CDROM_GET_UPC, on
-	      request of Thomas Quinot. 
- 25 mar 1996: 0.96 Interpretation of opening with O_WRONLY or O_RDWR:
-	      open only for ioctl operation, e.g., for operation of
-	      tray etc.
- 4 apr 1996:  0.97 First implementation of layer between VFS and cdrom
-              driver, a generic interface. Much of the functionality
-	      of cm206_open() and cm206_ioctl() is transferred to a
-	      new file cdrom.c and its header ucdrom.h. 
-
-	      Upgrade to Linux kernel 1.3.78. 
-
- 11 apr 1996  0.98 Upgrade to Linux kernel 1.3.85
-              More code moved to cdrom.c
- 
- 	      0.99 Some more small changes to decrease number
- 	      of oopses at module load; 
- 
- 27 jul 1996  0.100 Many hours of debugging, kernel change from 1.2.13
-	      to 2.0.7 seems to have introduced some weird behavior
-	      in (interruptible_)sleep_on(&cd->data): the process
-	      seems to be woken without any explicit wake_up in my own
-	      code. Patch to try 100x in case such untriggered wake_up's 
-	      occur. 
-
- 28 jul 1996  0.101 Rewriting of the code that receives the command echo,
-	      using a fifo to store echoed bytes. 
-
- 	      Branch from 0.99:
- 
- 	      0.99.1.0 Update to kernel release 2.0.10 dev_t -> kdev_t
- 	      (emoenke) various typos found by others.  extra
- 	      module-load oops protection.
- 
- 	      0.99.1.1 Initialization constant cdrom_dops.speed
- 	      changed from float (2.0) to int (2); Cli()-sti() pair
- 	      around cm260_reset() in module initialization code.
- 
- 	      0.99.1.2 Changes literally as proposed by Scott Snyder
- 	      <snyder@d0sgif.fnal.gov> for the 2.1 kernel line, which
- 	      have to do mainly with the poor minor support i had. The
- 	      major new concept is to change a cdrom driver's
- 	      operations struct from the capabilities struct. This
- 	      reflects the fact that there is one major for a driver,
- 	      whilst there can be many minors whith completely
- 	      different capabilities.
-
-	      0.99.1.3 More changes for operations/info separation.
-
-	      0.99.1.4 Added speed selection (someone had to do this
-	      first).
-
-  23 jan 1997 0.99.1.5 MODULE_PARMS call added.
-
-  23 jan 1997 0.100.1.2--0.100.1.5 following similar lines as 
-  	      0.99.1.1--0.99.1.5. I get too many complaints about the
-	      drive making read errors. What't wrong with the 2.0+
-	      kernel line? Why get i (and othe cm206 owners) weird
-	      results? Why were things good in the good old 1.1--1.2 
-	      era? Why don't i throw away the drive?
-
- 2 feb 1997   0.102 Added `volatile' to values in cm206_struct. Seems to 
- 	      reduce many of the problems. Rewrote polling routines
-	      to use fixed delays between polls. 
-	      0.103 Changed printk behavior. 
-	      0.104 Added a 0.100 -> 0.100.1.1 change
-
-11 feb 1997   0.105 Allow auto_probe during module load, disable
-              with module option "auto_probe=0". Moved some debugging
-	      statements to lower priority. Implemented select_speed()
-	      function. 
-
-13 feb 1997   1.0 Final version for 2.0 kernel line. 
-
-	      All following changes will be for the 2.1 kernel line. 
-
-15 feb 1997   1.1 Keep up with kernel 2.1.26, merge in changes from 
-              cdrom.c 0.100.1.1--1.0. Add some more MODULE_PARMS. 
-
-14 sep 1997   1.2 Upgrade to Linux 2.1.55.  Added blksize_size[], patch
-              sent by James Bottomley <James.Bottomley@columbiasc.ncr.com>.
-
-21 dec 1997   1.4 Upgrade to Linux 2.1.72.  
-
-24 jan 1998   Removed the cm206_disc_status() function, as it was now dead
-              code.  The Uniform CDROM driver now provides this functionality.
-	      
-9 Nov. 1999   Make kernel-parameter implementation work with 2.3.x 
-	      Removed init_module & cleanup_module in favor of 
-	      module_init & module_exit.
-	      Torben Mathiasen <tmm@image.dk>
- * 
- * Parts of the code are based upon lmscd.c written by Kai Petzke,
- * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
- * Harriss, but any off-the-shelf dynamic programming algorithm won't
- * be able to find them.
- *
- * The cm206 drive interface and the cm260 adapter card seem to be 
- * sufficiently different from their cm205/cm250 counterparts
- * in order to write a complete new driver.
- * 
- * I call all routines connected to the Linux kernel something
- * with `cm206' in it, as this stuff is too series-dependent. 
- * 
- * Currently, my limited knowledge is based on:
- * - The Linux Kernel Hacker's guide, v. 0.5, by Michael K. Johnson
- * - Linux Kernel Programmierung, by Michael Beck and others
- * - Philips/LMS cm206 and cm226 product specification
- * - Philips/LMS cm260 product specification
- *
- * David van Leeuwen, david@tm.tno.nl.  */
-#define REVISION "$Revision: 1.5 $"
-
-#include <linux/module.h>
-
-#include <linux/errno.h>	/* These include what we really need */
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-/* #include <linux/ucdrom.h> */
-
-#include <asm/io.h>
-
-#define MAJOR_NR CM206_CDROM_MAJOR
-
-#include <linux/blkdev.h>
-
-#undef DEBUG
-#define STATISTICS		/* record times and frequencies of events */
-#define AUTO_PROBE_MODULE
-#define USE_INSW
-
-#include "cm206.h"
-
-/* This variable defines whether or not to probe for adapter base port 
-   address and interrupt request. It can be overridden by the boot 
-   parameter `auto'.
-*/
-static int auto_probe = 1;	/* Yes, why not? */
-
-static int cm206_base = CM206_BASE;
-static int cm206_irq = CM206_IRQ;
-#ifdef MODULE
-static int cm206[2] = { 0, 0 };	/* for compatible `insmod' parameter passing */
-module_param_array(cm206, int, NULL, 0);	/* base,irq or irq,base */
-#endif
-
-module_param(cm206_base, int, 0);	/* base */
-module_param(cm206_irq, int, 0);	/* irq */
-module_param(auto_probe, bool, 0);	/* auto probe base and irq */
-MODULE_LICENSE("GPL");
-
-#define POLLOOP 100		/* milliseconds */
-#define READ_AHEAD 1		/* defines private buffer, waste! */
-#define BACK_AHEAD 1		/* defines adapter-read ahead */
-#define DATA_TIMEOUT (3*HZ)	/* measured in jiffies (10 ms) */
-#define UART_TIMEOUT (5*HZ/100)
-#define DSB_TIMEOUT (7*HZ)	/* time for the slowest command to finish */
-#define UR_SIZE 4		/* uart receive buffer fifo size */
-
-#define LINUX_BLOCK_SIZE 512	/* WHERE is this defined? */
-#define RAW_SECTOR_SIZE 2352	/* ok, is also defined in cdrom.h */
-#define ISO_SECTOR_SIZE 2048
-#define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE)	/* 4 */
-#define CD_SYNC_HEAD 16		/* CD_SYNC + CD_HEAD */
-
-#ifdef STATISTICS		/* keep track of errors in counters */
-#define stats(i) { ++cd->stats[st_ ## i]; \
-		     cd->last_stat[st_ ## i] = cd->stat_counter++; \
-		 }
-#else
-#define stats(i) (void) 0;
-#endif
-
-#define Debug(a) {printk (KERN_DEBUG); printk a;}
-#ifdef DEBUG
-#define debug(a) Debug(a)
-#else
-#define debug(a) (void) 0;
-#endif
-
-typedef unsigned char uch;	/* 8-bits */
-typedef unsigned short ush;	/* 16-bits */
-
-struct toc_struct {		/* private copy of Table of Contents */
-	uch track, fsm[3], q0;
-};
-
-struct cm206_struct {
-	volatile ush intr_ds;	/* data status read on last interrupt */
-	volatile ush intr_ls;	/* uart line status read on last interrupt */
-	volatile uch ur[UR_SIZE];	/* uart receive buffer fifo */
-	volatile uch ur_w, ur_r;	/* write/read buffer index */
-	volatile uch dsb, cc;	/* drive status byte and condition (error) code */
-	int command;		/* command to be written to the uart */
-	int openfiles;
-	ush sector[READ_AHEAD * RAW_SECTOR_SIZE / 2];	/* buffered cd-sector */
-	int sector_first, sector_last;	/* range of these sectors */
-	wait_queue_head_t uart;	/* wait queues for interrupt */
-	wait_queue_head_t data;
-	struct timer_list timer;	/* time-out */
-	char timed_out;
-	signed char max_sectors;	/* number of sectors that fit in adapter mem */
-	char wait_back;		/* we're waiting for a background-read */
-	char background;	/* is a read going on in the background? */
-	int adapter_first;	/* if so, that's the starting sector */
-	int adapter_last;
-	char fifo_overflowed;
-	uch disc_status[7];	/* result of get_disc_status command */
-#ifdef STATISTICS
-	int stats[NR_STATS];
-	int last_stat[NR_STATS];	/* `time' at which stat was stat */
-	int stat_counter;
-#endif
-	struct toc_struct toc[101];	/* The whole table of contents + lead-out */
-	uch q[10];		/* Last read q-channel info */
-	uch audio_status[5];	/* last read position on pause */
-	uch media_changed;	/* record if media changed */
-};
-
-#define DISC_STATUS cd->disc_status[0]
-#define FIRST_TRACK cd->disc_status[1]
-#define LAST_TRACK cd->disc_status[2]
-#define PAUSED cd->audio_status[0]	/* misuse this memory byte! */
-#define PLAY_TO cd->toc[0]	/* toc[0] records end-time in play */
-
-static struct cm206_struct *cd;	/* the main memory structure */
-static struct request_queue *cm206_queue;
-static DEFINE_SPINLOCK(cm206_lock);
-
-/* First, we define some polling functions. These are actually
-   only being used in the initialization. */
-
-static void send_command_polled(int command)
-{
-	int loop = POLLOOP;
-	while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
-	       && loop > 0) {
-		mdelay(1);	/* one millisec delay */
-		--loop;
-	}
-	outw(command, r_uart_transmit);
-}
-
-static uch receive_echo_polled(void)
-{
-	int loop = POLLOOP;
-	while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
-		mdelay(1);
-		--loop;
-	}
-	return ((uch) inw(r_uart_receive));
-}
-
-static uch send_receive_polled(int command)
-{
-	send_command_polled(command);
-	return receive_echo_polled();
-}
-
-static inline void clear_ur(void)
-{
-	if (cd->ur_r != cd->ur_w) {
-		debug(("Deleting bytes from fifo:"));
-		for (; cd->ur_r != cd->ur_w;
-		     cd->ur_r++, cd->ur_r %= UR_SIZE)
-			debug((" 0x%x", cd->ur[cd->ur_r]));
-		debug(("\n"));
-	}
-}
-
-static struct tasklet_struct cm206_tasklet;
-
-/* The interrupt handler. When the cm260 generates an interrupt, very
-   much care has to be taken in reading out the registers in the right
-   order; in case of a receive_buffer_full interrupt, first the
-   uart_receive must be read, and then the line status again to
-   de-assert the interrupt line. It took me a couple of hours to find
-   this out:-( 
-
-   The function reset_cm206 appears to cause an interrupt, because
-   pulling up the INIT line clears both the uart-write-buffer /and/
-   the uart-write-buffer-empty mask. We call this a `lost interrupt,'
-   as there seems so reason for this to happen.
-*/
-
-static irqreturn_t cm206_interrupt(int sig, void *dev_id)
-{
-	volatile ush fool;
-	cd->intr_ds = inw(r_data_status);	/* resets data_ready, data_error,
-						   crc_error, sync_error, toc_ready 
-						   interrupts */
-	cd->intr_ls = inw(r_line_status);	/* resets overrun bit */
-	debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls,
-	       cd->background));
-	if (cd->intr_ls & ls_attention)
-		stats(attention);
-	/* receive buffer full? */
-	if (cd->intr_ls & ls_receive_buffer_full) {
-		cd->ur[cd->ur_w] = inb(r_uart_receive);	/* get order right! */
-		cd->intr_ls = inw(r_line_status);	/* resets rbf interrupt */
-		debug(("receiving #%d: 0x%x\n", cd->ur_w,
-		       cd->ur[cd->ur_w]));
-		cd->ur_w++;
-		cd->ur_w %= UR_SIZE;
-		if (cd->ur_w == cd->ur_r)
-			debug(("cd->ur overflow!\n"));
-		if (waitqueue_active(&cd->uart) && cd->background < 2) {
-			del_timer(&cd->timer);
-			wake_up_interruptible(&cd->uart);
-		}
-	}
-	/* data ready in fifo? */
-	else if (cd->intr_ds & ds_data_ready) {
-		if (cd->background)
-			++cd->adapter_last;
-		if (waitqueue_active(&cd->data)
-		    && (cd->wait_back || !cd->background)) {
-			del_timer(&cd->timer);
-			wake_up_interruptible(&cd->data);
-		}
-		stats(data_ready);
-	}
-	/* ready to issue a write command? */
-	else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) {
-		outw(dc_normal | (inw(r_data_status) & 0x7f),
-		     r_data_control);
-		outw(cd->command, r_uart_transmit);
-		cd->command = 0;
-		if (!cd->background)
-			wake_up_interruptible(&cd->uart);
-	}
-	/* now treat errors (at least, identify them for debugging) */
-	else if (cd->intr_ds & ds_fifo_overflow) {
-		debug(("Fifo overflow at sectors 0x%x\n",
-		       cd->sector_first));
-		fool = inw(r_fifo_output_buffer);	/* de-assert the interrupt */
-		cd->fifo_overflowed = 1;	/* signal one word less should be read */
-		stats(fifo_overflow);
-	} else if (cd->intr_ds & ds_data_error) {
-		debug(("Data error at sector 0x%x\n", cd->sector_first));
-		stats(data_error);
-	} else if (cd->intr_ds & ds_crc_error) {
-		debug(("CRC error at sector 0x%x\n", cd->sector_first));
-		stats(crc_error);
-	} else if (cd->intr_ds & ds_sync_error) {
-		debug(("Sync at sector 0x%x\n", cd->sector_first));
-		stats(sync_error);
-	} else if (cd->intr_ds & ds_toc_ready) {
-		/* do something appropriate */
-	}
-	/* couldn't see why this interrupt, maybe due to init */
-	else {
-		outw(dc_normal | READ_AHEAD, r_data_control);
-		stats(lost_intr);
-	}
-	if (cd->background
-	    && (cd->adapter_last - cd->adapter_first == cd->max_sectors
-		|| cd->fifo_overflowed))
-		tasklet_schedule(&cm206_tasklet);	/* issue a stop read command */
-	stats(interrupt);
-	return IRQ_HANDLED;
-}
-
-/* we have put the address of the wait queue in who */
-static void cm206_timeout(unsigned long who)
-{
-	cd->timed_out = 1;
-	debug(("Timing out\n"));
-	wake_up_interruptible((wait_queue_head_t *) who);
-}
-
-/* This function returns 1 if a timeout occurred, 0 if an interrupt
-   happened */
-static int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
-{
-	cd->timed_out = 0;
-	init_timer(&cd->timer);
-	cd->timer.data = (unsigned long) wait;
-	cd->timer.expires = jiffies + timeout;
-	add_timer(&cd->timer);
-	debug(("going to sleep\n"));
-	interruptible_sleep_on(wait);
-	del_timer(&cd->timer);
-	if (cd->timed_out) {
-		cd->timed_out = 0;
-		return 1;
-	} else
-		return 0;
-}
-
-static void send_command(int command)
-{
-	debug(("Sending 0x%x\n", command));
-	if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
-		cd->command = command;
-		cli();		/* don't interrupt before sleep */
-		outw(dc_mask_sync_error | dc_no_stop_on_error |
-		     (inw(r_data_status) & 0x7f), r_data_control);
-		/* interrupt routine sends command */
-		if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
-			debug(("Time out on write-buffer\n"));
-			stats(write_timeout);
-			outw(command, r_uart_transmit);
-		}
-		debug(("Write commmand delayed\n"));
-	} else
-		outw(command, r_uart_transmit);
-}
-
-static uch receive_byte(int timeout)
-{
-	uch ret;
-	cli();
-	debug(("cli\n"));
-	ret = cd->ur[cd->ur_r];
-	if (cd->ur_r != cd->ur_w) {
-		sti();
-		debug(("returning #%d: 0x%x\n", cd->ur_r,
-		       cd->ur[cd->ur_r]));
-		cd->ur_r++;
-		cd->ur_r %= UR_SIZE;
-		return ret;
-	} else if (sleep_or_timeout(&cd->uart, timeout)) {	/* does sti() */
-		debug(("Time out on receive-buffer\n"));
-#ifdef STATISTICS
-		if (timeout == UART_TIMEOUT)
-			stats(receive_timeout)	/* no `;'! */
-			    else
-			stats(dsb_timeout);
-#endif
-		return 0xda;
-	}
-	ret = cd->ur[cd->ur_r];
-	debug(("slept; returning #%d: 0x%x\n", cd->ur_r,
-	       cd->ur[cd->ur_r]));
-	cd->ur_r++;
-	cd->ur_r %= UR_SIZE;
-	return ret;
-}
-
-static inline uch receive_echo(void)
-{
-	return receive_byte(UART_TIMEOUT);
-}
-
-static inline uch send_receive(int command)
-{
-	send_command(command);
-	return receive_echo();
-}
-
-static inline uch wait_dsb(void)
-{
-	return receive_byte(DSB_TIMEOUT);
-}
-
-static int type_0_command(int command, int expect_dsb)
-{
-	int e;
-	clear_ur();
-	if (command != (e = send_receive(command))) {
-		debug(("command 0x%x echoed as 0x%x\n", command, e));
-		stats(echo);
-		return -1;
-	}
-	if (expect_dsb) {
-		cd->dsb = wait_dsb();	/* wait for command to finish */
-	}
-	return 0;
-}
-
-static int type_1_command(int command, int bytes, uch * status)
-{				/* returns info */
-	int i;
-	if (type_0_command(command, 0))
-		return -1;
-	for (i = 0; i < bytes; i++)
-		status[i] = send_receive(c_gimme);
-	return 0;
-}
-
-/* This function resets the adapter card. We'd better not do this too
- * often, because it tends to generate `lost interrupts.' */
-static void reset_cm260(void)
-{
-	outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
-	udelay(10);		/* 3.3 mu sec minimum */
-	outw(dc_normal | READ_AHEAD, r_data_control);
-}
-
-/* fsm: frame-sec-min from linear address; one of many */
-static void fsm(int lba, uch * fsm)
-{
-	fsm[0] = lba % 75;
-	lba /= 75;
-	lba += 2;
-	fsm[1] = lba % 60;
-	fsm[2] = lba / 60;
-}
-
-static inline int fsm2lba(uch * fsm)
-{
-	return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
-}
-
-static inline int f_s_m2lba(uch f, uch s, uch m)
-{
-	return f + 75 * (s - 2 + 60 * m);
-}
-
-static int start_read(int start)
-{
-	uch read_sector[4] = { c_read_data, };
-	int i, e;
-
-	fsm(start, &read_sector[1]);
-	clear_ur();
-	for (i = 0; i < 4; i++)
-		if (read_sector[i] != (e = send_receive(read_sector[i]))) {
-			debug(("read_sector: %x echoes %x\n",
-			       read_sector[i], e));
-			stats(echo);
-			if (e == 0xff) {	/* this seems to happen often */
-				e = receive_echo();
-				debug(("Second try %x\n", e));
-				if (e != read_sector[i])
-					return -1;
-			}
-		}
-	return 0;
-}
-
-static int stop_read(void)
-{
-	int e;
-	type_0_command(c_stop, 0);
-	if ((e = receive_echo()) != 0xff) {
-		debug(("c_stop didn't send 0xff, but 0x%x\n", e));
-		stats(stop_0xff);
-		return -1;
-	}
-	return 0;
-}
-
-/* This function starts to read sectors in adapter memory, the
-   interrupt routine should stop the read. In fact, the bottom_half
-   routine takes care of this. Set a flag `background' in the cd
-   struct to indicate the process. */
-
-static int read_background(int start, int reading)
-{
-	if (cd->background)
-		return -1;	/* can't do twice */
-	outw(dc_normal | BACK_AHEAD, r_data_control);
-	if (!reading && start_read(start))
-		return -2;
-	cd->adapter_first = cd->adapter_last = start;
-	cd->background = 1;	/* flag a read is going on */
-	return 0;
-}
-
-#ifdef USE_INSW
-#define transport_data insw
-#else
-/* this routine implements insw(,,). There was a time i had the
-   impression that there would be any difference in error-behaviour. */
-void transport_data(int port, ush * dest, int count)
-{
-	int i;
-	ush *d;
-	for (i = 0, d = dest; i < count; i++, d++)
-		*d = inw(port);
-}
-#endif
-
-
-#define MAX_TRIES 100
-static int read_sector(int start)
-{
-	int tries = 0;
-	if (cd->background) {
-		cd->background = 0;
-		cd->adapter_last = -1;	/* invalidate adapter memory */
-		stop_read();
-	}
-	cd->fifo_overflowed = 0;
-	reset_cm260();		/* empty fifo etc. */
-	if (start_read(start))
-		return -1;
-	do {
-		if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
-			debug(("Read timed out sector 0x%x\n", start));
-			stats(read_timeout);
-			stop_read();
-			return -3;
-		}
-		tries++;
-	} while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES);
-	if (tries > 1)
-		debug(("Took me some tries\n"))
-		    else
-	if (tries == MAX_TRIES)
-		debug(("MAX_TRIES tries for read sector\n"));
-	transport_data(r_fifo_output_buffer, cd->sector,
-		       READ_AHEAD * RAW_SECTOR_SIZE / 2);
-	if (read_background(start + READ_AHEAD, 1))
-		stats(read_background);
-	cd->sector_first = start;
-	cd->sector_last = start + READ_AHEAD;
-	stats(read_restarted);
-	return 0;
-}
-
-/* The function of bottom-half is to send a stop command to the drive
-   This isn't easy because the routine is not `owned' by any process;
-   we can't go to sleep! The variable cd->background gives the status:
-   0 no read pending
-   1 a read is pending
-   2 c_stop waits for write_buffer_empty
-   3 c_stop waits for receive_buffer_full: echo
-   4 c_stop waits for receive_buffer_full: 0xff
-*/
-
-static void cm206_tasklet_func(unsigned long ignore)
-{
-	debug(("bh: %d\n", cd->background));
-	switch (cd->background) {
-	case 1:
-		stats(bh);
-		if (!(cd->intr_ls & ls_transmitter_buffer_empty)) {
-			cd->command = c_stop;
-			outw(dc_mask_sync_error | dc_no_stop_on_error |
-			     (inw(r_data_status) & 0x7f), r_data_control);
-			cd->background = 2;
-			break;	/* we'd better not time-out here! */
-		} else
-			outw(c_stop, r_uart_transmit);
-		/* fall into case 2: */
-	case 2:
-		/* the write has been satisfied by interrupt routine */
-		cd->background = 3;
-		break;
-	case 3:
-		if (cd->ur_r != cd->ur_w) {
-			if (cd->ur[cd->ur_r] != c_stop) {
-				debug(("cm206_bh: c_stop echoed 0x%x\n",
-				       cd->ur[cd->ur_r]));
-				stats(echo);
-			}
-			cd->ur_r++;
-			cd->ur_r %= UR_SIZE;
-		}
-		cd->background++;
-		break;
-	case 4:
-		if (cd->ur_r != cd->ur_w) {
-			if (cd->ur[cd->ur_r] != 0xff) {
-				debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r]));
-				stats(stop_0xff);
-			}
-			cd->ur_r++;
-			cd->ur_r %= UR_SIZE;
-		}
-		cd->background = 0;
-	}
-}
-
-static DECLARE_TASKLET(cm206_tasklet, cm206_tasklet_func, 0);
-
-/* This command clears the dsb_possible_media_change flag, so we must 
- * retain it.
- */
-static void get_drive_status(void)
-{
-	uch status[2];
-	type_1_command(c_drive_status, 2, status);	/* this might be done faster */
-	cd->dsb = status[0];
-	cd->cc = status[1];
-	cd->media_changed |=
-	    !!(cd->dsb & (dsb_possible_media_change |
-			  dsb_drive_not_ready | dsb_tray_not_closed));
-}
-
-static void get_disc_status(void)
-{
-	if (type_1_command(c_disc_status, 7, cd->disc_status)) {
-		debug(("get_disc_status: error\n"));
-	}
-}
-
-/* The new open. The real opening strategy is defined in cdrom.c. */
-
-static int cm206_open(struct cdrom_device_info *cdi, int purpose)
-{
-	if (!cd->openfiles) {	/* reset only first time */
-		cd->background = 0;
-		reset_cm260();
-		cd->adapter_last = -1;	/* invalidate adapter memory */
-		cd->sector_last = -1;
-	}
-	++cd->openfiles;
-	stats(open);
-	return 0;
-}
-
-static void cm206_release(struct cdrom_device_info *cdi)
-{
-	if (cd->openfiles == 1) {
-		if (cd->background) {
-			cd->background = 0;
-			stop_read();
-		}
-		cd->sector_last = -1;	/* Make our internal buffer invalid */
-		FIRST_TRACK = 0;	/* No valid disc status */
-	}
-	--cd->openfiles;
-}
-
-/* Empty buffer empties $sectors$ sectors of the adapter card buffer,
- * and then reads a sector in kernel memory.  */
-static void empty_buffer(int sectors)
-{
-	while (sectors >= 0) {
-		transport_data(r_fifo_output_buffer,
-			       cd->sector + cd->fifo_overflowed,
-			       RAW_SECTOR_SIZE / 2 - cd->fifo_overflowed);
-		--sectors;
-		++cd->adapter_first;	/* update the current adapter sector */
-		cd->fifo_overflowed = 0;	/* reset overflow bit */
-		stats(sector_transferred);
-	}
-	cd->sector_first = cd->adapter_first - 1;
-	cd->sector_last = cd->adapter_first;	/* update the buffer sector */
-}
-
-/* try_adapter. This function determines if the requested sector is
-   in adapter memory, or will appear there soon. Returns 0 upon
-   success */
-static int try_adapter(int sector)
-{
-	if (cd->adapter_first <= sector && sector < cd->adapter_last) {
-		/* sector is in adapter memory */
-		empty_buffer(sector - cd->adapter_first);
-		return 0;
-	} else if (cd->background == 1 && cd->adapter_first <= sector
-		   && sector < cd->adapter_first + cd->max_sectors) {
-		/* a read is going on, we can wait for it */
-		cd->wait_back = 1;
-		while (sector >= cd->adapter_last) {
-			if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
-				debug(("Timed out during background wait: %d %d %d %d\n", sector, cd->adapter_last, cd->adapter_first, cd->background));
-				stats(back_read_timeout);
-				cd->wait_back = 0;
-				return -1;
-			}
-		}
-		cd->wait_back = 0;
-		empty_buffer(sector - cd->adapter_first);
-		return 0;
-	} else
-		return -2;
-}
-
-/* This is not a very smart implementation. We could optimize for 
-   consecutive block numbers. I'm not convinced this would really
-   bring down the processor load. */
-static void do_cm206_request(request_queue_t * q)
-{
-	long int i, cd_sec_no;
-	int quarter, error;
-	uch *source, *dest;
-	struct request *req;
-
-	while (1) {	/* repeat until all requests have been satisfied */
-		req = elv_next_request(q);
-		if (!req)
-			return;
-
-		if (req->cmd != READ) {
-			debug(("Non-read command %d on cdrom\n", req->cmd));
-			end_request(req, 0);
-			continue;
-		}
-		spin_unlock_irq(q->queue_lock);
-		error = 0;
-		for (i = 0; i < req->nr_sectors; i++) {
-			int e1, e2;
-			cd_sec_no = (req->sector + i) / BLOCKS_ISO;	/* 4 times 512 bytes */
-			quarter = (req->sector + i) % BLOCKS_ISO;
-			dest = req->buffer + i * LINUX_BLOCK_SIZE;
-			/* is already in buffer memory? */
-			if (cd->sector_first <= cd_sec_no
-			    && cd_sec_no < cd->sector_last) {
-				source =
-				    ((uch *) cd->sector) + 16 +
-				    quarter * LINUX_BLOCK_SIZE +
-				    (cd_sec_no -
-				     cd->sector_first) * RAW_SECTOR_SIZE;
-				memcpy(dest, source, LINUX_BLOCK_SIZE);
-			} else if (!(e1 = try_adapter(cd_sec_no)) ||
-				   !(e2 = read_sector(cd_sec_no))) {
-				source =
-				    ((uch *) cd->sector) + 16 +
-				    quarter * LINUX_BLOCK_SIZE;
-				memcpy(dest, source, LINUX_BLOCK_SIZE);
-			} else {
-				error = 1;
-				debug(("cm206_request: %d %d\n", e1, e2));
-			}
-		}
-		spin_lock_irq(q->queue_lock);
-		end_request(req, !error);
-	}
-}
-
-/* Audio support. I've tried very hard, but the cm206 drive doesn't 
-   seem to have a get_toc (table-of-contents) function, while i'm
-   pretty sure it must read the toc upon disc insertion. Therefore
-   this function has been implemented through a binary search 
-   strategy. All track starts that happen to be found are stored in
-   cd->toc[], for future use. 
-
-   I've spent a whole day on a bug that only shows under Workman---
-   I don't get it. Tried everything, nothing works. If workman asks
-   for track# 0xaa, it'll get the wrong time back. Any other program
-   receives the correct value. I'm stymied.
-*/
-
-/* seek seeks to address lba. It does wait to arrive there. */
-static void seek(int lba)
-{
-	int i;
-	uch seek_command[4] = { c_seek, };
-
-	fsm(lba, &seek_command[1]);
-	for (i = 0; i < 4; i++)
-		type_0_command(seek_command[i], 0);
-	cd->dsb = wait_dsb();
-}
-
-static uch bcdbin(unsigned char bcd)
-{				/* stolen from mcd.c! */
-	return (bcd >> 4) * 10 + (bcd & 0xf);
-}
-
-static inline uch normalize_track(uch track)
-{
-	if (track < 1)
-		return 1;
-	if (track > LAST_TRACK)
-		return LAST_TRACK + 1;
-	return track;
-}
-
-/* This function does a binary search for track start. It records all
- * tracks seen in the process. Input $track$ must be between 1 and
- * #-of-tracks+1.  Note that the start of the disc must be in toc[1].fsm. 
- */
-static int get_toc_lba(uch track)
-{
-	int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
-	int i, lba, l, old_lba = 0;
-	uch *q = cd->q;
-	uch ct;			/* current track */
-	int binary = 0;
-	const int skip = 3 * 60 * 75;	/* 3 minutes */
-
-	for (i = track; i > 0; i--)
-		if (cd->toc[i].track) {
-			min = fsm2lba(cd->toc[i].fsm);
-			break;
-		}
-	lba = min + skip;
-	do {
-		seek(lba);
-		type_1_command(c_read_current_q, 10, q);
-		ct = normalize_track(q[1]);
-		if (!cd->toc[ct].track) {
-			l = q[9] - bcdbin(q[5]) + 75 * (q[8] -
-							bcdbin(q[4]) - 2 +
-							60 * (q[7] -
-							      bcdbin(q
-								     [3])));
-			cd->toc[ct].track = q[1];	/* lead out still 0xaa */
-			fsm(l, cd->toc[ct].fsm);
-			cd->toc[ct].q0 = q[0];	/* contains adr and ctrl info */
-			if (ct == track)
-				return l;
-		}
-		old_lba = lba;
-		if (binary) {
-			if (ct < track)
-				min = lba;
-			else
-				max = lba;
-			lba = (min + max) / 2;
-		} else {
-			if (ct < track)
-				lba += skip;
-			else {
-				binary = 1;
-				max = lba;
-				min = lba - skip;
-				lba = (min + max) / 2;
-			}
-		}
-	} while (lba != old_lba);
-	return lba;
-}
-
-static void update_toc_entry(uch track)
-{
-	track = normalize_track(track);
-	if (!cd->toc[track].track)
-		get_toc_lba(track);
-}
-
-/* return 0 upon success */
-static int read_toc_header(struct cdrom_tochdr *hp)
-{
-	if (!FIRST_TRACK)
-		get_disc_status();
-	if (hp) {
-		int i;
-		hp->cdth_trk0 = FIRST_TRACK;
-		hp->cdth_trk1 = LAST_TRACK;
-		/* fill in first track position */
-		for (i = 0; i < 3; i++)
-			cd->toc[1].fsm[i] = cd->disc_status[3 + i];
-		update_toc_entry(LAST_TRACK + 1);	/* find most entries */
-		return 0;
-	}
-	return -1;
-}
-
-static void play_from_to_msf(struct cdrom_msf *msfp)
-{
-	uch play_command[] = { c_play,
-		msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
-		msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2,
-		    2
-	};
-	int i;
-	for (i = 0; i < 9; i++)
-		type_0_command(play_command[i], 0);
-	for (i = 0; i < 3; i++)
-		PLAY_TO.fsm[i] = play_command[i + 4];
-	PLAY_TO.track = 0;	/* say no track end */
-	cd->dsb = wait_dsb();
-}
-
-static void play_from_to_track(int from, int to)
-{
-	uch play_command[8] = { c_play, };
-	int i;
-
-	if (from == 0) {	/* continue paused play */
-		for (i = 0; i < 3; i++) {
-			play_command[i + 1] = cd->audio_status[i + 2];
-			play_command[i + 4] = PLAY_TO.fsm[i];
-		}
-	} else {
-		update_toc_entry(from);
-		update_toc_entry(to + 1);
-		for (i = 0; i < 3; i++) {
-			play_command[i + 1] = cd->toc[from].fsm[i];
-			PLAY_TO.fsm[i] = play_command[i + 4] =
-			    cd->toc[to + 1].fsm[i];
-		}
-		PLAY_TO.track = to;
-	}
-	for (i = 0; i < 7; i++)
-		type_0_command(play_command[i], 0);
-	for (i = 0; i < 2; i++)
-		type_0_command(0x2, 0);	/* volume */
-	cd->dsb = wait_dsb();
-}
-
-static int get_current_q(struct cdrom_subchnl *qp)
-{
-	int i;
-	uch *q = cd->q;
-	if (type_1_command(c_read_current_q, 10, q))
-		return 0;
-/*  q[0] = bcdbin(q[0]); Don't think so! */
-	for (i = 2; i < 6; i++)
-		q[i] = bcdbin(q[i]);
-	qp->cdsc_adr = q[0] & 0xf;
-	qp->cdsc_ctrl = q[0] >> 4;	/* from mcd.c */
-	qp->cdsc_trk = q[1];
-	qp->cdsc_ind = q[2];
-	if (qp->cdsc_format == CDROM_MSF) {
-		qp->cdsc_reladdr.msf.minute = q[3];
-		qp->cdsc_reladdr.msf.second = q[4];
-		qp->cdsc_reladdr.msf.frame = q[5];
-		qp->cdsc_absaddr.msf.minute = q[7];
-		qp->cdsc_absaddr.msf.second = q[8];
-		qp->cdsc_absaddr.msf.frame = q[9];
-	} else {
-		qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]);
-		qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]);
-	}
-	get_drive_status();
-	if (cd->dsb & dsb_play_in_progress)
-		qp->cdsc_audiostatus = CDROM_AUDIO_PLAY;
-	else if (PAUSED)
-		qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED;
-	else
-		qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
-	return 0;
-}
-
-static void invalidate_toc(void)
-{
-	memset(cd->toc, 0, sizeof(cd->toc));
-	memset(cd->disc_status, 0, sizeof(cd->disc_status));
-}
-
-/* cdrom.c guarantees that cdte_format == CDROM_MSF */
-static void get_toc_entry(struct cdrom_tocentry *ep)
-{
-	uch track = normalize_track(ep->cdte_track);
-	update_toc_entry(track);
-	ep->cdte_addr.msf.frame = cd->toc[track].fsm[0];
-	ep->cdte_addr.msf.second = cd->toc[track].fsm[1];
-	ep->cdte_addr.msf.minute = cd->toc[track].fsm[2];
-	ep->cdte_adr = cd->toc[track].q0 & 0xf;
-	ep->cdte_ctrl = cd->toc[track].q0 >> 4;
-	ep->cdte_datamode = 0;
-}
-
-/* Audio ioctl.  Ioctl commands connected to audio are in such an
- * idiosyncratic i/o format, that we leave these untouched. Return 0
- * upon success. Memory checking has been done by cdrom_ioctl(), the
- * calling function, as well as LBA/MSF sanitization.
-*/
-static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
-			     void *arg)
-{
-	switch (cmd) {
-	case CDROMREADTOCHDR:
-		return read_toc_header((struct cdrom_tochdr *) arg);
-	case CDROMREADTOCENTRY:
-		get_toc_entry((struct cdrom_tocentry *) arg);
-		return 0;
-	case CDROMPLAYMSF:
-		play_from_to_msf((struct cdrom_msf *) arg);
-		return 0;
-	case CDROMPLAYTRKIND:	/* admittedly, not particularly beautiful */
-		play_from_to_track(((struct cdrom_ti *) arg)->cdti_trk0,
-				   ((struct cdrom_ti *) arg)->cdti_trk1);
-		return 0;
-	case CDROMSTOP:
-		PAUSED = 0;
-		if (cd->dsb & dsb_play_in_progress)
-			return type_0_command(c_stop, 1);
-		else
-			return 0;
-	case CDROMPAUSE:
-		get_drive_status();
-		if (cd->dsb & dsb_play_in_progress) {
-			type_0_command(c_stop, 1);
-			type_1_command(c_audio_status, 5,
-				       cd->audio_status);
-			PAUSED = 1;	/* say we're paused */
-		}
-		return 0;
-	case CDROMRESUME:
-		if (PAUSED)
-			play_from_to_track(0, 0);
-		PAUSED = 0;
-		return 0;
-	case CDROMSTART:
-	case CDROMVOLCTRL:
-		return 0;
-	case CDROMSUBCHNL:
-		return get_current_q((struct cdrom_subchnl *) arg);
-	default:
-		return -EINVAL;
-	}
-}
-
-static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
-	if (cd != NULL) {
-		int r;
-		get_drive_status();	/* ensure cd->media_changed OK */
-		r = cd->media_changed;
-		cd->media_changed = 0;	/* clear bit */
-		return r;
-	} else
-		return -EIO;
-}
-
-/* The new generic cdrom support. Routines should be concise, most of
-   the logic should be in cdrom.c */
-
-
-/* controls tray movement */
-static int cm206_tray_move(struct cdrom_device_info *cdi, int position)
-{
-	if (position) {		/* 1: eject */
-		type_0_command(c_open_tray, 1);
-		invalidate_toc();
-	} else
-		type_0_command(c_close_tray, 1);	/* 0: close */
-	return 0;
-}
-
-/* gives current state of the drive */
-static int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
-	get_drive_status();
-	if (cd->dsb & dsb_tray_not_closed)
-		return CDS_TRAY_OPEN;
-	if (!(cd->dsb & dsb_disc_present))
-		return CDS_NO_DISC;
-	if (cd->dsb & dsb_drive_not_ready)
-		return CDS_DRIVE_NOT_READY;
-	return CDS_DISC_OK;
-}
-
-/* locks or unlocks door lock==1: lock; return 0 upon success */
-static int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
-{
-	uch command = (lock) ? c_lock_tray : c_unlock_tray;
-	type_0_command(command, 1);	/* wait and get dsb */
-	/* the logic calculates the success, 0 means successful */
-	return lock ^ ((cd->dsb & dsb_tray_locked) != 0);
-}
-
-/* Although a session start should be in LBA format, we return it in 
-   MSF format because it is slightly easier, and the new generic ioctl
-   will take care of the necessary conversion. */
-static int cm206_get_last_session(struct cdrom_device_info *cdi,
-				  struct cdrom_multisession *mssp)
-{
-	if (!FIRST_TRACK)
-		get_disc_status();
-	if (mssp != NULL) {
-		if (DISC_STATUS & cds_multi_session) {	/* multi-session */
-			mssp->addr.msf.frame = cd->disc_status[3];
-			mssp->addr.msf.second = cd->disc_status[4];
-			mssp->addr.msf.minute = cd->disc_status[5];
-			mssp->addr_format = CDROM_MSF;
-			mssp->xa_flag = 1;
-		} else {
-			mssp->xa_flag = 0;
-		}
-		return 1;
-	}
-	return 0;
-}
-
-static int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
-	uch upc[10];
-	char *ret = mcn->medium_catalog_number;
-	int i;
-
-	if (type_1_command(c_read_upc, 10, upc))
-		return -EIO;
-	for (i = 0; i < 13; i++) {
-		int w = i / 2 + 1, r = i % 2;
-		if (r)
-			ret[i] = 0x30 | (upc[w] & 0x0f);
-		else
-			ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f);
-	}
-	ret[13] = '\0';
-	return 0;
-}
-
-static int cm206_reset(struct cdrom_device_info *cdi)
-{
-	stop_read();
-	reset_cm260();
-	outw(dc_normal | dc_break | READ_AHEAD, r_data_control);
-	mdelay(1);		/* 750 musec minimum */
-	outw(dc_normal | READ_AHEAD, r_data_control);
-	cd->sector_last = -1;	/* flag no data buffered */
-	cd->adapter_last = -1;
-	invalidate_toc();
-	return 0;
-}
-
-static int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
-{
-	int r;
-	switch (speed) {
-	case 0:
-		r = type_0_command(c_auto_mode, 1);
-		break;
-	case 1:
-		r = type_0_command(c_force_1x, 1);
-		break;
-	case 2:
-		r = type_0_command(c_force_2x, 1);
-		break;
-	default:
-		return -1;
-	}
-	if (r < 0)
-		return r;
-	else
-		return 1;
-}
-
-static struct cdrom_device_ops cm206_dops = {
-	.open			= cm206_open,
-	.release		= cm206_release,
-	.drive_status		= cm206_drive_status,
-	.media_changed		= cm206_media_changed,
-	.tray_move		= cm206_tray_move,
-	.lock_door		= cm206_lock_door,
-	.select_speed		= cm206_select_speed,
-	.get_last_session	= cm206_get_last_session,
-	.get_mcn		= cm206_get_upc,
-	.reset			= cm206_reset,
-	.audio_ioctl		= cm206_audio_ioctl,
-	.capability		= CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
-				  CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
-				  CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
-				  CDC_DRIVE_STATUS,
-	.n_minors		= 1,
-};
-
-
-static struct cdrom_device_info cm206_info = {
-	.ops		= &cm206_dops,
-	.speed		= 2,
-	.capacity	= 1,
-	.name		= "cm206",
-};
-
-static int cm206_block_open(struct inode *inode, struct file *file)
-{
-	return cdrom_open(&cm206_info, inode, file);
-}
-
-static int cm206_block_release(struct inode *inode, struct file *file)
-{
-	return cdrom_release(&cm206_info, file);
-}
-
-static int cm206_block_ioctl(struct inode *inode, struct file *file,
-				unsigned cmd, unsigned long arg)
-{
-	switch (cmd) {
-#ifdef STATISTICS
-	case CM206CTL_GET_STAT:
-		if (arg >= NR_STATS)
-			return -EINVAL;
-		return cd->stats[arg];
-	case CM206CTL_GET_LAST_STAT:
-		if (arg >= NR_STATS)
-			return -EINVAL;
-		return cd->last_stat[arg];
-#endif
-	default:
-		break;
-	}
-
-	return cdrom_ioctl(file, &cm206_info, inode, cmd, arg);
-}
-
-static int cm206_block_media_changed(struct gendisk *disk)
-{
-	return cdrom_media_changed(&cm206_info);
-}
-
-static struct block_device_operations cm206_bdops =
-{
-	.owner		= THIS_MODULE,
-	.open		= cm206_block_open,
-	.release	= cm206_block_release,
-	.ioctl		= cm206_block_ioctl,
-	.media_changed	= cm206_block_media_changed,
-};
-
-static struct gendisk *cm206_gendisk;
-
-/* This function probes for the adapter card. It returns the base
-   address if it has found the adapter card. One can specify a base 
-   port to probe specifically, or 0 which means span all possible
-   bases. 
-
-   Linus says it is too dangerous to use writes for probing, so we
-   stick with pure reads for a while. Hope that 8 possible ranges,
-   request_region, 15 bits of one port and 6 of another make things
-   likely enough to accept the region on the first hit...
- */
-static int __init probe_base_port(int base)
-{
-	int b = 0x300, e = 0x370;	/* this is the range of start addresses */
-	volatile int fool, i;
-
-	if (base)
-		b = e = base;
-	for (base = b; base <= e; base += 0x10) {
-		if (!request_region(base, 0x10,"cm206"))
-			continue;
-		for (i = 0; i < 3; i++)
-			fool = inw(base + 2);	/* empty possibly uart_receive_buffer */
-		if ((inw(base + 6) & 0xffef) != 0x0001 ||	/* line_status */
-		    (inw(base) & 0xad00) != 0)	{ /* data status */
-		    	release_region(base,0x10);
-			continue;
-		}
-		return (base);
-	}
-	return 0;
-}
-
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
-/* Probe for irq# nr. If nr==0, probe for all possible irq's. */
-static int __init probe_irq(int nr)
-{
-	int irqs, irq;
-	outw(dc_normal | READ_AHEAD, r_data_control);	/* disable irq-generation */
-	sti();
-	irqs = probe_irq_on();
-	reset_cm260();		/* causes interrupt */
-	udelay(100);		/* wait for it */
-	irq = probe_irq_off(irqs);
-	outw(dc_normal | READ_AHEAD, r_data_control);	/* services interrupt */
-	if (nr && irq != nr && irq > 0)
-		return 0;	/* wrong interrupt happened */
-	else
-		return irq;
-}
-#endif
-
-int __init cm206_init(void)
-{
-	uch e = 0;
-	long int size = sizeof(struct cm206_struct);
-	struct gendisk *disk;
-
-	printk(KERN_INFO "cm206 cdrom driver " REVISION);
-	cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
-	if (!cm206_base) {
-		printk(" can't find adapter!\n");
-		return -EIO;
-	}
-	printk(" adapter at 0x%x", cm206_base);
-	cd = kmalloc(size, GFP_KERNEL);
-	if (!cd)
-               goto out_base;
-	/* Now we have found the adaptor card, try to reset it. As we have
-	 * found out earlier, this process generates an interrupt as well,
-	 * so we might just exploit that fact for irq probing! */
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
-	cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);
-	if (cm206_irq <= 0) {
-		printk("can't find IRQ!\n");
-		goto out_probe;
-	} else
-		printk(" IRQ %d found\n", cm206_irq);
-#else
-	cli();
-	reset_cm260();
-	/* Now, the problem here is that reset_cm260 can generate an
-	   interrupt. It seems that this can cause a kernel oops some time
-	   later. So we wait a while and `service' this interrupt. */
-	mdelay(1);
-	outw(dc_normal | READ_AHEAD, r_data_control);
-	sti();
-	printk(" using IRQ %d\n", cm206_irq);
-#endif
-	if (send_receive_polled(c_drive_configuration) !=
-	    c_drive_configuration) {
-		printk(KERN_INFO " drive not there\n");
-		goto out_probe;
-	}
-	e = send_receive_polled(c_gimme);
-	printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code);
-	if (e & dcf_transfer_rate)
-		printk(" double");
-	else
-		printk(" single");
-	printk(" speed drive");
-	if (e & dcf_motorized_tray)
-		printk(", motorized tray");
-	if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) {
-		printk("\nUnable to reserve IRQ---aborted\n");
-		goto out_probe;
-	}
-	printk(".\n");
-
-	if (register_blkdev(MAJOR_NR, "cm206"))
-		goto out_blkdev;
-
-	disk = alloc_disk(1);
-	if (!disk)
-		goto out_disk;
-	disk->major = MAJOR_NR;
-	disk->first_minor = 0;
-	sprintf(disk->disk_name, "cm206cd");
-	disk->fops = &cm206_bdops;
-	disk->flags = GENHD_FL_CD;
-	cm206_gendisk = disk;
-	if (register_cdrom(&cm206_info) != 0) {
-		printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
-		goto out_cdrom;
-	}
-	cm206_queue = blk_init_queue(do_cm206_request, &cm206_lock);
-	if (!cm206_queue)
-		goto out_queue;
-		
-	blk_queue_hardsect_size(cm206_queue, 2048);
-	disk->queue = cm206_queue;
-	add_disk(disk);
-
-	memset(cd, 0, sizeof(*cd));	/* give'm some reasonable value */
-	cd->sector_last = -1;	/* flag no data buffered */
-	cd->adapter_last = -1;
-	init_timer(&cd->timer);
-	cd->timer.function = cm206_timeout;
-	cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
-	printk(KERN_INFO "%d kB adapter memory available, "
-	       " %ld bytes kernel memory used.\n", cd->max_sectors * 2,
-	       size);
-	return 0;
-
-out_queue:
-	unregister_cdrom(&cm206_info);
-out_cdrom:
-	put_disk(disk);
-out_disk:
-	unregister_blkdev(MAJOR_NR, "cm206");
-out_blkdev:
-	free_irq(cm206_irq, NULL);
-out_probe:
-	kfree(cd);
-out_base:
-	release_region(cm206_base, 16);
-	return -EIO;
-}
-
-#ifdef MODULE
-
-
-static void __init parse_options(void)
-{
-	int i;
-	for (i = 0; i < 2; i++) {
-		if (0x300 <= cm206[i] && i <= 0x370
-		    && cm206[i] % 0x10 == 0) {
-			cm206_base = cm206[i];
-			auto_probe = 0;
-		} else if (3 <= cm206[i] && cm206[i] <= 15) {
-			cm206_irq = cm206[i];
-			auto_probe = 0;
-		}
-	}
-}
-
-static int __init __cm206_init(void)
-{
-	parse_options();
-#if !defined(AUTO_PROBE_MODULE)
-	auto_probe = 0;
-#endif
-	return cm206_init();
-}
-
-static void __exit cm206_exit(void)
-{
-	del_gendisk(cm206_gendisk);
-	put_disk(cm206_gendisk);
-	if (unregister_cdrom(&cm206_info)) {
-		printk("Can't unregister cdrom cm206\n");
-		return;
-	}
-	if (unregister_blkdev(MAJOR_NR, "cm206")) {
-		printk("Can't unregister major cm206\n");
-		return;
-	}
-	blk_cleanup_queue(cm206_queue);
-	free_irq(cm206_irq, NULL);
-	kfree(cd);
-	release_region(cm206_base, 16);
-	printk(KERN_INFO "cm206 removed\n");
-}
-
-module_init(__cm206_init);
-module_exit(cm206_exit);
-
-#else				/* !MODULE */
-
-/* This setup function accepts either `auto' or numbers in the range
- * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
-
-static int __init cm206_setup(char *s)
-{
-	int i, p[4];
-
-	(void) get_options(s, ARRAY_SIZE(p), p);
-
-	if (!strcmp(s, "auto"))
-		auto_probe = 1;
-	for (i = 1; i <= p[0]; i++) {
-		if (0x300 <= p[i] && i <= 0x370 && p[i] % 0x10 == 0) {
-			cm206_base = p[i];
-			auto_probe = 0;
-		} else if (3 <= p[i] && p[i] <= 15) {
-			cm206_irq = p[i];
-			auto_probe = 0;
-		}
-	}
-	return 1;
-}
-
-__setup("cm206=", cm206_setup);
-
-#endif				/* !MODULE */
-MODULE_ALIAS_BLOCKDEV_MAJOR(CM206_CDROM_MAJOR);
-
diff --git a/drivers/cdrom/cm206.h b/drivers/cdrom/cm206.h
deleted file mode 100644
index 0ae51c1..0000000
--- a/drivers/cdrom/cm206.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* cm206.h Header file for cm206.c.
-   Copyright (c) 1995 David van Leeuwen 
-*/
-
-#ifndef LINUX_CM206_H
-#define LINUX_CM206_H
-
-#include <linux/ioctl.h>
-
-/* First, the cm260 stuff */
-/* The ports and irq used. Although CM206_BASE and CM206_IRQ are defined
-   below, the values are not used unless autoprobing is turned off and 
-   no LILO boot options or module command line options are given. Change
-   these values to your own as last resort if autoprobing and options
-   don't work. */
-
-#define CM206_BASE 0x340
-#define CM206_IRQ 11
-
-#define r_data_status (cm206_base)
-#define r_uart_receive (cm206_base+0x2)
-#define r_fifo_output_buffer (cm206_base+0x4)
-#define r_line_status (cm206_base+0x6)
-#define r_data_control (cm206_base+0x8)
-#define r_uart_transmit (cm206_base+0xa)
-#define r_test_clock (cm206_base+0xc)
-#define r_test_control (cm206_base+0xe)
-
-/* the data_status flags */
-#define ds_ram_size 0x4000
-#define ds_toc_ready 0x2000
-#define ds_fifo_empty 0x1000
-#define ds_sync_error 0x800
-#define ds_crc_error 0x400
-#define ds_data_error 0x200
-#define ds_fifo_overflow 0x100
-#define ds_data_ready 0x80
-
-/* the line_status flags */
-#define ls_attention 0x10
-#define ls_parity_error 0x8
-#define ls_overrun 0x4
-#define ls_receive_buffer_full 0x2
-#define ls_transmitter_buffer_empty 0x1
-
-/* the data control register flags */
-#define dc_read_q_channel 0x4000
-#define dc_mask_sync_error 0x2000
-#define dc_toc_enable 0x1000
-#define dc_no_stop_on_error 0x800
-#define dc_break 0x400
-#define dc_initialize 0x200
-#define dc_mask_transmit_ready 0x100
-#define dc_flag_enable 0x80
-
-/* Define the default data control register flags here */
-#define dc_normal (dc_mask_sync_error | dc_no_stop_on_error | \
-		   dc_mask_transmit_ready)
-
-/* now some constants related to the cm206 */
-/* another drive status byte, echoed by the cm206 on most commands */
-
-#define dsb_error_condition 0x1
-#define dsb_play_in_progress 0x4
-#define dsb_possible_media_change 0x8
-#define dsb_disc_present 0x10
-#define dsb_drive_not_ready 0x20
-#define dsb_tray_locked 0x40
-#define dsb_tray_not_closed 0x80
-
-#define dsb_not_useful (dsb_drive_not_ready | dsb_tray_not_closed)
-
-/* the cm206 command set */
-
-#define c_close_tray 0
-#define c_lock_tray 0x01
-#define c_unlock_tray 0x04
-#define c_open_tray 0x05
-#define c_seek 0x10
-#define c_read_data 0x20
-#define c_force_1x 0x21
-#define c_force_2x 0x22
-#define c_auto_mode 0x23
-#define c_play 0x30
-#define c_set_audio_mode 0x31
-#define c_read_current_q 0x41
-#define c_stream_q 0x42
-#define c_drive_status 0x50
-#define c_disc_status 0x51
-#define c_audio_status 0x52
-#define c_drive_configuration 0x53
-#define c_read_upc 0x60
-#define c_stop 0x70
-#define c_calc_checksum 0xe5
-
-#define c_gimme 0xf8
-
-/* finally, the (error) condition that the drive can be in      *
- * OK, this is not always an error, but let's prefix it with e_ */
-
-#define e_none 0
-#define e_illegal_command 0x01
-#define e_sync 0x02
-#define e_seek 0x03
-#define e_parity 0x04
-#define e_focus 0x05
-#define e_header_sync 0x06
-#define e_code_incompatibility 0x07
-#define e_reset_done 0x08
-#define e_bad_parameter 0x09
-#define e_radial 0x0a
-#define e_sub_code 0x0b
-#define e_no_data_track 0x0c
-#define e_scan 0x0d
-#define e_tray_open 0x0f
-#define e_no_disc 0x10
-#define e_tray stalled 0x11
-
-/* drive configuration masks */
-
-#define dcf_revision_code 0x7
-#define dcf_transfer_rate 0x60
-#define dcf_motorized_tray 0x80
-
-/* disc status byte */
-
-#define cds_multi_session 0x2
-#define cds_all_audio 0x8
-#define cds_xa_mode 0xf0
-
-/* finally some ioctls for the driver */
-
-#define CM206CTL_GET_STAT _IO( 0x20, 0 )
-#define CM206CTL_GET_LAST_STAT _IO( 0x20, 1 )
-
-#ifdef STATISTICS
-
-/* This is an ugly way to guarantee that the names of the statistics
- * are the same in the code and in the diagnostics program.  */
-
-#ifdef __KERNEL__
-#define x(a) st_ ## a
-#define y enum
-#else
-#define x(a) #a
-#define y char * stats_name[] = 
-#endif
-
-y {x(interrupt), x(data_ready), x(fifo_overflow), x(data_error),
-     x(crc_error), x(sync_error), x(lost_intr), x(echo),
-     x(write_timeout), x(receive_timeout), x(read_timeout),
-     x(dsb_timeout), x(stop_0xff), x(back_read_timeout),
-     x(sector_transferred), x(read_restarted), x(read_background),
-     x(bh), x(open), x(ioctl_multisession), x(attention)
-#ifdef __KERNEL__
-     , x(last_entry)
-#endif
- };
-
-#ifdef __KERNEL__
-#define NR_STATS st_last_entry
-#else
-#define NR_STATS (sizeof(stats_name)/sizeof(char*))
-#endif
-
-#undef y
-#undef x
-
-#endif /* STATISTICS */
-
-#endif /* LINUX_CM206_H */
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
deleted file mode 100644
index b3ab6e9..0000000
--- a/drivers/cdrom/gscd.c
+++ /dev/null
@@ -1,1029 +0,0 @@
-#define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"
-
-/*
-	linux/drivers/block/gscd.c - GoldStar R420 CDROM driver
-
-        Copyright (C) 1995  Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
-        based upon pre-works by   Eberhard Moenkeberg <emoenke@gwdg.de>
-        
-
-        For all kind of other information about the GoldStar CDROM
-        and this Linux device driver I installed a WWW-URL:
-        http://linux.rz.fh-hannover.de/~raupach        
-
-
-             If you are the editor of a Linux CD, you should
-             enable gscd.c within your boot floppy kernel and
-             send me one of your CDs for free.
-
-
-        --------------------------------------------------------------------
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2, or (at your option)
-	any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-	
-	--------------------------------------------------------------------
-	
-	9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
-	                   Removed init_module & cleanup_module in favor of 
-		   	   module_init & module_exit.
-			   Torben Mathiasen <tmm@image.dk>
-
-*/
-
-/* These settings are for various debug-level. Leave they untouched ... */
-#define  NO_GSCD_DEBUG
-#define  NO_IOCTL_DEBUG
-#define  NO_MODULE_DEBUG
-#define  NO_FUTURE_WORK
-/*------------------------*/
-
-#include <linux/module.h>
-
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#define MAJOR_NR GOLDSTAR_CDROM_MAJOR
-#include <linux/blkdev.h>
-#include "gscd.h"
-
-static int gscdPresent = 0;
-
-static unsigned char gscd_buf[2048];	/* buffer for block size conversion */
-static int gscd_bn = -1;
-static short gscd_port = GSCD_BASE_ADDR;
-module_param_named(gscd, gscd_port, short, 0);
-
-/* Kommt spaeter vielleicht noch mal dran ...
- *    static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
- */
-
-static void gscd_read_cmd(struct request *req);
-static void gscd_hsg2msf(long hsg, struct msf *msf);
-static void gscd_bin2bcd(unsigned char *p);
-
-/* Schnittstellen zum Kern/FS */
-
-static void __do_gscd_request(unsigned long dummy);
-static int gscd_ioctl(struct inode *, struct file *, unsigned int,
-		      unsigned long);
-static int gscd_open(struct inode *, struct file *);
-static int gscd_release(struct inode *, struct file *);
-static int check_gscd_med_chg(struct gendisk *disk);
-
-/*      GoldStar Funktionen    */
-
-static void cmd_out(int, char *, char *, int);
-static void cmd_status(void);
-static void init_cd_drive(int);
-
-static int get_status(void);
-static void clear_Audio(void);
-static void cc_invalidate(void);
-
-/* some things for the next version */
-#ifdef FUTURE_WORK
-static void update_state(void);
-static long gscd_msf2hsg(struct msf *mp);
-static int gscd_bcd2bin(unsigned char bcd);
-#endif
-
-
-/*      lo-level cmd-Funktionen    */
-
-static void cmd_info_in(char *, int);
-static void cmd_end(void);
-static void cmd_read_b(char *, int, int);
-static void cmd_read_w(char *, int, int);
-static int cmd_unit_alive(void);
-static void cmd_write_cmd(char *);
-
-
-/*      GoldStar Variablen     */
-
-static int curr_drv_state;
-static int drv_states[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-static int drv_mode;
-static int disk_state;
-static int speed;
-static int ndrives;
-
-static unsigned char drv_num_read;
-static unsigned char f_dsk_valid;
-static unsigned char current_drive;
-static unsigned char f_drv_ok;
-
-
-static char f_AudioPlay;
-static char f_AudioPause;
-static int AudioStart_m;
-static int AudioStart_f;
-static int AudioEnd_m;
-static int AudioEnd_f;
-
-static DEFINE_TIMER(gscd_timer, NULL, 0, 0);
-static DEFINE_SPINLOCK(gscd_lock);
-static struct request_queue *gscd_queue;
-
-static struct block_device_operations gscd_fops = {
-	.owner		= THIS_MODULE,
-	.open		= gscd_open,
-	.release	= gscd_release,
-	.ioctl		= gscd_ioctl,
-	.media_changed	= check_gscd_med_chg,
-};
-
-/* 
- * Checking if the media has been changed
- * (not yet implemented)
- */
-static int check_gscd_med_chg(struct gendisk *disk)
-{
-#ifdef GSCD_DEBUG
-	printk("gscd: check_med_change\n");
-#endif
-	return 0;
-}
-
-
-#ifndef MODULE
-/* Using new interface for kernel-parameters */
-
-static int __init gscd_setup(char *str)
-{
-	int ints[2];
-	(void) get_options(str, ARRAY_SIZE(ints), ints);
-
-	if (ints[0] > 0) {
-		gscd_port = ints[1];
-	}
-	return 1;
-}
-
-__setup("gscd=", gscd_setup);
-
-#endif
-
-static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
-		      unsigned long arg)
-{
-	unsigned char to_do[10];
-	unsigned char dummy;
-
-
-	switch (cmd) {
-	case CDROMSTART:	/* Spin up the drive */
-		/* Don't think we can do this.  Even if we could,
-		 * I think the drive times out and stops after a while
-		 * anyway.  For now, ignore it.
-		 */
-		return 0;
-
-	case CDROMRESUME:	/* keine Ahnung was das ist */
-		return 0;
-
-
-	case CDROMEJECT:
-		cmd_status();
-		to_do[0] = CMD_TRAY_CTL;
-		cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
-		return 0;
-
-	default:
-		return -EINVAL;
-	}
-
-}
-
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static void gscd_transfer(struct request *req)
-{
-	while (req->nr_sectors > 0 && gscd_bn == req->sector / 4) {
-		long offs = (req->sector & 3) * 512;
-		memcpy(req->buffer, gscd_buf + offs, 512);
-		req->nr_sectors--;
-		req->sector++;
-		req->buffer += 512;
-	}
-}
-
-
-/*
- * I/O request routine called from Linux kernel.
- */
-
-static void do_gscd_request(request_queue_t * q)
-{
-	__do_gscd_request(0);
-}
-
-static void __do_gscd_request(unsigned long dummy)
-{
-	struct request *req;
-	unsigned int block;
-	unsigned int nsect;
-
-repeat:
-	req = elv_next_request(gscd_queue);
-	if (!req)
-		return;
-
-	block = req->sector;
-	nsect = req->nr_sectors;
-
-	if (req->sector == -1)
-		goto out;
-
-	if (req->cmd != READ) {
-		printk("GSCD: bad cmd %u\n", rq_data_dir(req));
-		end_request(req, 0);
-		goto repeat;
-	}
-
-	gscd_transfer(req);
-
-	/* if we satisfied the request from the buffer, we're done. */
-
-	if (req->nr_sectors == 0) {
-		end_request(req, 1);
-		goto repeat;
-	}
-#ifdef GSCD_DEBUG
-	printk("GSCD: block %d, nsect %d\n", block, nsect);
-#endif
-	gscd_read_cmd(req);
-out:
-	return;
-}
-
-
-
-/*
- * Check the result of the set-mode command.  On success, send the
- * read-data command.
- */
-
-static void gscd_read_cmd(struct request *req)
-{
-	long block;
-	struct gscd_Play_msf gscdcmd;
-	char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 };	/* cmd mode M-S-F secth sectl */
-
-	cmd_status();
-	if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) {
-		printk("GSCD: no disk or door open\n");
-		end_request(req, 0);
-	} else {
-		if (disk_state & ST_INVALID) {
-			printk("GSCD: disk invalid\n");
-			end_request(req, 0);
-		} else {
-			gscd_bn = -1;	/* purge our buffer */
-			block = req->sector / 4;
-			gscd_hsg2msf(block, &gscdcmd.start);	/* cvt to msf format */
-
-			cmd[2] = gscdcmd.start.min;
-			cmd[3] = gscdcmd.start.sec;
-			cmd[4] = gscdcmd.start.frame;
-
-#ifdef GSCD_DEBUG
-			printk("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3],
-			       cmd[4]);
-#endif
-			cmd_out(TYPE_DATA, (char *) &cmd,
-				(char *) &gscd_buf[0], 1);
-
-			gscd_bn = req->sector / 4;
-			gscd_transfer(req);
-			end_request(req, 1);
-		}
-	}
-	SET_TIMER(__do_gscd_request, 1);
-}
-
-
-/*
- * Open the device special file.  Check that a disk is in.
- */
-
-static int gscd_open(struct inode *ip, struct file *fp)
-{
-	int st;
-
-#ifdef GSCD_DEBUG
-	printk("GSCD: open\n");
-#endif
-
-	if (gscdPresent == 0)
-		return -ENXIO;	/* no hardware */
-
-	get_status();
-	st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);
-	if (st) {
-		printk("GSCD: no disk or door open\n");
-		return -ENXIO;
-	}
-
-/*	if (updateToc() < 0)
-		return -EIO;
-*/
-
-	return 0;
-}
-
-
-/*
- * On close, we flush all gscd blocks from the buffer cache.
- */
-
-static int gscd_release(struct inode *inode, struct file *file)
-{
-
-#ifdef GSCD_DEBUG
-	printk("GSCD: release\n");
-#endif
-
-	gscd_bn = -1;
-
-	return 0;
-}
-
-
-static int get_status(void)
-{
-	int status;
-
-	cmd_status();
-	status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);
-
-	if (status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) {
-		cc_invalidate();
-		return 1;
-	} else {
-		return 0;
-	}
-}
-
-
-static void cc_invalidate(void)
-{
-	drv_num_read = 0xFF;
-	f_dsk_valid = 0xFF;
-	current_drive = 0xFF;
-	f_drv_ok = 0xFF;
-
-	clear_Audio();
-
-}
-
-static void clear_Audio(void)
-{
-
-	f_AudioPlay = 0;
-	f_AudioPause = 0;
-	AudioStart_m = 0;
-	AudioStart_f = 0;
-	AudioEnd_m = 0;
-	AudioEnd_f = 0;
-
-}
-
-/*
- *   waiting ?  
- */
-
-static int wait_drv_ready(void)
-{
-	int found, read;
-
-	do {
-		found = inb(GSCDPORT(0));
-		found &= 0x0f;
-		read = inb(GSCDPORT(0));
-		read &= 0x0f;
-	} while (read != found);
-
-#ifdef GSCD_DEBUG
-	printk("Wait for: %d\n", read);
-#endif
-
-	return read;
-}
-
-static void cc_Ident(char *respons)
-{
-	char to_do[] = { CMD_IDENT, 0, 0 };
-
-	cmd_out(TYPE_INFO, (char *) &to_do, (char *) respons, (int) 0x1E);
-
-}
-
-static void cc_SetSpeed(void)
-{
-	char to_do[] = { CMD_SETSPEED, 0, 0 };
-	char dummy;
-
-	if (speed > 0) {
-		to_do[1] = speed & 0x0F;
-		cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-	}
-}
-
-static void cc_Reset(void)
-{
-	char to_do[] = { CMD_RESET, 0 };
-	char dummy;
-
-	cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-}
-
-static void cmd_status(void)
-{
-	char to_do[] = { CMD_STATUS, 0 };
-	char dummy;
-
-	cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
-#ifdef GSCD_DEBUG
-	printk("GSCD: Status: %d\n", disk_state);
-#endif
-
-}
-
-static void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count)
-{
-	int result;
-
-
-	result = wait_drv_ready();
-	if (result != drv_mode) {
-		unsigned long test_loops = 0xFFFF;
-		int i, dummy;
-
-		outb(curr_drv_state, GSCDPORT(0));
-
-		/* LOCLOOP_170 */
-		do {
-			result = wait_drv_ready();
-			test_loops--;
-		} while ((result != drv_mode) && (test_loops > 0));
-
-		if (result != drv_mode) {
-			disk_state = ST_x08 | ST_x04 | ST_INVALID;
-			return;
-		}
-
-		/* ...and waiting */
-		for (i = 1, dummy = 1; i < 0xFFFF; i++) {
-			dummy *= i;
-		}
-	}
-
-	/* LOC_172 */
-	/* check the unit */
-	/* and wake it up */
-	if (cmd_unit_alive() != 0x08) {
-		/* LOC_174 */
-		/* game over for this unit */
-		disk_state = ST_x08 | ST_x04 | ST_INVALID;
-		return;
-	}
-
-	/* LOC_176 */
-#ifdef GSCD_DEBUG
-	printk("LOC_176 ");
-#endif
-	if (drv_mode == 0x09) {
-		/* magic... */
-		printk("GSCD: magic ...\n");
-		outb(result, GSCDPORT(2));
-	}
-
-	/* write the command to the drive */
-	cmd_write_cmd(cmd);
-
-	/* LOC_178 */
-	for (;;) {
-		result = wait_drv_ready();
-		if (result != drv_mode) {
-			/* LOC_179 */
-			if (result == 0x04) {	/* Mode 4 */
-				/* LOC_205 */
-#ifdef GSCD_DEBUG
-				printk("LOC_205 ");
-#endif
-				disk_state = inb(GSCDPORT(2));
-
-				do {
-					result = wait_drv_ready();
-				} while (result != drv_mode);
-				return;
-
-			} else {
-				if (result == 0x06) {	/* Mode 6 */
-					/* LOC_181 */
-#ifdef GSCD_DEBUG
-					printk("LOC_181 ");
-#endif
-
-					if (cmd_type == TYPE_DATA) {
-						/* read data */
-						/* LOC_184 */
-						if (drv_mode == 9) {
-							/* read the data to the buffer (word) */
-
-							/* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */
-							cmd_read_w
-							    (respo_buf,
-							     respo_count,
-							     CD_FRAMESIZE /
-							     2);
-							return;
-						} else {
-							/* read the data to the buffer (byte) */
-
-							/* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW)    */
-							cmd_read_b
-							    (respo_buf,
-							     respo_count,
-							     CD_FRAMESIZE);
-							return;
-						}
-					} else {
-						/* read the info to the buffer */
-						cmd_info_in(respo_buf,
-							    respo_count);
-						return;
-					}
-
-					return;
-				}
-			}
-
-		} else {
-			disk_state = ST_x08 | ST_x04 | ST_INVALID;
-			return;
-		}
-	}			/* for (;;) */
-
-
-#ifdef GSCD_DEBUG
-	printk("\n");
-#endif
-}
-
-
-static void cmd_write_cmd(char *pstr)
-{
-	int i, j;
-
-	/* LOC_177 */
-#ifdef GSCD_DEBUG
-	printk("LOC_177 ");
-#endif
-
-	/* calculate the number of parameter */
-	j = *pstr & 0x0F;
-
-	/* shift it out */
-	for (i = 0; i < j; i++) {
-		outb(*pstr, GSCDPORT(2));
-		pstr++;
-	}
-}
-
-
-static int cmd_unit_alive(void)
-{
-	int result;
-	unsigned long max_test_loops;
-
-
-	/* LOC_172 */
-#ifdef GSCD_DEBUG
-	printk("LOC_172 ");
-#endif
-
-	outb(curr_drv_state, GSCDPORT(0));
-	max_test_loops = 0xFFFF;
-
-	do {
-		result = wait_drv_ready();
-		max_test_loops--;
-	} while ((result != 0x08) && (max_test_loops > 0));
-
-	return result;
-}
-
-
-static void cmd_info_in(char *pb, int count)
-{
-	int result;
-	char read;
-
-
-	/* read info */
-	/* LOC_182 */
-#ifdef GSCD_DEBUG
-	printk("LOC_182 ");
-#endif
-
-	do {
-		read = inb(GSCDPORT(2));
-		if (count > 0) {
-			*pb = read;
-			pb++;
-			count--;
-		}
-
-		/* LOC_183 */
-		do {
-			result = wait_drv_ready();
-		} while (result == 0x0E);
-	} while (result == 6);
-
-	cmd_end();
-	return;
-}
-
-
-static void cmd_read_b(char *pb, int count, int size)
-{
-	int result;
-	int i;
-
-
-	/* LOC_188 */
-	/* LOC_189 */
-#ifdef GSCD_DEBUG
-	printk("LOC_189 ");
-#endif
-
-	do {
-		do {
-			result = wait_drv_ready();
-		} while (result != 6 || result == 0x0E);
-
-		if (result != 6) {
-			cmd_end();
-			return;
-		}
-#ifdef GSCD_DEBUG
-		printk("LOC_191 ");
-#endif
-
-		for (i = 0; i < size; i++) {
-			*pb = inb(GSCDPORT(2));
-			pb++;
-		}
-		count--;
-	} while (count > 0);
-
-	cmd_end();
-	return;
-}
-
-
-static void cmd_end(void)
-{
-	int result;
-
-
-	/* LOC_204 */
-#ifdef GSCD_DEBUG
-	printk("LOC_204 ");
-#endif
-
-	do {
-		result = wait_drv_ready();
-		if (result == drv_mode) {
-			return;
-		}
-	} while (result != 4);
-
-	/* LOC_205 */
-#ifdef GSCD_DEBUG
-	printk("LOC_205 ");
-#endif
-
-	disk_state = inb(GSCDPORT(2));
-
-	do {
-		result = wait_drv_ready();
-	} while (result != drv_mode);
-	return;
-
-}
-
-
-static void cmd_read_w(char *pb, int count, int size)
-{
-	int result;
-	int i;
-
-
-#ifdef GSCD_DEBUG
-	printk("LOC_185 ");
-#endif
-
-	do {
-		/* LOC_185 */
-		do {
-			result = wait_drv_ready();
-		} while (result != 6 || result == 0x0E);
-
-		if (result != 6) {
-			cmd_end();
-			return;
-		}
-
-		for (i = 0; i < size; i++) {
-			/* na, hier muss ich noch mal drueber nachdenken */
-			*pb = inw(GSCDPORT(2));
-			pb++;
-		}
-		count--;
-	} while (count > 0);
-
-	cmd_end();
-	return;
-}
-
-static int __init find_drives(void)
-{
-	int *pdrv;
-	int drvnum;
-	int subdrv;
-	int i;
-
-	speed = 0;
-	pdrv = (int *) &drv_states;
-	curr_drv_state = 0xFE;
-	subdrv = 0;
-	drvnum = 0;
-
-	for (i = 0; i < 8; i++) {
-		subdrv++;
-		cmd_status();
-		disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
-		if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) {
-			/* LOC_240 */
-			*pdrv = curr_drv_state;
-			init_cd_drive(drvnum);
-			pdrv++;
-			drvnum++;
-		} else {
-			if (subdrv < 2) {
-				continue;
-			} else {
-				subdrv = 0;
-			}
-		}
-
-/*       curr_drv_state<<1;         <-- das geht irgendwie nicht */
-/* muss heissen:    curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */
-		curr_drv_state *= 2;
-		curr_drv_state |= 1;
-#ifdef GSCD_DEBUG
-		printk("DriveState: %d\n", curr_drv_state);
-#endif
-	}
-
-	ndrives = drvnum;
-	return drvnum;
-}
-
-static void __init init_cd_drive(int num)
-{
-	char resp[50];
-	int i;
-
-	printk("GSCD: init unit %d\n", num);
-	cc_Ident((char *) &resp);
-
-	printk("GSCD: identification: ");
-	for (i = 0; i < 0x1E; i++) {
-		printk("%c", resp[i]);
-	}
-	printk("\n");
-
-	cc_SetSpeed();
-
-}
-
-#ifdef FUTURE_WORK
-/* return_done */
-static void update_state(void)
-{
-	unsigned int AX;
-
-
-	if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) {
-		if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) {
-			AX = ST_INVALID;
-		}
-
-		if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01))
-		    == 0) {
-			invalidate();
-			f_drv_ok = 0;
-		}
-
-		AX |= 0x8000;
-	}
-
-	if (disk_state & ST_PLAYING) {
-		AX |= 0x200;
-	}
-
-	AX |= 0x100;
-	/* pkt_esbx = AX; */
-
-	disk_state = 0;
-
-}
-#endif
-
-static struct gendisk *gscd_disk;
-
-static void __exit gscd_exit(void)
-{
-	CLEAR_TIMER;
-
-	del_gendisk(gscd_disk);
-	put_disk(gscd_disk);
-	if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
-		printk("What's that: can't unregister GoldStar-module\n");
-		return;
-	}
-	blk_cleanup_queue(gscd_queue);
-	release_region(gscd_port, GSCD_IO_EXTENT);
-	printk(KERN_INFO "GoldStar-module released.\n");
-}
-
-/* This is the common initialisation for the GoldStar drive. */
-/* It is called at boot time AND for module init.           */
-static int __init gscd_init(void)
-{
-	int i;
-	int result;
-	int ret=0;
-
-	printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION);
-	printk(KERN_INFO
-	       "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n",
-	       gscd_port);
-
-	if (!request_region(gscd_port, GSCD_IO_EXTENT, "gscd")) {
-		printk(KERN_WARNING "GSCD: Init failed, I/O port (%X) already"
-		       " in use.\n", gscd_port);
-		return -EIO;
-	}
-
-
-	/* check for card */
-	result = wait_drv_ready();
-	if (result == 0x09) {
-		printk(KERN_WARNING "GSCD: DMA kann ich noch nicht!\n");
-		ret = -EIO;
-		goto err_out1;
-	}
-
-	if (result == 0x0b) {
-		drv_mode = result;
-		i = find_drives();
-		if (i == 0) {
-			printk(KERN_WARNING "GSCD: GoldStar CD-ROM Drive is"
-			       " not found.\n");
-			ret = -EIO;
-			goto err_out1;
-		}
-	}
-
-	if ((result != 0x0b) && (result != 0x09)) {
-		printk(KERN_WARNING "GSCD: GoldStar Interface Adapter does not "
-		       "exist or H/W error\n");
-		ret = -EIO;
-		goto err_out1;
-	}
-
-	/* reset all drives */
-	i = 0;
-	while (drv_states[i] != 0) {
-		curr_drv_state = drv_states[i];
-		printk(KERN_INFO "GSCD: Reset unit %d ... ", i);
-		cc_Reset();
-		printk("done\n");
-		i++;
-	}
-
-	gscd_disk = alloc_disk(1);
-	if (!gscd_disk)
-		goto err_out1;
-	gscd_disk->major = MAJOR_NR;
-	gscd_disk->first_minor = 0;
-	gscd_disk->fops = &gscd_fops;
-	sprintf(gscd_disk->disk_name, "gscd");
-
-	if (register_blkdev(MAJOR_NR, "gscd")) {
-		ret = -EIO;
-		goto err_out2;
-	}
-
-	gscd_queue = blk_init_queue(do_gscd_request, &gscd_lock);
-	if (!gscd_queue) {
-		ret = -ENOMEM;
-		goto err_out3;
-	}
-
-	disk_state = 0;
-	gscdPresent = 1;
-
-	gscd_disk->queue = gscd_queue;
-	add_disk(gscd_disk);
-
-	printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
-	return 0;
-
-err_out3:
-	unregister_blkdev(MAJOR_NR, "gscd");
-err_out2:
-	put_disk(gscd_disk);
-err_out1:
-	release_region(gscd_port, GSCD_IO_EXTENT);
-	return ret;
-}
-
-static void gscd_hsg2msf(long hsg, struct msf *msf)
-{
-	hsg += CD_MSF_OFFSET;
-	msf->min = hsg / (CD_FRAMES * CD_SECS);
-	hsg %= CD_FRAMES * CD_SECS;
-	msf->sec = hsg / CD_FRAMES;
-	msf->frame = hsg % CD_FRAMES;
-
-	gscd_bin2bcd(&msf->min);	/* convert to BCD */
-	gscd_bin2bcd(&msf->sec);
-	gscd_bin2bcd(&msf->frame);
-}
-
-
-static void gscd_bin2bcd(unsigned char *p)
-{
-	int u, t;
-
-	u = *p % 10;
-	t = *p / 10;
-	*p = u | (t << 4);
-}
-
-
-#ifdef FUTURE_WORK
-static long gscd_msf2hsg(struct msf *mp)
-{
-	return gscd_bcd2bin(mp->frame)
-	    + gscd_bcd2bin(mp->sec) * CD_FRAMES
-	    + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET;
-}
-
-static int gscd_bcd2bin(unsigned char bcd)
-{
-	return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-#endif
-
-MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>");
-MODULE_LICENSE("GPL");
-module_init(gscd_init);
-module_exit(gscd_exit);
-MODULE_ALIAS_BLOCKDEV_MAJOR(GOLDSTAR_CDROM_MAJOR);
diff --git a/drivers/cdrom/gscd.h b/drivers/cdrom/gscd.h
deleted file mode 100644
index a41e64b..0000000
--- a/drivers/cdrom/gscd.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Definitions for a GoldStar R420 CD-ROM interface
- *
- *   Copyright (C) 1995  Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
- *                       Eberhard Moenkeberg <emoenke@gwdg.de>
- *
- *  Published under the GPL.
- *
- */
-
-
-/* The Interface Card default address is 0x340. This will work for most
-   applications. Address selection is accomplished by jumpers PN801-1 to
-   PN801-4 on the GoldStar Interface Card.
-   Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360
-   0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0             */
-
-/* insert here the I/O port address and extent */
-#define GSCD_BASE_ADDR	        0x340
-#define GSCD_IO_EXTENT          4
-
-
-/************** nothing to set up below here *********************/
-
-/* port access macro */
-#define GSCDPORT(x)		(gscd_port + (x))
-
-/*
- * commands
- * the lower nibble holds the command length
- */
-#define CMD_STATUS     0x01
-#define CMD_READSUBQ   0x02 /* 1: ?, 2: UPC, 5: ? */
-#define CMD_SEEK       0x05 /* read_mode M-S-F */
-#define CMD_READ       0x07 /* read_mode M-S-F nsec_h nsec_l */
-#define CMD_RESET      0x11
-#define CMD_SETMODE    0x15
-#define CMD_PLAY       0x17 /* M-S-F M-S-F */
-#define CMD_LOCK_CTL   0x22 /* 0: unlock, 1: lock */
-#define CMD_IDENT      0x31
-#define CMD_SETSPEED   0x32 /* 0: auto */ /* ??? */
-#define CMD_GETMODE    0x41
-#define CMD_PAUSE      0x51
-#define CMD_READTOC    0x61
-#define CMD_DISKINFO   0x71
-#define CMD_TRAY_CTL   0x81
-
-/*
- * disk_state:
- */
-#define ST_PLAYING	0x80
-#define ST_UNLOCKED	0x40
-#define ST_NO_DISK	0x20
-#define ST_DOOR_OPEN	0x10
-#define ST_x08  0x08
-#define ST_x04	0x04
-#define ST_INVALID	0x02
-#define ST_x01	0x01
-
-/*
- * cmd_type:
- */
-#define TYPE_INFO	0x01
-#define TYPE_DATA	0x02
-
-/*
- * read_mode:
- */
-#define MOD_POLLED	0x80
-#define MOD_x08	0x08
-#define MOD_RAW	0x04
-
-#define READ_DATA(port, buf, nr) insb(port, buf, nr)
-
-#define SET_TIMER(func, jifs) \
-	((mod_timer(&gscd_timer, jiffies + jifs)), \
-	(gscd_timer.function = func))
-
-#define CLEAR_TIMER		del_timer_sync(&gscd_timer)
-
-#define MAX_TRACKS		104
-
-struct msf {
-	unsigned char	min;
-	unsigned char	sec;
-	unsigned char	frame;
-};
-
-struct gscd_Play_msf {
-	struct msf	start;
-	struct msf	end;
-};
-
-struct gscd_DiskInfo {
-	unsigned char	first;
-	unsigned char	last;
-	struct msf	diskLength;
-	struct msf	firstTrack;
-};
-
-struct gscd_Toc {
-	unsigned char	ctrl_addr;
-	unsigned char	track;
-	unsigned char	pointIndex;
-	struct msf	trackTime;
-	struct msf	diskTime;
-};
-
diff --git a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c
deleted file mode 100644
index db0fd9a..0000000
--- a/drivers/cdrom/isp16.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/* -- ISP16 cdrom detection and configuration
- *
- *    Copyright (c) 1995,1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
- *
- *    Version 0.6
- *
- *    History:
- *    0.5 First release.
- *        Was included in the sjcd and optcd cdrom drivers.
- *    0.6 First "stand-alone" version.
- *        Removed sound configuration.
- *        Added "module" support.
- *
- *      9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	                   Removed init_module & cleanup_module in favor of 
- *			   module_init & module_exit.
- *			   Torben Mathiasen <tmm@image.dk>
- *
- *     19 June 2004     -- check_region() converted to request_region()
- *                         and return statement cleanups.
- *                          - Jesper Juhl
- *
- *    Detect cdrom interface on ISP16 sound card.
- *    Configure cdrom interface.
- *
- *    Algorithm for the card with OPTi 82C928 taken
- *    from the CDSETUP.SYS driver for MSDOS,
- *    by OPTi Computers, version 2.03.
- *    Algorithm for the card with OPTi 82C929 as communicated
- *    to me by Vadim Model and Leo Spiekman.
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define ISP16_VERSION_MAJOR 0
-#define ISP16_VERSION_MINOR 6
-
-#include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include "isp16.h"
-
-static short isp16_detect(void);
-static short isp16_c928__detect(void);
-static short isp16_c929__detect(void);
-static short isp16_cdi_config(int base, u_char drive_type, int irq,
-			      int dma);
-static short isp16_type;	/* dependent on type of interface card */
-static u_char isp16_ctrl;
-static u_short isp16_enable_port;
-
-static int isp16_cdrom_base = ISP16_CDROM_IO_BASE;
-static int isp16_cdrom_irq = ISP16_CDROM_IRQ;
-static int isp16_cdrom_dma = ISP16_CDROM_DMA;
-static char *isp16_cdrom_type = ISP16_CDROM_TYPE;
-
-module_param(isp16_cdrom_base, int, 0);
-module_param(isp16_cdrom_irq, int, 0);
-module_param(isp16_cdrom_dma, int, 0);
-module_param(isp16_cdrom_type, charp, 0);
-
-#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
-#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
-
-#ifndef MODULE
-
-static int
-__init isp16_setup(char *str)
-{
-	int ints[4];
-
-	(void) get_options(str, ARRAY_SIZE(ints), ints);
-	if (ints[0] > 0)
-		isp16_cdrom_base = ints[1];
-	if (ints[0] > 1)
-		isp16_cdrom_irq = ints[2];
-	if (ints[0] > 2)
-		isp16_cdrom_dma = ints[3];
-	if (str)
-		isp16_cdrom_type = str;
-
-	return 1;
-}
-
-__setup("isp16=", isp16_setup);
-
-#endif				/* MODULE */
-
-/*
- *  ISP16 initialisation.
- *
- */
-static int __init isp16_init(void)
-{
-	u_char expected_drive;
-
-	printk(KERN_INFO
-	       "ISP16: configuration cdrom interface, version %d.%d.\n",
-	       ISP16_VERSION_MAJOR, ISP16_VERSION_MINOR);
-
-	if (!strcmp(isp16_cdrom_type, "noisp16")) {
-		printk("ISP16: no cdrom interface configured.\n");
-		return 0;
-	}
-
-	if (!request_region(ISP16_IO_BASE, ISP16_IO_SIZE, "isp16")) {
-		printk("ISP16: i/o ports already in use.\n");
-		goto out;
-	}
-
-	if ((isp16_type = isp16_detect()) < 0) {
-		printk("ISP16: no cdrom interface found.\n");
-		goto cleanup_out;
-	}
-
-	printk(KERN_INFO
-	       "ISP16: cdrom interface (with OPTi 82C92%d chip) detected.\n",
-	       (isp16_type == 2) ? 9 : 8);
-
-	if (!strcmp(isp16_cdrom_type, "Sanyo"))
-		expected_drive =
-		    (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0);
-	else if (!strcmp(isp16_cdrom_type, "Sony"))
-		expected_drive = ISP16_SONY;
-	else if (!strcmp(isp16_cdrom_type, "Panasonic"))
-		expected_drive =
-		    (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0);
-	else if (!strcmp(isp16_cdrom_type, "Mitsumi"))
-		expected_drive = ISP16_MITSUMI;
-	else {
-		printk("ISP16: %s not supported by cdrom interface.\n",
-		       isp16_cdrom_type);
-		goto cleanup_out;
-	}
-
-	if (isp16_cdi_config(isp16_cdrom_base, expected_drive,
-			     isp16_cdrom_irq, isp16_cdrom_dma) < 0) {
-		printk
-		    ("ISP16: cdrom interface has not been properly configured.\n");
-		goto cleanup_out;
-	}
-	printk(KERN_INFO
-	       "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d,"
-	       " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq,
-	       isp16_cdrom_dma, isp16_cdrom_type);
-	return 0;
-
-cleanup_out:
-	release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
-out:
-	return -EIO;
-}
-
-static short __init isp16_detect(void)
-{
-
-	if (isp16_c929__detect() >= 0)
-		return 2;
-	else
-		return (isp16_c928__detect());
-}
-
-static short __init isp16_c928__detect(void)
-{
-	u_char ctrl;
-	u_char enable_cdrom;
-	u_char io;
-	short i = -1;
-
-	isp16_ctrl = ISP16_C928__CTRL;
-	isp16_enable_port = ISP16_C928__ENABLE_PORT;
-
-	/* read' and write' are a special read and write, respectively */
-
-	/* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
-	ctrl = ISP16_IN(ISP16_CTRL_PORT) & 0xFC;
-	ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
-	/* read' 3,4 and 5-bit from the cdrom enable port */
-	enable_cdrom = ISP16_IN(ISP16_C928__ENABLE_PORT) & 0x38;
-
-	if (!(enable_cdrom & 0x20)) {	/* 5-bit not set */
-		/* read' last 2 bits of ISP16_IO_SET_PORT */
-		io = ISP16_IN(ISP16_IO_SET_PORT) & 0x03;
-		if (((io & 0x01) << 1) == (io & 0x02)) {	/* bits are the same */
-			if (io == 0) {	/* ...the same and 0 */
-				i = 0;
-				enable_cdrom |= 0x20;
-			} else {	/* ...the same and 1 *//* my card, first time 'round */
-				i = 1;
-				enable_cdrom |= 0x28;
-			}
-			ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom);
-		} else {	/* bits are not the same */
-			ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-			return i;	/* -> not detected: possibly incorrect conclusion */
-		}
-	} else if (enable_cdrom == 0x20)
-		i = 0;
-	else if (enable_cdrom == 0x28)	/* my card, already initialised */
-		i = 1;
-
-	ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
-	return i;
-}
-
-static short __init isp16_c929__detect(void)
-{
-	u_char ctrl;
-	u_char tmp;
-
-	isp16_ctrl = ISP16_C929__CTRL;
-	isp16_enable_port = ISP16_C929__ENABLE_PORT;
-
-	/* read' and write' are a special read and write, respectively */
-
-	/* read' ISP16_CTRL_PORT and save */
-	ctrl = ISP16_IN(ISP16_CTRL_PORT);
-
-	/* write' zero to the ctrl port and get response */
-	ISP16_OUT(ISP16_CTRL_PORT, 0);
-	tmp = ISP16_IN(ISP16_CTRL_PORT);
-
-	if (tmp != 2)		/* isp16 with 82C929 not detected */
-		return -1;
-
-	/* restore ctrl port value */
-	ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
-	return 2;
-}
-
-static short __init
-isp16_cdi_config(int base, u_char drive_type, int irq, int dma)
-{
-	u_char base_code;
-	u_char irq_code;
-	u_char dma_code;
-	u_char i;
-
-	if ((drive_type == ISP16_MITSUMI) && (dma != 0))
-		printk("ISP16: Mitsumi cdrom drive has no dma support.\n");
-
-	switch (base) {
-	case 0x340:
-		base_code = ISP16_BASE_340;
-		break;
-	case 0x330:
-		base_code = ISP16_BASE_330;
-		break;
-	case 0x360:
-		base_code = ISP16_BASE_360;
-		break;
-	case 0x320:
-		base_code = ISP16_BASE_320;
-		break;
-	default:
-		printk
-		    ("ISP16: base address 0x%03X not supported by cdrom interface.\n",
-		     base);
-		return -1;
-	}
-	switch (irq) {
-	case 0:
-		irq_code = ISP16_IRQ_X;
-		break;		/* disable irq */
-	case 5:
-		irq_code = ISP16_IRQ_5;
-		printk("ISP16: irq 5 shouldn't be used by cdrom interface,"
-		       " due to possible conflicts with the sound card.\n");
-		break;
-	case 7:
-		irq_code = ISP16_IRQ_7;
-		printk("ISP16: irq 7 shouldn't be used by cdrom interface,"
-		       " due to possible conflicts with the sound card.\n");
-		break;
-	case 3:
-		irq_code = ISP16_IRQ_3;
-		break;
-	case 9:
-		irq_code = ISP16_IRQ_9;
-		break;
-	case 10:
-		irq_code = ISP16_IRQ_10;
-		break;
-	case 11:
-		irq_code = ISP16_IRQ_11;
-		break;
-	default:
-		printk("ISP16: irq %d not supported by cdrom interface.\n",
-		       irq);
-		return -1;
-	}
-	switch (dma) {
-	case 0:
-		dma_code = ISP16_DMA_X;
-		break;		/* disable dma */
-	case 1:
-		printk("ISP16: dma 1 cannot be used by cdrom interface,"
-		       " due to conflict with the sound card.\n");
-		return -1;
-		break;
-	case 3:
-		dma_code = ISP16_DMA_3;
-		break;
-	case 5:
-		dma_code = ISP16_DMA_5;
-		break;
-	case 6:
-		dma_code = ISP16_DMA_6;
-		break;
-	case 7:
-		dma_code = ISP16_DMA_7;
-		break;
-	default:
-		printk("ISP16: dma %d not supported by cdrom interface.\n",
-		       dma);
-		return -1;
-	}
-
-	if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
-	    drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
-	    drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
-	    drive_type != ISP16_DRIVE_X) {
-		printk
-		    ("ISP16: drive type (code 0x%02X) not supported by cdrom"
-		     " interface.\n", drive_type);
-		return -1;
-	}
-
-	/* set type of interface */
-	i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;	/* clear some bits */
-	ISP16_OUT(ISP16_DRIVE_SET_PORT, i | drive_type);
-
-	/* enable cdrom on interface with 82C929 chip */
-	if (isp16_type > 1)
-		ISP16_OUT(isp16_enable_port, ISP16_ENABLE_CDROM);
-
-	/* set base address, irq and dma */
-	i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;	/* keep some bits */
-	ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code);
-
-	return 0;
-}
-
-static void __exit isp16_exit(void)
-{
-	release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
-	printk(KERN_INFO "ISP16: module released.\n");
-}
-
-module_init(isp16_init);
-module_exit(isp16_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/cdrom/isp16.h b/drivers/cdrom/isp16.h
deleted file mode 100644
index 5bd22c8..0000000
--- a/drivers/cdrom/isp16.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -- isp16.h
- *
- *  Header for detection and initialisation of cdrom interface (only) on
- *  ISP16 (MAD16, Mozart) sound card.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/* These are the default values */
-#define ISP16_CDROM_TYPE "Sanyo"
-#define ISP16_CDROM_IO_BASE 0x340
-#define ISP16_CDROM_IRQ 0
-#define ISP16_CDROM_DMA 0
-
-/* Some (Media)Magic */
-/* define types of drive the interface on an ISP16 card may be looking at */
-#define ISP16_DRIVE_X 0x00
-#define ISP16_SONY  0x02
-#define ISP16_PANASONIC0 0x02
-#define ISP16_SANYO0 0x02
-#define ISP16_MITSUMI  0x04
-#define ISP16_PANASONIC1 0x06
-#define ISP16_SANYO1 0x06
-#define ISP16_DRIVE_NOT_USED 0x08  /* not used */
-#define ISP16_DRIVE_SET_MASK 0xF1  /* don't change 0-bit or 4-7-bits*/
-/* ...for port */
-#define ISP16_DRIVE_SET_PORT 0xF8D
-/* set io parameters */
-#define ISP16_BASE_340  0x00
-#define ISP16_BASE_330  0x40
-#define ISP16_BASE_360  0x80
-#define ISP16_BASE_320  0xC0
-#define ISP16_IRQ_X  0x00
-#define ISP16_IRQ_5  0x04  /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_7  0x08  /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_3  0x0C
-#define ISP16_IRQ_9  0x10
-#define ISP16_IRQ_10  0x14
-#define ISP16_IRQ_11  0x18
-#define ISP16_DMA_X  0x03
-#define ISP16_DMA_3  0x00
-#define ISP16_DMA_5  0x00
-#define ISP16_DMA_6  0x01
-#define ISP16_DMA_7  0x02
-#define ISP16_IO_SET_MASK  0x20  /* don't change 5-bit */
-/* ...for port */
-#define ISP16_IO_SET_PORT  0xF8E
-/* enable the card */
-#define ISP16_C928__ENABLE_PORT  0xF90  /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__ENABLE_PORT  0xF91  /* ISP16 with OPTi 82C929 chip */
-#define ISP16_ENABLE_CDROM  0x80  /* seven bit */
-
-/* the magic stuff */
-#define ISP16_CTRL_PORT  0xF8F
-#define ISP16_C928__CTRL  0xE2  /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__CTRL  0xE3  /* ISP16 with OPTi 82C929 chip */
-
-#define ISP16_IO_BASE 0xF8D
-#define ISP16_IO_SIZE 5  /* ports used from 0xF8D up to 0xF91 */
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
deleted file mode 100644
index 4310cc8..0000000
--- a/drivers/cdrom/mcdx.c
+++ /dev/null
@@ -1,1943 +0,0 @@
-/*
- * The Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 2.14(hs)
- *
- * ... anyway, I'm back again, thanks to Marcin, he adopted
- * large portions of my code (at least the parts containing
- * my main thoughts ...)
- *
- ****************** H E L P *********************************
- * If you ever plan to update your CD ROM drive and perhaps
- * want to sell or simply give away your Mitsumi FX-001[DS]
- * -- Please --
- * mail me (heiko@lotte.sax.de).  When my last drive goes
- * ballistic no more driver support will be available from me!
- *************************************************************
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- *  The Linux Community at all and ...
- *  Martin Harriss (he wrote the first Mitsumi Driver)
- *  Eberhard Moenkeberg (he gave me much support and the initial kick)
- *  Bernd Huebner, Ruediger Helsch (Unifix-Software GmbH, they
- *      improved the original driver)
- *  Jon Tombs, Bjorn Ekwall (module support)
- *  Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- *  Gerd Knorr (he lent me his PhotoCD)
- *  Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- *  Andreas Kies (testing the mysterious hang-ups)
- *  Heiko Eissfeldt (VERIFY_READ/WRITE)
- *  Marcin Dalecki (improved performance, shortened code)
- *  ... somebody forgotten?
- *
- *  9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	               Removed init_module & cleanup_module in favor of 
- *		       module_init & module_exit.
- *		       Torben Mathiasen <tmm@image.dk>
- */
-
-
-#ifdef RCS
-static const char *mcdx_c_version
-    = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $";
-#endif
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/current.h>
-#include <asm/uaccess.h>
-
-#include <linux/major.h>
-#define MAJOR_NR MITSUMI_X_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#include "mcdx.h"
-
-#ifndef HZ
-#error HZ not defined
-#endif
-
-#define xwarn(fmt, args...) printk(KERN_WARNING MCDX " " fmt, ## args)
-
-#if !MCDX_QUIET
-#define xinfo(fmt, args...) printk(KERN_INFO MCDX " " fmt, ## args)
-#else
-#define xinfo(fmt, args...) { ; }
-#endif
-
-#if MCDX_DEBUG
-#define xtrace(lvl, fmt, args...) \
-		{ if (lvl > 0) \
-			{ printk(KERN_DEBUG MCDX ":: " fmt, ## args); } }
-#define xdebug(fmt, args...) printk(KERN_DEBUG MCDX ":: " fmt, ## args)
-#else
-#define xtrace(lvl, fmt, args...) { ; }
-#define xdebug(fmt, args...) { ; }
-#endif
-
-/* CONSTANTS *******************************************************/
-
-/* Following are the number of sectors we _request_ from the drive
-   every time an access outside the already requested range is done.
-   The _direct_ size is the number of sectors we're allowed to skip
-   directly (performing a read instead of requesting the new sector
-   needed */
-static const int REQUEST_SIZE = 800;	/* should be less then 255 * 4 */
-static const int DIRECT_SIZE = 400;	/* should be less then REQUEST_SIZE */
-
-enum drivemodes { TOC, DATA, RAW, COOKED };
-enum datamodes { MODE0, MODE1, MODE2 };
-enum resetmodes { SOFT, HARD };
-
-static const int SINGLE = 0x01;		/* single speed drive (FX001S, LU) */
-static const int DOUBLE = 0x02;		/* double speed drive (FX001D, ..? */
-static const int DOOR = 0x04;		/* door locking capability */
-static const int MULTI = 0x08;		/* multi session capability */
-
-static const unsigned char READ1X = 0xc0;
-static const unsigned char READ2X = 0xc1;
-
-
-/* DECLARATIONS ****************************************************/
-struct s_subqcode {
-	unsigned char control;
-	unsigned char tno;
-	unsigned char index;
-	struct cdrom_msf0 tt;
-	struct cdrom_msf0 dt;
-};
-
-struct s_diskinfo {
-	unsigned int n_first;
-	unsigned int n_last;
-	struct cdrom_msf0 msf_leadout;
-	struct cdrom_msf0 msf_first;
-};
-
-struct s_multi {
-	unsigned char multi;
-	struct cdrom_msf0 msf_last;
-};
-
-struct s_version {
-	unsigned char code;
-	unsigned char ver;
-};
-
-/* Per drive/controller stuff **************************************/
-
-struct s_drive_stuff {
-	/* waitqueues */
-	wait_queue_head_t busyq;
-	wait_queue_head_t lockq;
-	wait_queue_head_t sleepq;
-
-	/* flags */
-	volatile int introk;	/* status of last irq operation */
-	volatile int busy;	/* drive performs an operation */
-	volatile int lock;	/* exclusive usage */
-
-	/* cd infos */
-	struct s_diskinfo di;
-	struct s_multi multi;
-	struct s_subqcode *toc;	/* first entry of the toc array */
-	struct s_subqcode start;
-	struct s_subqcode stop;
-	int xa;			/* 1 if xa disk */
-	int audio;		/* 1 if audio disk */
-	int audiostatus;
-
-	/* `buffer' control */
-	volatile int valid;	/* pending, ..., values are valid */
-	volatile int pending;	/* next sector to be read */
-	volatile int low_border;	/* first sector not to be skipped direct */
-	volatile int high_border;	/* first sector `out of area' */
-#ifdef AK2
-	volatile int int_err;
-#endif				/* AK2 */
-
-	/* adds and odds */
-	unsigned wreg_data;	/* w data */
-	unsigned wreg_reset;	/* w hardware reset */
-	unsigned wreg_hcon;	/* w hardware conf */
-	unsigned wreg_chn;	/* w channel */
-	unsigned rreg_data;	/* r data */
-	unsigned rreg_status;	/* r status */
-
-	int irq;		/* irq used by this drive */
-	int present;		/* drive present and its capabilities */
-	unsigned char readcmd;	/* read cmd depends on single/double speed */
-	unsigned char playcmd;	/* play should always be single speed */
-	unsigned int xxx;	/* set if changed, reset while open */
-	unsigned int yyy;	/* set if changed, reset by media_changed */
-	int users;		/* keeps track of open/close */
-	int lastsector;		/* last block accessible */
-	int status;		/* last operation's error / status */
-	int readerrs;		/* # of blocks read w/o error */
-	struct cdrom_device_info info;
-	struct gendisk *disk;
-};
-
-
-/* Prototypes ******************************************************/
-
-/*	The following prototypes are already declared elsewhere.  They are
- 	repeated here to show what's going on.  And to sense, if they're
-	changed elsewhere. */
-
-static int mcdx_init(void);
-
-static int mcdx_block_open(struct inode *inode, struct file *file)
-{
-	struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
-	return cdrom_open(&p->info, inode, file);
-}
-
-static int mcdx_block_release(struct inode *inode, struct file *file)
-{
-	struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
-	return cdrom_release(&p->info, file);
-}
-
-static int mcdx_block_ioctl(struct inode *inode, struct file *file,
-				unsigned cmd, unsigned long arg)
-{
-	struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
-	return cdrom_ioctl(file, &p->info, inode, cmd, arg);
-}
-
-static int mcdx_block_media_changed(struct gendisk *disk)
-{
-	struct s_drive_stuff *p = disk->private_data;
-	return cdrom_media_changed(&p->info);
-}
-
-static struct block_device_operations mcdx_bdops =
-{
-	.owner		= THIS_MODULE,
-	.open		= mcdx_block_open,
-	.release	= mcdx_block_release,
-	.ioctl		= mcdx_block_ioctl,
-	.media_changed	= mcdx_block_media_changed,
-};
-
-
-/*	Indirect exported functions. These functions are exported by their
-	addresses, such as mcdx_open and mcdx_close in the
-	structure mcdx_dops. */
-
-/* exported by file_ops */
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose);
-static void mcdx_close(struct cdrom_device_info *cdi);
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr);
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position);
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock);
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
-			    unsigned int cmd, void *arg);
-
-/* misc internal support functions */
-static void log2msf(unsigned int, struct cdrom_msf0 *);
-static unsigned int msf2log(const struct cdrom_msf0 *);
-static unsigned int uint2bcd(unsigned int);
-static unsigned int bcd2uint(unsigned char);
-static unsigned port(int *);
-static int irq(int *);
-static void mcdx_delay(struct s_drive_stuff *, long jifs);
-static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector,
-			 int nr_sectors);
-static int mcdx_xfer(struct s_drive_stuff *, char *buf, int sector,
-		     int nr_sectors);
-
-static int mcdx_config(struct s_drive_stuff *, int);
-static int mcdx_requestversion(struct s_drive_stuff *, struct s_version *,
-			       int);
-static int mcdx_stop(struct s_drive_stuff *, int);
-static int mcdx_hold(struct s_drive_stuff *, int);
-static int mcdx_reset(struct s_drive_stuff *, enum resetmodes, int);
-static int mcdx_setdrivemode(struct s_drive_stuff *, enum drivemodes, int);
-static int mcdx_setdatamode(struct s_drive_stuff *, enum datamodes, int);
-static int mcdx_requestsubqcode(struct s_drive_stuff *,
-				struct s_subqcode *, int);
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *,
-				     struct s_multi *, int);
-static int mcdx_requesttocdata(struct s_drive_stuff *, struct s_diskinfo *,
-			       int);
-static int mcdx_getstatus(struct s_drive_stuff *, int);
-static int mcdx_getval(struct s_drive_stuff *, int to, int delay, char *);
-static int mcdx_talk(struct s_drive_stuff *,
-		     const unsigned char *cmd, size_t,
-		     void *buffer, size_t size, unsigned int timeout, int);
-static int mcdx_readtoc(struct s_drive_stuff *);
-static int mcdx_playtrk(struct s_drive_stuff *, const struct cdrom_ti *);
-static int mcdx_playmsf(struct s_drive_stuff *, const struct cdrom_msf *);
-static int mcdx_setattentuator(struct s_drive_stuff *,
-			       struct cdrom_volctrl *, int);
-
-/* static variables ************************************************/
-
-static int mcdx_drive_map[][2] = MCDX_DRIVEMAP;
-static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES];
-static DEFINE_SPINLOCK(mcdx_lock);
-static struct request_queue *mcdx_queue;
-
-/* You can only set the first two pairs, from old MODULE_PARM code.  */
-static int mcdx_set(const char *val, struct kernel_param *kp)
-{
-	get_options((char *)val, 4, (int *)mcdx_drive_map);
-	return 0;
-}
-module_param_call(mcdx, mcdx_set, NULL, NULL, 0);
-
-static struct cdrom_device_ops mcdx_dops = {
-	.open		= mcdx_open,
-	.release	= mcdx_close,
-	.media_changed	= mcdx_media_changed,
-	.tray_move	= mcdx_tray_move,
-	.lock_door	= mcdx_lockdoor,
-	.audio_ioctl	= mcdx_audio_ioctl,
-	.capability	= CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED |
-			  CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
-};
-
-/* KERNEL INTERFACE FUNCTIONS **************************************/
-
-
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
-			    unsigned int cmd, void *arg)
-{
-	struct s_drive_stuff *stuffp = cdi->handle;
-
-	if (!stuffp->present)
-		return -ENXIO;
-
-	if (stuffp->xxx) {
-		if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
-			stuffp->lastsector = -1;
-		} else {
-			stuffp->lastsector = (CD_FRAMESIZE / 512)
-			    * msf2log(&stuffp->di.msf_leadout) - 1;
-		}
-
-		if (stuffp->toc) {
-			kfree(stuffp->toc);
-			stuffp->toc = NULL;
-			if (-1 == mcdx_readtoc(stuffp))
-				return -1;
-		}
-
-		stuffp->xxx = 0;
-	}
-
-	switch (cmd) {
-	case CDROMSTART:{
-			xtrace(IOCTL, "ioctl() START\n");
-			/* Spin up the drive.  Don't think we can do this.
-			   * For now, ignore it.
-			 */
-			return 0;
-		}
-
-	case CDROMSTOP:{
-			xtrace(IOCTL, "ioctl() STOP\n");
-			stuffp->audiostatus = CDROM_AUDIO_INVALID;
-			if (-1 == mcdx_stop(stuffp, 1))
-				return -EIO;
-			return 0;
-		}
-
-	case CDROMPLAYTRKIND:{
-			struct cdrom_ti *ti = (struct cdrom_ti *) arg;
-
-			xtrace(IOCTL, "ioctl() PLAYTRKIND\n");
-			if ((ti->cdti_trk0 < stuffp->di.n_first)
-			    || (ti->cdti_trk0 > stuffp->di.n_last)
-			    || (ti->cdti_trk1 < stuffp->di.n_first))
-				return -EINVAL;
-			if (ti->cdti_trk1 > stuffp->di.n_last)
-				ti->cdti_trk1 = stuffp->di.n_last;
-			xtrace(PLAYTRK, "ioctl() track %d to %d\n",
-			       ti->cdti_trk0, ti->cdti_trk1);
-			return mcdx_playtrk(stuffp, ti);
-		}
-
-	case CDROMPLAYMSF:{
-			struct cdrom_msf *msf = (struct cdrom_msf *) arg;
-
-			xtrace(IOCTL, "ioctl() PLAYMSF\n");
-
-			if ((stuffp->audiostatus == CDROM_AUDIO_PLAY)
-			    && (-1 == mcdx_hold(stuffp, 1)))
-				return -EIO;
-
-			msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0);
-			msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0);
-			msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0);
-
-			msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1);
-			msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1);
-			msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1);
-
-			stuffp->stop.dt.minute = msf->cdmsf_min1;
-			stuffp->stop.dt.second = msf->cdmsf_sec1;
-			stuffp->stop.dt.frame = msf->cdmsf_frame1;
-
-			return mcdx_playmsf(stuffp, msf);
-		}
-
-	case CDROMRESUME:{
-			xtrace(IOCTL, "ioctl() RESUME\n");
-			return mcdx_playtrk(stuffp, NULL);
-		}
-
-	case CDROMREADTOCENTRY:{
-			struct cdrom_tocentry *entry =
-			    (struct cdrom_tocentry *) arg;
-			struct s_subqcode *tp = NULL;
-			xtrace(IOCTL, "ioctl() READTOCENTRY\n");
-
-			if (-1 == mcdx_readtoc(stuffp))
-				return -1;
-			if (entry->cdte_track == CDROM_LEADOUT)
-				tp = &stuffp->toc[stuffp->di.n_last -
-						  stuffp->di.n_first + 1];
-			else if (entry->cdte_track > stuffp->di.n_last
-				 || entry->cdte_track < stuffp->di.n_first)
-				return -EINVAL;
-			else
-				tp = &stuffp->toc[entry->cdte_track -
-						  stuffp->di.n_first];
-
-			if (NULL == tp)
-				return -EIO;
-			entry->cdte_adr = tp->control;
-			entry->cdte_ctrl = tp->control >> 4;
-			/* Always return stuff in MSF, and let the Uniform cdrom driver
-			   worry about what the user actually wants */
-			entry->cdte_addr.msf.minute =
-			    bcd2uint(tp->dt.minute);
-			entry->cdte_addr.msf.second =
-			    bcd2uint(tp->dt.second);
-			entry->cdte_addr.msf.frame =
-			    bcd2uint(tp->dt.frame);
-			return 0;
-		}
-
-	case CDROMSUBCHNL:{
-			struct cdrom_subchnl *sub =
-			    (struct cdrom_subchnl *) arg;
-			struct s_subqcode q;
-
-			xtrace(IOCTL, "ioctl() SUBCHNL\n");
-
-			if (-1 == mcdx_requestsubqcode(stuffp, &q, 2))
-				return -EIO;
-
-			xtrace(SUBCHNL, "audiostatus: %x\n",
-			       stuffp->audiostatus);
-			sub->cdsc_audiostatus = stuffp->audiostatus;
-			sub->cdsc_adr = q.control;
-			sub->cdsc_ctrl = q.control >> 4;
-			sub->cdsc_trk = bcd2uint(q.tno);
-			sub->cdsc_ind = bcd2uint(q.index);
-
-			xtrace(SUBCHNL, "trk %d, ind %d\n",
-			       sub->cdsc_trk, sub->cdsc_ind);
-			/* Always return stuff in MSF, and let the Uniform cdrom driver
-			   worry about what the user actually wants */
-			sub->cdsc_absaddr.msf.minute =
-			    bcd2uint(q.dt.minute);
-			sub->cdsc_absaddr.msf.second =
-			    bcd2uint(q.dt.second);
-			sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
-			sub->cdsc_reladdr.msf.minute =
-			    bcd2uint(q.tt.minute);
-			sub->cdsc_reladdr.msf.second =
-			    bcd2uint(q.tt.second);
-			sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
-			xtrace(SUBCHNL,
-			       "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
-			       sub->cdsc_absaddr.msf.minute,
-			       sub->cdsc_absaddr.msf.second,
-			       sub->cdsc_absaddr.msf.frame,
-			       sub->cdsc_reladdr.msf.minute,
-			       sub->cdsc_reladdr.msf.second,
-			       sub->cdsc_reladdr.msf.frame);
-
-			return 0;
-		}
-
-	case CDROMREADTOCHDR:{
-			struct cdrom_tochdr *toc =
-			    (struct cdrom_tochdr *) arg;
-
-			xtrace(IOCTL, "ioctl() READTOCHDR\n");
-			toc->cdth_trk0 = stuffp->di.n_first;
-			toc->cdth_trk1 = stuffp->di.n_last;
-			xtrace(TOCHDR,
-			       "ioctl() track0 = %d, track1 = %d\n",
-			       stuffp->di.n_first, stuffp->di.n_last);
-			return 0;
-		}
-
-	case CDROMPAUSE:{
-			xtrace(IOCTL, "ioctl() PAUSE\n");
-			if (stuffp->audiostatus != CDROM_AUDIO_PLAY)
-				return -EINVAL;
-			if (-1 == mcdx_stop(stuffp, 1))
-				return -EIO;
-			stuffp->audiostatus = CDROM_AUDIO_PAUSED;
-			if (-1 ==
-			    mcdx_requestsubqcode(stuffp, &stuffp->start,
-						 1))
-				return -EIO;
-			return 0;
-		}
-
-	case CDROMMULTISESSION:{
-			struct cdrom_multisession *ms =
-			    (struct cdrom_multisession *) arg;
-			xtrace(IOCTL, "ioctl() MULTISESSION\n");
-			/* Always return stuff in LBA, and let the Uniform cdrom driver
-			   worry about what the user actually wants */
-			ms->addr.lba = msf2log(&stuffp->multi.msf_last);
-			ms->xa_flag = !!stuffp->multi.multi;
-			xtrace(MS,
-			       "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
-			       ms->xa_flag, ms->addr.lba,
-			       stuffp->multi.msf_last.minute,
-			       stuffp->multi.msf_last.second,
-			       stuffp->multi.msf_last.frame);
-
-			return 0;
-		}
-
-	case CDROMEJECT:{
-			xtrace(IOCTL, "ioctl() EJECT\n");
-			if (stuffp->users > 1)
-				return -EBUSY;
-			return (mcdx_tray_move(cdi, 1));
-		}
-
-	case CDROMCLOSETRAY:{
-			xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n");
-			return (mcdx_tray_move(cdi, 0));
-		}
-
-	case CDROMVOLCTRL:{
-			struct cdrom_volctrl *volctrl =
-			    (struct cdrom_volctrl *) arg;
-			xtrace(IOCTL, "ioctl() VOLCTRL\n");
-
-#if 0				/* not tested! */
-			/* adjust for the weirdness of workman (md) */
-			/* can't test it (hs) */
-			volctrl.channel2 = volctrl.channel1;
-			volctrl.channel1 = volctrl.channel3 = 0x00;
-#endif
-			return mcdx_setattentuator(stuffp, volctrl, 2);
-		}
-
-	default:
-		return -EINVAL;
-	}
-}
-
-static void do_mcdx_request(request_queue_t * q)
-{
-	struct s_drive_stuff *stuffp;
-	struct request *req;
-
-      again:
-
-	req = elv_next_request(q);
-	if (!req)
-		return;
-
-	stuffp = req->rq_disk->private_data;
-
-	if (!stuffp->present) {
-		xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name);
-		xtrace(REQUEST, "end_request(0): bad device\n");
-		end_request(req, 0);
-		return;
-	}
-
-	if (stuffp->audio) {
-		xwarn("do_request() attempt to read from audio cd\n");
-		xtrace(REQUEST, "end_request(0): read from audio\n");
-		end_request(req, 0);
-		return;
-	}
-
-	xtrace(REQUEST, "do_request() (%lu + %lu)\n",
-	       req->sector, req->nr_sectors);
-
-	if (req->cmd != READ) {
-		xwarn("do_request(): non-read command to cd!!\n");
-		xtrace(REQUEST, "end_request(0): write\n");
-		end_request(req, 0);
-		return;
-	}
-	else {
-		stuffp->status = 0;
-		while (req->nr_sectors) {
-			int i;
-
-			i = mcdx_transfer(stuffp,
-					  req->buffer,
-					  req->sector,
-					  req->nr_sectors);
-
-			if (i == -1) {
-				end_request(req, 0);
-				goto again;
-			}
-			req->sector += i;
-			req->nr_sectors -= i;
-			req->buffer += (i * 512);
-		}
-		end_request(req, 1);
-		goto again;
-
-		xtrace(REQUEST, "end_request(1)\n");
-		end_request(req, 1);
-	}
-
-	goto again;
-}
-
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose)
-{
-	struct s_drive_stuff *stuffp;
-	xtrace(OPENCLOSE, "open()\n");
-	stuffp = cdi->handle;
-	if (!stuffp->present)
-		return -ENXIO;
-
-	/* Make the modules looking used ... (thanx bjorn).
-	 * But we shouldn't forget to decrement the module counter
-	 * on error return */
-
-	/* this is only done to test if the drive talks with us */
-	if (-1 == mcdx_getstatus(stuffp, 1))
-		return -EIO;
-
-	if (stuffp->xxx) {
-
-		xtrace(OPENCLOSE, "open() media changed\n");
-		stuffp->audiostatus = CDROM_AUDIO_INVALID;
-		stuffp->readcmd = 0;
-		xtrace(OPENCLOSE, "open() Request multisession info\n");
-		if (-1 ==
-		    mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6))
-			xinfo("No multidiskinfo\n");
-	} else {
-		/* multisession ? */
-		if (!stuffp->multi.multi)
-			stuffp->multi.msf_last.second = 2;
-
-		xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",
-		       stuffp->multi.multi,
-		       stuffp->multi.msf_last.minute,
-		       stuffp->multi.msf_last.second,
-		       stuffp->multi.msf_last.frame);
-
-		{;
-		}		/* got multisession information */
-		/* request the disks table of contents (aka diskinfo) */
-		if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
-
-			stuffp->lastsector = -1;
-
-		} else {
-
-			stuffp->lastsector = (CD_FRAMESIZE / 512)
-			    * msf2log(&stuffp->di.msf_leadout) - 1;
-
-			xtrace(OPENCLOSE,
-			       "open() start %d (%02x:%02x.%02x) %d\n",
-			       stuffp->di.n_first,
-			       stuffp->di.msf_first.minute,
-			       stuffp->di.msf_first.second,
-			       stuffp->di.msf_first.frame,
-			       msf2log(&stuffp->di.msf_first));
-			xtrace(OPENCLOSE,
-			       "open() last %d (%02x:%02x.%02x) %d\n",
-			       stuffp->di.n_last,
-			       stuffp->di.msf_leadout.minute,
-			       stuffp->di.msf_leadout.second,
-			       stuffp->di.msf_leadout.frame,
-			       msf2log(&stuffp->di.msf_leadout));
-		}
-
-		if (stuffp->toc) {
-			xtrace(MALLOC, "open() free old toc @ %p\n",
-			       stuffp->toc);
-			kfree(stuffp->toc);
-
-			stuffp->toc = NULL;
-		}
-
-		xtrace(OPENCLOSE, "open() init irq generation\n");
-		if (-1 == mcdx_config(stuffp, 1))
-			return -EIO;
-#ifdef FALLBACK
-		/* Set the read speed */
-		xwarn("AAA %x AAA\n", stuffp->readcmd);
-		if (stuffp->readerrs)
-			stuffp->readcmd = READ1X;
-		else
-			stuffp->readcmd =
-			    stuffp->present | SINGLE ? READ1X : READ2X;
-		xwarn("XXX %x XXX\n", stuffp->readcmd);
-#else
-		stuffp->readcmd =
-		    stuffp->present | SINGLE ? READ1X : READ2X;
-#endif
-
-		/* try to get the first sector, iff any ... */
-		if (stuffp->lastsector >= 0) {
-			char buf[512];
-			int ans;
-			int tries;
-
-			stuffp->xa = 0;
-			stuffp->audio = 0;
-
-			for (tries = 6; tries; tries--) {
-
-				stuffp->introk = 1;
-
-				xtrace(OPENCLOSE, "open() try as %s\n",
-				       stuffp->xa ? "XA" : "normal");
-				/* set data mode */
-				if (-1 == (ans = mcdx_setdatamode(stuffp,
-								  stuffp->
-								  xa ?
-								  MODE2 :
-								  MODE1,
-								  1))) {
-					/* return -EIO; */
-					stuffp->xa = 0;
-					break;
-				}
-
-				if ((stuffp->audio = e_audio(ans)))
-					break;
-
-				while (0 ==
-				       (ans =
-					mcdx_transfer(stuffp, buf, 0, 1)));
-
-				if (ans == 1)
-					break;
-				stuffp->xa = !stuffp->xa;
-			}
-		}
-		/* xa disks will be read in raw mode, others not */
-		if (-1 == mcdx_setdrivemode(stuffp,
-					    stuffp->xa ? RAW : COOKED,
-					    1))
-			return -EIO;
-		if (stuffp->audio) {
-			xinfo("open() audio disk found\n");
-		} else if (stuffp->lastsector >= 0) {
-			xinfo("open() %s%s disk found\n",
-			      stuffp->xa ? "XA / " : "",
-			      stuffp->multi.
-			      multi ? "Multi Session" : "Single Session");
-		}
-	}
-	stuffp->xxx = 0;
-	stuffp->users++;
-	return 0;
-}
-
-static void mcdx_close(struct cdrom_device_info *cdi)
-{
-	struct s_drive_stuff *stuffp;
-
-	xtrace(OPENCLOSE, "close()\n");
-
-	stuffp = cdi->handle;
-
-	--stuffp->users;
-}
-
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-/*	Return: 1 if media changed since last call to this function
-			0 otherwise */
-{
-	struct s_drive_stuff *stuffp;
-
-	xinfo("mcdx_media_changed called for device %s\n", cdi->name);
-
-	stuffp = cdi->handle;
-	mcdx_getstatus(stuffp, 1);
-
-	if (stuffp->yyy == 0)
-		return 0;
-
-	stuffp->yyy = 0;
-	return 1;
-}
-
-#ifndef MODULE
-static int __init mcdx_setup(char *str)
-{
-	int pi[4];
-	(void) get_options(str, ARRAY_SIZE(pi), pi);
-
-	if (pi[0] > 0)
-		mcdx_drive_map[0][0] = pi[1];
-	if (pi[0] > 1)
-		mcdx_drive_map[0][1] = pi[2];
-	return 1;
-}
-
-__setup("mcdx=", mcdx_setup);
-
-#endif
-
-/* DIRTY PART ******************************************************/
-
-static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
-/* This routine is used for sleeping.
- * A jifs value <0 means NO sleeping,
- *              =0 means minimal sleeping (let the kernel
- *                 run for other processes)
- *              >0 means at least sleep for that amount.
- *	May be we could use a simple count loop w/ jumps to itself, but
- *	I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */
-{
-	if (jifs < 0)
-		return;
-
-	xtrace(SLEEP, "*** delay: sleepq\n");
-	interruptible_sleep_on_timeout(&stuff->sleepq, jifs);
-	xtrace(SLEEP, "delay awoken\n");
-	if (signal_pending(current)) {
-		xtrace(SLEEP, "got signal\n");
-	}
-}
-
-static irqreturn_t mcdx_intr(int irq, void *dev_id)
-{
-	struct s_drive_stuff *stuffp = dev_id;
-	unsigned char b;
-
-#ifdef AK2
-	if (!stuffp->busy && stuffp->pending)
-		stuffp->int_err = 1;
-
-#endif				/* AK2 */
-	/* get the interrupt status */
-	b = inb(stuffp->rreg_status);
-	stuffp->introk = ~b & MCDX_RBIT_DTEN;
-
-	/* NOTE: We only should get interrupts if the data we
-	 * requested are ready to transfer.
-	 * But the drive seems to generate ``asynchronous'' interrupts
-	 * on several error conditions too.  (Despite the err int enable
-	 * setting during initialisation) */
-
-	/* if not ok, read the next byte as the drives status */
-	if (!stuffp->introk) {
-		xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b);
-		if (~b & MCDX_RBIT_STEN) {
-			xinfo("intr() irq %d    status 0x%02x\n",
-			      irq, inb(stuffp->rreg_data));
-		} else {
-			xinfo("intr() irq %d ambiguous hw status\n", irq);
-		}
-	} else {
-		xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b);
-	}
-
-	stuffp->busy = 0;
-	wake_up_interruptible(&stuffp->busyq);
-	return IRQ_HANDLED;
-}
-
-
-static int mcdx_talk(struct s_drive_stuff *stuffp,
-	  const unsigned char *cmd, size_t cmdlen,
-	  void *buffer, size_t size, unsigned int timeout, int tries)
-/* Send a command to the drive, wait for the result.
- * returns -1 on timeout, drive status otherwise
- * If buffer is not zero, the result (length size) is stored there.
- * If buffer is zero the size should be the number of bytes to read
- * from the drive.  These bytes are discarded.
- */
-{
-	int st;
-	char c;
-	int discard;
-
-	/* Somebody wants the data read? */
-	if ((discard = (buffer == NULL)))
-		buffer = &c;
-
-	while (stuffp->lock) {
-		xtrace(SLEEP, "*** talk: lockq\n");
-		interruptible_sleep_on(&stuffp->lockq);
-		xtrace(SLEEP, "talk: awoken\n");
-	}
-
-	stuffp->lock = 1;
-
-	/* An operation other then reading data destroys the
-	   * data already requested and remembered in stuffp->request, ... */
-	stuffp->valid = 0;
-
-#if MCDX_DEBUG & TALK
-	{
-		unsigned char i;
-		xtrace(TALK,
-		       "talk() %d / %d tries, res.size %d, command 0x%02x",
-		       tries, timeout, size, (unsigned char) cmd[0]);
-		for (i = 1; i < cmdlen; i++)
-			xtrace(TALK, " 0x%02x", cmd[i]);
-		xtrace(TALK, "\n");
-	}
-#endif
-
-	/*  give up if all tries are done (bad) or if the status
-	 *  st != -1 (good) */
-	for (st = -1; st == -1 && tries; tries--) {
-
-		char *bp = (char *) buffer;
-		size_t sz = size;
-
-		outsb(stuffp->wreg_data, cmd, cmdlen);
-		xtrace(TALK, "talk() command sent\n");
-
-		/* get the status byte */
-		if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
-			xinfo("talk() %02x timed out (status), %d tr%s left\n",
-			     cmd[0], tries - 1, tries == 2 ? "y" : "ies");
-			continue;
-		}
-		st = *bp;
-		sz--;
-		if (!discard)
-			bp++;
-
-		xtrace(TALK, "talk() got status 0x%02x\n", st);
-
-		/* command error? */
-		if (e_cmderr(st)) {
-			xwarn("command error cmd = %02x %s \n",
-			      cmd[0], cmdlen > 1 ? "..." : "");
-			st = -1;
-			continue;
-		}
-
-		/* audio status? */
-		if (stuffp->audiostatus == CDROM_AUDIO_INVALID)
-			stuffp->audiostatus =
-			    e_audiobusy(st) ? CDROM_AUDIO_PLAY :
-			    CDROM_AUDIO_NO_STATUS;
-		else if (stuffp->audiostatus == CDROM_AUDIO_PLAY
-			 && e_audiobusy(st) == 0)
-			stuffp->audiostatus = CDROM_AUDIO_COMPLETED;
-
-		/* media change? */
-		if (e_changed(st)) {
-			xinfo("talk() media changed\n");
-			stuffp->xxx = stuffp->yyy = 1;
-		}
-
-		/* now actually get the data */
-		while (sz--) {
-			if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
-				xinfo("talk() %02x timed out (data), %d tr%s left\n",
-				     cmd[0], tries - 1,
-				     tries == 2 ? "y" : "ies");
-				st = -1;
-				break;
-			}
-			if (!discard)
-				bp++;
-			xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1));
-		}
-	}
-
-#if !MCDX_QUIET
-	if (!tries && st == -1)
-		xinfo("talk() giving up\n");
-#endif
-
-	stuffp->lock = 0;
-	wake_up_interruptible(&stuffp->lockq);
-
-	xtrace(TALK, "talk() done with 0x%02x\n", st);
-	return st;
-}
-
-/* MODULE STUFF ***********************************************************/
-
-static int __init __mcdx_init(void)
-{
-	int i;
-	int drives = 0;
-
-	mcdx_init();
-	for (i = 0; i < MCDX_NDRIVES; i++) {
-		if (mcdx_stuffp[i]) {
-			xtrace(INIT, "init_module() drive %d stuff @ %p\n",
-			       i, mcdx_stuffp[i]);
-			drives++;
-		}
-	}
-
-	if (!drives)
-		return -EIO;
-
-	return 0;
-}
-
-static void __exit mcdx_exit(void)
-{
-	int i;
-
-	xinfo("cleanup_module called\n");
-
-	for (i = 0; i < MCDX_NDRIVES; i++) {
-		struct s_drive_stuff *stuffp = mcdx_stuffp[i];
-		if (!stuffp)
-			continue;
-		del_gendisk(stuffp->disk);
-		if (unregister_cdrom(&stuffp->info)) {
-			printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
-			continue;
-		}
-		put_disk(stuffp->disk);
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		free_irq(stuffp->irq, NULL);
-		if (stuffp->toc) {
-			xtrace(MALLOC, "cleanup_module() free toc @ %p\n",
-			       stuffp->toc);
-			kfree(stuffp->toc);
-		}
-		xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n",
-		       stuffp);
-		mcdx_stuffp[i] = NULL;
-		kfree(stuffp);
-	}
-
-	if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
-		xwarn("cleanup() unregister_blkdev() failed\n");
-	}
-#if !MCDX_QUIET
-	else
-	xinfo("cleanup() succeeded\n");
-#endif
-	blk_cleanup_queue(mcdx_queue);
-}
-
-#ifdef MODULE
-module_init(__mcdx_init);
-#endif
-module_exit(mcdx_exit);
-
-
-/* Support functions ************************************************/
-
-static int __init mcdx_init_drive(int drive)
-{
-	struct s_version version;
-	struct gendisk *disk;
-	struct s_drive_stuff *stuffp;
-	int size = sizeof(*stuffp);
-	char msg[80];
-
-	xtrace(INIT, "init() try drive %d\n", drive);
-
-	xtrace(INIT, "kmalloc space for stuffpt's\n");
-	xtrace(MALLOC, "init() malloc %d bytes\n", size);
-	if (!(stuffp = kzalloc(size, GFP_KERNEL))) {
-		xwarn("init() malloc failed\n");
-		return 1;
-	}
-
-	disk = alloc_disk(1);
-	if (!disk) {
-		xwarn("init() malloc failed\n");
-		kfree(stuffp);
-		return 1;
-	}
-
-	xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",
-	       sizeof(*stuffp), stuffp);
-
-	/* set default values */
-	stuffp->present = 0;	/* this should be 0 already */
-	stuffp->toc = NULL;	/* this should be NULL already */
-
-	/* setup our irq and i/o addresses */
-	stuffp->irq = irq(mcdx_drive_map[drive]);
-	stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]);
-	stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
-	stuffp->wreg_hcon = stuffp->wreg_reset + 1;
-	stuffp->wreg_chn = stuffp->wreg_hcon + 1;
-
-	init_waitqueue_head(&stuffp->busyq);
-	init_waitqueue_head(&stuffp->lockq);
-	init_waitqueue_head(&stuffp->sleepq);
-
-	/* check if i/o addresses are available */
-	if (!request_region(stuffp->wreg_data, MCDX_IO_SIZE, "mcdx")) {
-		xwarn("0x%03x,%d: Init failed. "
-		      "I/O ports (0x%03x..0x%03x) already in use.\n",
-		      stuffp->wreg_data, stuffp->irq,
-		      stuffp->wreg_data,
-		      stuffp->wreg_data + MCDX_IO_SIZE - 1);
-		xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
-		kfree(stuffp);
-		put_disk(disk);
-		xtrace(INIT, "init() continue at next drive\n");
-		return 0;	/* next drive */
-	}
-
-	xtrace(INIT, "init() i/o port is available at 0x%03x\n"
-	       stuffp->wreg_data);
-	xtrace(INIT, "init() hardware reset\n");
-	mcdx_reset(stuffp, HARD, 1);
-
-	xtrace(INIT, "init() get version\n");
-	if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
-		/* failed, next drive */
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		xwarn("%s=0x%03x,%d: Init failed. Can't get version.\n",
-		      MCDX, stuffp->wreg_data, stuffp->irq);
-		xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
-		kfree(stuffp);
-		put_disk(disk);
-		xtrace(INIT, "init() continue at next drive\n");
-		return 0;
-	}
-
-	switch (version.code) {
-	case 'D':
-		stuffp->readcmd = READ2X;
-		stuffp->present = DOUBLE | DOOR | MULTI;
-		break;
-	case 'F':
-		stuffp->readcmd = READ1X;
-		stuffp->present = SINGLE | DOOR | MULTI;
-		break;
-	case 'M':
-		stuffp->readcmd = READ1X;
-		stuffp->present = SINGLE;
-		break;
-	default:
-		stuffp->present = 0;
-		break;
-	}
-
-	stuffp->playcmd = READ1X;
-
-	if (!stuffp->present) {
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		xwarn("%s=0x%03x,%d: Init failed. No Mitsumi CD-ROM?.\n",
-		      MCDX, stuffp->wreg_data, stuffp->irq);
-		kfree(stuffp);
-		put_disk(disk);
-		return 0;	/* next drive */
-	}
-
-	xtrace(INIT, "init() register blkdev\n");
-	if (register_blkdev(MAJOR_NR, "mcdx")) {
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		kfree(stuffp);
-		put_disk(disk);
-		return 1;
-	}
-
-	mcdx_queue = blk_init_queue(do_mcdx_request, &mcdx_lock);
-	if (!mcdx_queue) {
-		unregister_blkdev(MAJOR_NR, "mcdx");
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		kfree(stuffp);
-		put_disk(disk);
-		return 1;
-	}
-
-	xtrace(INIT, "init() subscribe irq and i/o\n");
-	if (request_irq(stuffp->irq, mcdx_intr, IRQF_DISABLED, "mcdx", stuffp)) {
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		xwarn("%s=0x%03x,%d: Init failed. Can't get irq (%d).\n",
-		      MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
-		stuffp->irq = 0;
-		blk_cleanup_queue(mcdx_queue);
-		kfree(stuffp);
-		put_disk(disk);
-		return 0;
-	}
-
-	xtrace(INIT, "init() get garbage\n");
-	{
-		int i;
-		mcdx_delay(stuffp, HZ / 2);
-		for (i = 100; i; i--)
-			(void) inb(stuffp->rreg_status);
-	}
-
-
-#ifdef WE_KNOW_WHY
-	/* irq 11 -> channel register */
-	outb(0x50, stuffp->wreg_chn);
-#endif
-
-	xtrace(INIT, "init() set non dma but irq mode\n");
-	mcdx_config(stuffp, 1);
-
-	stuffp->info.ops = &mcdx_dops;
-	stuffp->info.speed = 2;
-	stuffp->info.capacity = 1;
-	stuffp->info.handle = stuffp;
-	sprintf(stuffp->info.name, "mcdx%d", drive);
-	disk->major = MAJOR_NR;
-	disk->first_minor = drive;
-	strcpy(disk->disk_name, stuffp->info.name);
-	disk->fops = &mcdx_bdops;
-	disk->flags = GENHD_FL_CD;
-	stuffp->disk = disk;
-
-	sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%03x, irq %d."
-		" (Firmware version %c %x)\n",
-		stuffp->wreg_data, stuffp->irq, version.code, version.ver);
-	mcdx_stuffp[drive] = stuffp;
-	xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
-	if (register_cdrom(&stuffp->info) != 0) {
-		printk("Cannot register Mitsumi CD-ROM!\n");
-		free_irq(stuffp->irq, NULL);
-		release_region(stuffp->wreg_data, MCDX_IO_SIZE);
-		kfree(stuffp);
-		put_disk(disk);
-		if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
-			xwarn("cleanup() unregister_blkdev() failed\n");
-		blk_cleanup_queue(mcdx_queue);
-		return 2;
-	}
-	disk->private_data = stuffp;
-	disk->queue = mcdx_queue;
-	add_disk(disk);
-	printk(msg);
-	return 0;
-}
-
-static int __init mcdx_init(void)
-{
-	int drive;
-	xwarn("Version 2.14(hs) \n");
-
-	xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n");
-
-	/* zero the pointer array */
-	for (drive = 0; drive < MCDX_NDRIVES; drive++)
-		mcdx_stuffp[drive] = NULL;
-
-	/* do the initialisation */
-	for (drive = 0; drive < MCDX_NDRIVES; drive++) {
-		switch (mcdx_init_drive(drive)) {
-		case 2:
-			return -EIO;
-		case 1:
-			break;
-		}
-	}
-	return 0;
-}
-
-static int mcdx_transfer(struct s_drive_stuff *stuffp,
-	      char *p, int sector, int nr_sectors)
-/*	This seems to do the actually transfer.  But it does more.  It
-	keeps track of errors occurred and will (if possible) fall back
-	to single speed on error.
-	Return:	-1 on timeout or other error
-			else status byte (as in stuff->st) */
-{
-	int ans;
-
-	ans = mcdx_xfer(stuffp, p, sector, nr_sectors);
-	return ans;
-#ifdef FALLBACK
-	if (-1 == ans)
-		stuffp->readerrs++;
-	else
-		return ans;
-
-	if (stuffp->readerrs && stuffp->readcmd == READ1X) {
-		xwarn("XXX Already reading 1x -- no chance\n");
-		return -1;
-	}
-
-	xwarn("XXX Fallback to 1x\n");
-
-	stuffp->readcmd = READ1X;
-	return mcdx_transfer(stuffp, p, sector, nr_sectors);
-#endif
-
-}
-
-
-static int mcdx_xfer(struct s_drive_stuff *stuffp,
-		     char *p, int sector, int nr_sectors)
-/*	This does actually the transfer from the drive.
-	Return:	-1 on timeout or other error
-			else status byte (as in stuff->st) */
-{
-	int border;
-	int done = 0;
-	long timeout;
-
-	if (stuffp->audio) {
-		xwarn("Attempt to read from audio CD.\n");
-		return -1;
-	}
-
-	if (!stuffp->readcmd) {
-		xinfo("Can't transfer from missing disk.\n");
-		return -1;
-	}
-
-	while (stuffp->lock) {
-		interruptible_sleep_on(&stuffp->lockq);
-	}
-
-	if (stuffp->valid && (sector >= stuffp->pending)
-	    && (sector < stuffp->low_border)) {
-
-		/* All (or at least a part of the sectors requested) seems
-		   * to be already requested, so we don't need to bother the
-		   * drive with new requests ...
-		   * Wait for the drive become idle, but first
-		   * check for possible occurred errors --- the drive
-		   * seems to report them asynchronously */
-
-
-		border = stuffp->high_border < (border =
-						sector + nr_sectors)
-		    ? stuffp->high_border : border;
-
-		stuffp->lock = current->pid;
-
-		do {
-
-			while (stuffp->busy) {
-
-				timeout =
-				    interruptible_sleep_on_timeout
-				    (&stuffp->busyq, 5 * HZ);
-
-				if (!stuffp->introk) {
-					xtrace(XFER,
-					       "error via interrupt\n");
-				} else if (!timeout) {
-					xtrace(XFER, "timeout\n");
-				} else if (signal_pending(current)) {
-					xtrace(XFER, "signal\n");
-				} else
-					continue;
-
-				stuffp->lock = 0;
-				stuffp->busy = 0;
-				stuffp->valid = 0;
-
-				wake_up_interruptible(&stuffp->lockq);
-				xtrace(XFER, "transfer() done (-1)\n");
-				return -1;
-			}
-
-			/* check if we need to set the busy flag (as we
-			 * expect an interrupt */
-			stuffp->busy = (3 == (stuffp->pending & 3));
-
-			/* Test if it's the first sector of a block,
-			 * there we have to skip some bytes as we read raw data */
-			if (stuffp->xa && (0 == (stuffp->pending & 3))) {
-				const int HEAD =
-				    CD_FRAMESIZE_RAW - CD_XA_TAIL -
-				    CD_FRAMESIZE;
-				insb(stuffp->rreg_data, p, HEAD);
-			}
-
-			/* now actually read the data */
-			insb(stuffp->rreg_data, p, 512);
-
-			/* test if it's the last sector of a block,
-			 * if so, we have to handle XA special */
-			if ((3 == (stuffp->pending & 3)) && stuffp->xa) {
-				char dummy[CD_XA_TAIL];
-				insb(stuffp->rreg_data, &dummy[0], CD_XA_TAIL);
-			}
-
-			if (stuffp->pending == sector) {
-				p += 512;
-				done++;
-				sector++;
-			}
-		} while (++(stuffp->pending) < border);
-
-		stuffp->lock = 0;
-		wake_up_interruptible(&stuffp->lockq);
-
-	} else {
-
-		/* The requested sector(s) is/are out of the
-		 * already requested range, so we have to bother the drive
-		 * with a new request. */
-
-		static unsigned char cmd[] = {
-			0,
-			0, 0, 0,
-			0, 0, 0
-		};
-
-		cmd[0] = stuffp->readcmd;
-
-		/* The numbers held in ->pending, ..., should be valid */
-		stuffp->valid = 1;
-		stuffp->pending = sector & ~3;
-
-		/* do some sanity checks */
-		if (stuffp->pending > stuffp->lastsector) {
-			xwarn
-			    ("transfer() sector %d from nirvana requested.\n",
-			     stuffp->pending);
-			stuffp->status = MCDX_ST_EOM;
-			stuffp->valid = 0;
-			xtrace(XFER, "transfer() done (-1)\n");
-			return -1;
-		}
-
-		if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE)
-		    > stuffp->lastsector + 1) {
-			xtrace(XFER, "cut low_border\n");
-			stuffp->low_border = stuffp->lastsector + 1;
-		}
-		if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE)
-		    > stuffp->lastsector + 1) {
-			xtrace(XFER, "cut high_border\n");
-			stuffp->high_border = stuffp->lastsector + 1;
-		}
-
-		{		/* Convert the sector to be requested to MSF format */
-			struct cdrom_msf0 pending;
-			log2msf(stuffp->pending / 4, &pending);
-			cmd[1] = pending.minute;
-			cmd[2] = pending.second;
-			cmd[3] = pending.frame;
-		}
-
-		cmd[6] =
-		    (unsigned
-		     char) ((stuffp->high_border - stuffp->pending) / 4);
-		xtrace(XFER, "[%2d]\n", cmd[6]);
-
-		stuffp->busy = 1;
-		/* Now really issue the request command */
-		outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
-	}
-#ifdef AK2
-	if (stuffp->int_err) {
-		stuffp->valid = 0;
-		stuffp->int_err = 0;
-		return -1;
-	}
-#endif				/* AK2 */
-
-	stuffp->low_border = (stuffp->low_border +=
-			      done) <
-	    stuffp->high_border ? stuffp->low_border : stuffp->high_border;
-
-	return done;
-}
-
-
-/*	Access to elements of the mcdx_drive_map members */
-
-static unsigned port(int *ip)
-{
-	return ip[0];
-}
-static int irq(int *ip)
-{
-	return ip[1];
-}
-
-/*	Misc number converters */
-
-static unsigned int bcd2uint(unsigned char c)
-{
-	return (c >> 4) * 10 + (c & 0x0f);
-}
-
-static unsigned int uint2bcd(unsigned int ival)
-{
-	return ((ival / 10) << 4) | (ival % 10);
-}
-
-static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf)
-{
-	l += CD_MSF_OFFSET;
-	pmsf->minute = uint2bcd(l / 4500), l %= 4500;
-	pmsf->second = uint2bcd(l / 75);
-	pmsf->frame = uint2bcd(l % 75);
-}
-
-static unsigned int msf2log(const struct cdrom_msf0 *pmsf)
-{
-	return bcd2uint(pmsf->frame)
-	    + bcd2uint(pmsf->second) * 75
-	    + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET;
-}
-
-int mcdx_readtoc(struct s_drive_stuff *stuffp)
-/*  Read the toc entries from the CD,
- *  Return: -1 on failure, else 0 */
-{
-
-	if (stuffp->toc) {
-		xtrace(READTOC, "ioctl() toc already read\n");
-		return 0;
-	}
-
-	xtrace(READTOC, "ioctl() readtoc for %d tracks\n",
-	       stuffp->di.n_last - stuffp->di.n_first + 1);
-
-	if (-1 == mcdx_hold(stuffp, 1))
-		return -1;
-
-	xtrace(READTOC, "ioctl() tocmode\n");
-	if (-1 == mcdx_setdrivemode(stuffp, TOC, 1))
-		return -EIO;
-
-	/* all seems to be ok so far ... malloc */
-	{
-		int size;
-		size =
-		    sizeof(struct s_subqcode) * (stuffp->di.n_last -
-						 stuffp->di.n_first + 2);
-
-		xtrace(MALLOC, "ioctl() malloc %d bytes\n", size);
-		stuffp->toc = kmalloc(size, GFP_KERNEL);
-		if (!stuffp->toc) {
-			xwarn("Cannot malloc %d bytes for toc\n", size);
-			mcdx_setdrivemode(stuffp, DATA, 1);
-			return -EIO;
-		}
-	}
-
-	/* now read actually the index */
-	{
-		int trk;
-		int retries;
-
-		for (trk = 0;
-		     trk < (stuffp->di.n_last - stuffp->di.n_first + 1);
-		     trk++)
-			stuffp->toc[trk].index = 0;
-
-		for (retries = 300; retries; retries--) {	/* why 300? */
-			struct s_subqcode q;
-			unsigned int idx;
-
-			if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) {
-				mcdx_setdrivemode(stuffp, DATA, 1);
-				return -EIO;
-			}
-
-			idx = bcd2uint(q.index);
-
-			if ((idx > 0)
-			    && (idx <= stuffp->di.n_last)
-			    && (q.tno == 0)
-			    && (stuffp->toc[idx - stuffp->di.n_first].
-				index == 0)) {
-				stuffp->toc[idx - stuffp->di.n_first] = q;
-				xtrace(READTOC,
-				       "ioctl() toc idx %d (trk %d)\n",
-				       idx, trk);
-				trk--;
-			}
-			if (trk == 0)
-				break;
-		}
-		memset(&stuffp->
-		       toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0,
-		       sizeof(stuffp->toc[0]));
-		stuffp->toc[stuffp->di.n_last - stuffp->di.n_first +
-			    1].dt = stuffp->di.msf_leadout;
-	}
-
-	/* unset toc mode */
-	xtrace(READTOC, "ioctl() undo toc mode\n");
-	if (-1 == mcdx_setdrivemode(stuffp, DATA, 2))
-		return -EIO;
-
-#if MCDX_DEBUG && READTOC
-	{
-		int trk;
-		for (trk = 0;
-		     trk < (stuffp->di.n_last - stuffp->di.n_first + 2);
-		     trk++)
-			xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x"
-			       "  %02x:%02x.%02x  %02x:%02x.%02x\n",
-			       trk + stuffp->di.n_first,
-			       stuffp->toc[trk].control,
-			       stuffp->toc[trk].tno,
-			       stuffp->toc[trk].index,
-			       stuffp->toc[trk].tt.minute,
-			       stuffp->toc[trk].tt.second,
-			       stuffp->toc[trk].tt.frame,
-			       stuffp->toc[trk].dt.minute,
-			       stuffp->toc[trk].dt.second,
-			       stuffp->toc[trk].dt.frame);
-	}
-#endif
-
-	return 0;
-}
-
-static int
-mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf)
-{
-	unsigned char cmd[7] = {
-		0, 0, 0, 0, 0, 0, 0
-	};
-
-	if (!stuffp->readcmd) {
-		xinfo("Can't play from missing disk.\n");
-		return -1;
-	}
-
-	cmd[0] = stuffp->playcmd;
-
-	cmd[1] = msf->cdmsf_min0;
-	cmd[2] = msf->cdmsf_sec0;
-	cmd[3] = msf->cdmsf_frame0;
-	cmd[4] = msf->cdmsf_min1;
-	cmd[5] = msf->cdmsf_sec1;
-	cmd[6] = msf->cdmsf_frame1;
-
-	xtrace(PLAYMSF, "ioctl(): play %x "
-	       "%02x:%02x:%02x -- %02x:%02x:%02x\n",
-	       cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
-
-	outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
-	if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {
-		xwarn("playmsf() timeout\n");
-		return -1;
-	}
-
-	stuffp->audiostatus = CDROM_AUDIO_PLAY;
-	return 0;
-}
-
-static int
-mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti)
-{
-	struct s_subqcode *p;
-	struct cdrom_msf msf;
-
-	if (-1 == mcdx_readtoc(stuffp))
-		return -1;
-
-	if (ti)
-		p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first];
-	else
-		p = &stuffp->start;
-
-	msf.cdmsf_min0 = p->dt.minute;
-	msf.cdmsf_sec0 = p->dt.second;
-	msf.cdmsf_frame0 = p->dt.frame;
-
-	if (ti) {
-		p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1];
-		stuffp->stop = *p;
-	} else
-		p = &stuffp->stop;
-
-	msf.cdmsf_min1 = p->dt.minute;
-	msf.cdmsf_sec1 = p->dt.second;
-	msf.cdmsf_frame1 = p->dt.frame;
-
-	return mcdx_playmsf(stuffp, &msf);
-}
-
-
-/* Drive functions ************************************************/
-
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position)
-{
-	struct s_drive_stuff *stuffp = cdi->handle;
-
-	if (!stuffp->present)
-		return -ENXIO;
-	if (!(stuffp->present & DOOR))
-		return -ENOSYS;
-
-	if (position)		/* 1: eject */
-		return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3);
-	else			/* 0: close */
-		return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3);
-	return 1;
-}
-
-static int mcdx_stop(struct s_drive_stuff *stuffp, int tries)
-{
-	return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_hold(struct s_drive_stuff *stuffp, int tries)
-{
-	return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
-		     struct s_subqcode *sub, int tries)
-{
-	char buf[11];
-	int ans;
-
-	if (-1 == (ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf),
-				   2 * HZ, tries)))
-		return -1;
-	sub->control = buf[1];
-	sub->tno = buf[2];
-	sub->index = buf[3];
-	sub->tt.minute = buf[4];
-	sub->tt.second = buf[5];
-	sub->tt.frame = buf[6];
-	sub->dt.minute = buf[8];
-	sub->dt.second = buf[9];
-	sub->dt.frame = buf[10];
-
-	return ans;
-}
-
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp,
-			  struct s_multi *multi, int tries)
-{
-	char buf[5];
-	int ans;
-
-	if (stuffp->present & MULTI) {
-		ans =
-		    mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ,
-			      tries);
-		multi->multi = buf[1];
-		multi->msf_last.minute = buf[2];
-		multi->msf_last.second = buf[3];
-		multi->msf_last.frame = buf[4];
-		return ans;
-	} else {
-		multi->multi = 0;
-		return 0;
-	}
-}
-
-static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info,
-		    int tries)
-{
-	char buf[9];
-	int ans;
-	ans =
-	    mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries);
-	if (ans == -1) {
-		info->n_first = 0;
-		info->n_last = 0;
-	} else {
-		info->n_first = bcd2uint(buf[1]);
-		info->n_last = bcd2uint(buf[2]);
-		info->msf_leadout.minute = buf[3];
-		info->msf_leadout.second = buf[4];
-		info->msf_leadout.frame = buf[5];
-		info->msf_first.minute = buf[6];
-		info->msf_first.second = buf[7];
-		info->msf_first.frame = buf[8];
-	}
-	return ans;
-}
-
-static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode,
-		  int tries)
-{
-	char cmd[2];
-	int ans;
-
-	xtrace(HW, "setdrivemode() %d\n", mode);
-
-	if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries)))
-		return -1;
-
-	switch (mode) {
-	case TOC:
-		cmd[1] |= 0x04;
-		break;
-	case DATA:
-		cmd[1] &= ~0x04;
-		break;
-	case RAW:
-		cmd[1] |= 0x40;
-		break;
-	case COOKED:
-		cmd[1] &= ~0x40;
-		break;
-	default:
-		break;
-	}
-	cmd[0] = 0x50;
-	return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode,
-		 int tries)
-{
-	unsigned char cmd[2] = { 0xa0 };
-	xtrace(HW, "setdatamode() %d\n", mode);
-	switch (mode) {
-	case MODE0:
-		cmd[1] = 0x00;
-		break;
-	case MODE1:
-		cmd[1] = 0x01;
-		break;
-	case MODE2:
-		cmd[1] = 0x02;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_config(struct s_drive_stuff *stuffp, int tries)
-{
-	char cmd[4];
-
-	xtrace(HW, "config()\n");
-
-	cmd[0] = 0x90;
-
-	cmd[1] = 0x10;		/* irq enable */
-	cmd[2] = 0x05;		/* pre, err irq enable */
-
-	if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries))
-		return -1;
-
-	cmd[1] = 0x02;		/* dma select */
-	cmd[2] = 0x00;		/* no dma */
-
-	return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries);
-}
-
-static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver,
-		    int tries)
-{
-	char buf[3];
-	int ans;
-
-	if (-1 == (ans = mcdx_talk(stuffp, "\xdc",
-				   1, buf, sizeof(buf), 2 * HZ, tries)))
-		return ans;
-
-	ver->code = buf[1];
-	ver->ver = buf[2];
-
-	return ans;
-}
-
-static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
-{
-	if (mode == HARD) {
-		outb(0, stuffp->wreg_chn);	/* no dma, no irq -> hardware */
-		outb(0, stuffp->wreg_reset);	/* hw reset */
-		return 0;
-	} else
-		return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock)
-{
-	struct s_drive_stuff *stuffp = cdi->handle;
-	char cmd[2] = { 0xfe };
-
-	if (!(stuffp->present & DOOR))
-		return -ENOSYS;
-	if (stuffp->present & DOOR) {
-		cmd[1] = lock ? 0x01 : 0x00;
-		return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);
-	} else
-		return 0;
-}
-
-static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries)
-{
-	return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int
-mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf)
-{
-	unsigned long timeout = to + jiffies;
-	char c;
-
-	if (!buf)
-		buf = &c;
-
-	while (inb(stuffp->rreg_status) & MCDX_RBIT_STEN) {
-		if (time_after(jiffies, timeout))
-			return -1;
-		mcdx_delay(stuffp, delay);
-	}
-
-	*buf = (unsigned char) inb(stuffp->rreg_data) & 0xff;
-
-	return 0;
-}
-
-static int mcdx_setattentuator(struct s_drive_stuff *stuffp,
-		    struct cdrom_volctrl *vol, int tries)
-{
-	char cmd[5];
-	cmd[0] = 0xae;
-	cmd[1] = vol->channel0;
-	cmd[2] = 0;
-	cmd[3] = vol->channel1;
-	cmd[4] = 0;
-
-	return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_X_CDROM_MAJOR);
diff --git a/drivers/cdrom/mcdx.h b/drivers/cdrom/mcdx.h
deleted file mode 100644
index 83c364a..0000000
--- a/drivers/cdrom/mcdx.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Definitions for the Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: @VERSION@
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- *  The Linux Community at all and ...
- *  Martin Harris (he wrote the first Mitsumi Driver)
- *  Eberhard Moenkeberg (he gave me much support and the initial kick)
- *  Bernd Huebner, Ruediger Helsch (Unifix-Software Gmbh, they
- *      improved the original driver)
- *  Jon Tombs, Bjorn Ekwall (module support)
- *  Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- *  Gerd Knorr (he lent me his PhotoCD)
- *  Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- *  Andreas Kies (testing the mysterious hang up's)
- *  ... somebody forgotten?
- *  Marcin Dalecki
- *  
- */
-
-/*
- *	The following lines are for user configuration
- *	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *	{0|1} -- 1 if you want the driver detect your drive, may crash and
- *	needs a long time to seek.  The higher the address the longer the
- *	seek.
- *
- *  WARNING: AUTOPROBE doesn't work.
- */
-#define MCDX_AUTOPROBE 0
-
-/*
- *	Drive specific settings according to the jumpers on the controller
- *	board(s).
- *	o	MCDX_NDRIVES  :  number of used entries of the following table
- *	o	MCDX_DRIVEMAP :  table of {i/o base, irq} per controller
- *
- *	NOTE: I didn't get a drive at irq 9(2) working.  Not even alone.
- */
-#if MCDX_AUTOPROBE == 0
-	#define MCDX_NDRIVES 1
-	#define MCDX_DRIVEMAP {		\
-			{0x300, 11},	\
-			{0x304, 05},  	\
-			{0x000, 00},  	\
-			{0x000, 00},  	\
-			{0x000, 00},  	\
-	  	}
-#else
-	#error Autoprobing is not implemented yet.
-#endif
-
-#ifndef MCDX_QUIET
-#define MCDX_QUIET   1
-#endif
-
-#ifndef MCDX_DEBUG
-#define MCDX_DEBUG   0
-#endif
-
-/* *** make the following line uncommented, if you're sure,
- * *** all configuration is done */
-/* #define I_WAS_HERE */
-
-/*	The name of the device */
-#define MCDX "mcdx"	
-
-/* Flags for DEBUGGING */
-#define INIT 		0
-#define MALLOC 		0
-#define IOCTL 		0
-#define PLAYTRK     0
-#define SUBCHNL     0
-#define TOCHDR      0
-#define MS          0
-#define PLAYMSF     0
-#define READTOC     0
-#define OPENCLOSE 	0
-#define HW		    0
-#define TALK		0
-#define IRQ 		0
-#define XFER 		0
-#define REQUEST	 	0
-#define SLEEP		0
-
-/*	The following addresses are taken from the Mitsumi Reference 
- *  and describe the possible i/o range for the controller.
- */
-#define MCDX_IO_BEGIN	((char*) 0x300)	/* first base of i/o addr */
-#define MCDX_IO_END		((char*) 0x3fc)	/* last base of i/o addr */
-
-/*	Per controller 4 bytes i/o are needed. */
-#define MCDX_IO_SIZE		4
-
-/*
- *	Bits
- */
-
-/* The status byte, returned from every command, set if
- * the description is true */
-#define MCDX_RBIT_OPEN       0x80	/* door is open */
-#define MCDX_RBIT_DISKSET    0x40	/* disk set (recognised) */
-#define MCDX_RBIT_CHANGED    0x20	/* disk was changed */
-#define MCDX_RBIT_CHECK      0x10	/* disk rotates, servo is on */
-#define MCDX_RBIT_AUDIOTR    0x08   /* current track is audio */
-#define MCDX_RBIT_RDERR      0x04	/* read error, refer SENSE KEY */
-#define MCDX_RBIT_AUDIOBS    0x02	/* currently playing audio */
-#define MCDX_RBIT_CMDERR     0x01	/* command, param or format error */
-
-/* The I/O Register holding the h/w status of the drive,
- * can be read at i/o base + 1 */
-#define MCDX_RBIT_DOOR       0x10	/* door is open */
-#define MCDX_RBIT_STEN       0x04	/* if 0, i/o base contains drive status */
-#define MCDX_RBIT_DTEN       0x02	/* if 0, i/o base contains data */
-
-/*
- *	The commands.
- */
-
-#define OPCODE	1		/* offset of opcode */
-#define MCDX_CMD_REQUEST_TOC		1, 0x10
-#define MCDX_CMD_REQUEST_STATUS		1, 0x40 
-#define MCDX_CMD_RESET				1, 0x60
-#define MCDX_CMD_REQUEST_DRIVE_MODE	1, 0xc2
-#define MCDX_CMD_SET_INTERLEAVE		2, 0xc8, 0
-#define MCDX_CMD_DATAMODE_SET		2, 0xa0, 0
-	#define MCDX_DATAMODE1		0x01
-	#define MCDX_DATAMODE2		0x02
-#define MCDX_CMD_LOCK_DOOR		2, 0xfe, 0
-
-#define READ_AHEAD			4	/* 8 Sectors (4K) */
-
-/*	Useful macros */
-#define e_door(x)		((x) & MCDX_RBIT_OPEN)
-#define e_check(x)		(~(x) & MCDX_RBIT_CHECK)
-#define e_notset(x)		(~(x) & MCDX_RBIT_DISKSET)
-#define e_changed(x)	((x) & MCDX_RBIT_CHANGED)
-#define e_audio(x)		((x) & MCDX_RBIT_AUDIOTR)
-#define e_audiobusy(x)	((x) & MCDX_RBIT_AUDIOBS)
-#define e_cmderr(x)		((x) & MCDX_RBIT_CMDERR)
-#define e_readerr(x)	((x) & MCDX_RBIT_RDERR)
-
-/**	no drive specific */
-#define MCDX_CDBLK	2048	/* 2048 cooked data each blk */
-
-#define MCDX_DATA_TIMEOUT	(HZ/10)	/* 0.1 second */
-
-/*
- * Access to the msf array
- */
-#define MSF_MIN		0			/* minute */
-#define MSF_SEC		1			/* second */
-#define MSF_FRM		2			/* frame  */
-
-/*
- * Errors
- */
-#define MCDX_E		1			/* unspec error */
-#define MCDX_ST_EOM 0x0100		/* end of media */
-#define MCDX_ST_DRV 0x00ff		/* mask to query the drive status */
-
-#ifndef I_WAS_HERE
-#ifndef MODULE
-#warning You have not edited mcdx.h
-#warning Perhaps irq and i/o settings are wrong.
-#endif
-#endif
-
-/* ex:set ts=4 sw=4: */
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
deleted file mode 100644
index 3541690..0000000
--- a/drivers/cdrom/optcd.c
+++ /dev/null
@@ -1,2105 +0,0 @@
-/*	linux/drivers/cdrom/optcd.c - Optics Storage 8000 AT CDROM driver
-	$Id: optcd.c,v 1.11 1997/01/26 07:13:00 davem Exp $
-
-	Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
-	Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks
-	by Eberhard Moenkeberg (emoenke@gwdg.de). 
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2, or (at your option)
-	any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/*	Revision history
-
-
-	14-5-95		v0.0	Plays sound tracks. No reading of data CDs yet.
-				Detection of disk change doesn't work.
-	21-5-95		v0.1	First ALPHA version. CD can be mounted. The
-				device major nr is borrowed from the Aztech
-				driver. Speed is around 240 kb/s, as measured
-				with "time dd if=/dev/cdrom of=/dev/null \
-				bs=2048 count=4096".
-	24-6-95		v0.2	Reworked the #defines for the command codes
-				and the like, as well as the structure of
-				the hardware communication protocol, to
-				reflect the "official" documentation, kindly
-				supplied by C.K. Tan, Optics Storage Pte. Ltd.
-				Also tidied up the state machine somewhat.
-	28-6-95		v0.3	Removed the ISP-16 interface code, as this
-				should go into its own driver. The driver now
-				has its own major nr.
-				Disk change detection now seems to work, too.
-				This version became part of the standard
-				kernel as of version 1.3.7
-	24-9-95		v0.4	Re-inserted ISP-16 interface code which I
-				copied from sjcd.c, with a few changes.
-				Updated README.optcd. Submitted for
-				inclusion in 1.3.21
-	29-9-95		v0.4a	Fixed bug that prevented compilation as module
-	25-10-95	v0.5	Started multisession code. Implementation
-				copied from Werner Zimmermann, who copied it
-				from Heiko Schlittermann's mcdx.
-	17-1-96		v0.6	Multisession works; some cleanup too.
-	18-4-96		v0.7	Increased some timing constants;
-				thanks to Luke McFarlane. Also tidied up some
-				printk behaviour. ISP16 initialization
-				is now handled by a separate driver.
-				
-	09-11-99 	  	Make kernel-parameter implementation work with 2.3.x 
-	                 	Removed init_module & cleanup_module in favor of 
-			 	module_init & module_exit.
-			 	Torben Mathiasen <tmm@image.dk>
-*/
-
-/* Includes */
-
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <linux/blkdev.h>
-
-#include <linux/cdrom.h>
-#include "optcd.h"
-
-#include <asm/uaccess.h>
-
-#define MAJOR_NR OPTICS_CDROM_MAJOR
-#define QUEUE (opt_queue)
-#define CURRENT elv_next_request(opt_queue)
-
-
-/* Debug support */
-
-
-/* Don't forget to add new debug flags here. */
-#if DEBUG_DRIVE_IF | DEBUG_VFS | DEBUG_CONV | DEBUG_TOC | \
-    DEBUG_BUFFERS | DEBUG_REQUEST | DEBUG_STATE | DEBUG_MULTIS
-#define DEBUG(x) debug x
-static void debug(int debug_this, const char* fmt, ...)
-{
-	char s[1024];
-	va_list args;
-
-	if (!debug_this)
-		return;
-
-	va_start(args, fmt);
-	vsnprintf(s, sizeof(s), fmt, args);
-	printk(KERN_DEBUG "optcd: %s\n", s);
-	va_end(args);
-}
-#else
-#define DEBUG(x)
-#endif
-
-
-/* Drive hardware/firmware characteristics
-   Identifiers in accordance with Optics Storage documentation */
-
-
-#define optcd_port optcd			/* Needed for the modutils. */
-static short optcd_port = OPTCD_PORTBASE;	/* I/O base of drive. */
-module_param(optcd_port, short, 0);
-/* Drive registers, read */
-#define DATA_PORT	optcd_port	/* Read data/status */
-#define STATUS_PORT	optcd_port+1	/* Indicate data/status availability */
-
-/* Drive registers, write */
-#define COMIN_PORT	optcd_port	/* For passing command/parameter */
-#define RESET_PORT	optcd_port+1	/* Write anything and wait 0.5 sec */
-#define HCON_PORT	optcd_port+2	/* Host Xfer Configuration */
-
-
-/* Command completion/status read from DATA register */
-#define ST_DRVERR		0x80
-#define ST_DOOR_OPEN		0x40
-#define ST_MIXEDMODE_DISK	0x20
-#define ST_MODE_BITS		0x1c
-#define ST_M_STOP		0x00
-#define ST_M_READ		0x04
-#define ST_M_AUDIO		0x04
-#define ST_M_PAUSE		0x08
-#define ST_M_INITIAL		0x0c
-#define ST_M_ERROR		0x10
-#define ST_M_OTHERS		0x14
-#define	ST_MODE2TRACK		0x02
-#define	ST_DSK_CHG		0x01
-#define ST_L_LOCK		0x01
-#define ST_CMD_OK		0x00
-#define ST_OP_OK		0x01
-#define ST_PA_OK		0x02
-#define ST_OP_ERROR		0x05
-#define ST_PA_ERROR		0x06
-
-
-/* Error codes (appear as command completion code from DATA register) */
-/* Player related errors */
-#define ERR_ILLCMD	0x11	/* Illegal command to player module */
-#define ERR_ILLPARM	0x12	/* Illegal parameter to player module */
-#define ERR_SLEDGE	0x13
-#define ERR_FOCUS	0x14
-#define ERR_MOTOR	0x15
-#define ERR_RADIAL	0x16
-#define ERR_PLL		0x17	/* PLL lock error */
-#define ERR_SUB_TIM	0x18	/* Subcode timeout error */
-#define ERR_SUB_NF	0x19	/* Subcode not found error */
-#define ERR_TRAY	0x1a
-#define ERR_TOC		0x1b	/* Table of Contents read error */
-#define ERR_JUMP	0x1c
-/* Data errors */
-#define ERR_MODE	0x21
-#define ERR_FORM	0x22
-#define ERR_HEADADDR	0x23	/* Header Address not found */
-#define ERR_CRC		0x24
-#define ERR_ECC		0x25	/* Uncorrectable ECC error */
-#define ERR_CRC_UNC	0x26	/* CRC error and uncorrectable error */
-#define ERR_ILLBSYNC	0x27	/* Illegal block sync error */
-#define ERR_VDST	0x28	/* VDST not found */
-/* Timeout errors */
-#define ERR_READ_TIM	0x31	/* Read timeout error */
-#define ERR_DEC_STP	0x32	/* Decoder stopped */
-#define ERR_DEC_TIM	0x33	/* Decoder interrupt timeout error */
-/* Function abort codes */
-#define ERR_KEY		0x41	/* Key -Detected abort */
-#define ERR_READ_FINISH	0x42	/* Read Finish */
-/* Second Byte diagnostic codes */
-#define ERR_NOBSYNC	0x01	/* No block sync */
-#define ERR_SHORTB	0x02	/* Short block */
-#define ERR_LONGB	0x03	/* Long block */
-#define ERR_SHORTDSP	0x04	/* Short DSP word */
-#define ERR_LONGDSP	0x05	/* Long DSP word */
-
-
-/* Status availability flags read from STATUS register */
-#define FL_EJECT	0x20
-#define FL_WAIT		0x10	/* active low */
-#define FL_EOP		0x08	/* active low */
-#define FL_STEN		0x04	/* Status available when low */
-#define FL_DTEN		0x02	/* Data available when low */
-#define FL_DRQ		0x01	/* active low */
-#define FL_RESET	0xde	/* These bits are high after a reset */
-#define FL_STDT		(FL_STEN|FL_DTEN)
-
-
-/* Transfer mode, written to HCON register */
-#define HCON_DTS	0x08
-#define HCON_SDRQB	0x04
-#define HCON_LOHI	0x02
-#define HCON_DMA16	0x01
-
-
-/* Drive command set, written to COMIN register */
-/* Quick response commands */
-#define COMDRVST	0x20	/* Drive Status Read */
-#define COMERRST	0x21	/* Error Status Read */
-#define COMIOCTLISTAT	0x22	/* Status Read; reset disk changed bit */
-#define COMINITSINGLE	0x28	/* Initialize Single Speed */
-#define COMINITDOUBLE	0x29	/* Initialize Double Speed */
-#define COMUNLOCK	0x30	/* Unlock */
-#define COMLOCK		0x31	/* Lock */
-#define COMLOCKST	0x32	/* Lock/Unlock Status */
-#define COMVERSION	0x40	/* Get Firmware Revision */
-#define COMVOIDREADMODE	0x50	/* Void Data Read Mode */
-/* Read commands */
-#define COMFETCH	0x60	/* Prefetch Data */
-#define COMREAD		0x61	/* Read */
-#define COMREADRAW	0x62	/* Read Raw Data */
-#define COMREADALL	0x63	/* Read All 2646 Bytes */
-/* Player control commands */
-#define COMLEADIN	0x70	/* Seek To Lead-in */
-#define COMSEEK		0x71	/* Seek */
-#define COMPAUSEON	0x80	/* Pause On */
-#define COMPAUSEOFF	0x81	/* Pause Off */
-#define COMSTOP		0x82	/* Stop */
-#define COMOPEN		0x90	/* Open Tray Door */
-#define COMCLOSE	0x91	/* Close Tray Door */
-#define COMPLAY		0xa0	/* Audio Play */
-#define COMPLAY_TNO	0xa2	/* Audio Play By Track Number */
-#define COMSUBQ		0xb0	/* Read Sub-q Code */
-#define COMLOCATION	0xb1	/* Read Head Position */
-/* Audio control commands */
-#define COMCHCTRL	0xc0	/* Audio Channel Control */
-/* Miscellaneous (test) commands */
-#define COMDRVTEST	0xd0	/* Write Test Bytes */
-#define COMTEST		0xd1	/* Diagnostic Test */
-
-/* Low level drive interface. Only here we do actual I/O
-   Waiting for status / data available */
-
-
-/* Busy wait until FLAG goes low. Return 0 on timeout. */
-static inline int flag_low(int flag, unsigned long timeout)
-{
-	int flag_high;
-	unsigned long count = 0;
-
-	while ((flag_high = (inb(STATUS_PORT) & flag)))
-		if (++count >= timeout)
-			break;
-
-	DEBUG((DEBUG_DRIVE_IF, "flag_low 0x%x count %ld%s",
-		flag, count, flag_high ? " timeout" : ""));
-	return !flag_high;
-}
-
-
-/* Timed waiting for status or data */
-static int sleep_timeout;	/* max # of ticks to sleep */
-static DECLARE_WAIT_QUEUE_HEAD(waitq);
-static void sleep_timer(unsigned long data);
-static DEFINE_TIMER(delay_timer, sleep_timer, 0, 0);
-static DEFINE_SPINLOCK(optcd_lock);
-static struct request_queue *opt_queue;
-
-/* Timer routine: wake up when desired flag goes low,
-   or when timeout expires. */
-static void sleep_timer(unsigned long data)
-{
-	int flags = inb(STATUS_PORT) & FL_STDT;
-
-	if (flags == FL_STDT && --sleep_timeout > 0) {
-		mod_timer(&delay_timer, jiffies + HZ/100); /* multi-statement macro */
-	} else
-		wake_up(&waitq);
-}
-
-
-/* Sleep until FLAG goes low. Return 0 on timeout or wrong flag low. */
-static int sleep_flag_low(int flag, unsigned long timeout)
-{
-	int flag_high;
-
-	DEBUG((DEBUG_DRIVE_IF, "sleep_flag_low"));
-
-	sleep_timeout = timeout;
-	flag_high = inb(STATUS_PORT) & flag;
-	if (flag_high && sleep_timeout > 0) {
-		mod_timer(&delay_timer, jiffies + HZ/100);
-		sleep_on(&waitq);
-		flag_high = inb(STATUS_PORT) & flag;
-	}
-
-	DEBUG((DEBUG_DRIVE_IF, "flag 0x%x count %ld%s",
-		flag, timeout, flag_high ? " timeout" : ""));
-	return !flag_high;
-}
-
-/* Low level drive interface. Only here we do actual I/O
-   Sending commands and parameters */
-
-
-/* Errors in the command protocol */
-#define ERR_IF_CMD_TIMEOUT	0x100
-#define ERR_IF_ERR_TIMEOUT	0x101
-#define ERR_IF_RESP_TIMEOUT	0x102
-#define ERR_IF_DATA_TIMEOUT	0x103
-#define ERR_IF_NOSTAT		0x104
-
-
-/* Send command code. Return <0 indicates error */
-static int send_cmd(int cmd)
-{
-	unsigned char ack;
-
-	DEBUG((DEBUG_DRIVE_IF, "sending command 0x%02x\n", cmd));
-
-	outb(HCON_DTS, HCON_PORT);	/* Enable Suspend Data Transfer */
-	outb(cmd, COMIN_PORT);		/* Send command code */
-	if (!flag_low(FL_STEN, BUSY_TIMEOUT))	/* Wait for status */
-		return -ERR_IF_CMD_TIMEOUT;
-	ack = inb(DATA_PORT);		/* read command acknowledge */
-	outb(HCON_SDRQB, HCON_PORT);	/* Disable Suspend Data Transfer */
-	return ack==ST_OP_OK ? 0 : -ack;
-}
-
-
-/* Send command parameters. Return <0 indicates error */
-static int send_params(struct cdrom_msf *params)
-{
-	unsigned char ack;
-
-	DEBUG((DEBUG_DRIVE_IF, "sending parameters"
-		" %02x:%02x:%02x"
-		" %02x:%02x:%02x",
-		params->cdmsf_min0,
-		params->cdmsf_sec0,
-		params->cdmsf_frame0,
-		params->cdmsf_min1,
-		params->cdmsf_sec1,
-		params->cdmsf_frame1));
-
-	outb(params->cdmsf_min0, COMIN_PORT);
-	outb(params->cdmsf_sec0, COMIN_PORT);
-	outb(params->cdmsf_frame0, COMIN_PORT);
-	outb(params->cdmsf_min1, COMIN_PORT);
-	outb(params->cdmsf_sec1, COMIN_PORT);
-	outb(params->cdmsf_frame1, COMIN_PORT);
-	if (!flag_low(FL_STEN, BUSY_TIMEOUT))	/* Wait for status */
-		return -ERR_IF_CMD_TIMEOUT;
-	ack = inb(DATA_PORT);		/* read command acknowledge */
-	return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Send parameters for SEEK command. Return <0 indicates error */
-static int send_seek_params(struct cdrom_msf *params)
-{
-	unsigned char ack;
-
-	DEBUG((DEBUG_DRIVE_IF, "sending seek parameters"
-		" %02x:%02x:%02x",
-		params->cdmsf_min0,
-		params->cdmsf_sec0,
-		params->cdmsf_frame0));
-
-	outb(params->cdmsf_min0, COMIN_PORT);
-	outb(params->cdmsf_sec0, COMIN_PORT);
-	outb(params->cdmsf_frame0, COMIN_PORT);
-	if (!flag_low(FL_STEN, BUSY_TIMEOUT))	/* Wait for status */
-		return -ERR_IF_CMD_TIMEOUT;
-	ack = inb(DATA_PORT);		/* read command acknowledge */
-	return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Wait for command execution status. Choice between busy waiting
-   and sleeping. Return value <0 indicates timeout. */
-static inline int get_exec_status(int busy_waiting)
-{
-	unsigned char exec_status;
-
-	if (busy_waiting
-	    ? !flag_low(FL_STEN, BUSY_TIMEOUT)
-	    : !sleep_flag_low(FL_STEN, SLEEP_TIMEOUT))
-		return -ERR_IF_CMD_TIMEOUT;
-
-	exec_status = inb(DATA_PORT);
-	DEBUG((DEBUG_DRIVE_IF, "returned exec status 0x%02x", exec_status));
-	return exec_status;
-}
-
-
-/* Wait busy for extra byte of data that a command returns.
-   Return value <0 indicates timeout. */
-static inline int get_data(int short_timeout)
-{
-	unsigned char data;
-
-	if (!flag_low(FL_STEN, short_timeout ? FAST_TIMEOUT : BUSY_TIMEOUT))
-		return -ERR_IF_DATA_TIMEOUT;
-
-	data = inb(DATA_PORT);
-	DEBUG((DEBUG_DRIVE_IF, "returned data 0x%02x", data));
-	return data;
-}
-
-
-/* Returns 0 if failed */
-static int reset_drive(void)
-{
-	unsigned long count = 0;
-	int flags;
-
-	DEBUG((DEBUG_DRIVE_IF, "reset drive"));
-
-	outb(0, RESET_PORT);
-	while (++count < RESET_WAIT)
-		inb(DATA_PORT);
-
-	count = 0;
-	while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET)
-		if (++count >= BUSY_TIMEOUT)
-			break;
-
-	DEBUG((DEBUG_DRIVE_IF, "reset %s",
-		flags == FL_RESET ? "succeeded" : "failed"));
-
-	if (flags != FL_RESET)
-		return 0;		/* Reset failed */
-	outb(HCON_SDRQB, HCON_PORT);	/* Disable Suspend Data Transfer */
-	return 1;			/* Reset succeeded */
-}
-
-
-/* Facilities for asynchronous operation */
-
-/* Read status/data availability flags FL_STEN and FL_DTEN */
-static inline int stdt_flags(void)
-{
-	return inb(STATUS_PORT) & FL_STDT;
-}
-
-
-/* Fetch status that has previously been waited for. <0 means not available */
-static inline int fetch_status(void)
-{
-	unsigned char status;
-
-	if (inb(STATUS_PORT) & FL_STEN)
-		return -ERR_IF_NOSTAT;
-
-	status = inb(DATA_PORT);
-	DEBUG((DEBUG_DRIVE_IF, "fetched exec status 0x%02x", status));
-	return status;
-}
-
-
-/* Fetch data that has previously been waited for. */
-static inline void fetch_data(char *buf, int n)
-{
-	insb(DATA_PORT, buf, n);
-	DEBUG((DEBUG_DRIVE_IF, "fetched 0x%x bytes", n));
-}
-
-
-/* Flush status and data fifos */
-static inline void flush_data(void)
-{
-	while ((inb(STATUS_PORT) & FL_STDT) != FL_STDT)
-		inb(DATA_PORT);
-	DEBUG((DEBUG_DRIVE_IF, "flushed fifos"));
-}
-
-/* Command protocol */
-
-
-/* Send a simple command and wait for response. Command codes < COMFETCH
-   are quick response commands */
-static inline int exec_cmd(int cmd)
-{
-	int ack = send_cmd(cmd);
-	if (ack < 0)
-		return ack;
-	return get_exec_status(cmd < COMFETCH);
-}
-
-
-/* Send a command with parameters. Don't wait for the response,
- * which consists of data blocks read from the CD. */
-static inline int exec_read_cmd(int cmd, struct cdrom_msf *params)
-{
-	int ack = send_cmd(cmd);
-	if (ack < 0)
-		return ack;
-	return send_params(params);
-}
-
-
-/* Send a seek command with parameters and wait for response */
-static inline int exec_seek_cmd(int cmd, struct cdrom_msf *params)
-{
-	int ack = send_cmd(cmd);
-	if (ack < 0)
-		return ack;
-	ack = send_seek_params(params);
-	if (ack < 0)
-		return ack;
-	return 0;
-}
-
-
-/* Send a command with parameters and wait for response */
-static inline int exec_long_cmd(int cmd, struct cdrom_msf *params)
-{
-	int ack = exec_read_cmd(cmd, params);
-	if (ack < 0)
-		return ack;
-	return get_exec_status(0);
-}
-
-/* Address conversion routines */
-
-
-/* Binary to BCD (2 digits) */
-static inline void single_bin2bcd(u_char *p)
-{
-	DEBUG((DEBUG_CONV, "bin2bcd %02d", *p));
-	*p = (*p % 10) | ((*p / 10) << 4);
-}
-
-
-/* Convert entire msf struct */
-static void bin2bcd(struct cdrom_msf *msf)
-{
-	single_bin2bcd(&msf->cdmsf_min0);
-	single_bin2bcd(&msf->cdmsf_sec0);
-	single_bin2bcd(&msf->cdmsf_frame0);
-	single_bin2bcd(&msf->cdmsf_min1);
-	single_bin2bcd(&msf->cdmsf_sec1);
-	single_bin2bcd(&msf->cdmsf_frame1);
-}
-
-
-/* Linear block address to minute, second, frame form */
-#define CD_FPM	(CD_SECS * CD_FRAMES)	/* frames per minute */
-
-static void lba2msf(int lba, struct cdrom_msf *msf)
-{
-	DEBUG((DEBUG_CONV, "lba2msf %d", lba));
-	lba += CD_MSF_OFFSET;
-	msf->cdmsf_min0 = lba / CD_FPM; lba %= CD_FPM;
-	msf->cdmsf_sec0 = lba / CD_FRAMES;
-	msf->cdmsf_frame0 = lba % CD_FRAMES;
-	msf->cdmsf_min1 = 0;
-	msf->cdmsf_sec1 = 0;
-	msf->cdmsf_frame1 = 0;
-	bin2bcd(msf);
-}
-
-
-/* Two BCD digits to binary */
-static inline u_char bcd2bin(u_char bcd)
-{
-	DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd));
-	return (bcd >> 4) * 10 + (bcd & 0x0f);
-}
-
-
-static void msf2lba(union cdrom_addr *addr)
-{
-	addr->lba = addr->msf.minute * CD_FPM
-	            + addr->msf.second * CD_FRAMES
-	            + addr->msf.frame - CD_MSF_OFFSET;
-}
-
-
-/* Minute, second, frame address BCD to binary or to linear address,
-   depending on MODE */
-static void msf_bcd2bin(union cdrom_addr *addr)
-{
-	addr->msf.minute = bcd2bin(addr->msf.minute);
-	addr->msf.second = bcd2bin(addr->msf.second);
-	addr->msf.frame = bcd2bin(addr->msf.frame);
-}
-
-/* High level drive commands */
-
-
-static int audio_status = CDROM_AUDIO_NO_STATUS;
-static char toc_uptodate = 0;
-static char disk_changed = 1;
-
-/* Get drive status, flagging completion of audio play and disk changes. */
-static int drive_status(void)
-{
-	int status;
-
-	status = exec_cmd(COMIOCTLISTAT);
-	DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status));
-	if (status < 0)
-		return status;
-	if (status == 0xff)	/* No status available */
-		return -ERR_IF_NOSTAT;
-
-	if (((status & ST_MODE_BITS) != ST_M_AUDIO) &&
-		(audio_status == CDROM_AUDIO_PLAY)) {
-		audio_status = CDROM_AUDIO_COMPLETED;
-	}
-
-	if (status & ST_DSK_CHG) {
-		toc_uptodate = 0;
-		disk_changed = 1;
-		audio_status = CDROM_AUDIO_NO_STATUS;
-	}
-
-	return status;
-}
-
-
-/* Read the current Q-channel info. Also used for reading the
-   table of contents. qp->cdsc_format must be set on entry to
-   indicate the desired address format */
-static int get_q_channel(struct cdrom_subchnl *qp)
-{
-	int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
-
-	status = drive_status();
-	if (status < 0)
-		return status;
-	qp->cdsc_audiostatus = audio_status;
-
-	status = exec_cmd(COMSUBQ);
-	if (status < 0)
-		return status;
-
-	d1 = get_data(0);
-	if (d1 < 0)
-		return d1;
-	qp->cdsc_adr = d1;
-	qp->cdsc_ctrl = d1 >> 4;
-
-	d2 = get_data(0);
-	if (d2 < 0)
-		return d2;
-	qp->cdsc_trk = bcd2bin(d2);
-
-	d3 = get_data(0);
-	if (d3 < 0)
-		return d3;
-	qp->cdsc_ind = bcd2bin(d3);
-
-	d4 = get_data(0);
-	if (d4 < 0)
-		return d4;
-	qp->cdsc_reladdr.msf.minute = d4;
-
-	d5 = get_data(0);
-	if (d5 < 0)
-		return d5;
-	qp->cdsc_reladdr.msf.second = d5;
-
-	d6 = get_data(0);
-	if (d6 < 0)
-		return d6;
-	qp->cdsc_reladdr.msf.frame = d6;
-
-	d7 = get_data(0);
-	if (d7 < 0)
-		return d7;
-	/* byte not used */
-
-	d8 = get_data(0);
-	if (d8 < 0)
-		return d8;
-	qp->cdsc_absaddr.msf.minute = d8;
-
-	d9 = get_data(0);
-	if (d9 < 0)
-		return d9;
-	qp->cdsc_absaddr.msf.second = d9;
-
-	d10 = get_data(0);
-	if (d10 < 0)
-		return d10;
-	qp->cdsc_absaddr.msf.frame = d10;
-
-	DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
-		d1, d2, d3, d4, d5, d6, d7, d8, d9, d10));
-
-	msf_bcd2bin(&qp->cdsc_absaddr);
-	msf_bcd2bin(&qp->cdsc_reladdr);
-	if (qp->cdsc_format == CDROM_LBA) {
-		msf2lba(&qp->cdsc_absaddr);
-		msf2lba(&qp->cdsc_reladdr);
-	}
-
-	return 0;
-}
-
-/* Table of contents handling */
-
-
-/* Errors in table of contents */
-#define ERR_TOC_MISSINGINFO	0x120
-#define ERR_TOC_MISSINGENTRY	0x121
-
-
-struct cdrom_disk_info {
-	unsigned char		first;
-	unsigned char		last;
-	struct cdrom_msf0	disk_length;
-	struct cdrom_msf0	first_track;
-	/* Multisession info: */
-	unsigned char		next;
-	struct cdrom_msf0	next_session;
-	struct cdrom_msf0	last_session;
-	unsigned char		multi;
-	unsigned char		xa;
-	unsigned char		audio;
-};
-static struct cdrom_disk_info disk_info;
-
-#define MAX_TRACKS		111
-static struct cdrom_subchnl toc[MAX_TRACKS];
-
-#define QINFO_FIRSTTRACK	100 /* bcd2bin(0xa0) */
-#define QINFO_LASTTRACK		101 /* bcd2bin(0xa1) */
-#define QINFO_DISKLENGTH	102 /* bcd2bin(0xa2) */
-#define QINFO_NEXTSESSION	110 /* bcd2bin(0xb0) */
-
-#define I_FIRSTTRACK	0x01
-#define I_LASTTRACK	0x02
-#define I_DISKLENGTH	0x04
-#define I_NEXTSESSION	0x08
-#define I_ALL	(I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH)
-
-
-#if DEBUG_TOC
-static void toc_debug_info(int i)
-{
-	printk(KERN_DEBUG "#%3d ctl %1x, adr %1x, track %2d index %3d"
-		"  %2d:%02d.%02d %2d:%02d.%02d\n",
-		i, toc[i].cdsc_ctrl, toc[i].cdsc_adr,
-		toc[i].cdsc_trk, toc[i].cdsc_ind,
-		toc[i].cdsc_reladdr.msf.minute,
-		toc[i].cdsc_reladdr.msf.second,
-		toc[i].cdsc_reladdr.msf.frame,
-		toc[i].cdsc_absaddr.msf.minute,
-		toc[i].cdsc_absaddr.msf.second,
-		toc[i].cdsc_absaddr.msf.frame);
-}
-#endif
-
-
-static int read_toc(void)
-{
-	int status, limit, count;
-	unsigned char got_info = 0;
-	struct cdrom_subchnl q_info;
-#if DEBUG_TOC
-	int i;
-#endif
-
-	DEBUG((DEBUG_TOC, "starting read_toc"));
-
-	count = 0;
-	for (limit = 60; limit > 0; limit--) {
-		int index;
-
-		q_info.cdsc_format = CDROM_MSF;
-		status = get_q_channel(&q_info);
-		if (status < 0)
-			return status;
-
-		index = q_info.cdsc_ind;
-		if (index > 0 && index < MAX_TRACKS
-		    && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) {
-			toc[index] = q_info;
-			DEBUG((DEBUG_TOC, "got %d", index));
-			if (index < 100)
-				count++;
-
-			switch (q_info.cdsc_ind) {
-			case QINFO_FIRSTTRACK:
-				got_info |= I_FIRSTTRACK;
-				break;
-			case QINFO_LASTTRACK:
-				got_info |= I_LASTTRACK;
-				break;
-			case QINFO_DISKLENGTH:
-				got_info |= I_DISKLENGTH;
-				break;
-			case QINFO_NEXTSESSION:
-				got_info |= I_NEXTSESSION;
-				break;
-			}
-		}
-
-		if ((got_info & I_ALL) == I_ALL
-		    && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
-		       >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
-			break;
-	}
-
-	/* Construct disk_info from TOC */
-	if (disk_info.first == 0) {
-		disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
-		disk_info.first_track.minute =
-			toc[disk_info.first].cdsc_absaddr.msf.minute;
-		disk_info.first_track.second =
-			toc[disk_info.first].cdsc_absaddr.msf.second;
-		disk_info.first_track.frame =
-			toc[disk_info.first].cdsc_absaddr.msf.frame;
-	}
-	disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute;
-	disk_info.disk_length.minute =
-			toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute;
-	disk_info.disk_length.second =
-			toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2;
-	disk_info.disk_length.frame =
-			toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame;
-	disk_info.next_session.minute =
-			toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute;
-	disk_info.next_session.second =
-			toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second;
-	disk_info.next_session.frame =
-			toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame;
-	disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
-	disk_info.last_session.minute =
-			toc[disk_info.next].cdsc_absaddr.msf.minute;
-	disk_info.last_session.second =
-			toc[disk_info.next].cdsc_absaddr.msf.second;
-	disk_info.last_session.frame =
-			toc[disk_info.next].cdsc_absaddr.msf.frame;
-	toc[disk_info.last + 1].cdsc_absaddr.msf.minute =
-			disk_info.disk_length.minute;
-	toc[disk_info.last + 1].cdsc_absaddr.msf.second =
-			disk_info.disk_length.second;
-	toc[disk_info.last + 1].cdsc_absaddr.msf.frame =
-			disk_info.disk_length.frame;
-#if DEBUG_TOC
-	for (i = 1; i <= disk_info.last + 1; i++)
-		toc_debug_info(i);
-	toc_debug_info(QINFO_FIRSTTRACK);
-	toc_debug_info(QINFO_LASTTRACK);
-	toc_debug_info(QINFO_DISKLENGTH);
-	toc_debug_info(QINFO_NEXTSESSION);
-#endif
-
-	DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d",
-		got_info, count));
-	if ((got_info & I_ALL) != I_ALL
-	    || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
-	       < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
-		return -ERR_TOC_MISSINGINFO;
-	return 0;
-}
-
-
-#ifdef MULTISESSION
-static int get_multi_disk_info(void)
-{
-	int sessions, status;
-	struct cdrom_msf multi_index;
-
-
-	for (sessions = 2; sessions < 10 /* %%for now */; sessions++) {
-		int count;
-
-		for (count = 100; count < MAX_TRACKS; count++) 
-			toc[count].cdsc_ind = 0;
-
-		multi_index.cdmsf_min0 = disk_info.next_session.minute;
-		multi_index.cdmsf_sec0 = disk_info.next_session.second;
-		multi_index.cdmsf_frame0 = disk_info.next_session.frame;
-		if (multi_index.cdmsf_sec0 >= 20)
-			multi_index.cdmsf_sec0 -= 20;
-		else {
-			multi_index.cdmsf_sec0 += 40;
-			multi_index.cdmsf_min0--;
-		}
-		DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions,
-			multi_index.cdmsf_min0,
-			multi_index.cdmsf_sec0,
-			multi_index.cdmsf_frame0));
-		bin2bcd(&multi_index);
-		multi_index.cdmsf_min1 = 0;
-		multi_index.cdmsf_sec1 = 0;
-		multi_index.cdmsf_frame1 = 1;
-
-		status = exec_read_cmd(COMREAD, &multi_index);
-		if (status < 0) {
-			DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x",
-				-status));
-			break;
-		}
-		status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ?
-				0 : -ERR_TOC_MISSINGINFO;
-		flush_data();
-		if (status < 0) {
-			DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status));
-			break;
-		}
-
-		status = read_toc();
-		if (status < 0) {
-			DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
-			break;
-		}
-
-		disk_info.multi = 1;
-	}
-
-	exec_cmd(COMSTOP);
-
-	if (status < 0)
-		return -EIO;
-	return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int update_toc(void)
-{
-	int status, count;
-
-	if (toc_uptodate)
-		return 0;
-
-	DEBUG((DEBUG_TOC, "starting update_toc"));
-
-	disk_info.first = 0;
-	for (count = 0; count < MAX_TRACKS; count++) 
-		toc[count].cdsc_ind = 0;
-
-	status = exec_cmd(COMLEADIN);
-	if (status < 0)
-		return -EIO;
-
-	status = read_toc();
-	if (status < 0) {
-		DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
-		return -EIO;
-	}
-
-        /* Audio disk detection. Look at first track. */
-	disk_info.audio =
-		(toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1;
-
-	/* XA detection */
-	disk_info.xa = drive_status() & ST_MODE2TRACK;
-
-	/* Multisession detection: if we want this, define MULTISESSION */
-	disk_info.multi = 0;
-#ifdef MULTISESSION
- 	if (disk_info.xa)
-		get_multi_disk_info();	/* Here disk_info.multi is set */
-#endif /* MULTISESSION */
-	if (disk_info.multi)
-		printk(KERN_WARNING "optcd: Multisession support experimental, "
-			"see Documentation/cdrom/optcd\n");
-
-	DEBUG((DEBUG_TOC, "exiting update_toc"));
-
-	toc_uptodate = 1;
-	return 0;
-}
-
-/* Request handling */
-
-static int current_valid(void)
-{
-        return CURRENT &&
-		CURRENT->cmd == READ &&
-		CURRENT->sector != -1;
-}
-
-/* Buffers for block size conversion. */
-#define NOBUF		-1
-
-static char buf[CD_FRAMESIZE * N_BUFS];
-static volatile int buf_bn[N_BUFS], next_bn;
-static volatile int buf_in = 0, buf_out = NOBUF;
-
-static inline void opt_invalidate_buffers(void)
-{
-	int i;
-
-	DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers"));
-
-	for (i = 0; i < N_BUFS; i++)
-		buf_bn[i] = NOBUF;
-	buf_out = NOBUF;
-}
-
-
-/* Take care of the different block sizes between cdrom and Linux.
-   When Linux gets variable block sizes this will probably go away. */
-static void transfer(void)
-{
-#if DEBUG_BUFFERS | DEBUG_REQUEST
-	printk(KERN_DEBUG "optcd: executing transfer\n");
-#endif
-
-	if (!current_valid())
-		return;
-	while (CURRENT -> nr_sectors) {
-		int bn = CURRENT -> sector / 4;
-		int i, offs, nr_sectors;
-		for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i);
-
-		DEBUG((DEBUG_REQUEST, "found %d", i));
-
-		if (i >= N_BUFS) {
-			buf_out = NOBUF;
-			break;
-		}
-
-		offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
-		nr_sectors = 4 - (CURRENT -> sector & 3);
-
-		if (buf_out != i) {
-			buf_out = i;
-			if (buf_bn[i] != bn) {
-				buf_out = NOBUF;
-				continue;
-			}
-		}
-
-		if (nr_sectors > CURRENT -> nr_sectors)
-			nr_sectors = CURRENT -> nr_sectors;
-		memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512);
-		CURRENT -> nr_sectors -= nr_sectors;
-		CURRENT -> sector += nr_sectors;
-		CURRENT -> buffer += nr_sectors * 512;
-	}
-}
-
-
-/* State machine for reading disk blocks */
-
-enum state_e {
-	S_IDLE,		/* 0 */
-	S_START,	/* 1 */
-	S_READ,		/* 2 */
-	S_DATA,		/* 3 */
-	S_STOP,		/* 4 */
-	S_STOPPING	/* 5 */
-};
-
-static volatile enum state_e state = S_IDLE;
-#if DEBUG_STATE
-static volatile enum state_e state_old = S_STOP;
-static volatile int flags_old = 0;
-static volatile long state_n = 0;
-#endif
-
-
-/* Used as mutex to keep do_optcd_request (and other processes calling
-   ioctl) out while some process is inside a VFS call.
-   Reverse is accomplished by checking if state = S_IDLE upon entry
-   of opt_ioctl and opt_media_change. */
-static int in_vfs = 0;
-
-
-static volatile int transfer_is_active = 0;
-static volatile int error = 0;	/* %% do something with this?? */
-static int tries;		/* ibid?? */
-static int timeout = 0;
-
-static void poll(unsigned long data);
-static struct timer_list req_timer = {.function = poll};
-
-
-static void poll(unsigned long data)
-{
-	static volatile int read_count = 1;
-	int flags;
-	int loop_again = 1;
-	int status = 0;
-	int skip = 0;
-
-	if (error) {
-		printk(KERN_ERR "optcd: I/O error 0x%02x\n", error);
-		opt_invalidate_buffers();
-		if (!tries--) {
-			printk(KERN_ERR "optcd: read block %d failed;"
-				" Giving up\n", next_bn);
-			if (transfer_is_active)
-				loop_again = 0;
-			if (current_valid())
-				end_request(CURRENT, 0);
-			tries = 5;
-		}
-		error = 0;
-		state = S_STOP;
-	}
-
-	while (loop_again)
-	{
-		loop_again = 0; /* each case must flip this back to 1 if we want
-		                 to come back up here */
-
-#if DEBUG_STATE
-		if (state == state_old)
-			state_n++;
-		else {
-			state_old = state;
-			if (++state_n > 1)
-				printk(KERN_DEBUG "optcd: %ld times "
-					"in previous state\n", state_n);
-			printk(KERN_DEBUG "optcd: state %d\n", state);
-			state_n = 0;
-		}
-#endif
-
-		switch (state) {
-		case S_IDLE:
-			return;
-		case S_START:
-			if (in_vfs)
-				break;
-			if (send_cmd(COMDRVST)) {
-				state = S_IDLE;
-				while (current_valid())
-					end_request(CURRENT, 0);
-				return;
-			}
-			state = S_READ;
-			timeout = READ_TIMEOUT;
-			break;
-		case S_READ: {
-			struct cdrom_msf msf;
-			if (!skip) {
-				status = fetch_status();
-				if (status < 0)
-					break;
-				if (status & ST_DSK_CHG) {
-					toc_uptodate = 0;
-					opt_invalidate_buffers();
-				}
-			}
-			skip = 0;
-			if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
-				toc_uptodate = 0;
-				opt_invalidate_buffers();
-				printk(KERN_WARNING "optcd: %s\n",
-					(status & ST_DOOR_OPEN)
-					? "door open"
-					: "disk removed");
-				state = S_IDLE;
-				while (current_valid())
-					end_request(CURRENT, 0);
-				return;
-			}
-			if (!current_valid()) {
-				state = S_STOP;
-				loop_again = 1;
-				break;
-			}
-			next_bn = CURRENT -> sector / 4;
-			lba2msf(next_bn, &msf);
-			read_count = N_BUFS;
-			msf.cdmsf_frame1 = read_count; /* Not BCD! */
-
-			DEBUG((DEBUG_REQUEST, "reading %x:%x.%x %x:%x.%x",
-				msf.cdmsf_min0,
-				msf.cdmsf_sec0,
-				msf.cdmsf_frame0,
-				msf.cdmsf_min1,
-				msf.cdmsf_sec1,
-				msf.cdmsf_frame1));
-			DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d"
-				" buf_out:%d buf_bn:%d",
-				next_bn,
-				buf_in,
-				buf_out,
-				buf_bn[buf_in]));
-
-			exec_read_cmd(COMREAD, &msf);
-			state = S_DATA;
-			timeout = READ_TIMEOUT;
-			break;
-		}
-		case S_DATA:
-			flags = stdt_flags() & (FL_STEN|FL_DTEN);
-
-#if DEBUG_STATE
-			if (flags != flags_old) {
-				flags_old = flags;
-				printk(KERN_DEBUG "optcd: flags:%x\n", flags);
-			}
-			if (flags == FL_STEN)
-				printk(KERN_DEBUG "timeout cnt: %d\n", timeout);
-#endif
-
-			switch (flags) {
-			case FL_DTEN:		/* only STEN low */
-				if (!tries--) {
-					printk(KERN_ERR
-						"optcd: read block %d failed; "
-						"Giving up\n", next_bn);
-					if (transfer_is_active) {
-						tries = 0;
-						break;
-					}
-					if (current_valid())
-						end_request(CURRENT, 0);
-					tries = 5;
-				}
-				state = S_START;
-				timeout = READ_TIMEOUT;
-				loop_again = 1;
-			case (FL_STEN|FL_DTEN):	 /* both high */
-				break;
-			default:	/* DTEN low */
-				tries = 5;
-				if (!current_valid() && buf_in == buf_out) {
-					state = S_STOP;
-					loop_again = 1;
-					break;
-				}
-				if (read_count<=0)
-					printk(KERN_WARNING
-						"optcd: warning - try to read"
-						" 0 frames\n");
-				while (read_count) {
-					buf_bn[buf_in] = NOBUF;
-					if (!flag_low(FL_DTEN, BUSY_TIMEOUT)) {
-					/* should be no waiting here!?? */
-						printk(KERN_ERR
-						   "read_count:%d "
-						   "CURRENT->nr_sectors:%ld "
-						   "buf_in:%d\n",
-							read_count,
-							CURRENT->nr_sectors,
-							buf_in);
-						printk(KERN_ERR
-							"transfer active: %x\n",
-							transfer_is_active);
-						read_count = 0;
-						state = S_STOP;
-						loop_again = 1;
-						end_request(CURRENT, 0);
-						break;
-					}
-					fetch_data(buf+
-					    CD_FRAMESIZE*buf_in,
-					    CD_FRAMESIZE);
-					read_count--;
-
-					DEBUG((DEBUG_REQUEST,
-						"S_DATA; ---I've read data- "
-						"read_count: %d",
-						read_count));
-					DEBUG((DEBUG_REQUEST,
-						"next_bn:%d  buf_in:%d "
-						"buf_out:%d  buf_bn:%d",
-						next_bn,
-						buf_in,
-						buf_out,
-						buf_bn[buf_in]));
-
-					buf_bn[buf_in] = next_bn++;
-					if (buf_out == NOBUF)
-						buf_out = buf_in;
-					buf_in = buf_in + 1 ==
-						N_BUFS ? 0 : buf_in + 1;
-				}
-				if (!transfer_is_active) {
-					while (current_valid()) {
-						transfer();
-						if (CURRENT -> nr_sectors == 0)
-							end_request(CURRENT, 1);
-						else
-							break;
-					}
-				}
-
-				if (current_valid()
-				    && (CURRENT -> sector / 4 < next_bn ||
-				    CURRENT -> sector / 4 >
-				     next_bn + N_BUFS)) {
-					state = S_STOP;
-					loop_again = 1;
-					break;
-				}
-				timeout = READ_TIMEOUT;
-				if (read_count == 0) {
-					state = S_STOP;
-					loop_again = 1;
-					break;
-				}
-			}
-			break;
-		case S_STOP:
-			if (read_count != 0)
-				printk(KERN_ERR
-					"optcd: discard data=%x frames\n",
-					read_count);
-			flush_data();
-			if (send_cmd(COMDRVST)) {
-				state = S_IDLE;
-				while (current_valid())
-					end_request(CURRENT, 0);
-				return;
-			}
-			state = S_STOPPING;
-			timeout = STOP_TIMEOUT;
-			break;
-		case S_STOPPING:
-			status = fetch_status();
-			if (status < 0 && timeout)
-					break;
-			if ((status >= 0) && (status & ST_DSK_CHG)) {
-				toc_uptodate = 0;
-				opt_invalidate_buffers();
-			}
-			if (current_valid()) {
-				if (status >= 0) {
-					state = S_READ;
-					loop_again = 1;
-					skip = 1;
-					break;
-				} else {
-					state = S_START;
-					timeout = 1;
-				}
-			} else {
-				state = S_IDLE;
-				return;
-			}
-			break;
-		default:
-			printk(KERN_ERR "optcd: invalid state %d\n", state);
-			return;
-		} /* case */
-	} /* while */
-
-	if (!timeout--) {
-		printk(KERN_ERR "optcd: timeout in state %d\n", state);
-		state = S_STOP;
-		if (exec_cmd(COMSTOP) < 0) {
-			state = S_IDLE;
-			while (current_valid())
-				end_request(CURRENT, 0);
-			return;
-		}
-	}
-
-	mod_timer(&req_timer, jiffies + HZ/100);
-}
-
-
-static void do_optcd_request(request_queue_t * q)
-{
-	DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)",
-	       CURRENT -> sector, CURRENT -> nr_sectors));
-
-	if (disk_info.audio) {
-		printk(KERN_WARNING "optcd: tried to mount an Audio CD\n");
-		end_request(CURRENT, 0);
-		return;
-	}
-
-	transfer_is_active = 1;
-	while (current_valid()) {
-		transfer();	/* First try to transfer block from buffers */
-		if (CURRENT -> nr_sectors == 0) {
-			end_request(CURRENT, 1);
-		} else {	/* Want to read a block not in buffer */
-			buf_out = NOBUF;
-			if (state == S_IDLE) {
-				/* %% Should this block the request queue?? */
-				if (update_toc() < 0) {
-					while (current_valid())
-						end_request(CURRENT, 0);
-					break;
-				}
-				/* Start state machine */
-				state = S_START;
-				timeout = READ_TIMEOUT;
-				tries = 5;
-				/* %% why not start right away?? */
-				mod_timer(&req_timer, jiffies + HZ/100);
-			}
-			break;
-		}
-	}
-	transfer_is_active = 0;
-
-	DEBUG((DEBUG_REQUEST, "next_bn:%d  buf_in:%d buf_out:%d  buf_bn:%d",
-	       next_bn, buf_in, buf_out, buf_bn[buf_in]));
-	DEBUG((DEBUG_REQUEST, "do_optcd_request ends"));
-}
-
-/* IOCTLs */
-
-
-static char auto_eject = 0;
-
-static int cdrompause(void)
-{
-	int status;
-
-	if (audio_status != CDROM_AUDIO_PLAY)
-		return -EINVAL;
-
-	status = exec_cmd(COMPAUSEON);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status));
-		return -EIO;
-	}
-	audio_status = CDROM_AUDIO_PAUSED;
-	return 0;
-}
-
-
-static int cdromresume(void)
-{
-	int status;
-
-	if (audio_status != CDROM_AUDIO_PAUSED)
-		return -EINVAL;
-
-	status = exec_cmd(COMPAUSEOFF);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status));
-		audio_status = CDROM_AUDIO_ERROR;
-		return -EIO;
-	}
-	audio_status = CDROM_AUDIO_PLAY;
-	return 0;
-}
-
-
-static int cdromplaymsf(void __user *arg)
-{
-	int status;
-	struct cdrom_msf msf;
-
-	if (copy_from_user(&msf, arg, sizeof msf))
-		return -EFAULT;
-
-	bin2bcd(&msf);
-	status = exec_long_cmd(COMPLAY, &msf);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
-		audio_status = CDROM_AUDIO_ERROR;
-		return -EIO;
-	}
-
-	audio_status = CDROM_AUDIO_PLAY;
-	return 0;
-}
-
-
-static int cdromplaytrkind(void __user *arg)
-{
-	int status;
-	struct cdrom_ti ti;
-	struct cdrom_msf msf;
-
-	if (copy_from_user(&ti, arg, sizeof ti))
-		return -EFAULT;
-
-	if (ti.cdti_trk0 < disk_info.first
-	    || ti.cdti_trk0 > disk_info.last
-	    || ti.cdti_trk1 < ti.cdti_trk0)
-		return -EINVAL;
-	if (ti.cdti_trk1 > disk_info.last)
-		ti.cdti_trk1 = disk_info.last;
-
-	msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute;
-	msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second;
-	msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame;
-	msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute;
-	msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second;
-	msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame;
-
-	DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d",
-		msf.cdmsf_min0,
-		msf.cdmsf_sec0,
-		msf.cdmsf_frame0,
-		msf.cdmsf_min1,
-		msf.cdmsf_sec1,
-		msf.cdmsf_frame1));
-
-	bin2bcd(&msf);
-	status = exec_long_cmd(COMPLAY, &msf);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
-		audio_status = CDROM_AUDIO_ERROR;
-		return -EIO;
-	}
-
-	audio_status = CDROM_AUDIO_PLAY;
-	return 0;
-}
-
-
-static int cdromreadtochdr(void __user *arg)
-{
-	struct cdrom_tochdr tochdr;
-
-	tochdr.cdth_trk0 = disk_info.first;
-	tochdr.cdth_trk1 = disk_info.last;
-
-	return copy_to_user(arg, &tochdr, sizeof tochdr) ? -EFAULT : 0;
-}
-
-
-static int cdromreadtocentry(void __user *arg)
-{
-	struct cdrom_tocentry entry;
-	struct cdrom_subchnl *tocptr;
-
-	if (copy_from_user(&entry, arg, sizeof entry))
-		return -EFAULT;
-
-	if (entry.cdte_track == CDROM_LEADOUT)
-		tocptr = &toc[disk_info.last + 1];
-	else if (entry.cdte_track > disk_info.last
-		|| entry.cdte_track < disk_info.first)
-		return -EINVAL;
-	else
-		tocptr = &toc[entry.cdte_track];
-
-	entry.cdte_adr = tocptr->cdsc_adr;
-	entry.cdte_ctrl = tocptr->cdsc_ctrl;
-	entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute;
-	entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second;
-	entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame;
-	/* %% What should go into entry.cdte_datamode? */
-
-	if (entry.cdte_format == CDROM_LBA)
-		msf2lba(&entry.cdte_addr);
-	else if (entry.cdte_format != CDROM_MSF)
-		return -EINVAL;
-
-	return copy_to_user(arg, &entry, sizeof entry) ? -EFAULT : 0;
-}
-
-
-static int cdromvolctrl(void __user *arg)
-{
-	int status;
-	struct cdrom_volctrl volctrl;
-	struct cdrom_msf msf;
-
-	if (copy_from_user(&volctrl, arg, sizeof volctrl))
-		return -EFAULT;
-
-	msf.cdmsf_min0 = 0x10;
-	msf.cdmsf_sec0 = 0x32;
-	msf.cdmsf_frame0 = volctrl.channel0;
-	msf.cdmsf_min1 = volctrl.channel1;
-	msf.cdmsf_sec1 = volctrl.channel2;
-	msf.cdmsf_frame1 = volctrl.channel3;
-
-	status = exec_long_cmd(COMCHCTRL, &msf);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status));
-		return -EIO;
-	}
-	return 0;
-}
-
-
-static int cdromsubchnl(void __user *arg)
-{
-	int status;
-	struct cdrom_subchnl subchnl;
-
-	if (copy_from_user(&subchnl, arg, sizeof subchnl))
-		return -EFAULT;
-
-	if (subchnl.cdsc_format != CDROM_LBA
-	    && subchnl.cdsc_format != CDROM_MSF)
-		return -EINVAL;
-
-	status = get_q_channel(&subchnl);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status));
-		return -EIO;
-	}
-
-	if (copy_to_user(arg, &subchnl, sizeof subchnl))
-		return -EFAULT;
-	return 0;
-}
-
-
-static struct gendisk *optcd_disk;
-
-
-static int cdromread(void __user *arg, int blocksize, int cmd)
-{
-	int status;
-	struct cdrom_msf msf;
-
-	if (copy_from_user(&msf, arg, sizeof msf))
-		return -EFAULT;
-
-	bin2bcd(&msf);
-	msf.cdmsf_min1 = 0;
-	msf.cdmsf_sec1 = 0;
-	msf.cdmsf_frame1 = 1;	/* read only one frame */
-	status = exec_read_cmd(cmd, &msf);
-
-	DEBUG((DEBUG_VFS, "read cmd status 0x%x", status));
-
-	if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT))
-		return -EIO;
-
-	fetch_data(optcd_disk->private_data, blocksize);
-
-	if (copy_to_user(arg, optcd_disk->private_data, blocksize))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int cdromseek(void __user *arg)
-{
-	int status;
-	struct cdrom_msf msf;
-
-	if (copy_from_user(&msf, arg, sizeof msf))
-		return -EFAULT;
-
-	bin2bcd(&msf);
-	status = exec_seek_cmd(COMSEEK, &msf);
-
-	DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status));
-
-	if (status < 0)
-		return -EIO;
-	return 0;
-}
-
-
-#ifdef MULTISESSION
-static int cdrommultisession(void __user *arg)
-{
-	struct cdrom_multisession ms;
-
-	if (copy_from_user(&ms, arg, sizeof ms))
-		return -EFAULT;
-
-	ms.addr.msf.minute = disk_info.last_session.minute;
-	ms.addr.msf.second = disk_info.last_session.second;
-	ms.addr.msf.frame = disk_info.last_session.frame;
-
-	if (ms.addr_format != CDROM_LBA
-	   && ms.addr_format != CDROM_MSF)
-		return -EINVAL;
-	if (ms.addr_format == CDROM_LBA)
-		msf2lba(&ms.addr);
-
-	ms.xa_flag = disk_info.xa;
-
-  	if (copy_to_user(arg, &ms, sizeof(struct cdrom_multisession)))
-		return -EFAULT;
-
-#if DEBUG_MULTIS
- 	if (ms.addr_format == CDROM_MSF)
-               	printk(KERN_DEBUG
-			"optcd: multisession xa:%d, msf:%02d:%02d.%02d\n",
-			ms.xa_flag,
-			ms.addr.msf.minute,
-			ms.addr.msf.second,
-			ms.addr.msf.frame);
-	else
-		printk(KERN_DEBUG
-		    "optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n",
-			ms.xa_flag,
-			ms.addr.lba,
-			disk_info.last_session.minute,
-			disk_info.last_session.second,
-			disk_info.last_session.frame);
-#endif /* DEBUG_MULTIS */
-
-	return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int cdromreset(void)
-{
-	if (state != S_IDLE) {
-		error = 1;
-		tries = 0;
-	}
-
-	toc_uptodate = 0;
-	disk_changed = 1;
-	opt_invalidate_buffers();
-	audio_status = CDROM_AUDIO_NO_STATUS;
-
-	if (!reset_drive())
-		return -EIO;
-	return 0;
-}
-
-/* VFS calls */
-
-
-static int opt_ioctl(struct inode *ip, struct file *fp,
-                     unsigned int cmd, unsigned long arg)
-{
-	int status, err, retval = 0;
-	void __user *argp = (void __user *)arg;
-
-	DEBUG((DEBUG_VFS, "starting opt_ioctl"));
-
-	if (!ip)
-		return -EINVAL;
-
-	if (cmd == CDROMRESET)
-		return cdromreset();
-
-	/* is do_optcd_request or another ioctl busy? */
-	if (state != S_IDLE || in_vfs)
-		return -EBUSY;
-
-	in_vfs = 1;
-
-	status = drive_status();
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
-		in_vfs = 0;
-		return -EIO;
-	}
-
-	if (status & ST_DOOR_OPEN)
-		switch (cmd) {	/* Actions that can be taken with door open */
-		case CDROMCLOSETRAY:
-			/* We do this before trying to read the toc. */
-			err = exec_cmd(COMCLOSE);
-			if (err < 0) {
-				DEBUG((DEBUG_VFS,
-				       "exec_cmd COMCLOSE: %02x", -err));
-				in_vfs = 0;
-				return -EIO;
-			}
-			break;
-		default:	in_vfs = 0;
-				return -EBUSY;
-		}
-
-	err = update_toc();
-	if (err < 0) {
-		DEBUG((DEBUG_VFS, "update_toc: %02x", -err));
-		in_vfs = 0;
-		return -EIO;
-	}
-
-	DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd));
-
-	switch (cmd) {
-	case CDROMPAUSE:	retval = cdrompause(); break;
-	case CDROMRESUME:	retval = cdromresume(); break;
-	case CDROMPLAYMSF:	retval = cdromplaymsf(argp); break;
-	case CDROMPLAYTRKIND:	retval = cdromplaytrkind(argp); break;
-	case CDROMREADTOCHDR:	retval = cdromreadtochdr(argp); break;
-	case CDROMREADTOCENTRY:	retval = cdromreadtocentry(argp); break;
-
-	case CDROMSTOP:		err = exec_cmd(COMSTOP);
-				if (err < 0) {
-					DEBUG((DEBUG_VFS,
-						"exec_cmd COMSTOP: %02x",
-						-err));
-					retval = -EIO;
-				} else
-					audio_status = CDROM_AUDIO_NO_STATUS;
-				break;
-	case CDROMSTART:	break;	/* This is a no-op */
-	case CDROMEJECT:	err = exec_cmd(COMUNLOCK);
-				if (err < 0) {
-					DEBUG((DEBUG_VFS,
-						"exec_cmd COMUNLOCK: %02x",
-						-err));
-					retval = -EIO;
-					break;
-				}
-				err = exec_cmd(COMOPEN);
-				if (err < 0) {
-					DEBUG((DEBUG_VFS,
-						"exec_cmd COMOPEN: %02x",
-						-err));
-					retval = -EIO;
-				}
-				break;
-
-	case CDROMVOLCTRL:	retval = cdromvolctrl(argp); break;
-	case CDROMSUBCHNL:	retval = cdromsubchnl(argp); break;
-
-	/* The drive detects the mode and automatically delivers the
-	   correct 2048 bytes, so we don't need these IOCTLs */
-	case CDROMREADMODE2:	retval = -EINVAL; break;
-	case CDROMREADMODE1:	retval = -EINVAL; break;
-
-	/* Drive doesn't support reading audio */
-	case CDROMREADAUDIO:	retval = -EINVAL; break;
-
-	case CDROMEJECT_SW:	auto_eject = (char) arg;
-				break;
-
-#ifdef MULTISESSION
-	case CDROMMULTISESSION:	retval = cdrommultisession(argp); break;
-#endif
-
-	case CDROM_GET_MCN:	retval = -EINVAL; break; /* not implemented */
-	case CDROMVOLREAD:	retval = -EINVAL; break; /* not implemented */
-
-	case CDROMREADRAW:
-			/* this drive delivers 2340 bytes in raw mode */
-			retval = cdromread(argp, CD_FRAMESIZE_RAW1, COMREADRAW);
-			break;
-	case CDROMREADCOOKED:
-			retval = cdromread(argp, CD_FRAMESIZE, COMREAD);
-			break;
-	case CDROMREADALL:
-			retval = cdromread(argp, CD_FRAMESIZE_RAWER, COMREADALL);
-			break;
-
-	case CDROMSEEK:		retval = cdromseek(argp); break;
-	case CDROMPLAYBLK:	retval = -EINVAL; break; /* not implemented */
-	case CDROMCLOSETRAY:	break;	/* The action was taken earlier */
-	default:		retval = -EINVAL;
-	}
-	in_vfs = 0;
-	return retval;
-}
-
-
-static int open_count = 0;
-
-/* Open device special file; check that a disk is in. */
-static int opt_open(struct inode *ip, struct file *fp)
-{
-	DEBUG((DEBUG_VFS, "starting opt_open"));
-
-	if (!open_count && state == S_IDLE) {
-		int status;
-		char *buf;
-
-		buf = kmalloc(CD_FRAMESIZE_RAWER, GFP_KERNEL);
-		if (!buf) {
-			printk(KERN_INFO "optcd: cannot allocate read buffer\n");
-			return -ENOMEM;
-		}
-		optcd_disk->private_data = buf;		/* save read buffer */
-
-		toc_uptodate = 0;
-		opt_invalidate_buffers();
-
-		status = exec_cmd(COMCLOSE);	/* close door */
-		if (status < 0) {
-			DEBUG((DEBUG_VFS, "exec_cmd COMCLOSE: %02x", -status));
-		}
-
-		status = drive_status();
-		if (status < 0) {
-			DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
-			goto err_out;
-		}
-		DEBUG((DEBUG_VFS, "status: %02x", status));
-		if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
-			printk(KERN_INFO "optcd: no disk or door open\n");
-			goto err_out;
-		}
-		status = exec_cmd(COMLOCK);		/* Lock door */
-		if (status < 0) {
-			DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status));
-		}
-		status = update_toc();	/* Read table of contents */
-		if (status < 0)	{
-			DEBUG((DEBUG_VFS, "update_toc: %02x", -status));
-	 		status = exec_cmd(COMUNLOCK);	/* Unlock door */
-			if (status < 0) {
-				DEBUG((DEBUG_VFS,
-				       "exec_cmd COMUNLOCK: %02x", -status));
-			}
-			goto err_out;
-		}
-		open_count++;
-	}
-
-	DEBUG((DEBUG_VFS, "exiting opt_open"));
-
-	return 0;
-
-err_out:
-	return -EIO;
-}
-
-
-/* Release device special file; flush all blocks from the buffer cache */
-static int opt_release(struct inode *ip, struct file *fp)
-{
-	int status;
-
-	DEBUG((DEBUG_VFS, "executing opt_release"));
-	DEBUG((DEBUG_VFS, "inode: %p, device: %s, file: %p\n",
-		ip, ip->i_bdev->bd_disk->disk_name, fp));
-
-	if (!--open_count) {
-		toc_uptodate = 0;
-		opt_invalidate_buffers();
-	 	status = exec_cmd(COMUNLOCK);	/* Unlock door */
-		if (status < 0) {
-			DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status));
-		}
-		if (auto_eject) {
-			status = exec_cmd(COMOPEN);
-			DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status));
-		}
-		kfree(optcd_disk->private_data);
-		del_timer(&delay_timer);
-		del_timer(&req_timer);
-	}
-	return 0;
-}
-
-
-/* Check if disk has been changed */
-static int opt_media_change(struct gendisk *disk)
-{
-	DEBUG((DEBUG_VFS, "executing opt_media_change"));
-	DEBUG((DEBUG_VFS, "dev: %s; disk_changed = %d\n",
-			disk->disk_name, disk_changed));
-
-	if (disk_changed) {
-		disk_changed = 0;
-		return 1;
-	}
-	return 0;
-}
-
-/* Driver initialisation */
-
-
-/* Returns 1 if a drive is detected with a version string
-   starting with "DOLPHIN". Otherwise 0. */
-static int __init version_ok(void)
-{
-	char devname[100];
-	int count, i, ch, status;
-
-	status = exec_cmd(COMVERSION);
-	if (status < 0) {
-		DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status));
-		return 0;
-	}
-	if ((count = get_data(1)) < 0) {
-		DEBUG((DEBUG_VFS, "get_data(1): %02x", -count));
-		return 0;
-	}
-	for (i = 0, ch = -1; count > 0; count--) {
-		if ((ch = get_data(1)) < 0) {
-			DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch));
-			break;
-		}
-		if (i < 99)
-			devname[i++] = ch;
-	}
-	devname[i] = '\0';
-	if (ch < 0)
-		return 0;
-
-	printk(KERN_INFO "optcd: Device %s detected\n", devname);
-	return ((devname[0] == 'D')
-	     && (devname[1] == 'O')
-	     && (devname[2] == 'L')
-	     && (devname[3] == 'P')
-	     && (devname[4] == 'H')
-	     && (devname[5] == 'I')
-	     && (devname[6] == 'N'));
-}
-
-
-static struct block_device_operations opt_fops = {
-	.owner		= THIS_MODULE,
-	.open		= opt_open,
-	.release	= opt_release,
-	.ioctl		= opt_ioctl,
-	.media_changed	= opt_media_change,
-};
-
-#ifndef MODULE
-/* Get kernel parameter when used as a kernel driver */
-static int optcd_setup(char *str)
-{
-	int ints[4];
-	(void)get_options(str, ARRAY_SIZE(ints), ints);
-	
-	if (ints[0] > 0)
-		optcd_port = ints[1];
-
- 	return 1;
-}
-
-__setup("optcd=", optcd_setup);
-
-#endif /* MODULE */
-
-/* Test for presence of drive and initialize it. Called at boot time
-   or during module initialisation. */
-static int __init optcd_init(void)
-{
-	int status;
-
-	if (optcd_port <= 0) {
-		printk(KERN_INFO
-			"optcd: no Optics Storage CDROM Initialization\n");
-		return -EIO;
-	}
-	optcd_disk = alloc_disk(1);
-	if (!optcd_disk) {
-		printk(KERN_ERR "optcd: can't allocate disk\n");
-		return -ENOMEM;
-	}
-	optcd_disk->major = MAJOR_NR;
-	optcd_disk->first_minor = 0;
-	optcd_disk->fops = &opt_fops;
-	sprintf(optcd_disk->disk_name, "optcd");
-
-	if (!request_region(optcd_port, 4, "optcd")) {
-		printk(KERN_ERR "optcd: conflict, I/O port 0x%x already used\n",
-			optcd_port);
-		put_disk(optcd_disk);
-		return -EIO;
-	}
-
-	if (!reset_drive()) {
-		printk(KERN_ERR "optcd: drive at 0x%x not ready\n", optcd_port);
-		release_region(optcd_port, 4);
-		put_disk(optcd_disk);
-		return -EIO;
-	}
-	if (!version_ok()) {
-		printk(KERN_ERR "optcd: unknown drive detected; aborting\n");
-		release_region(optcd_port, 4);
-		put_disk(optcd_disk);
-		return -EIO;
-	}
-	status = exec_cmd(COMINITDOUBLE);
-	if (status < 0) {
-		printk(KERN_ERR "optcd: cannot init double speed mode\n");
-		release_region(optcd_port, 4);
-		DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
-		put_disk(optcd_disk);
-		return -EIO;
-	}
-	if (register_blkdev(MAJOR_NR, "optcd")) {
-		release_region(optcd_port, 4);
-		put_disk(optcd_disk);
-		return -EIO;
-	}
-
-
-	opt_queue = blk_init_queue(do_optcd_request, &optcd_lock);
-	if (!opt_queue) {
-		unregister_blkdev(MAJOR_NR, "optcd");
-		release_region(optcd_port, 4);
-		put_disk(optcd_disk);
-		return -ENOMEM;
-	}
-
-	blk_queue_hardsect_size(opt_queue, 2048);
-	optcd_disk->queue = opt_queue;
-	add_disk(optcd_disk);
-
-	printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
-	return 0;
-}
-
-
-static void __exit optcd_exit(void)
-{
-	del_gendisk(optcd_disk);
-	put_disk(optcd_disk);
-	if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
-		printk(KERN_ERR "optcd: what's that: can't unregister\n");
-		return;
-	}
-	blk_cleanup_queue(opt_queue);
-	release_region(optcd_port, 4);
-	printk(KERN_INFO "optcd: module released.\n");
-}
-
-module_init(optcd_init);
-module_exit(optcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(OPTICS_CDROM_MAJOR);
diff --git a/drivers/cdrom/optcd.h b/drivers/cdrom/optcd.h
deleted file mode 100644
index 1911bb9..0000000
--- a/drivers/cdrom/optcd.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*	linux/include/linux/optcd.h - Optics Storage 8000 AT CDROM driver
-	$Id: optcd.h,v 1.2 1996/01/15 18:43:44 root Exp root $
-
-	Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
-	Configuration file for linux/drivers/cdrom/optcd.c
-*/
-
-#ifndef _LINUX_OPTCD_H
-#define _LINUX_OPTCD_H
-
-
-/* I/O base of drive. Drive uses base to base+2.
-   This setting can be overridden with the kernel or insmod command
-   line option 'optcd=<portbase>'. Use address of 0 to disable driver. */
-#define OPTCD_PORTBASE	0x340
-
-
-/* enable / disable parts of driver by define / undef */
-#define	MULTISESSION		/* multisession support (ALPHA) */
-
-
-/* Change 0 to 1 to debug various parts of the driver */
-#define	DEBUG_DRIVE_IF	0	/* Low level drive interface */
-#define	DEBUG_CONV	0	/* Address conversions */
-#define	DEBUG_BUFFERS	0	/* Buffering and block size conversion */
-#define	DEBUG_REQUEST	0	/* Request mechanism */
-#define	DEBUG_STATE	0	/* State machine */
-#define	DEBUG_TOC	0	/* Q-channel and Table of Contents */
-#define	DEBUG_MULTIS	0	/* Multisession code */
-#define	DEBUG_VFS	0	/* VFS interface */
-
-
-/* Don't touch these unless you know what you're doing. */
-
-/* Various timeout loop repetition counts. */
-#define BUSY_TIMEOUT		10000000	/* for busy wait */
-#define FAST_TIMEOUT		100000		/* ibid. for probing */
-#define SLEEP_TIMEOUT		6000		/* for timer wait */
-#define MULTI_SEEK_TIMEOUT	1000		/* for timer wait */
-#define READ_TIMEOUT		6000		/* for poll wait */
-#define STOP_TIMEOUT		2000		/* for poll wait */
-#define RESET_WAIT		5000		/* busy wait at drive reset */
-
-/* # of buffers for block size conversion. 6 is optimal for my setup (P75),
-   giving 280 kb/s, with 0.4% CPU usage. Experiment to find your optimal
-   setting */
-#define N_BUFS		6
-
-
-#endif /* _LINUX_OPTCD_H */
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
deleted file mode 100644
index a1283b1..0000000
--- a/drivers/cdrom/sbpcd.c
+++ /dev/null
@@ -1,5966 +0,0 @@
-/*
- *  sbpcd.c   CD-ROM device driver for the whole family of traditional,
- *            non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives.
- *            Works with SoundBlaster compatible cards and with "no-sound"
- *            interface cards like Lasermate, Panasonic CI-101P, Teac, ...
- *            Also for the Longshine LCS-7260 drive.
- *            Also for the IBM "External ISA CD-Rom" drive.
- *            Also for the CreativeLabs CD200 drive.
- *            Also for the TEAC CD-55A drive.
- *            Also for the ECS-AT "Vertos 100" drive.
- *            Not for Sanyo drives (but for the H94A, sjcd is there...).
- *            Not for any other Funai drives than the CD200 types (sometimes
- *             labelled E2550UA or MK4015 or 2800F).
- */
-
-#define VERSION "v4.63 Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000"
-
-/*   Copyright (C) 1993, 1994, 1995  Eberhard Moenkeberg <emoenke@gwdg.de>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2, or (at your option)
- *   any later version.
- *
- *   You should have received a copy of the GNU General Public License
- *   (for example /usr/src/linux/COPYING); if not, write to the Free
- *   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *   If you change this software, you should mail a .diff file with some
- *   description lines to emoenke@gwdg.de. I want to know about it.
- *
- *   If you are the editor of a Linux CD, you should enable sbpcd.c within
- *   your boot floppy kernel and send me one of your CDs for free.
- *
- *   If you would like to port the driver to an other operating system (f.e.
- *   FreeBSD or NetBSD) or use it as an information source, you shall not be
- *   restricted by the GPL under the following conditions:
- *     a) the source code of your work is freely available
- *     b) my part of the work gets mentioned at all places where your 
- *        authorship gets mentioned
- *     c) I receive a copy of your code together with a full installation
- *        package of your operating system for free.
- *
- *
- *  VERSION HISTORY
- *
- *  0.1  initial release, April/May 93, after mcd.c (Martin Harriss)
- *
- *  0.2  thek "repeat:"-loop in do_sbpcd_request did not check for
- *       end-of-request_queue (resulting in kernel panic).
- *       Flow control seems stable, but throughput is not better.  
- *
- *  0.3  interrupt locking totally eliminated (maybe "inb" and "outb"
- *       are still locking) - 0.2 made keyboard-type-ahead losses.
- *       check_sbpcd_media_change added (to use by isofs/inode.c)
- *       - but it detects almost nothing.
- *
- *  0.4  use MAJOR 25 definitely.
- *       Almost total re-design to support double-speed drives and
- *       "naked" (no sound) interface cards ("LaserMate" interface type).
- *       Flow control should be exact now.
- *       Don't occupy the SbPro IRQ line (not needed either); will
- *       live together with Hannu Savolainen's sndkit now.
- *       Speeded up data transfer to 150 kB/sec, with help from Kai
- *       Makisara, the "provider" of the "mt" tape utility.
- *       Give "SpinUp" command if necessary.
- *       First steps to support up to 4 drives (but currently only one).
- *       Implemented audio capabilities - workman should work, xcdplayer
- *       gives some problems.
- *       This version is still consuming too much CPU time, and
- *       sleeping still has to be worked on.
- *       During "long" implied seeks, it seems possible that a 
- *       ReadStatus command gets ignored. That gives the message
- *       "ResponseStatus timed out" (happens about 6 times here during
- *       a "ls -alR" of the YGGDRASIL LGX-Beta CD). Such a case is
- *       handled without data error, but it should get done better.
- *
- *  0.5  Free CPU during waits (again with help from Kai Makisara).
- *       Made it work together with the LILO/kernel setup standard.
- *       Included auto-probing code, as suggested by YGGDRASIL.
- *       Formal redesign to add DDI debugging.
- *       There are still flaws in IOCTL (workman with double speed drive).
- *
- *  1.0  Added support for all drive IDs (0...3, no longer only 0)
- *       and up to 4 drives on one controller.
- *       Added "#define MANY_SESSION" for "old" multi session CDs.
- *
- *  1.1  Do SpinUp for new drives, too.
- *       Revised for clean compile under "old" kernels (0.99pl9).
- *
- *  1.2  Found the "workman with double-speed drive" bug: use the driver's
- *       audio_state, not what the drive is reporting with ReadSubQ.
- *
- *  1.3  Minor cleanups.
- *       Refinements regarding Workman.
- *
- *  1.4  Read XA disks (PhotoCDs) with "old" drives, too (but only the first
- *       session - no chance to fully access a "multi-session" CD).
- *       This currently still is too slow (50 kB/sec) - but possibly
- *       the old drives won't do it faster.
- *       Implemented "door (un)lock" for new drives (still does not work
- *       as wanted - no lock possible after an unlock).
- *       Added some debugging printout for the UPC/EAN code - but my drives 
- *       return only zeroes. Is there no UPC/EAN code written?
- *
- *  1.5  Laborate with UPC/EAN code (not better yet).
- *       Adapt to kernel 1.1.8 change (have to explicitly include
- *       <linux/string.h> now).
- *
- *  1.6  Trying to read audio frames as data. Impossible with the current
- *       drive firmware levels, as it seems. Awaiting any hint. ;-)
- *       Changed "door unlock": repeat it until success.
- *       Changed CDROMSTOP routine (stop somewhat "softer" so that Workman
- *       won't get confused).
- *       Added a third interface type: Sequoia S-1000, as used with the SPEA
- *       Media FX sound card. This interface (usable for Sony and Mitsumi 
- *       drives, too) needs a special configuration setup and behaves like a 
- *       LaserMate type after that. Still experimental - I do not have such
- *       an interface.
- *       Use the "variable BLOCK_SIZE" feature (2048). But it does only work
- *       if you give the mount option "block=2048".
- *       The media_check routine is currently disabled; now that it gets
- *       called as it should I fear it must get synchronized for not to
- *       disturb the normal driver's activity.
- *
- *  2.0  Version number bumped - two reasons:
- *       - reading audio tracks as data works now with CR-562 and CR-563. We
- *       currently do it by an IOCTL (yet has to get standardized), one frame
- *       at a time; that is pretty slow. But it works.
- *       - we are maintaining now up to 4 interfaces (each up to 4 drives):
- *       did it the easy way - a different MAJOR (25, 26, ...) and a different
- *       copy of the driver (sbpcd.c, sbpcd2.c, sbpcd3.c, sbpcd4.c - only
- *       distinguished by the value of SBPCD_ISSUE and the driver's name),
- *       and a common sbpcd.h file.
- *       Bettered the "ReadCapacity error" problem with old CR-52x drives (the
- *       drives sometimes need a manual "eject/insert" before work): just
- *       reset the drive and do again. Needs lots of resets here and sometimes
- *       that does not cure, so this can't be the solution.
- *
- *  2.1  Found bug with multisession CDs (accessing frame 16).
- *       "read audio" works now with address type CDROM_MSF, too.
- *       Bigger audio frame buffer: allows reading max. 4 frames at time; this
- *       gives a significant speedup, but reading more than one frame at once
- *       gives missing chunks at each single frame boundary.
- *
- *  2.2  Kernel interface cleanups: timers, init, setup, media check.
- *
- *  2.3  Let "door lock" and "eject" live together.
- *       Implemented "close tray" (done automatically during open).
- *
- *  2.4  Use different names for device registering.
- *
- *  2.5  Added "#if EJECT" code (default: enabled) to automatically eject
- *       the tray during last call to "sbpcd_release".
- *       Added "#if JUKEBOX" code (default: disabled) to automatically eject
- *       the tray during call to "sbpcd_open" if no disk is in.
- *       Turn on the CD volume of "compatible" sound cards, too; just define
- *       SOUND_BASE (in sbpcd.h) accordingly (default: disabled).
- *
- *  2.6  Nothing new.  
- *
- *  2.7  Added CDROMEJECT_SW ioctl to set the "EJECT" behavior on the fly:
- *       0 disables, 1 enables auto-ejecting. Useful to keep the tray in
- *       during shutdown.
- *
- *  2.8  Added first support (still BETA, I need feedback or a drive) for
- *       the Longshine LCS-7260 drives. They appear as double-speed drives
- *       using the "old" command scheme, extended by tray control and door
- *       lock functions.
- *       Found (and fixed preliminary) a flaw with some multisession CDs: we
- *       have to re-direct not only the accesses to frame 16 (the isofs
- *       routines drive it up to max. 100), but also those to the continuation
- *       (repetition) frames (as far as they exist - currently set fix as
- *       16..20).
- *       Changed default of the "JUKEBOX" define. If you use this default,
- *       your tray will eject if you try to mount without a disk in. Next
- *       mount command will insert the tray - so, just fill in a disk. ;-)
- *
- *  2.9  Fulfilled the Longshine LCS-7260 support; with great help and
- *       experiments by Serge Robyns.
- *       First attempts to support the TEAC CD-55A drives; but still not
- *       usable yet.
- *       Implemented the CDROMMULTISESSION ioctl; this is an attempt to handle
- *       multi session CDs more "transparent" (redirection handling has to be
- *       done within the isofs routines, and only for the special purpose of
- *       obtaining the "right" volume descriptor; accesses to the raw device
- *       should not get redirected).
- *
- *  3.0  Just a "normal" increment, with some provisions to do it better. ;-)
- *       Introduced "#define READ_AUDIO" to specify the maximum number of 
- *       audio frames to grab with one request. This defines a buffer size
- *       within kernel space; a value of 0 will reserve no such space and
- *       disable the CDROMREADAUDIO ioctl. A value of 75 enables the reading
- *       of a whole second with one command, but will use a buffer of more
- *       than 172 kB.
- *       Started CD200 support. Drive detection should work, but nothing
- *       more.
- *
- *  3.1  Working to support the CD200 and the Teac CD-55A drives.
- *       AT-BUS style device numbering no longer used: use SCSI style now.
- *       So, the first "found" device has MINOR 0, regardless of the
- *       jumpered drive ID. This implies modifications to the /dev/sbpcd*
- *       entries for some people, but will help the DAU (german TLA, english:
- *       "newbie", maybe ;-) to install his "first" system from a CD.
- *
- *  3.2  Still testing with CD200 and CD-55A drives.
- *
- *  3.3  Working with CD200 support.
- *
- *  3.4  Auto-probing stops if an address of 0 is seen (to be entered with
- *       the kernel command line).
- *       Made the driver "loadable". If used as a module, "audio copy" is
- *       disabled, and the internal read ahead data buffer has a reduced size
- *       of 4 kB; so, throughput may be reduced a little bit with slow CPUs.
- *
- *  3.5  Provisions to handle weird photoCDs which have an interrupted
- *       "formatting" immediately after the last frames of some files: simply
- *       never "read ahead" with MultiSession CDs. By this, CPU usage may be
- *       increased with those CDs, and there may be a loss in speed.
- *       Re-structured the messaging system.
- *       The "loadable" version no longer has a limited READ_AUDIO buffer
- *       size.
- *       Removed "MANY_SESSION" handling for "old" multi session CDs.
- *       Added "private" IOCTLs CDROMRESET and CDROMVOLREAD.
- *       Started again to support the TEAC CD-55A drives, now that I found
- *       the money for "my own" drive. ;-)
- *       The TEAC CD-55A support is fairly working now.
- *       I have measured that the drive "delivers" at 600 kB/sec (even with
- *       bigger requests than the drive's 64 kB buffer can satisfy), but
- *       the "real" rate does not exceed 520 kB/sec at the moment. 
- *       Caused by the various changes to build in TEAC support, the timed
- *       loops are de-optimized at the moment (less throughput with CR-52x
- *       drives, and the TEAC will give speed only with SBP_BUFFER_FRAMES 64).
- *
- *  3.6  Fixed TEAC data read problems with SbPro interfaces.
- *       Initial size of the READ_AUDIO buffer is 0. Can get set to any size
- *       during runtime.
- *
- *  3.7  Introduced MAX_DRIVES for some poor interface cards (seen with TEAC
- *       drives) which allow only one drive (ID 0); this avoids repetitive
- *       detection under IDs 1..3. 
- *       Elongated cmd_out_T response waiting; necessary for photo CDs with
- *       a lot of sessions.
- *       Bettered the sbpcd_open() behavior with TEAC drives.
- *
- *  3.8  Elongated max_latency for CR-56x drives.
- *
- *  3.9  Finally fixed the long-known SoundScape/SPEA/Sequoia S-1000 interface
- *       configuration bug.
- *       Now Corey, Heiko, Ken, Leo, Vadim/Eric & Werner are invited to copy
- *       the config_spea() routine into their drivers. ;-)
- *
- *  4.0  No "big step" - normal version increment.
- *       Adapted the benefits from 1.3.33.
- *       Fiddled with CDROMREADAUDIO flaws.
- *       Avoid ReadCapacity command with CD200 drives (the MKE 1.01 version
- *       seems not to support it).
- *       Fulfilled "read audio" for CD200 drives, with help of Pete Heist
- *       (heistp@rpi.edu).
- *
- *  4.1  Use loglevel KERN_INFO with printk().
- *       Added support for "Vertos 100" drive ("ECS-AT") - it is very similar
- *       to the Longshine LCS-7260. Give feedback if you can - I never saw
- *       such a drive, and I have no specs.
- *
- *  4.2  Support for Teac 16-bit interface cards. Can't get auto-detected,
- *       so you have to jumper your card to 0x2C0. Still not 100% - come
- *       in contact if you can give qualified feedback.
- *       Use loglevel KERN_NOTICE with printk(). If you get annoyed by a
- *       flood of unwanted messages and the accompanied delay, try to read
- *       my documentation. Especially the Linux CDROM drivers have to do an
- *       important job for the newcomers, so the "distributed" version has
- *       to fit some special needs. Since generations, the flood of messages
- *       is user-configurable (even at runtime), but to get aware of this, one
- *       needs a special mental quality: the ability to read.
- *       
- *  4.3  CD200F does not like to receive a command while the drive is
- *       reading the ToC; still trying to solve it.
- *       Removed some redundant verify_area calls (yes, Heiko Eissfeldt
- *       is visiting all the Linux CDROM drivers ;-).
- *       
- *  4.4  Adapted one idea from tiensivu@pilot.msu.edu's "stripping-down"
- *       experiments: "KLOGD_PAUSE".
- *       Inhibited "play audio" attempts with data CDs. Provisions for a
- *       "data-safe" handling of "mixed" (data plus audio) Cds.
- *
- *  4.5  Meanwhile Gonzalo Tornaria <tornaria@cmat.edu.uy> (GTL) built a
- *       special end_request routine: we seem to have to take care for not
- *       to have two processes working at the request list. My understanding
- *       was and is that ll_rw_blk should not call do_sbpcd_request as long
- *       as there is still one call active (the first call will care for all
- *       outstanding I/Os, and if a second call happens, that is a bug in
- *       ll_rw_blk.c).
- *       "Check media change" without touching any drive.
- *
- *  4.6  Use a semaphore to synchronize multi-activity; elaborated by Rob
- *       Riggs <rriggs@tesser.com>. At the moment, we simply block "read"
- *       against "ioctl" and vice versa. This could be refined further, but
- *       I guess with almost no performance increase.
- *       Experiments to speed up the CD-55A; again with help of Rob Riggs
- *       (to be true, he gave both, idea & code. ;-)
- *
- *  4.61 Ported to Uniform CD-ROM driver by 
- *       Heiko Eissfeldt <heiko@colossus.escape.de> with additional
- *       changes by Erik Andersen <andersee@debian.org>
- *
- *  4.62 Fix a bug where playing audio left the drive in an unusable state.
- *         Heiko Eissfeldt <heiko@colossus.escape.de>
- *
- *  November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	             Removed init_module & cleanup_module in favor of 
- *	             module_init & module_exit.
- *	             Torben Mathiasen <tmm@image.dk>
- *
- *  4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer.
- *		Annoying things fixed:
- *		TOC reread on automated disk changes
- *		TOC reread on manual cd changes
- *		Play IOCTL tries to play CD before it's actually ready... sometimes.
- *		CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play.
- *		Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000
- *
- *  4.64 Fix module parameters - were being completely ignored.
- *	 Can also specify max_drives=N as a setup int to get rid of
- *	 "ghost" drives on crap hardware (aren't they all?)   Paul Gortmaker
- *
- *  TODO
- *     implement "read all subchannel data" (96 bytes per frame)
- *     remove alot of the virtual status bits and deal with hardware status
- *     move the change of cd for audio to a better place
- *     add debug levels to insmod parameters (trivial)
- *
- *     special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine
- *     elaborated speed-up experiments (and the fabulous results!), for
- *     the "push" towards load-free wait loops, and for the extensive mail
- *     thread which brought additional hints and bug fixes.
- *
- */
-
-/*
- * Trying to merge requests breaks this driver horribly (as in it goes
- * boom and apparently has done so since 2.3.41).  As it is a legacy
- * driver for a horribly slow double speed CD on a hideous interface
- * designed for polled operation, I won't lose any sleep in simply
- * disallowing merging.				Paul G.  02/2001
- *
- * Thu May 30 14:14:47 CEST 2002:
- *
- * I have presumably found the reson for the above - there was a bogous
- * end_request substitute, which was manipulating the request queues
- * incorrectly. If someone has access to the actual hardware, and it's
- * still operations - well  please free to test it.
- *
- * Marcin Dalecki
- */
-
-/*
- * Add bio/kdev_t changes for 2.5.x required to make it work again. 
- * Still room for improvement in the request handling here if anyone
- * actually cares.  Bring your own chainsaw.    Paul G.  02/2002
- */
-
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <stdarg.h>
-#include "sbpcd.h"
-
-#define MAJOR_NR MATSUSHITA_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-/*==========================================================================*/
-#if SBPCD_DIS_IRQ
-# define SBPCD_CLI cli()
-# define SBPCD_STI sti()
-#else
-# define SBPCD_CLI
-# define SBPCD_STI
-#endif
-
-/*==========================================================================*/
-/*
- * auto-probing address list
- * inspired by Adam J. Richter from Yggdrasil
- *
- * still not good enough - can cause a hang.
- *   example: a NE 2000 ethernet card at 300 will cause a hang probing 310.
- * if that happens, reboot and use the LILO (kernel) command line.
- * The possibly conflicting ethernet card addresses get NOT probed 
- * by default - to minimize the hang possibilities. 
- *
- * The SB Pro addresses get "mirrored" at 0x6xx and some more locations - to
- * avoid a type error, the 0x2xx-addresses must get checked before 0x6xx.
- *
- * send mail to emoenke@gwdg.de if your interface card is not FULLY
- * represented here.
- */
-static int sbpcd[] =
-{
-	CDROM_PORT, SBPRO, /* probe with user's setup first */
-#if DISTRIBUTION
-	0x230, 1, /* Soundblaster Pro and 16 (default) */
-#if 0
-	0x300, 0, /* CI-101P (default), WDH-7001C (default),
-		     Galaxy (default), Reveal (one default) */
-	0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */
-	0x2C0, 3, /* Teac 16-bit cards */
-	0x260, 1, /* OmniCD */
-	0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default),
-		     Longshine LCS-6853 (default) */
-	0x338, 0, /* Reveal Sound Wave 32 card model #SC600 */
-	0x340, 0, /* Mozart sound card (default), Lasermate, CI-101P */
-	0x360, 0, /* Lasermate, CI-101P */
-	0x270, 1, /* Soundblaster 16 */
-	0x670, 0, /* "sound card #9" */
-	0x690, 0, /* "sound card #9" */
-	0x338, 2, /* SPEA Media FX, Ensonic SoundScape (default) */
-	0x328, 2, /* SPEA Media FX */
-	0x348, 2, /* SPEA Media FX */
-	0x634, 0, /* some newer sound cards */
-	0x638, 0, /* some newer sound cards */
-	0x230, 1, /* some newer sound cards */
-	/* due to incomplete address decoding of the SbPro card, these must be last */
-	0x630, 0, /* "sound card #9" (default) */
-	0x650, 0, /* "sound card #9" */
-#ifdef MODULE
-	/*
-	 * some "hazardous" locations (no harm with the loadable version)
-	 * (will stop the bus if a NE2000 ethernet card resides at offset -0x10)
-	 */
-	0x330, 0, /* Lasermate, CI-101P, WDH-7001C */
-	0x350, 0, /* Lasermate, CI-101P */
-	0x358, 2, /* SPEA Media FX */
-	0x370, 0, /* Lasermate, CI-101P */
-	0x290, 1, /* Soundblaster 16 */
-	0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
-#endif /* MODULE */
-#endif
-#endif /* DISTRIBUTION */
-};
-
-/*
- * Protects access to global structures etc.
- */
-static  __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock);
-static struct request_queue *sbpcd_queue;
-
-/* You can only set the first pair, from old MODULE_PARM code.  */
-static int sbpcd_set(const char *val, struct kernel_param *kp)
-{
-	get_options((char *)val, 2, (int *)sbpcd);
-	return 0;
-}
-module_param_call(sbpcd, sbpcd_set, NULL, NULL, 0);
-
-#define NUM_PROBE  (sizeof(sbpcd) / sizeof(int))
-
-/*==========================================================================*/
-
-#define INLINE inline
-
-/*==========================================================================*/
-/*
- * the forward references:
- */
-static void sbp_sleep(u_int);
-static void mark_timeout_delay(u_long);
-static void mark_timeout_data(u_long);
-#if 0
-static void mark_timeout_audio(u_long);
-#endif
-static void sbp_read_cmd(struct request *req);
-static int sbp_data(struct request *req);
-static int cmd_out(void);
-static int DiskInfo(void);
-
-/*==========================================================================*/
-
-/*
- * pattern for printk selection:
- *
- * (1<<DBG_INF)  necessary information
- * (1<<DBG_BSZ)  BLOCK_SIZE trace
- * (1<<DBG_REA)  "read" status trace
- * (1<<DBG_CHK)  "media check" trace
- * (1<<DBG_TIM)  datarate timer test
- * (1<<DBG_INI)  initialization trace
- * (1<<DBG_TOC)  tell TocEntry values
- * (1<<DBG_IOC)  ioctl trace
- * (1<<DBG_STA)  "ResponseStatus" trace
- * (1<<DBG_ERR)  "cc_ReadError" trace
- * (1<<DBG_CMD)  "cmd_out" trace
- * (1<<DBG_WRN)  give explanation before auto-probing
- * (1<<DBG_MUL)  multi session code test
- * (1<<DBG_IDX)  "drive_id != 0" test code
- * (1<<DBG_IOX)  some special information
- * (1<<DBG_DID)  drive ID test
- * (1<<DBG_RES)  drive reset info
- * (1<<DBG_SPI)  SpinUp test info
- * (1<<DBG_IOS)  ioctl trace: "subchannel"
- * (1<<DBG_IO2)  ioctl trace: general
- * (1<<DBG_UPC)  show UPC info
- * (1<<DBG_XA1)  XA mode debugging
- * (1<<DBG_LCK)  door (un)lock info
- * (1<<DBG_SQ1)   dump SubQ frame
- * (1<<DBG_AUD)  "read audio" debugging
- * (1<<DBG_SEQ)  Sequoia interface configuration trace
- * (1<<DBG_LCS)  Longshine LCS-7260 debugging trace
- * (1<<DBG_CD2)  MKE/Funai CD200 debugging trace
- * (1<<DBG_TEA)  TEAC CD-55A debugging trace
- * (1<<DBG_ECS)  ECS-AT (Vertos-100) debugging trace
- * (1<<DBG_000)  unnecessary information
- */
-#if DISTRIBUTION
-static int sbpcd_debug = (1<<DBG_INF);
-#else
-static int sbpcd_debug = 0 & ((1<<DBG_INF) |
-			  (1<<DBG_TOC) |
-			  (1<<DBG_MUL) |
-			  (1<<DBG_UPC));
-#endif /* DISTRIBUTION */
-
-static int sbpcd_ioaddr = CDROM_PORT;	/* default I/O base address */
-static int sbpro_type = SBPRO;
-static unsigned char f_16bit;
-static unsigned char do_16bit;
-static int CDo_command, CDo_reset;
-static int CDo_sel_i_d, CDo_enable;
-static int CDi_info, CDi_status, CDi_data;
-static struct cdrom_msf msf;
-static struct cdrom_ti ti;
-static struct cdrom_tochdr tochdr;
-static struct cdrom_tocentry tocentry;
-static struct cdrom_subchnl SC;
-static struct cdrom_volctrl volctrl;
-static struct cdrom_read_audio read_audio;
-
-static unsigned char msgnum;
-static char msgbuf[80];
-
-static int max_drives = MAX_DRIVES;
-module_param(max_drives, int, 0);
-#ifndef MODULE
-static unsigned char setup_done;
-static const char *str_sb_l = "soundblaster";
-static const char *str_sp_l = "spea";
-static const char *str_ss_l = "soundscape";
-static const char *str_t16_l = "teac16bit";
-static const char *str_ss = "SoundScape";
-#endif
-static const char *str_sb = "SoundBlaster";
-static const char *str_lm = "LaserMate";
-static const char *str_sp = "SPEA";
-static const char *str_t16 = "Teac16bit";
-static const char *type;
-static const char *major_name="sbpcd";
-
-/*==========================================================================*/
-
-#ifdef FUTURE
-static DECLARE_WAIT_QUEUE_HEAD(sbp_waitq);
-#endif /* FUTURE */
-
-static int teac=SBP_TEAC_SPEED;
-static int buffers=SBP_BUFFER_FRAMES;
-
-static u_char family0[]="MATSHITA"; /* MKE CR-521, CR-522, CR-523 */
-static u_char family1[]="CR-56";    /* MKE CR-562, CR-563 */
-static u_char family2[]="CD200";    /* MKE CD200, Funai CD200F */
-static u_char familyL[]="LCS-7260"; /* Longshine LCS-7260 */
-static u_char familyT[]="CD-55";    /* TEAC CD-55A */
-static u_char familyV[]="ECS-AT";   /* ECS Vertos 100 */
-
-static u_int recursion; /* internal testing only */
-static u_int fatal_err; /* internal testing only */
-static u_int response_count;
-static u_int flags_cmd_out;
-static u_char cmd_type;
-static u_char drvcmd[10];
-static u_char infobuf[20];
-static u_char xa_head_buf[CD_XA_HEAD];
-static u_char xa_tail_buf[CD_XA_TAIL];
-
-#if OLD_BUSY
-static volatile u_char busy_data;
-static volatile u_char busy_audio; /* true semaphores would be safer */
-#endif /* OLD_BUSY */ 
-static DECLARE_MUTEX(ioctl_read_sem);
-static u_long timeout;
-static volatile u_char timed_out_delay;
-static volatile u_char timed_out_data;
-#if 0
-static volatile u_char timed_out_audio;
-#endif
-static u_int datarate= 1000000;
-static u_int maxtim16=16000000;
-static u_int maxtim04= 4000000;
-static u_int maxtim02= 2000000;
-static u_int maxtim_8=   30000;
-#if LONG_TIMING
-static u_int maxtim_data= 9000;
-#else
-static u_int maxtim_data= 3000;
-#endif /* LONG_TIMING */ 
-#if DISTRIBUTION
-static int n_retries=6;
-#else
-static int n_retries=6;
-#endif
-/*==========================================================================*/
-
-static int ndrives;
-static u_char drv_pattern[NR_SBPCD]={speed_auto,speed_auto,speed_auto,speed_auto};
-
-/*==========================================================================*/
-/*
- * drive space begins here (needed separate for each unit) 
- */
-static struct sbpcd_drive {
-	char drv_id;           /* "jumpered" drive ID or -1 */
-	char drv_sel;          /* drive select lines bits */
-	
-	char drive_model[9];
-	u_char firmware_version[4];
-	char f_eject;          /* auto-eject flag: 0 or 1 */
-	u_char *sbp_buf;       /* Pointer to internal data buffer,
-				  space allocated during sbpcd_init() */
-	u_int sbp_bufsiz;      /* size of sbp_buf (# of frames) */
-	int sbp_first_frame;   /* First frame in buffer */
-	int sbp_last_frame;    /* Last frame in buffer  */
-	int sbp_read_frames;   /* Number of frames being read to buffer */
-	int sbp_current;       /* Frame being currently read */
-	
-	u_char mode;           /* read_mode: READ_M1, READ_M2, READ_SC, READ_AU */
-	u_char *aud_buf;       /* Pointer to audio data buffer,
-				  space allocated during sbpcd_init() */
-	u_int sbp_audsiz;      /* size of aud_buf (# of raw frames) */
-	u_int drv_type;
-	u_char drv_options;
-	int status_bits;
-	u_char diskstate_flags;
-	u_char sense_byte;
-	
-	u_char CD_changed;
-	char open_count;
-	u_char error_byte;
-	
-	u_char f_multisession;
-	u_int lba_multi;
-	int first_session;
-	int last_session;
-	int track_of_last_session;
-	
-	u_char audio_state;
-	u_int pos_audio_start;
-	u_int pos_audio_end;
-	char vol_chan0;
-	u_char vol_ctrl0;
-	char vol_chan1;
-	u_char vol_ctrl1;
-#if 000 /* no supported drive has it */
-	char vol_chan2;
-	u_char vol_ctrl2;
-	char vol_chan3;
-	u_char vol_ctrl3;
-#endif /*000 */
-	u_char volume_control; /* TEAC on/off bits */
-	
-	u_char SubQ_ctl_adr;
-	u_char SubQ_trk;
-	u_char SubQ_pnt_idx;
-	u_int SubQ_run_tot;
-	u_int SubQ_run_trk;
-	u_char SubQ_whatisthis;
-	
-	u_char UPC_ctl_adr;
-	u_char UPC_buf[7];
-	
-	int frame_size;
-	int CDsize_frm;
-	
-	u_char xa_byte; /* 0x20: XA capabilities */
-	u_char n_first_track; /* binary */
-	u_char n_last_track; /* binary (not bcd), 0x01...0x63 */
-	u_int size_msf; /* time of whole CD, position of LeadOut track */
-	u_int size_blk;
-	
-	u_char TocEnt_nixbyte; /* em */
-	u_char TocEnt_ctl_adr;
-	u_char TocEnt_number;
-	u_char TocEnt_format; /* em */
-	u_int TocEnt_address;
-#ifdef SAFE_MIXED
-	char has_data;
-#endif /* SAFE_MIXED */ 
-	u_char ored_ctl_adr; /* to detect if CDROM contains data tracks */
-	
-	struct {
-		u_char nixbyte; /* em */
-		u_char ctl_adr; /* 0x4x: data, 0x0x: audio */
-		u_char number;
-		u_char format; /* em */ /* 0x00: lba, 0x01: msf */
-		u_int address;
-	} TocBuffer[MAX_TRACKS+1]; /* last entry faked */ 
-	
-	int in_SpinUp; /* CR-52x test flag */
-	int n_bytes; /* TEAC awaited response count */
-	u_char error_state, b3, b4; /* TEAC command error state */
-	u_char f_drv_error; /* TEAC command error flag */
-	u_char speed_byte;
-	int frmsiz;
-	u_char f_XA; /* 1: XA */
-	u_char type_byte; /* 0, 1, 3 */
-	u_char mode_xb_6;
-	u_char mode_yb_7;
-	u_char mode_xb_8;
-	u_char delay;
-	struct cdrom_device_info *sbpcd_infop;
-	struct gendisk *disk;
-} D_S[NR_SBPCD];
-
-static struct sbpcd_drive *current_drive = D_S;
-
-/*
- * drive space ends here (needed separate for each unit)
- */
-/*==========================================================================*/
-#if 0
-unsigned long cli_sti; /* for saving the processor flags */
-#endif
-/*==========================================================================*/
-static DEFINE_TIMER(delay_timer, mark_timeout_delay, 0, 0);
-static DEFINE_TIMER(data_timer, mark_timeout_data, 0, 0);
-#if 0
-static DEFINE_TIMER(audio_timer, mark_timeout_audio, 0, 0);
-#endif
-/*==========================================================================*/
-/*
- * DDI interface
- */
-static void msg(int level, const char *fmt, ...)
-{
-#if DISTRIBUTION
-#define MSG_LEVEL KERN_NOTICE
-#else
-#define MSG_LEVEL KERN_INFO
-#endif /* DISTRIBUTION */
-
-	char buf[256];
-	va_list args;
-	
-	if (!(sbpcd_debug&(1<<level))) return;
-	
-	msgnum++;
-	if (msgnum>99) msgnum=0;
-	va_start(args, fmt);
-	vsnprintf(buf, sizeof(buf), fmt, args);
-	va_end(args);
-	printk(MSG_LEVEL "%s-%d [%02d]:  %s", major_name, current_drive - D_S, msgnum, buf);
-#if KLOGD_PAUSE
-	sbp_sleep(KLOGD_PAUSE); /* else messages get lost */
-#endif /* KLOGD_PAUSE */ 
-	return;
-}
-/*==========================================================================*/
-/*
- * DDI interface: runtime trace bit pattern maintenance
- */
-static int sbpcd_dbg_ioctl(unsigned long arg, int level)
-{
-	switch(arg)
-	{
-	case 0:	/* OFF */
-		sbpcd_debug = DBG_INF;
-		break;
-		
-	default:
-		if (arg>=128) sbpcd_debug &= ~(1<<(arg-128));
-		else sbpcd_debug |= (1<<arg);
-	}
-	return (arg);
-}
-/*==========================================================================*/
-static void mark_timeout_delay(u_long i)
-{
-	timed_out_delay=1;
-#if 0
-	msg(DBG_TIM,"delay timer expired.\n");
-#endif
-}
-/*==========================================================================*/
-static void mark_timeout_data(u_long i)
-{
-	timed_out_data=1;
-#if 0
-	msg(DBG_TIM,"data timer expired.\n");
-#endif
-}
-/*==========================================================================*/
-#if 0
-static void mark_timeout_audio(u_long i)
-{
-	timed_out_audio=1;
-#if 0
-	msg(DBG_TIM,"audio timer expired.\n");
-#endif
-}
-#endif
-/*==========================================================================*/
-/*
- * Wait a little while (used for polling the drive).
- */
-static void sbp_sleep(u_int time)
-{
-	sti();
-	schedule_timeout_interruptible(time);
-	sti();
-}
-/*==========================================================================*/
-#define RETURN_UP(rc) {up(&ioctl_read_sem); return(rc);}
-/*==========================================================================*/
-/*
- *  convert logical_block_address to m-s-f_number (3 bytes only)
- */
-static INLINE void lba2msf(int lba, u_char *msf)
-{
-	lba += CD_MSF_OFFSET;
-	msf[0] = lba / (CD_SECS*CD_FRAMES);
-	lba %= CD_SECS*CD_FRAMES;
-	msf[1] = lba / CD_FRAMES;
-	msf[2] = lba % CD_FRAMES;
-}
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- *  convert msf-bin to msf-bcd
- */
-static INLINE void bin2bcdx(u_char *p)  /* must work only up to 75 or 99 */
-{
-	*p=((*p/10)<<4)|(*p%10);
-}
-/*==========================================================================*/
-static INLINE u_int blk2msf(u_int blk)
-{
-	MSF msf;
-	u_int mm;
-	
-	msf.c[3] = 0;
-	msf.c[2] = (blk + CD_MSF_OFFSET) / (CD_SECS * CD_FRAMES);
-	mm = (blk + CD_MSF_OFFSET) % (CD_SECS * CD_FRAMES);
-	msf.c[1] = mm / CD_FRAMES;
-	msf.c[0] = mm % CD_FRAMES;
-	return (msf.n);
-}
-/*==========================================================================*/
-static INLINE u_int make16(u_char rh, u_char rl)
-{
-	return ((rh<<8)|rl);
-}
-/*==========================================================================*/
-static INLINE u_int make32(u_int rh, u_int rl)
-{
-	return ((rh<<16)|rl);
-}
-/*==========================================================================*/
-static INLINE u_char swap_nibbles(u_char i)
-{
-	return ((i<<4)|(i>>4));
-}
-/*==========================================================================*/
-static INLINE u_char byt2bcd(u_char i)
-{
-	return (((i/10)<<4)+i%10);
-}
-/*==========================================================================*/
-static INLINE u_char bcd2bin(u_char bcd)
-{
-	return ((bcd>>4)*10+(bcd&0x0F));
-}
-/*==========================================================================*/
-static INLINE int msf2blk(int msfx)
-{
-	MSF msf;
-	int i;
-	
-	msf.n=msfx;
-	i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_MSF_OFFSET;
-	if (i<0) return (0);
-	return (i);
-}
-/*==========================================================================*/
-/*
- *  convert m-s-f_number (3 bytes only) to logical_block_address 
- */
-static INLINE int msf2lba(u_char *msf)
-{
-	int i;
-	
-	i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_MSF_OFFSET;
-	if (i<0) return (0);
-	return (i);
-}
-/*==========================================================================*/
-/* evaluate cc_ReadError code */ 
-static int sta2err(int sta)
-{
-	if (famT_drive)
-	{
-		if (sta==0x00) return (0);
-		if (sta==0x01) return (-604); /* CRC error */
-		if (sta==0x02) return (-602); /* drive not ready */
-		if (sta==0x03) return (-607); /* unknown media */
-		if (sta==0x04) return (-612); /* general failure */
-		if (sta==0x05) return (0);
-		if (sta==0x06) return (-ERR_DISKCHANGE); /* disk change */
-		if (sta==0x0b) return (-612); /* general failure */
-		if (sta==0xff) return (-612); /* general failure */
-		return (0);
-	}
-	else
-	{
-		if (sta<=2) return (sta);
-		if (sta==0x05) return (-604); /* CRC error */
-		if (sta==0x06) return (-606); /* seek error */
-		if (sta==0x0d) return (-606); /* seek error */
-		if (sta==0x0e) return (-603); /* unknown command */
-		if (sta==0x14) return (-603); /* unknown command */
-		if (sta==0x0c) return (-611); /* read fault */
-		if (sta==0x0f) return (-611); /* read fault */
-		if (sta==0x10) return (-611); /* read fault */
-		if (sta>=0x16) return (-612); /* general failure */
-		if (sta==0x11) return (-ERR_DISKCHANGE); /* disk change (LCS: removed) */
-		if (famL_drive)
-			if (sta==0x12) return (-ERR_DISKCHANGE); /* disk change (inserted) */
-		return (-602); /* drive not ready */
-	}
-}
-/*==========================================================================*/
-static INLINE void clr_cmdbuf(void)
-{
-	int i;
-	
-	for (i=0;i<10;i++) drvcmd[i]=0;
-	cmd_type=0;
-}
-/*==========================================================================*/
-static void flush_status(void)
-{
-	int i;
-	
-	sbp_sleep(15*HZ/10);
-	for (i=maxtim_data;i!=0;i--) inb(CDi_status);
-}
-/*====================================================================*/
-/*
- * CDi status loop for Teac CD-55A (Rob Riggs)
- *
- * This is needed because for some strange reason
- * the CD-55A can take a real long time to give a
- * status response. This seems to happen after we
- * issue a READ command where a long seek is involved.
- *
- * I tried to ensure that we get max throughput with
- * minimal busy waiting. We busy wait at first, then
- * "switch gears" and start sleeping. We sleep for
- * longer periods of time the longer we wait.
- *
- */
-static int CDi_stat_loop_T(void)
-{
-	int	i, gear=1;
-	u_long  timeout_1, timeout_2, timeout_3, timeout_4;
-
-	timeout_1 = jiffies + HZ / 50;  /* sbp_sleep(0) for a short period */
-	timeout_2 = jiffies + HZ / 5;	/* nap for no more than 200ms */
-	timeout_3 = jiffies + 5 * HZ;	/* sleep for up to 5s */
-	timeout_4 = jiffies + 45 * HZ;	/* long sleep for up to 45s. */
-	do
-          {
-            i = inb(CDi_status);
-            if (!(i&s_not_data_ready)) return (i);
-            if (!(i&s_not_result_ready)) return (i);
-            switch(gear)
-              {
-              case 4:
-                sbp_sleep(HZ);
-                if (time_after(jiffies, timeout_4)) gear++;
-                msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n");
-                break;
-              case 3:
-                sbp_sleep(HZ/10);
-                if (time_after(jiffies, timeout_3)) gear++;
-                break;
-              case 2:
-                sbp_sleep(HZ/100);
-                if (time_after(jiffies, timeout_2)) gear++;
-                break;
-              case 1:
-                sbp_sleep(0);
-                if (time_after(jiffies, timeout_1)) gear++;
-              }
-          } while (gear < 5);
-	return -1;
-}
-/*==========================================================================*/
-static int CDi_stat_loop(void)
-{
-	int i,j;
-	
-	for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); )
-	{
-		for ( ;i!=0;i--)
-		{
-			j=inb(CDi_status);
-			if (!(j&s_not_data_ready)) return (j);
-			if (!(j&s_not_result_ready)) return (j);
-			if (fam0L_drive) if (j&s_attention) return (j);
-		}
-		sbp_sleep(1);
-		i = 1;
-	}
-	msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__);
-	return (-1);
-}
-/*==========================================================================*/
-#if 00000
-/*==========================================================================*/
-static int tst_DataReady(void)
-{
-	int i;
-	
-	i=inb(CDi_status);
-	if (i&s_not_data_ready) return (0);
-	return (1);
-}
-/*==========================================================================*/
-static int tst_ResultReady(void)
-{
-	int i;
-	
-	i=inb(CDi_status);
-	if (i&s_not_result_ready) return (0);
-	return (1);
-}
-/*==========================================================================*/
-static int tst_Attention(void)
-{
-	int i;
-	
-	i=inb(CDi_status);
-	if (i&s_attention) return (1);
-	return (0);
-}
-/*==========================================================================*/
-#endif
-/*==========================================================================*/
-static int ResponseInfo(void)
-{
-	int i,j,st=0;
-	u_long timeout;
-	
-	for (i=0,timeout=jiffies+HZ;i<response_count;i++) 
-	{
-		for (j=maxtim_data; ; )
-		{
-			for ( ;j!=0;j-- )
-			{
-				st=inb(CDi_status);
-				if (!(st&s_not_result_ready)) break;
-			}
-			if ((j!=0)||time_after_eq(jiffies, timeout)) break;
-			sbp_sleep(1);
-			j = 1;
-		}
-		if (time_after_eq(jiffies, timeout)) break;
-		infobuf[i]=inb(CDi_info);
-	}
-#if 000
-	while (!(inb(CDi_status)&s_not_result_ready))
-	{
-		infobuf[i++]=inb(CDi_info);
-	}
-	j=i-response_count;
-	if (j>0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j);
-#endif /* 000 */
-	for (j=0;j<i;j++)
-		sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
-	msgbuf[j*3]=0;
-	msg(DBG_CMD,"ResponseInfo:%s (%d,%d)\n",msgbuf,response_count,i);
-	j=response_count-i;
-	if (j>0) return (-j);
-	else return (i);
-}
-/*==========================================================================*/
-static void EvaluateStatus(int st)
-{
-	current_drive->status_bits=0;
-	if (fam1_drive) current_drive->status_bits=st|p_success;
-	else if (fam0_drive)
-	{
-		if (st&p_caddin_old) current_drive->status_bits |= p_door_closed|p_caddy_in;
-		if (st&p_spinning) current_drive->status_bits |= p_spinning;
-		if (st&p_check) current_drive->status_bits |= p_check;
- 		if (st&p_success_old) current_drive->status_bits |= p_success;
- 		if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
-		if (st&p_disk_ok) current_drive->status_bits |= p_disk_ok;
-	}
-	else if (famLV_drive)
-	{
- 		current_drive->status_bits |= p_success;
-		if (st&p_caddin_old) current_drive->status_bits |= p_disk_ok|p_caddy_in;
-		if (st&p_spinning) current_drive->status_bits |= p_spinning;
-		if (st&p_check) current_drive->status_bits |= p_check;
-		if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
-		if (st&p_lcs_door_closed) current_drive->status_bits |= p_door_closed;
-		if (st&p_lcs_door_locked) current_drive->status_bits |= p_door_locked;
-	}
-	else if (fam2_drive)
-	{
- 		current_drive->status_bits |= p_success;
-		if (st&p2_check) current_drive->status_bits |= p1_check;
-		if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
-		if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
-		if (st&p2_busy1) current_drive->status_bits |= p1_busy;
-		if (st&p2_busy2) current_drive->status_bits |= p1_busy;
-		if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
-		if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
-		if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
-	}
-	else if (famT_drive)
-	{
-		return; /* still needs to get coded */
- 		current_drive->status_bits |= p_success;
-		if (st&p2_check) current_drive->status_bits |= p1_check;
-		if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
-		if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
-		if (st&p2_busy1) current_drive->status_bits |= p1_busy;
-		if (st&p2_busy2) current_drive->status_bits |= p1_busy;
-		if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
-		if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
-		if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
-	}
-	return;
-}
-/*==========================================================================*/
-static int cmd_out_T(void);
-
-static int get_state_T(void)
-{
-	int i;
-
-	clr_cmdbuf();
-	current_drive->n_bytes=1;
-	drvcmd[0]=CMDT_STATUS;
-	i=cmd_out_T();
-	if (i>=0) i=infobuf[0];
-	else
-	{
-		msg(DBG_TEA,"get_state_T error %d\n", i);
-		return (i);
-	}
-	if (i>=0)
-		/* 2: closed, disk in */
-		current_drive->status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok;
-	else if (current_drive->error_state==6)
-	{
-		/* 3: closed, disk in, changed ("06 xx xx") */
-		current_drive->status_bits=p1_door_closed|p1_disk_in;
-		current_drive->CD_changed=0xFF;
-		current_drive->diskstate_flags &= ~toc_bit;
-	}
-	else if ((current_drive->error_state!=2)||(current_drive->b3!=0x3A)||(current_drive->b4==0x00))
-	{
-		/* 1: closed, no disk ("xx yy zz"or "02 3A 00") */
-		current_drive->status_bits=p1_door_closed;
-		current_drive->open_count=0;
-	}
-	else if (current_drive->b4==0x01)
-	{
-		/* 0: open ("02 3A 01") */
-		current_drive->status_bits=0;
-		current_drive->open_count=0;
-	}
-	else
-	{
-		/* 1: closed, no disk ("02 3A xx") */
-		current_drive->status_bits=p1_door_closed;
-		current_drive->open_count=0;
-	}
-	return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static int ResponseStatus(void)
-{
-	int i,j;
-	u_long timeout;
-	
-	msg(DBG_STA,"doing ResponseStatus...\n");
-	if (famT_drive) return (get_state_T());
-	if (flags_cmd_out & f_respo3) timeout = jiffies;
-	else if (flags_cmd_out & f_respo2) timeout = jiffies + 16*HZ;
-	else timeout = jiffies + 4*HZ;
-	j=maxtim_8;
-	do
-	{
-		for ( ;j!=0;j--)
-		{ 
-			i=inb(CDi_status);
-			if (!(i&s_not_result_ready)) break;
-		}
-		if ((j!=0)||time_after(jiffies, timeout)) break;
-		sbp_sleep(1);
-		j = 1;
-	}
-	while (1);
-	if (j==0) 
-	{
-		if ((flags_cmd_out & f_respo3) == 0)
-			msg(DBG_STA,"ResponseStatus: timeout.\n");
-		current_drive->status_bits=0;
-		return (-401);
-	}
-	i=inb(CDi_info);
-	msg(DBG_STA,"ResponseStatus: response %02X.\n", i);
-	EvaluateStatus(i);
-	msg(DBG_STA,"status_bits=%02X, i=%02X\n",current_drive->status_bits,i);
-	return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static void cc_ReadStatus(void)
-{
-	int i;
-	
-	msg(DBG_STA,"giving cc_ReadStatus command\n");
-	if (famT_drive) return;
-	SBPCD_CLI;
-	if (fam0LV_drive) OUT(CDo_command,CMD0_STATUS);
-	else if (fam1_drive) OUT(CDo_command,CMD1_STATUS);
-	else if (fam2_drive) OUT(CDo_command,CMD2_STATUS);
-	if (!fam0LV_drive) for (i=0;i<6;i++) OUT(CDo_command,0);
-	SBPCD_STI;
-}
-/*==========================================================================*/
-static int cc_ReadError(void)
-{
-	int i;
-
-	clr_cmdbuf();
-	msg(DBG_ERR,"giving cc_ReadError command.\n");
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_READ_ERR;
-		response_count=8;
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (fam0LV_drive)
-	{
-		drvcmd[0]=CMD0_READ_ERR;
-		response_count=6;
-		if (famLV_drive)
-			flags_cmd_out=f_putcmd;
-		else
-			flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_READ_ERR;
-		response_count=6;
-		flags_cmd_out=f_putcmd;
-	}
-	else if (famT_drive)
-	{
-		response_count=5;
-		drvcmd[0]=CMDT_READ_ERR;
-	}
-	i=cmd_out();
-	current_drive->error_byte=0;
-	msg(DBG_ERR,"cc_ReadError: cmd_out(CMDx_READ_ERR) returns %d (%02X)\n",i,i);
-	if (i<0) return (i);
-	if (fam0V_drive) i=1;
-	else i=2;
-	current_drive->error_byte=infobuf[i];
-	msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,current_drive->error_byte,current_drive->error_byte);
-	i=sta2err(infobuf[i]);
-        if (i==-ERR_DISKCHANGE)
-        {
-                current_drive->CD_changed=0xFF;
-                current_drive->diskstate_flags &= ~toc_bit;
-        }
-	return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void);
-
-static int cmd_out_T(void)
-{
-#undef CMDT_TRIES
-#define CMDT_TRIES 1000
-#define TEST_FALSE_FF 1
-
-	int i, j, l=0, m, ntries;
-	unsigned long flags;
-
-	current_drive->error_state=0;
-	current_drive->b3=0;
-	current_drive->b4=0;
-	current_drive->f_drv_error=0;
-	for (i=0;i<10;i++) sprintf(&msgbuf[i*3]," %02X",drvcmd[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_CMD,"cmd_out_T:%s\n",msgbuf);
-
-	OUT(CDo_sel_i_d,0);
-	OUT(CDo_enable,current_drive->drv_sel);
-	i=inb(CDi_status);
-	do_16bit=0;
-	if ((f_16bit)&&(!(i&0x80)))
-	{
-		do_16bit=1;
-		msg(DBG_TEA,"cmd_out_T: do_16bit set.\n");
-	}
-	if (!(i&s_not_result_ready))
-	do
-	{
-		j=inb(CDi_info);
-		i=inb(CDi_status);
-		sbp_sleep(0);
-		msg(DBG_TEA,"cmd_out_T: spurious !s_not_result_ready. (%02X)\n", j);
-	}
-	while (!(i&s_not_result_ready));
-	save_flags(flags); cli();
-	for (i=0;i<10;i++) OUT(CDo_command,drvcmd[i]);
-	restore_flags(flags);
-	for (ntries=CMDT_TRIES;ntries>0;ntries--)
-	{
-		if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(HZ); /* fixme */
-#if 01
-		OUT(CDo_sel_i_d,1);
-#endif /* 01 */
-		if (teac==2)
-                  {
-                    if ((i=CDi_stat_loop_T()) == -1) break;
-                  }
-		else
-                  {
-#if 0
-                    OUT(CDo_sel_i_d,1);
-#endif /* 0 */ 
-                    i=inb(CDi_status);
-                  }
-		if (!(i&s_not_data_ready)) /* f.e. CMDT_DISKINFO */
-		{
-			OUT(CDo_sel_i_d,1);
-			if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
-			if (drvcmd[0]==CMDT_DISKINFO)
-			{
-				l=0;
-				do
-                                {
-                                        if (do_16bit)
-                                        {
-                                                i=inw(CDi_data);
-                                                infobuf[l++]=i&0x0ff;
-                                                infobuf[l++]=i>>8;
-#if TEST_FALSE_FF
-                                                if ((l==2)&&(infobuf[0]==0x0ff))
-                                                {
-                                                        infobuf[0]=infobuf[1];
-                                                        l=1;
-                                                        msg(DBG_TEA,"cmd_out_T: do_16bit: false first byte!\n");
-                                                }
-#endif /* TEST_FALSE_FF */ 
-                                        }
-                                        else infobuf[l++]=inb(CDi_data);
-                                        i=inb(CDi_status);
-                                }
-				while (!(i&s_not_data_ready));
-				for (j=0;j<l;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
-				msgbuf[j*3]=0;
-				msg(DBG_CMD,"cmd_out_T data response:%s\n", msgbuf);
-			}
-			else
-			{
-				msg(DBG_TEA,"cmd_out_T: data response with cmd_%02X!\n",
-                                    drvcmd[0]);
-				j=0;
-				do
-				{
-                                        if (do_16bit) i=inw(CDi_data);
-                                        else i=inb(CDi_data);
-                                        j++;
-                                        i=inb(CDi_status);
-				}
-				while (!(i&s_not_data_ready));
-				msg(DBG_TEA,"cmd_out_T: data response: discarded %d bytes/words.\n", j);
-				fatal_err++;
-			}
-		}
-		i=inb(CDi_status);
-		if (!(i&s_not_result_ready))
-		{
-			OUT(CDo_sel_i_d,0);
-			if (drvcmd[0]==CMDT_DISKINFO) m=l;
-			else m=0;
-			do
-			{
-				infobuf[m++]=inb(CDi_info);
-				i=inb(CDi_status);
-			}
-			while (!(i&s_not_result_ready));
-			for (j=0;j<m;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
-			msgbuf[j*3]=0;
-			msg(DBG_CMD,"cmd_out_T info response:%s\n", msgbuf);
-			if (drvcmd[0]==CMDT_DISKINFO)
-                        {
-                                infobuf[0]=infobuf[l];
-                                if (infobuf[0]!=0x02) return (l); /* data length */
-                        }
-			else if (infobuf[0]!=0x02) return (m); /* info length */
-			do
-			{
-				++recursion;
-				if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (%02X): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", drvcmd[0], recursion);
-				clr_cmdbuf();
-				drvcmd[0]=CMDT_READ_ERR;
-				j=cmd_out_T(); /* !!! recursive here !!! */
-				--recursion;
-				sbp_sleep(1);
-			}
-			while (j<0);
-			current_drive->error_state=infobuf[2];
-			current_drive->b3=infobuf[3];
-			current_drive->b4=infobuf[4];
-			if (current_drive->f_drv_error)
-			{
-				current_drive->f_drv_error=0;
-				cc_DriveReset();
-				current_drive->error_state=2;
-			}
-			return (-current_drive->error_state-400);
-		}
-		if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
-		if ((teac==0)||(ntries<(CMDT_TRIES-5))) sbp_sleep(HZ/10);
-		else sbp_sleep(HZ/100);
-		if (ntries>(CMDT_TRIES-50)) continue;
-		msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1);
-	}
-	current_drive->f_drv_error=1;
-	cc_DriveReset();
-	current_drive->error_state=2;
-	return (-99);
-}
-/*==========================================================================*/
-static int cmd_out(void)
-{
-	int i=0;
-	
-	if (famT_drive) return(cmd_out_T());
-	
-	if (flags_cmd_out&f_putcmd)
-	{ 
-		unsigned long flags;
-		for (i=0;i<7;i++)
-			sprintf(&msgbuf[i*3], " %02X", drvcmd[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_CMD,"cmd_out:%s\n", msgbuf);
-		save_flags(flags); cli();
-		for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]);
-		restore_flags(flags);
-	}
-	if (response_count!=0)
-	{
-		if (cmd_type!=0)
-		{
-			if (sbpro_type==1) OUT(CDo_sel_i_d,1);
-			msg(DBG_INF,"misleaded to try ResponseData.\n");
-			if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-			return (-22);
-		}
-		else i=ResponseInfo();
-		if (i<0) return (i);
-	}
-	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n");
-	if (flags_cmd_out&f_lopsta)
-	{
-		i=CDi_stat_loop();
-		if ((i<0)||!(i&s_attention)) return (-8);
-	}
-	if (!(flags_cmd_out&f_getsta)) goto LOC_229;
-	
- LOC_228:
-	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n");
-	cc_ReadStatus();
-	
- LOC_229:
-	if (flags_cmd_out&f_ResponseStatus) 
-	{
-		if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n");
-		i=ResponseStatus();
-		/* builds status_bits, returns orig. status or p_busy_new */
-		if (i<0) return (i);
-		if (flags_cmd_out&(f_bit1|f_wait_if_busy))
-		{
-			if (!st_check)
-			{
-				if ((flags_cmd_out&f_bit1)&&(i&p_success)) goto LOC_232;
-				if ((!(flags_cmd_out&f_wait_if_busy))||(!st_busy)) goto LOC_228;
-			}
-		}
-	}
- LOC_232:
-	if (!(flags_cmd_out&f_obey_p_check)) return (0);
-	if (!st_check) return (0);
-	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n");
-	i=cc_ReadError();
-	if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n");
-	msg(DBG_000,"cmd_out: cc_ReadError=%d\n", i);
-	return (i);
-}
-/*==========================================================================*/
-static int cc_Seek(u_int pos, char f_blk_msf)
-{
-	int i;
-	
-  clr_cmdbuf();
-	if (f_blk_msf>1) return (-3);
-	if (fam0V_drive)
-	{
-		drvcmd[0]=CMD0_SEEK;
-		if (f_blk_msf==1) pos=msf2blk(pos);
-		drvcmd[2]=(pos>>16)&0x00FF;
-		drvcmd[3]=(pos>>8)&0x00FF;
-		drvcmd[4]=pos&0x00FF;
-		if (fam0_drive)
-		  flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
-			f_ResponseStatus | f_obey_p_check | f_bit1;
-		else
-		  flags_cmd_out = f_putcmd;
-	}
-	else if (fam1L_drive)
-	{
-		drvcmd[0]=CMD1_SEEK; /* same as CMD1_ and CMDL_ */
-		if (f_blk_msf==0) pos=blk2msf(pos);
-		drvcmd[1]=(pos>>16)&0x00FF;
-		drvcmd[2]=(pos>>8)&0x00FF;
-		drvcmd[3]=pos&0x00FF;
-		if (famL_drive)
-			flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-		else
-			flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_SEEK;
-		if (f_blk_msf==0) pos=blk2msf(pos);
-		drvcmd[2]=(pos>>24)&0x00FF;
-		drvcmd[3]=(pos>>16)&0x00FF;
-		drvcmd[4]=(pos>>8)&0x00FF;
-		drvcmd[5]=pos&0x00FF;
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_SEEK;
-		if (f_blk_msf==1) pos=msf2blk(pos);
-		drvcmd[2]=(pos>>24)&0x00FF;
-		drvcmd[3]=(pos>>16)&0x00FF;
-		drvcmd[4]=(pos>>8)&0x00FF;
-		drvcmd[5]=pos&0x00FF;
-		current_drive->n_bytes=1;
-	}
-	response_count=0;
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_SpinUp(void)
-{
-	int i;
-	
-	msg(DBG_SPI,"SpinUp.\n");
-	current_drive->in_SpinUp = 1;
-	clr_cmdbuf();
-	if (fam0LV_drive)
-	{
-		drvcmd[0]=CMD0_SPINUP;
-		if (fam0L_drive)
-		  flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
-		    f_ResponseStatus|f_obey_p_check|f_bit1;
-		else
-		  flags_cmd_out=f_putcmd;
-	}
-	else if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_SPINUP;
-		flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_TRAY_CTL;
-		drvcmd[4]=0x01; /* "spinup" */
-		flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_TRAY_CTL;
-		drvcmd[4]=0x03; /* "insert", it hopefully spins the drive up */
-	}
-	response_count=0;
-	i=cmd_out();
-	current_drive->in_SpinUp = 0;
-	return (i);
-}
-/*==========================================================================*/
-static int cc_SpinDown(void)
-{
-	int i;
-	
-	if (fam0_drive) return (0);
-	clr_cmdbuf();
-	response_count=0;
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_SPINDOWN;
-		flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_TRAY_CTL;
-		drvcmd[4]=0x02; /* "eject" */
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (famL_drive)
-	{
-		drvcmd[0]=CMDL_SPINDOWN;
-		drvcmd[1]=1;
-		flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-	}
-	else if (famV_drive)
-	{
-		drvcmd[0]=CMDV_SPINDOWN;
-		flags_cmd_out=f_putcmd;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_TRAY_CTL;
-		drvcmd[4]=0x02; /* "eject" */
-	}
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_get_mode_T(void)
-{
-	int i;
-	
-	clr_cmdbuf();
-	response_count=10;
-	drvcmd[0]=CMDT_GETMODE;
-	drvcmd[4]=response_count;
-	i=cmd_out_T();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_set_mode_T(void)
-{
-	int i;
-	
-	clr_cmdbuf();
-	response_count=1;
-	drvcmd[0]=CMDT_SETMODE;
-	drvcmd[1]=current_drive->speed_byte;
-	drvcmd[2]=current_drive->frmsiz>>8;
-	drvcmd[3]=current_drive->frmsiz&0x0FF;
-	drvcmd[4]=current_drive->f_XA; /* 1: XA */
-	drvcmd[5]=current_drive->type_byte; /* 0, 1, 3 */
-	drvcmd[6]=current_drive->mode_xb_6;
-	drvcmd[7]=current_drive->mode_yb_7|current_drive->volume_control;
-	drvcmd[8]=current_drive->mode_xb_8;
-	drvcmd[9]=current_drive->delay;
-	i=cmd_out_T();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_prep_mode_T(void)
-{
-	int i, j;
-	
-	i=cc_get_mode_T();
-	if (i<0) return (i);
-	for (i=0;i<10;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
-	current_drive->speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */
-	current_drive->frmsiz=make16(infobuf[2],infobuf[3]);
-	current_drive->f_XA=infobuf[4];
-	if (current_drive->f_XA==0) current_drive->type_byte=0;
-	else current_drive->type_byte=1;
-	current_drive->mode_xb_6=infobuf[6];
-	current_drive->mode_yb_7=1;
-	current_drive->mode_xb_8=infobuf[8];
-	current_drive->delay=0; /* 0, 1, 2, 3 */
-	j=cc_set_mode_T();
-	i=cc_get_mode_T();
-	for (i=0;i<10;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
-	return (j);
-}
-/*==========================================================================*/
-static int cc_SetSpeed(u_char speed, u_char x1, u_char x2)
-{
-	int i;
-	
-	if (fam0LV_drive) return (0);
-	clr_cmdbuf();
-	response_count=0;
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_SETMODE;
-		drvcmd[1]=0x03;
-		drvcmd[2]=speed;
-		drvcmd[3]=x1;
-		drvcmd[4]=x2;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_SETSPEED;
-		if (speed&speed_auto)
-		{
-			drvcmd[2]=0xFF;
-			drvcmd[3]=0xFF;
-		}
-		else
-		{
-			drvcmd[2]=0;
-			drvcmd[3]=150;
-		}
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		return (0);
-	}
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_SetVolume(void)
-{
-	int i;
-	u_char channel0,channel1,volume0,volume1;
-	u_char control0,value0,control1,value1;
-	
-	current_drive->diskstate_flags &= ~volume_bit;
-	clr_cmdbuf();
-	channel0=current_drive->vol_chan0;
-	volume0=current_drive->vol_ctrl0;
-	channel1=control1=current_drive->vol_chan1;
-	volume1=value1=current_drive->vol_ctrl1;
-	control0=value0=0;
-	
-	if (famV_drive) return (0);
-
-	if (((current_drive->drv_options&audio_mono)!=0)&&(current_drive->drv_type>=drv_211))
-	{
-		if ((volume0!=0)&&(volume1==0))
-		{
-			volume1=volume0;
-			channel1=channel0;
-		}
-		else if ((volume0==0)&&(volume1!=0))
-		{
-			volume0=volume1;
-			channel0=channel1;
-		}
-	}
-	if (channel0>1)
-	{
-		channel0=0;
-		volume0=0;
-	}
-	if (channel1>1)
-	{
-		channel1=1;
-		volume1=0;
-	}
-	
-	if (fam1_drive)
-	{
-		control0=channel0+1;
-		control1=channel1+1;
-		value0=(volume0>volume1)?volume0:volume1;
-		value1=value0;
-		if (volume0==0) control0=0;
-		if (volume1==0) control1=0;
-		drvcmd[0]=CMD1_SETMODE;
-		drvcmd[1]=0x05;
-		drvcmd[3]=control0;
-		drvcmd[4]=value0;
-		drvcmd[5]=control1;
-		drvcmd[6]=value1;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		control0=channel0+1;
-		control1=channel1+1;
-		value0=(volume0>volume1)?volume0:volume1;
-		value1=value0;
-		if (volume0==0) control0=0;
-		if (volume1==0) control1=0;
-		drvcmd[0]=CMD2_SETMODE;
-		drvcmd[1]=0x0E;
-		drvcmd[3]=control0;
-		drvcmd[4]=value0;
-		drvcmd[5]=control1;
-		drvcmd[6]=value1;
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (famL_drive)
-	{
-		if ((volume0==0)||(channel0!=0)) control0 |= 0x80;
-		if ((volume1==0)||(channel1!=1)) control0 |= 0x40;
-		if (volume0|volume1) value0=0x80;
-		drvcmd[0]=CMDL_SETMODE;
-		drvcmd[1]=0x03;
-		drvcmd[4]=control0;
-		drvcmd[5]=value0;
-		flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-	}
-	else if (fam0_drive) /* different firmware levels */
-	{
-		if (current_drive->drv_type>=drv_300)
-		{
-			control0=volume0&0xFC;
-			value0=volume1&0xFC;
-			if ((volume0!=0)&&(volume0<4)) control0 |= 0x04;
-			if ((volume1!=0)&&(volume1<4)) value0 |= 0x04;
-			if (channel0!=0) control0 |= 0x01;
-			if (channel1==1) value0 |= 0x01;
-		}
-		else
-		{
-			value0=(volume0>volume1)?volume0:volume1;
-			if (current_drive->drv_type<drv_211)
-			{
-				if (channel0!=0)
-				{
-					i=channel1;
-					channel1=channel0;
-					channel0=i;
-					i=volume1;
-					volume1=volume0;
-					volume0=i;
-				}
-				if (channel0==channel1)
-				{
-					if (channel0==0)
-					{
-						channel1=1;
-						volume1=0;
-						volume0=value0;
-					}
-					else
-					{
-						channel0=0;
-						volume0=0;
-						volume1=value0;
-					}
-				}
-			}
-			
-			if ((volume0!=0)&&(volume1!=0))
-			{
-				if (volume0==0xFF) volume1=0xFF;
-				else if (volume1==0xFF) volume0=0xFF;
-			}
-			else if (current_drive->drv_type<drv_201) volume0=volume1=value0;
-			
-			if (current_drive->drv_type>=drv_201)
-			{
-				if (volume0==0) control0 |= 0x80;
-				if (volume1==0) control0 |= 0x40;
-			}
-			if (current_drive->drv_type>=drv_211)
-			{
-				if (channel0!=0) control0 |= 0x20;
-				if (channel1!=1) control0 |= 0x10;
-			}
-		}
-		drvcmd[0]=CMD0_SETMODE;
-		drvcmd[1]=0x83;
-		drvcmd[4]=control0;
-		drvcmd[5]=value0;
-		flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		current_drive->volume_control=0;
-		if (!volume0) current_drive->volume_control|=0x10;
-		if (!volume1) current_drive->volume_control|=0x20;
-		i=cc_prep_mode_T();
-		if (i<0) return (i);
-	}
-	if (!famT_drive)
-	{
-		response_count=0;
-		i=cmd_out();
-		if (i<0) return (i);
-	}
-	current_drive->diskstate_flags |= volume_bit;
-	return (0);
-}
-/*==========================================================================*/
-static int GetStatus(void)
-{
-	int i;
-	
-	if (famT_drive) return (0);
-	flags_cmd_out=f_getsta|f_ResponseStatus|f_obey_p_check;
-	response_count=0;
-	cmd_type=0;
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void)
-{
-	int i;
-	
-	msg(DBG_RES,"cc_DriveReset called.\n");
-	clr_cmdbuf();
-	response_count=0;
-	if (fam0LV_drive) OUT(CDo_reset,0x00);
-	else if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_RESET;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_RESET;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-		OUT(CDo_reset,0x00);
-	}
-	else if (famT_drive)
-	{
-		OUT(CDo_sel_i_d,0);
-		OUT(CDo_enable,current_drive->drv_sel);
-		OUT(CDo_command,CMDT_RESET);
-		for (i=1;i<10;i++) OUT(CDo_command,0);
-	}
-	if (fam0LV_drive) sbp_sleep(5*HZ); /* wait 5 seconds */
-	else sbp_sleep(1*HZ); /* wait a second */
-#if 1
-	if (famT_drive)
-	{
-		msg(DBG_TEA, "================CMDT_RESET given=================.\n");
-		sbp_sleep(3*HZ);
-	}
-#endif /* 1 */ 
-	flush_status();
-	i=GetStatus();
-	if (i<0) return i;
-	if (!famT_drive)
-		if (current_drive->error_byte!=aud_12) return -501;
-	return (0);
-}
-
-/*==========================================================================*/
-static int SetSpeed(void)
-{
-	int i, speed;
-	
-	if (!(current_drive->drv_options&(speed_auto|speed_300|speed_150))) return (0);
-	speed=speed_auto;
-	if (!(current_drive->drv_options&speed_auto))
-	{
-		speed |= speed_300;
-		if (!(current_drive->drv_options&speed_300)) speed=0;
-	}
-	i=cc_SetSpeed(speed,0,0);
-	return (i);
-}
-
-static void switch_drive(struct sbpcd_drive *);
-
-static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	if (p != current_drive)
-		switch_drive(p);
-
-	return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0);
-}
-
-/*==========================================================================*/
-static int DriveReset(void)
-{
-	int i;
-	
-	i=cc_DriveReset();
-	if (i<0) return (-22);
-	do
-	{
-		i=GetStatus();
-		if ((i<0)&&(i!=-ERR_DISKCHANGE)) {
-			return (-2); /* from sta2err */
-		}
-		if (!st_caddy_in) break;
-		sbp_sleep(1);
-	}
-	while (!st_diskok);
-#if 000
-	current_drive->CD_changed=1;
-#endif
-	if ((st_door_closed) && (st_caddy_in))
-	{
-		i=DiskInfo();
-		if (i<0) return (-23);
-	}
-	return (0);
-}
-
-static int sbpcd_reset(struct cdrom_device_info *cdi)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	if (p != current_drive)
-		switch_drive(p);
-	return DriveReset();
-}
-
-/*==========================================================================*/
-static int cc_PlayAudio(int pos_audio_start,int pos_audio_end)
-{
-	int i, j, n;
-	
-	if (current_drive->audio_state==audio_playing) return (-EINVAL);
-	clr_cmdbuf();
-	response_count=0;
-	if (famLV_drive)
-	{
-		drvcmd[0]=CMDL_PLAY;
-		i=msf2blk(pos_audio_start);
-		n=msf2blk(pos_audio_end)+1-i;
-		drvcmd[1]=(i>>16)&0x00FF;
-		drvcmd[2]=(i>>8)&0x00FF;
-		drvcmd[3]=i&0x00FF;
-		drvcmd[4]=(n>>16)&0x00FF;
-		drvcmd[5]=(n>>8)&0x00FF;
-		drvcmd[6]=n&0x00FF;
-		if (famL_drive)
-		flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
-			f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
-		else
-		  flags_cmd_out = f_putcmd;
-	}
-	else
-	{
-		j=1;
-		if (fam1_drive)
-		{
-			drvcmd[0]=CMD1_PLAY_MSF;
-			flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus |
-				f_obey_p_check | f_wait_if_busy;
-		}
-		else if (fam2_drive)
-		{
-			drvcmd[0]=CMD2_PLAY_MSF;
-			flags_cmd_out = f_putcmd | f_ResponseStatus | f_obey_p_check;
-		}
-		else if (famT_drive)
-		{
-			drvcmd[0]=CMDT_PLAY_MSF;
-			j=3;
-			response_count=1;
-		}
-		else if (fam0_drive)
-		{
-			drvcmd[0]=CMD0_PLAY_MSF;
-			flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
-				f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
-		}
-		drvcmd[j]=(pos_audio_start>>16)&0x00FF;
-		drvcmd[j+1]=(pos_audio_start>>8)&0x00FF;
-		drvcmd[j+2]=pos_audio_start&0x00FF;
-		drvcmd[j+3]=(pos_audio_end>>16)&0x00FF;
-		drvcmd[j+4]=(pos_audio_end>>8)&0x00FF;
-		drvcmd[j+5]=pos_audio_end&0x00FF;
-	}
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_Pause_Resume(int pau_res)
-{
-	int i;
-	
-	clr_cmdbuf();
-	response_count=0;
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_PAU_RES;
-		if (pau_res!=1) drvcmd[1]=0x80;
-		flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_PAU_RES;
-		if (pau_res!=1) drvcmd[2]=0x01;
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (fam0LV_drive)
-	{
-		drvcmd[0]=CMD0_PAU_RES;
-		if (pau_res!=1) drvcmd[1]=0x80;
-		if (famL_drive)
-			flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
-				f_obey_p_check|f_bit1;
-		else if (famV_drive)
-		  flags_cmd_out=f_putcmd;
-		else
-			flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
-				f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		if (pau_res==3)	return (cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end));
-		else if (pau_res==1) drvcmd[0]=CMDT_PAUSE;
-		else return (-56);
-	}
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int cc_LockDoor(char lock)
-{
-	int i;
-	
-	if (fam0_drive) return (0);
-	msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, current_drive - D_S);
-	msg(DBG_LCS,"p_door_locked bit %d before\n", st_door_locked);
-	clr_cmdbuf();
-	response_count=0;
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_LOCK_CTL;
-		if (lock==1) drvcmd[1]=0x01;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_LOCK_CTL;
-		if (lock==1) drvcmd[4]=0x01;
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (famLV_drive)
-	{
-		drvcmd[0]=CMDL_LOCK_CTL;
-		if (lock==1) drvcmd[1]=0x01;
-		if (famL_drive)
-		  flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-		else
-		  flags_cmd_out=f_putcmd;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_LOCK_CTL;
-		if (lock==1) drvcmd[4]=0x01;
-	}
-	i=cmd_out();
-	msg(DBG_LCS,"p_door_locked bit %d after\n", st_door_locked);
-	return (i);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int UnLockDoor(void)
-{
-	int i,j;
-	
-	j=20;
-	do
-	{
-		i=cc_LockDoor(0);
-		--j;
-		sbp_sleep(1);
-	}
-	while ((i<0)&&(j));
-	if (i<0)
-	{
-		cc_DriveReset();
-		return -84;
-	}
-	return (0);
-}
-/*==========================================================================*/
-static int LockDoor(void)
-{
-	int i,j;
-	
-	j=20;
-	do
-	{
-		i=cc_LockDoor(1);
-		--j;
-		sbp_sleep(1);
-	}
-	while ((i<0)&&(j));
-	if (j==0)
-	{		
-		cc_DriveReset();
-		j=20;
-		do
-		{
-			i=cc_LockDoor(1);
-			--j;
-			sbp_sleep(1);
-		}
-		while ((i<0)&&(j));
-	}
-	return (i);
-}
-
-static int sbpcd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
-  return lock ? LockDoor() : UnLockDoor();
-}
-
-/*==========================================================================*/
-static int cc_CloseTray(void)
-{
-	int i;
-	
-	if (fam0_drive) return (0);
-	msg(DBG_LCK,"cc_CloseTray (drive %d)\n", current_drive - D_S);
-	msg(DBG_LCS,"p_door_closed bit %d before\n", st_door_closed);
-	
-	clr_cmdbuf();
-	response_count=0;
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_TRAY_CTL;
-		flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_TRAY_CTL;
-		drvcmd[1]=0x01;
-		drvcmd[4]=0x03; /* "insert" */
-		flags_cmd_out=f_putcmd|f_ResponseStatus;
-	}
-	else if (famLV_drive)
-	{
-		drvcmd[0]=CMDL_TRAY_CTL;
-		if (famLV_drive)
-		  flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
-			f_ResponseStatus|f_obey_p_check|f_bit1;
-		else
-		  flags_cmd_out=f_putcmd;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_TRAY_CTL;
-		drvcmd[4]=0x03; /* "insert" */
-	}
-	i=cmd_out();
-	msg(DBG_LCS,"p_door_closed bit %d after\n", st_door_closed);
-
-	i=cc_ReadError();
-	flags_cmd_out |= f_respo2;
-	cc_ReadStatus(); /* command: give 1-byte status */
-	i=ResponseStatus();
-	if (famT_drive&&(i<0))
-	{
-		cc_DriveReset();
-		i=ResponseStatus();
-#if 0
-                sbp_sleep(HZ);
-#endif /* 0 */ 
-		i=ResponseStatus();
-	}
-	if (i<0)
-	{
-		msg(DBG_INF,"sbpcd cc_CloseTray: ResponseStatus timed out (%d).\n",i);
-	}
-	if (!(famT_drive))
-	{
-		if (!st_spinning)
-		{
-			cc_SpinUp();
-			if (st_check) i=cc_ReadError();
-			flags_cmd_out |= f_respo2;
-			cc_ReadStatus();
-			i=ResponseStatus();
-		} else {
-		}
-	}
-	i=DiskInfo();
-	return (i);
-}
-
-static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
-{
-	int retval=0;
-	switch_drive(cdi->handle);
-	/* DUH! --AJK */
-	if(current_drive->CD_changed != 0xFF) {
-		current_drive->CD_changed=0xFF;
-		current_drive->diskstate_flags &= ~cd_size_bit;
-	}
-	if (position == 1) {
-		cc_SpinDown();
-	} else {
-		retval=cc_CloseTray();
-	}
-  return retval;
-}
-
-/*==========================================================================*/
-static int cc_ReadSubQ(void)
-{
-	int i,j;
-
-	current_drive->diskstate_flags &= ~subq_bit;
-	for (j=255;j>0;j--)
-	{
-		clr_cmdbuf();
-		if (fam1_drive)
-		{
-			drvcmd[0]=CMD1_READSUBQ;
-			flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-			response_count=11;
-		}
-		else if (fam2_drive)
-		{
-			drvcmd[0]=CMD2_READSUBQ;
-			drvcmd[1]=0x02;
-			drvcmd[3]=0x01;
-			flags_cmd_out=f_putcmd;
-			response_count=10;
-		}
-		else if (fam0LV_drive)
-		{
-			drvcmd[0]=CMD0_READSUBQ;
-			drvcmd[1]=0x02;
-			if (famLV_drive)
-				flags_cmd_out=f_putcmd;
-			else
-				flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-			response_count=13;
-		}
-		else if (famT_drive)
-		{
-			response_count=12;
-			drvcmd[0]=CMDT_READSUBQ;
-			drvcmd[1]=0x02;
-			drvcmd[2]=0x40;
-			drvcmd[3]=0x01;
-			drvcmd[8]=response_count;
-		}
-		i=cmd_out();
-		if (i<0) return (i);
-		for (i=0;i<response_count;i++)
-		{
-			sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-			msgbuf[i*3]=0;
-			msg(DBG_SQ1,"cc_ReadSubQ:%s\n", msgbuf);
-		}
-		if (famT_drive) break;
-		if (infobuf[0]!=0) break;
-		if ((!st_spinning) || (j==1))
-		{
-			current_drive->SubQ_ctl_adr=current_drive->SubQ_trk=current_drive->SubQ_pnt_idx=current_drive->SubQ_whatisthis=0;
-			current_drive->SubQ_run_tot=current_drive->SubQ_run_trk=0;
-			return (0);
-		}
-	}
-	if (famT_drive) current_drive->SubQ_ctl_adr=infobuf[1];
-	else current_drive->SubQ_ctl_adr=swap_nibbles(infobuf[1]);
-	current_drive->SubQ_trk=byt2bcd(infobuf[2]);
-	current_drive->SubQ_pnt_idx=byt2bcd(infobuf[3]);
-	if (fam0LV_drive) i=5;
-	else if (fam12_drive) i=4;
-	else if (famT_drive) i=8;
-	current_drive->SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
-	i=7;
-	if (fam0LV_drive) i=9;
-	else if (fam12_drive) i=7;
-	else if (famT_drive) i=4;
-	current_drive->SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
-	current_drive->SubQ_whatisthis=infobuf[i+3];
-	current_drive->diskstate_flags |= subq_bit;
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ModeSense(void)
-{
-	int i;
-	
-	if (fam2_drive) return (0);
-	if (famV_drive) return (0);
-	current_drive->diskstate_flags &= ~frame_size_bit;
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		response_count=5;
-		drvcmd[0]=CMD1_GETMODE;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam0L_drive)
-	{
-		response_count=2;
-		drvcmd[0]=CMD0_GETMODE;
-		if (famL_drive) flags_cmd_out=f_putcmd;
-		else flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		response_count=10;
-		drvcmd[0]=CMDT_GETMODE;
-		drvcmd[4]=response_count;
-	}
-	i=cmd_out();
-	if (i<0) return (i);
-	i=0;
-	current_drive->sense_byte=0;
-	if (fam1_drive) current_drive->sense_byte=infobuf[i++];
-	else if (famT_drive)
-	{
-		if (infobuf[4]==0x01) current_drive->xa_byte=0x20;
-		else current_drive->xa_byte=0;
-		i=2;
-	}
-	current_drive->frame_size=make16(infobuf[i],infobuf[i+1]);
-	for (i=0;i<response_count;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_XA1,"cc_ModeSense:%s\n", msgbuf);
-	
-	current_drive->diskstate_flags |= frame_size_bit;
-	return (0);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int cc_ModeSelect(int framesize)
-{
-	int i;
-	
-	if (fam2_drive) return (0);
-	if (famV_drive) return (0);
-	current_drive->diskstate_flags &= ~frame_size_bit;
-	clr_cmdbuf();
-	current_drive->frame_size=framesize;
-	if (framesize==CD_FRAMESIZE_RAW) current_drive->sense_byte=0x82;
-	else current_drive->sense_byte=0x00;
-	
-	msg(DBG_XA1,"cc_ModeSelect: %02X %04X\n",
-	    current_drive->sense_byte, current_drive->frame_size);
-	
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_SETMODE;
-		drvcmd[1]=0x00;
-		drvcmd[2]=current_drive->sense_byte;
-		drvcmd[3]=(current_drive->frame_size>>8)&0xFF;
-		drvcmd[4]=current_drive->frame_size&0xFF;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam0L_drive)
-	{
-		drvcmd[0]=CMD0_SETMODE;
-		drvcmd[1]=0x00;
-		drvcmd[2]=(current_drive->frame_size>>8)&0xFF;
-		drvcmd[3]=current_drive->frame_size&0xFF;
-		drvcmd[4]=0x00;
-		if(famL_drive)
-			flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check;
-		else
-			flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		return (-1);
-	}
-	response_count=0;
-	i=cmd_out();
-	if (i<0) return (i);
-	current_drive->diskstate_flags |= frame_size_bit;
-	return (0);
-}
-/*==========================================================================*/
-static int cc_GetVolume(void)
-{
-	int i;
-	u_char switches;
-	u_char chan0=0;
-	u_char vol0=0;
-	u_char chan1=1;
-	u_char vol1=0;
-	
-	if (famV_drive) return (0);
-	current_drive->diskstate_flags &= ~volume_bit;
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_GETMODE;
-		drvcmd[1]=0x05;
-		response_count=5;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_GETMODE;
-		drvcmd[1]=0x0E;
-		response_count=5;
-		flags_cmd_out=f_putcmd;
-	}
-	else if (fam0L_drive)
-	{
-		drvcmd[0]=CMD0_GETMODE;
-		drvcmd[1]=0x03;
-		response_count=2;
-		if(famL_drive)
-			flags_cmd_out=f_putcmd;
-		else
-			flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		i=cc_get_mode_T();
-		if (i<0) return (i);
-	}
-	if (!famT_drive)
-	{
-		i=cmd_out();
-		if (i<0) return (i);
-	}
-	if (fam1_drive)
-	{
-		chan0=infobuf[1]&0x0F;
-		vol0=infobuf[2];
-		chan1=infobuf[3]&0x0F;
-		vol1=infobuf[4];
-		if (chan0==0)
-		{
-			chan0=1;
-			vol0=0;
-		}
-		if (chan1==0)
-		{
-			chan1=2;
-			vol1=0;
-		}
-		chan0 >>= 1;
-		chan1 >>= 1;
-	}
-	else if (fam2_drive)
-	{
-		chan0=infobuf[1];
-		vol0=infobuf[2];
-		chan1=infobuf[3];
-		vol1=infobuf[4];
-	}
-	else if (famL_drive)
-	{
-		chan0=0;
-		chan1=1;
-		vol0=vol1=infobuf[1];
-		switches=infobuf[0];
-		if ((switches&0x80)!=0) chan0=1;
-		if ((switches&0x40)!=0) chan1=0;
-	}
-	else if (fam0_drive) /* different firmware levels */
-	{
-		chan0=0;
-		chan1=1;
-		vol0=vol1=infobuf[1];
-		if (current_drive->drv_type>=drv_201)
-		{
-			if (current_drive->drv_type<drv_300)
-			{
-				switches=infobuf[0];
-				if ((switches&0x80)!=0) vol0=0;
-				if ((switches&0x40)!=0) vol1=0;
-				if (current_drive->drv_type>=drv_211)
-				{
-					if ((switches&0x20)!=0) chan0=1;
-					if ((switches&0x10)!=0) chan1=0;
-				}
-			}
-			else
-			{
-				vol0=infobuf[0];
-				if ((vol0&0x01)!=0) chan0=1;
-				if ((vol1&0x01)==0) chan1=0;
-				vol0 &= 0xFC;
-				vol1 &= 0xFC;
-				if (vol0!=0) vol0 += 3;
-				if (vol1!=0) vol1 += 3;
-			}
-		}
-	}
-	else if (famT_drive)
-	{
-		current_drive->volume_control=infobuf[7];
-		chan0=0;
-		chan1=1;
-		if (current_drive->volume_control&0x10) vol0=0;
-		else vol0=0xff;
-		if (current_drive->volume_control&0x20) vol1=0;
-		else vol1=0xff;
-	}
-	current_drive->vol_chan0=chan0;
-	current_drive->vol_ctrl0=vol0;
-	current_drive->vol_chan1=chan1;
-	current_drive->vol_ctrl1=vol1;
-#if 000
-	current_drive->vol_chan2=2;
-	current_drive->vol_ctrl2=0xFF;
-	current_drive->vol_chan3=3;
-	current_drive->vol_ctrl3=0xFF;
-#endif /*  000 */
-	current_drive->diskstate_flags |= volume_bit;
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ReadCapacity(void)
-{
-	int i, j;
-	
-	if (fam2_drive) return (0); /* some firmware lacks this command */
-	if (famLV_drive) return (0); /* some firmware lacks this command */
-	if (famT_drive) return (0); /* done with cc_ReadTocDescr() */
-	current_drive->diskstate_flags &= ~cd_size_bit;
-	for (j=3;j>0;j--)
-	{
-		clr_cmdbuf();
-		if (fam1_drive)
-		{
-			drvcmd[0]=CMD1_CAPACITY;
-			response_count=5;
-			flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-		}
-#if 00
-		else if (fam2_drive)
-		{
-			drvcmd[0]=CMD2_CAPACITY;
-			response_count=8;
-			flags_cmd_out=f_putcmd;
-		}
-#endif
-		else if (fam0_drive)
-		{
-			drvcmd[0]=CMD0_CAPACITY;
-			response_count=5;
-			flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-		}
-		i=cmd_out();
-		if (i>=0) break;
-		msg(DBG_000,"cc_ReadCapacity: cmd_out: err %d\n", i);
-		cc_ReadError();
-	}
-	if (j==0) return (i);
-	if (fam1_drive) current_drive->CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET;
-	else if (fam0_drive) current_drive->CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2]));
-#if 00
-	else if (fam2_drive) current_drive->CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3]));
-#endif
-	current_drive->diskstate_flags |= cd_size_bit;
-	msg(DBG_000,"cc_ReadCapacity: %d frames.\n", current_drive->CDsize_frm);
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocDescr(void)
-{
-	int i;
-	
-	current_drive->diskstate_flags &= ~toc_bit;
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_DISKINFO;
-		response_count=6;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam0LV_drive)
-	{
-		drvcmd[0]=CMD0_DISKINFO;
-		response_count=6;
-		if(famLV_drive)
-			flags_cmd_out=f_putcmd;
-		else
-			flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		/* possibly longer timeout periods necessary */
-		current_drive->f_multisession=0;
-		drvcmd[0]=CMD2_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[2]=0xAB;
-		drvcmd[3]=0xFF; /* session */
-		response_count=8;
-		flags_cmd_out=f_putcmd;
-	}
-	else if (famT_drive)
-	{
-		current_drive->f_multisession=0;
-		response_count=12;
-		drvcmd[0]=CMDT_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[6]=CDROM_LEADOUT;
-		drvcmd[8]=response_count;
-		drvcmd[9]=0x00;
-	}
-	i=cmd_out();
-	if (i<0) return (i);
-	if ((famT_drive)&&(i<response_count)) return (-100-i);
-	if ((fam1_drive)||(fam2_drive)||(fam0LV_drive))
-		current_drive->xa_byte=infobuf[0];
-	if (fam2_drive)
-	{
-		current_drive->first_session=infobuf[1];
-		current_drive->last_session=infobuf[2];
-		current_drive->n_first_track=infobuf[3];
-		current_drive->n_last_track=infobuf[4];
-		if (current_drive->first_session!=current_drive->last_session)
-		{
-			current_drive->f_multisession=1;
-			current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])));
-		}
-#if 0
-		if (current_drive->first_session!=current_drive->last_session)
-		{
-			if (current_drive->last_session<=20)
-				zwanzig=current_drive->last_session+1;
-			else zwanzig=20;
-			for (count=current_drive->first_session;count<zwanzig;count++)
-			{
-				drvcmd[0]=CMD2_DISKINFO;
-				drvcmd[1]=0x02;
-				drvcmd[2]=0xAB;
-				drvcmd[3]=count;
-				response_count=8;
-				flags_cmd_out=f_putcmd;
-				i=cmd_out();
-				if (i<0) return (i);
-				current_drive->msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]));
-			}
-			current_drive->diskstate_flags |= multisession_bit;
-		}
-#endif
-		drvcmd[0]=CMD2_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[2]=0xAA;
-		drvcmd[3]=0xFF;
-		response_count=5;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-		if (i<0) return (i);
-		current_drive->size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4]));
-		current_drive->size_blk=msf2blk(current_drive->size_msf);
-		current_drive->CDsize_frm=current_drive->size_blk+1;
-	}
-	else if (famT_drive)
-	{
-		current_drive->size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11]));
-		current_drive->size_blk=msf2blk(current_drive->size_msf);
-		current_drive->CDsize_frm=current_drive->size_blk+1;
-		current_drive->n_first_track=infobuf[2];
-		current_drive->n_last_track=infobuf[3];
-	}
-	else
-	{
-		current_drive->n_first_track=infobuf[1];
-		current_drive->n_last_track=infobuf[2];
-		current_drive->size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5]));
-		current_drive->size_blk=msf2blk(current_drive->size_msf);
-		if (famLV_drive) current_drive->CDsize_frm=current_drive->size_blk+1;
-	}
-	current_drive->diskstate_flags |= toc_bit;
-	msg(DBG_TOC,"TocDesc: xa %02X firstt %02X lastt %02X size %08X firstses %02X lastsess %02X\n",
-	    current_drive->xa_byte,
-	    current_drive->n_first_track,
-	    current_drive->n_last_track,
-	    current_drive->size_msf,
-	    current_drive->first_session,
-	    current_drive->last_session);
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocEntry(int num)
-{
-	int i;
-	
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_READTOC;
-		drvcmd[2]=num;
-		response_count=8;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam2_drive)
-	{
-		/* possibly longer timeout periods necessary */
-		drvcmd[0]=CMD2_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[2]=num;
-		response_count=5;
-		flags_cmd_out=f_putcmd;
-	}
-	else if (fam0LV_drive)
-	{
-		drvcmd[0]=CMD0_READTOC;
-		drvcmd[1]=0x02;
-		drvcmd[2]=num;
-		response_count=8;
-		if (famLV_drive)
-			flags_cmd_out=f_putcmd;
-		else
-		  flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (famT_drive)
-	{
-		response_count=12;
-		drvcmd[0]=CMDT_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[6]=num;
-		drvcmd[8]=response_count;
-		drvcmd[9]=0x00;
-	}
-	i=cmd_out();
-	if (i<0) return (i);
-	if ((famT_drive)&&(i<response_count)) return (-100-i);
-	if ((fam1_drive)||(fam0LV_drive))
-	{
-		current_drive->TocEnt_nixbyte=infobuf[0];
-		i=1;
-	}
-	else if (fam2_drive) i=0;
-	else if (famT_drive) i=5;
-	current_drive->TocEnt_ctl_adr=swap_nibbles(infobuf[i++]);
-	if ((fam1_drive)||(fam0L_drive))
-	{
-		current_drive->TocEnt_number=infobuf[i++];
-		current_drive->TocEnt_format=infobuf[i];
-	}
-	else
-	  {
-	    current_drive->TocEnt_number=num;
-	    current_drive->TocEnt_format=0;
-	  }
-	if (fam1_drive) i=4;
-	else if (fam0LV_drive) i=5;
-	else if (fam2_drive) i=2;
-	else if (famT_drive) i=9;
-	current_drive->TocEnt_address=make32(make16(0,infobuf[i]),
-				     make16(infobuf[i+1],infobuf[i+2]));
-	for (i=0;i<response_count;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_ECS,"TocEntry:%s\n", msgbuf);
-	msg(DBG_TOC,"TocEntry: %02X %02X %02X %02X %08X\n",
-	    current_drive->TocEnt_nixbyte, current_drive->TocEnt_ctl_adr,
-	    current_drive->TocEnt_number, current_drive->TocEnt_format,
-	    current_drive->TocEnt_address);
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ReadPacket(void)
-{
-	int i;
-	
-	clr_cmdbuf();
-	drvcmd[0]=CMD0_PACKET;
-	drvcmd[1]=response_count;
-	if(famL_drive) flags_cmd_out=f_putcmd;
-	else if (fam01_drive)
-		flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
-	else if (fam2_drive) return (-1); /* not implemented yet */
-	else if (famT_drive)
-	{
-		return (-1);
-	}
-	i=cmd_out();
-	return (i);
-}
-/*==========================================================================*/
-static int convert_UPC(u_char *p)
-{
-	int i;
-	
-	p++;
-	if (fam0L_drive) p[13]=0;
-	for (i=0;i<7;i++)
-	{
-		if (fam1_drive) current_drive->UPC_buf[i]=swap_nibbles(*p++);
-		else if (fam0L_drive)
-		{
-			current_drive->UPC_buf[i]=((*p++)<<4)&0xFF;
-			current_drive->UPC_buf[i] |= *p++;
-		}
-		else if (famT_drive)
-		{
-			return (-1);
-		}
-		else /* CD200 */
-		{
-			return (-1);
-		}
-	}
-	current_drive->UPC_buf[6] &= 0xF0;
-	return (0);
-}
-/*==========================================================================*/
-static int cc_ReadUPC(void)
-{
-	int i;
-#if TEST_UPC
-	int block, checksum;
-#endif /* TEST_UPC */ 
-	
-	if (fam2_drive) return (0); /* not implemented yet */
-	if (famT_drive)	return (0); /* not implemented yet */
-	if (famV_drive)	return (0); /* not implemented yet */
-#if 1
-	if (fam0_drive) return (0); /* but it should work */
-#endif
-	
-	current_drive->diskstate_flags &= ~upc_bit;
-#if TEST_UPC
-	for (block=CD_MSF_OFFSET+1;block<CD_MSF_OFFSET+200;block++)
-	{
-#endif /* TEST_UPC */ 
-		clr_cmdbuf();
-		if (fam1_drive)
-		{
-			drvcmd[0]=CMD1_READ_UPC;
-#if TEST_UPC
-			drvcmd[1]=(block>>16)&0xFF;
-			drvcmd[2]=(block>>8)&0xFF;
-			drvcmd[3]=block&0xFF;
-#endif /* TEST_UPC */ 
-			response_count=8;
-			flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-		}
-		else if (fam0L_drive)
-		{
-			drvcmd[0]=CMD0_READ_UPC;
-#if TEST_UPC
-			drvcmd[2]=(block>>16)&0xFF;
-			drvcmd[3]=(block>>8)&0xFF;
-			drvcmd[4]=block&0xFF;
-#endif /* TEST_UPC */ 
-			response_count=0;
-			flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-		}
-		else if (fam2_drive)
-		{
-			return (-1);
-		}
-		else if (famT_drive)
-		{
-			return (-1);
-		}
-		i=cmd_out();
-		if (i<0)
-		{
-			msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
-			return (i);
-		}
-		if (fam0L_drive)
-		{
-			response_count=16;
-			if (famL_drive) flags_cmd_out=f_putcmd;
-			i=cc_ReadPacket();
-			if (i<0)
-			{
-				msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
-				return (i);
-			}
-		}
-#if TEST_UPC
-		checksum=0;
-#endif /* TEST_UPC */ 
-		for (i=0;i<(fam1_drive?8:16);i++)
-		{
-#if TEST_UPC
-			checksum |= infobuf[i];
-#endif /* TEST_UPC */ 
-			sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-		}
-		msgbuf[i*3]=0;
-		msg(DBG_UPC,"UPC info:%s\n", msgbuf);
-#if TEST_UPC
-		if ((checksum&0x7F)!=0) break;
-	}
-#endif /* TEST_UPC */ 
-	current_drive->UPC_ctl_adr=0;
-	if (fam1_drive) i=0;
-	else i=2;
-	if ((infobuf[i]&0x80)!=0)
-	{
-		convert_UPC(&infobuf[i]);
-		current_drive->UPC_ctl_adr = (current_drive->TocEnt_ctl_adr & 0xF0) | 0x02;
-	}
-	for (i=0;i<7;i++)
-		sprintf(&msgbuf[i*3], " %02X", current_drive->UPC_buf[i]);
-	sprintf(&msgbuf[i*3], " (%02X)", current_drive->UPC_ctl_adr);
-	msgbuf[i*3+5]=0;
-	msg(DBG_UPC,"UPC code:%s\n", msgbuf);
-	current_drive->diskstate_flags |= upc_bit;
-	return (0);
-}
-
-static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
-	int i;
-	unsigned char *mcnp = mcn->medium_catalog_number;
-	unsigned char *resp;
-
-	current_drive->diskstate_flags &= ~upc_bit;
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_READ_UPC;
-		response_count=8;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-	}
-	else if (fam0L_drive)
-	{
-		drvcmd[0]=CMD0_READ_UPC;
-		response_count=0;
-		flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
-	}
-	else if (fam2_drive)
-	{
-		return (-1);
-	}
-	else if (famT_drive)
-	{
-		return (-1);
-	}
-	i=cmd_out();
-	if (i<0)
-	{
-		msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
-		return (i);
-	}
-	if (fam0L_drive)
-	{
-		response_count=16;
-		if (famL_drive) flags_cmd_out=f_putcmd;
-		i=cc_ReadPacket();
-		if (i<0)
-		{
-			msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
-			return (i);
-		}
-	}
-	current_drive->UPC_ctl_adr=0;
-	if (fam1_drive) i=0;
-	else i=2;
-
-	resp = infobuf + i;
-	if (*resp++ == 0x80) {
-		/* packed bcd to single ASCII digits */
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-		*mcnp++ = (*resp++ & 0x0f) + '0';
-		*mcnp++ = (*resp >> 4)     + '0';
-	}
-	*mcnp = '\0';
-
-	current_drive->diskstate_flags |= upc_bit;
-	return (0);
-}
-
-/*==========================================================================*/
-static int cc_CheckMultiSession(void)
-{
-	int i;
-	
-	if (fam2_drive) return (0);
-	current_drive->f_multisession=0;
-	current_drive->lba_multi=0;
-	if (fam0_drive) return (0);
-	clr_cmdbuf();
-	if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_MULTISESS;
-		response_count=6;
-		flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
-		i=cmd_out();
-		if (i<0) return (i);
-		if ((infobuf[0]&0x80)!=0)
-		{
-			current_drive->f_multisession=1;
-			current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[1]),
-							make16(infobuf[2],infobuf[3])));
-		}
-	}
-	else if (famLV_drive)
-	{
-		drvcmd[0]=CMDL_MULTISESS;
-		drvcmd[1]=3;
-		drvcmd[2]=1;
-		response_count=8;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-		if (i<0) return (i);
-		current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),
-						make16(infobuf[6],infobuf[7])));
-	}
-	else if (famT_drive)
-	{
-		response_count=12;
-		drvcmd[0]=CMDT_DISKINFO;
-		drvcmd[1]=0x02;
-		drvcmd[6]=0;
-		drvcmd[8]=response_count;
-		drvcmd[9]=0x40;
-		i=cmd_out();
-		if (i<0) return (i);
-		if (i<response_count) return (-100-i);
-		current_drive->first_session=infobuf[2];
-		current_drive->last_session=infobuf[3];
-		current_drive->track_of_last_session=infobuf[6];
-		if (current_drive->first_session!=current_drive->last_session)
-		{
-			current_drive->f_multisession=1;
-			current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11])));
-		}
-	}
-	for (i=0;i<response_count;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, current_drive->lba_multi);
-	if (current_drive->lba_multi>200)
-	{
-		current_drive->f_multisession=1;
-		msg(DBG_MUL,"MultiSession base: %06X\n", current_drive->lba_multi);
-	}
-	return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-static int cc_SubChanInfo(int frame, int count, u_char *buffer)
-	/* "frame" is a RED BOOK (msf-bin) address */
-{
-	int i;
-	
-	if (fam0LV_drive) return (-ENOSYS); /* drive firmware lacks it */
-	if (famT_drive)
-	{
-		return (-1);
-	}
-#if 0
-	if (current_drive->audio_state!=audio_playing) return (-ENODATA);
-#endif
-	clr_cmdbuf();
-	drvcmd[0]=CMD1_SUBCHANINF;
-	drvcmd[1]=(frame>>16)&0xFF;
-	drvcmd[2]=(frame>>8)&0xFF;
-	drvcmd[3]=frame&0xFF;
-	drvcmd[5]=(count>>8)&0xFF;
-	drvcmd[6]=count&0xFF;
-	flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
-	cmd_type=READ_SC;
-	current_drive->frame_size=CD_FRAMESIZE_SUB;
-	i=cmd_out(); /* which buffer to use? */
-	return (i);
-}
-#endif /* FUTURE */ 
-/*==========================================================================*/
-static void __init check_datarate(void)
-{
-	int i=0;
-	
-	msg(DBG_IOX,"check_datarate entered.\n");
-	datarate=0;
-#if TEST_STI
-	for (i=0;i<=1000;i++) printk(".");
-#endif
-	/* set a timer to make (timed_out_delay!=0) after 1.1 seconds */
-#if 1
-	del_timer(&delay_timer);
-#endif
-	delay_timer.expires=jiffies+11*HZ/10;
-	timed_out_delay=0;
-	add_timer(&delay_timer);
-#if 0
-	msg(DBG_TIM,"delay timer started (11*HZ/10).\n");
-#endif
-	do
-	{
-		i=inb(CDi_status);
-		datarate++;
-#if 1
-		if (datarate>0x6FFFFFFF) break;
-#endif 
-	}
-	while (!timed_out_delay);
-	del_timer(&delay_timer);
-#if 0
-	msg(DBG_TIM,"datarate: %04X\n", datarate);
-#endif
-	if (datarate<65536) datarate=65536;
-	maxtim16=datarate*16;
-	maxtim04=datarate*4;
-	maxtim02=datarate*2;
-	maxtim_8=datarate/32;
-#if LONG_TIMING
-	maxtim_data=datarate/100;
-#else
-	maxtim_data=datarate/300;
-#endif /* LONG_TIMING */ 
-#if 0
-	msg(DBG_TIM,"maxtim_8 %d, maxtim_data %d.\n", maxtim_8, maxtim_data);
-#endif
-}
-/*==========================================================================*/
-#if 0
-static int c2_ReadError(int fam)
-{
-	int i;
-	
-	clr_cmdbuf();
-	response_count=9;
-	clr_respo_buf(9);
-	if (fam==1)
-	{
-		drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
-		i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus);
-	}
-	else if (fam==2)
-	{
-		drvcmd[0]=CMD2_READ_ERR;
-		i=do_cmd(f_putcmd);
-	}
-	else return (-1);
-	return (i);
-}
-#endif
-/*==========================================================================*/
-static void __init ask_mail(void)
-{
-	int i;
-	
-	msg(DBG_INF, "please mail the following lines to emoenke@gwdg.de\n");
-	msg(DBG_INF, "(don't mail if you are not using the actual kernel):\n");
-	msg(DBG_INF, "%s\n", VERSION);
-	msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)\n",
-	    CDo_command, type, current_drive->drive_model, current_drive->drv_id);
-	for (i=0;i<12;i++)
-		sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_INF,"infobuf =%s\n", msgbuf);
-	for (i=0;i<12;i++)
-		sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
-	msgbuf[i*3]=0;
-	msg(DBG_INF,"infobuf =%s\n", msgbuf);
-}
-/*==========================================================================*/
-static int __init check_version(void)
-{
-	int i, j, l;
-	int teac_possible=0;
-	
-	msg(DBG_INI,"check_version: id=%d, d=%d.\n", current_drive->drv_id, current_drive - D_S);
-	current_drive->drv_type=0;
-
-	/* check for CR-52x, CR-56x, LCS-7260 and ECS-AT */
-	/* clear any pending error state */
-	clr_cmdbuf();
-	drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
-	response_count=9;
-	flags_cmd_out=f_putcmd;
-	i=cmd_out();
-	if (i<0) msg(DBG_INI,"CMD0_READ_ERR returns %d (ok anyway).\n",i);
-	/* read drive version */
-	clr_cmdbuf();
-	for (i=0;i<12;i++) infobuf[i]=0;
-	drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */
-	response_count=12; /* fam1: only 11 */
-	flags_cmd_out=f_putcmd;
-	i=cmd_out();
-	if (i<-1) msg(DBG_INI,"CMD0_READ_VER returns %d\n",i);
-	if (i==-11) teac_possible++;
-	j=0;
-	for (i=0;i<12;i++) j+=infobuf[i];
-	if (j)
-	{
-		for (i=0;i<12;i++)
-			sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_ECS,"infobuf =%s\n", msgbuf);
-		for (i=0;i<12;i++)
-			sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_ECS,"infobuf =%s\n", msgbuf);
-	}
-	for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break;
-	if (i==4)
-	{
-		current_drive->drive_model[0]='C';
-		current_drive->drive_model[1]='R';
-		current_drive->drive_model[2]='-';
-		current_drive->drive_model[3]='5';
-		current_drive->drive_model[4]=infobuf[i++];
-		current_drive->drive_model[5]=infobuf[i++];
-		current_drive->drive_model[6]=0;
-		current_drive->drv_type=drv_fam1;
-	}
-	if (!current_drive->drv_type)
-	{
-		for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break;
-		if (i==8)
-		{
-			current_drive->drive_model[0]='C';
-			current_drive->drive_model[1]='R';
-			current_drive->drive_model[2]='-';
-			current_drive->drive_model[3]='5';
-			current_drive->drive_model[4]='2';
-			current_drive->drive_model[5]='x';
-			current_drive->drive_model[6]=0;
-			current_drive->drv_type=drv_fam0;
-		}
-	}
-	if (!current_drive->drv_type)
-	{
-		for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break;
-		if (i==8)
-		{
-			for (j=0;j<8;j++)
-				current_drive->drive_model[j]=infobuf[j];
-			current_drive->drive_model[8]=0;
-			current_drive->drv_type=drv_famL;
-		}
-	}
-	if (!current_drive->drv_type)
-	{
-		for (i=0;i<6;i++) if (infobuf[i]!=familyV[i]) break;
-		if (i==6)
-		{
-			for (j=0;j<6;j++)
-				current_drive->drive_model[j]=infobuf[j];
-			current_drive->drive_model[6]=0;
-			current_drive->drv_type=drv_famV;
-			i+=2; /* 2 blanks before version */
-		}
-	}
-	if (!current_drive->drv_type)
-	{
-		/* check for CD200 */
-		clr_cmdbuf();
-		drvcmd[0]=CMD2_READ_ERR;
-		response_count=9;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-		if (i<0) msg(DBG_INI,"CMD2_READERR returns %d (ok anyway).\n",i);
-		if (i<0) msg(DBG_000,"CMD2_READERR returns %d (ok anyway).\n",i);
-		/* read drive version */
-		clr_cmdbuf();
-		for (i=0;i<12;i++) infobuf[i]=0;
-		if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-#if 0
-		OUT(CDo_reset,0);
-		sbp_sleep(6*HZ);
-		OUT(CDo_enable,current_drive->drv_sel);
-#endif
-		drvcmd[0]=CMD2_READ_VER;
-		response_count=12;
-		flags_cmd_out=f_putcmd;
-		i=cmd_out();
-		if (i<0) msg(DBG_INI,"CMD2_READ_VER returns %d\n",i);
-		if (i==-7) teac_possible++;
-		j=0;
-		for (i=0;i<12;i++) j+=infobuf[i];
-		if (j)
-		{
-			for (i=0;i<12;i++)
-				sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
-			msgbuf[i*3]=0;
-			msg(DBG_IDX,"infobuf =%s\n", msgbuf);
-			for (i=0;i<12;i++)
-				sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
-			msgbuf[i*3]=0;
-			msg(DBG_IDX,"infobuf =%s\n", msgbuf);
-		}
-		if (i>=0)
-		{
-			for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break;
-			if (i==5)
-			{
-				current_drive->drive_model[0]='C';
-				current_drive->drive_model[1]='D';
-				current_drive->drive_model[2]='2';
-				current_drive->drive_model[3]='0';
-				current_drive->drive_model[4]='0';
-				current_drive->drive_model[5]=infobuf[i++];
-				current_drive->drive_model[6]=infobuf[i++];
-				current_drive->drive_model[7]=0;
-				current_drive->drv_type=drv_fam2;
-			}
-		}
-	}
-	if (!current_drive->drv_type)
-	{
-		/* check for TEAC CD-55A */
-		msg(DBG_TEA,"teac_possible: %d\n",teac_possible);
-		for (j=1;j<=((current_drive->drv_id==0)?3:1);j++)
-		{
-			for (l=1;l<=((current_drive->drv_id==0)?10:1);l++)
-			{
-				msg(DBG_TEA,"TEAC reset #%d-%d.\n", j, l);
-				if (sbpro_type==1) OUT(CDo_reset,0);
-				else
-				{
-					OUT(CDo_enable,current_drive->drv_sel);
-					OUT(CDo_sel_i_d,0);
-					OUT(CDo_command,CMDT_RESET);
-					for (i=0;i<9;i++) OUT(CDo_command,0);
-				}
-				sbp_sleep(5*HZ/10);
-				OUT(CDo_enable,current_drive->drv_sel);
-				OUT(CDo_sel_i_d,0);
-				i=inb(CDi_status);
-				msg(DBG_TEA,"TEAC CDi_status: %02X.\n",i);
-#if 0
-				if (i&s_not_result_ready) continue; /* drive not present or ready */
-#endif
-				i=inb(CDi_info);
-				msg(DBG_TEA,"TEAC CDi_info: %02X.\n",i);
-				if (i==0x55) break; /* drive found */
-			}
-			if (i==0x55) break; /* drive found */
-		}
-		if (i==0x55) /* drive found */
-		{
-			msg(DBG_TEA,"TEAC drive found.\n");
-			clr_cmdbuf();
-			flags_cmd_out=f_putcmd;
-			response_count=12;
-			drvcmd[0]=CMDT_READ_VER;
-			drvcmd[4]=response_count;
-			for (i=0;i<12;i++) infobuf[i]=0;
-			i=cmd_out_T();
-			if (i!=0) msg(DBG_TEA,"cmd_out_T(CMDT_READ_VER) returns %d.\n",i);
-			for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break;
-			if (i==6)
-			{
-				current_drive->drive_model[0]='C';
-				current_drive->drive_model[1]='D';
-				current_drive->drive_model[2]='-';
-				current_drive->drive_model[3]='5';
-				current_drive->drive_model[4]='5';
-				current_drive->drive_model[5]=0;
-				current_drive->drv_type=drv_famT;
-			}
-		}
-	}
-	if (!current_drive->drv_type)
-	{
-		msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,current_drive->drv_id);
-		return (-522);
-	}
-	for (j=0;j<4;j++) current_drive->firmware_version[j]=infobuf[i+j];
-	if (famL_drive)
-	{
-	  u_char lcs_firm_e1[]="A E1";
-	  u_char lcs_firm_f4[]="A4F4";
-		
-	  for (j=0;j<4;j++)
-	    if (current_drive->firmware_version[j]!=lcs_firm_e1[j]) break;
-	  if (j==4) current_drive->drv_type=drv_e1;
-	  
-	  for (j=0;j<4;j++)
-	    if (current_drive->firmware_version[j]!=lcs_firm_f4[j]) break;
-	  if (j==4) current_drive->drv_type=drv_f4;
-
-	  if (current_drive->drv_type==drv_famL) ask_mail();
-	}
-	else if (famT_drive)
-	{
-		j=infobuf[4]; /* one-byte version??? - here: 0x15 */
-		if (j=='5')
-		{
-			current_drive->firmware_version[0]=infobuf[7];
-			current_drive->firmware_version[1]=infobuf[8];
-			current_drive->firmware_version[2]=infobuf[10];
-			current_drive->firmware_version[3]=infobuf[11];
-		}
-		else
-		{
-			if (j!=0x15) ask_mail();
-			current_drive->firmware_version[0]='0';
-			current_drive->firmware_version[1]='.';
-			current_drive->firmware_version[2]='0'+(j>>4);
-			current_drive->firmware_version[3]='0'+(j&0x0f);
-		}
-	}
-	else /* CR-52x, CR-56x, CD200, ECS-AT */
-	{
-		j = (current_drive->firmware_version[0] & 0x0F) * 100 +
-			(current_drive->firmware_version[2] & 0x0F) *10 +
-				(current_drive->firmware_version[3] & 0x0F);
-		if (fam0_drive)
-		{
-			if (j<200) current_drive->drv_type=drv_199;
-			else if (j<201) current_drive->drv_type=drv_200;
-			else if (j<210) current_drive->drv_type=drv_201;
-			else if (j<211) current_drive->drv_type=drv_210;
-			else if (j<300) current_drive->drv_type=drv_211;
-			else if (j>=300) current_drive->drv_type=drv_300;
-		}
-		else if (fam1_drive)
-		{
-			if (j<100) current_drive->drv_type=drv_099;
-			else
-			{
-				current_drive->drv_type=drv_100;
-				if ((j!=500)&&(j!=102)) ask_mail();
-			}
-		}
-		else if (fam2_drive)
-		{
-			if (current_drive->drive_model[5]=='F')
-			{
-				if ((j!=1)&&(j!=35)&&(j!=200)&&(j!=210))
-				  ask_mail(); /* unknown version at time */
-			}
-			else
-			{
-				msg(DBG_INF,"this CD200 drive is not fully supported yet - only audio will work.\n");
-				if ((j!=101)&&(j!=35))
-				  ask_mail(); /* unknown version at time */
-			}
-		}
-		else if (famV_drive)
-		  {
-		    if ((j==100)||(j==150)) current_drive->drv_type=drv_at;
-		    ask_mail(); /* hopefully we get some feedback by this */
-		  }
-	}
-	msg(DBG_LCS,"drive type %02X\n",current_drive->drv_type);
-	msg(DBG_INI,"check_version done.\n");
-	return (0);
-}
-/*==========================================================================*/
-static void switch_drive(struct sbpcd_drive *p)
-{
-	current_drive = p;
-	OUT(CDo_enable,current_drive->drv_sel);
-	msg(DBG_DID,"drive %d (ID=%d) activated.\n",
-		current_drive - D_S, current_drive->drv_id);
-	return;
-}
-/*==========================================================================*/
-#ifdef PATH_CHECK
-/*
- * probe for the presence of an interface card
- */
-static int __init check_card(int port)
-{
-#undef N_RESPO
-#define N_RESPO 20
-	int i, j, k;
-	u_char response[N_RESPO];
-	u_char save_port0;
-	u_char save_port3;
-	
-	msg(DBG_INI,"check_card entered.\n");
-	save_port0=inb(port+0);
-	save_port3=inb(port+3);
-	
-	for (j=0;j<NR_SBPCD;j++)
-	{
-		OUT(port+3,j) ; /* enable drive #j */
-		OUT(port+0,CMD0_PATH_CHECK);
-		for (i=10;i>0;i--) OUT(port+0,0);
-		for (k=0;k<N_RESPO;k++) response[k]=0;
-		for (k=0;k<N_RESPO;k++)
-		{
-			for (i=10000;i>0;i--)
-			{
-				if (inb(port+1)&s_not_result_ready) continue;
-				response[k]=inb(port+0);
-				break;
-			}
-		}
-		for (i=0;i<N_RESPO;i++)
-			sprintf(&msgbuf[i*3], " %02X", response[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
-		OUT(port+0,CMD0_PATH_CHECK);
-		for (i=10;i>0;i--) OUT(port+0,0);
-		for (k=0;k<N_RESPO;k++) response[k]=0xFF;
-		for (k=0;k<N_RESPO;k++)
-		{
-			for (i=10000;i>0;i--)
-			{
-				if (inb(port+1)&s_not_result_ready) continue;
-				response[k]=inb(port+0);
-				break;
-			}
-		}
-		for (i=0;i<N_RESPO;i++)
-			sprintf(&msgbuf[i*3], " %02X", response[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
-
-		if (response[0]==0xAA)
-			if (response[1]==0x55)
-				return (0);
-	}
-	for (j=0;j<NR_SBPCD;j++)
-	{
-		OUT(port+3,j) ; /* enable drive #j */
-		OUT(port+0,CMD2_READ_VER);
-		for (i=10;i>0;i--) OUT(port+0,0);
-		for (k=0;k<N_RESPO;k++) response[k]=0;
-		for (k=0;k<N_RESPO;k++)
-		{
-			for (i=1000000;i>0;i--)
-			{
-				if (inb(port+1)&s_not_result_ready) continue;
-				response[k]=inb(port+0);
-				break;
-			}
-		}
-		for (i=0;i<N_RESPO;i++)
-			sprintf(&msgbuf[i*3], " %02X", response[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
-		OUT(port+0,CMD2_READ_VER);
-		for (i=10;i>0;i--) OUT(port+0,0);
-		for (k=0;k<N_RESPO;k++) response[k]=0xFF;
-		for (k=0;k<N_RESPO;k++)
-		{
-			for (i=1000000;i>0;i--)
-			{
-				if (inb(port+1)&s_not_result_ready) continue;
-				response[k]=inb(port+0);
-				break;
-			}
-		}
-		for (i=0;i<N_RESPO;i++)
-			sprintf(&msgbuf[i*3], " %02X", response[i]);
-		msgbuf[i*3]=0;
-		msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
-		if (response[0]==0xAA)
-			if (response[1]==0x55)
-				return (0);
-	}
-	OUT(port+0,save_port0);
-	OUT(port+3,save_port3);
-	return (0); /* in any case - no real "function" at time */
-}
-#endif /* PATH_CHECK */ 
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * probe for the presence of drives on the selected controller
- */
-static int __init check_drives(void)
-{
-	int i, j;
-	
-	msg(DBG_INI,"check_drives entered.\n");
-	ndrives=0;
-	for (j=0;j<max_drives;j++)
-	{
-		struct sbpcd_drive *p = D_S + ndrives;
-		p->drv_id=j;
-		if (sbpro_type==1) p->drv_sel=(j&0x01)<<1|(j&0x02)>>1;
-		else p->drv_sel=j;
-		switch_drive(p);
-		msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
-		msg(DBG_000,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
-		i=check_version();
-		if (i<0) msg(DBG_INI,"check_version returns %d.\n",i);
-		else
-		{
-			current_drive->drv_options=drv_pattern[j];
-			if (fam0L_drive) current_drive->drv_options&=~(speed_auto|speed_300|speed_150);
-			msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)\n",
-			    current_drive - D_S,
-			    current_drive->drv_id,
-			    current_drive->drive_model,
-			    current_drive->firmware_version,
-			    CDo_command,
-			    sbpro_type);
-			ndrives++;
-		}
-	}
-	for (j=ndrives;j<NR_SBPCD;j++) D_S[j].drv_id=-1;
-	if (ndrives==0) return (-1);
-	return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- *  obtain if requested service disturbs current audio state
- */            
-static int obey_audio_state(u_char audio_state, u_char func,u_char subfunc)
-{
-	switch (audio_state)                   /* audio status from controller  */
-	{
-	case aud_11: /* "audio play in progress" */
-	case audx11:
-		switch (func)                      /* DOS command code */
-		{
-		case cmd_07: /* input flush  */
-		case cmd_0d: /* open device  */
-		case cmd_0e: /* close device */
-		case cmd_0c: /* ioctl output */
-			return (1);
-		case cmd_03: /* ioctl input  */
-			switch (subfunc)
-				/* DOS ioctl input subfunction */
-			{
-			case cxi_00:
-			case cxi_06:
-			case cxi_09:
-				return (1);
-			default:
-				return (ERROR15);
-			}
-			return (1);
-		default:
-			return (ERROR15);
-		}
-		return (1);
-	case aud_12:                  /* "audio play paused"      */
-	case audx12:
-		return (1);
-	default:
-		return (2);
-	}
-}
-/*==========================================================================*/
-/* allowed is only
- * ioctl_o, flush_input, open_device, close_device, 
- * tell_address, tell_volume, tell_capabiliti,
- * tell_framesize, tell_CD_changed, tell_audio_posi
- */
-static int check_allowed1(u_char func1, u_char func2)
-{
-#if 000
-	if (func1==ioctl_o) return (0);
-	if (func1==read_long) return (-1);
-	if (func1==read_long_prefetch) return (-1);
-	if (func1==seek) return (-1);
-	if (func1==audio_play) return (-1);
-	if (func1==audio_pause) return (-1);
-	if (func1==audio_resume) return (-1);
-	if (func1!=ioctl_i) return (0);
-	if (func2==tell_SubQ_run_tot) return (-1);
-	if (func2==tell_cdsize) return (-1);
-	if (func2==tell_TocDescrip) return (-1);
-	if (func2==tell_TocEntry) return (-1);
-	if (func2==tell_subQ_info) return (-1);
-	if (fam1_drive) if (func2==tell_SubChanInfo) return (-1);
-	if (func2==tell_UPC) return (-1);
-#else
-	return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed2(u_char func1, u_char func2)
-{
-#if 000
-	if (func1==read_long) return (-1);
-	if (func1==read_long_prefetch) return (-1);
-	if (func1==seek) return (-1);
-	if (func1==audio_play) return (-1);
-  if (func1!=ioctl_o) return (0);
-	if (fam1_drive)
-	{
-		if (func2==EjectDisk) return (-1);
-		if (func2==CloseTray) return (-1);
-	}
-#else
-	return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed3(u_char func1, u_char func2)
-{
-#if 000
-	if (func1==ioctl_i)
-	{
-		if (func2==tell_address) return (0);
-		if (func2==tell_capabiliti) return (0);
-		if (func2==tell_CD_changed) return (0);
-		if (fam0L_drive) if (func2==tell_SubChanInfo) return (0);
-		return (-1);
-	}
-	if (func1==ioctl_o)
-	{
-		if (func2==DriveReset) return (0);
-		if (fam0L_drive)
-		{
-			if (func2==EjectDisk) return (0);
-			if (func2==LockDoor) return (0);
-	  if (func2==CloseTray) return (0);
-		}
-		return (-1);
-    }
-	if (func1==flush_input) return (-1);
-	if (func1==read_long) return (-1);
-	if (func1==read_long_prefetch) return (-1);
-	if (func1==seek) return (-1);
-	if (func1==audio_play) return (-1);
-	if (func1==audio_pause) return (-1);
-	if (func1==audio_resume) return (-1);
-#else
-	return (0);
-#endif
-}
-/*==========================================================================*/
-static int seek_pos_audio_end(void)
-{
-	int i;
-
-	i=msf2blk(current_drive->pos_audio_end)-1;
-	if (i<0) return (-1);
-	i=cc_Seek(i,0);
-	return (i);
-}
-#endif /* FUTURE */ 
-/*==========================================================================*/
-static int ReadToC(void)
-{
-	int i, j;
-	current_drive->diskstate_flags &= ~toc_bit;
-	current_drive->ored_ctl_adr=0;
-	/* special handling of CD-I HE */
-	if ((current_drive->n_first_track == 2 && current_drive->n_last_track == 2) ||
-             current_drive->xa_byte == 0x10)
-        {
-		current_drive->TocBuffer[1].nixbyte=0;
-		current_drive->TocBuffer[1].ctl_adr=0x40;
-		current_drive->TocBuffer[1].number=1;
-		current_drive->TocBuffer[1].format=0;
-		current_drive->TocBuffer[1].address=blk2msf(0);
-		current_drive->ored_ctl_adr |= 0x40;
-		current_drive->n_first_track = 1;
-		current_drive->n_last_track = 1;
-		current_drive->xa_byte = 0x10;
-                j = 2;
-        } else
-	for (j=current_drive->n_first_track;j<=current_drive->n_last_track;j++)
-	{
-		i=cc_ReadTocEntry(j);
-		if (i<0)
-		{
-			msg(DBG_INF,"cc_ReadTocEntry(%d) returns %d.\n",j,i);
-			return (i);
-		}
-		current_drive->TocBuffer[j].nixbyte=current_drive->TocEnt_nixbyte;
-		current_drive->TocBuffer[j].ctl_adr=current_drive->TocEnt_ctl_adr;
-		current_drive->TocBuffer[j].number=current_drive->TocEnt_number;
-		current_drive->TocBuffer[j].format=current_drive->TocEnt_format;
-		current_drive->TocBuffer[j].address=current_drive->TocEnt_address;
-		current_drive->ored_ctl_adr |= current_drive->TocEnt_ctl_adr;
-	}
-	/* fake entry for LeadOut Track */
-	current_drive->TocBuffer[j].nixbyte=0;
-	current_drive->TocBuffer[j].ctl_adr=0;
-	current_drive->TocBuffer[j].number=CDROM_LEADOUT;
-	current_drive->TocBuffer[j].format=0;
-	current_drive->TocBuffer[j].address=current_drive->size_msf;
-	
-	current_drive->diskstate_flags |= toc_bit;
-	return (0);
-}
-/*==========================================================================*/
-static int DiskInfo(void)
-{
-	int i, j;
-	
-	current_drive->mode=READ_M1;
-	
-#undef LOOP_COUNT
-#define LOOP_COUNT 10 /* needed for some "old" drives */
-	
-	msg(DBG_000,"DiskInfo entered.\n");
-	for (j=1;j<LOOP_COUNT;j++)
-	{
-#if 0
-		i=SetSpeed();
-		if (i<0)
-		{
-			msg(DBG_INF,"DiskInfo: SetSpeed returns %d\n", i);
-			continue;
-		}
-		i=cc_ModeSense();
-		if (i<0)
-		{
-			msg(DBG_INF,"DiskInfo: cc_ModeSense returns %d\n", i);
-			continue;
-		}
-#endif
-		i=cc_ReadCapacity();
-		if (i>=0) break;
-		msg(DBG_INF,"DiskInfo: ReadCapacity #%d returns %d\n", j, i);
-#if 0
-		i=cc_DriveReset();
-#endif
-		if (!fam0_drive && j == 2) break;
-	}
-	if (j==LOOP_COUNT) return (-33); /* give up */
-	
-	i=cc_ReadTocDescr();
-	if (i<0)
-	{
-		msg(DBG_INF,"DiskInfo: ReadTocDescr returns %d\n", i);
-		return (i);
-	}
-	i=ReadToC();
-	if (i<0)
-	{
-		msg(DBG_INF,"DiskInfo: ReadToC returns %d\n", i);
-		return (i);
-	}
-	i=cc_CheckMultiSession();
-	if (i<0)
-	{
-		msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %d\n", i);
-		return (i);
-	}
-	if (current_drive->f_multisession) current_drive->sbp_bufsiz=1;  /* possibly a weird PhotoCD */
-	else current_drive->sbp_bufsiz=buffers;
-	i=cc_ReadTocEntry(current_drive->n_first_track);
-	if (i<0)
-	{
-		msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %d\n", i);
-		return (i);
-	}
-	i=cc_ReadUPC();
-	if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i);
-	if ((fam0L_drive) && (current_drive->xa_byte==0x20 || current_drive->xa_byte == 0x10))
-	{
-		/* XA disk with old drive */
-		cc_ModeSelect(CD_FRAMESIZE_RAW1);
-		cc_ModeSense();
-	}
-	if (famT_drive)	cc_prep_mode_T();
-	msg(DBG_000,"DiskInfo done.\n");
-	return (0);
-}
-
-static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	int st;
-
-	if (CDSL_CURRENT != slot_nr) {
-		 /* we have no changer support */
-		 return -EINVAL;
-	}
-
-        cc_ReadStatus();
-	st=ResponseStatus();
-	if (st<0)
-	{
-		msg(DBG_INF,"sbpcd_drive_status: timeout.\n");
-		return (0);
-	}
-	msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
-	msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
-	msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
-	msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
-	msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
-	msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
-
-#if 0
-  if (!(p->status_bits & p_door_closed)) return CDS_TRAY_OPEN;
-  if (p->status_bits & p_disk_ok) return CDS_DISC_OK;
-  if (p->status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
-
-  return CDS_NO_DISC;
-#else
-  if (p->status_bits & p_spinning) return CDS_DISC_OK;
-/*  return CDS_TRAY_OPEN; */
-  return CDS_NO_DISC;
-  
-#endif
-
-}
-
-
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- *  called always if driver gets entered
- *  returns 0 or ERROR2 or ERROR15
- */
-static int prepare(u_char func, u_char subfunc)
-{
-	int i;
-	
-	if (fam0L_drive)
-	{
-		i=inb(CDi_status);
-		if (i&s_attention) GetStatus();
-	}
-	else if (fam1_drive) GetStatus();
-	else if (fam2_drive) GetStatus();
-	else if (famT_drive) GetStatus();
-	if (current_drive->CD_changed==0xFF)
-	{
-		current_drive->diskstate_flags=0;
-		current_drive->audio_state=0;
-		if (!st_diskok)
-		{
-			i=check_allowed1(func,subfunc);
-			if (i<0) return (-2);
-		}
-		else 
-		{
-			i=check_allowed3(func,subfunc);
-			if (i<0)
-			{
-				current_drive->CD_changed=1;
-				return (-15);
-			}
-		}
-	}
-	else
-	{
-		if (!st_diskok)
-		{
-			current_drive->diskstate_flags=0;
-			current_drive->audio_state=0;
-			i=check_allowed1(func,subfunc);
-			if (i<0) return (-2);
-		}
-		else
-		{ 
-			if (st_busy)
-			{
-				if (current_drive->audio_state!=audio_pausing)
-				{
-					i=check_allowed2(func,subfunc);
-					if (i<0) return (-2);
-				}
-			}
-			else
-			{
-				if (current_drive->audio_state==audio_playing) seek_pos_audio_end();
-				current_drive->audio_state=0;
-			}
-			if (!frame_size_valid)
-			{
-				i=DiskInfo();
-				if (i<0)
-				{
-					current_drive->diskstate_flags=0;
-					current_drive->audio_state=0;
-					i=check_allowed1(func,subfunc);
-					if (i<0) return (-2);
-				}
-			}
-		}
-    }
-	return (0);
-}
-#endif /* FUTURE */ 
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * Check the results of the "get status" command.
- */
-static int sbp_status(void)
-{
-	int st;
-	
-	st=ResponseStatus();
-	if (st<0)
-	{
-		msg(DBG_INF,"sbp_status: timeout.\n");
-		return (0);
-	}
-	
-	if (!st_spinning) msg(DBG_SPI,"motor got off - ignoring.\n");
-	
-	if (st_check) 
-	{
-		msg(DBG_INF,"st_check detected - retrying.\n");
-		return (0);
-	}
-	if (!st_door_closed)
-	{
-		msg(DBG_INF,"door is open - retrying.\n");
-		return (0);
-	}
-	if (!st_caddy_in)
-	{
-		msg(DBG_INF,"disk removed - retrying.\n");
-		return (0);
-	}
-	if (!st_diskok) 
-	{
-		msg(DBG_INF,"!st_diskok detected - retrying.\n");
-		return (0);
-	}
-	if (st_busy) 
-	{
-		msg(DBG_INF,"st_busy detected - retrying.\n");
-		return (0);
-	}
-	return (1);
-}
-/*==========================================================================*/
-		
-static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	ms_infp->addr_format = CDROM_LBA;
-	ms_infp->addr.lba    = p->lba_multi;
-	if (p->f_multisession)
-		ms_infp->xa_flag=1; /* valid redirection address */
-	else
-		ms_infp->xa_flag=0; /* invalid redirection address */
-
-	return  0;
-}
-
-static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
-		       void * arg)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	int i, st, j;
-	
-	msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg);
-	if (p->drv_id==-1) {
-		msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
-		return (-ENXIO);             /* no such drive */
-	}
-	down(&ioctl_read_sem);
-	if (p != current_drive)
-		switch_drive(p);
-	
-	msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
-	switch (cmd) 		/* Sun-compatible */
-	{
-		
-	case CDROMPAUSE:     /* Pause the drive */
-		msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n");
-		/* pause the drive unit when it is currently in PLAY mode,         */
-		/* or reset the starting and ending locations when in PAUSED mode. */
-		/* If applicable, at the next stopping point it reaches            */
-		/* the drive will discontinue playing.                             */
-		switch (current_drive->audio_state)
-		{
-		case audio_playing:
-			if (famL_drive) i=cc_ReadSubQ();
-			else i=cc_Pause_Resume(1);
-			if (i<0) RETURN_UP(-EIO);
-			if (famL_drive) i=cc_Pause_Resume(1);
-			else i=cc_ReadSubQ();
-			if (i<0) RETURN_UP(-EIO);
-			current_drive->pos_audio_start=current_drive->SubQ_run_tot;
-			current_drive->audio_state=audio_pausing;
-			RETURN_UP(0);
-		case audio_pausing:
-			i=cc_Seek(current_drive->pos_audio_start,1);
-			if (i<0) RETURN_UP(-EIO);
-			RETURN_UP(0);
-		default:
-			RETURN_UP(-EINVAL);
-		}
-
-	case CDROMRESUME: /* resume paused audio play */
-		msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n");
-		/* resume playing audio tracks when a previous PLAY AUDIO call has  */
-		/* been paused with a PAUSE command.                                */
-		/* It will resume playing from the location saved in SubQ_run_tot.  */
-		if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL);
-		if (famL_drive)
-			i=cc_PlayAudio(current_drive->pos_audio_start,
-				       current_drive->pos_audio_end);
-		else i=cc_Pause_Resume(3);
-		if (i<0) RETURN_UP(-EIO);
-		current_drive->audio_state=audio_playing;
-		RETURN_UP(0);
-
-	case CDROMPLAYMSF:
-		msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-		if (current_drive->audio_state==audio_playing)
-		{
-			i=cc_Pause_Resume(1);
-			if (i<0) RETURN_UP(-EIO);
-			i=cc_ReadSubQ();
-			if (i<0) RETURN_UP(-EIO);
-			current_drive->pos_audio_start=current_drive->SubQ_run_tot;
-			i=cc_Seek(current_drive->pos_audio_start,1);
-		}
-		memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf));
-		/* values come as msf-bin */
-		current_drive->pos_audio_start = (msf.cdmsf_min0<<16) |
-                        (msf.cdmsf_sec0<<8) |
-				msf.cdmsf_frame0;
-		current_drive->pos_audio_end = (msf.cdmsf_min1<<16) |
-			(msf.cdmsf_sec1<<8) |
-				msf.cdmsf_frame1;
-		msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n",
-		    current_drive->pos_audio_start,current_drive->pos_audio_end);
-		i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
-		if (i<0)
-		{
-			msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
-			DriveReset();
-			current_drive->audio_state=0;
-			RETURN_UP(-EIO);
-		}
-		current_drive->audio_state=audio_playing;
-		RETURN_UP(0);
-		
-	case CDROMPLAYTRKIND: /* Play a track.  This currently ignores index. */
-		msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-		if (current_drive->audio_state==audio_playing)
-		{
-			msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
-#if 1
-			RETURN_UP(0); /* just let us play on */
-#else
-			RETURN_UP(-EINVAL); /* play on, but say "error" */
-#endif
-		}
-		memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti));
-		msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
-		    ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
-		if (ti.cdti_trk0<current_drive->n_first_track) RETURN_UP(-EINVAL);
-		if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL);
-		if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
-		if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track;
-		current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address;
-		current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address;
-		i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
-		if (i<0)
-		{
-			msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
-			DriveReset();
-			current_drive->audio_state=0;
-			RETURN_UP(-EIO);
-		}
-		current_drive->audio_state=audio_playing;
-		RETURN_UP(0);
-		
-	case CDROMREADTOCHDR:        /* Read the table of contents header */
-		msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
-		tochdr.cdth_trk0=current_drive->n_first_track;
-		tochdr.cdth_trk1=current_drive->n_last_track;
-		memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
-		RETURN_UP(0);
-		
-	case CDROMREADTOCENTRY:      /* Read an entry in the table of contents */
-		msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
-		memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
-		i=tocentry.cdte_track;
-		if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1;
-		else if (i<current_drive->n_first_track||i>current_drive->n_last_track)
-                  RETURN_UP(-EINVAL);
-		tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F;
-		tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F;
-		tocentry.cdte_datamode=current_drive->TocBuffer[i].format;
-		if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
-		{
-			tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF;
-			tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF;
-			tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF;
-		}
-		else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
-			tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address);
-		else RETURN_UP(-EINVAL);
-		memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
-		RETURN_UP(0);
-		
-	case CDROMSTOP:      /* Spin down the drive */
-		msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */ 
-		i=cc_Pause_Resume(1);
-		current_drive->audio_state=0;
-#if 0
-		cc_DriveReset();
-#endif
-		RETURN_UP(i);
-
-	case CDROMSTART:  /* Spin up the drive */
-		msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
-		cc_SpinUp();
-		current_drive->audio_state=0;
-		RETURN_UP(0);
-
-	case CDROMVOLCTRL:   /* Volume control */
-		msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
-		memcpy(&volctrl,(char *) arg,sizeof(volctrl));
-		current_drive->vol_chan0=0;
-		current_drive->vol_ctrl0=volctrl.channel0;
-		current_drive->vol_chan1=1;
-		current_drive->vol_ctrl1=volctrl.channel1;
-		i=cc_SetVolume();
-		RETURN_UP(0);
-
-	case CDROMVOLREAD:   /* read Volume settings from drive */
-		msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
-		st=cc_GetVolume();
-		if (st<0) RETURN_UP(st);
-		volctrl.channel0=current_drive->vol_ctrl0;
-		volctrl.channel1=current_drive->vol_ctrl1;
-		volctrl.channel2=0;
-		volctrl.channel2=0;
-		memcpy((void *)arg,&volctrl,sizeof(volctrl));
-		RETURN_UP(0);
-
-	case CDROMSUBCHNL:   /* Get subchannel info */
-		msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n");
-		/* Bogus, I can do better than this! --AJK
-		if ((st_spinning)||(!subq_valid)) {
-			i=cc_ReadSubQ();
-			if (i<0) RETURN_UP(-EIO);
-		}
-		*/
-		i=cc_ReadSubQ();
-		if (i<0) {
-			j=cc_ReadError(); /* clear out error status from drive */
-			current_drive->audio_state=CDROM_AUDIO_NO_STATUS;
-			/* get and set the disk state here,
-			probably not the right place, but who cares!
-			It makes it work properly! --AJK */
-			if (current_drive->CD_changed==0xFF) {
-				msg(DBG_000,"Disk changed detect\n");
-				current_drive->diskstate_flags &= ~cd_size_bit;
-			}
-			RETURN_UP(-EIO);
-		}
-		if (current_drive->CD_changed==0xFF) {
-			/* reread the TOC because the disk has changed! --AJK */
-			msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n");
-			i=DiskInfo();
-			if(i==0) {
-				current_drive->CD_changed=0x00; /* cd has changed, procede, */
-				RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */
-			} else {
-				RETURN_UP(-EIO); /* we weren't ready yet! --AJK */
-			}
-		}
-		memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
-		/*
-			This virtual crap is very bogus!
-			It doesn't detect when the cd is done playing audio!
-			Lets do this right with proper hardware register reading!
-		*/
-		cc_ReadStatus();
-		i=ResponseStatus();
-		msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
-		msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
-		msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
-		msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
-		msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
-		msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
-		/* st_busy indicates if it's _ACTUALLY_ playing audio */
-		switch (current_drive->audio_state)
-		{
-		case audio_playing:
-			if(st_busy==0) {
-				/* CD has stopped playing audio --AJK */
-				current_drive->audio_state=audio_completed;
-				SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
-			} else {
-				SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
-			}
-			break;
-		case audio_pausing:
-			SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
-			break;
-		case audio_completed:
-			SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
-			break;
-		default:
-			SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
-			break;
-		}
-		SC.cdsc_adr=current_drive->SubQ_ctl_adr;
-		SC.cdsc_ctrl=current_drive->SubQ_ctl_adr>>4;
-		SC.cdsc_trk=bcd2bin(current_drive->SubQ_trk);
-		SC.cdsc_ind=bcd2bin(current_drive->SubQ_pnt_idx);
-		if (SC.cdsc_format==CDROM_LBA)
-		{
-			SC.cdsc_absaddr.lba=msf2blk(current_drive->SubQ_run_tot);
-			SC.cdsc_reladdr.lba=msf2blk(current_drive->SubQ_run_trk);
-		}
-		else /* not only if (SC.cdsc_format==CDROM_MSF) */
-		{
-			SC.cdsc_absaddr.msf.minute=(current_drive->SubQ_run_tot>>16)&0x00FF;
-			SC.cdsc_absaddr.msf.second=(current_drive->SubQ_run_tot>>8)&0x00FF;
-			SC.cdsc_absaddr.msf.frame=current_drive->SubQ_run_tot&0x00FF;
-			SC.cdsc_reladdr.msf.minute=(current_drive->SubQ_run_trk>>16)&0x00FF;
-			SC.cdsc_reladdr.msf.second=(current_drive->SubQ_run_trk>>8)&0x00FF;
-			SC.cdsc_reladdr.msf.frame=current_drive->SubQ_run_trk&0x00FF;
-		}
-		memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl));
-		msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
-		    SC.cdsc_format,SC.cdsc_audiostatus,
-		    SC.cdsc_adr,SC.cdsc_ctrl,
-		    SC.cdsc_trk,SC.cdsc_ind,
-		    SC.cdsc_absaddr,SC.cdsc_reladdr);
-		RETURN_UP(0);
-
-	default:
-		msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
-		RETURN_UP(-EINVAL);
-	} /* end switch(cmd) */
-}
-/*==========================================================================*/
-/*
- *  Take care of the different block sizes between cdrom and Linux.
- */
-static void sbp_transfer(struct request *req)
-{
-	long offs;
-
-	while ( (req->nr_sectors > 0) &&
-	       (req->sector/4 >= current_drive->sbp_first_frame) &&
-	       (req->sector/4 <= current_drive->sbp_last_frame) )
-	{
-		offs = (req->sector - current_drive->sbp_first_frame * 4) * 512;
-		memcpy(req->buffer, current_drive->sbp_buf + offs, 512);
-		req->nr_sectors--;
-		req->sector++;
-		req->buffer += 512;
-	}
-}
-/*==========================================================================*/
-/*
- *  special end_request for sbpcd to solve CURRENT==NULL bug. (GTL)
- *  GTL = Gonzalo Tornaria <tornaria@cmat.edu.uy>
- *
- *  This is a kludge so we don't need to modify end_request.
- *  We put the req we take out after INIT_REQUEST in the requests list,
- *  so that end_request will discard it.
- *
- *  The bug could be present in other block devices, perhaps we
- *  should modify INIT_REQUEST and end_request instead, and
- *  change every block device..
- *
- *  Could be a race here?? Could e.g. a timer interrupt schedule() us?
- *  If so, we should copy end_request here, and do it right.. (or
- *  modify end_request and the block devices).
- *
- *  In any case, the race here would be much small than it was, and
- *  I couldn't reproduce..
- *
- *  The race could be: suppose CURRENT==NULL. We put our req in the list,
- *  and we are scheduled. Other process takes over, and gets into
- *  do_sbpcd_request. It sees CURRENT!=NULL (it is == to our req), so
- *  proceeds. It ends, so CURRENT is now NULL.. Now we awake somewhere in
- *  end_request, but now CURRENT==NULL... oops!
- *
- */
-#undef DEBUG_GTL
-
-/*==========================================================================*/
-/*
- *  I/O request routine, called from Linux kernel.
- */
-static void do_sbpcd_request(request_queue_t * q)
-{
-	u_int block;
-	u_int nsect;
-	int status_tries, data_tries;
-	struct request *req;
-	struct sbpcd_drive *p;
-#ifdef DEBUG_GTL
-	static int xx_nr=0;
-	int xnr;
-#endif
-
- request_loop:
-#ifdef DEBUG_GTL
-	xnr=++xx_nr;
-
-	req = elv_next_request(q);
-
-	if (!req)
-	{
-		printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n",
-			xnr, current->pid, jiffies);
-		printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n",
-			xnr, jiffies);
-		return;
-	}
-
-	printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n",
-		xnr, req, req->sector, req->nr_sectors, current->pid, jiffies);
-#endif
-
-	req = elv_next_request(q);	/* take out our request so no other */
-	if (!req)
-		return;
-
-	if (req -> sector == -1)
-		end_request(req, 0);
-	spin_unlock_irq(q->queue_lock);
-
-	down(&ioctl_read_sem);
-	if (rq_data_dir(elv_next_request(q)) != READ)
-	{
-		msg(DBG_INF, "bad cmd %d\n", req->cmd[0]);
-		goto err_done;
-	}
-	p = req->rq_disk->private_data;
-#if OLD_BUSY
-	while (busy_audio) sbp_sleep(HZ); /* wait a bit */
-	busy_data=1;
-#endif /* OLD_BUSY */
-
-	if (p->audio_state==audio_playing) goto err_done;
-	if (p != current_drive)
-		switch_drive(p);
-
-	block = req->sector; /* always numbered as 512-byte-pieces */
-	nsect = req->nr_sectors; /* always counted as 512-byte-pieces */
-
-	msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect);
-#if 0
-	msg(DBG_MUL,"read LBA %d\n", block/4);
-#endif
-
-	sbp_transfer(req);
-	/* if we satisfied the request from the buffer, we're done. */
-	if (req->nr_sectors == 0)
-	{
-#ifdef DEBUG_GTL
-		printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n",
-			xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
-		up(&ioctl_read_sem);
-		spin_lock_irq(q->queue_lock);
-		end_request(req, 1);
-		goto request_loop;
-	}
-
-#ifdef FUTURE
-	i=prepare(0,0); /* at moment not really a hassle check, but ... */
-	if (i!=0)
-		msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i);
-#endif /* FUTURE */
-
-	if (!st_spinning) cc_SpinUp();
-
-	for (data_tries=n_retries; data_tries > 0; data_tries--)
-	{
-		for (status_tries=3; status_tries > 0; status_tries--)
-		{
-			flags_cmd_out |= f_respo3;
-			cc_ReadStatus();
-			if (sbp_status() != 0) break;
-			if (st_check) cc_ReadError();
-			sbp_sleep(1);    /* wait a bit, try again */
-		}
-		if (status_tries == 0)
-		{
-			msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__);
-			break;
-		}
-		
-		sbp_read_cmd(req);
-		sbp_sleep(0);
-		if (sbp_data(req) != 0)
-		{
-#ifdef SAFE_MIXED
-			current_drive->has_data=2; /* is really a data disk */
-#endif /* SAFE_MIXED */
-#ifdef DEBUG_GTL
-			printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n",
-				xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
-			up(&ioctl_read_sem);
-			spin_lock_irq(q->queue_lock);
-			end_request(req, 1);
-			goto request_loop;
-		}
-	}
-
- err_done:
-#if OLD_BUSY
-	busy_data=0;
-#endif /* OLD_BUSY */
-#ifdef DEBUG_GTL
-	printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n",
-		xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
-	up(&ioctl_read_sem);
-	sbp_sleep(0);    /* wait a bit, try again */
-	spin_lock_irq(q->queue_lock);
-	end_request(req, 0);
-	goto request_loop;
-}
-/*==========================================================================*/
-/*
- *  build and send the READ command.
- */
-static void sbp_read_cmd(struct request *req)
-{
-#undef OLD
-
-	int i;
-	int block;
-
-	current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1;      /* purge buffer */
-	current_drive->sbp_current = 0;
-	block=req->sector/4;
-	if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm)
-		current_drive->sbp_read_frames = current_drive->sbp_bufsiz;
-	else
-	{
-		current_drive->sbp_read_frames=current_drive->CDsize_frm-block;
-		/* avoid reading past end of data */
-		if (current_drive->sbp_read_frames < 1)
-		{
-			msg(DBG_INF,"requested frame %d, CD size %d ???\n",
-			    block, current_drive->CDsize_frm);
-			current_drive->sbp_read_frames=1;
-		}
-	}
-
-	flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
-	clr_cmdbuf();
-	if (famV_drive)
-	  {
-	    drvcmd[0]=CMDV_READ;
-	    lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
-	    bin2bcdx(&drvcmd[1]);
-	    bin2bcdx(&drvcmd[2]);
-	    bin2bcdx(&drvcmd[3]);
-	    drvcmd[4]=current_drive->sbp_read_frames>>8;
-	    drvcmd[5]=current_drive->sbp_read_frames&0xff;
-	    drvcmd[6]=0x02; /* flag "msf-bcd" */
-	}
-	else if (fam0L_drive)
-	{
-		flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
-		if (current_drive->xa_byte==0x20)
-		{
-			cmd_type=READ_M2;
-			drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
-			drvcmd[1]=(block>>16)&0x0ff;
-			drvcmd[2]=(block>>8)&0x0ff;
-			drvcmd[3]=block&0x0ff;
-			drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
-			drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
-		}
-		else
-		{
-			drvcmd[0]=CMD0_READ; /* "read frames", old drives */
-			if (current_drive->drv_type>=drv_201)
-			{
-				lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
-				bin2bcdx(&drvcmd[1]);
-				bin2bcdx(&drvcmd[2]);
-				bin2bcdx(&drvcmd[3]);
-			}
-			else
-			{
-				drvcmd[1]=(block>>16)&0x0ff;
-				drvcmd[2]=(block>>8)&0x0ff;
-				drvcmd[3]=block&0x0ff;
-			}
-			drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
-			drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
-			drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
-		}
-	}
-	else if (fam1_drive)
-	{
-		drvcmd[0]=CMD1_READ;
-		lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-		drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff;
-		drvcmd[6]=current_drive->sbp_read_frames&0x0ff;
-	}
-	else if (fam2_drive)
-	{
-		drvcmd[0]=CMD2_READ;
-		lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-		drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
-		drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
-		drvcmd[6]=0x02;
-	}
-	else if (famT_drive)
-	{
-		drvcmd[0]=CMDT_READ;
-		drvcmd[2]=(block>>24)&0x0ff;
-		drvcmd[3]=(block>>16)&0x0ff;
-		drvcmd[4]=(block>>8)&0x0ff;
-		drvcmd[5]=block&0x0ff;
-		drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff;
-		drvcmd[8]=current_drive->sbp_read_frames&0x0ff;
-	}
-	flags_cmd_out=f_putcmd;
-	response_count=0;
-	i=cmd_out();
-	if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i);
-	return;
-}
-/*==========================================================================*/
-/*
- *  Check the completion of the read-data command.  On success, read
- *  the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer.
- */
-static int sbp_data(struct request *req)
-{
-	int i=0, j=0, l, frame;
-	u_int try=0;
-	u_long timeout;
-	u_char *p;
-	u_int data_tries = 0;
-	u_int data_waits = 0;
-	u_int data_retrying = 0;
-	int error_flag;
-	int xa_count;
-	int max_latency;
-	int success;
-	int wait;
-	int duration;
-
-	error_flag=0;
-	success=0;
-#if LONG_TIMING
-	max_latency=9*HZ;
-#else
-	if (current_drive->f_multisession) max_latency=15*HZ;
-	else max_latency=5*HZ;
-#endif
-	duration=jiffies;
-	for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++)
-	{
-		SBPCD_CLI;
-
-		del_timer(&data_timer);
-		data_timer.expires=jiffies+max_latency;
-		timed_out_data=0;
-		add_timer(&data_timer);
-		while (!timed_out_data)
-		{
-			if (current_drive->f_multisession) try=maxtim_data*4;
-			else try=maxtim_data;
-			msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try);
-			for ( ; try!=0;try--)
-			{
-				j=inb(CDi_status);
-				if (!(j&s_not_data_ready)) break;
-				if (!(j&s_not_result_ready)) break;
-				if (fam0LV_drive) if (j&s_attention) break;
-			}
-			if (!(j&s_not_data_ready)) goto data_ready;
-			if (try==0)
-			{
-				if (data_retrying == 0) data_waits++;
-				data_retrying = 1;
-				msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n");
-				sbp_sleep(1);
-				try = 1;
-			}
-		}
-		msg(DBG_INF,"sbp_data: CDi_status loop expired.\n");
-	data_ready:
-		del_timer(&data_timer);
-
-		if (timed_out_data)
-		{
-			msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j);
-			error_flag++;
-		}
-		if (try==0)
-		{
-			msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j);
-			error_flag++;
-		}
-		if (!(j&s_not_result_ready))
-		{
-			msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j);
-			response_count=20;
-			j=ResponseInfo();
-			j=inb(CDi_status);
-		}
-		if (j&s_not_data_ready)
-		{
-			if ((current_drive->ored_ctl_adr&0x40)==0)
-				msg(DBG_INF, "CD contains no data tracks.\n");
-			else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j);
-			error_flag++;
-		}
-		SBPCD_STI;
-		if (error_flag) break;
-
-		msg(DBG_000, "sbp_data: beginning to read.\n");
-		p = current_drive->sbp_buf + frame *  CD_FRAMESIZE;
-		if (sbpro_type==1) OUT(CDo_sel_i_d,1);
-		if (cmd_type==READ_M2) {
-                        if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1);
-                        else insb(CDi_data, xa_head_buf, CD_XA_HEAD);
-		}
-		if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1);
-		else insb(CDi_data, p, CD_FRAMESIZE);
-		if (cmd_type==READ_M2) {
-                        if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1);
-                        else insb(CDi_data, xa_tail_buf, CD_XA_TAIL);
-		}
-		current_drive->sbp_current++;
-		if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-		if (cmd_type==READ_M2)
-		{
-			for (xa_count=0;xa_count<CD_XA_HEAD;xa_count++)
-				sprintf(&msgbuf[xa_count*3], " %02X", xa_head_buf[xa_count]);
-			msgbuf[xa_count*3]=0;
-			msg(DBG_XA1,"xa head:%s\n", msgbuf);
-		}
-		data_retrying = 0;
-		data_tries++;
-		if (data_tries >= 1000)
-		{
-			msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries);
-			data_waits = data_tries = 0;
-		}
-	}
-	duration=jiffies-duration;
-	msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration);
-	if (famT_drive)
-	{
-		wait=8;
-		do
-		{
-			if (teac==2)
-                          {
-                            if ((i=CDi_stat_loop_T()) == -1) break;
-                          }
-                        else
-                          {
-                            sbp_sleep(1);
-                            OUT(CDo_sel_i_d,0);
-                            i=inb(CDi_status);
-                          }
-			if (!(i&s_not_data_ready))
-			{
-				OUT(CDo_sel_i_d,1);
-				j=0;
-				do
-				{
-					if (do_16bit) i=inw(CDi_data);
-					else i=inb(CDi_data);
-					j++;
-					i=inb(CDi_status);
-				}
-				while (!(i&s_not_data_ready));
-				msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j);
-			}
-			if (!(i&s_not_result_ready))
-			{
-				OUT(CDo_sel_i_d,0);
-				l=0;
-				do
-				{
-					infobuf[l++]=inb(CDi_info);
-					i=inb(CDi_status);
-				}
-				while (!(i&s_not_result_ready));
-				if (infobuf[0]==0x00) success=1;
-#if 1
-				for (j=0;j<l;j++) sprintf(&msgbuf[j*3], " %02X", infobuf[j]);
-				msgbuf[j*3]=0;
-				msg(DBG_TEA,"sbp_data info response:%s\n", msgbuf);
-#endif
-				if (infobuf[0]==0x02)
-				{
-					error_flag++;
-					do
-					{
-						++recursion;
-						if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion);
-						else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n");
-						clr_cmdbuf();
-						drvcmd[0]=CMDT_READ_ERR;
-						j=cmd_out_T(); /* !!! recursive here !!! */
-						--recursion;
-						sbp_sleep(1);
-					}
-					while (j<0);
-					current_drive->error_state=infobuf[2];
-					current_drive->b3=infobuf[3];
-					current_drive->b4=infobuf[4];
-				}
-				break;
-			}
-			else
-			{
-#if 0
-				msg(DBG_TEA, "============= waiting for result=================.\n");
-				sbp_sleep(1);
-#endif
-			}
-		}
-		while (wait--);
-	}
-
-	if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
-	{
-		msg(DBG_TEA, "================error flag: %d=================.\n", error_flag);
-		msg(DBG_INF,"sbp_data: read aborted by drive.\n");
-#if 1
-		i=cc_DriveReset(); /* ugly fix to prevent a hang */
-#else
-		i=cc_ReadError();
-#endif
-		return (0);
-	}
-	
-	if (fam0LV_drive)
-	{
-		SBPCD_CLI;
-		i=maxtim_data;
-		for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
-		{
-			for ( ;i!=0;i--)
-			{
-				j=inb(CDi_status);
-				if (!(j&s_not_data_ready)) break;
-				if (!(j&s_not_result_ready)) break;
-				if (j&s_attention) break;
-			}
-			if (i != 0 || time_after_eq(jiffies, timeout)) break;
-			sbp_sleep(0);
-			i = 1;
-		}
-		if (i==0) msg(DBG_INF,"status timeout after READ.\n");
-		if (!(j&s_attention))
-		{
-			msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n");
-			i=cc_DriveReset();  /* ugly fix to prevent a hang */
-			SBPCD_STI;
-			return (0);
-		}
-		SBPCD_STI;
-	}
-
-#if 0
-	if (!success)
-#endif
-		do
-		{
-			if (fam0LV_drive) cc_ReadStatus();
-#if 1
-			if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i);
-#endif
-			i=ResponseStatus();  /* builds status_bits, returns orig. status (old) or faked p_success (new) */
-#if 1
-			if (famT_drive)	msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i);
-#endif
-			if (i<0)
-			{
-				msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits);
-				return (0);
-			}
-		}
-		while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success)));
-	if (st_check)
-	{
-		i=cc_ReadError();
-		msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i);
-		return (0);
-	}
-	if (fatal_err)
-	{
-		fatal_err=0;
-		current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1;      /* purge buffer */
-		current_drive->sbp_current = 0;
-		msg(DBG_INF,"sbp_data: fatal_err - retrying.\n");
-		return (0);
-	}
-	
-	current_drive->sbp_first_frame = req -> sector / 4;
-	current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1;
-	sbp_transfer(req);
-	return (1);
-}
-/*==========================================================================*/
-
-static int sbpcd_block_open(struct inode *inode, struct file *file)
-{
-	struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
-	return cdrom_open(p->sbpcd_infop, inode, file);
-}
-
-static int sbpcd_block_release(struct inode *inode, struct file *file)
-{
-	struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
-	return cdrom_release(p->sbpcd_infop, file);
-}
-
-static int sbpcd_block_ioctl(struct inode *inode, struct file *file,
-				unsigned cmd, unsigned long arg)
-{
-	struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
-	struct cdrom_device_info *cdi = p->sbpcd_infop;
-	int ret, i;
-
-	ret = cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg);
-	if (ret != -ENOSYS)
-		return ret;
-
-	msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg);
-	if (p->drv_id==-1) {
-		msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
-		return (-ENXIO);             /* no such drive */
-	}
-	down(&ioctl_read_sem);
-	if (p != current_drive)
-		switch_drive(p);
-	
-	msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
-	switch (cmd) 		/* Sun-compatible */
-	{
-	case DDIOCSDBG:		/* DDI Debug */
-		if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
-		i=sbpcd_dbg_ioctl(arg,1);
-		RETURN_UP(i);
-	case CDROMRESET:      /* hard reset the drive */
-		msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
-		i=DriveReset();
-		current_drive->audio_state=0;
-		RETURN_UP(i);
-
-	case CDROMREADMODE1:
-		msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n");
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-		cc_ModeSelect(CD_FRAMESIZE);
-		cc_ModeSense();
-		current_drive->mode=READ_M1;
-		RETURN_UP(0);
-
-	case CDROMREADMODE2: /* not usable at the moment */
-		msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n");
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-		cc_ModeSelect(CD_FRAMESIZE_RAW1);
-		cc_ModeSense();
-		current_drive->mode=READ_M2;
-		RETURN_UP(0);
-
-	case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
-		msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
-		if (current_drive->sbp_audsiz>0)
-			vfree(current_drive->aud_buf);
-		current_drive->aud_buf=NULL;
-		current_drive->sbp_audsiz=arg;
-
-		if (current_drive->sbp_audsiz>16)
-		{
-			current_drive->sbp_audsiz = 0;
-			RETURN_UP(current_drive->sbp_audsiz);
-		}
-	
-		if (current_drive->sbp_audsiz>0)
-		{
-			current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW);
-			if (current_drive->aud_buf==NULL)
-			{
-				msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz);
-				current_drive->sbp_audsiz=0;
-			}
-			else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz);
-		}
-		RETURN_UP(current_drive->sbp_audsiz);
-
-	case CDROMREADAUDIO:
-	{ /* start of CDROMREADAUDIO */
-		int i=0, j=0, frame, block=0;
-		u_int try=0;
-		u_long timeout;
-		u_char *p;
-		u_int data_tries = 0;
-		u_int data_waits = 0;
-		u_int data_retrying = 0;
-		int status_tries;
-		int error_flag;
-
-		msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n");
-		if (fam0_drive) RETURN_UP(-EINVAL);
-		if (famL_drive) RETURN_UP(-EINVAL);
-		if (famV_drive) RETURN_UP(-EINVAL);
-		if (famT_drive) RETURN_UP(-EINVAL);
-#ifdef SAFE_MIXED
-		if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
-		if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL);
-		if (copy_from_user(&read_audio, (void __user *)arg,
-				   sizeof(struct cdrom_read_audio)))
-			RETURN_UP(-EFAULT);
-		if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL);
-		if (!access_ok(VERIFY_WRITE, read_audio.buf,
-			      read_audio.nframes*CD_FRAMESIZE_RAW))
-                	RETURN_UP(-EFAULT);
-
-		if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
-			block=msf2lba(&read_audio.addr.msf.minute);
-		else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
-			block=read_audio.addr.lba;
-		else RETURN_UP(-EINVAL);
-#if 000
-		i=cc_SetSpeed(speed_150,0,0);
-		if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i);
-#endif
-		msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n",
-		    block, blk2msf(block));
-		msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n");
-#if OLD_BUSY
-		while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
-		busy_audio=1;
-#endif /* OLD_BUSY */
-		error_flag=0;
-		for (data_tries=5; data_tries>0; data_tries--)
-		{
-			msg(DBG_AUD,"data_tries=%d ...\n", data_tries);
-			current_drive->mode=READ_AU;
-			cc_ModeSelect(CD_FRAMESIZE_RAW);
-			cc_ModeSense();
-			for (status_tries=3; status_tries > 0; status_tries--)
-			{
-				flags_cmd_out |= f_respo3;
-				cc_ReadStatus();
-				if (sbp_status() != 0) break;
-				if (st_check) cc_ReadError();
-				sbp_sleep(1);    /* wait a bit, try again */
-			}
-			if (status_tries == 0)
-			{
-				msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__);
-				continue;
-			}
-			msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
-
-			flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
-			if (fam0L_drive)
-			{
-				flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
-				cmd_type=READ_M2;
-				drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
-				drvcmd[1]=(block>>16)&0x000000ff;
-				drvcmd[2]=(block>>8)&0x000000ff;
-				drvcmd[3]=block&0x000000ff;
-				drvcmd[4]=0;
-				drvcmd[5]=read_audio.nframes; /* # of frames */
-				drvcmd[6]=0;
-			}
-			else if (fam1_drive)
-			{
-				drvcmd[0]=CMD1_READ; /* "read frames", new drives */
-				lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-				drvcmd[4]=0;
-				drvcmd[5]=0;
-				drvcmd[6]=read_audio.nframes; /* # of frames */
-			}
-			else if (fam2_drive)
-			{
-				drvcmd[0]=CMD2_READ_XA2;
-				lba2msf(block,&drvcmd[1]); /* msf-bin format required */
-				drvcmd[4]=0;
-				drvcmd[5]=read_audio.nframes; /* # of frames */
-				drvcmd[6]=0x11; /* raw mode */
-			}
-			else if (famT_drive) /* CD-55A: not tested yet */
-			{
-			}
-			msg(DBG_AUD,"read_audio: before giving \"read\" command.\n");
-			flags_cmd_out=f_putcmd;
-			response_count=0;
-			i=cmd_out();
-			if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i);
-			sbp_sleep(0);
-			msg(DBG_AUD,"read_audio: after giving \"read\" command.\n");
-			for (frame=1;frame<2 && !error_flag; frame++)
-			{
-				try=maxtim_data;
-				for (timeout=jiffies+9*HZ; ; )
-				{
-					for ( ; try!=0;try--)
-					{
-						j=inb(CDi_status);
-						if (!(j&s_not_data_ready)) break;
-						if (!(j&s_not_result_ready)) break;
-						if (fam0L_drive) if (j&s_attention) break;
-					}
-					if (try != 0 || time_after_eq(jiffies, timeout)) break;
-					if (data_retrying == 0) data_waits++;
-					data_retrying = 1;
-					sbp_sleep(1);
-					try = 1;
-				}
-				if (try==0)
-				{
-					msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n");
-					error_flag++;
-					break;
-				}
-				msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n");
-				if (j&s_not_data_ready)
-				{
-					msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n");
-					error_flag++;
-					break;
-				}
-				msg(DBG_AUD,"read_audio: before reading data.\n");
-				error_flag=0;
-				p = current_drive->aud_buf;
-				if (sbpro_type==1) OUT(CDo_sel_i_d,1);
-				if (do_16bit)
-				{
-					u_short *p2 = (u_short *) p;
-
-					for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
-				  	{
-						if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
-						/* get one sample */
-						*p2++ = inw_p(CDi_data);
-						*p2++ = inw_p(CDi_data);
-					}
-				} else {
-					for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
-				  	{
-						if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
-						/* get one sample */
-						*p++ = inb_p(CDi_data);
-						*p++ = inb_p(CDi_data);
-						*p++ = inb_p(CDi_data);
-						*p++ = inb_p(CDi_data);
-					}
-				}
-				if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-				data_retrying = 0;
-			}
-			msg(DBG_AUD,"read_audio: after reading data.\n");
-			if (error_flag)    /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
-			{
-				msg(DBG_AUD,"read_audio: read aborted by drive\n");
-#if 0000
-				i=cc_DriveReset();                /* ugly fix to prevent a hang */
-#else
-				i=cc_ReadError();
-#endif
-				continue;
-			}
-			if (fam0L_drive)
-			{
-				i=maxtim_data;
-				for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
-				{
-					for ( ;i!=0;i--)
-					{
-						j=inb(CDi_status);
-						if (!(j&s_not_data_ready)) break;
-						if (!(j&s_not_result_ready)) break;
-						if (j&s_attention) break;
-					}
-					if (i != 0 || time_after_eq(jiffies, timeout)) break;
-					sbp_sleep(0);
-					i = 1;
-				}
-				if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ");
-				if (!(j&s_attention))
-				{
-					msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n");
-					i=cc_DriveReset();  /* ugly fix to prevent a hang */
-					continue;
-				}
-			}
-			do
-			{
-				if (fam0L_drive) cc_ReadStatus();
-				i=ResponseStatus();  /* builds status_bits, returns orig. status (old) or faked p_success (new) */
-				if (i<0) { msg(DBG_AUD,
-					       "read_audio: cc_ReadStatus error after read: %02X\n",
-					       current_drive->status_bits);
-					   continue; /* FIXME */
-				   }
-			}
-			while ((fam0L_drive)&&(!st_check)&&(!(i&p_success)));
-			if (st_check)
-			{
-				i=cc_ReadError();
-				msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i);
-				continue;
-			}
-			if (copy_to_user(read_audio.buf,
-					 current_drive->aud_buf,
-					 read_audio.nframes * CD_FRAMESIZE_RAW))
-				RETURN_UP(-EFAULT);
-			msg(DBG_AUD,"read_audio: copy_to_user done.\n");
-			break;
-		}
-		cc_ModeSelect(CD_FRAMESIZE);
-		cc_ModeSense();
-		current_drive->mode=READ_M1;
-#if OLD_BUSY
-		busy_audio=0;
-#endif /* OLD_BUSY */
-		if (data_tries == 0)
-		{
-			msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
-			RETURN_UP(-EIO);
-		}
-		msg(DBG_AUD,"read_audio: successful return.\n");
-		RETURN_UP(0);
-	} /* end of CDROMREADAUDIO */
-
-	default:
-		msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
-		RETURN_UP(-EINVAL);
-	} /* end switch(cmd) */
-}
-
-static int sbpcd_block_media_changed(struct gendisk *disk)
-{
-	struct sbpcd_drive *p = disk->private_data;
-	return cdrom_media_changed(p->sbpcd_infop);
-}
-
-static struct block_device_operations sbpcd_bdops =
-{
-	.owner		= THIS_MODULE,
-	.open		= sbpcd_block_open,
-	.release	= sbpcd_block_release,
-	.ioctl		= sbpcd_block_ioctl,
-	.media_changed	= sbpcd_block_media_changed,
-};
-/*==========================================================================*/
-/*
- *  Open the device special file.  Check that a disk is in. Read TOC.
- */
-static int sbpcd_open(struct cdrom_device_info *cdi, int purpose)
-{
-	struct sbpcd_drive *p = cdi->handle;
-
-	down(&ioctl_read_sem);
-	switch_drive(p);
-
-	/*
-	 * try to keep an "open" counter here and lock the door if 0->1.
-	 */
-	msg(DBG_LCK,"open_count: %d -> %d\n",
-	    current_drive->open_count,current_drive->open_count+1);
-	if (++current_drive->open_count<=1)
-	{
-		int i;
-		i=LockDoor();
-		current_drive->open_count=1;
-		if (famT_drive)	msg(DBG_TEA,"sbpcd_open: before i=DiskInfo();.\n");
-		i=DiskInfo();
-		if (famT_drive)	msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.\n");
-		if ((current_drive->ored_ctl_adr&0x40)==0)
-		{		
-			msg(DBG_INF,"CD contains no data tracks.\n");
-#ifdef SAFE_MIXED
-			current_drive->has_data=0;
-#endif /* SAFE_MIXED */
-		}
-#ifdef SAFE_MIXED
-		else if (current_drive->has_data<1) current_drive->has_data=1;
-#endif /* SAFE_MIXED */ 
-	}
-	if (!st_spinning) cc_SpinUp();
-	RETURN_UP(0);
-}
-/*==========================================================================*/
-/*
- *  On close, we flush all sbp blocks from the buffer cache.
- */
-static void sbpcd_release(struct cdrom_device_info * cdi)
-{
-	struct sbpcd_drive *p = cdi->handle;
-
-	if (p->drv_id==-1) {
-		msg(DBG_INF, "release: bad device: %s\n", cdi->name);
-		return;
-	}
-	down(&ioctl_read_sem);
-	switch_drive(p);
-	/*
-	 * try to keep an "open" counter here and unlock the door if 1->0.
-	 */
-	msg(DBG_LCK,"open_count: %d -> %d\n",
-	    p->open_count,p->open_count-1);
-	if (p->open_count>-2) /* CDROMEJECT may have been done */
-	{
-		if (--p->open_count<=0) 
-		{
-			p->sbp_first_frame=p->sbp_last_frame=-1;
-			if (p->audio_state!=audio_playing)
-				if (p->f_eject) cc_SpinDown();
-			p->diskstate_flags &= ~cd_size_bit;
-			p->open_count=0; 
-#ifdef SAFE_MIXED
-			p->has_data=0;
-#endif /* SAFE_MIXED */ 
-		}
-	}
-	up(&ioctl_read_sem);
-	return ;
-}
-/*==========================================================================*/
-/*
- *
- */
-static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr);
-static struct cdrom_device_ops sbpcd_dops = {
-	.open			= sbpcd_open,
-	.release		= sbpcd_release,
-	.drive_status		= sbpcd_drive_status,
-	.media_changed		= sbpcd_media_changed,
-	.tray_move		= sbpcd_tray_move,
-	.lock_door		= sbpcd_lock_door,
-	.select_speed		= sbpcd_select_speed,
-	.get_last_session	= sbpcd_get_last_session,
-	.get_mcn		= sbpcd_get_mcn,
-	.reset			= sbpcd_reset,
-	.audio_ioctl		= sbpcd_audio_ioctl,
-	.capability		= CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
-				CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
-				CDC_MCN | CDC_PLAY_AUDIO,
-	.n_minors		= 1,
-};
-
-/*==========================================================================*/
-/*
- * accept "kernel command line" parameters 
- * (suggested by Peter MacDonald with SLS 1.03)
- *
- * This is only implemented for the first controller. Should be enough to
- * allow installing with a "strange" distribution kernel.
- *
- * use: tell LILO:
- *                 sbpcd=0x230,SoundBlaster
- *             or
- *                 sbpcd=0x300,LaserMate
- *             or
- *                 sbpcd=0x338,SoundScape
- *             or
- *                 sbpcd=0x2C0,Teac16bit
- *
- * (upper/lower case sensitive here - but all-lowercase is ok!!!).
- *
- * the address value has to be the CDROM PORT ADDRESS -
- * not the soundcard base address.
- * For the SPEA/SoundScape setup, DO NOT specify the "configuration port"
- * address, but the address which is really used for the CDROM (usually 8
- * bytes above).
- *
- */
-
-int sbpcd_setup(char *s)
-{
-#ifndef MODULE
-	int p[4];
-	(void)get_options(s, ARRAY_SIZE(p), p);
-	setup_done++;
-	msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s);
-	sbpro_type=0; /* default: "LaserMate" */
-	if (p[0]>1) sbpro_type=p[2];
-	else if (!strcmp(s,str_sb)) sbpro_type=1;
-	else if (!strcmp(s,str_sb_l)) sbpro_type=1;
-	else if (!strcmp(s,str_sp)) sbpro_type=2;
-	else if (!strcmp(s,str_sp_l)) sbpro_type=2;
-	else if (!strcmp(s,str_ss)) sbpro_type=2;
-	else if (!strcmp(s,str_ss_l)) sbpro_type=2;
-	else if (!strcmp(s,str_t16)) sbpro_type=3;
-	else if (!strcmp(s,str_t16_l)) sbpro_type=3;
-	if (p[0]>0) sbpcd_ioaddr=p[1];
-	if (p[0]>2) max_drives=p[3];
-#else
-	sbpcd_ioaddr = sbpcd[0];
-	sbpro_type = sbpcd[1];
-#endif
-	
-	CDo_command=sbpcd_ioaddr;
-	CDi_info=sbpcd_ioaddr;
-	CDi_status=sbpcd_ioaddr+1;
-	CDo_sel_i_d=sbpcd_ioaddr+1;
-	CDo_reset=sbpcd_ioaddr+2;
-	CDo_enable=sbpcd_ioaddr+3; 
-	f_16bit=0;
-	if ((sbpro_type==1)||(sbpro_type==3))
-	{
-		CDi_data=sbpcd_ioaddr;
-		if (sbpro_type==3)
-                {
-                        f_16bit=1;
-                        sbpro_type=1;
-                }
-	}
-	else CDi_data=sbpcd_ioaddr+2;
-
-	return 1;
-}
-
-__setup("sbpcd=", sbpcd_setup);
-
-
-/*==========================================================================*/
-/*
- * Sequoia S-1000 CD-ROM Interface Configuration
- * as used within SPEA Media FX, Ensonic SoundScape and some Reveal cards
- * The soundcard has to get jumpered for the interface type "Panasonic"
- * (not Sony or Mitsumi) and to get soft-configured for
- *     -> configuration port address
- *     -> CDROM port offset (num_ports): has to be 8 here. Possibly this
- *        offset value determines the interface type (none, Panasonic,
- *        Mitsumi, Sony).
- *        The interface uses a configuration port (0x320, 0x330, 0x340, 0x350)
- *        some bytes below the real CDROM address.
- *         
- *        For the Panasonic style (LaserMate) interface and the configuration
- *        port 0x330, we have to use an offset of 8; so, the real CDROM port
- *        address is 0x338.
- */
-static int __init config_spea(void)
-{
-	/*
-         * base address offset between configuration port and CDROM port,
-	 * this probably defines the interface type
-         *   2 (type=??): 0x00
-         *   8 (type=LaserMate):0x10
-         *  16 (type=??):0x20
-         *  32 (type=??):0x30
-         */
-	int n_ports=0x10;
-
-	int irq_number=0; /* off:0x00, 2/9:0x01, 7:0x03, 12:0x05, 15:0x07 */
-	int dma_channel=0; /* off: 0x00, 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68 */
-	int dack_polarity=0; /* L:0x00, H:0x80 */
-	int drq_polarity=0x40; /* L:0x00, H:0x40 */
-	int i;
-
-#define SPEA_REG_1 sbpcd_ioaddr-0x08+4
-#define SPEA_REG_2 sbpcd_ioaddr-0x08+5
-	
-	OUT(SPEA_REG_1,0xFF);
-	i=inb(SPEA_REG_1);
-	if (i!=0x0F)
-	{
-		msg(DBG_SEQ,"no SPEA interface at %04X present.\n", sbpcd_ioaddr);
-		return (-1); /* no interface found */
-	}
-	OUT(SPEA_REG_1,0x04);
-	OUT(SPEA_REG_2,0xC0);
-	
-	OUT(SPEA_REG_1,0x05);
-	OUT(SPEA_REG_2,0x10|drq_polarity|dack_polarity);
-	
-#if 1
-#define SPEA_PATTERN 0x80
-#else
-#define SPEA_PATTERN 0x00
-#endif
-	OUT(SPEA_REG_1,0x06);
-	OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
-	OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
-	
-	OUT(SPEA_REG_1,0x09);
-	i=(inb(SPEA_REG_2)&0xCF)|n_ports;
-	OUT(SPEA_REG_2,i);
-	
-	sbpro_type = 0; /* acts like a LaserMate interface now */
-	msg(DBG_SEQ,"found SoundScape interface at %04X.\n", sbpcd_ioaddr);
-	return (0);
-}
-
-/*==========================================================================*/
-/*
- *  Test for presence of drive and initialize it.
- *  Called once at boot or load time.
- */
-
-/* FIXME: cleanups after failed allocations are too ugly for words */
-#ifdef MODULE
-int __init __sbpcd_init(void)
-#else
-int __init sbpcd_init(void)
-#endif
-{
-	int i=0, j=0;
-	int addr[2]={1, CDROM_PORT};
-	int port_index;
-
-	sti();
-	
-	msg(DBG_INF,"sbpcd.c %s\n", VERSION);
-#ifndef MODULE
-#if DISTRIBUTION
-	if (!setup_done)
-	{
-		msg(DBG_INF,"Looking for Matsushita/Panasonic, CreativeLabs, Longshine, TEAC CD-ROM drives\n");
-		msg(DBG_INF,"= = = = = = = = = = W A R N I N G = = = = = = = = = =\n");
-		msg(DBG_INF,"Auto-Probing can cause a hang (f.e. touching an NE2000 card).\n");
-		msg(DBG_INF,"If that happens, you have to reboot and use the\n");
-		msg(DBG_INF,"LILO (kernel) command line feature like:\n");
-		msg(DBG_INF,"   LILO boot: ... sbpcd=0x230,SoundBlaster\n");
-		msg(DBG_INF,"or like:\n");
-		msg(DBG_INF,"   LILO boot: ... sbpcd=0x300,LaserMate\n");
-		msg(DBG_INF,"or like:\n");
-		msg(DBG_INF,"   LILO boot: ... sbpcd=0x338,SoundScape\n");
-		msg(DBG_INF,"with your REAL address.\n");
-		msg(DBG_INF,"= = = = = = = = = = END of WARNING = = = = = == = = =\n");
-	}
-#endif /* DISTRIBUTION */
-	sbpcd[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */
-	sbpcd[1]=sbpro_type; /* possibly changed by kernel command line */
-#endif /* MODULE */
-	
-	for (port_index=0;port_index<NUM_PROBE;port_index+=2)
-	{
-		addr[1]=sbpcd[port_index];
-		if (addr[1]==0) break;
-		if (check_region(addr[1],4))
-		{
-			msg(DBG_INF,"check_region: %03X is not free.\n",addr[1]);
-			continue;
-		}
-		if (sbpcd[port_index+1]==2) type=str_sp;
-		else if (sbpcd[port_index+1]==1) type=str_sb;
-		else if (sbpcd[port_index+1]==3) type=str_t16;
-		else type=str_lm;
-		sbpcd_setup((char *)type);
-#if DISTRIBUTION
-		msg(DBG_INF,"Scanning 0x%X (%s)...\n", CDo_command, type);
-#endif /* DISTRIBUTION */
-		if (sbpcd[port_index+1]==2)
-		{
-			i=config_spea();
-			if (i<0) continue;
-		}
-#ifdef PATH_CHECK
-		if (check_card(addr[1])) continue;
-#endif /* PATH_CHECK */ 
-		i=check_drives();
-		msg(DBG_INI,"check_drives done.\n");
-		if (i>=0) break; /* drive found */
-	} /* end of cycling through the set of possible I/O port addresses */
-	
-	if (ndrives==0)
-	{
-		msg(DBG_INF, "No drive found.\n");
-#ifdef MODULE
-		return -EIO;
-#else
-		goto init_done;
-#endif /* MODULE */
-	}
-	
-	if (port_index>0)
-          {
-            msg(DBG_INF, "You should read Documentation/cdrom/sbpcd\n");
-            msg(DBG_INF, "and then configure sbpcd.h for your hardware.\n");
-          }
-	check_datarate();
-	msg(DBG_INI,"check_datarate done.\n");
-	
-	for (j=0;j<NR_SBPCD;j++)
-	{
-		struct sbpcd_drive *p = D_S + j;
-		if (p->drv_id==-1)
-			continue;
-		switch_drive(p);
-#if 1
-		if (!famL_drive) cc_DriveReset();
-#endif
-		if (!st_spinning) cc_SpinUp();
-		p->sbp_first_frame = -1;  /* First frame in buffer */
-		p->sbp_last_frame = -1;   /* Last frame in buffer  */
-		p->sbp_read_frames = 0;   /* Number of frames being read to buffer */
-		p->sbp_current = 0;       /* Frame being currently read */
-		p->CD_changed=1;
-		p->frame_size=CD_FRAMESIZE;
-		p->f_eject=0;
-#if EJECT
-		if (!fam0_drive) p->f_eject=1;
-#endif /* EJECT */ 
-		cc_ReadStatus();
-		i=ResponseStatus();  /* returns orig. status or p_busy_new */
-		if (famT_drive) i=ResponseStatus();  /* returns orig. status or p_busy_new */
-		if (i<0)
-		{
-			if (i!=-402)
-				msg(DBG_INF,"init: ResponseStatus returns %d.\n",i);
-		}
-		else
-		{
-			if (st_check)
-			{
-				i=cc_ReadError();
-				msg(DBG_INI,"init: cc_ReadError returns %d\n",i);
-			}
-		}
-		msg(DBG_INI,"init: first GetStatus: %d\n",i);
-		msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n",
-		    p->error_byte);
-		if (p->error_byte==aud_12)
-		{
-			timeout=jiffies+2*HZ;
-			do
-			{
-				i=GetStatus();
-				msg(DBG_INI,"init: second GetStatus: %02X\n",i);
-				msg(DBG_LCS,
-				    "init: second GetStatus: error_byte=%d\n",
-				    p->error_byte);
-				if (i<0) break;
-				if (!st_caddy_in) break;
-				}
-			while ((!st_diskok)||time_after(jiffies, timeout));
-		}
-		i=SetSpeed();
-		if (i>=0) p->CD_changed=1;
-	}
-
-	if (!request_region(CDo_command,4,major_name))
-	{
-		printk(KERN_WARNING "sbpcd: Unable to request region 0x%x\n", CDo_command);
-		return -EIO;
-	}
-
-	/*
-	 * Turn on the CD audio channels.
-	 * The addresses are obtained from SOUND_BASE (see sbpcd.h).
-	 */
-#if SOUND_BASE
-	OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */
-	OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
-#endif /* SOUND_BASE */
-
-	if (register_blkdev(MAJOR_NR, major_name)) {
-#ifdef MODULE
-		return -EIO;
-#else
-		goto init_done;
-#endif /* MODULE */
-	}
-
-	/*
-	 * init error handling is broken beyond belief in this driver...
-	 */
-	sbpcd_queue = blk_init_queue(do_sbpcd_request, &sbpcd_lock);
-	if (!sbpcd_queue) {
-		release_region(CDo_command,4);
-		unregister_blkdev(MAJOR_NR, major_name);
-		return -ENOMEM;
-	}
-
-	for (j=0;j<NR_SBPCD;j++)
-	{
-		struct cdrom_device_info * sbpcd_infop;
-		struct gendisk *disk;
-		struct sbpcd_drive *p = D_S + j;
-
-		if (p->drv_id==-1) continue;
-		switch_drive(p);
-#ifdef SAFE_MIXED
-		p->has_data=0;
-#endif /* SAFE_MIXED */ 
-		/*
-		 * allocate memory for the frame buffers
-		 */
-		p->aud_buf=NULL;
-		p->sbp_audsiz=0;
-		p->sbp_bufsiz=buffers;
-		if (p->drv_type&drv_fam1)
-			if (READ_AUDIO>0)
-				p->sbp_audsiz = READ_AUDIO;
-		p->sbp_buf=(u_char *) vmalloc(buffers*CD_FRAMESIZE);
-		if (!p->sbp_buf) {
-			msg(DBG_INF,"data buffer (%d frames) not available.\n",
-				buffers);
-			if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
-			{
-				printk("Can't unregister %s\n", major_name);
-			}
-			release_region(CDo_command,4);
-			blk_cleanup_queue(sbpcd_queue);
-			return -EIO;
-		}
-#ifdef MODULE
-		msg(DBG_INF,"data buffer size: %d frames.\n",buffers);
-#endif /* MODULE */
-		if (p->sbp_audsiz>0)
-		{
-			p->aud_buf=(u_char *) vmalloc(p->sbp_audsiz*CD_FRAMESIZE_RAW);
-			if (p->aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",p->sbp_audsiz);
-			else msg(DBG_INF,"audio buffer size: %d frames.\n",p->sbp_audsiz);
-		}
-                sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info));
-		if (sbpcd_infop == NULL)
-		{
-                        release_region(CDo_command,4);
-			blk_cleanup_queue(sbpcd_queue);
-                        return -ENOMEM;
-		}
-		memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info));
-		sbpcd_infop->ops = &sbpcd_dops;
-		sbpcd_infop->speed = 2;
-		sbpcd_infop->capacity = 1;
-		sprintf(sbpcd_infop->name, "sbpcd%d", j);
-		sbpcd_infop->handle = p;
-		p->sbpcd_infop = sbpcd_infop;
-		disk = alloc_disk(1);
-		disk->major = MAJOR_NR;
-		disk->first_minor = j;
-		disk->fops = &sbpcd_bdops;
-		strcpy(disk->disk_name, sbpcd_infop->name);
-		disk->flags = GENHD_FL_CD;
-		p->disk = disk;
-		if (register_cdrom(sbpcd_infop))
-		{
-			printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
-		}
-		disk->private_data = p;
-		disk->queue = sbpcd_queue;
-		add_disk(disk);
-	}
-	blk_queue_hardsect_size(sbpcd_queue, CD_FRAMESIZE);
-
-#ifndef MODULE
- init_done:
-#endif
-	return 0;
-}
-/*==========================================================================*/
-#ifdef MODULE
-static void sbpcd_exit(void)
-{
-	int j;
-	
-	if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
-	{
-		msg(DBG_INF, "What's that: can't unregister %s.\n", major_name);
-		return;
-	}
-	release_region(CDo_command,4);
-	blk_cleanup_queue(sbpcd_queue);
-	for (j=0;j<NR_SBPCD;j++)
-	{
-		if (D_S[j].drv_id==-1) continue;
-		del_gendisk(D_S[j].disk);
-		put_disk(D_S[j].disk);
-		vfree(D_S[j].sbp_buf);
-		if (D_S[j].sbp_audsiz>0)
-			vfree(D_S[j].aud_buf);
-		if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
-		{
-			msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
-			return;
-		}
-		vfree(D_S[j].sbpcd_infop);
-	}
-	msg(DBG_INF, "%s module released.\n", major_name);
-}
-
-
-module_init(__sbpcd_init) /*HACK!*/;
-module_exit(sbpcd_exit);
-
-
-#endif /* MODULE */
-static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
-	struct sbpcd_drive *p = cdi->handle;
-	msg(DBG_CHK,"media_check (%s) called\n", cdi->name);
-	
-	if (p->CD_changed==0xFF)
-        {
-                p->CD_changed=0;
-                msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name);
-		current_drive->diskstate_flags &= ~toc_bit;
-		/* we *don't* need invalidate here, it's done by caller */
-		current_drive->diskstate_flags &= ~cd_size_bit;
-#ifdef SAFE_MIXED
-		current_drive->has_data=0;
-#endif /* SAFE_MIXED */ 
-
-                return (1);
-        }
-        else
-                return (0);
-}
-
-MODULE_LICENSE("GPL");
-/* FIXME: Old modules.conf claims MATSUSHITA_CDROM2_MAJOR and CDROM3, but
-   AFAICT this doesn't support those majors, so why? --RR 30 Jul 2003 */
-MODULE_ALIAS_BLOCKDEV_MAJOR(MATSUSHITA_CDROM_MAJOR);
-
-/*==========================================================================*/
-/*
- * 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-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
-
diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h
deleted file mode 100644
index 2f2225f..0000000
--- a/drivers/cdrom/sbpcd.h
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * sbpcd.h   Specify interface address and interface type here.
- */
-
-/*
- * Attention! This file contains user-serviceable parts!
- * I recommend to make use of it...
- * If you feel helpless, look into Documentation/cdrom/sbpcd
- * (good idea anyway, at least before mailing me).
- *
- * The definitions for the first controller can get overridden by
- * the kernel command line ("lilo boot option").
- * Examples:
- *                                 sbpcd=0x300,LaserMate
- *                             or
- *                                 sbpcd=0x230,SoundBlaster
- *                             or
- *                                 sbpcd=0x338,SoundScape
- *                             or
- *                                 sbpcd=0x2C0,Teac16bit
- *
- * If sbpcd gets used as a module, you can load it with
- *     insmod sbpcd.o sbpcd=0x300,0
- * or
- *     insmod sbpcd.o sbpcd=0x230,1
- * or
- *     insmod sbpcd.o sbpcd=0x338,2
- * or
- *     insmod sbpcd.o sbpcd=0x2C0,3
- * respective to override the configured address and type.
- */
-
-/*
- * define your CDROM port base address as CDROM_PORT
- * and specify the type of your interface card as SBPRO.
- *
- * address:
- * ========
- * SBPRO type addresses typically are 0x0230 (=0x220+0x10), 0x0250, ...
- * LASERMATE type (CI-101P, WDH-7001C) addresses typically are 0x0300, ...
- * SOUNDSCAPE addresses are from the LASERMATE type and range. You have to
- * specify the REAL address here, not the configuration port address. Look
- * at the CDROM driver's invoking line within your DOS CONFIG.SYS, or let
- * sbpcd auto-probe, if you are not firm with the address.
- * There are some soundcards on the market with 0x0630, 0x0650, ...; their
- * type is not obvious (both types are possible).
- *
- * example: if your SBPRO audio address is 0x220, specify 0x230 and SBPRO 1.
- *          if your soundcard has its CDROM port above 0x300, specify
- *          that address and try SBPRO 0 first.
- *          if your SoundScape configuration port is at 0x330, specify
- *          0x338 and SBPRO 2.
- *
- * interface type:
- * ===============
- * set SBPRO to 1 for "true" SoundBlaster card
- * set SBPRO to 0 for "compatible" soundcards and
- *                for "poor" (no sound) interface cards.
- * set SBPRO to 2 for Ensonic SoundScape or SPEA Media FX cards
- * set SBPRO to 3 for Teac 16bit interface cards
- *
- * Almost all "compatible" sound boards need to set SBPRO to 0.
- * If SBPRO is set wrong, the drives will get found - but any
- * data access will give errors (audio access will work).
- * The "OmniCD" no-sound interface card from CreativeLabs and most Teac
- * interface cards need SBPRO 1.
- *
- * sound base:
- * ===========
- * The SOUND_BASE definition tells if we should try to turn the CD sound
- * channels on. It will only be of use regarding soundcards with a SbPro
- * compatible mixer.
- *
- * Example: #define SOUND_BASE 0x220 enables the sound card's CD channels
- *          #define SOUND_BASE 0     leaves the soundcard untouched
- */
-#define CDROM_PORT 0x340 /* <-----------<< port address                      */
-#define SBPRO      0     /* <-----------<< interface type                    */
-#define MAX_DRIVES 4     /* set to 1 if the card does not use "drive select" */
-#define SOUND_BASE 0x220 /* <-----------<< sound address of this card or 0   */
-
-/*
- * some more or less user dependent definitions - service them!
- */
-
-/* Set this to 0 once you have configured your interface definitions right. */
-#define DISTRIBUTION 1
-
-/*
- * Time to wait after giving a message.
- * This gets important if you enable non-standard DBG_xxx flags.
- * You will see what happens if you omit the pause or make it
- * too short. Be warned!
- */
-#define KLOGD_PAUSE 1
-
-/* tray control: eject tray if no disk is in */
-#if DISTRIBUTION
-#define JUKEBOX 0
-#else
-#define JUKEBOX 1
-#endif /* DISTRIBUTION */
-
-/* tray control: eject tray after last use */
-#if DISTRIBUTION
-#define EJECT 0
-#else
-#define EJECT 1
-#endif /* DISTRIBUTION */
-
-/* max. number of audio frames to read with one     */
-/* request (allocates n* 2352 bytes kernel memory!) */
-/* may be freely adjusted, f.e. 75 (= 1 sec.), at   */
-/* runtime by use of the CDROMAUDIOBUFSIZ ioctl.    */
-#define READ_AUDIO 0
-
-/* Optimizations for the Teac CD-55A drive read performance.
- * SBP_TEAC_SPEED can be changed here, or one can set the 
- * variable "teac" when loading as a module.
- * Valid settings are:
- *   0 - very slow - the recommended "DISTRIBUTION 1" setup.
- *   1 - 2x performance with little overhead. No busy waiting.
- *   2 - 4x performance with 5ms overhead per read. Busy wait.
- *
- * Setting SBP_TEAC_SPEED or the variable 'teac' to anything
- * other than 0 may cause problems. If you run into them, first
- * change SBP_TEAC_SPEED back to 0 and see if your drive responds
- * normally. If yes, you are "allowed" to report your case - to help
- * me with the driver, not to solve your hassle. Don´t mail if you
- * simply are stuck into your own "tuning" experiments, you know?
- */
-#define SBP_TEAC_SPEED 1
-
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * nothing to change below here if you are not fully aware what you're doing
- */
-#ifndef _LINUX_SBPCD_H
-
-#define _LINUX_SBPCD_H
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * driver's own read_ahead, data mode
- */
-#define SBP_BUFFER_FRAMES 8 
-
-#define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */
-#undef  FUTURE
-#undef SAFE_MIXED
-
-#define TEST_UPC 0
-#define SPEA_TEST 0
-#define TEST_STI 0
-#define OLD_BUSY 0
-#undef PATH_CHECK
-#ifndef SOUND_BASE
-#define SOUND_BASE 0
-#endif
-#if DISTRIBUTION
-#undef SBP_TEAC_SPEED
-#define SBP_TEAC_SPEED 0
-#endif
-/*==========================================================================*/
-/*
- * DDI interface definitions
- * "invented" by Fred N. van Kempen..
- */
-#define DDIOCSDBG	0x9000
-
-/*==========================================================================*/
-/*
- * "private" IOCTL functions
- */
-#define CDROMAUDIOBUFSIZ	0x5382 /* set the audio buffer size */
-
-/*==========================================================================*/
-/*
- * Debug output levels
- */
-#define DBG_INF	1	/* necessary information */
-#define DBG_BSZ	2	/* BLOCK_SIZE trace */
-#define DBG_REA	3	/* READ status trace */
-#define DBG_CHK	4	/* MEDIA CHECK trace */
-#define DBG_TIM	5	/* datarate timer test */
-#define DBG_INI	6	/* initialization trace */
-#define DBG_TOC	7	/* tell TocEntry values */
-#define DBG_IOC	8	/* ioctl trace */
-#define DBG_STA	9	/* ResponseStatus() trace */
-#define DBG_ERR	10	/* cc_ReadError() trace */
-#define DBG_CMD	11	/* cmd_out() trace */
-#define DBG_WRN	12	/* give explanation before auto-probing */
-#define DBG_MUL	13	/* multi session code test */
-#define DBG_IDX	14	/* test code for drive_id !=0 */
-#define DBG_IOX	15	/* some special information */
-#define DBG_DID	16	/* drive ID test */
-#define DBG_RES	17	/* drive reset info */
-#define DBG_SPI	18	/* SpinUp test */
-#define DBG_IOS	19	/* ioctl trace: subchannel functions */
-#define DBG_IO2	20	/* ioctl trace: general */
-#define DBG_UPC	21	/* show UPC information */
-#define DBG_XA1	22	/* XA mode debugging */
-#define DBG_LCK	23	/* door (un)lock info */
-#define DBG_SQ1	24	/* dump SubQ frame */
-#define DBG_AUD	25	/* READ AUDIO debugging */
-#define DBG_SEQ	26	/* Sequoia interface configuration trace */
-#define DBG_LCS	27	/* Longshine LCS-7260 debugging trace */
-#define DBG_CD2	28	/* MKE/Funai CD200 debugging trace */
-#define DBG_TEA	29	/* TEAC CD-55A debugging trace */
-#define DBG_ECS	30	/* ECS-AT (Vertos 100) debugging trace */
-#define DBG_000	31	/* unnecessary information */
-
-/*==========================================================================*/
-/*==========================================================================*/
-
-/*
- * bits of flags_cmd_out:
- */
-#define f_respo3		0x100
-#define f_putcmd		0x80
-#define f_respo2		0x40
-#define f_lopsta		0x20
-#define f_getsta		0x10
-#define f_ResponseStatus	0x08
-#define f_obey_p_check		0x04
-#define f_bit1			0x02
-#define f_wait_if_busy		0x01
-
-/*
- * diskstate_flags:
- */
-#define x80_bit			0x80
-#define upc_bit			0x40
-#define volume_bit		0x20
-#define toc_bit			0x10
-#define multisession_bit	0x08
-#define cd_size_bit		0x04
-#define subq_bit		0x02
-#define frame_size_bit		0x01
-
-/*
- * disk states (bits of diskstate_flags):
- */
-#define upc_valid		(current_drive->diskstate_flags&upc_bit)
-#define volume_valid		(current_drive->diskstate_flags&volume_bit)
-#define toc_valid		(current_drive->diskstate_flags&toc_bit)
-#define cd_size_valid		(current_drive->diskstate_flags&cd_size_bit)
-#define subq_valid		(current_drive->diskstate_flags&subq_bit)
-#define frame_size_valid	(current_drive->diskstate_flags&frame_size_bit)
-
-/*
- * the status_bits variable
- */
-#define p_success	0x100
-#define p_door_closed	0x80
-#define p_caddy_in	0x40
-#define p_spinning	0x20
-#define p_check		0x10
-#define p_busy_new	0x08
-#define p_door_locked	0x04
-#define p_disk_ok	0x01
-
-/*
- * LCS-7260 special status result bits:
- */
-#define p_lcs_door_locked	0x02
-#define p_lcs_door_closed	0x01 /* probably disk_in */
-
-/*
- * CR-52x special status result bits:
- */
-#define p_caddin_old	0x40
-#define p_success_old	0x08
-#define p_busy_old	0x04
-#define p_bit_1		0x02	/* hopefully unused now */
-
-/*
- * "generation specific" defs of the status result bits:
- */
-#define p0_door_closed	0x80
-#define p0_caddy_in	0x40
-#define p0_spinning	0x20
-#define p0_check	0x10
-#define p0_success	0x08 /* unused */
-#define p0_busy		0x04
-#define p0_bit_1	0x02 /* unused */
-#define p0_disk_ok	0x01
-
-#define pL_disk_in	0x40
-#define pL_spinning	0x20
-#define pL_check	0x10
-#define pL_success	0x08 /* unused ?? */
-#define pL_busy		0x04
-#define pL_door_locked	0x02
-#define pL_door_closed	0x01
-
-#define pV_door_closed	0x40
-#define pV_spinning	0x20
-#define pV_check	0x10
-#define pV_success	0x08
-#define pV_busy		0x04
-#define pV_door_locked	0x02
-#define pV_disk_ok	0x01
-
-#define p1_door_closed	0x80
-#define p1_disk_in	0x40
-#define p1_spinning	0x20
-#define p1_check	0x10
-#define p1_busy		0x08
-#define p1_door_locked	0x04
-#define p1_bit_1	0x02 /* unused */
-#define p1_disk_ok	0x01
-
-#define p2_disk_ok	0x80
-#define p2_door_locked	0x40
-#define p2_spinning	0x20
-#define p2_busy2	0x10
-#define p2_busy1	0x08
-#define p2_door_closed	0x04
-#define p2_disk_in	0x02
-#define p2_check	0x01
-
-/*
- * used drive states:
- */
-#define st_door_closed	(current_drive->status_bits&p_door_closed)
-#define st_caddy_in	(current_drive->status_bits&p_caddy_in)
-#define st_spinning	(current_drive->status_bits&p_spinning)
-#define st_check	(current_drive->status_bits&p_check)
-#define st_busy		(current_drive->status_bits&p_busy_new)
-#define st_door_locked	(current_drive->status_bits&p_door_locked)
-#define st_diskok	(current_drive->status_bits&p_disk_ok)
-
-/*
- * bits of the CDi_status register:
- */
-#define s_not_result_ready	0x04 /* 0: "result ready" */
-#define s_not_data_ready	0x02 /* 0: "data ready"   */
-#define s_attention		0x01 /* 1: "attention required" */
-/*
- * usable as:
- */
-#define DRV_ATTN	((inb(CDi_status)&s_attention)!=0)
-#define DATA_READY	((inb(CDi_status)&s_not_data_ready)==0)
-#define RESULT_READY	((inb(CDi_status)&s_not_result_ready)==0)
-
-/*
- * drive families and types (firmware versions):
- */
-#define drv_fam0	0x0100		/* CR-52x family */
-#define drv_199		(drv_fam0+0x01)	/* <200 */
-#define drv_200		(drv_fam0+0x02)	/* <201 */
-#define drv_201		(drv_fam0+0x03)	/* <210 */
-#define drv_210		(drv_fam0+0x04)	/* <211 */
-#define drv_211		(drv_fam0+0x05)	/* <300 */
-#define drv_300		(drv_fam0+0x06)	/* >=300 */
-
-#define drv_fam1	0x0200		/* CR-56x family */
-#define drv_099		(drv_fam1+0x01)	/* <100 */
-#define drv_100		(drv_fam1+0x02)	/* >=100, only 1.02 and 5.00 known */
-
-#define drv_fam2	0x0400		/* CD200 family */
-
-#define drv_famT	0x0800		/* TEAC CD-55A */
-
-#define drv_famL	0x1000		/* Longshine family */
-#define drv_260		(drv_famL+0x01)	/* LCS-7260 */
-#define drv_e1		(drv_famL+0x01)	/* LCS-7260, firmware "A E1" */
-#define drv_f4		(drv_famL+0x02)	/* LCS-7260, firmware "A4F4" */
-
-#define drv_famV	0x2000		/* ECS-AT (vertos-100) family */
-#define drv_at		(drv_famV+0x01)	/* ECS-AT, firmware "1.00" */
-
-#define fam0_drive	(current_drive->drv_type&drv_fam0)
-#define famL_drive	(current_drive->drv_type&drv_famL)
-#define famV_drive	(current_drive->drv_type&drv_famV)
-#define fam1_drive	(current_drive->drv_type&drv_fam1)
-#define fam2_drive	(current_drive->drv_type&drv_fam2)
-#define famT_drive	(current_drive->drv_type&drv_famT)
-#define fam0L_drive	(current_drive->drv_type&(drv_fam0|drv_famL))
-#define fam0V_drive	(current_drive->drv_type&(drv_fam0|drv_famV))
-#define famLV_drive	(current_drive->drv_type&(drv_famL|drv_famV))
-#define fam0LV_drive	(current_drive->drv_type&(drv_fam0|drv_famL|drv_famV))
-#define fam1L_drive	(current_drive->drv_type&(drv_fam1|drv_famL))
-#define fam1V_drive	(current_drive->drv_type&(drv_fam1|drv_famV))
-#define fam1LV_drive	(current_drive->drv_type&(drv_fam1|drv_famL|drv_famV))
-#define fam01_drive	(current_drive->drv_type&(drv_fam0|drv_fam1))
-#define fam12_drive	(current_drive->drv_type&(drv_fam1|drv_fam2))
-#define fam2T_drive	(current_drive->drv_type&(drv_fam2|drv_famT))
-
-/*
- * audio states:
- */
-#define audio_completed	3 /* Forgot this one! --AJK */
-#define audio_playing	2
-#define audio_pausing	1
-
-/*
- * drv_pattern, drv_options:
- */
-#define speed_auto	0x80
-#define speed_300	0x40
-#define speed_150	0x20
-#define audio_mono	0x04
-
-/*
- * values of cmd_type (0 else):
- */
-#define READ_M1	0x01	/* "data mode 1": 2048 bytes per frame */
-#define READ_M2	0x02	/* "data mode 2": 12+2048+280 bytes per frame */
-#define READ_SC	0x04	/* "subchannel info": 96 bytes per frame */
-#define READ_AU	0x08	/* "audio frame": 2352 bytes per frame */
-
-/*
- * sense_byte:
- *
- *          values: 00
- *                  01
- *                  81
- *                  82 "raw audio" mode
- *                  xx from infobuf[0] after 85 00 00 00 00 00 00
- */
-
-/* audio status (bin) */
-#define aud_00 0x00 /* Audio status byte not supported or not valid */
-#define audx11 0x0b /* Audio play operation in progress             */
-#define audx12 0x0c /* Audio play operation paused                  */
-#define audx13 0x0d /* Audio play operation successfully completed  */
-#define audx14 0x0e /* Audio play operation stopped due to error    */
-#define audx15 0x0f /* No current audio status to return            */
-/* audio status (bcd) */
-#define aud_11 0x11 /* Audio play operation in progress             */
-#define aud_12 0x12 /* Audio play operation paused                  */
-#define aud_13 0x13 /* Audio play operation successfully completed  */
-#define aud_14 0x14 /* Audio play operation stopped due to error    */
-#define aud_15 0x15 /* No current audio status to return            */
-
-/*
- * highest allowed drive number (MINOR+1)
- */
-#define NR_SBPCD	4
-
-/*
- * we try to never disable interrupts - seems to work
- */
-#define SBPCD_DIS_IRQ	0
-
-/*
- * "write byte to port"
- */
-#define OUT(x,y)	outb(y,x)
-
-/*==========================================================================*/
-
-#define MIXER_addr SOUND_BASE+4 /* sound card's address register */
-#define MIXER_data SOUND_BASE+5 /* sound card's data register */
-#define MIXER_CD_Volume	0x28	/* internal SB Pro register address */
-
-/*==========================================================================*/
-
-#define MAX_TRACKS	99
-
-#define ERR_DISKCHANGE 615
-
-/*==========================================================================*/
-/*
- * To make conversions easier (machine dependent!)
- */
-typedef union _msf
-{
-	u_int n;
-	u_char c[4];
-} MSF;
-
-typedef union _blk
-{
-	u_int n;
-	u_char c[4];
-} BLK;
-
-/*==========================================================================*/
-
-/*============================================================================
-==============================================================================
-
-COMMAND SET of "old" drives like CR-521, CR-522
-               (the CR-562 family is different):
-
-No.	Command			       Code
---------------------------------------------
-
-Drive Commands:
- 1	Seek				01	
- 2	Read Data			02
- 3	Read XA-Data			03
- 4	Read Header			04
- 5	Spin Up				05
- 6	Spin Down			06
- 7	Diagnostic			07
- 8	Read UPC			08
- 9	Read ISRC			09
-10	Play Audio			0A
-11	Play Audio MSF			0B
-12	Play Audio Track/Index		0C
-
-Status Commands:
-13	Read Status			81	
-14	Read Error			82
-15	Read Drive Version		83
-16	Mode Select			84
-17	Mode Sense			85
-18	Set XA Parameter		86
-19	Read XA Parameter		87
-20	Read Capacity			88
-21	Read SUB_Q			89
-22	Read Disc Code			8A
-23	Read Disc Information		8B
-24	Read TOC			8C
-25	Pause/Resume			8D
-26	Read Packet			8E
-27	Read Path Check			00
- 
- 
-all numbers (lba, msf-bin, msf-bcd, counts) to transfer high byte first
-
-mnemo     7-byte command        #bytes response (r0...rn)
-________ ____________________  ____ 
-
-Read Status:
-status:  81.                    (1)  one-byte command, gives the main
-                                                          status byte
-Read Error:
-check1:  82 00 00 00 00 00 00.  (6)  r1: audio status
-
-Read Packet:
-check2:  8e xx 00 00 00 00 00. (xx)  gets xx bytes response, relating
-                                        to commands 01 04 05 07 08 09
-
-Play Audio:
-play:    0a ll-bb-aa nn-nn-nn.  (0)  play audio, ll-bb-aa: starting block (lba),
-                                                 nn-nn-nn: #blocks
-Play Audio MSF:
-         0b mm-ss-ff mm-ss-ff   (0)  play audio from/to
-
-Play Audio Track/Index:
-         0c ...
-
-Pause/Resume:
-pause:   8d pr 00 00 00 00 00.  (0)  pause (pr=00) 
-                                     resume (pr=80) audio playing
-
-Mode Select:
-         84 00 nn-nn ??.?? 00   (0)  nn-nn: 2048 or 2340
-                                     possibly defines transfer size
-
-set_vol: 84 83 00 00 sw le 00.  (0)  sw(itch): lrxxxxxx (off=1)
-                                     le(vel): min=0, max=FF, else half
-				     (firmware 2.11)
-
-Mode Sense:
-get_vol: 85 03 00 00 00 00 00.  (2)  tell current audio volume setting
-
-Read Disc Information:
-tocdesc: 8b 00 00 00 00 00 00.  (6)  read the toc descriptor ("msf-bin"-format)
-
-Read TOC:
-tocent:  8c fl nn 00 00 00 00.  (8)  read toc entry #nn
-                                       (fl=0:"lba"-, =2:"msf-bin"-format)
-
-Read Capacity:
-capacit: 88 00 00 00 00 00 00.  (5)  "read CD-ROM capacity"
-
-
-Read Path Check:
-ping:    00 00 00 00 00 00 00.  (2)  r0=AA, r1=55
-                                     ("ping" if the drive is connected)
-
-Read Drive Version:
-ident:   83 00 00 00 00 00 00. (12)  gives "MATSHITAn.nn" 
-                                     (n.nn = 2.01, 2.11., 3.00, ...)
-
-Seek:
-seek:    01 00 ll-bb-aa 00 00.  (0)  
-seek:    01 02 mm-ss-ff 00 00.  (0)  
-
-Read Data:
-read:    02 xx-xx-xx nn-nn fl.  (?)  read nn-nn blocks of 2048 bytes,
-                                     starting at block xx-xx-xx  
-                                     fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read XA-Data:
-read:    03 xx-xx-xx nn-nn fl.  (?)  read nn-nn blocks of 2340 bytes, 
-                                     starting at block xx-xx-xx
-                                     fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read SUB_Q:
-         89 fl 00 00 00 00 00. (13)  r0: audio status, r4-r7: lba/msf, 
-                                       fl=0: "lba", fl=2: "msf"
-
-Read Disc Code:
-         8a 00 00 00 00 00 00. (14)  possibly extended "check condition"-info
-
-Read Header:
-         04 00 ll-bb-aa 00 00.  (0)   4 bytes response with "check2"
-         04 02 mm-ss-ff 00 00.  (0)   4 bytes response with "check2"
-
-Spin Up:
-         05 00 ll-bb-aa 00 00.  (0)  possibly implies a "seek"
-
-Spin Down:
-         06 ...
-
-Diagnostic:
-         07 00 ll-bb-aa 00 00.  (2)   2 bytes response with "check2"
-         07 02 mm-ss-ff 00 00.  (2)   2 bytes response with "check2"
-
-Read UPC:
-         08 00 ll-bb-aa 00 00. (16)  
-         08 02 mm-ss-ff 00 00. (16)  
-
-Read ISRC:
-         09 00 ll-bb-aa 00 00. (15)  15 bytes response with "check2"
-         09 02 mm-ss-ff 00 00. (15)  15 bytes response with "check2"
-
-Set XA Parameter:
-         86 ...
-
-Read XA Parameter:
-         87 ...
-
-==============================================================================
-============================================================================*/
-
-/*
- * commands
- *
- * CR-52x:      CMD0_
- * CR-56x:      CMD1_
- * CD200:       CMD2_
- * LCS-7260:    CMDL_
- * TEAC CD-55A: CMDT_
- * ECS-AT:      CMDV_
- */
-#define CMD1_RESET	0x0a
-#define CMD2_RESET	0x01
-#define CMDT_RESET	0xc0
-
-#define CMD1_LOCK_CTL	0x0c
-#define CMD2_LOCK_CTL	0x1e
-#define CMDT_LOCK_CTL	CMD2_LOCK_CTL
-#define CMDL_LOCK_CTL	0x0e
-#define CMDV_LOCK_CTL	CMDL_LOCK_CTL
-
-#define CMD1_TRAY_CTL	0x07
-#define CMD2_TRAY_CTL	0x1b
-#define CMDT_TRAY_CTL	CMD2_TRAY_CTL
-#define CMDL_TRAY_CTL	0x0d
-#define CMDV_TRAY_CTL	CMDL_TRAY_CTL
-
-#define CMD1_MULTISESS	0x8d
-#define CMDL_MULTISESS	0x8c
-#define CMDV_MULTISESS	CMDL_MULTISESS
-
-#define CMD1_SUBCHANINF	0x11
-#define CMD2_SUBCHANINF	0x??
-
-#define CMD1_ABORT	0x08
-#define CMD2_ABORT	0x08
-#define CMDT_ABORT	0x08
-
-#define CMD2_x02	0x02
-
-#define CMD2_SETSPEED	0xda
-
-#define CMD0_PATH_CHECK	0x00
-#define CMD1_PATH_CHECK	0x???
-#define CMD2_PATH_CHECK	0x???
-#define CMDT_PATH_CHECK	0x???
-#define CMDL_PATH_CHECK	CMD0_PATH_CHECK
-#define CMDV_PATH_CHECK	CMD0_PATH_CHECK
-
-#define CMD0_SEEK	0x01
-#define CMD1_SEEK	CMD0_SEEK
-#define CMD2_SEEK	0x2b
-#define CMDT_SEEK	CMD2_SEEK
-#define CMDL_SEEK	CMD0_SEEK
-#define CMDV_SEEK	CMD0_SEEK
-
-#define CMD0_READ	0x02
-#define CMD1_READ	0x10
-#define CMD2_READ	0x28
-#define CMDT_READ	CMD2_READ
-#define CMDL_READ	CMD0_READ
-#define CMDV_READ	CMD0_READ
-
-#define CMD0_READ_XA	0x03
-#define CMD2_READ_XA	0xd4
-#define CMD2_READ_XA2	0xd5
-#define CMDL_READ_XA	CMD0_READ_XA /* really ?? */
-#define CMDV_READ_XA	CMD0_READ_XA
-
-#define CMD0_READ_HEAD	0x04
-
-#define CMD0_SPINUP	0x05
-#define CMD1_SPINUP	0x02
-#define CMD2_SPINUP	CMD2_TRAY_CTL
-#define CMDL_SPINUP	CMD0_SPINUP
-#define CMDV_SPINUP	CMD0_SPINUP
-
-#define CMD0_SPINDOWN	0x06 /* really??? */
-#define CMD1_SPINDOWN	0x06
-#define CMD2_SPINDOWN	CMD2_TRAY_CTL
-#define CMDL_SPINDOWN	0x0d
-#define CMDV_SPINDOWN	CMD0_SPINDOWN
-
-#define CMD0_DIAG	0x07
-
-#define CMD0_READ_UPC	0x08
-#define CMD1_READ_UPC	0x88
-#define CMD2_READ_UPC	0x???
-#define CMDL_READ_UPC	CMD0_READ_UPC
-#define CMDV_READ_UPC	0x8f
-
-#define CMD0_READ_ISRC	0x09
-
-#define CMD0_PLAY	0x0a
-#define CMD1_PLAY	0x???
-#define CMD2_PLAY	0x???
-#define CMDL_PLAY	CMD0_PLAY
-#define CMDV_PLAY	CMD0_PLAY
-
-#define CMD0_PLAY_MSF	0x0b
-#define CMD1_PLAY_MSF	0x0e
-#define CMD2_PLAY_MSF	0x47
-#define CMDT_PLAY_MSF	CMD2_PLAY_MSF
-#define CMDL_PLAY_MSF	0x???
-
-#define CMD0_PLAY_TI	0x0c
-#define CMD1_PLAY_TI	0x0f
-
-#define CMD0_STATUS	0x81
-#define CMD1_STATUS	0x05
-#define CMD2_STATUS	0x00
-#define CMDT_STATUS	CMD2_STATUS
-#define CMDL_STATUS	CMD0_STATUS
-#define CMDV_STATUS	CMD0_STATUS
-#define CMD2_SEEK_LEADIN 0x00
-
-#define CMD0_READ_ERR	0x82
-#define CMD1_READ_ERR	CMD0_READ_ERR
-#define CMD2_READ_ERR	0x03
-#define CMDT_READ_ERR	CMD2_READ_ERR /* get audio status */
-#define CMDL_READ_ERR	CMD0_READ_ERR
-#define CMDV_READ_ERR	CMD0_READ_ERR
-
-#define CMD0_READ_VER	0x83
-#define CMD1_READ_VER	CMD0_READ_VER
-#define CMD2_READ_VER	0x12
-#define CMDT_READ_VER	CMD2_READ_VER /* really ?? */
-#define CMDL_READ_VER	CMD0_READ_VER
-#define CMDV_READ_VER	CMD0_READ_VER
-
-#define CMD0_SETMODE	0x84
-#define CMD1_SETMODE	0x09
-#define CMD2_SETMODE	0x55
-#define CMDT_SETMODE	CMD2_SETMODE
-#define CMDL_SETMODE	CMD0_SETMODE
-
-#define CMD0_GETMODE	0x85
-#define CMD1_GETMODE	0x84
-#define CMD2_GETMODE	0x5a
-#define CMDT_GETMODE	CMD2_GETMODE
-#define CMDL_GETMODE	CMD0_GETMODE
-
-#define CMD0_SET_XA	0x86
-
-#define CMD0_GET_XA	0x87
-
-#define CMD0_CAPACITY	0x88
-#define CMD1_CAPACITY	0x85
-#define CMD2_CAPACITY	0x25
-#define CMDL_CAPACITY	CMD0_CAPACITY /* missing in some firmware versions */
-
-#define CMD0_READSUBQ	0x89
-#define CMD1_READSUBQ	0x87
-#define CMD2_READSUBQ	0x42
-#define CMDT_READSUBQ	CMD2_READSUBQ
-#define CMDL_READSUBQ	CMD0_READSUBQ
-#define CMDV_READSUBQ	CMD0_READSUBQ
-
-#define CMD0_DISKCODE	0x8a
-
-#define CMD0_DISKINFO	0x8b
-#define CMD1_DISKINFO	CMD0_DISKINFO
-#define CMD2_DISKINFO	0x43
-#define CMDT_DISKINFO	CMD2_DISKINFO
-#define CMDL_DISKINFO	CMD0_DISKINFO
-#define CMDV_DISKINFO	CMD0_DISKINFO
-
-#define CMD0_READTOC	0x8c
-#define CMD1_READTOC	CMD0_READTOC
-#define CMD2_READTOC	0x???
-#define CMDL_READTOC	CMD0_READTOC
-#define CMDV_READTOC	CMD0_READTOC
-
-#define CMD0_PAU_RES	0x8d
-#define CMD1_PAU_RES	0x0d
-#define CMD2_PAU_RES	0x4b
-#define CMDT_PAUSE	CMD2_PAU_RES
-#define CMDL_PAU_RES	CMD0_PAU_RES
-#define CMDV_PAUSE	CMD0_PAU_RES
-
-#define CMD0_PACKET	0x8e
-#define CMD1_PACKET	CMD0_PACKET
-#define CMD2_PACKET	0x???
-#define CMDL_PACKET	CMD0_PACKET
-#define CMDV_PACKET	0x???
-
-/*==========================================================================*/
-/*==========================================================================*/
-#endif /* _LINUX_SBPCD_H */
-/*==========================================================================*/
-/*
- * 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-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
deleted file mode 100644
index 5409fca..0000000
--- a/drivers/cdrom/sjcd.c
+++ /dev/null
@@ -1,1815 +0,0 @@
-/* -- sjcd.c
- *
- *   Sanyo CD-ROM device driver implementation, Version 1.6
- *   Copyright (C) 1995  Vadim V. Model
- *
- *   model@cecmow.enet.dec.com
- *   vadim@rbrf.ru
- *   vadim@ipsun.ras.ru
- *
- *
- *  This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de);
- *  it was developed under use of mcd.c from Martin Harriss, with help of
- *  Eric van der Maarel (H.T.M.v.d.Maarel@marin.nl).
- *
- *  It is planned to include these routines into sbpcd.c later - to make
- *  a "mixed use" on one cable possible for all kinds of drives which use
- *  the SoundBlaster/Panasonic style CDROM interface. But today, the
- *  ability to install directly from CDROM is more important than flexibility.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  History:
- *  1.1 First public release with kernel version 1.3.7.
- *      Written by Vadim Model.
- *  1.2 Added detection and configuration of cdrom interface
- *      on ISP16 soundcard.
- *      Allow for command line options: sjcd=<io_base>,<irq>,<dma>
- *  1.3 Some minor changes to README.sjcd.
- *  1.4 MSS Sound support!! Listen to a CD through the speakers.
- *  1.5 Module support and bugfixes.
- *      Tray locking.
- *  1.6 Removed ISP16 code from this driver.
- *      Allow only to set io base address on command line: sjcd=<io_base>
- *      Changes to Documentation/cdrom/sjcd
- *      Added cleanup after any error in the initialisation.
- *  1.7 Added code to set the sector size tables to prevent the bug present in 
- *      the previous version of this driver.  Coded added by Anthony Barbachan 
- *      from bugfix tip originally suggested by Alan Cox.
- *
- *  November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	             Removed init_module & cleanup_module in favor of 
- *	             module_init & module_exit.
- *	             Torben Mathiasen <tmm@image.dk>
- */
-
-#define SJCD_VERSION_MAJOR 1
-#define SJCD_VERSION_MINOR 7
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/major.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/blkdev.h>
-#include "sjcd.h"
-
-static int sjcd_present = 0;
-static struct request_queue *sjcd_queue;
-
-#define MAJOR_NR SANYO_CDROM_MAJOR
-#define QUEUE (sjcd_queue)
-#define CURRENT elv_next_request(sjcd_queue)
-
-#define SJCD_BUF_SIZ 32		/* cdr-h94a has internal 64K buffer */
-
-/*
- * buffer for block size conversion
- */
-static char sjcd_buf[2048 * SJCD_BUF_SIZ];
-static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn;
-static volatile int sjcd_buf_in, sjcd_buf_out = -1;
-
-/*
- * Status.
- */
-static unsigned short sjcd_status_valid = 0;
-static unsigned short sjcd_door_closed;
-static unsigned short sjcd_door_was_open;
-static unsigned short sjcd_media_is_available;
-static unsigned short sjcd_media_is_changed;
-static unsigned short sjcd_toc_uptodate = 0;
-static unsigned short sjcd_command_failed;
-static volatile unsigned char sjcd_completion_status = 0;
-static volatile unsigned char sjcd_completion_error = 0;
-static unsigned short sjcd_command_is_in_progress = 0;
-static unsigned short sjcd_error_reported = 0;
-static DEFINE_SPINLOCK(sjcd_lock);
-
-static int sjcd_open_count;
-
-static int sjcd_audio_status;
-static struct sjcd_play_msf sjcd_playing;
-
-static int sjcd_base = SJCD_BASE_ADDR;
-
-module_param(sjcd_base, int, 0);
-
-static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq);
-
-/*
- * Data transfer.
- */
-static volatile unsigned short sjcd_transfer_is_active = 0;
-
-enum sjcd_transfer_state {
-	SJCD_S_IDLE = 0,
-	SJCD_S_START = 1,
-	SJCD_S_MODE = 2,
-	SJCD_S_READ = 3,
-	SJCD_S_DATA = 4,
-	SJCD_S_STOP = 5,
-	SJCD_S_STOPPING = 6
-};
-static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE;
-static long sjcd_transfer_timeout = 0;
-static int sjcd_read_count = 0;
-static unsigned char sjcd_mode = 0;
-
-#define SJCD_READ_TIMEOUT 5000
-
-#if defined( SJCD_GATHER_STAT )
-/*
- * Statistic.
- */
-static struct sjcd_stat statistic;
-#endif
-
-/*
- * Timer.
- */
-static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0);
-
-#define SJCD_SET_TIMER( func, tmout )           \
-    ( sjcd_delay_timer.expires = jiffies+tmout,         \
-      sjcd_delay_timer.function = ( void * )func, \
-      add_timer( &sjcd_delay_timer ) )
-
-#define CLEAR_TIMER del_timer( &sjcd_delay_timer )
-
-/*
- * Set up device, i.e., use command line data to set
- * base address.
- */
-#ifndef MODULE
-static int __init sjcd_setup(char *str)
-{
-	int ints[2];
-	(void) get_options(str, ARRAY_SIZE(ints), ints);
-	if (ints[0] > 0)
-		sjcd_base = ints[1];
-
-	return 1;
-}
-
-__setup("sjcd=", sjcd_setup);
-
-#endif
-
-/*
- * Special converters.
- */
-static unsigned char bin2bcd(int bin)
-{
-	int u, v;
-
-	u = bin % 10;
-	v = bin / 10;
-	return (u | (v << 4));
-}
-
-static int bcd2bin(unsigned char bcd)
-{
-	return ((bcd >> 4) * 10 + (bcd & 0x0F));
-}
-
-static long msf2hsg(struct msf *mp)
-{
-	return (bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75
-		+ bcd2bin(mp->min) * 4500 - 150);
-}
-
-static void hsg2msf(long hsg, struct msf *msf)
-{
-	hsg += 150;
-	msf->min = hsg / 4500;
-	hsg %= 4500;
-	msf->sec = hsg / 75;
-	msf->frame = hsg % 75;
-	msf->min = bin2bcd(msf->min);	/* convert to BCD */
-	msf->sec = bin2bcd(msf->sec);
-	msf->frame = bin2bcd(msf->frame);
-}
-
-/*
- * Send a command to cdrom. Invalidate status.
- */
-static void sjcd_send_cmd(unsigned char cmd)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: send_cmd( 0x%x )\n", cmd);
-#endif
-	outb(cmd, SJCDPORT(0));
-	sjcd_command_is_in_progress = 1;
-	sjcd_status_valid = 0;
-	sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with one arg to cdrom. Invalidate status.
- */
-static void sjcd_send_1_cmd(unsigned char cmd, unsigned char a)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a);
-#endif
-	outb(cmd, SJCDPORT(0));
-	outb(a, SJCDPORT(0));
-	sjcd_command_is_in_progress = 1;
-	sjcd_status_valid = 0;
-	sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with four args to cdrom. Invalidate status.
- */
-static void sjcd_send_4_cmd(unsigned char cmd, unsigned char a,
-			    unsigned char b, unsigned char c,
-			    unsigned char d)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: send_4_cmd( 0x%x )\n", cmd);
-#endif
-	outb(cmd, SJCDPORT(0));
-	outb(a, SJCDPORT(0));
-	outb(b, SJCDPORT(0));
-	outb(c, SJCDPORT(0));
-	outb(d, SJCDPORT(0));
-	sjcd_command_is_in_progress = 1;
-	sjcd_status_valid = 0;
-	sjcd_command_failed = 0;
-}
-
-/*
- * Send a play or read command to cdrom. Invalidate Status.
- */
-static void sjcd_send_6_cmd(unsigned char cmd, struct sjcd_play_msf *pms)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: send_long_cmd( 0x%x )\n", cmd);
-#endif
-	outb(cmd, SJCDPORT(0));
-	outb(pms->start.min, SJCDPORT(0));
-	outb(pms->start.sec, SJCDPORT(0));
-	outb(pms->start.frame, SJCDPORT(0));
-	outb(pms->end.min, SJCDPORT(0));
-	outb(pms->end.sec, SJCDPORT(0));
-	outb(pms->end.frame, SJCDPORT(0));
-	sjcd_command_is_in_progress = 1;
-	sjcd_status_valid = 0;
-	sjcd_command_failed = 0;
-}
-
-/*
- * Get a value from the data port. Should not block, so we use a little
- * wait for a while. Returns 0 if OK.
- */
-static int sjcd_load_response(void *buf, int len)
-{
-	unsigned char *resp = (unsigned char *) buf;
-
-	for (; len; --len) {
-		int i;
-		for (i = 200;
-		     i-- && !SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))););
-		if (i > 0)
-			*resp++ = (unsigned char) inb(SJCDPORT(0));
-		else
-			break;
-	}
-	return (len);
-}
-
-/*
- * Load and parse command completion status (drive info byte and maybe error).
- * Sorry, no error classification yet.
- */
-static void sjcd_load_status(void)
-{
-	sjcd_media_is_changed = 0;
-	sjcd_completion_error = 0;
-	sjcd_completion_status = inb(SJCDPORT(0));
-	if (sjcd_completion_status & SST_DOOR_OPENED) {
-		sjcd_door_closed = sjcd_media_is_available = 0;
-	} else {
-		sjcd_door_closed = 1;
-		if (sjcd_completion_status & SST_MEDIA_CHANGED)
-			sjcd_media_is_available = sjcd_media_is_changed =
-			    1;
-		else if (sjcd_completion_status & 0x0F) {
-			/*
-			 * OK, we seem to catch an error ...
-			 */
-			while (!SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))));
-			sjcd_completion_error = inb(SJCDPORT(0));
-			if ((sjcd_completion_status & 0x08) &&
-			    (sjcd_completion_error & 0x40))
-				sjcd_media_is_available = 0;
-			else
-				sjcd_command_failed = 1;
-		} else
-			sjcd_media_is_available = 1;
-	}
-	/*
-	 * Ok, status loaded successfully.
-	 */
-	sjcd_status_valid = 1, sjcd_error_reported = 0;
-	sjcd_command_is_in_progress = 0;
-
-	/*
-	 * If the disk is changed, the TOC is not valid.
-	 */
-	if (sjcd_media_is_changed)
-		sjcd_toc_uptodate = 0;
-#if defined( SJCD_TRACE )
-	printk("SJCD: status %02x.%02x loaded.\n",
-	       (int) sjcd_completion_status, (int) sjcd_completion_error);
-#endif
-}
-
-/*
- * Read status from cdrom. Check to see if the status is available.
- */
-static int sjcd_check_status(void)
-{
-	/*
-	 * Try to load the response from cdrom into buffer.
-	 */
-	if (SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))) {
-		sjcd_load_status();
-		return (1);
-	} else {
-		/*
-		 * No status is available.
-		 */
-		return (0);
-	}
-}
-
-/*
- * This is just timeout counter, and nothing more. Surprised ? :-)
- */
-static volatile long sjcd_status_timeout;
-
-/*
- * We need about 10 seconds to wait. The longest command takes about 5 seconds
- * to probe the disk (usually after tray closed or drive reset). Other values
- * should be thought of for other commands.
- */
-#define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
-
-static void sjcd_status_timer(void)
-{
-	if (sjcd_check_status()) {
-		/*
-		 * The command completed and status is loaded, stop waiting.
-		 */
-		wake_up(&sjcd_waitq);
-	} else if (--sjcd_status_timeout <= 0) {
-		/*
-		 * We are timed out. 
-		 */
-		wake_up(&sjcd_waitq);
-	} else {
-		/*
-		 * We have still some time to wait. Try again.
-		 */
-		SJCD_SET_TIMER(sjcd_status_timer, 1);
-	}
-}
-
-/*
- * Wait for status for 10 sec approx. Returns non-positive when timed out.
- * Should not be used while reading data CDs.
- */
-static int sjcd_wait_for_status(void)
-{
-	sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT;
-	SJCD_SET_TIMER(sjcd_status_timer, 1);
-	sleep_on(&sjcd_waitq);
-#if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE )
-	if (sjcd_status_timeout <= 0)
-		printk("SJCD: Error Wait For Status.\n");
-#endif
-	return (sjcd_status_timeout);
-}
-
-static int sjcd_receive_status(void)
-{
-	int i;
-#if defined( SJCD_TRACE )
-	printk("SJCD: receive_status\n");
-#endif
-	/*
-	 * Wait a bit for status available.
-	 */
-	for (i = 200; i-- && (sjcd_check_status() == 0););
-	if (i < 0) {
-#if defined( SJCD_TRACE )
-		printk("SJCD: long wait for status\n");
-#endif
-		if (sjcd_wait_for_status() <= 0)
-			printk("SJCD: Timeout when read status.\n");
-		else
-			i = 0;
-	}
-	return (i);
-}
-
-/*
- * Load the status. Issue get status command and wait for status available.
- */
-static void sjcd_get_status(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: get_status\n");
-#endif
-	sjcd_send_cmd(SCMD_GET_STATUS);
-	sjcd_receive_status();
-}
-
-/*
- * Check the drive if the disk is changed. Should be revised.
- */
-static int sjcd_disk_change(struct gendisk *disk)
-{
-#if 0
-	printk("SJCD: sjcd_disk_change(%s)\n", disk->disk_name);
-#endif
-	if (!sjcd_command_is_in_progress)
-		sjcd_get_status();
-	return (sjcd_status_valid ? sjcd_media_is_changed : 0);
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary.
- * We assume that the drive contains no more than 99 toc entries.
- */
-static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS];
-static unsigned char sjcd_first_track_no, sjcd_last_track_no;
-#define sjcd_disk_length  sjcd_table_of_contents[0].un.track_msf
-
-static int sjcd_update_toc(void)
-{
-	struct sjcd_hw_disk_info info;
-	int i;
-#if defined( SJCD_TRACE )
-	printk("SJCD: update toc:\n");
-#endif
-	/*
-	 * check to see if we need to do anything
-	 */
-	if (sjcd_toc_uptodate)
-		return (0);
-
-	/*
-	 * Get the TOC start information.
-	 */
-	sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK);
-	sjcd_receive_status();
-
-	if (!sjcd_status_valid) {
-		printk("SJCD: cannot load status.\n");
-		return (-1);
-	}
-
-	if (!sjcd_media_is_available) {
-		printk("SJCD: no disk in drive\n");
-		return (-1);
-	}
-
-	if (!sjcd_command_failed) {
-		if (sjcd_load_response(&info, sizeof(info)) != 0) {
-			printk
-			    ("SJCD: cannot load response about TOC start.\n");
-			return (-1);
-		}
-		sjcd_first_track_no = bcd2bin(info.un.track_no);
-	} else {
-		printk("SJCD: get first failed\n");
-		return (-1);
-	}
-#if defined( SJCD_TRACE )
-	printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no);
-#endif
-	/*
-	 * Get the TOC finish information.
-	 */
-	sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK);
-	sjcd_receive_status();
-
-	if (!sjcd_status_valid) {
-		printk("SJCD: cannot load status.\n");
-		return (-1);
-	}
-
-	if (!sjcd_media_is_available) {
-		printk("SJCD: no disk in drive\n");
-		return (-1);
-	}
-
-	if (!sjcd_command_failed) {
-		if (sjcd_load_response(&info, sizeof(info)) != 0) {
-			printk
-			    ("SJCD: cannot load response about TOC finish.\n");
-			return (-1);
-		}
-		sjcd_last_track_no = bcd2bin(info.un.track_no);
-	} else {
-		printk("SJCD: get last failed\n");
-		return (-1);
-	}
-#if defined( SJCD_TRACE )
-	printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no);
-#endif
-	for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) {
-		/*
-		 * Get the first track information.
-		 */
-		sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i));
-		sjcd_receive_status();
-
-		if (!sjcd_status_valid) {
-			printk("SJCD: cannot load status.\n");
-			return (-1);
-		}
-
-		if (!sjcd_media_is_available) {
-			printk("SJCD: no disk in drive\n");
-			return (-1);
-		}
-
-		if (!sjcd_command_failed) {
-			if (sjcd_load_response(&sjcd_table_of_contents[i],
-					       sizeof(struct
-						      sjcd_hw_disk_info))
-			    != 0) {
-				printk
-				    ("SJCD: cannot load info for %d track\n",
-				     i);
-				return (-1);
-			}
-		} else {
-			printk("SJCD: get info %d failed\n", i);
-			return (-1);
-		}
-	}
-
-	/*
-	 * Get the disk length info.
-	 */
-	sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE);
-	sjcd_receive_status();
-
-	if (!sjcd_status_valid) {
-		printk("SJCD: cannot load status.\n");
-		return (-1);
-	}
-
-	if (!sjcd_media_is_available) {
-		printk("SJCD: no disk in drive\n");
-		return (-1);
-	}
-
-	if (!sjcd_command_failed) {
-		if (sjcd_load_response(&info, sizeof(info)) != 0) {
-			printk
-			    ("SJCD: cannot load response about disk size.\n");
-			return (-1);
-		}
-		sjcd_disk_length.min = info.un.track_msf.min;
-		sjcd_disk_length.sec = info.un.track_msf.sec;
-		sjcd_disk_length.frame = info.un.track_msf.frame;
-	} else {
-		printk("SJCD: get size failed\n");
-		return (1);
-	}
-#if defined( SJCD_TRACE )
-	printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min,
-	       sjcd_disk_length.sec, sjcd_disk_length.frame);
-#endif
-	return (0);
-}
-
-/*
- * Load subchannel information.
- */
-static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp)
-{
-	int s;
-#if defined( SJCD_TRACE )
-	printk("SJCD: load sub q\n");
-#endif
-	sjcd_send_cmd(SCMD_GET_QINFO);
-	s = sjcd_receive_status();
-	if (s < 0 || sjcd_command_failed || !sjcd_status_valid) {
-		sjcd_send_cmd(0xF2);
-		s = sjcd_receive_status();
-		if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
-			return (-1);
-		sjcd_send_cmd(SCMD_GET_QINFO);
-		s = sjcd_receive_status();
-		if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
-			return (-1);
-	}
-	if (sjcd_media_is_available)
-		if (sjcd_load_response(qp, sizeof(*qp)) == 0)
-			return (0);
-	return (-1);
-}
-
-/*
- * Start playing from the specified position.
- */
-static int sjcd_play(struct sjcd_play_msf *mp)
-{
-	struct sjcd_play_msf msf;
-
-	/*
-	 * Turn the device to play mode.
-	 */
-	sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY);
-	if (sjcd_receive_status() < 0)
-		return (-1);
-
-	/*
-	 * Seek to the starting point.
-	 */
-	msf.start = mp->start;
-	msf.end.min = msf.end.sec = msf.end.frame = 0x00;
-	sjcd_send_6_cmd(SCMD_SEEK, &msf);
-	if (sjcd_receive_status() < 0)
-		return (-1);
-
-	/*
-	 * Start playing.
-	 */
-	sjcd_send_6_cmd(SCMD_PLAY, mp);
-	return (sjcd_receive_status());
-}
-
-/*
- * Tray control functions.
- */
-static int sjcd_tray_close(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: tray_close\n");
-#endif
-	sjcd_send_cmd(SCMD_CLOSE_TRAY);
-	return (sjcd_receive_status());
-}
-
-static int sjcd_tray_lock(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: tray_lock\n");
-#endif
-	sjcd_send_cmd(SCMD_LOCK_TRAY);
-	return (sjcd_receive_status());
-}
-
-static int sjcd_tray_unlock(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: tray_unlock\n");
-#endif
-	sjcd_send_cmd(SCMD_UNLOCK_TRAY);
-	return (sjcd_receive_status());
-}
-
-static int sjcd_tray_open(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: tray_open\n");
-#endif
-	sjcd_send_cmd(SCMD_EJECT_TRAY);
-	return (sjcd_receive_status());
-}
-
-/*
- * Do some user commands.
- */
-static int sjcd_ioctl(struct inode *ip, struct file *fp,
-		      unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-#if defined( SJCD_TRACE )
-	printk("SJCD:ioctl\n");
-#endif
-
-	sjcd_get_status();
-	if (!sjcd_status_valid)
-		return (-EIO);
-	if (sjcd_update_toc() < 0)
-		return (-EIO);
-
-	switch (cmd) {
-	case CDROMSTART:{
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: start\n");
-#endif
-			return (0);
-		}
-
-	case CDROMSTOP:{
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: stop\n");
-#endif
-			sjcd_send_cmd(SCMD_PAUSE);
-			(void) sjcd_receive_status();
-			sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
-			return (0);
-		}
-
-	case CDROMPAUSE:{
-			struct sjcd_hw_qinfo q_info;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: pause\n");
-#endif
-			if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
-				sjcd_send_cmd(SCMD_PAUSE);
-				(void) sjcd_receive_status();
-				if (sjcd_get_q_info(&q_info) < 0) {
-					sjcd_audio_status =
-					    CDROM_AUDIO_NO_STATUS;
-				} else {
-					sjcd_audio_status =
-					    CDROM_AUDIO_PAUSED;
-					sjcd_playing.start = q_info.abs;
-				}
-				return (0);
-			} else
-				return (-EINVAL);
-		}
-
-	case CDROMRESUME:{
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: resume\n");
-#endif
-			if (sjcd_audio_status == CDROM_AUDIO_PAUSED) {
-				/*
-				 * continue play starting at saved location
-				 */
-				if (sjcd_play(&sjcd_playing) < 0) {
-					sjcd_audio_status =
-					    CDROM_AUDIO_ERROR;
-					return (-EIO);
-				} else {
-					sjcd_audio_status =
-					    CDROM_AUDIO_PLAY;
-					return (0);
-				}
-			} else
-				return (-EINVAL);
-		}
-
-	case CDROMPLAYTRKIND:{
-			struct cdrom_ti ti;
-			int s = -EFAULT;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: playtrkind\n");
-#endif
-			if (!copy_from_user(&ti, argp, sizeof(ti))) {
-				s = 0;
-				if (ti.cdti_trk0 < sjcd_first_track_no)
-					return (-EINVAL);
-				if (ti.cdti_trk1 > sjcd_last_track_no)
-					ti.cdti_trk1 = sjcd_last_track_no;
-				if (ti.cdti_trk0 > ti.cdti_trk1)
-					return (-EINVAL);
-
-				sjcd_playing.start =
-				    sjcd_table_of_contents[ti.cdti_trk0].
-				    un.track_msf;
-				sjcd_playing.end =
-				    (ti.cdti_trk1 <
-				     sjcd_last_track_no) ?
-				    sjcd_table_of_contents[ti.cdti_trk1 +
-							   1].un.
-				    track_msf : sjcd_table_of_contents[0].
-				    un.track_msf;
-
-				if (sjcd_play(&sjcd_playing) < 0) {
-					sjcd_audio_status =
-					    CDROM_AUDIO_ERROR;
-					return (-EIO);
-				} else
-					sjcd_audio_status =
-					    CDROM_AUDIO_PLAY;
-			}
-			return (s);
-		}
-
-	case CDROMPLAYMSF:{
-			struct cdrom_msf sjcd_msf;
-			int s;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: playmsf\n");
-#endif
-			if ((s =
-			     access_ok(VERIFY_READ, argp, sizeof(sjcd_msf))
-			     		? 0 : -EFAULT) == 0) {
-				if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
-					sjcd_send_cmd(SCMD_PAUSE);
-					(void) sjcd_receive_status();
-					sjcd_audio_status =
-					    CDROM_AUDIO_NO_STATUS;
-				}
-
-				if (copy_from_user(&sjcd_msf, argp,
-					       sizeof(sjcd_msf)))
-					return (-EFAULT);
-
-				sjcd_playing.start.min =
-				    bin2bcd(sjcd_msf.cdmsf_min0);
-				sjcd_playing.start.sec =
-				    bin2bcd(sjcd_msf.cdmsf_sec0);
-				sjcd_playing.start.frame =
-				    bin2bcd(sjcd_msf.cdmsf_frame0);
-				sjcd_playing.end.min =
-				    bin2bcd(sjcd_msf.cdmsf_min1);
-				sjcd_playing.end.sec =
-				    bin2bcd(sjcd_msf.cdmsf_sec1);
-				sjcd_playing.end.frame =
-				    bin2bcd(sjcd_msf.cdmsf_frame1);
-
-				if (sjcd_play(&sjcd_playing) < 0) {
-					sjcd_audio_status =
-					    CDROM_AUDIO_ERROR;
-					return (-EIO);
-				} else
-					sjcd_audio_status =
-					    CDROM_AUDIO_PLAY;
-			}
-			return (s);
-		}
-
-	case CDROMREADTOCHDR:{
-			struct cdrom_tochdr toc_header;
-#if defined (SJCD_TRACE )
-			printk("SJCD: ioctl: readtocheader\n");
-#endif
-			toc_header.cdth_trk0 = sjcd_first_track_no;
-			toc_header.cdth_trk1 = sjcd_last_track_no;
-			if (copy_to_user(argp, &toc_header,
-					 sizeof(toc_header)))
-				return -EFAULT;
-			return 0;
-		}
-
-	case CDROMREADTOCENTRY:{
-			struct cdrom_tocentry toc_entry;
-			int s;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: readtocentry\n");
-#endif
-			if ((s =
-			     access_ok(VERIFY_WRITE, argp, sizeof(toc_entry))
-			     		? 0 : -EFAULT) == 0) {
-				struct sjcd_hw_disk_info *tp;
-
-				if (copy_from_user(&toc_entry, argp,
-					       sizeof(toc_entry)))
-					return (-EFAULT);
-				if (toc_entry.cdte_track == CDROM_LEADOUT)
-					tp = &sjcd_table_of_contents[0];
-				else if (toc_entry.cdte_track <
-					 sjcd_first_track_no)
-					return (-EINVAL);
-				else if (toc_entry.cdte_track >
-					 sjcd_last_track_no)
-					return (-EINVAL);
-				else
-					tp = &sjcd_table_of_contents
-					    [toc_entry.cdte_track];
-
-				toc_entry.cdte_adr =
-				    tp->track_control & 0x0F;
-				toc_entry.cdte_ctrl =
-				    tp->track_control >> 4;
-
-				switch (toc_entry.cdte_format) {
-				case CDROM_LBA:
-					toc_entry.cdte_addr.lba =
-					    msf2hsg(&(tp->un.track_msf));
-					break;
-				case CDROM_MSF:
-					toc_entry.cdte_addr.msf.minute =
-					    bcd2bin(tp->un.track_msf.min);
-					toc_entry.cdte_addr.msf.second =
-					    bcd2bin(tp->un.track_msf.sec);
-					toc_entry.cdte_addr.msf.frame =
-					    bcd2bin(tp->un.track_msf.
-						    frame);
-					break;
-				default:
-					return (-EINVAL);
-				}
-				if (copy_to_user(argp, &toc_entry,
-						 sizeof(toc_entry)))
-					s = -EFAULT;
-			}
-			return (s);
-		}
-
-	case CDROMSUBCHNL:{
-			struct cdrom_subchnl subchnl;
-			int s;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: subchnl\n");
-#endif
-			if ((s =
-			     access_ok(VERIFY_WRITE, argp, sizeof(subchnl))
-			     		? 0 : -EFAULT) == 0) {
-				struct sjcd_hw_qinfo q_info;
-
-				if (copy_from_user(&subchnl, argp,
-					       sizeof(subchnl)))
-					return (-EFAULT);
-
-				if (sjcd_get_q_info(&q_info) < 0)
-					return (-EIO);
-
-				subchnl.cdsc_audiostatus =
-				    sjcd_audio_status;
-				subchnl.cdsc_adr =
-				    q_info.track_control & 0x0F;
-				subchnl.cdsc_ctrl =
-				    q_info.track_control >> 4;
-				subchnl.cdsc_trk =
-				    bcd2bin(q_info.track_no);
-				subchnl.cdsc_ind = bcd2bin(q_info.x);
-
-				switch (subchnl.cdsc_format) {
-				case CDROM_LBA:
-					subchnl.cdsc_absaddr.lba =
-					    msf2hsg(&(q_info.abs));
-					subchnl.cdsc_reladdr.lba =
-					    msf2hsg(&(q_info.rel));
-					break;
-				case CDROM_MSF:
-					subchnl.cdsc_absaddr.msf.minute =
-					    bcd2bin(q_info.abs.min);
-					subchnl.cdsc_absaddr.msf.second =
-					    bcd2bin(q_info.abs.sec);
-					subchnl.cdsc_absaddr.msf.frame =
-					    bcd2bin(q_info.abs.frame);
-					subchnl.cdsc_reladdr.msf.minute =
-					    bcd2bin(q_info.rel.min);
-					subchnl.cdsc_reladdr.msf.second =
-					    bcd2bin(q_info.rel.sec);
-					subchnl.cdsc_reladdr.msf.frame =
-					    bcd2bin(q_info.rel.frame);
-					break;
-				default:
-					return (-EINVAL);
-				}
-				if (copy_to_user(argp, &subchnl,
-					         sizeof(subchnl)))
-					s = -EFAULT;
-			}
-			return (s);
-		}
-
-	case CDROMVOLCTRL:{
-			struct cdrom_volctrl vol_ctrl;
-			int s;
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: volctrl\n");
-#endif
-			if ((s =
-			     access_ok(VERIFY_READ, argp, sizeof(vol_ctrl))
-			     		? 0 : -EFAULT) == 0) {
-				unsigned char dummy[4];
-
-				if (copy_from_user(&vol_ctrl, argp,
-					       sizeof(vol_ctrl)))
-					return (-EFAULT);
-				sjcd_send_4_cmd(SCMD_SET_VOLUME,
-						vol_ctrl.channel0, 0xFF,
-						vol_ctrl.channel1, 0xFF);
-				if (sjcd_receive_status() < 0)
-					return (-EIO);
-				(void) sjcd_load_response(dummy, 4);
-			}
-			return (s);
-		}
-
-	case CDROMEJECT:{
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: eject\n");
-#endif
-			if (!sjcd_command_is_in_progress) {
-				sjcd_tray_unlock();
-				sjcd_send_cmd(SCMD_EJECT_TRAY);
-				(void) sjcd_receive_status();
-			}
-			return (0);
-		}
-
-#if defined( SJCD_GATHER_STAT )
-	case 0xABCD:{
-#if defined( SJCD_TRACE )
-			printk("SJCD: ioctl: statistic\n");
-#endif
-			if (copy_to_user(argp, &statistic, sizeof(statistic)))
-				return -EFAULT;
-			return 0;
-		}
-#endif
-
-	default:
-		return (-EINVAL);
-	}
-}
-
-/*
- * Invalidate internal buffers of the driver.
- */
-static void sjcd_invalidate_buffers(void)
-{
-	int i;
-	for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1);
-	sjcd_buf_out = -1;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static int current_valid(void)
-{
-        return CURRENT &&
-		CURRENT->cmd == READ &&
-		CURRENT->sector != -1;
-}
-
-static void sjcd_transfer(void)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: transfer:\n");
-#endif
-	if (current_valid()) {
-		while (CURRENT->nr_sectors) {
-			int i, bn = CURRENT->sector / 4;
-			for (i = 0;
-			     i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn;
-			     i++);
-			if (i < SJCD_BUF_SIZ) {
-				int offs =
-				    (i * 4 + (CURRENT->sector & 3)) * 512;
-				int nr_sectors = 4 - (CURRENT->sector & 3);
-				if (sjcd_buf_out != i) {
-					sjcd_buf_out = i;
-					if (sjcd_buf_bn[i] != bn) {
-						sjcd_buf_out = -1;
-						continue;
-					}
-				}
-				if (nr_sectors > CURRENT->nr_sectors)
-					nr_sectors = CURRENT->nr_sectors;
-#if defined( SJCD_TRACE )
-				printk("SJCD: copy out\n");
-#endif
-				memcpy(CURRENT->buffer, sjcd_buf + offs,
-				       nr_sectors * 512);
-				CURRENT->nr_sectors -= nr_sectors;
-				CURRENT->sector += nr_sectors;
-				CURRENT->buffer += nr_sectors * 512;
-			} else {
-				sjcd_buf_out = -1;
-				break;
-			}
-		}
-	}
-#if defined( SJCD_TRACE )
-	printk("SJCD: transfer: done\n");
-#endif
-}
-
-static void sjcd_poll(void)
-{
-#if defined( SJCD_GATHER_STAT )
-	/*
-	 * Update total number of ticks.
-	 */
-	statistic.ticks++;
-	statistic.tticks[sjcd_transfer_state]++;
-#endif
-
-      ReSwitch:switch (sjcd_transfer_state) {
-
-	case SJCD_S_IDLE:{
-#if defined( SJCD_GATHER_STAT )
-			statistic.idle_ticks++;
-#endif
-#if defined( SJCD_TRACE )
-			printk("SJCD_S_IDLE\n");
-#endif
-			return;
-		}
-
-	case SJCD_S_START:{
-#if defined( SJCD_GATHER_STAT )
-			statistic.start_ticks++;
-#endif
-			sjcd_send_cmd(SCMD_GET_STATUS);
-			sjcd_transfer_state =
-			    sjcd_mode ==
-			    SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;
-			sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
-			printk("SJCD_S_START: goto SJCD_S_%s mode\n",
-			       sjcd_transfer_state ==
-			       SJCD_S_READ ? "READ" : "MODE");
-#endif
-			break;
-		}
-
-	case SJCD_S_MODE:{
-			if (sjcd_check_status()) {
-				/*
-				 * Previous command is completed.
-				 */
-				if (!sjcd_status_valid
-				    || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-
-				sjcd_mode = 0;	/* unknown mode; should not be valid when failed */
-				sjcd_send_1_cmd(SCMD_SET_MODE,
-						SCMD_MODE_COOKED);
-				sjcd_transfer_state = SJCD_S_READ;
-				sjcd_transfer_timeout = 1000;
-#if defined( SJCD_TRACE )
-				printk
-				    ("SJCD_S_MODE: goto SJCD_S_READ mode\n");
-#endif
-			}
-#if defined( SJCD_GATHER_STAT )
-			else
-				statistic.mode_ticks++;
-#endif
-			break;
-		}
-
-	case SJCD_S_READ:{
-			if (sjcd_status_valid ? 1 : sjcd_check_status()) {
-				/*
-				 * Previous command is completed.
-				 */
-				if (!sjcd_status_valid
-				    || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-				if (!sjcd_media_is_available) {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-				if (sjcd_mode != SCMD_MODE_COOKED) {
-					/*
-					 * We seem to come from set mode. So discard one byte of result.
-					 */
-					if (sjcd_load_response
-					    (&sjcd_mode, 1) != 0) {
-#if defined( SJCD_TRACE )
-						printk
-						    ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n");
-#endif
-						sjcd_transfer_state =
-						    SJCD_S_STOP;
-						goto ReSwitch;
-					}
-					if (sjcd_mode != SCMD_MODE_COOKED) {
-#if defined( SJCD_TRACE )
-						printk
-						    ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n");
-#endif
-						sjcd_transfer_state =
-						    SJCD_S_STOP;
-						goto ReSwitch;
-					}
-				}
-
-				if (current_valid()) {
-					struct sjcd_play_msf msf;
-
-					sjcd_next_bn = CURRENT->sector / 4;
-					hsg2msf(sjcd_next_bn, &msf.start);
-					msf.end.min = 0;
-					msf.end.sec = 0;
-					msf.end.frame = sjcd_read_count =
-					    SJCD_BUF_SIZ;
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD: ---reading msf-address %x:%x:%x  %x:%x:%x\n",
-					     msf.start.min, msf.start.sec,
-					     msf.start.frame, msf.end.min,
-					     msf.end.sec, msf.end.frame);
-					printk
-					    ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n",
-					     sjcd_next_bn, sjcd_buf_in,
-					     sjcd_buf_out,
-					     sjcd_buf_bn[sjcd_buf_in]);
-#endif
-					sjcd_send_6_cmd(SCMD_DATA_READ,
-							&msf);
-					sjcd_transfer_state = SJCD_S_DATA;
-					sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_READ: go to SJCD_S_DATA mode\n");
-#endif
-				} else {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-			}
-#if defined( SJCD_GATHER_STAT )
-			else
-				statistic.read_ticks++;
-#endif
-			break;
-		}
-
-	case SJCD_S_DATA:{
-			unsigned char stat;
-
-		      sjcd_s_data:stat =
-			    inb(SJCDPORT
-				(1));
-#if defined( SJCD_TRACE )
-			printk("SJCD_S_DATA: status = 0x%02x\n", stat);
-#endif
-			if (SJCD_STATUS_AVAILABLE(stat)) {
-				/*
-				 * No data is waiting for us in the drive buffer. Status of operation
-				 * completion is available. Read and parse it.
-				 */
-				sjcd_load_status();
-
-				if (!sjcd_status_valid
-				    || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD: read block %d failed, maybe audio disk? Giving up\n",
-					     sjcd_next_bn);
-#endif
-					if (current_valid())
-						end_request(CURRENT, 0);
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-
-				if (!sjcd_media_is_available) {
-					printk
-					    ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n");
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-
-				sjcd_transfer_state = SJCD_S_READ;
-				goto ReSwitch;
-			} else if (SJCD_DATA_AVAILABLE(stat)) {
-				/*
-				 * One frame is read into device buffer. We must copy it to our memory.
-				 * Otherwise cdrom hangs up. Check to see if we have something to copy
-				 * to.
-				 */
-				if (!current_valid()
-				    && sjcd_buf_in == sjcd_buf_out) {
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n");
-					printk
-					    (" ... all the date would be discarded\n");
-#endif
-					sjcd_transfer_state = SJCD_S_STOP;
-					goto ReSwitch;
-				}
-
-				/*
-				 * Everything seems to be OK. Just read the frame and recalculate
-				 * indices.
-				 */
-				sjcd_buf_bn[sjcd_buf_in] = -1;	/* ??? */
-				insb(SJCDPORT(2),
-				     sjcd_buf + 2048 * sjcd_buf_in, 2048);
-#if defined( SJCD_TRACE )
-				printk
-				    ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n",
-				     sjcd_next_bn, sjcd_buf_in,
-				     sjcd_buf_out,
-				     sjcd_buf_bn[sjcd_buf_in]);
-#endif
-				sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++;
-				if (sjcd_buf_out == -1)
-					sjcd_buf_out = sjcd_buf_in;
-				if (++sjcd_buf_in == SJCD_BUF_SIZ)
-					sjcd_buf_in = 0;
-
-				/*
-				 * Only one frame is ready at time. So we should turn over to wait for
-				 * another frame. If we need that, of course.
-				 */
-				if (--sjcd_read_count == 0) {
-					/*
-					 * OK, request seems to be precessed. Continue transferring...
-					 */
-					if (!sjcd_transfer_is_active) {
-						while (current_valid()) {
-							/*
-							 * Continue transferring.
-							 */
-							sjcd_transfer();
-							if (CURRENT->
-							    nr_sectors ==
-							    0)
-								end_request
-								    (CURRENT, 1);
-							else
-								break;
-						}
-					}
-					if (current_valid() &&
-					    (CURRENT->sector / 4 <
-					     sjcd_next_bn
-					     || CURRENT->sector / 4 >
-					     sjcd_next_bn +
-					     SJCD_BUF_SIZ)) {
-#if defined( SJCD_TRACE )
-						printk
-						    ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n");
-#endif
-						sjcd_transfer_state =
-						    SJCD_S_STOP;
-						goto ReSwitch;
-					}
-				}
-				/*
-				 * Now we should turn around rather than wait for while.
-				 */
-				goto sjcd_s_data;
-			}
-#if defined( SJCD_GATHER_STAT )
-			else
-				statistic.data_ticks++;
-#endif
-			break;
-		}
-
-	case SJCD_S_STOP:{
-			sjcd_read_count = 0;
-			sjcd_send_cmd(SCMD_STOP);
-			sjcd_transfer_state = SJCD_S_STOPPING;
-			sjcd_transfer_timeout = 500;
-#if defined( SJCD_GATHER_STAT )
-			statistic.stop_ticks++;
-#endif
-			break;
-		}
-
-	case SJCD_S_STOPPING:{
-			unsigned char stat;
-
-			stat = inb(SJCDPORT(1));
-#if defined( SJCD_TRACE )
-			printk("SJCD_S_STOP: status = 0x%02x\n", stat);
-#endif
-			if (SJCD_DATA_AVAILABLE(stat)) {
-				int i;
-#if defined( SJCD_TRACE )
-				printk("SJCD_S_STOP: discard data\n");
-#endif
-				/*
-				 * Discard all the data from the pipe. Foolish method.
-				 */
-				for (i = 2048; i--;
-				     (void) inb(SJCDPORT(2)));
-				sjcd_transfer_timeout = 500;
-			} else if (SJCD_STATUS_AVAILABLE(stat)) {
-				sjcd_load_status();
-				if (sjcd_status_valid
-				    && sjcd_media_is_changed) {
-					sjcd_toc_uptodate = 0;
-					sjcd_invalidate_buffers();
-				}
-				if (current_valid()) {
-					if (sjcd_status_valid)
-						sjcd_transfer_state =
-						    SJCD_S_READ;
-					else
-						sjcd_transfer_state =
-						    SJCD_S_START;
-				} else
-					sjcd_transfer_state = SJCD_S_IDLE;
-				goto ReSwitch;
-			}
-#if defined( SJCD_GATHER_STAT )
-			else
-				statistic.stopping_ticks++;
-#endif
-			break;
-		}
-
-	default:
-		printk("SJCD: poll: invalid state %d\n",
-		       sjcd_transfer_state);
-		return;
-	}
-
-	if (--sjcd_transfer_timeout == 0) {
-		printk("SJCD: timeout in state %d\n", sjcd_transfer_state);
-		while (current_valid())
-			end_request(CURRENT, 0);
-		sjcd_send_cmd(SCMD_STOP);
-		sjcd_transfer_state = SJCD_S_IDLE;
-		goto ReSwitch;
-	}
-
-	/*
-	 * Get back in some time. 1 should be replaced with count variable to
-	 * avoid unnecessary testings.
-	 */
-	SJCD_SET_TIMER(sjcd_poll, 1);
-}
-
-static void do_sjcd_request(request_queue_t * q)
-{
-#if defined( SJCD_TRACE )
-	printk("SJCD: do_sjcd_request(%ld+%ld)\n",
-	       CURRENT->sector, CURRENT->nr_sectors);
-#endif
-	sjcd_transfer_is_active = 1;
-	while (current_valid()) {
-		sjcd_transfer();
-		if (CURRENT->nr_sectors == 0)
-			end_request(CURRENT, 1);
-		else {
-			sjcd_buf_out = -1;	/* Want to read a block not in buffer */
-			if (sjcd_transfer_state == SJCD_S_IDLE) {
-				if (!sjcd_toc_uptodate) {
-					if (sjcd_update_toc() < 0) {
-						printk
-						    ("SJCD: transfer: discard\n");
-						while (current_valid())
-							end_request(CURRENT, 0);
-						break;
-					}
-				}
-				sjcd_transfer_state = SJCD_S_START;
-				SJCD_SET_TIMER(sjcd_poll, HZ / 100);
-			}
-			break;
-		}
-	}
-	sjcd_transfer_is_active = 0;
-#if defined( SJCD_TRACE )
-	printk
-	    ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n",
-	     sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
-	     sjcd_buf_bn[sjcd_buf_in]);
-	printk("do_sjcd_request ends\n");
-#endif
-}
-
-/*
- * Open the device special file. Check disk is in.
- */
-static int sjcd_open(struct inode *ip, struct file *fp)
-{
-	/*
-	 * Check the presence of device.
-	 */
-	if (!sjcd_present)
-		return (-ENXIO);
-
-	/*
-	 * Only read operations are allowed. Really? (:-)
-	 */
-	if (fp->f_mode & 2)
-		return (-EROFS);
-
-	if (sjcd_open_count == 0) {
-		int s, sjcd_open_tries;
-/* We don't know that, do we? */
-/*
-    sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
-*/
-		sjcd_mode = 0;
-		sjcd_door_was_open = 0;
-		sjcd_transfer_state = SJCD_S_IDLE;
-		sjcd_invalidate_buffers();
-		sjcd_status_valid = 0;
-
-		/*
-		 * Strict status checking.
-		 */
-		for (sjcd_open_tries = 4; --sjcd_open_tries;) {
-			if (!sjcd_status_valid)
-				sjcd_get_status();
-			if (!sjcd_status_valid) {
-#if defined( SJCD_DIAGNOSTIC )
-				printk
-				    ("SJCD: open: timed out when check status.\n");
-#endif
-				goto err_out;
-			} else if (!sjcd_media_is_available) {
-#if defined( SJCD_DIAGNOSTIC )
-				printk("SJCD: open: no disk in drive\n");
-#endif
-				if (!sjcd_door_closed) {
-					sjcd_door_was_open = 1;
-#if defined( SJCD_TRACE )
-					printk
-					    ("SJCD: open: close the tray\n");
-#endif
-					s = sjcd_tray_close();
-					if (s < 0 || !sjcd_status_valid
-					    || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-						printk
-						    ("SJCD: open: tray close attempt failed\n");
-#endif
-						goto err_out;
-					}
-					continue;
-				} else
-					goto err_out;
-			}
-			break;
-		}
-		s = sjcd_tray_lock();
-		if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-			printk("SJCD: open: tray lock attempt failed\n");
-#endif
-			goto err_out;
-		}
-#if defined( SJCD_TRACE )
-		printk("SJCD: open: done\n");
-#endif
-	}
-
-	++sjcd_open_count;
-	return (0);
-
-      err_out:
-	return (-EIO);
-}
-
-/*
- * On close, we flush all sjcd blocks from the buffer cache.
- */
-static int sjcd_release(struct inode *inode, struct file *file)
-{
-	int s;
-
-#if defined( SJCD_TRACE )
-	printk("SJCD: release\n");
-#endif
-	if (--sjcd_open_count == 0) {
-		sjcd_invalidate_buffers();
-		s = sjcd_tray_unlock();
-		if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-			printk
-			    ("SJCD: release: tray unlock attempt failed.\n");
-#endif
-		}
-		if (sjcd_door_was_open) {
-			s = sjcd_tray_open();
-			if (s < 0 || !sjcd_status_valid
-			    || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
-				printk
-				    ("SJCD: release: tray unload attempt failed.\n");
-#endif
-			}
-		}
-	}
-	return 0;
-}
-
-/*
- * A list of file operations allowed for this cdrom.
- */
-static struct block_device_operations sjcd_fops = {
-	.owner		= THIS_MODULE,
-	.open		= sjcd_open,
-	.release	= sjcd_release,
-	.ioctl		= sjcd_ioctl,
-	.media_changed	= sjcd_disk_change,
-};
-
-/*
- * Following stuff is intended for initialization of the cdrom. It
- * first looks for presence of device. If the device is present, it
- * will be reset. Then read the version of the drive and load status.
- * The version is two BCD-coded bytes.
- */
-static struct {
-	unsigned char major, minor;
-} sjcd_version;
-
-static struct gendisk *sjcd_disk;
-
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- * Probe cdrom, find out version and status.
- */
-static int __init sjcd_init(void)
-{
-	int i;
-
-	printk(KERN_INFO
-	       "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n",
-	       SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR);
-
-#if defined( SJCD_TRACE )
-	printk("SJCD: sjcd=0x%x: ", sjcd_base);
-#endif
-
-	if (register_blkdev(MAJOR_NR, "sjcd"))
-		return -EIO;
-
-	sjcd_queue = blk_init_queue(do_sjcd_request, &sjcd_lock);
-	if (!sjcd_queue)
-		goto out0;
-
-	blk_queue_hardsect_size(sjcd_queue, 2048);
-
-	sjcd_disk = alloc_disk(1);
-	if (!sjcd_disk) {
-		printk(KERN_ERR "SJCD: can't allocate disk");
-		goto out1;
-	}
-	sjcd_disk->major = MAJOR_NR,
-	sjcd_disk->first_minor = 0,
-	sjcd_disk->fops = &sjcd_fops,
-	sprintf(sjcd_disk->disk_name, "sjcd");
-
-	if (!request_region(sjcd_base, 4,"sjcd")) {
-		printk
-		    ("SJCD: Init failed, I/O port (%X) is already in use\n",
-		     sjcd_base);
-		goto out2;
-	}
-
-	/*
-	 * Check for card. Since we are booting now, we can't use standard
-	 * wait algorithm.
-	 */
-	printk(KERN_INFO "SJCD: Resetting: ");
-	sjcd_send_cmd(SCMD_RESET);
-	for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
-		unsigned long timer;
-
-		/*
-		 * Wait 10ms approx.
-		 */
-		for (timer = jiffies; time_before_eq(jiffies, timer););
-		if ((i % 100) == 0)
-			printk(".");
-		(void) sjcd_check_status();
-	}
-	if (i == 0 || sjcd_command_failed) {
-		printk(" reset failed, no drive found.\n");
-		goto out3;
-	} else
-		printk("\n");
-
-	/*
-	 * Get and print out cdrom version.
-	 */
-	printk(KERN_INFO "SJCD: Getting version: ");
-	sjcd_send_cmd(SCMD_GET_VERSION);
-	for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
-		unsigned long timer;
-
-		/*
-		 * Wait 10ms approx.
-		 */
-		for (timer = jiffies; time_before_eq(jiffies, timer););
-		if ((i % 100) == 0)
-			printk(".");
-		(void) sjcd_check_status();
-	}
-	if (i == 0 || sjcd_command_failed) {
-		printk(" get version failed, no drive found.\n");
-		goto out3;
-	}
-
-	if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) {
-		printk(" %1x.%02x\n", (int) sjcd_version.major,
-		       (int) sjcd_version.minor);
-	} else {
-		printk(" read version failed, no drive found.\n");
-		goto out3;
-	}
-
-	/*
-	 * Check and print out the tray state. (if it is needed?).
-	 */
-	if (!sjcd_status_valid) {
-		printk(KERN_INFO "SJCD: Getting status: ");
-		sjcd_send_cmd(SCMD_GET_STATUS);
-		for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
-			unsigned long timer;
-
-			/*
-			 * Wait 10ms approx.
-			 */
-			for (timer = jiffies;
-			     time_before_eq(jiffies, timer););
-			if ((i % 100) == 0)
-				printk(".");
-			(void) sjcd_check_status();
-		}
-		if (i == 0 || sjcd_command_failed) {
-			printk(" get status failed, no drive found.\n");
-			goto out3;
-		} else
-			printk("\n");
-	}
-
-	printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
-	sjcd_disk->queue = sjcd_queue;
-	add_disk(sjcd_disk);
-
-	sjcd_present++;
-	return (0);
-out3:
-	release_region(sjcd_base, 4);
-out2:
-	put_disk(sjcd_disk);
-out1:
-	blk_cleanup_queue(sjcd_queue);
-out0:
-	if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
-		printk("SJCD: cannot unregister device.\n");
-	return (-EIO);
-}
-
-static void __exit sjcd_exit(void)
-{
-	del_gendisk(sjcd_disk);
-	put_disk(sjcd_disk);
-	release_region(sjcd_base, 4);
-	blk_cleanup_queue(sjcd_queue);
-	if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
-		printk("SJCD: cannot unregister device.\n");
-	printk(KERN_INFO "SJCD: module: removed.\n");
-}
-
-module_init(sjcd_init);
-module_exit(sjcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(SANYO_CDROM_MAJOR);
diff --git a/drivers/cdrom/sjcd.h b/drivers/cdrom/sjcd.h
deleted file mode 100644
index 0aa5e71..0000000
--- a/drivers/cdrom/sjcd.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Definitions for a Sanyo CD-ROM interface.
- *
- *   Copyright (C) 1995  Vadim V. Model
- *                                       model@cecmow.enet.dec.com
- *                                       vadim@rbrf.msk.su
- *                                       vadim@ipsun.ras.ru
- *                       Eric van der Maarel
- *                                       H.T.M.v.d.Maarel@marin.nl
- *
- *  This information is based on mcd.c from M. Harriss and sjcd102.lst from
- *  E. Moenkeberg.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __SJCD_H__
-#define __SJCD_H__
-
-/*
- * Change this to set the I/O port address as default. More flexibility
- * come with setup implementation.
- */
-#define SJCD_BASE_ADDR      0x340
-
-/*
- * Change this to set the irq as default. Really SANYO do not use interrupts
- * at all.
- */
-#define SJCD_INTR_NR        0
-
-/*
- * Change this to set the dma as default value. really SANYO does not use
- * direct memory access at all.
- */
-#define SJCD_DMA_NR         0
-
-/*
- * Macros which allow us to find out the status of the drive.
- */
-#define SJCD_STATUS_AVAILABLE( x ) (((x)&0x02)==0)
-#define SJCD_DATA_AVAILABLE( x )   (((x)&0x01)==0)
-
-/*
- * Port access macro. Three ports are available: S-data port (command port),
- * status port (read only) and D-data port (read only).
- */
-#define SJCDPORT( x )       ( sjcd_base + ( x ) )
-#define SJCD_STATUS_PORT    SJCDPORT( 1 )
-#define SJCD_S_DATA_PORT    SJCDPORT( 0 )
-#define SJCD_COMMAND_PORT   SJCDPORT( 0 )
-#define SJCD_D_DATA_PORT    SJCDPORT( 2 )
-
-/*
- * Drive info bits. Drive info available as first (mandatory) byte of
- * command completion status.
- */
-#define SST_NOT_READY       0x10        /* no disk in the drive (???) */
-#define SST_MEDIA_CHANGED   0x20        /* disk is changed */
-#define SST_DOOR_OPENED     0x40        /* door is open */
-
-/* commands */
-
-#define SCMD_EJECT_TRAY     0xD0        /* eject tray if not locked */
-#define SCMD_LOCK_TRAY      0xD2        /* lock tray when in */
-#define SCMD_UNLOCK_TRAY    0xD4        /* unlock tray when in */
-#define SCMD_CLOSE_TRAY     0xD6        /* load tray in */
-
-#define SCMD_RESET          0xFA        /* soft reset */
-#define SCMD_GET_STATUS     0x80
-#define SCMD_GET_VERSION    0xCC
-
-#define SCMD_DATA_READ      0xA0        /* are the same, depend on mode&args */
-#define SCMD_SEEK           0xA0
-#define SCMD_PLAY           0xA0
-
-#define SCMD_GET_QINFO      0xA8
-
-#define SCMD_SET_MODE       0xC4
-#define SCMD_MODE_PLAY      0xE0
-#define SCMD_MODE_COOKED    (0xF8 & ~0x20)
-#define SCMD_MODE_RAW       0xF9
-#define SCMD_MODE_x20_BIT   0x20        /* What is it for ? */
-
-#define SCMD_SET_VOLUME     0xAE
-#define SCMD_PAUSE          0xE0
-#define SCMD_STOP           0xE0
-
-#define SCMD_GET_DISK_INFO  0xAA
-
-/*
- * Some standard arguments for SCMD_GET_DISK_INFO.
- */
-#define SCMD_GET_1_TRACK    0xA0    /* get the first track information */
-#define SCMD_GET_L_TRACK    0xA1    /* get the last track information */
-#define SCMD_GET_D_SIZE     0xA2    /* get the whole disk information */
-
-/*
- * Borrowed from hd.c. Allows to optimize multiple port read commands.
- */
-#define S_READ_DATA( port, buf, nr )      insb( port, buf, nr )
-
-/*
- * We assume that there are no audio disks with TOC length more than this
- * number (I personally have never seen disks with more than 20 fragments).
- */
-#define SJCD_MAX_TRACKS		100
-
-struct msf {
-  unsigned char   min;
-  unsigned char   sec;
-  unsigned char   frame;
-};
-
-struct sjcd_hw_disk_info {
-  unsigned char track_control;
-  unsigned char track_no;
-  unsigned char x, y, z;
-  union {
-    unsigned char track_no;
-    struct msf track_msf;
-  } un;
-};
-
-struct sjcd_hw_qinfo {
-  unsigned char track_control;
-  unsigned char track_no;
-  unsigned char x;
-  struct msf rel;
-  struct msf abs;
-};
-
-struct sjcd_play_msf {
-  struct msf  start;
-  struct msf  end;
-};
-
-struct sjcd_disk_info {
-  unsigned char   first;
-  unsigned char   last;
-  struct msf      disk_length;
-  struct msf      first_track;
-};
-
-struct sjcd_toc {
-  unsigned char   ctrl_addr;
-  unsigned char   track;
-  unsigned char   point_index;
-  struct msf      track_time;
-  struct msf      disk_time;
-};
-
-#if defined( SJCD_GATHER_STAT )
-
-struct sjcd_stat {
-  int ticks;
-  int tticks[ 8 ];
-  int idle_ticks;
-  int start_ticks;
-  int mode_ticks;
-  int read_ticks;
-  int data_ticks;
-  int stop_ticks;
-  int stopping_ticks;
-};
-
-#endif
-
-#endif
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
deleted file mode 100644
index f77ada9..0000000
--- a/drivers/cdrom/sonycd535.c
+++ /dev/null
@@ -1,1689 +0,0 @@
-/*
- * Sony CDU-535 interface device driver
- *
- * This is a modified version of the CDU-31A device driver (see below).
- * Changes were made using documentation for the CDU-531 (which Sony
- * assures me is very similar to the 535) and partial disassembly of the
- * DOS driver.  I used Minyard's driver and replaced the CDU-31A
- * commands with the CDU-531 commands.  This was complicated by a different
- * interface protocol with the drive.  The driver is still polled.
- *
- * Data transfer rate is about 110 Kb/sec, theoretical maximum is 150 Kb/sec.
- * I tried polling without the sony_sleep during the data transfers but
- * it did not speed things up any.
- *
- * 1993-05-23 (rgj) changed the major number to 21 to get rid of conflict
- * with CDU-31A driver.  This is the also the number from the Linux
- * Device Driver Registry for the Sony Drive.  Hope nobody else is using it.
- *
- * 1993-08-29 (rgj) remove the configuring of the interface board address
- * from the top level configuration, you have to modify it in this file.
- *
- * 1995-01-26 Made module-capable (Joel Katz <Stimpson@Panix.COM>)
- *
- * 1995-05-20
- *  Modified to support CDU-510/515 series
- *      (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- *  Fixed to report verify_area() failures
- *      (Heiko Eissfeldt <heiko@colossus.escape.de>)
- *
- * 1995-06-01
- *  More changes to support CDU-510/515 series
- *      (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- *
- * November 1999 -- Make kernel-parameter implementation work with 2.3.x 
- *	            Removed init_module & cleanup_module in favor of 
- *	            module_init & module_exit.
- *                  Torben Mathiasen <tmm@image.dk>
- *
- * September 2003 - Fix SMP support by removing cli/sti calls.
- *                  Using spinlocks with a wait_queue instead.
- *                  Felipe Damasio <felipewd@terra.com.br>
- *
- * Things to do:
- *  - handle errors and status better, put everything into a single word
- *  - use interrupts (code mostly there, but a big hole still missing)
- *  - handle multi-session CDs?
- *  - use DMA?
- *
- *  Known Bugs:
- *  -
- *
- *   Ken Pizzini (ken@halcyon.com)
- *
- * Original by:
- *   Ron Jeppesen (ronj.an@site007.saic.com)
- *
- *
- *------------------------------------------------------------------------
- * Sony CDROM interface device driver.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to Ken above)
- *
- * Colossians 3:17
- *
- * The Sony interface device driver handles Sony interface CDROM
- * drives and provides a complete block-level interface as well as an
- * ioctl() interface compatible with the Sun (as specified in
- * include/linux/cdrom.h).  With this interface, CDROMs can be
- * accessed and standard audio CDs can be played back normally.
- *
- * This interface is (unfortunately) a polled interface.  This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables.  Some (like mine) do not even have the capability to
- * handle interrupts or DMA.  For this reason you will see a bit of
- * the following:
- *
- *   snap = jiffies;
- *   while (jiffies-snap < SONY_JIFFIES_TIMEOUT)
- *   {
- *		if (some_condition())
- *         break;
- *      sony_sleep();
- *   }
- *   if (some_condition not met)
- *   {
- *      return an_error;
- *   }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try.  (The conditional is written so that jiffies
- * wrap-around is handled properly.)
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk.  The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal.  A lot of conversion goes on.
- *
- *  Copyright (C) 1993  Corey Minyard
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-
-# include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#define REALLY_SLOW_IO
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/cdrom.h>
-
-#define MAJOR_NR CDU535_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
-#include "sonycd535.h"
-
-/*
- * this is the base address of the interface card for the Sony CDU-535
- * CDROM drive.  If your jumpers are set for an address other than
- * this one (the default), change the following line to the
- * proper address.
- */
-#ifndef CDU535_ADDRESS
-# define CDU535_ADDRESS			0x340
-#endif
-#ifndef CDU535_INTERRUPT
-# define CDU535_INTERRUPT		0
-#endif
-#ifndef CDU535_HANDLE
-# define CDU535_HANDLE			"cdu535"
-#endif
-#ifndef CDU535_MESSAGE_NAME
-# define CDU535_MESSAGE_NAME	"Sony CDU-535"
-#endif
-
-#define CDU535_BLOCK_SIZE	2048 
- 
-#ifndef MAX_SPINUP_RETRY
-# define MAX_SPINUP_RETRY		3	/* 1 is sufficient for most drives... */
-#endif
-#ifndef RETRY_FOR_BAD_STATUS
-# define RETRY_FOR_BAD_STATUS	100	/* in 10th of second */
-#endif
-
-#ifndef DEBUG
-# define DEBUG	1
-#endif
-
-/*
- *  SONY535_BUFFER_SIZE determines the size of internal buffer used
- *  by the drive.  It must be at least 2K and the larger the buffer
- *  the better the transfer rate.  It does however take system memory.
- *  On my system I get the following transfer rates using dd to read
- *  10 Mb off /dev/cdrom.
- *
- *    8K buffer      43 Kb/sec
- *   16K buffer      66 Kb/sec
- *   32K buffer      91 Kb/sec
- *   64K buffer     111 Kb/sec
- *  128K buffer     123 Kb/sec
- *  512K buffer     123 Kb/sec
- */
-#define SONY535_BUFFER_SIZE	(64*1024)
-
-/*
- *  if LOCK_DOORS is defined then the eject button is disabled while
- * the device is open.
- */
-#ifndef NO_LOCK_DOORS
-# define LOCK_DOORS
-#endif
-
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int cdu_open(struct inode *inode, struct file *filp);
-static inline unsigned int int_to_bcd(unsigned int val);
-static unsigned int bcd_to_int(unsigned int bcd);
-static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2],
-					   Byte * response, int n_response, int ignoreStatusBit7);
-
-/* The base I/O address of the Sony Interface.  This is a variable (not a
-   #define) so it can be easily changed via some future ioctl() */
-static unsigned int sony535_cd_base_io = CDU535_ADDRESS;
-module_param(sony535_cd_base_io, int, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive.  The
- * comment for the base address also applies here.
- */
-static unsigned short select_unit_reg;
-static unsigned short result_reg;
-static unsigned short command_reg;
-static unsigned short read_status_reg;
-static unsigned short data_reg;
-
-static DEFINE_SPINLOCK(sonycd535_lock); /* queue lock */
-static struct request_queue *sonycd535_queue;
-
-static int initialized;			/* Has the drive been initialized? */
-static int sony_disc_changed = 1;	/* Has the disk been changed
-					   since the last check? */
-static int sony_toc_read;		/* Has the table of contents been
-					   read? */
-static unsigned int sony_buffer_size;	/* Size in bytes of the read-ahead
-					   buffer. */
-static unsigned int sony_buffer_sectors;	/* Size (in 2048 byte records) of
-						   the read-ahead buffer. */
-static unsigned int sony_usage;		/* How many processes have the
-					   drive open. */
-
-static int sony_first_block = -1;	/* First OS block (512 byte) in
-					   the read-ahead buffer */
-static int sony_last_block = -1;	/* Last OS block (512 byte) in
-					   the read-ahead buffer */
-
-static struct s535_sony_toc *sony_toc;	/* Points to the table of
-					   contents. */
-
-static struct s535_sony_subcode *last_sony_subcode;		/* Points to the last
-								   subcode address read */
-static Byte **sony_buffer;		/* Points to the pointers
-					   to the sector buffers */
-
-static int sony_inuse;			/* is the drive in use? Only one
-					   open at a time allowed */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play.  The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over.  This holds the
- * position during a pause so a resume can restart it.  It uses the
- * audio status variable above to tell if it is paused.
- *   I just kept the CDU-31A driver behavior rather than using the PAUSE
- * command on the CDU-535.
- */
-static Byte cur_pos_msf[3];
-static Byte final_pos_msf[3];
-
-/* What IRQ is the drive using?  0 if none. */
-static int sony535_irq_used = CDU535_INTERRUPT;
-
-/* The interrupt handler will wake this queue up when it gets an interrupt. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait);
-
-
-/*
- * This routine returns 1 if the disk has been changed since the last
- * check or 0 if it hasn't.  Setting flag to 0 resets the changed flag.
- */
-static int
-cdu535_check_media_change(struct gendisk *disk)
-{
-	/* if driver is not initialized, always return 0 */
-	int retval = initialized ? sony_disc_changed : 0;
-	sony_disc_changed = 0;
-	return retval;
-}
-
-static inline void
-enable_interrupts(void)
-{
-#ifdef USE_IRQ
-	/*
-	 * This code was taken from cdu31a.c; it will not
-	 * directly work for the cdu535 as written...
-	 */
-	curr_control_reg |= ( SONY_ATTN_INT_EN_BIT
-						| SONY_RES_RDY_INT_EN_BIT
-						| SONY_DATA_RDY_INT_EN_BIT);
-	outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static inline void
-disable_interrupts(void)
-{
-#ifdef USE_IRQ
-	/*
-	 * This code was taken from cdu31a.c; it will not
-	 * directly work for the cdu535 as written...
-	 */
-	curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
-						| SONY_RES_RDY_INT_EN_BIT
-						| SONY_DATA_RDY_INT_EN_BIT);
-	outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static irqreturn_t
-cdu535_interrupt(int irq, void *dev_id)
-{
-	disable_interrupts();
-	if (waitqueue_active(&cdu535_irq_wait)) {
-		wake_up(&cdu535_irq_wait);
-		return IRQ_HANDLED;
-	}
-	printk(CDU535_MESSAGE_NAME
-			": Got an interrupt but nothing was waiting\n");
-	return IRQ_NONE;
-}
-
-
-/*
- * Wait a little while.
- */
-static inline void
-sony_sleep(void)
-{
-	if (sony535_irq_used <= 0) {	/* poll */
-		yield();
-	} else {	/* Interrupt driven */
-		DEFINE_WAIT(wait);
-		
-		spin_lock_irq(&sonycd535_lock);
-		enable_interrupts();
-		prepare_to_wait(&cdu535_irq_wait, &wait, TASK_INTERRUPTIBLE);
-		spin_unlock_irq(&sonycd535_lock);
-		schedule();
-		finish_wait(&cdu535_irq_wait, &wait);
-	}
-}
-
-/*------------------start of SONY CDU535 very specific ---------------------*/
-
-/****************************************************************************
- * void select_unit( int unit_no )
- *
- *  Select the specified unit (0-3) so that subsequent commands reference it
- ****************************************************************************/
-static void
-select_unit(int unit_no)
-{
-	unsigned int select_mask = ~(1 << unit_no);
-	outb(select_mask, select_unit_reg);
-}
-
-/***************************************************************************
- * int read_result_reg( Byte *data_ptr )
- *
- *  Read a result byte from the Sony CDU controller, store in location pointed
- * to by data_ptr.  Return zero on success, TIME_OUT if we did not receive
- * data.
- ***************************************************************************/
-static int
-read_result_reg(Byte *data_ptr)
-{
-	unsigned long snap;
-	int read_status;
-
-	snap = jiffies;
-	while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
-		read_status = inb(read_status_reg);
-		if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
-#if DEBUG > 1
-			printk(CDU535_MESSAGE_NAME
-					": read_result_reg(): readStatReg = 0x%x\n", read_status);
-#endif
-			*data_ptr = inb(result_reg);
-			return 0;
-		} else {
-			sony_sleep();
-		}
-	}
-	printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n");
-	return TIME_OUT;
-}
-
-/****************************************************************************
- * int read_exec_status( Byte status[2] )
- *
- *  Read the execution status of the last command and put into status.
- * Handles reading second status word if available.  Returns 0 on success,
- * TIME_OUT on failure.
- ****************************************************************************/
-static int
-read_exec_status(Byte status[2])
-{
-	status[1] = 0;
-	if (read_result_reg(&(status[0])) != 0)
-		return TIME_OUT;
-	if ((status[0] & 0x80) != 0) {	/* byte two follows */
-		if (read_result_reg(&(status[1])) != 0)
-			return TIME_OUT;
-	}
-#if DEBUG > 1
-	printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n",
-			status[0], status[1]);
-#endif
-	return 0;
-}
-
-/****************************************************************************
- * int check_drive_status( void )
- *
- *  Check the current drive status.  Using this before executing a command
- * takes care of the problem of unsolicited drive status-2 messages.
- * Add a check of the audio status if we think the disk is playing.
- ****************************************************************************/
-static int
-check_drive_status(void)
-{
-	Byte status, e_status[2];
-	int  CDD, ATN;
-	Byte cmd;
-
-	select_unit(0);
-	if (sony_audio_status == CDROM_AUDIO_PLAY) {	/* check status */
-		outb(SONY535_REQUEST_AUDIO_STATUS, command_reg);
-		if (read_result_reg(&status) == 0) {
-			switch (status) {
-			case 0x0:
-				break;		/* play in progress */
-			case 0x1:
-				break;		/* paused */
-			case 0x3:		/* audio play completed */
-			case 0x5:		/* play not requested */
-				sony_audio_status = CDROM_AUDIO_COMPLETED;
-				read_subcode();
-				break;
-			case 0x4:		/* error during play */
-				sony_audio_status = CDROM_AUDIO_ERROR;
-				break;
-			}
-		}
-	}
-	/* now check drive status */
-	outb(SONY535_REQUEST_DRIVE_STATUS_2, command_reg);
-	if (read_result_reg(&status) != 0)
-		return TIME_OUT;
-
-#if DEBUG > 1
-	printk(CDU535_MESSAGE_NAME ": check_drive_status() got 0x%x\n", status);
-#endif
-
-	if (status == 0)
-		return 0;
-
-	ATN = status & 0xf;
-	CDD = (status >> 4) & 0xf;
-
-	switch (ATN) {
-	case 0x0:
-		break;					/* go on to CDD stuff */
-	case SONY535_ATN_BUSY:
-		if (initialized)
-			printk(CDU535_MESSAGE_NAME " error: drive busy\n");
-		return CD_BUSY;
-	case SONY535_ATN_EJECT_IN_PROGRESS:
-		printk(CDU535_MESSAGE_NAME " error: eject in progress\n");
-		sony_audio_status = CDROM_AUDIO_INVALID;
-		return CD_BUSY;
-	case SONY535_ATN_RESET_OCCURRED:
-	case SONY535_ATN_DISC_CHANGED:
-	case SONY535_ATN_RESET_AND_DISC_CHANGED:
-#if DEBUG > 0
-		printk(CDU535_MESSAGE_NAME " notice: reset occurred or disc changed\n");
-#endif
-		sony_disc_changed = 1;
-		sony_toc_read = 0;
-		sony_audio_status = CDROM_AUDIO_NO_STATUS;
-		sony_first_block = -1;
-		sony_last_block = -1;
-		if (initialized) {
-			cmd = SONY535_SPIN_UP;
-			do_sony_cmd(&cmd, 1, e_status, NULL, 0, 0);
-			sony_get_toc();
-		}
-		return 0;
-	default:
-		printk(CDU535_MESSAGE_NAME " error: drive busy (ATN=0x%x)\n", ATN);
-		return CD_BUSY;
-	}
-	switch (CDD) {			/* the 531 docs are not helpful in decoding this */
-	case 0x0:				/* just use the values from the DOS driver */
-	case 0x2:
-	case 0xa:
-		break;				/* no error */
-	case 0xc:
-		printk(CDU535_MESSAGE_NAME
-				": check_drive_status(): CDD = 0xc! Not properly handled!\n");
-		return CD_BUSY;		/* ? */
-	default:
-		return CD_BUSY;
-	}
-	return 0;
-}	/* check_drive_status() */
-
-/*****************************************************************************
- * int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2],
- *                Byte *response, int n_response, int ignore_status_bit7 )
- *
- *  Generic routine for executing commands.  The command and its parameters
- *  should be placed in the cmd[] array, number of bytes in the command is
- *  stored in nCmd.  The response from the command will be stored in the
- *  response array.  The number of bytes you expect back (excluding status)
- *  should be passed in n_response.  Finally, some
- *  commands set bit 7 of the return status even when there is no second
- *  status byte, on these commands set ignoreStatusBit7 TRUE.
- *    If the command was sent and data received back, then we return 0,
- *  else we return TIME_OUT.  You still have to check the status yourself.
- *    You should call check_drive_status() before calling this routine
- *  so that you do not lose notifications of disk changes, etc.
- ****************************************************************************/
-static int
-do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
-			Byte * response, int n_response, int ignore_status_bit7)
-{
-	int i;
-
-	/* write out the command */
-	for (i = 0; i < n_cmd; i++)
-		outb(cmd[i], command_reg);
-
-	/* read back the status */
-	if (read_result_reg(status) != 0)
-		return TIME_OUT;
-	if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) {
-		/* get second status byte */
-		if (read_result_reg(status + 1) != 0)
-			return TIME_OUT;
-	} else {
-		status[1] = 0;
-	}
-#if DEBUG > 2
-	printk(CDU535_MESSAGE_NAME ": do_sony_cmd %x: %x %x\n",
-			*cmd, status[0], status[1]);
-#endif
-
-	/* do not know about when I should read set of data and when not to */
-	if ((status[0] & ((ignore_status_bit7 ? 0x7f : 0xff) & 0x8f)) != 0)
-		return 0;
-
-	/* else, read in rest of data */
-	for (i = 0; 0 < n_response; n_response--, i++)
-		if (read_result_reg(response + i) != 0)
-			return TIME_OUT;
-	return 0;
-}	/* do_sony_cmd() */
-
-/**************************************************************************
- * int set_drive_mode( int mode, Byte status[2] )
- *
- *  Set the drive mode to the specified value (mode=0 is audio, mode=e0
- * is mode-1 CDROM
- **************************************************************************/
-static int
-set_drive_mode(int mode, Byte status[2])
-{
-	Byte cmd_buff[2];
-	Byte ret_buff[1];
-
-	cmd_buff[0] = SONY535_SET_DRIVE_MODE;
-	cmd_buff[1] = mode;
-	return do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1);
-}
-
-/***************************************************************************
- * int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2],
- *                             Byte *data_buff, int buff_size )
- *
- *  Read n_blocks of data from the CDROM starting at position params[0:2],
- *  number of blocks in stored in params[3:5] -- both these are already
- *  int bcd format.
- *  Transfer the data into the buffer pointed at by data_buff.  buff_size
- *  gives the number of bytes available in the buffer.
- *    The routine returns number of bytes read in if successful, otherwise
- *  it returns one of the standard error returns.
- ***************************************************************************/
-static int
-seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
-					   Byte **buff, int buf_size)
-{
-	Byte cmd_buff[7];
-	int  i;
-	int  read_status;
-	unsigned long snap;
-	Byte *data_buff;
-	int  sector_count = 0;
-
-	if (buf_size < CDU535_BLOCK_SIZE * n_blocks)
-		return NO_ROOM;
-
-	set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
-
-	/* send command to read the data */
-	cmd_buff[0] = SONY535_SEEK_AND_READ_N_BLOCKS_1;
-	for (i = 0; i < 6; i++)
-		cmd_buff[i + 1] = params[i];
-	for (i = 0; i < 7; i++)
-		outb(cmd_buff[i], command_reg);
-
-	/* read back the data one block at a time */
-	while (0 < n_blocks--) {
-		/* wait for data to be ready */
-		int data_valid = 0;
-		snap = jiffies;
-		while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
-			read_status = inb(read_status_reg);
-			if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
-				read_exec_status(status);
-				return BAD_STATUS;
-			}
-			if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
-				/* data is ready, read it */
-				data_buff = buff[sector_count++];
-				for (i = 0; i < CDU535_BLOCK_SIZE; i++)
-					*data_buff++ = inb(data_reg);	/* unrolling this loop does not seem to help */
-				data_valid = 1;
-				break;			/* exit the timeout loop */
-			}
-			sony_sleep();		/* data not ready, sleep a while */
-		}
-		if (!data_valid)
-			return TIME_OUT;	/* if we reach this stage */
-	}
-
-	/* read all the data, now read the status */
-	if ((i = read_exec_status(status)) != 0)
-		return i;
-	return CDU535_BLOCK_SIZE * sector_count;
-}	/* seek_and_read_N_blocks() */
-
-/****************************************************************************
- * int request_toc_data( Byte status[2], struct s535_sony_toc *toc )
- *
- *  Read in the table of contents data.  Converts all the bcd data
- * into integers in the toc structure.
- ****************************************************************************/
-static int
-request_toc_data(Byte status[2], struct s535_sony_toc *toc)
-{
-	int  to_status;
-	int  i, j, n_tracks, track_no;
-	int  first_track_num, last_track_num;
-	Byte cmd_no = 0xb2;
-	Byte track_address_buffer[5];
-
-	/* read the fixed portion of the table of contents */
-	if ((to_status = do_sony_cmd(&cmd_no, 1, status, (Byte *) toc, 15, 1)) != 0)
-		return to_status;
-
-	/* convert the data into integers so we can use them */
-	first_track_num = bcd_to_int(toc->first_track_num);
-	last_track_num = bcd_to_int(toc->last_track_num);
-	n_tracks = last_track_num - first_track_num + 1;
-
-	/* read each of the track address descriptors */
-	for (i = 0; i < n_tracks; i++) {
-		/* read the descriptor into a temporary buffer */
-		for (j = 0; j < 5; j++) {
-			if (read_result_reg(track_address_buffer + j) != 0)
-				return TIME_OUT;
-			if (j == 1)		/* need to convert from bcd */
-				track_no = bcd_to_int(track_address_buffer[j]);
-		}
-		/* copy the descriptor to proper location - sonycd.c just fills */
-		memcpy(toc->tracks + i, track_address_buffer, 5);
-	}
-	return 0;
-}	/* request_toc_data() */
-
-/***************************************************************************
- * int spin_up_drive( Byte status[2] )
- *
- *  Spin up the drive (unless it is already spinning).
- ***************************************************************************/
-static int
-spin_up_drive(Byte status[2])
-{
-	Byte cmd;
-
-	/* first see if the drive is already spinning */
-	cmd = SONY535_REQUEST_DRIVE_STATUS_1;
-	if (do_sony_cmd(&cmd, 1, status, NULL, 0, 0) != 0)
-		return TIME_OUT;
-	if ((status[0] & SONY535_STATUS1_NOT_SPINNING) == 0)
-		return 0;	/* it's already spinning */
-
-	/* otherwise, give the spin-up command */
-	cmd = SONY535_SPIN_UP;
-	return do_sony_cmd(&cmd, 1, status, NULL, 0, 0);
-}
-
-/*--------------------end of SONY CDU535 very specific ---------------------*/
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int
-int_to_bcd(unsigned int val)
-{
-	int retval;
-
-	retval = (val / 10) << 4;
-	retval = retval | val % 10;
-	return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int
-bcd_to_int(unsigned int bcd)
-{
-	return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void
-log_to_msf(unsigned int log, Byte *msf)
-{
-	log = log + LOG_START_OFFSET;
-	msf[0] = int_to_bcd(log / 4500);
-	log = log % 4500;
-	msf[1] = int_to_bcd(log / 75);
-	msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int
-msf_to_log(Byte *msf)
-{
-	unsigned int log;
-
-
-	log = bcd_to_int(msf[2]);
-	log += bcd_to_int(msf[1]) * 75;
-	log += bcd_to_int(msf[0]) * 4500;
-	log = log - LOG_START_OFFSET;
-
-	return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void
-size_to_buf(unsigned int size, Byte *buf)
-{
-	buf[0] = size / 65536;
-	size = size % 65536;
-	buf[1] = size / 256;
-	buf[2] = size % 256;
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail.  Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations.  This especially helps since the OS
- * may use 1024 byte blocks and the drive uses 2048 byte blocks.  Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void
-do_cdu535_request(request_queue_t * q)
-{
-	struct request *req;
-	unsigned int read_size;
-	int  block;
-	int  nsect;
-	int  copyoff;
-	int  spin_up_retry;
-	Byte params[10];
-	Byte status[2];
-	Byte cmd[2];
-
-	while (1) {
-		req = elv_next_request(q);
-		if (!req)
-			return;
-
-		block = req->sector;
-		nsect = req->nr_sectors;
-		if (!blk_fs_request(req)) {
-			end_request(req, 0);
-			continue;
-		}
-		if (rq_data_dir(req) == WRITE) {
-			end_request(req, 0);
-			continue;
-		}
-		/*
-		 * If the block address is invalid or the request goes beyond
-		 * the end of the media, return an error.
-		 */
-		if (sony_toc->lead_out_start_lba <= (block/4)) {
-			end_request(req, 0);
-			return;
-		}
-		if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
-			end_request(req, 0);
-			return;
-		}
-		while (0 < nsect) {
-			/*
-			 * If the requested sector is not currently in
-			 * the read-ahead buffer, it must be read in.
-			 */
-			if ((block < sony_first_block) || (sony_last_block < block)) {
-				sony_first_block = (block / 4) * 4;
-				log_to_msf(block / 4, params);
-				
-				/*
-				 * If the full read-ahead would go beyond the end of the media, trim
-				 * it back to read just till the end of the media.
-				 */
-				if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
-					sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
-					read_size = sony_toc->lead_out_start_lba - (block / 4);
-				} else {
-					sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
-					read_size = sony_buffer_sectors;
-				}
-				size_to_buf(read_size, &params[3]);
-				
-				/*
-				 * Read the data.  If the drive was not spinning,
-				 * spin it up and try some more.
-				 */
-				for (spin_up_retry=0 ;; ++spin_up_retry) {
-					/* This loop has been modified to support the Sony
-					 * CDU-510/515 series, thanks to Claudio Porfiri 
-					 * <C.Porfiri@nisms.tei.ericsson.se>.
-					 */
-					/*
-					 * This part is to deal with very slow hardware.  We
-					 * try at most MAX_SPINUP_RETRY times to read the same
-					 * block.  A check for seek_and_read_N_blocks' result is
-					 * performed; if the result is wrong, the CDROM's engine
-					 * is restarted and the operation is tried again.
-					 */
-					/*
-					 * 1995-06-01: The system got problems when downloading
-					 * from Slackware CDROM, the problem seems to be:
-					 * seek_and_read_N_blocks returns BAD_STATUS and we
-					 * should wait for a while before retrying, so a new
-					 * part was added to discriminate the return value from
-					 * seek_and_read_N_blocks for the various cases.
-					 */
-					int readStatus = seek_and_read_N_blocks(params, read_size,
-										status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
-					if (0 <= readStatus)	/* Good data; common case, placed first */
-						break;
-					if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
-						/* give up */
-						if (readStatus == NO_ROOM)
-							printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
-						else
-							printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
-							       status[0]);
-						sony_first_block = -1;
-						sony_last_block = -1;
-						end_request(req, 0);
-						return;
-					}
-					if (readStatus == BAD_STATUS) {
-						/* Sleep for a while, then retry */
-						set_current_state(TASK_INTERRUPTIBLE);
-						spin_unlock_irq(&sonycd535_lock);
-						schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
-						spin_lock_irq(&sonycd535_lock);
-					}
-#if DEBUG > 0
-					printk(CDU535_MESSAGE_NAME
-					       " debug: calling spin up when reading data!\n");
-#endif
-					cmd[0] = SONY535_SPIN_UP;
-					do_sony_cmd(cmd, 1, status, NULL, 0, 0);
-				}
-			}
-			/*
-			 * The data is in memory now, copy it to the buffer and advance to the
-			 * next block to read.
-			 */
-			copyoff = block - sony_first_block;
-			memcpy(req->buffer,
-			       sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
-			
-			block += 1;
-			nsect -= 1;
-			req->buffer += 512;
-		}
-
-		end_request(req, 1);
-	}
-}
-
-/*
- * Read the table of contents from the drive and set sony_toc_read if
- * successful.
- */
-static void
-sony_get_toc(void)
-{
-	Byte status[2];
-	if (!sony_toc_read) {
-		/* do not call check_drive_status() from here since it can call this routine */
-		if (request_toc_data(status, sony_toc) < 0)
-			return;
-		sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);
-		sony_toc_read = 1;
-	}
-}
-
-
-/*
- * Search for a specific track in the table of contents.  track is
- * passed in bcd format
- */
-static int
-find_track(int track)
-{
-	int i;
-	int num_tracks;
-
-
-	num_tracks = bcd_to_int(sony_toc->last_track_num) -
-		bcd_to_int(sony_toc->first_track_num) + 1;
-	for (i = 0; i < num_tracks; i++) {
-		if (sony_toc->tracks[i].track == track) {
-			return i;
-		}
-	}
-
-	return -1;
-}
-
-/*
- * Read the subcode and put it int last_sony_subcode for future use.
- */
-static int
-read_subcode(void)
-{
-	Byte cmd = SONY535_REQUEST_SUB_Q_DATA;
-	Byte status[2];
-	int  dsc_status;
-
-	if (check_drive_status() != 0)
-		return -EIO;
-
-	if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode,
-							   sizeof(struct s535_sony_subcode), 1)) != 0) {
-		printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n",
-				status[0], dsc_status);
-		return -EIO;
-	}
-	return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it.  If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing).  If the drive is paused or completed, the subcode information has
- * already been stored, just use that.  The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int
-sony_get_subchnl_info(void __user *arg)
-{
-	struct cdrom_subchnl schi;
-
-	/* Get attention stuff */
-	if (check_drive_status() != 0)
-		return -EIO;
-
-	sony_get_toc();
-	if (!sony_toc_read) {
-		return -EIO;
-	}
-	if (copy_from_user(&schi, arg, sizeof schi))
-		return -EFAULT;
-
-	switch (sony_audio_status) {
-	case CDROM_AUDIO_PLAY:
-		if (read_subcode() < 0) {
-			return -EIO;
-		}
-		break;
-
-	case CDROM_AUDIO_PAUSED:
-	case CDROM_AUDIO_COMPLETED:
-		break;
-
-	case CDROM_AUDIO_NO_STATUS:
-		schi.cdsc_audiostatus = sony_audio_status;
-		if (copy_to_user(arg, &schi, sizeof schi))
-			return -EFAULT;
-		return 0;
-		break;
-
-	case CDROM_AUDIO_INVALID:
-	case CDROM_AUDIO_ERROR:
-	default:
-		return -EIO;
-	}
-
-	schi.cdsc_audiostatus = sony_audio_status;
-	schi.cdsc_adr = last_sony_subcode->address;
-	schi.cdsc_ctrl = last_sony_subcode->control;
-	schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num);
-	schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);
-	if (schi.cdsc_format == CDROM_MSF) {
-		schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);
-		schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);
-		schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);
-
-		schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);
-		schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);
-		schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]);
-	} else if (schi.cdsc_format == CDROM_LBA) {
-		schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
-		schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
-	}
-	return copy_to_user(arg, &schi, sizeof schi) ? -EFAULT : 0;
-}
-
-
-/*
- * The big ugly ioctl handler.
- */
-static int
-cdu_ioctl(struct inode *inode,
-		  struct file *file,
-		  unsigned int cmd,
-		  unsigned long arg)
-{
-	Byte status[2];
-	Byte cmd_buff[10], params[10];
-	int  i;
-	int  dsc_status;
-	void __user *argp = (void __user *)arg;
-
-	if (check_drive_status() != 0)
-		return -EIO;
-
-	switch (cmd) {
-	case CDROMSTART:			/* Spin up the drive */
-		if (spin_up_drive(status) < 0) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n",
-					status[0]);
-			return -EIO;
-		}
-		return 0;
-		break;
-
-	case CDROMSTOP:			/* Spin down the drive */
-		cmd_buff[0] = SONY535_HOLD;
-		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
-		/*
-		 * Spin the drive down, ignoring the error if the disk was
-		 * already not spinning.
-		 */
-		sony_audio_status = CDROM_AUDIO_NO_STATUS;
-		cmd_buff[0] = SONY535_SPIN_DOWN;
-		dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-		if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) ||
-			((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n",
-					status[0]);
-			return -EIO;
-		}
-		return 0;
-		break;
-
-	case CDROMPAUSE:			/* Pause the drive */
-		cmd_buff[0] = SONY535_HOLD;		/* CDU-31 driver uses AUDIO_STOP, not pause */
-		if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n",
-					status[0]);
-			return -EIO;
-		}
-		/* Get the current position and save it for resuming */
-		if (read_subcode() < 0) {
-			return -EIO;
-		}
-		cur_pos_msf[0] = last_sony_subcode->abs_msf[0];
-		cur_pos_msf[1] = last_sony_subcode->abs_msf[1];
-		cur_pos_msf[2] = last_sony_subcode->abs_msf[2];
-		sony_audio_status = CDROM_AUDIO_PAUSED;
-		return 0;
-		break;
-
-	case CDROMRESUME:			/* Start the drive after being paused */
-		set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
-		if (sony_audio_status != CDROM_AUDIO_PAUSED) {
-			return -EINVAL;
-		}
-		spin_up_drive(status);
-
-		/* Start the drive at the saved position. */
-		cmd_buff[0] = SONY535_PLAY_AUDIO;
-		cmd_buff[1] = 0;		/* play back starting at this address */
-		cmd_buff[2] = cur_pos_msf[0];
-		cmd_buff[3] = cur_pos_msf[1];
-		cmd_buff[4] = cur_pos_msf[2];
-		cmd_buff[5] = SONY535_PLAY_AUDIO;
-		cmd_buff[6] = 2;		/* set ending address */
-		cmd_buff[7] = final_pos_msf[0];
-		cmd_buff[8] = final_pos_msf[1];
-		cmd_buff[9] = final_pos_msf[2];
-		if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
-			(do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n",
-					status[0]);
-			return -EIO;
-		}
-		sony_audio_status = CDROM_AUDIO_PLAY;
-		return 0;
-		break;
-
-	case CDROMPLAYMSF:			/* Play starting at the given MSF address. */
-		if (copy_from_user(params, argp, 6))
-			return -EFAULT;
-		spin_up_drive(status);
-		set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
-		/* The parameters are given in int, must be converted */
-		for (i = 0; i < 3; i++) {
-			cmd_buff[2 + i] = int_to_bcd(params[i]);
-			cmd_buff[7 + i] = int_to_bcd(params[i + 3]);
-		}
-		cmd_buff[0] = SONY535_PLAY_AUDIO;
-		cmd_buff[1] = 0;		/* play back starting at this address */
-		/* cmd_buff[2-4] are filled in for loop above */
-		cmd_buff[5] = SONY535_PLAY_AUDIO;
-		cmd_buff[6] = 2;		/* set ending address */
-		/* cmd_buff[7-9] are filled in for loop above */
-		if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
-			(do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n",
-					status[0]);
-			return -EIO;
-		}
-		/* Save the final position for pauses and resumes */
-		final_pos_msf[0] = cmd_buff[7];
-		final_pos_msf[1] = cmd_buff[8];
-		final_pos_msf[2] = cmd_buff[9];
-		sony_audio_status = CDROM_AUDIO_PLAY;
-		return 0;
-		break;
-
-	case CDROMREADTOCHDR:		/* Read the table of contents header */
-		{
-			struct cdrom_tochdr __user *hdr = argp;
-			struct cdrom_tochdr loc_hdr;
-
-			sony_get_toc();
-			if (!sony_toc_read)
-				return -EIO;
-			loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
-			loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
-			if (copy_to_user(hdr, &loc_hdr, sizeof *hdr))
-				return -EFAULT;
-		}
-		return 0;
-		break;
-
-	case CDROMREADTOCENTRY:	/* Read a given table of contents entry */
-		{
-			struct cdrom_tocentry __user *entry = argp;
-			struct cdrom_tocentry loc_entry;
-			int  track_idx;
-			Byte *msf_val = NULL;
-
-			sony_get_toc();
-			if (!sony_toc_read) {
-				return -EIO;
-			}
-
-			if (copy_from_user(&loc_entry, entry, sizeof loc_entry))
-				return -EFAULT;
-
-			/* Lead out is handled separately since it is special. */
-			if (loc_entry.cdte_track == CDROM_LEADOUT) {
-				loc_entry.cdte_adr = 0 /*sony_toc->address2 */ ;
-				loc_entry.cdte_ctrl = sony_toc->control2;
-				msf_val = sony_toc->lead_out_start_msf;
-			} else {
-				track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
-				if (track_idx < 0)
-					return -EINVAL;
-				loc_entry.cdte_adr = 0 /*sony_toc->tracks[track_idx].address */ ;
-				loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;
-				msf_val = sony_toc->tracks[track_idx].track_start_msf;
-			}
-
-			/* Logical buffer address or MSF format requested? */
-			if (loc_entry.cdte_format == CDROM_LBA) {
-				loc_entry.cdte_addr.lba = msf_to_log(msf_val);
-			} else if (loc_entry.cdte_format == CDROM_MSF) {
-				loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
-				loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1));
-				loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2));
-			}
-			if (copy_to_user(entry, &loc_entry, sizeof *entry))
-				return -EFAULT;
-		}
-		return 0;
-		break;
-
-	case CDROMPLAYTRKIND:		/* Play a track.  This currently ignores index. */
-		{
-			struct cdrom_ti ti;
-			int track_idx;
-
-			sony_get_toc();
-			if (!sony_toc_read)
-				return -EIO;
-
-			if (copy_from_user(&ti, argp, sizeof ti))
-				return -EFAULT;
-			if ((ti.cdti_trk0 < sony_toc->first_track_num)
-				|| (sony_toc->last_track_num < ti.cdti_trk0)
-				|| (ti.cdti_trk1 < ti.cdti_trk0)) {
-				return -EINVAL;
-			}
-			track_idx = find_track(int_to_bcd(ti.cdti_trk0));
-			if (track_idx < 0)
-				return -EINVAL;
-			params[1] = sony_toc->tracks[track_idx].track_start_msf[0];
-			params[2] = sony_toc->tracks[track_idx].track_start_msf[1];
-			params[3] = sony_toc->tracks[track_idx].track_start_msf[2];
-			/*
-			 * If we want to stop after the last track, use the lead-out
-			 * MSF to do that.
-			 */
-			if (bcd_to_int(sony_toc->last_track_num) <= ti.cdti_trk1) {
-				log_to_msf(msf_to_log(sony_toc->lead_out_start_msf) - 1,
-						   &(params[4]));
-			} else {
-				track_idx = find_track(int_to_bcd(ti.cdti_trk1 + 1));
-				if (track_idx < 0)
-					return -EINVAL;
-				log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf) - 1,
-						   &(params[4]));
-			}
-			params[0] = 0x03;
-
-			spin_up_drive(status);
-
-			set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
-			/* Start the drive at the saved position. */
-			cmd_buff[0] = SONY535_PLAY_AUDIO;
-			cmd_buff[1] = 0;	/* play back starting at this address */
-			cmd_buff[2] = params[1];
-			cmd_buff[3] = params[2];
-			cmd_buff[4] = params[3];
-			cmd_buff[5] = SONY535_PLAY_AUDIO;
-			cmd_buff[6] = 2;	/* set ending address */
-			cmd_buff[7] = params[4];
-			cmd_buff[8] = params[5];
-			cmd_buff[9] = params[6];
-			if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
-				(do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
-				printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYTRKIND)\n",
-						status[0]);
-				printk("... Params: %x %x %x %x %x %x %x\n",
-						params[0], params[1], params[2],
-						params[3], params[4], params[5], params[6]);
-				return -EIO;
-			}
-			/* Save the final position for pauses and resumes */
-			final_pos_msf[0] = params[4];
-			final_pos_msf[1] = params[5];
-			final_pos_msf[2] = params[6];
-			sony_audio_status = CDROM_AUDIO_PLAY;
-			return 0;
-		}
-
-	case CDROMSUBCHNL:			/* Get subchannel info */
-		return sony_get_subchnl_info(argp);
-
-	case CDROMVOLCTRL:			/* Volume control.  What volume does this change, anyway? */
-		{
-			struct cdrom_volctrl volctrl;
-
-			if (copy_from_user(&volctrl, argp, sizeof volctrl))
-				return -EFAULT;
-			cmd_buff[0] = SONY535_SET_VOLUME;
-			cmd_buff[1] = volctrl.channel0;
-			cmd_buff[2] = volctrl.channel1;
-			if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) {
-				printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n",
-						status[0]);
-				return -EIO;
-			}
-		}
-		return 0;
-
-	case CDROMEJECT:			/* Eject the drive */
-		cmd_buff[0] = SONY535_STOP;
-		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-		cmd_buff[0] = SONY535_SPIN_DOWN;
-		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
-		sony_audio_status = CDROM_AUDIO_INVALID;
-		cmd_buff[0] = SONY535_EJECT_CADDY;
-		if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
-			printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n",
-					status[0]);
-			return -EIO;
-		}
-		return 0;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-}
-
-
-/*
- * Open the drive for operations.  Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int
-cdu_open(struct inode *inode,
-		 struct file *filp)
-{
-	Byte status[2], cmd_buff[2];
-
-	if (sony_inuse)
-		return -EBUSY;
-	if (check_drive_status() != 0)
-		return -EIO;
-	sony_inuse = 1;
-
-	if (spin_up_drive(status) != 0) {
-		printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n",
-				status[0]);
-		sony_inuse = 0;
-		return -EIO;
-	}
-	sony_get_toc();
-	if (!sony_toc_read) {
-		cmd_buff[0] = SONY535_SPIN_DOWN;
-		do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-		sony_inuse = 0;
-		return -EIO;
-	}
-	check_disk_change(inode->i_bdev);
-	sony_usage++;
-
-#ifdef LOCK_DOORS
-	/* disable the eject button while mounted */
-	cmd_buff[0] = SONY535_DISABLE_EJECT_BUTTON;
-	do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-#endif
-
-	return 0;
-}
-
-
-/*
- * Close the drive.  Spin it down if no task is using it.  The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static int
-cdu_release(struct inode *inode,
-			struct file *filp)
-{
-	Byte status[2], cmd_no;
-
-	sony_inuse = 0;
-
-	if (0 < sony_usage) {
-		sony_usage--;
-	}
-	if (sony_usage == 0) {
-		check_drive_status();
-
-		if (sony_audio_status != CDROM_AUDIO_PLAY) {
-			cmd_no = SONY535_SPIN_DOWN;
-			do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
-		}
-#ifdef LOCK_DOORS
-		/* enable the eject button after umount */
-		cmd_no = SONY535_ENABLE_EJECT_BUTTON;
-		do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
-#endif
-	}
-	return 0;
-}
-
-static struct block_device_operations cdu_fops =
-{
-	.owner		= THIS_MODULE,
-	.open		= cdu_open,
-	.release	= cdu_release,
-	.ioctl		= cdu_ioctl,
-	.media_changed	= cdu535_check_media_change,
-};
-
-static struct gendisk *cdu_disk;
-
-/*
- * Initialize the driver.
- */
-static int __init sony535_init(void)
-{
-	struct s535_sony_drive_config drive_config;
-	Byte cmd_buff[3];
-	Byte ret_buff[2];
-	Byte status[2];
-	unsigned long snap;
-	int  got_result = 0;
-	int  tmp_irq;
-	int  i;
-	int err;
-
-	/* Setting the base I/O address to 0 will disable it. */
-	if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0))
-		return 0;
-
-	/* Set up all the register locations */
-	result_reg = sony535_cd_base_io;
-	command_reg = sony535_cd_base_io;
-	data_reg = sony535_cd_base_io + 1;
-	read_status_reg = sony535_cd_base_io + 2;
-	select_unit_reg = sony535_cd_base_io + 3;
-
-#ifndef USE_IRQ
-	sony535_irq_used = 0;	/* polling only until this is ready... */
-#endif
-	/* we need to poll until things get initialized */
-	tmp_irq = sony535_irq_used;
-	sony535_irq_used = 0;
-
-#if DEBUG > 0
-	printk(KERN_INFO CDU535_MESSAGE_NAME ": probing base address %03X\n",
-			sony535_cd_base_io);
-#endif
-	/* look for the CD-ROM, follows the procedure in the DOS driver */
-	inb(select_unit_reg);
-	/* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */
-	schedule_timeout_interruptible((HZ+17)*40/18);
-	inb(result_reg);
-
-	outb(0, read_status_reg);	/* does a reset? */
-	snap = jiffies;
-	while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
-		select_unit(0);
-		if (inb(result_reg) != 0xff) {
-			got_result = 1;
-			break;
-		}
-		sony_sleep();
-	}
-
-	if (!got_result || check_drive_status() == TIME_OUT)
-		goto Enodev;
-
-	/* CD-ROM drive responded --  get the drive configuration */
-	cmd_buff[0] = SONY535_INQUIRY;
-	if (do_sony_cmd(cmd_buff, 1, status, (Byte *)&drive_config, 28, 1) != 0)
-		goto Enodev;
-
-	/* was able to get the configuration,
-	 * set drive mode as rest of init
-	 */
-#if DEBUG > 0
-	/* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
-	if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
-		printk(CDU535_MESSAGE_NAME
-				"Inquiry command returned status = 0x%x\n", status[0]);
-#endif
-	/* now ready to use interrupts, if available */
-	sony535_irq_used = tmp_irq;
-
-	/* A negative sony535_irq_used will attempt an autoirq. */
-	if (sony535_irq_used < 0) {
-		unsigned long irq_mask, delay;
-
-		irq_mask = probe_irq_on();
-		enable_interrupts();
-		outb(0, read_status_reg);	/* does a reset? */
-		delay = jiffies + HZ/10;
-		while (time_before(jiffies, delay)) ;
-
-		sony535_irq_used = probe_irq_off(irq_mask);
-		disable_interrupts();
-	}
-	if (sony535_irq_used > 0) {
-	    if (request_irq(sony535_irq_used, cdu535_interrupt,
-						IRQF_DISABLED, CDU535_HANDLE, NULL)) {
-			printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME
-					" driver; polling instead.\n", sony535_irq_used);
-			sony535_irq_used = 0;
-		}
-	}
-	cmd_buff[0] = SONY535_SET_DRIVE_MODE;
-	cmd_buff[1] = 0x0;	/* default audio */
-	if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) != 0)
-		goto Enodev_irq;
-
-	/* set the drive mode successful, we are set! */
-	sony_buffer_size = SONY535_BUFFER_SIZE;
-	sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
-
-	printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
-		   drive_config.vendor_id,
-		   drive_config.product_id,
-		   drive_config.product_rev_level);
-	printk("  base address %03X, ", sony535_cd_base_io);
-	if (tmp_irq > 0)
-		printk("IRQ%d, ", tmp_irq);
-	printk("using %d byte buffer\n", sony_buffer_size);
-
-	if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) {
-		err = -EIO;
-		goto out1;
-	}
-	sonycd535_queue = blk_init_queue(do_cdu535_request, &sonycd535_lock);
-	if (!sonycd535_queue) {
-		err = -ENOMEM;
-		goto out1a;
-	}
-
-	blk_queue_hardsect_size(sonycd535_queue, CDU535_BLOCK_SIZE);
-	sony_toc = kmalloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
-	err = -ENOMEM;
-	if (!sony_toc)
-		goto out2;
-	last_sony_subcode = kmalloc(sizeof(struct s535_sony_subcode), GFP_KERNEL);
-	if (!last_sony_subcode)
-		goto out3;
-	sony_buffer = kmalloc(sizeof(Byte *) * sony_buffer_sectors, GFP_KERNEL);
-	if (!sony_buffer)
-		goto out4;
-	for (i = 0; i < sony_buffer_sectors; i++) {
-		sony_buffer[i] = kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
-		if (!sony_buffer[i]) {
-			while (--i>=0)
-				kfree(sony_buffer[i]);
-			goto out5;
-		}
-	}
-	initialized = 1;
-
-	cdu_disk = alloc_disk(1);
-	if (!cdu_disk)
-		goto out6;
-	cdu_disk->major = MAJOR_NR;
-	cdu_disk->first_minor = 0;
-	cdu_disk->fops = &cdu_fops;
-	sprintf(cdu_disk->disk_name, "cdu");
-
-	if (!request_region(sony535_cd_base_io, 4, CDU535_HANDLE)) {
-		printk(KERN_WARNING"sonycd535: Unable to request region 0x%x\n",
-			sony535_cd_base_io);
-		goto out7;
-	}
-	cdu_disk->queue = sonycd535_queue;
-	add_disk(cdu_disk);
-	return 0;
-
-out7:
-	put_disk(cdu_disk);
-out6:
-	for (i = 0; i < sony_buffer_sectors; i++)
-		kfree(sony_buffer[i]);
-out5:
-	kfree(sony_buffer);
-out4:
-	kfree(last_sony_subcode);
-out3:
-	kfree(sony_toc);
-out2:
-	blk_cleanup_queue(sonycd535_queue);
-out1a:
-	unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
-out1:
-	if (sony535_irq_used)
-		free_irq(sony535_irq_used, NULL);
-	return err;
-Enodev_irq:
-	if (sony535_irq_used)
-		free_irq(sony535_irq_used, NULL);
-Enodev:
-	printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
-	return -EIO;
-}
-
-#ifndef MODULE
-
-/*
- * accept "kernel command line" parameters
- * (added by emoenke@gwdg.de)
- *
- * use: tell LILO:
- *                 sonycd535=0x320
- *
- * the address value has to be the existing CDROM port address.
- */
-static int __init
-sonycd535_setup(char *strings)
-{
-	int ints[3];
-	(void)get_options(strings, ARRAY_SIZE(ints), ints);
-	/* if IRQ change and default io base desired,
-	 * then call with io base of 0
-	 */
-	if (ints[0] > 0)
-		if (ints[1] != 0)
-			sony535_cd_base_io = ints[1];
-	if (ints[0] > 1)
-		sony535_irq_used = ints[2];
-	if ((strings != NULL) && (*strings != '\0'))
-		printk(CDU535_MESSAGE_NAME
-				": Warning: Unknown interface type: %s\n", strings);
-				
-	return 1;
-}
-
-__setup("sonycd535=", sonycd535_setup);
-
-#endif /* MODULE */
-
-static void __exit
-sony535_exit(void)
-{
-	int i;
-
-	release_region(sony535_cd_base_io, 4);
-	for (i = 0; i < sony_buffer_sectors; i++)
-		kfree(sony_buffer[i]);
-	kfree(sony_buffer);
-	kfree(last_sony_subcode);
-	kfree(sony_toc);
-	del_gendisk(cdu_disk);
-	put_disk(cdu_disk);
-	blk_cleanup_queue(sonycd535_queue);
-	if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
-		printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
-	else
-		printk(KERN_INFO CDU535_HANDLE " module released\n");
-}
-
-module_init(sony535_init);
-module_exit(sony535_exit);
-
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU535_CDROM_MAJOR);
diff --git a/drivers/cdrom/sonycd535.h b/drivers/cdrom/sonycd535.h
deleted file mode 100644
index 5dea1ef..0000000
--- a/drivers/cdrom/sonycd535.h
+++ /dev/null
@@ -1,183 +0,0 @@
-#ifndef SONYCD535_H
-#define SONYCD535_H
-
-/*
- * define all the commands recognized by the CDU-531/5
- */
-#define SONY535_REQUEST_DRIVE_STATUS_1		(0x80)
-#define SONY535_REQUEST_SENSE			(0x82)
-#define SONY535_REQUEST_DRIVE_STATUS_2		(0x84)
-#define SONY535_REQUEST_ERROR_STATUS		(0x86)
-#define SONY535_REQUEST_AUDIO_STATUS		(0x88)
-#define SONY535_INQUIRY				(0x8a)
-
-#define SONY535_SET_INACTIVITY_TIME		(0x90)
-
-#define SONY535_SEEK_AND_READ_N_BLOCKS_1	(0xa0)
-#define SONY535_SEEK_AND_READ_N_BLOCKS_2	(0xa4)
-#define SONY535_PLAY_AUDIO			(0xa6)
-
-#define SONY535_REQUEST_DISC_CAPACITY		(0xb0)
-#define SONY535_REQUEST_TOC_DATA		(0xb2)
-#define SONY535_REQUEST_SUB_Q_DATA		(0xb4)
-#define SONY535_REQUEST_ISRC			(0xb6)
-#define SONY535_REQUEST_UPC_EAN			(0xb8)
-
-#define SONY535_SET_DRIVE_MODE			(0xc0)
-#define SONY535_REQUEST_DRIVE_MODE		(0xc2)
-#define SONY535_SET_RETRY_COUNT			(0xc4)
-
-#define SONY535_DIAGNOSTIC_1			(0xc6)
-#define SONY535_DIAGNOSTIC_4			(0xcc)
-#define SONY535_DIAGNOSTIC_5			(0xce)
-
-#define SONY535_EJECT_CADDY			(0xd0)
-#define SONY535_DISABLE_EJECT_BUTTON		(0xd2)
-#define SONY535_ENABLE_EJECT_BUTTON		(0xd4)
-
-#define SONY535_HOLD				(0xe0)
-#define SONY535_AUDIO_PAUSE_ON_OFF		(0xe2)
-#define SONY535_SET_VOLUME			(0xe8)
-
-#define SONY535_STOP				(0xf0)
-#define SONY535_SPIN_UP				(0xf2)
-#define SONY535_SPIN_DOWN			(0xf4)
-
-#define SONY535_CLEAR_PARAMETERS		(0xf6)
-#define SONY535_CLEAR_ENDING_ADDRESS		(0xf8)
-
-/*
- * define some masks
- */
-#define SONY535_DATA_NOT_READY_BIT		(0x1)
-#define SONY535_RESULT_NOT_READY_BIT		(0x2)
-
-/*
- *  drive status 1
- */
-#define SONY535_STATUS1_COMMAND_ERROR		(0x1)
-#define SONY535_STATUS1_DATA_ERROR		(0x2)
-#define SONY535_STATUS1_SEEK_ERROR		(0x4)
-#define SONY535_STATUS1_DISC_TYPE_ERROR		(0x8)
-#define SONY535_STATUS1_NOT_SPINNING		(0x10)
-#define SONY535_STATUS1_EJECT_BUTTON_PRESSED	(0x20)
-#define SONY535_STATUS1_CADDY_NOT_INSERTED	(0x40)
-#define SONY535_STATUS1_BYTE_TWO_FOLLOWS	(0x80)
-
-/*
- * drive status 2
- */
-#define SONY535_CDD_LOADING_ERROR		(0x7)
-#define SONY535_CDD_NO_DISC			(0x8)
-#define SONY535_CDD_UNLOADING_ERROR		(0x9)
-#define SONY535_CDD_CADDY_NOT_INSERTED		(0xd)
-#define SONY535_ATN_RESET_OCCURRED		(0x2)
-#define SONY535_ATN_DISC_CHANGED		(0x4)
-#define SONY535_ATN_RESET_AND_DISC_CHANGED	(0x6)
-#define SONY535_ATN_EJECT_IN_PROGRESS		(0xe)
-#define SONY535_ATN_BUSY			(0xf)
-
-/*
- * define some parameters
- */
-#define SONY535_AUDIO_DRIVE_MODE		(0)
-#define SONY535_CDROM_DRIVE_MODE		(0xe0)
-
-#define SONY535_PLAY_OP_PLAYBACK		(0)
-#define SONY535_PLAY_OP_ENTER_HOLD		(1)
-#define SONY535_PLAY_OP_SET_AUDIO_ENDING_ADDR	(2)
-#define SONY535_PLAY_OP_SCAN_FORWARD		(3)
-#define SONY535_PLAY_OP_SCAN_BACKWARD		(4)
-
-/*
- *  convert from msf format to block number 
- */
-#define SONY_BLOCK_NUMBER(m,s,f) (((m)*60L+(s))*75L+(f))
-#define SONY_BLOCK_NUMBER_MSF(x) (((x)[0]*60L+(x)[1])*75L+(x)[2])
-
-/*
- *  error return values from the doSonyCmd() routines
- */
-#define TIME_OUT			(-1)
-#define NO_CDROM			(-2)
-#define BAD_STATUS			(-3)
-#define CD_BUSY				(-4)
-#define NOT_DATA_CD			(-5)
-#define NO_ROOM				(-6)
-
-#define LOG_START_OFFSET        150     /* Offset of first logical sector */
-
-#define SONY_JIFFIES_TIMEOUT	(5*HZ)	/* Maximum time
-					   the drive will wait/try for an
-					   operation */
-#define SONY_READY_RETRIES      (50000)  /* How many times to retry a
-                                                  spin waiting for a register
-                                                  to come ready */
-#define SONY535_FAST_POLLS	(10000)   /* how many times recheck 
-                                                  status waiting for a data
-                                                  to become ready */
-
-typedef unsigned char Byte;
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s535_sony_drive_config
-{
-   char vendor_id[8];
-   char product_id[16];
-   char product_rev_level[4];
-};
-
-/* The following is returned from the request sub-q data command */
-struct s535_sony_subcode
-{
-   unsigned char address        :4;
-   unsigned char control        :4;
-   unsigned char track_num;
-   unsigned char index_num;
-   unsigned char rel_msf[3];
-   unsigned char abs_msf[3];
-};
-
-struct s535_sony_disc_capacity
-{
-   Byte mFirstTrack, sFirstTrack, fFirstTrack;
-   Byte mLeadOut, sLeadOut, fLeadOut;
-};
-
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s535_sony_toc
-{
-   unsigned char reserved0      :4;
-   unsigned char control0       :4;
-   unsigned char point0;
-   unsigned char first_track_num;
-   unsigned char reserved0a;
-   unsigned char reserved0b;
-   unsigned char reserved1      :4;
-   unsigned char control1       :4;
-   unsigned char point1;
-   unsigned char last_track_num;
-   unsigned char dummy1;
-   unsigned char dummy2;
-   unsigned char reserved2      :4;
-   unsigned char control2       :4;
-   unsigned char point2;
-   unsigned char lead_out_start_msf[3];
-   struct
-   {
-      unsigned char reserved    :4;
-      unsigned char control     :4;
-      unsigned char track;
-      unsigned char track_start_msf[3];
-   } tracks[100];
-
-   unsigned int lead_out_start_lba;
-};
-
-#endif /* SONYCD535_H */
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 1b09450..90965b4 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -1005,8 +1005,8 @@
 	284,285,309,  0,312, 91,327,328,329,331,333,335,336,337,338,339,
 	367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
 	360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
-	103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
-	291,108,381,281,290,272,292,305,280, 99,112,257,258,359,113,114,
+	103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
+	291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
 	264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
 	377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
 	308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index cc9a9d0..bbee97f 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -24,7 +24,7 @@
 #include <linux/crash_dump.h>
 #include <linux/backing-dev.h>
 #include <linux/bootmem.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
 #include <linux/pfn.h>
 
 #include <asm/uaccess.h>
@@ -75,6 +75,13 @@
 	 * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
 	 */
 	return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
+#elif defined(CONFIG_MIPS)
+	{
+		extern int __uncached_access(struct file *file,
+					     unsigned long addr);
+
+		return __uncached_access(file, addr);
+	}
 #else
 	/*
 	 * Accessing memory above the top the kernel knows about or through a file pointer
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 1da92a6..85a2328 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -2721,9 +2721,9 @@
    its because the standard requires it. So check for SUBVENDOR_ID. */
 static struct pci_device_id sx_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
-		.subvendor = 0x0200,.subdevice = PCI_ANY_ID },
+		.subvendor = PCI_ANY_ID, .subdevice = 0x0200 },
 	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
-		.subvendor = 0x0300,.subdevice = PCI_ANY_ID },
+		.subvendor = PCI_ANY_ID, .subdevice = 0x0300 },
 	{ 0 }
 };
 
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 9eb1eda..0aeab32 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -336,8 +336,11 @@
 	}
 
  pick_me:
-	/* Now figure out what gap count to set. */
-	if (card->topology_type == FW_TOPOLOGY_A &&
+	/*
+	 * Pick a gap count from 1394a table E-1.  The table doesn't cover
+	 * the typically much larger 1394b beta repeater delays though.
+	 */
+	if (!card->beta_repeaters_present &&
 	    card->root_node->max_hops < ARRAY_SIZE(gap_count_table))
 		gap_count = gap_count_table[card->root_node->max_hops];
 	else
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index dbb7642..7538864 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -397,7 +397,7 @@
 			request->tcode & 0x1f,
 			device->node->node_id,
 			request->generation,
-			device->node->max_speed,
+			device->max_speed,
 			request->offset,
 			response->response.data, request->length,
 			complete_transaction, response);
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index c1ce465..2b65863 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -401,8 +401,7 @@
 
 	offset = 0xfffff0000400ULL + index * 4;
 	fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
-			device->node_id,
-			device->generation, SCODE_100,
+			device->node_id, device->generation, device->max_speed,
 			offset, NULL, 4, complete_transaction, &callback_data);
 
 	wait_for_completion(&callback_data.done);
@@ -418,6 +417,8 @@
 	u32 stack[16], sp, key;
 	int i, end, length;
 
+	device->max_speed = SCODE_100;
+
 	/* First read the bus info block. */
 	for (i = 0; i < 5; i++) {
 		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
@@ -434,6 +435,33 @@
 			return -1;
 	}
 
+	device->max_speed = device->node->max_speed;
+
+	/*
+	 * Determine the speed of
+	 *   - devices with link speed less than PHY speed,
+	 *   - devices with 1394b PHY (unless only connected to 1394a PHYs),
+	 *   - all devices if there are 1394b repeaters.
+	 * Note, we cannot use the bus info block's link_spd as starting point
+	 * because some buggy firmwares set it lower than necessary and because
+	 * 1394-1995 nodes do not have the field.
+	 */
+	if ((rom[2] & 0x7) < device->max_speed ||
+	    device->max_speed == SCODE_BETA ||
+	    device->card->beta_repeaters_present) {
+		u32 dummy;
+
+		/* for S1600 and S3200 */
+		if (device->max_speed == SCODE_BETA)
+			device->max_speed = device->card->link_speed;
+
+		while (device->max_speed > SCODE_100) {
+			if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
+				break;
+			device->max_speed--;
+		}
+	}
+
 	/*
 	 * Now parse the config rom.  The config rom is a recursive
 	 * directory structure so we parse it using a stack of
@@ -680,8 +708,10 @@
 		    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
 		fw_device_shutdown(&device->work.work);
 	else
-		fw_notify("created new fw device %s (%d config rom retries)\n",
-			  device->device.bus_id, device->config_rom_retries);
+		fw_notify("created new fw device %s "
+			  "(%d config rom retries, S%d00)\n",
+			  device->device.bus_id, device->config_rom_retries,
+			  1 << device->max_speed);
 
 	/*
 	 * Reschedule the IRM work if we just finished reading the
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
index af1723e..d13e6a6 100644
--- a/drivers/firewire/fw-device.h
+++ b/drivers/firewire/fw-device.h
@@ -40,6 +40,7 @@
 	struct fw_node *node;
 	int node_id;
 	int generation;
+	unsigned max_speed;
 	struct fw_card *card;
 	struct device device;
 	struct list_head link;
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 96c8ac5..41476ab 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -1934,12 +1934,12 @@
 	free_irq(pdev->irq, ohci);
 	err = pci_save_state(pdev);
 	if (err) {
-		fw_error("pci_save_state failed with %d", err);
+		fw_error("pci_save_state failed\n");
 		return err;
 	}
 	err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
 	if (err) {
-		fw_error("pci_set_power_state failed with %d", err);
+		fw_error("pci_set_power_state failed\n");
 		return err;
 	}
 
@@ -1955,7 +1955,7 @@
 	pci_restore_state(pdev);
 	err = pci_enable_device(pdev);
 	if (err) {
-		fw_error("pci_enable_device failed with %d", err);
+		fw_error("pci_enable_device failed\n");
 		return err;
 	}
 
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index a98d391..7c53be0 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -30,10 +30,13 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/mod_devicetable.h>
 #include <linux/device.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
+#include <linux/blkdev.h>
+#include <linux/string.h>
 #include <linux/timer.h>
 
 #include <scsi/scsi.h>
@@ -46,6 +49,18 @@
 #include "fw-topology.h"
 #include "fw-device.h"
 
+/*
+ * So far only bridges from Oxford Semiconductor are known to support
+ * concurrent logins. Depending on firmware, four or two concurrent logins
+ * are possible on OXFW911 and newer Oxsemi bridges.
+ *
+ * Concurrent logins are useful together with cluster filesystems.
+ */
+static int sbp2_param_exclusive_login = 1;
+module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
+MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
+		 "(default = Y, use N for concurrent initiators)");
+
 /* I don't know why the SCSI stack doesn't define something like this... */
 typedef void (*scsi_done_fn_t)(struct scsi_cmnd *);
 
@@ -154,7 +169,7 @@
 #define MANAGEMENT_ORB_LUN(v)			((v))
 #define MANAGEMENT_ORB_FUNCTION(v)		((v) << 16)
 #define MANAGEMENT_ORB_RECONNECT(v)		((v) << 20)
-#define MANAGEMENT_ORB_EXCLUSIVE		((1) << 28)
+#define MANAGEMENT_ORB_EXCLUSIVE(v)		((v) ? 1 << 28 : 0)
 #define MANAGEMENT_ORB_REQUEST_FORMAT(v)	((v) << 29)
 #define MANAGEMENT_ORB_NOTIFY			((1) << 31)
 
@@ -205,9 +220,8 @@
 	scsi_done_fn_t done;
 	struct fw_unit *unit;
 
-	struct sbp2_pointer page_table[SG_ALL];
+	struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
 	dma_addr_t page_table_bus;
-	dma_addr_t request_buffer_bus;
 };
 
 /*
@@ -347,8 +361,7 @@
 	spin_unlock_irqrestore(&device->card->lock, flags);
 
 	fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
-			node_id, generation,
-			device->node->max_speed, offset,
+			node_id, generation, device->max_speed, offset,
 			&orb->pointer, sizeof(orb->pointer),
 			complete_transaction, orb);
 }
@@ -383,7 +396,7 @@
 complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
 {
 	struct sbp2_management_orb *orb =
-	    (struct sbp2_management_orb *)base_orb;
+		container_of(base_orb, struct sbp2_management_orb, base);
 
 	if (status)
 		memcpy(&orb->status, status, sizeof(*status));
@@ -403,21 +416,11 @@
 	if (orb == NULL)
 		return -ENOMEM;
 
-	/*
-	 * The sbp2 device is going to send a block read request to
-	 * read out the request from host memory, so map it for dma.
-	 */
-	orb->base.request_bus =
-		dma_map_single(device->card->device, &orb->request,
-			       sizeof(orb->request), DMA_TO_DEVICE);
-	if (dma_mapping_error(orb->base.request_bus))
-		goto out;
-
 	orb->response_bus =
 		dma_map_single(device->card->device, &orb->response,
 			       sizeof(orb->response), DMA_FROM_DEVICE);
 	if (dma_mapping_error(orb->response_bus))
-		goto out;
+		goto fail_mapping_response;
 
 	orb->request.response.high    = 0;
 	orb->request.response.low     = orb->response_bus;
@@ -432,14 +435,9 @@
 	orb->request.status_fifo.high = sd->address_handler.offset >> 32;
 	orb->request.status_fifo.low  = sd->address_handler.offset;
 
-	/*
-	 * FIXME: Yeah, ok this isn't elegant, we hardwire exclusive
-	 * login and 1 second reconnect time.  The reconnect setting
-	 * is probably fine, but the exclusive login should be an option.
-	 */
 	if (function == SBP2_LOGIN_REQUEST) {
 		orb->request.misc |=
-			MANAGEMENT_ORB_EXCLUSIVE |
+			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) |
 			MANAGEMENT_ORB_RECONNECT(0);
 	}
 
@@ -448,6 +446,12 @@
 	init_completion(&orb->done);
 	orb->base.callback = complete_management_orb;
 
+	orb->base.request_bus =
+		dma_map_single(device->card->device, &orb->request,
+			       sizeof(orb->request), DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->base.request_bus))
+		goto fail_mapping_request;
+
 	sbp2_send_orb(&orb->base, unit,
 		      node_id, generation, sd->management_agent_address);
 
@@ -479,9 +483,10 @@
  out:
 	dma_unmap_single(device->card->device, orb->base.request_bus,
 			 sizeof(orb->request), DMA_TO_DEVICE);
+ fail_mapping_request:
 	dma_unmap_single(device->card->device, orb->response_bus,
 			 sizeof(orb->response), DMA_FROM_DEVICE);
-
+ fail_mapping_response:
 	if (response)
 		fw_memcpy_from_be32(response,
 				    orb->response, sizeof(orb->response));
@@ -511,7 +516,7 @@
 		return -ENOMEM;
 
 	fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
-			sd->node_id, sd->generation, SCODE_400,
+			sd->node_id, sd->generation, device->max_speed,
 			sd->command_block_agent_address + SBP2_AGENT_RESET,
 			&zero, sizeof(zero), complete_agent_reset_write, t);
 
@@ -521,17 +526,15 @@
 static void sbp2_reconnect(struct work_struct *work);
 static struct scsi_host_template scsi_driver_template;
 
-static void
-release_sbp2_device(struct kref *kref)
+static void release_sbp2_device(struct kref *kref)
 {
 	struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref);
 	struct Scsi_Host *host =
 		container_of((void *)sd, struct Scsi_Host, hostdata[0]);
 
+	scsi_remove_host(host);
 	sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation,
 				 SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
-
-	scsi_remove_host(host);
 	fw_core_remove_address_handler(&sd->address_handler);
 	fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id);
 	put_device(&sd->unit->device);
@@ -833,7 +836,8 @@
 static void
 complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
 {
-	struct sbp2_command_orb *orb = (struct sbp2_command_orb *)base_orb;
+	struct sbp2_command_orb *orb =
+		container_of(base_orb, struct sbp2_command_orb, base);
 	struct fw_unit *unit = orb->unit;
 	struct fw_device *device = fw_device(unit->device.parent);
 	struct scatterlist *sg;
@@ -880,12 +884,7 @@
 
 	if (orb->page_table_bus != 0)
 		dma_unmap_single(device->card->device, orb->page_table_bus,
-				 sizeof(orb->page_table_bus), DMA_TO_DEVICE);
-
-	if (orb->request_buffer_bus != 0)
-		dma_unmap_single(device->card->device, orb->request_buffer_bus,
-				 sizeof(orb->request_buffer_bus),
-				 DMA_FROM_DEVICE);
+				 sizeof(orb->page_table), DMA_TO_DEVICE);
 
 	orb->cmd->result = result;
 	orb->done(orb->cmd);
@@ -900,7 +899,6 @@
 	struct fw_device *device = fw_device(unit->device.parent);
 	struct scatterlist *sg;
 	int sg_len, l, i, j, count;
-	size_t size;
 	dma_addr_t sg_addr;
 
 	sg = (struct scatterlist *)orb->cmd->request_buffer;
@@ -935,6 +933,11 @@
 		sg_len = sg_dma_len(sg + i);
 		sg_addr = sg_dma_address(sg + i);
 		while (sg_len) {
+			/* FIXME: This won't get us out of the pinch. */
+			if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
+				fw_error("page table overflow\n");
+				goto fail_page_table;
+			}
 			l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
 			orb->page_table[j].low = sg_addr;
 			orb->page_table[j].high = (l << 16);
@@ -944,7 +947,13 @@
 		}
 	}
 
-	size = sizeof(orb->page_table[0]) * j;
+	fw_memcpy_to_be32(orb->page_table, orb->page_table,
+			  sizeof(orb->page_table[0]) * j);
+	orb->page_table_bus =
+		dma_map_single(device->card->device, orb->page_table,
+			       sizeof(orb->page_table), DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->page_table_bus))
+		goto fail_page_table;
 
 	/*
 	 * The data_descriptor pointer is the one case where we need
@@ -953,20 +962,12 @@
 	 * initiator (i.e. us), but data_descriptor can refer to data
 	 * on other nodes so we need to put our ID in descriptor.high.
 	 */
-
-	orb->page_table_bus =
-		dma_map_single(device->card->device, orb->page_table,
-			       size, DMA_TO_DEVICE);
-	if (dma_mapping_error(orb->page_table_bus))
-		goto fail_page_table;
 	orb->request.data_descriptor.high = sd->address_high;
 	orb->request.data_descriptor.low  = orb->page_table_bus;
 	orb->request.misc |=
 		COMMAND_ORB_PAGE_TABLE_PRESENT |
 		COMMAND_ORB_DATA_SIZE(j);
 
-	fw_memcpy_to_be32(orb->page_table, orb->page_table, size);
-
 	return 0;
 
  fail_page_table:
@@ -991,7 +992,7 @@
 	 * transfer direction not handled.
 	 */
 	if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
-		fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+		fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
 		cmd->result = DID_ERROR << 16;
 		done(cmd);
 		return 0;
@@ -1005,11 +1006,6 @@
 
 	/* Initialize rcode to something not RCODE_COMPLETE. */
 	orb->base.rcode = -1;
-	orb->base.request_bus =
-		dma_map_single(device->card->device, &orb->request,
-			       sizeof(orb->request), DMA_TO_DEVICE);
-	if (dma_mapping_error(orb->base.request_bus))
-		goto fail_mapping;
 
 	orb->unit = unit;
 	orb->done = done;
@@ -1024,8 +1020,8 @@
 	 * if we set this to max_speed + 7, we get the right value.
 	 */
 	orb->request.misc =
-		COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) |
-		COMMAND_ORB_SPEED(device->node->max_speed) |
+		COMMAND_ORB_MAX_PAYLOAD(device->max_speed + 7) |
+		COMMAND_ORB_SPEED(device->max_speed) |
 		COMMAND_ORB_NOTIFY;
 
 	if (cmd->sc_data_direction == DMA_FROM_DEVICE)
@@ -1036,7 +1032,7 @@
 			COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
 
 	if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0)
-		goto fail_map_payload;
+		goto fail_mapping;
 
 	fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
 
@@ -1045,15 +1041,17 @@
 	memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
 
 	orb->base.callback = complete_command_orb;
+	orb->base.request_bus =
+		dma_map_single(device->card->device, &orb->request,
+			       sizeof(orb->request), DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->base.request_bus))
+		goto fail_mapping;
 
 	sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation,
 		      sd->command_block_agent_address + SBP2_ORB_POINTER);
 
 	return 0;
 
- fail_map_payload:
-	dma_unmap_single(device->card->device, orb->base.request_bus,
-			 sizeof(orb->request), DMA_TO_DEVICE);
  fail_mapping:
 	kfree(orb);
  fail_alloc:
@@ -1087,7 +1085,8 @@
 		fw_notify("setting fix_capacity for %s\n", unit->device.bus_id);
 		sdev->fix_capacity = 1;
 	}
-
+	if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
+		blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
 	return 0;
 }
 
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index 7aebb8a..39e5cd1 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -135,17 +135,17 @@
 	int i;
 
 	for (i = 0; i < node->port_count; i++) {
-		if (node->ports[i].node == NULL)
+		if (node->ports[i] == NULL)
 			continue;
 
-		if (node->ports[i].node->max_hops > max_child_hops)
-			max_child_hops = node->ports[i].node->max_hops;
+		if (node->ports[i]->max_hops > max_child_hops)
+			max_child_hops = node->ports[i]->max_hops;
 
-		if (node->ports[i].node->max_depth > depths[0]) {
+		if (node->ports[i]->max_depth > depths[0]) {
 			depths[1] = depths[0];
-			depths[0] = node->ports[i].node->max_depth;
-		} else if (node->ports[i].node->max_depth > depths[1])
-			depths[1] = node->ports[i].node->max_depth;
+			depths[0] = node->ports[i]->max_depth;
+		} else if (node->ports[i]->max_depth > depths[1])
+			depths[1] = node->ports[i]->max_depth;
 	}
 
 	node->max_depth = depths[0] + 1;
@@ -172,7 +172,8 @@
 	struct list_head stack, *h;
 	u32 *next_sid, *end, q;
 	int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
-	int gap_count, topology_type;
+	int gap_count;
+	bool beta_repeaters_present;
 
 	local_node = NULL;
 	node = NULL;
@@ -182,7 +183,7 @@
 	phy_id = 0;
 	irm_node = NULL;
 	gap_count = SELF_ID_GAP_COUNT(*sid);
-	topology_type = 0;
+	beta_repeaters_present = false;
 
 	while (sid < end) {
 		next_sid = count_ports(sid, &port_count, &child_port_count);
@@ -214,7 +215,7 @@
 
 		node = fw_node_create(q, port_count, card->color);
 		if (node == NULL) {
-			fw_error("Out of memory while building topology.");
+			fw_error("Out of memory while building topology.\n");
 			return NULL;
 		}
 
@@ -224,11 +225,6 @@
 		if (SELF_ID_CONTENDER(q))
 			irm_node = node;
 
-		if (node->phy_speed == SCODE_BETA)
-			topology_type |= FW_TOPOLOGY_B;
-		else
-			topology_type |= FW_TOPOLOGY_A;
-
 		parent_count = 0;
 
 		for (i = 0; i < port_count; i++) {
@@ -249,12 +245,12 @@
 				break;
 
 			case SELFID_PORT_CHILD:
-				node->ports[i].node = child;
+				node->ports[i] = child;
 				/*
 				 * Fix up parent reference for this
 				 * child node.
 				 */
-				child->ports[child->color].node = node;
+				child->ports[child->color] = node;
 				child->color = card->color;
 				child = fw_node(child->link.next);
 				break;
@@ -278,6 +274,10 @@
 		list_add_tail(&node->link, &stack);
 		stack_depth += 1 - child_port_count;
 
+		if (node->phy_speed == SCODE_BETA &&
+		    parent_count + child_port_count > 1)
+			beta_repeaters_present = true;
+
 		/*
 		 * If all PHYs does not report the same gap count
 		 * setting, we fall back to 63 which will force a gap
@@ -295,7 +295,7 @@
 	card->root_node = node;
 	card->irm_node = irm_node;
 	card->gap_count = gap_count;
-	card->topology_type = topology_type;
+	card->beta_repeaters_present = beta_repeaters_present;
 
 	return local_node;
 }
@@ -321,7 +321,7 @@
 		node->color = card->color;
 
 		for (i = 0; i < node->port_count; i++) {
-			child = node->ports[i].node;
+			child = node->ports[i];
 			if (!child)
 				continue;
 			if (child->color == card->color)
@@ -382,11 +382,11 @@
 	struct fw_node *tree;
 	int i;
 
-	tree = node1->ports[port].node;
-	node0->ports[port].node = tree;
+	tree = node1->ports[port];
+	node0->ports[port] = tree;
 	for (i = 0; i < tree->port_count; i++) {
-		if (tree->ports[i].node == node1) {
-			tree->ports[i].node = node0;
+		if (tree->ports[i] == node1) {
+			tree->ports[i] = node0;
 			break;
 		}
 	}
@@ -437,19 +437,17 @@
 			card->irm_node = node0;
 
 		for (i = 0; i < node0->port_count; i++) {
-			if (node0->ports[i].node && node1->ports[i].node) {
+			if (node0->ports[i] && node1->ports[i]) {
 				/*
 				 * This port didn't change, queue the
 				 * connected node for further
 				 * investigation.
 				 */
-				if (node0->ports[i].node->color == card->color)
+				if (node0->ports[i]->color == card->color)
 					continue;
-				list_add_tail(&node0->ports[i].node->link,
-					      &list0);
-				list_add_tail(&node1->ports[i].node->link,
-					      &list1);
-			} else if (node0->ports[i].node) {
+				list_add_tail(&node0->ports[i]->link, &list0);
+				list_add_tail(&node1->ports[i]->link, &list1);
+			} else if (node0->ports[i]) {
 				/*
 				 * The nodes connected here were
 				 * unplugged; unref the lost nodes and
@@ -457,10 +455,10 @@
 				 * them.
 				 */
 
-				for_each_fw_node(card, node0->ports[i].node,
+				for_each_fw_node(card, node0->ports[i],
 						 report_lost_node);
-				node0->ports[i].node = NULL;
-			} else if (node1->ports[i].node) {
+				node0->ports[i] = NULL;
+			} else if (node1->ports[i]) {
 				/*
 				 * One or more node were connected to
 				 * this port. Move the new nodes into
@@ -468,7 +466,7 @@
 				 * callbacks for them.
 				 */
 				move_tree(node0, node1, i);
-				for_each_fw_node(card, node0->ports[i].node,
+				for_each_fw_node(card, node0->ports[i],
 						 report_found_node);
 			}
 		}
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
index 363b6cb..1b56b4a 100644
--- a/drivers/firewire/fw-topology.h
+++ b/drivers/firewire/fw-topology.h
@@ -20,12 +20,6 @@
 #define __fw_topology_h
 
 enum {
-	FW_TOPOLOGY_A =		0x01,
-	FW_TOPOLOGY_B =		0x02,
-	FW_TOPOLOGY_MIXED =	0x03,
-};
-
-enum {
 	FW_NODE_CREATED =   0x00,
 	FW_NODE_UPDATED =   0x01,
 	FW_NODE_DESTROYED = 0x02,
@@ -33,21 +27,16 @@
 	FW_NODE_LINK_OFF =  0x04,
 };
 
-struct fw_port {
-	struct fw_node *node;
-	unsigned speed : 3; /* S100, S200, ... S3200 */
-};
-
 struct fw_node {
 	u16 node_id;
 	u8 color;
 	u8 port_count;
-	unsigned link_on : 1;
-	unsigned initiated_reset : 1;
-	unsigned b_path : 1;
-	u8 phy_speed : 3; /* As in the self ID packet. */
-	u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on
-			   * the path from the local node to this node. */
+	u8 link_on : 1;
+	u8 initiated_reset : 1;
+	u8 b_path : 1;
+	u8 phy_speed : 2; /* As in the self ID packet. */
+	u8 max_speed : 2; /* Minimum of all phy-speeds on the path from the
+			   * local node to this node. */
 	u8 max_depth : 4; /* Maximum depth to any leaf node */
 	u8 max_hops : 4;  /* Max hops in this sub tree */
 	atomic_t ref_count;
@@ -58,7 +47,7 @@
 	/* Upper layer specific data. */
 	void *data;
 
-	struct fw_port ports[0];
+	struct fw_node *ports[0];
 };
 
 static inline struct fw_node *
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index acdc3be..5abed19 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -81,7 +81,6 @@
 
 #define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
 #define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
-#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args)
 
 static inline void
 fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
@@ -246,7 +245,7 @@
 	struct fw_node *irm_node;
 	int color;
 	int gap_count;
-	int topology_type;
+	bool beta_repeaters_present;
 
 	int index;
 
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 8fbe9fd..3b63b0b 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1,8 +1,12 @@
 #
 # HID driver configuration
 #
-menu "HID Devices"
+menuconfig HID_SUPPORT
+	bool "HID Devices"
 	depends on INPUT
+	default y
+
+if HID_SUPPORT
 
 config HID
 	tristate "Generic HID support"
@@ -24,6 +28,7 @@
 
 config HID_DEBUG
 	bool "HID debugging support"
+	default y if !EMBEDDED
 	depends on HID
 	---help---
 	This option lets the HID layer output diagnostics about its internal
@@ -38,5 +43,4 @@
 
 source "drivers/hid/usbhid/Kconfig"
 
-endmenu
-
+endif # HID_SUPPORT
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 6ec04e7..317cf8a 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -40,6 +40,13 @@
 #define DRIVER_DESC "HID core driver"
 #define DRIVER_LICENSE "GPL"
 
+#ifdef CONFIG_HID_DEBUG
+int hid_debug = 0;
+module_param_named(debug, hid_debug, bool, 0600);
+MODULE_PARM_DESC(debug, "Turn HID debugging mode on and off");
+EXPORT_SYMBOL_GPL(hid_debug);
+#endif
+
 /*
  * Register a new report for a device.
  */
@@ -78,7 +85,7 @@
 	struct hid_field *field;
 
 	if (report->maxfield == HID_MAX_FIELDS) {
-		dbg("too many fields in report");
+		dbg_hid("too many fields in report\n");
 		return NULL;
 	}
 
@@ -106,7 +113,7 @@
 	usage = parser->local.usage[0];
 
 	if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
-		dbg("collection stack overflow");
+		dbg_hid("collection stack overflow\n");
 		return -1;
 	}
 
@@ -114,7 +121,7 @@
 		collection = kmalloc(sizeof(struct hid_collection) *
 				parser->device->collection_size * 2, GFP_KERNEL);
 		if (collection == NULL) {
-			dbg("failed to reallocate collection array");
+			dbg_hid("failed to reallocate collection array\n");
 			return -1;
 		}
 		memcpy(collection, parser->device->collection,
@@ -150,7 +157,7 @@
 static int close_collection(struct hid_parser *parser)
 {
 	if (!parser->collection_stack_ptr) {
-		dbg("collection stack underflow");
+		dbg_hid("collection stack underflow\n");
 		return -1;
 	}
 	parser->collection_stack_ptr--;
@@ -178,7 +185,7 @@
 static int hid_add_usage(struct hid_parser *parser, unsigned usage)
 {
 	if (parser->local.usage_index >= HID_MAX_USAGES) {
-		dbg("usage index exceeded");
+		dbg_hid("usage index exceeded\n");
 		return -1;
 	}
 	parser->local.usage[parser->local.usage_index] = usage;
@@ -202,12 +209,12 @@
 	int i;
 
 	if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
-		dbg("hid_register_report failed");
+		dbg_hid("hid_register_report failed\n");
 		return -1;
 	}
 
 	if (parser->global.logical_maximum < parser->global.logical_minimum) {
-		dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
+		dbg_hid("logical range invalid %d %d\n", parser->global.logical_minimum, parser->global.logical_maximum);
 		return -1;
 	}
 
@@ -287,7 +294,7 @@
 		case HID_GLOBAL_ITEM_TAG_PUSH:
 
 			if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
-				dbg("global enviroment stack overflow");
+				dbg_hid("global enviroment stack overflow\n");
 				return -1;
 			}
 
@@ -298,7 +305,7 @@
 		case HID_GLOBAL_ITEM_TAG_POP:
 
 			if (!parser->global_stack_ptr) {
-				dbg("global enviroment stack underflow");
+				dbg_hid("global enviroment stack underflow\n");
 				return -1;
 			}
 
@@ -342,27 +349,27 @@
 
 		case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
 			if ((parser->global.report_size = item_udata(item)) > 32) {
-				dbg("invalid report_size %d", parser->global.report_size);
+				dbg_hid("invalid report_size %d\n", parser->global.report_size);
 				return -1;
 			}
 			return 0;
 
 		case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
 			if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
-				dbg("invalid report_count %d", parser->global.report_count);
+				dbg_hid("invalid report_count %d\n", parser->global.report_count);
 				return -1;
 			}
 			return 0;
 
 		case HID_GLOBAL_ITEM_TAG_REPORT_ID:
 			if ((parser->global.report_id = item_udata(item)) == 0) {
-				dbg("report_id 0 is invalid");
+				dbg_hid("report_id 0 is invalid\n");
 				return -1;
 			}
 			return 0;
 
 		default:
-			dbg("unknown global tag 0x%x", item->tag);
+			dbg_hid("unknown global tag 0x%x\n", item->tag);
 			return -1;
 	}
 }
@@ -377,7 +384,7 @@
 	unsigned n;
 
 	if (item->size == 0) {
-		dbg("item data expected for local item");
+		dbg_hid("item data expected for local item\n");
 		return -1;
 	}
 
@@ -395,14 +402,14 @@
 				 * items and the first delimiter set.
 				 */
 				if (parser->local.delimiter_depth != 0) {
-					dbg("nested delimiters");
+					dbg_hid("nested delimiters\n");
 					return -1;
 				}
 				parser->local.delimiter_depth++;
 				parser->local.delimiter_branch++;
 			} else {
 				if (parser->local.delimiter_depth < 1) {
-					dbg("bogus close delimiter");
+					dbg_hid("bogus close delimiter\n");
 					return -1;
 				}
 				parser->local.delimiter_depth--;
@@ -412,7 +419,7 @@
 		case HID_LOCAL_ITEM_TAG_USAGE:
 
 			if (parser->local.delimiter_branch > 1) {
-				dbg("alternative usage ignored");
+				dbg_hid("alternative usage ignored\n");
 				return 0;
 			}
 
@@ -424,7 +431,7 @@
 		case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
 
 			if (parser->local.delimiter_branch > 1) {
-				dbg("alternative usage ignored");
+				dbg_hid("alternative usage ignored\n");
 				return 0;
 			}
 
@@ -437,7 +444,7 @@
 		case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
 
 			if (parser->local.delimiter_branch > 1) {
-				dbg("alternative usage ignored");
+				dbg_hid("alternative usage ignored\n");
 				return 0;
 			}
 
@@ -446,14 +453,14 @@
 
 			for (n = parser->local.usage_minimum; n <= data; n++)
 				if (hid_add_usage(parser, n)) {
-					dbg("hid_add_usage failed\n");
+					dbg_hid("hid_add_usage failed\n");
 					return -1;
 				}
 			return 0;
 
 		default:
 
-			dbg("unknown local item tag 0x%x", item->tag);
+			dbg_hid("unknown local item tag 0x%x\n", item->tag);
 			return 0;
 	}
 	return 0;
@@ -487,7 +494,7 @@
 			ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
 			break;
 		default:
-			dbg("unknown main item tag 0x%x", item->tag);
+			dbg_hid("unknown main item tag 0x%x\n", item->tag);
 			ret = 0;
 	}
 
@@ -502,7 +509,7 @@
 
 static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
 {
-	dbg("reserved item type, tag 0x%x", item->tag);
+	dbg_hid("reserved item type, tag 0x%x\n", item->tag);
 	return 0;
 }
 
@@ -667,14 +674,14 @@
 	while ((start = fetch_item(start, end, &item)) != NULL) {
 
 		if (item.format != HID_ITEM_FORMAT_SHORT) {
-			dbg("unexpected long global item");
+			dbg_hid("unexpected long global item\n");
 			hid_free_device(device);
 			vfree(parser);
 			return NULL;
 		}
 
 		if (dispatch_type[item.type](parser, &item)) {
-			dbg("item %u %u %u %u parsing failed\n",
+			dbg_hid("item %u %u %u %u parsing failed\n",
 				item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
 			hid_free_device(device);
 			vfree(parser);
@@ -683,13 +690,13 @@
 
 		if (start == end) {
 			if (parser->collection_stack_ptr) {
-				dbg("unbalanced collection at end of report description");
+				dbg_hid("unbalanced collection at end of report description\n");
 				hid_free_device(device);
 				vfree(parser);
 				return NULL;
 			}
 			if (parser->local.delimiter_depth) {
-				dbg("unbalanced delimiter at end of report description");
+				dbg_hid("unbalanced delimiter at end of report description\n");
 				hid_free_device(device);
 				vfree(parser);
 				return NULL;
@@ -699,7 +706,7 @@
 		}
 	}
 
-	dbg("item fetching failed at offset %d\n", (int)(end - start));
+	dbg_hid("item fetching failed at offset %d\n", (int)(end - start));
 	hid_free_device(device);
 	vfree(parser);
 	return NULL;
@@ -915,13 +922,13 @@
 	hid_dump_input(field->usage + offset, value);
 
 	if (offset >= field->report_count) {
-		dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
+		dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count);
 		hid_dump_field(field, 8);
 		return -1;
 	}
 	if (field->logical_minimum < 0) {
 		if (value != snto32(s32ton(value, size), size)) {
-			dbg("value %d is out of range", value);
+			dbg_hid("value %d is out of range\n", value);
 			return -1;
 		}
 	}
@@ -934,19 +941,17 @@
 {
 	struct hid_report_enum *report_enum = hid->report_enum + type;
 	struct hid_report *report;
-	int n, rsize;
+	int n, rsize, i;
 
 	if (!hid)
 		return -ENODEV;
 
 	if (!size) {
-		dbg("empty report");
+		dbg_hid("empty report\n");
 		return -1;
 	}
 
-#ifdef CONFIG_HID_DEBUG
-	printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
-#endif
+	dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
 
 	n = 0;                          /* Normally report number is 0 */
 	if (report_enum->numbered) {    /* Device uses numbered reports, data[0] is report number */
@@ -954,25 +959,21 @@
 		size--;
 	}
 
-#ifdef CONFIG_HID_DEBUG
-	{
-		int i;
-		printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
-		for (i = 0; i < size; i++)
-			printk(" %02x", data[i]);
-		printk("\n");
-	}
-#endif
+	/* dump the report descriptor */
+	dbg_hid("report %d (size %u) = ", n, size);
+	for (i = 0; i < size; i++)
+		dbg_hid_line(" %02x", data[i]);
+	dbg_hid_line("\n");
 
 	if (!(report = report_enum->report_id_hash[n])) {
-		dbg("undefined report_id %d received", n);
+		dbg_hid("undefined report_id %d received\n", n);
 		return -1;
 	}
 
 	rsize = ((report->size - 1) >> 3) + 1;
 
 	if (size < rsize) {
-		dbg("report %d is too short, (%d < %d)", report->id, size, rsize);
+		dbg_hid("report %d is too short, (%d < %d)\n", report->id, size, rsize);
 		memset(data + size, 0, rsize - size);
 	}
 
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 83c4126..a13757b 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -347,6 +347,9 @@
 void hid_resolv_usage(unsigned usage) {
 	const struct hid_usage_entry *p;
 
+	if (!hid_debug)
+		return;
+
 	resolv_usage_page(usage >> 16);
 	printk(".");
 	for (p = hid_usage_table; p->description; p++)
@@ -369,6 +372,9 @@
 void hid_dump_field(struct hid_field *field, int n) {
 	int j;
 
+	if (!hid_debug)
+		return;
+
 	if (field->physical) {
 		tab(n);
 		printk("Physical(");
@@ -466,6 +472,9 @@
 	unsigned i,k;
 	static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
 
+	if (!hid_debug)
+		return;
+
 	for (i = 0; i < HID_REPORT_TYPES; i++) {
 		report_enum = device->report_enum + i;
 		list = report_enum->report_list.next;
@@ -489,6 +498,9 @@
 EXPORT_SYMBOL_GPL(hid_dump_device);
 
 void hid_dump_input(struct hid_usage *usage, __s32 value) {
+	if (!hid_debug)
+		return;
+
 	printk("hid-debug: input ");
 	hid_resolv_usage(usage->hid);
 	printk(" = %d\n", value);
@@ -758,6 +770,9 @@
 
 void hid_resolv_event(__u8 type, __u16 code) {
 
+	if (!hid_debug)
+		return;
+
 	printk("%s.%s", events[type] ? events[type] : "?",
 		names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
 }
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 7f81789..8edbd30 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -60,6 +60,19 @@
 	150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
 };
 
+/* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */
+#define LOGITECH_EXPANDED_KEYMAP_SIZE 80
+static int logitech_expanded_keymap[LOGITECH_EXPANDED_KEYMAP_SIZE] = {
+	  0,216,  0,213,175,156,  0,  0,  0,  0,
+	144,  0,  0,  0,  0,  0,  0,  0,  0,212,
+	174,167,152,161,112,  0,  0,  0,154,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,183,184,185,186,187,
+	188,189,190,191,192,193,194,  0,  0,  0
+};
+
 static const struct {
 	__s32 x;
 	__s32 y;
@@ -308,9 +321,7 @@
 		
 		clear_bit(old_keycode, dev->keybit);
 		set_bit(usage->code, dev->keybit);
-#ifdef CONFIG_HID_DEBUG
-		printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
-#endif
+		dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
 		/* Set the keybit for the old keycode if the old keycode is used
 		 * by another key */
 		if (hidinput_find_key (hid, 0, old_keycode))
@@ -333,11 +344,9 @@
 
 	field->hidinput = hidinput;
 
-#ifdef CONFIG_HID_DEBUG
-	printk(KERN_DEBUG "Mapping: ");
+	dbg_hid("Mapping: ");
 	hid_resolv_usage(usage->hid);
-	printk(" ---> ");
-#endif
+	dbg_hid_line(" ---> ");
 
 	if (field->flags & HID_MAIN_ITEM_CONSTANT)
 		goto ignore;
@@ -378,6 +387,21 @@
 					}
 			}
 
+			/* Special handling for Logitech Cordless Desktop */
+			if (field->application != HID_GD_MOUSE) {
+				if (device->quirks & HID_QUIRK_LOGITECH_EXPANDED_KEYMAP) {
+					int hid = usage->hid & HID_USAGE;
+					if (hid < LOGITECH_EXPANDED_KEYMAP_SIZE && logitech_expanded_keymap[hid] != 0)
+						code = logitech_expanded_keymap[hid];
+				}
+			} else {
+				if (device->quirks & HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL) {
+					int hid = usage->hid & HID_USAGE;
+					if (hid == 7 || hid == 8)
+						goto ignore;
+				}
+			}
+
 			map_key(code);
 			break;
 
@@ -566,6 +590,11 @@
 				case 0x0e5: map_key_clear(KEY_BASSBOOST);	break;
 				case 0x0e9: map_key_clear(KEY_VOLUMEUP);	break;
 				case 0x0ea: map_key_clear(KEY_VOLUMEDOWN);	break;
+
+				/* reserved in HUT 1.12. Reported on Petalynx remote */
+				case 0x0f6: map_key_clear(KEY_NEXT);		break;
+				case 0x0fa: map_key_clear(KEY_BACK);		break;
+
 				case 0x183: map_key_clear(KEY_CONFIG);		break;
 				case 0x184: map_key_clear(KEY_WORDPROCESSOR);	break;
 				case 0x185: map_key_clear(KEY_EDITOR);		break;
@@ -598,7 +627,9 @@
 				case 0x21b: map_key_clear(KEY_COPY);		break;
 				case 0x21c: map_key_clear(KEY_CUT);		break;
 				case 0x21d: map_key_clear(KEY_PASTE);		break;
-				case 0x221: map_key_clear(KEY_FIND);		break;
+				case 0x21f: map_key_clear(KEY_FIND);		break;
+				case 0x221: map_key_clear(KEY_SEARCH);		break;
+				case 0x222: map_key_clear(KEY_GOTO);		break;
 				case 0x223: map_key_clear(KEY_HOMEPAGE);	break;
 				case 0x224: map_key_clear(KEY_BACK);		break;
 				case 0x225: map_key_clear(KEY_FORWARD);		break;
@@ -688,7 +719,28 @@
 			break;
 
 		case HID_UP_MSVENDOR:
-			goto ignore;
+
+			/* special case - Chicony Chicony KU-0418 tactical pad */
+			if (device->vendor == 0x04f2 && device->product == 0x0418) {
+				set_bit(EV_REP, input->evbit);
+				switch(usage->hid & HID_USAGE) {
+					case 0xff01: map_key_clear(BTN_1);		break;
+					case 0xff02: map_key_clear(BTN_2);		break;
+					case 0xff03: map_key_clear(BTN_3);		break;
+					case 0xff04: map_key_clear(BTN_4);		break;
+					case 0xff05: map_key_clear(BTN_5);		break;
+					case 0xff06: map_key_clear(BTN_6);		break;
+					case 0xff07: map_key_clear(BTN_7);		break;
+					case 0xff08: map_key_clear(BTN_8);		break;
+					case 0xff09: map_key_clear(BTN_9);		break;
+					case 0xff0a: map_key_clear(BTN_A);		break;
+					case 0xff0b: map_key_clear(BTN_B);		break;
+					default:    goto ignore;
+				}
+			} else {
+				goto ignore;
+			}
+			break;
 
 		case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
 
@@ -704,10 +756,10 @@
 			}
 			break;
 
-		case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
-
+		case HID_UP_LOGIVENDOR:
 			set_bit(EV_REP, input->evbit);
 			switch(usage->hid & HID_USAGE) {
+				/* Reported on Logitech Ultra X Media Remote */
 				case 0x004: map_key_clear(KEY_AGAIN);		break;
 				case 0x00d: map_key_clear(KEY_HOME);		break;
 				case 0x024: map_key_clear(KEY_SHUFFLE);		break;
@@ -725,6 +777,14 @@
 				case 0x04d: map_key_clear(KEY_SUBTITLE);	break;
 				case 0x051: map_key_clear(KEY_RED);		break;
 				case 0x052: map_key_clear(KEY_CLOSE);		break;
+
+				/* Reported on Petalynx Maxter remote */
+				case 0x05a: map_key_clear(KEY_TEXT);		break;
+				case 0x05b: map_key_clear(KEY_RED);		break;
+				case 0x05c: map_key_clear(KEY_GREEN);		break;
+				case 0x05d: map_key_clear(KEY_YELLOW);		break;
+				case 0x05e: map_key_clear(KEY_BLUE);		break;
+
 				default:    goto ignore;
 			}
 			break;
@@ -818,16 +878,24 @@
 			field->dpad = usage->code;
 	}
 
+	/* for those devices which produce Consumer volume usage as relative,
+	 * we emulate pressing volumeup/volumedown appropriate number of times
+	 * in hidinput_hid_event()
+	 */
+	if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
+			(usage->code == ABS_VOLUME)) {
+		set_bit(KEY_VOLUMEUP, input->keybit);
+		set_bit(KEY_VOLUMEDOWN, input->keybit);
+	}
+
 	hid_resolv_event(usage->type, usage->code);
-#ifdef CONFIG_HID_DEBUG
-	printk("\n");
-#endif
+
+	dbg_hid_line("\n");
+
 	return;
 
 ignore:
-#ifdef CONFIG_HID_DEBUG
-	printk("IGNORED\n");
-#endif
+	dbg_hid_line("IGNORED\n");
 	return;
 }
 
@@ -896,18 +964,33 @@
 	}
 
 	if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */
-		dbg("Maximum Effects - %d",value);
+		dbg_hid("Maximum Effects - %d\n",value);
 		return;
 	}
 
 	if (usage->hid == (HID_UP_PID | 0x7fUL)) {
-		dbg("PID Pool Report\n");
+		dbg_hid("PID Pool Report\n");
 		return;
 	}
 
 	if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
 		return;
 
+	if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
+			(usage->code == ABS_VOLUME)) {
+		int count = abs(value);
+		int direction = value > 0 ? KEY_VOLUMEUP : KEY_VOLUMEDOWN;
+		int i;
+
+		for (i = 0; i < count; i++) {
+			input_event(input, EV_KEY, direction, 1);
+			input_sync(input);
+			input_event(input, EV_KEY, direction, 0);
+			input_sync(input);
+		}
+		return;
+	}
+
 	input_event(input, usage->type, usage->code, value);
 
 	if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
@@ -976,7 +1059,7 @@
 			if (IS_INPUT_APPLICATION(hid->collection[i].usage))
 				break;
 
-	if (i == hid->maxcollection)
+	if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDINPUT) == 0)
 		return -1;
 
 	if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
@@ -994,7 +1077,7 @@
 				if (!hidinput || !input_dev) {
 					kfree(hidinput);
 					input_free_device(input_dev);
-					err("Out of memory during hid input probe");
+					err_hid("Out of memory during hid input probe");
 					return -1;
 				}
 
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index d91b9da..3afa4a5 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -60,6 +60,12 @@
 		" quirks=vendorID:productID:quirks"
 		" where vendorID, productID, and quirks are all in"
 		" 0x-prefixed hex");
+static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
+module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444);
+MODULE_PARM_DESC(rdesc_quirks, "Add/modify report descriptor quirks by specifying "
+		" rdesc_quirks=vendorID:productID:rdesc_quirks"
+		" where vendorID, productID, and rdesc_quirks are all in"
+		" 0x-prefixed hex");
 /*
  * Input submission and I/O error handler.
  */
@@ -127,7 +133,7 @@
 			hid_io_error(hid);
 		break;
 	default:
-		err("can't reset device, %s-%s/input%d, status %d",
+		err_hid("can't reset device, %s-%s/input%d, status %d",
 				hid_to_usb_dev(hid)->bus->bus_name,
 				hid_to_usb_dev(hid)->devpath,
 				usbhid->ifnum, rc);
@@ -220,7 +226,7 @@
 	if (status) {
 		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
 		if (status != -EPERM) {
-			err("can't resubmit intr, %s-%s/input%d, status %d",
+			err_hid("can't resubmit intr, %s-%s/input%d, status %d",
 					hid_to_usb_dev(hid)->bus->bus_name,
 					hid_to_usb_dev(hid)->devpath,
 					usbhid->ifnum, status);
@@ -240,10 +246,10 @@
 	usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
 	usbhid->urbout->dev = hid_to_usb_dev(hid);
 
-	dbg("submitting out urb");
+	dbg_hid("submitting out urb\n");
 
 	if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
-		err("usb_submit_urb(out) failed");
+		err_hid("usb_submit_urb(out) failed");
 		return -1;
 	}
 
@@ -287,12 +293,12 @@
 	usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
 	usbhid->cr->wLength = cpu_to_le16(len);
 
-	dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
+	dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n",
 		usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
 		usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
 
 	if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
-		err("usb_submit_urb(ctrl) failed");
+		err_hid("usb_submit_urb(ctrl) failed");
 		return -1;
 	}
 
@@ -474,7 +480,7 @@
 	if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
 					!test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
 					10*HZ)) {
-		dbg("timeout waiting for ctrl or out queue to clear");
+		dbg_hid("timeout waiting for ctrl or out queue to clear\n");
 		return -1;
 	}
 
@@ -633,20 +639,6 @@
 }
 
 /*
- * Cherry Cymotion keyboard have an invalid HID report descriptor,
- * that needs fixing before we can parse it.
- */
-
-static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
-{
-	if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
-		info("Fixing up Cherry Cymotion report descriptor");
-		rdesc[11] = rdesc[16] = 0xff;
-		rdesc[12] = rdesc[17] = 0x03;
-	}
-}
-
-/*
  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
  * to "operational".  Without this, the ps3 controller will not report any
  * events.
@@ -667,51 +659,11 @@
 				 USB_CTRL_GET_TIMEOUT);
 
 	if (result < 0)
-		err("%s failed: %d\n", __func__, result);
+		err_hid("%s failed: %d\n", __func__, result);
 
 	kfree(buf);
 }
 
-/*
- * Certain Logitech keyboards send in report #3 keys which are far
- * above the logical maximum described in descriptor. This extends
- * the original value of 0x28c of logical maximum to 0x104d
- */
-static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
-{
-	if (rsize >= 90 && rdesc[83] == 0x26
-			&& rdesc[84] == 0x8c
-			&& rdesc[85] == 0x02) {
-		info("Fixing up Logitech keyboard report descriptor");
-		rdesc[84] = rdesc[89] = 0x4d;
-		rdesc[85] = rdesc[90] = 0x10;
-	}
-}
-
-/*
- * Some USB barcode readers from cypress have usage min and usage max in
- * the wrong order
- */
-static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
-{
-	short fixed = 0;
-	int i;
-
-	for (i = 0; i < rsize - 4; i++) {
-		if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
-			unsigned char tmp;
-
-			rdesc[i] = 0x19; rdesc[i+2] = 0x29;
-			tmp = rdesc[i+3];
-			rdesc[i+3] = rdesc[i+1];
-			rdesc[i+1] = tmp;
-		}
-	}
-
-	if (fixed)
-		info("Fixing up Cypress report descriptor");
-}
-
 static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 {
 	struct usb_host_interface *interface = intf->cur_altsetting;
@@ -746,7 +698,7 @@
 	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
 	    (!interface->desc.bNumEndpoints ||
 	     usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
-		dbg("class descriptor not present\n");
+		dbg_hid("class descriptor not present\n");
 		return NULL;
 	}
 
@@ -755,41 +707,34 @@
 			rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
 
 	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
-		dbg("weird size of report descriptor (%u)", rsize);
+		dbg_hid("weird size of report descriptor (%u)\n", rsize);
 		return NULL;
 	}
 
 	if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
-		dbg("couldn't allocate rdesc memory");
+		dbg_hid("couldn't allocate rdesc memory\n");
 		return NULL;
 	}
 
 	hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
 
 	if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
-		dbg("reading report descriptor failed");
+		dbg_hid("reading report descriptor failed\n");
 		kfree(rdesc);
 		return NULL;
 	}
 
-	if ((quirks & HID_QUIRK_CYMOTION))
-		hid_fixup_cymotion_descriptor(rdesc, rsize);
+	usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
+			le16_to_cpu(dev->descriptor.idProduct), rdesc,
+			rsize, rdesc_quirks_param);
 
-	if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
-		hid_fixup_logitech_descriptor(rdesc, rsize);
-
-	if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
-		hid_fixup_cypress_descriptor(rdesc, rsize);
-
-#ifdef CONFIG_HID_DEBUG
-	printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
+	dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
 	for (n = 0; n < rsize; n++)
-		printk(" %02x", (unsigned char) rdesc[n]);
-	printk("\n");
-#endif
+		dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
+	dbg_hid_line("\n");
 
 	if (!(hid = hid_parse_report(rdesc, n))) {
-		dbg("parsing report descriptor failed");
+		dbg_hid("parsing report descriptor failed\n");
 		kfree(rdesc);
 		return NULL;
 	}
@@ -861,7 +806,7 @@
 	}
 
 	if (!usbhid->urbin) {
-		err("couldn't find an input interrupt endpoint");
+		err_hid("couldn't find an input interrupt endpoint");
 		goto fail;
 	}
 
@@ -956,7 +901,7 @@
 	usb_kill_urb(usbhid->urbctrl);
 
 	del_timer_sync(&usbhid->io_retry);
-	flush_scheduled_work();
+	cancel_work_sync(&usbhid->reset_work);
 
 	if (hid->claimed & HID_CLAIMED_INPUT)
 		hidinput_disconnect(hid);
@@ -978,7 +923,7 @@
 	int i;
 	char *c;
 
-	dbg("HID probe called for ifnum %d",
+	dbg_hid("HID probe called for ifnum %d\n",
 			intf->altsetting->desc.bInterfaceNumber);
 
 	if (!(hid = usb_hid_configure(intf)))
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/usbhid/hid-lgff.c
index c5cd410..4b7ab6a 100644
--- a/drivers/hid/usbhid/hid-lgff.c
+++ b/drivers/hid/usbhid/hid-lgff.c
@@ -78,7 +78,7 @@
 		report->field[0]->value[1] = 0x08;
 		report->field[0]->value[2] = x;
 		report->field[0]->value[3] = y;
-		dbg("(x, y)=(%04x, %04x)", x, y);
+		dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
 		usbhid_submit_report(hid, report, USB_DIR_OUT);
 		break;
 
@@ -93,7 +93,7 @@
 		report->field[0]->value[1] = 0x00;
 		report->field[0]->value[2] = left;
 		report->field[0]->value[3] = right;
-		dbg("(left, right)=(%04x, %04x)", left, right);
+		dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
 		usbhid_submit_report(hid, report, USB_DIR_OUT);
 		break;
 	}
@@ -113,20 +113,20 @@
 
 	/* Find the report to use */
 	if (list_empty(report_list)) {
-		err("No output report found");
+		err_hid("No output report found");
 		return -1;
 	}
 
 	/* Check that the report looks ok */
 	report = list_entry(report_list->next, struct hid_report, list);
 	if (!report) {
-		err("NULL output report");
+		err_hid("NULL output report");
 		return -1;
 	}
 
 	field = report->field[0];
 	if (!field) {
-		err("NULL field");
+		err_hid("NULL field");
 		return -1;
 	}
 
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index f5a90e9..0113261 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -738,6 +738,7 @@
 	pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0;
 	pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
 	pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
+	pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
 	pidff->set_effect[PID_START_DELAY].value[0] = 0;
 
 	usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index f6c4145..775b9f3 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -105,6 +105,9 @@
 #define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
 #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
 
+#define USB_VENDOR_ID_GAMERON		0x0810
+#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR	0x0001
+
 #define USB_VENDOR_ID_GLAB		0x06c2
 #define USB_DEVICE_ID_4_PHIDGETSERVO_30	0x0038
 #define USB_DEVICE_ID_1_PHIDGETSERVO_30	0x0039
@@ -196,8 +199,10 @@
 #define USB_VENDOR_ID_LOGITECH		0x046d
 #define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
 #define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
+#define USB_DEVICE_ID_LOGITECH_KBD	0xc311
 #define USB_DEVICE_ID_S510_RECEIVER	0xc50c
 #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
+#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500	0xc512
 #define USB_DEVICE_ID_MX3000_RECEIVER	0xc513
 #define USB_DEVICE_ID_DINOVO_EDGE	0xc714
 
@@ -209,6 +214,13 @@
 #define USB_DEVICE_ID_MGE_UPS		0xffff
 #define USB_DEVICE_ID_MGE_UPS1		0x0001
 
+#define USB_VENDOR_ID_MICROSOFT		0x045e
+#define USB_DEVICE_ID_SIDEWINDER_GV	0x003b
+
+#define USB_VENDOR_ID_NCR		0x0404
+#define USB_DEVICE_ID_NCR_FIRST		0x0300
+#define USB_DEVICE_ID_NCR_LAST		0x03ff
+
 #define USB_VENDOR_ID_NEC		0x073e
 #define USB_DEVICE_ID_NEC_USB_GAME_PAD	0x0301
 
@@ -220,6 +232,9 @@
 #define USB_VENDOR_ID_PANTHERLORD	0x0810
 #define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK	0x0001
 
+#define USB_VENDOR_ID_PETALYNX		0x18b1
+#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE	0x0037
+
 #define USB_VENDOR_ID_PLAYDOTCOM	0x0b43
 #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII	0x0003
 
@@ -278,6 +293,7 @@
 	{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
+	{ USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -285,11 +301,10 @@
 	{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
 	
-	{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
-
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
 
 	{ USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
 
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
@@ -409,9 +424,7 @@
 	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
 
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
-	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_LOGITECH_DESCRIPTOR },
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
 
 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
 
@@ -426,6 +439,7 @@
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
@@ -448,9 +462,28 @@
 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
 
 	{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
 
-	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX },
-	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX },
+	{ 0, 0 }
+};
+
+/* Quirks for devices which require report descriptor fixup go here */
+static const struct hid_rdesc_blacklist {
+	__u16 idVendor;
+	__u16 idProduct;
+	__u32 quirks;
+} hid_rdesc_blacklist[] = {
+
+	{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
+
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
+
+	{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
+
+	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
 
 	{ 0, 0 }
 };
@@ -493,7 +526,7 @@
 	}
 
 	if (bl_entry != NULL)
-		dbg("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
+		dbg_hid("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
 				bl_entry->quirks, bl_entry->idVendor,
 				bl_entry->idProduct);
 
@@ -521,13 +554,13 @@
 	int list_edited = 0;
 
 	if (!idVendor) {
-		dbg("Cannot add a quirk with idVendor = 0");
+		dbg_hid("Cannot add a quirk with idVendor = 0\n");
 		return -EINVAL;
 	}
 
 	q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL);
 	if (!q_new) {
-		dbg("Could not allocate quirks_list_struct");
+		dbg_hid("Could not allocate quirks_list_struct\n");
 		return -ENOMEM;
 	}
 
@@ -559,7 +592,6 @@
 	return 0;
 }
 
-
 /**
  * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory
  *
@@ -643,7 +675,7 @@
 			bl_entry = &hid_blacklist[n];
 
 	if (bl_entry != NULL)
-		dbg("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
+		dbg_hid("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
 				bl_entry->quirks, bl_entry->idVendor, 
 				bl_entry->idProduct);
 	return bl_entry;
@@ -675,6 +707,12 @@
 				idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
 			return HID_QUIRK_IGNORE;
 
+	/* NCR devices must not be queried for reports */
+	if (idVendor == USB_VENDOR_ID_NCR &&
+			idProduct >= USB_DEVICE_ID_NCR_FIRST &&
+			idProduct <= USB_DEVICE_ID_NCR_LAST)
+			return HID_QUIRK_NOGET;
+
 	down_read(&dquirks_rwsem);
 	bl_entry = usbhid_exists_dquirk(idVendor, idProduct);
 	if (!bl_entry)
@@ -686,3 +724,126 @@
 	return quirks;
 }
 
+/*
+ * Cherry Cymotion keyboard have an invalid HID report descriptor,
+ * that needs fixing before we can parse it.
+ */
+static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
+{
+	if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+		printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");
+		rdesc[11] = rdesc[16] = 0xff;
+		rdesc[12] = rdesc[17] = 0x03;
+	}
+}
+
+
+/*
+ * Certain Logitech keyboards send in report #3 keys which are far
+ * above the logical maximum described in descriptor. This extends
+ * the original value of 0x28c of logical maximum to 0x104d
+ */
+static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
+{
+	if (rsize >= 90 && rdesc[83] == 0x26
+			&& rdesc[84] == 0x8c
+			&& rdesc[85] == 0x02) {
+		printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
+		rdesc[84] = rdesc[89] = 0x4d;
+		rdesc[85] = rdesc[90] = 0x10;
+	}
+}
+
+/* Petalynx Maxter Remote has maximum for consumer page set too low */
+static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
+{
+	if (rsize >= 60 && rdesc[39] == 0x2a
+			&& rdesc[40] == 0xf5
+			&& rdesc[41] == 0x00
+			&& rdesc[59] == 0x26
+			&& rdesc[60] == 0xf9
+			&& rdesc[61] == 0x00) {
+		printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");
+		rdesc[60] = 0xfa;
+		rdesc[40] = 0xfa;
+	}
+}
+
+/*
+ * Some USB barcode readers from cypress have usage min and usage max in
+ * the wrong order
+ */
+static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
+{
+	short fixed = 0;
+	int i;
+
+	for (i = 0; i < rsize - 4; i++) {
+		if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
+			unsigned char tmp;
+
+			rdesc[i] = 0x19; rdesc[i+2] = 0x29;
+			tmp = rdesc[i+3];
+			rdesc[i+3] = rdesc[i+1];
+			rdesc[i+1] = tmp;
+		}
+	}
+
+	if (fixed)
+		printk(KERN_INFO "Fixing up Cypress report descriptor\n");
+}
+
+
+static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
+{
+	if ((quirks & HID_QUIRK_RDESC_CYMOTION))
+		usbhid_fixup_cymotion_descriptor(rdesc, rsize);
+
+	if (quirks & HID_QUIRK_RDESC_LOGITECH)
+		usbhid_fixup_logitech_descriptor(rdesc, rsize);
+
+	if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
+		usbhid_fixup_cypress_descriptor(rdesc, rsize);
+
+	if (quirks & HID_QUIRK_RDESC_PETALYNX)
+		usbhid_fixup_petalynx_descriptor(rdesc, rsize);
+}
+
+/**
+ * usbhid_fixup_report_descriptor: check if report descriptor needs fixup
+ *
+ * Description:
+ *	Walks the hid_rdesc_blacklist[] array and checks whether the device
+ *	is known to have broken report descriptor that needs to be fixed up
+ *	prior to entering the HID parser
+ *
+ * Returns: nothing
+ */
+void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
+				    char *rdesc, unsigned rsize, char **quirks_param)
+{
+	int n, m;
+	u16 paramVendor, paramProduct;
+	u32 quirks;
+
+	/* static rdesc quirk entries */
+	for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)
+		if (hid_rdesc_blacklist[n].idVendor == idVendor &&
+				hid_rdesc_blacklist[n].idProduct == idProduct)
+			__usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,
+					rdesc, rsize);
+
+	/* runtime rdesc quirk entries handling */
+	for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
+		m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
+				&paramVendor, &paramProduct, &quirks);
+
+		if (m != 3)
+			printk(KERN_WARNING
+				"Could not parse HID quirk module param %s\n",
+				quirks_param[n]);
+		else if (paramVendor == idVendor && paramProduct == idProduct)
+			__usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
+	}
+
+}
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c
index ab5ba6e..555bb48 100644
--- a/drivers/hid/usbhid/hid-tmff.c
+++ b/drivers/hid/usbhid/hid-tmff.c
@@ -70,7 +70,7 @@
 
 	tmff->rumble->value[0] = left;
 	tmff->rumble->value[1] = right;
-	dbg("(left,right)=(%08x, %08x)", left, right);
+	dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
 	usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
 
 	return 0;
diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/usbhid/hid-zpff.c
index a7fbffc..5a68827 100644
--- a/drivers/hid/usbhid/hid-zpff.c
+++ b/drivers/hid/usbhid/hid-zpff.c
@@ -21,10 +21,6 @@
  */
 
 
-/* #define DEBUG */
-
-#define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg)
-
 #include <linux/input.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
@@ -49,14 +45,14 @@
 
 	left = effect->u.rumble.strong_magnitude;
 	right = effect->u.rumble.weak_magnitude;
-	debug("called with 0x%04x 0x%04x", left, right);
+	dbg_hid("called with 0x%04x 0x%04x\n", left, right);
 
 	left = left * 0x7f / 0xffff;
 	right = right * 0x7f / 0xffff;
 
 	zpff->report->field[2]->value[0] = left;
 	zpff->report->field[3]->value[0] = right;
-	debug("running with 0x%02x 0x%02x", left, right);
+	dbg_hid("running with 0x%02x 0x%02x\n", left, right);
 	usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
 
 	return 0;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 488d61b..e793127 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -779,7 +779,7 @@
 
 	retval = usb_register_dev(usbhid->intf, &hiddev_class);
 	if (retval) {
-		err("Not able to get a minor for this device.");
+		err_hid("Not able to get a minor for this device.");
 		kfree(hiddev);
 		return -1;
 	}
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 1309787..b76b02f 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -125,7 +125,7 @@
 resubmit:
 	i = usb_submit_urb (urb, GFP_ATOMIC);
 	if (i)
-		err ("can't resubmit intr, %s-%s/input0, status %d",
+		err_hid ("can't resubmit intr, %s-%s/input0, status %d",
 				kbd->usbdev->bus->bus_name,
 				kbd->usbdev->devpath, i);
 }
@@ -151,7 +151,7 @@
 	*(kbd->leds) = kbd->newleds;
 	kbd->led->dev = kbd->usbdev;
 	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
-		err("usb_submit_urb(leds) failed");
+		err_hid("usb_submit_urb(leds) failed");
 
 	return 0;
 }
@@ -169,7 +169,7 @@
 	*(kbd->leds) = kbd->newleds;
 	kbd->led->dev = kbd->usbdev;
 	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
-		err("usb_submit_urb(leds) failed");
+		err_hid("usb_submit_urb(leds) failed");
 }
 
 static int usb_kbd_open(struct input_dev *dev)
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 66f8262..444a0b8 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -448,23 +448,21 @@
 			ICS_ARCIN_V6_INTRSTAT_1)) & 1;
 }
 
-static int icside_dma_timeout(ide_drive_t *drive)
+static void icside_dma_timeout(ide_drive_t *drive)
 {
 	printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
 
 	if (icside_dma_test_irq(drive))
-		return 0;
+		return;
 
-	ide_dump_status(drive, "DMA timeout",
-		HWIF(drive)->INB(IDE_STATUS_REG));
+	ide_dump_status(drive, "DMA timeout", HWIF(drive)->INB(IDE_STATUS_REG));
 
-	return icside_dma_end(drive);
+	icside_dma_end(drive);
 }
 
-static int icside_dma_lostirq(ide_drive_t *drive)
+static void icside_dma_lost_irq(ide_drive_t *drive)
 {
 	printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-	return 1;
 }
 
 static void icside_dma_init(ide_hwif_t *hwif)
@@ -490,8 +488,8 @@
 	hwif->dma_start		= icside_dma_start;
 	hwif->ide_dma_end	= icside_dma_end;
 	hwif->ide_dma_test_irq	= icside_dma_test_irq;
-	hwif->ide_dma_timeout	= icside_dma_timeout;
-	hwif->ide_dma_lostirq	= icside_dma_lostirq;
+	hwif->dma_timeout	= icside_dma_timeout;
+	hwif->dma_lost_irq	= icside_dma_lost_irq;
 
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index ca0341c..886091b 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -819,7 +819,7 @@
 		hwif->dma_host_off = &cris_dma_off;
 		hwif->dma_host_on = &cris_dma_on;
 		hwif->dma_off_quietly = &cris_dma_off;
-		hwif->udma_four = 0;
+		hwif->cbl = ATA_CBL_PATA40;
 		hwif->ultra_mask = cris_ultra_mask;
 		hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
 		hwif->autodma = 1;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 252ab82..1486eb2 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -481,7 +481,7 @@
 		else
 			printk("  Unknown Error Type: ");
 
-		if (sense->sense_key < ARY_LEN(sense_key_texts))
+		if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
 			s = sense_key_texts[sense->sense_key];
 
 		printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
@@ -491,7 +491,7 @@
 				 sense->ascq);
 			s = buf;
 		} else {
-			int lo = 0, mid, hi = ARY_LEN(sense_data_texts);
+			int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
 			unsigned long key = (sense->sense_key << 16);
 			key |= (sense->asc << 8);
 			if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
@@ -524,7 +524,7 @@
 
 		if (failed_command != NULL) {
 
-			int lo=0, mid, hi= ARY_LEN (packet_command_texts);
+			int lo=0, mid, hi= ARRAY_SIZE(packet_command_texts);
 			s = NULL;
 
 			while (hi > lo) {
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index ad1f2ed..228b29c 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -498,8 +498,6 @@
  * Descriptions of ATAPI error codes.
  */
 
-#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0])))
-
 /* This stuff should be in cdrom.h, since it is now generic... */
 
 /* ATAPI sense keys (from table 140 of ATAPI 2.6) */
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index dc2175c..b1304a7 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1190,11 +1190,11 @@
 	return generic_ide_ioctl(drive, file, bdev, cmd, arg);
 
 read_val:
-	down(&ide_setting_sem);
+	mutex_lock(&ide_setting_mtx);
 	spin_lock_irqsave(&ide_lock, flags);
 	err = *val;
 	spin_unlock_irqrestore(&ide_lock, flags);
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 	return err >= 0 ? put_user(err, (long __user *)arg) : err;
 
 set_val:
@@ -1204,9 +1204,9 @@
 		if (!capable(CAP_SYS_ADMIN))
 			err = -EACCES;
 		else {
-			down(&ide_setting_sem);
+			mutex_lock(&ide_setting_mtx);
 			err = setfunc(drive, arg);
-			up(&ide_setting_sem);
+			mutex_unlock(&ide_setting_mtx);
 		}
 	}
 	return err;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index ead141e..5fe1d72 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -91,45 +91,45 @@
 
 static const struct drive_list_entry drive_whitelist [] = {
 
-	{ "Micropolis 2112A"	,       "ALL"		},
-	{ "CONNER CTMA 4000"	,       "ALL"		},
-	{ "CONNER CTT8000-A"	,       "ALL"		},
-	{ "ST34342A"		,	"ALL"		},
+	{ "Micropolis 2112A"	,       NULL		},
+	{ "CONNER CTMA 4000"	,       NULL		},
+	{ "CONNER CTT8000-A"	,       NULL		},
+	{ "ST34342A"		,	NULL		},
 	{ NULL			,	NULL		}
 };
 
 static const struct drive_list_entry drive_blacklist [] = {
 
-	{ "WDC AC11000H"	,	"ALL"		},
-	{ "WDC AC22100H"	,	"ALL"		},
-	{ "WDC AC32500H"	,	"ALL"		},
-	{ "WDC AC33100H"	,	"ALL"		},
-	{ "WDC AC31600H"	,	"ALL"		},
+	{ "WDC AC11000H"	,	NULL 		},
+	{ "WDC AC22100H"	,	NULL 		},
+	{ "WDC AC32500H"	,	NULL 		},
+	{ "WDC AC33100H"	,	NULL 		},
+	{ "WDC AC31600H"	,	NULL 		},
 	{ "WDC AC32100H"	,	"24.09P07"	},
 	{ "WDC AC23200L"	,	"21.10N21"	},
-	{ "Compaq CRD-8241B"	,	"ALL"		},
-	{ "CRD-8400B"		,	"ALL"		},
-	{ "CRD-8480B",			"ALL"		},
-	{ "CRD-8482B",			"ALL"		},
- 	{ "CRD-84"		,	"ALL"		},
-	{ "SanDisk SDP3B"	,	"ALL"		},
-	{ "SanDisk SDP3B-64"	,	"ALL"		},
-	{ "SANYO CD-ROM CRD"	,	"ALL"		},
-	{ "HITACHI CDR-8"	,	"ALL"		},
-	{ "HITACHI CDR-8335"	,	"ALL"		},
-	{ "HITACHI CDR-8435"	,	"ALL"		},
-	{ "Toshiba CD-ROM XM-6202B"	,	"ALL"		},
-	{ "TOSHIBA CD-ROM XM-1702BC",	"ALL"		},
-	{ "CD-532E-A"		,	"ALL"		},
-	{ "E-IDE CD-ROM CR-840",	"ALL"		},
-	{ "CD-ROM Drive/F5A",	"ALL"		},
-	{ "WPI CDD-820",		"ALL"		},
-	{ "SAMSUNG CD-ROM SC-148C",	"ALL"		},
-	{ "SAMSUNG CD-ROM SC",	"ALL"		},
-	{ "ATAPI CD-ROM DRIVE 40X MAXIMUM",	"ALL"		},
-	{ "_NEC DV5800A",               "ALL"           },  
+	{ "Compaq CRD-8241B"	,	NULL 		},
+	{ "CRD-8400B"		,	NULL 		},
+	{ "CRD-8480B",			NULL 		},
+	{ "CRD-8482B",			NULL 		},
+	{ "CRD-84"		,	NULL 		},
+	{ "SanDisk SDP3B"	,	NULL 		},
+	{ "SanDisk SDP3B-64"	,	NULL 		},
+	{ "SANYO CD-ROM CRD"	,	NULL 		},
+	{ "HITACHI CDR-8"	,	NULL 		},
+	{ "HITACHI CDR-8335"	,	NULL 		},
+	{ "HITACHI CDR-8435"	,	NULL 		},
+	{ "Toshiba CD-ROM XM-6202B"	,	NULL 		},
+	{ "TOSHIBA CD-ROM XM-1702BC",	NULL 		},
+	{ "CD-532E-A"		,	NULL 		},
+	{ "E-IDE CD-ROM CR-840",	NULL 		},
+	{ "CD-ROM Drive/F5A",	NULL 		},
+	{ "WPI CDD-820",		NULL 		},
+	{ "SAMSUNG CD-ROM SC-148C",	NULL 		},
+	{ "SAMSUNG CD-ROM SC",	NULL 		},
+	{ "ATAPI CD-ROM DRIVE 40X MAXIMUM",	NULL 		},
+	{ "_NEC DV5800A",               NULL            },
 	{ "SAMSUNG CD-ROM SN-124",	"N001" },
-	{ "Seagate STT20000A",		"ALL" },
+	{ "Seagate STT20000A",		NULL  },
 	{ NULL			,	NULL		}
 
 };
@@ -147,8 +147,8 @@
 {
 	for ( ; drive_table->id_model ; drive_table++)
 		if ((!strcmp(drive_table->id_model, id->model)) &&
-		    ((strstr(id->fw_rev, drive_table->id_firmware)) ||
-		     (!strcmp(drive_table->id_firmware, "ALL"))))
+		    (!drive_table->id_firmware ||
+		     strstr(id->fw_rev, drive_table->id_firmware)))
 			return 1;
 	return 0;
 }
@@ -702,8 +702,22 @@
 			mask = id->dma_mword & hwif->mwdma_mask;
 		break;
 	case XFER_SW_DMA_0:
-		if (id->field_valid & 2)
+		if (id->field_valid & 2) {
 			mask = id->dma_1word & hwif->swdma_mask;
+		} else if (id->tDMA) {
+			/*
+			 * ide_fix_driveid() doesn't convert ->tDMA to the
+			 * CPU endianness so we need to do it here
+			 */
+			u8 mode = le16_to_cpu(id->tDMA);
+
+			/*
+			 * if the mode is valid convert it to the mask
+			 * (the maximum allowed mode is XFER_SW_DMA_2)
+			 */
+			if (mode <= 2)
+				mask = ((2 << mode) - 1) & hwif->swdma_mask;
+		}
 		break;
 	default:
 		BUG();
@@ -847,27 +861,27 @@
 	return rc;
 }
 
-EXPORT_SYMBOL_GPL(ide_set_dma);
-
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-int __ide_dma_lostirq (ide_drive_t *drive)
+void ide_dma_lost_irq (ide_drive_t *drive)
 {
 	printk("%s: DMA interrupt recovery\n", drive->name);
-	return 1;
 }
 
-EXPORT_SYMBOL(__ide_dma_lostirq);
+EXPORT_SYMBOL(ide_dma_lost_irq);
 
-int __ide_dma_timeout (ide_drive_t *drive)
+void ide_dma_timeout (ide_drive_t *drive)
 {
-	printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
-	if (HWIF(drive)->ide_dma_test_irq(drive))
-		return 0;
+	ide_hwif_t *hwif = HWIF(drive);
 
-	return HWIF(drive)->ide_dma_end(drive);
+	printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
+
+	if (hwif->ide_dma_test_irq(drive))
+		return;
+
+	hwif->ide_dma_end(drive);
 }
 
-EXPORT_SYMBOL(__ide_dma_timeout);
+EXPORT_SYMBOL(ide_dma_timeout);
 
 /*
  * Needed for allowing full modular support of ide-driver
@@ -1018,10 +1032,10 @@
 		hwif->ide_dma_end = &__ide_dma_end;
 	if (!hwif->ide_dma_test_irq)
 		hwif->ide_dma_test_irq = &__ide_dma_test_irq;
-	if (!hwif->ide_dma_timeout)
-		hwif->ide_dma_timeout = &__ide_dma_timeout;
-	if (!hwif->ide_dma_lostirq)
-		hwif->ide_dma_lostirq = &__ide_dma_lostirq;
+	if (!hwif->dma_timeout)
+		hwif->dma_timeout = &ide_dma_timeout;
+	if (!hwif->dma_lost_irq)
+		hwif->dma_lost_irq = &ide_dma_lost_irq;
 
 	if (hwif->chipset != ide_trm290) {
 		u8 dma_stat = hwif->INB(hwif->dma_status);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index bfe8f1b..c5b5011 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -1350,7 +1350,7 @@
 						hwif->INB(IDE_STATUS_REG));
 	} else {
 		printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
-		(void) hwif->ide_dma_timeout(drive);
+		hwif->dma_timeout(drive);
 	}
 
 	/*
@@ -1466,7 +1466,7 @@
 				startstop = handler(drive);
 			} else if (drive_is_ready(drive)) {
 				if (drive->waiting_for_dma)
-					(void) hwgroup->hwif->ide_dma_lostirq(drive);
+					hwgroup->hwif->dma_lost_irq(drive);
 				(void)ide_ack_intr(hwif);
 				printk(KERN_WARNING "%s: lost interrupt\n", drive->name);
 				startstop = handler(drive);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index f0be5f6..92578b6 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -574,7 +574,10 @@
 	ide_hwif_t *hwif = drive->hwif;
 	struct hd_driveid *id = drive->id;
 
-	if (hwif->udma_four == 0)
+	if (hwif->cbl == ATA_CBL_PATA40_SHORT)
+		return 1;
+
+	if (hwif->cbl != ATA_CBL_PATA80)
 		goto no_80w;
 
 	/* Check for SATA but only if we are ATA5 or higher */
@@ -600,7 +603,8 @@
 
 	printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "
 			    "limiting max speed to UDMA33\n",
-			    drive->name, hwif->udma_four ? "drive" : "host");
+			    drive->name,
+			    hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");
 
 	drive->udma33_warned = 1;
 
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index f5ce22c..cc58013 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -144,7 +144,7 @@
 	local_irq_enable();
 	ide_fix_driveid(id);
 
-#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
+#if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
 	/*
 	 * EATA SCSI controllers do a hardware ATA emulation:
 	 * Ignore them if there is a driver for them available.
@@ -154,7 +154,7 @@
 		printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model);
 		goto err_misc;
 	}
-#endif /* CONFIG_SCSI_EATA_DMA || CONFIG_SCSI_EATA_PIO */
+#endif /* CONFIG_SCSI_EATA || CONFIG_SCSI_EATA_PIO */
 
 	/*
 	 *  WIN_IDENTIFY returns little-endian info,
@@ -1025,7 +1025,7 @@
 	BUG_ON(irqs_disabled());	
 	BUG_ON(hwif == NULL);
 
-	down(&ide_cfg_sem);
+	mutex_lock(&ide_cfg_mtx);
 	hwif->hwgroup = NULL;
 #if MAX_HWIFS > 1
 	/*
@@ -1154,7 +1154,7 @@
 		printk(" (%sed with %s)",
 			hwif->sharing_irq ? "shar" : "serializ", match->name);
 	printk("\n");
-	up(&ide_cfg_sem);
+	mutex_unlock(&ide_cfg_mtx);
 	return 0;
 out_unlink:
 	spin_lock_irq(&ide_lock);
@@ -1177,7 +1177,7 @@
 	}
 	spin_unlock_irq(&ide_lock);
 out_up:
-	up(&ide_cfg_sem);
+	mutex_unlock(&ide_cfg_mtx);
 	return 1;
 }
 
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index ea94c9a..fc1d8ae 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -156,7 +156,7 @@
 {
 	ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
 
-	down(&ide_setting_sem);
+	mutex_lock(&ide_setting_mtx);
 	while ((*p) && strcmp((*p)->name, name) < 0)
 		p = &((*p)->next);
 	if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
@@ -177,10 +177,10 @@
 	if (auto_remove)
 		setting->auto_remove = 1;
 	*p = setting;
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 	return 0;
 abort:
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 	kfree(setting);
 	return -1;
 }
@@ -224,7 +224,7 @@
  *
  *	Automatically remove all the driver specific settings for this
  *	drive. This function may not be called from IRQ context. The
- *	caller must hold ide_setting_sem.
+ *	caller must hold ide_setting_mtx.
  */
 
 static void auto_remove_settings (ide_drive_t *drive)
@@ -269,7 +269,7 @@
  *	@setting: drive setting
  *
  *	Read a drive setting and return the value. The caller
- *	must hold the ide_setting_sem when making this call.
+ *	must hold the ide_setting_mtx when making this call.
  *
  *	BUGS: the data return and error are the same return value
  *	so an error -EINVAL and true return of the same value cannot
@@ -306,7 +306,7 @@
  *	@val: value
  *
  *	Write a drive setting if it is possible. The caller
- *	must hold the ide_setting_sem when making this call.
+ *	must hold the ide_setting_mtx when making this call.
  *
  *	BUGS: the data return and error are the same return value
  *	so an error -EINVAL and true return of the same value cannot
@@ -367,7 +367,7 @@
  *	@drive: drive being configured
  *
  *	Add the generic parts of the system settings to the /proc files.
- *	The caller must not be holding the ide_setting_sem.
+ *	The caller must not be holding the ide_setting_mtx.
  */
 
 void ide_add_generic_settings (ide_drive_t *drive)
@@ -408,7 +408,7 @@
 
 	proc_ide_settings_warn();
 
-	down(&ide_setting_sem);
+	mutex_lock(&ide_setting_mtx);
 	out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
 	out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
 	while(setting) {
@@ -428,7 +428,7 @@
 		setting = setting->next;
 	}
 	len = out - page;
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
@@ -508,16 +508,16 @@
 				++p;
 			}
 
-			down(&ide_setting_sem);
+			mutex_lock(&ide_setting_mtx);
 			setting = ide_find_setting_by_name(drive, name);
 			if (!setting)
 			{
-				up(&ide_setting_sem);
+				mutex_unlock(&ide_setting_mtx);
 				goto parse_error;
 			}
 			if (for_real)
 				ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
-			up(&ide_setting_sem);
+			mutex_unlock(&ide_setting_mtx);
 		}
 	} while (!for_real++);
 	free_page((unsigned long)buf);
@@ -705,7 +705,7 @@
  *	Clean up the driver specific /proc files and IDE settings
  *	for a given drive.
  *
- *	Takes ide_setting_sem and ide_lock.
+ *	Takes ide_setting_mtx and ide_lock.
  *	Caller must hold none of the locks.
  */
 
@@ -715,10 +715,10 @@
 
 	ide_remove_proc_entries(drive->proc, driver->proc);
 
-	down(&ide_setting_sem);
+	mutex_lock(&ide_setting_mtx);
 	spin_lock_irqsave(&ide_lock, flags);
 	/*
-	 * ide_setting_sem protects the settings list
+	 * ide_setting_mtx protects the settings list
 	 * ide_lock protects the use of settings
 	 *
 	 * so we need to hold both, ide_settings_sem because we want to
@@ -726,11 +726,11 @@
 	 * a setting out that is being used.
 	 *
 	 * OTOH both ide_{read,write}_setting are only ever used under
-	 * ide_setting_sem.
+	 * ide_setting_mtx.
 	 */
 	auto_remove_settings(drive);
 	spin_unlock_irqrestore(&ide_lock, flags);
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 }
 
 EXPORT_SYMBOL(ide_proc_unregister_driver);
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index c0864b1..e6cb859 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -102,66 +102,16 @@
 #define EZ(v,unit)		((v)?ENOUGH(v,unit):0)
 
 #define XFER_MODE	0xf0
-#define XFER_UDMA_133	0x48
-#define XFER_UDMA_100	0x44
-#define XFER_UDMA_66	0x42
-#define XFER_UDMA	0x40
 #define XFER_MWDMA	0x20
-#define XFER_SWDMA	0x10
 #define XFER_EPIO	0x01
 #define XFER_PIO	0x00
 
-static short ide_find_best_mode(ide_drive_t *drive, int map)
+static short ide_find_best_pio_mode(ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
 	short best = 0;
 
-	if (!id)
-		return XFER_PIO_SLOW;
-
-	if ((map & XFER_UDMA) && (id->field_valid & 4)) {	/* Want UDMA and UDMA bitmap valid */
-
-		if ((map & XFER_UDMA_133) == XFER_UDMA_133)
-			if ((best = (id->dma_ultra & 0x0040) ? XFER_UDMA_6 : 0)) return best;
-
-		if ((map & XFER_UDMA_100) == XFER_UDMA_100)
-			if ((best = (id->dma_ultra & 0x0020) ? XFER_UDMA_5 : 0)) return best;
-
-		if ((map & XFER_UDMA_66) == XFER_UDMA_66)
-			if ((best = (id->dma_ultra & 0x0010) ? XFER_UDMA_4 :
-                	    	    (id->dma_ultra & 0x0008) ? XFER_UDMA_3 : 0)) return best;
-
-                if ((best = (id->dma_ultra & 0x0004) ? XFER_UDMA_2 :
-                	    (id->dma_ultra & 0x0002) ? XFER_UDMA_1 :
-                	    (id->dma_ultra & 0x0001) ? XFER_UDMA_0 : 0)) return best;
-	}
-
-	if ((map & XFER_MWDMA) && (id->field_valid & 2)) {	/* Want MWDMA and drive has EIDE fields */
-
-		if ((best = (id->dma_mword & 0x0004) ? XFER_MW_DMA_2 :
-                	    (id->dma_mword & 0x0002) ? XFER_MW_DMA_1 :
-                	    (id->dma_mword & 0x0001) ? XFER_MW_DMA_0 : 0)) return best;
-	}
-
-	if (map & XFER_SWDMA) {					/* Want SWDMA */
-
- 		if (id->field_valid & 2) {			/* EIDE SWDMA */
-
-			if ((best = (id->dma_1word & 0x0004) ? XFER_SW_DMA_2 :
-      				    (id->dma_1word & 0x0002) ? XFER_SW_DMA_1 :
-				    (id->dma_1word & 0x0001) ? XFER_SW_DMA_0 : 0)) return best;
-		}
-
-		if (id->capability & 1) {			/* Pre-EIDE style SWDMA */
-
-			if ((best = (id->tDMA == 2) ? XFER_SW_DMA_2 :
-				    (id->tDMA == 1) ? XFER_SW_DMA_1 :
-				    (id->tDMA == 0) ? XFER_SW_DMA_0 : 0)) return best;
-		}
-	}
-
-
-	if ((map & XFER_EPIO) && (id->field_valid & 2)) {	/* EIDE PIO modes */
+	if (id->field_valid & 2) {	/* EIDE PIO modes */
 
 		if ((best = (drive->id->eide_pio_modes & 4) ? XFER_PIO_5 :
 			    (drive->id->eide_pio_modes & 2) ? XFER_PIO_4 :
@@ -262,7 +212,7 @@
  */
 
 	if ((speed & XFER_MODE) != XFER_PIO) {
-		ide_timing_compute(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO), &p, T, UT);
+		ide_timing_compute(drive, ide_find_best_pio_mode(drive), &p, T, UT);
 		ide_timing_merge(&p, t, t, IDE_TIMING_ALL);
 	}
 
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 0cd76bf..c948a5c 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -169,7 +169,7 @@
 static int idebus_parameter;	/* holds the "idebus=" parameter */
 static int system_bus_speed;	/* holds what we think is VESA/PCI bus speed */
 
-DECLARE_MUTEX(ide_cfg_sem);
+DEFINE_MUTEX(ide_cfg_mtx);
  __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
 
 #ifdef CONFIG_IDEPCI_PCIBUS_ORDER
@@ -460,6 +460,8 @@
 	hwif->mwdma_mask		= tmp_hwif->mwdma_mask;
 	hwif->swdma_mask		= tmp_hwif->swdma_mask;
 
+	hwif->cbl			= tmp_hwif->cbl;
+
 	hwif->chipset			= tmp_hwif->chipset;
 	hwif->hold			= tmp_hwif->hold;
 
@@ -496,8 +498,8 @@
 	hwif->ide_dma_clear_irq		= tmp_hwif->ide_dma_clear_irq;
 	hwif->dma_host_on		= tmp_hwif->dma_host_on;
 	hwif->dma_host_off		= tmp_hwif->dma_host_off;
-	hwif->ide_dma_lostirq		= tmp_hwif->ide_dma_lostirq;
-	hwif->ide_dma_timeout		= tmp_hwif->ide_dma_timeout;
+	hwif->dma_lost_irq		= tmp_hwif->dma_lost_irq;
+	hwif->dma_timeout		= tmp_hwif->dma_timeout;
 
 	hwif->OUTB			= tmp_hwif->OUTB;
 	hwif->OUTBSYNC			= tmp_hwif->OUTBSYNC;
@@ -533,7 +535,6 @@
 	hwif->extra_base		= tmp_hwif->extra_base;
 	hwif->extra_ports		= tmp_hwif->extra_ports;
 	hwif->autodma			= tmp_hwif->autodma;
-	hwif->udma_four			= tmp_hwif->udma_four;
 
 	hwif->hwif_data			= tmp_hwif->hwif_data;
 }
@@ -564,7 +565,7 @@
 {
 	ide_drive_t *drive;
 	ide_hwif_t *hwif, *g;
-	static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
+	static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */
 	ide_hwgroup_t *hwgroup;
 	int irq_count = 0, unit;
 
@@ -572,7 +573,7 @@
 
 	BUG_ON(in_interrupt());
 	BUG_ON(irqs_disabled());
-	down(&ide_cfg_sem);
+	mutex_lock(&ide_cfg_mtx);
 	spin_lock_irq(&ide_lock);
 	hwif = &ide_hwifs[index];
 	if (!hwif->present)
@@ -679,7 +680,7 @@
 
 abort:
 	spin_unlock_irq(&ide_lock);
-	up(&ide_cfg_sem);
+	mutex_unlock(&ide_cfg_mtx);
 }
 
 EXPORT_SYMBOL(ide_unregister);
@@ -817,9 +818,9 @@
  *	Locks for IDE setting functionality
  */
 
-DECLARE_MUTEX(ide_setting_sem);
+DEFINE_MUTEX(ide_setting_mtx);
 
-EXPORT_SYMBOL_GPL(ide_setting_sem);
+EXPORT_SYMBOL_GPL(ide_setting_mtx);
 
 /**
  *	ide_spin_wait_hwgroup	-	wait for group
@@ -1192,11 +1193,11 @@
 	}
 
 read_val:
-	down(&ide_setting_sem);
+	mutex_lock(&ide_setting_mtx);
 	spin_lock_irqsave(&ide_lock, flags);
 	err = *val;
 	spin_unlock_irqrestore(&ide_lock, flags);
-	up(&ide_setting_sem);
+	mutex_unlock(&ide_setting_mtx);
 	return err >= 0 ? put_user(err, (long __user *)arg) : err;
 
 set_val:
@@ -1206,9 +1207,9 @@
 		if (!capable(CAP_SYS_ADMIN))
 			err = -EACCES;
 		else {
-			down(&ide_setting_sem);
+			mutex_lock(&ide_setting_mtx);
 			err = setfunc(drive, arg);
-			up(&ide_setting_sem);
+			mutex_unlock(&ide_setting_mtx);
 		}
 	}
 	return err;
@@ -1548,7 +1549,11 @@
 				goto bad_option;
 			case -7: /* ata66 */
 #ifdef CONFIG_BLK_DEV_IDEPCI
-				hwif->udma_four = 1;
+				/*
+				 * Use ATA_CBL_PATA40_SHORT so drive side
+				 * cable detection is also overriden.
+				 */
+				hwif->cbl = ATA_CBL_PATA40_SHORT;
 				goto obsolete_option;
 #else
 				goto bad_hwif;
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index 45ed035..7f4c0a5 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/ide/legacy/hd.c
@@ -130,7 +130,7 @@
 	
 #ifdef HD_TYPE
 static struct hd_i_struct hd_info[] = { HD_TYPE };
-static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
+static int NR_HD = ARRAY_SIZE(hd_info);
 #else
 static struct hd_i_struct hd_info[MAX_HD];
 static int NR_HD;
@@ -623,7 +623,8 @@
 	cyl   = track / disk->head;
 #ifdef DEBUG
 	printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
-		req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ",
+		req->rq_disk->disk_name,
+		req_data_dir(req) == READ ? "read" : "writ",
 		cyl, head, sec, nsect, req->buffer);
 #endif
 	if (blk_fs_request(req)) {
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index c211fc7..b557c45 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -77,15 +77,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
-static void macide_mediabay_interrupt(int irq, void *dev_id)
-{
-	int state = baboon->mb_status & 0x04;
-
-	printk(KERN_INFO "macide: media bay %s detected\n", state? "removal":"insertion");
-}
-#endif
-
 /*
  * Probe for a Macintosh IDE interface
  */
@@ -128,11 +119,6 @@
 			ide_drive_t *drive = &ide_hwifs[index].drives[0];
 			drive->capacity64 = drive->cyl*drive->head*drive->sect;
 
-#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
-			request_irq(IRQ_BABOON_2, macide_mediabay_interrupt,
-					IRQ_FLG_FAST, "mediabay",
-					macide_mediabay_interrupt);
-#endif
 		}
 		break;
 
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index ca95e99..2e7013a 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -381,9 +381,7 @@
 
 static int auide_dma_check(ide_drive_t *drive)
 {
-	u8 speed;
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+	u8 speed = ide_max_dma_mode(drive);
 
 	if( dbdma_init_done == 0 ){
 		auide_hwif.white_list = ide_in_drive_list(drive->id,
@@ -394,7 +392,6 @@
 		auide_ddma_init(&auide_hwif);
 		dbdma_init_done = 1;
 	}
-#endif
 
 	/* Is the drive in our DMA black list? */
 
@@ -409,8 +406,6 @@
 	else
 		drive->using_dma = 1;
 
-	speed = ide_find_best_mode(drive, XFER_PIO | XFER_MWDMA);
-	
 	if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
 		return 0;
 
@@ -456,10 +451,9 @@
 	drive->using_dma = 0;
 }
 
-static int auide_dma_lostirq(ide_drive_t *drive)
+static void auide_dma_lost_irq(ide_drive_t *drive)
 {
 	printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-	return 0;
 }
 
 static void auide_ddma_tx_callback(int irq, void *param)
@@ -489,16 +483,16 @@
   
 #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
 
-static int auide_dma_timeout(ide_drive_t *drive)
+static void auide_dma_timeout(ide_drive_t *drive)
 {
-//      printk("%s\n", __FUNCTION__);
+	ide_hwif_t *hwif = HWIF(drive);
 
 	printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
 
-	if (HWIF(drive)->ide_dma_test_irq(drive))
-		return 0;
+	if (hwif->ide_dma_test_irq(drive))
+		return;
 
-	return HWIF(drive)->ide_dma_end(drive);
+	hwif->ide_dma_end(drive);
 }
 					
 
@@ -721,7 +715,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
 	hwif->dma_off_quietly		= &auide_dma_off_quietly;
-	hwif->ide_dma_timeout           = &auide_dma_timeout;
+	hwif->dma_timeout		= &auide_dma_timeout;
 
 	hwif->ide_dma_check             = &auide_dma_check;
 	hwif->dma_exec_cmd              = &auide_dma_exec_cmd;
@@ -731,7 +725,7 @@
 	hwif->ide_dma_test_irq          = &auide_dma_test_irq;
 	hwif->dma_host_off		= &auide_dma_host_off;
 	hwif->dma_host_on		= &auide_dma_host_on;
-	hwif->ide_dma_lostirq           = &auide_dma_lostirq;
+	hwif->dma_lost_irq		= &auide_dma_lost_irq;
 	hwif->ide_dma_on                = &auide_dma_on;
 
 	hwif->autodma                   = 1;
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index b173bc6..e5d0936 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/aec62xx.c		Version 0.21	Apr 21, 2007
+ * linux/drivers/ide/pci/aec62xx.c		Version 0.24	May 24, 2007
  *
  * Copyright (C) 1999-2002	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2007		MontaVista Software, Inc. <source@mvista.com>
@@ -140,25 +140,10 @@
 	return(ide_config_drive_speed(drive, speed));
 }
 
-static int aec62xx_tune_chipset (ide_drive_t *drive, u8 speed)
-{
-	switch (HWIF(drive)->pci_dev->device) {
-		case PCI_DEVICE_ID_ARTOP_ATP865:
-		case PCI_DEVICE_ID_ARTOP_ATP865R:
-		case PCI_DEVICE_ID_ARTOP_ATP860:
-		case PCI_DEVICE_ID_ARTOP_ATP860R:
-			return ((int) aec6260_tune_chipset(drive, speed));
-		case PCI_DEVICE_ID_ARTOP_ATP850UF:
-			return ((int) aec6210_tune_chipset(drive, speed));
-		default:
-			return -1;
-	}
-}
-
 static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio)
 {
 	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
-	(void) aec62xx_tune_chipset(drive, pio + XFER_PIO_0);
+	(void) HWIF(drive)->speedproc(drive, pio + XFER_PIO_0);
 }
 
 static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
@@ -172,12 +157,9 @@
 	return -1;
 }
 
-static int aec62xx_irq_timeout (ide_drive_t *drive)
+static void aec62xx_dma_lost_irq (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
-
-	switch(dev->device) {
+	switch (HWIF(drive)->pci_dev->device) {
 		case PCI_DEVICE_ID_ARTOP_ATP860:
 		case PCI_DEVICE_ID_ARTOP_ATP860R:
 		case PCI_DEVICE_ID_ARTOP_ATP865:
@@ -186,7 +168,6 @@
 		default:
 			break;
 	}
-	return 0;
 }
 
 static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
@@ -224,64 +205,46 @@
 
 static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *dev	= hwif->pci_dev;
+	u8 reg54 = 0,  mask	= hwif->channel ? 0xf0 : 0x0f;
+	unsigned long flags;
 
-	hwif->autodma = 0;
 	hwif->tuneproc = &aec62xx_tune_drive;
-	hwif->speedproc = &aec62xx_tune_chipset;
 
-	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
-		hwif->serialized = hwif->channel;
-
-	if (hwif->mate)
-		hwif->mate->serialized = hwif->serialized;
+	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+		if(hwif->mate)
+			hwif->mate->serialized = hwif->serialized = 1;
+		hwif->speedproc = &aec6210_tune_chipset;
+	} else
+		hwif->speedproc = &aec6260_tune_chipset;
 
 	if (!hwif->dma_base) {
-		hwif->drives[0].autotune = 1;
-		hwif->drives[1].autotune = 1;
+		hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
 		return;
 	}
 
 	hwif->ultra_mask = hwif->cds->udma_mask;
-
-	/* atp865 and atp865r */
-	if (hwif->ultra_mask == 0x3f) {
-		/* check bit 0x10 of DMA status register */
-		if (inb(pci_resource_start(dev, 4) + 2) & 0x10)
- 			hwif->ultra_mask = 0x7f; /* udma0-6 */
-	}
-
 	hwif->mwdma_mask = 0x07;
 
 	hwif->ide_dma_check	= &aec62xx_config_drive_xfer_rate;
-	hwif->ide_dma_lostirq	= &aec62xx_irq_timeout;
+	hwif->dma_lost_irq	= &aec62xx_dma_lost_irq;
+
+	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+		spin_lock_irqsave(&ide_lock, flags);
+		pci_read_config_byte (dev, 0x54, &reg54);
+		pci_write_config_byte(dev, 0x54, (reg54 & ~mask));
+		spin_unlock_irqrestore(&ide_lock, flags);
+	} else if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+		u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
+
+		pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
+
+		hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+	}
 
 	if (!noautodma)
 		hwif->autodma = 1;
-	hwif->drives[0].autodma = hwif->autodma;
-	hwif->drives[1].autodma = hwif->autodma;
-}
-
-static void __devinit init_dma_aec62xx(ide_hwif_t *hwif, unsigned long dmabase)
-{
-	struct pci_dev *dev	= hwif->pci_dev;
-
-	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
-		u8 reg54h = 0;
-		unsigned long flags;
-
-		spin_lock_irqsave(&ide_lock, flags);
-		pci_read_config_byte(dev, 0x54, &reg54h);
-		pci_write_config_byte(dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F));
-		spin_unlock_irqrestore(&ide_lock, flags);
-	} else {
-		u8 ata66	= 0;
-		pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
-	        if (!(hwif->udma_four))
-			hwif->udma_four = (ata66&(hwif->channel?0x02:0x01))?0:1;
-	}
-
-	ide_setup_dma(hwif, dmabase, 8);
+	hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
 }
 
 static int __devinit init_setup_aec62xx(struct pci_dev *dev, ide_pci_device_t *d)
@@ -291,16 +254,12 @@
 
 static int __devinit init_setup_aec6x80(struct pci_dev *dev, ide_pci_device_t *d)
 {
-	unsigned long bar4reg = pci_resource_start(dev, 4);
+	unsigned long dma_base = pci_resource_start(dev, 4);
 
-	if (inb(bar4reg+2) & 0x10) {
-		strcpy(d->name, "AEC6880");
-		if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
-			strcpy(d->name, "AEC6880R");
-	} else {
-		strcpy(d->name, "AEC6280");
-		if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
-			strcpy(d->name, "AEC6280R");
+	if (inb(dma_base + 2) & 0x10) {
+		d->name = (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) ?
+			  "AEC6880R" : "AEC6880";
+		d->udma_mask = 0x7f; /* udma0-6 */
 	}
 
 	return ide_setup_pci_device(dev, d);
@@ -312,7 +271,6 @@
 		.init_setup	= init_setup_aec62xx,
 		.init_chipset	= init_chipset_aec62xx,
 		.init_hwif	= init_hwif_aec62xx,
-		.init_dma	= init_dma_aec62xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
@@ -323,7 +281,6 @@
 		.init_setup	= init_setup_aec62xx,
 		.init_chipset	= init_chipset_aec62xx,
 		.init_hwif	= init_hwif_aec62xx,
-		.init_dma	= init_dma_aec62xx,
 		.channels	= 2,
 		.autodma	= NOAUTODMA,
 		.bootable	= OFF_BOARD,
@@ -333,28 +290,25 @@
 		.init_setup	= init_setup_aec62xx,
 		.init_chipset	= init_chipset_aec62xx,
 		.init_hwif	= init_hwif_aec62xx,
-		.init_dma	= init_dma_aec62xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
 		.bootable	= NEVER_BOARD,
 		.udma_mask	= 0x1f, /* udma0-4 */
 	},{	/* 3 */
-		.name		= "AEC6X80",
+		.name		= "AEC6280",
 		.init_setup	= init_setup_aec6x80,
 		.init_chipset	= init_chipset_aec62xx,
 		.init_hwif	= init_hwif_aec62xx,
-		.init_dma	= init_dma_aec62xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.bootable	= OFF_BOARD,
 		.udma_mask	= 0x3f, /* udma0-5 */
 	},{	/* 4 */
-		.name		= "AEC6X80R",
+		.name		= "AEC6280R",
 		.init_setup	= init_setup_aec6x80,
 		.init_chipset	= init_chipset_aec62xx,
 		.init_hwif	= init_hwif_aec62xx,
-		.init_dma	= init_dma_aec62xx,
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
@@ -370,13 +324,16 @@
  *
  *	Called when the PCI registration layer (or the IDE initialization)
  *	finds a device matching our IDE device tables.
+ *
+ *	NOTE: since we're going to modify the 'name' field for AEC-6[26]80[R]
+ *	chips, pass a local copy of 'struct pci_device_id' down the call chain.
  */
  
 static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	ide_pci_device_t *d = &aec62xx_chipsets[id->driver_data];
+	ide_pci_device_t d = aec62xx_chipsets[id->driver_data];
 
-	return d->init_setup(dev, d);
+	return d.init_setup(dev, &d);
 }
 
 static struct pci_device_id aec62xx_pci_tbl[] = {
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 27525ec..8a6b27b 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/alim15x3.c		Version 0.21	2007/02/03
+ * linux/drivers/ide/pci/alim15x3.c		Version 0.25	Jun 9 2007
  *
  *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
  *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
@@ -10,6 +10,7 @@
  *  Copyright (C) 2002 Alan Cox <alan@redhat.com>
  *  ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
  *  Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
+ *  Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
  *
  *  (U)DMA capable version of ali 1533/1543(C), 1535(D)
  *
@@ -36,6 +37,7 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/init.h>
+#include <linux/dmi.h>
 
 #include <asm/io.h>
 
@@ -583,6 +585,35 @@
 	return 0;
 }
 
+/*
+ *	Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+	{
+		.ident = "HP Pavilion N5430",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_BOARD_NAME, "OmniBook N32N-736"),
+		},
+	},
+	{ }
+};
+
+static int ali_cable_override(struct pci_dev *pdev)
+{
+	/* Fujitsu P2000 */
+	if (pdev->subsystem_vendor == 0x10CF &&
+	    pdev->subsystem_device == 0x10AF)
+		return 1;
+
+	/* Systems by DMI */
+	if (dmi_check_system(cable_dmi_table))
+		return 1;
+
+	return 0;
+}
+
 /**
  *	ata66_ali15x3	-	check for UDMA 66 support
  *	@hwif: IDE interface
@@ -594,37 +625,31 @@
  *	FIXME: frobs bits that are not defined on newer ALi devicea
  */
 
-static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
+static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
-	unsigned int ata66	= 0;
-	u8 cable_80_pin[2]	= { 0, 0 };
-
 	unsigned long flags;
-	u8 tmpbyte;
+	u8 cbl = ATA_CBL_PATA40, tmpbyte;
 
 	local_irq_save(flags);
 
 	if (m5229_revision >= 0xC2) {
 		/*
-		 * Ultra66 cable detection (from Host View)
-		 * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin
+		 * m5229 80-pin cable detection (from Host View)
+		 *
+		 * 0x4a bit0 is 0 => primary channel has 80-pin
+		 * 0x4a bit1 is 0 => secondary channel has 80-pin
+		 *
+		 * Certain laptops use short but suitable cables
+		 * and don't implement the detect logic.
 		 */
-		pci_read_config_byte(dev, 0x4a, &tmpbyte);
-		/*
-		 * 0x4a, bit0 is 0 => primary channel
-		 * has 80-pin (from host view)
-		 */
-		if (!(tmpbyte & 0x01)) cable_80_pin[0] = 1;
-		/*
-		 * 0x4a, bit1 is 0 => secondary channel
-		 * has 80-pin (from host view)
-		 */
-		if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1;
-		/*
-		 * Allow ata66 if cable of current channel has 80 pins
-		 */
-		ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0];
+		if (ali_cable_override(dev))
+			cbl = ATA_CBL_PATA40_SHORT;
+		else {
+			pci_read_config_byte(dev, 0x4a, &tmpbyte);
+			if ((tmpbyte & (1 << hwif->channel)) == 0)
+				cbl = ATA_CBL_PATA80;
+		}
 	} else {
 		/*
 		 * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
@@ -657,7 +682,7 @@
 
 	local_irq_restore(flags);
 
-	return(ata66);
+	return cbl;
 }
 
 /**
@@ -708,8 +733,9 @@
 		hwif->dma_setup = &ali15x3_dma_setup;
 		if (!noautodma)
 			hwif->autodma = 1;
-		if (!(hwif->udma_four))
-			hwif->udma_four = ata66_ali15x3(hwif);
+
+		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+			hwif->cbl = ata66_ali15x3(hwif);
 	}
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index a2be65fc..84ed30c 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -1,10 +1,11 @@
 /*
- * Version 2.16
+ * Version 2.20
  *
  * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
  * IDE driver for Linux.
  *
  * Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
  *
  * Based on the work of:
  *      Andre Hedrick
@@ -37,11 +38,6 @@
 #define AMD_ADDRESS_SETUP	(0x0c + amd_config->base)
 #define AMD_UDMA_TIMING		(0x10 + amd_config->base)
 
-#define AMD_UDMA		0x07
-#define AMD_UDMA_33		0x01
-#define AMD_UDMA_66		0x02
-#define AMD_UDMA_100		0x03
-#define AMD_UDMA_133		0x04
 #define AMD_CHECK_SWDMA		0x08
 #define AMD_BAD_SWDMA		0x10
 #define AMD_BAD_FIFO		0x20
@@ -53,32 +49,33 @@
 
 static struct amd_ide_chip {
 	unsigned short id;
-	unsigned long base;
-	unsigned char flags;
+	u8 base;
+	u8 udma_mask;
+	u8 flags;
 } amd_ide_chips[] = {
-	{ PCI_DEVICE_ID_AMD_COBRA_7401,		0x40, AMD_UDMA_33 | AMD_BAD_SWDMA },
-	{ PCI_DEVICE_ID_AMD_VIPER_7409,		0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA },
-	{ PCI_DEVICE_ID_AMD_VIPER_7411,		0x40, AMD_UDMA_100 | AMD_BAD_FIFO },
-	{ PCI_DEVICE_ID_AMD_OPUS_7441,		0x40, AMD_UDMA_100 },
-	{ PCI_DEVICE_ID_AMD_8111_IDE,		0x40, AMD_UDMA_133 | AMD_CHECK_SERENADE },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,	0x50, AMD_UDMA_100 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE,	0x50, AMD_UDMA_133 },
-	{ PCI_DEVICE_ID_AMD_CS5536_IDE,			0x40, AMD_UDMA_100 },
+	{ PCI_DEVICE_ID_AMD_COBRA_7401,		 0x40, ATA_UDMA2, AMD_BAD_SWDMA },
+	{ PCI_DEVICE_ID_AMD_VIPER_7409,		 0x40, ATA_UDMA4, AMD_CHECK_SWDMA },
+	{ PCI_DEVICE_ID_AMD_VIPER_7411,		 0x40, ATA_UDMA5, AMD_BAD_FIFO },
+	{ PCI_DEVICE_ID_AMD_OPUS_7441,		 0x40, ATA_UDMA5, },
+	{ PCI_DEVICE_ID_AMD_8111_IDE,		 0x40, ATA_UDMA6, AMD_CHECK_SERENADE },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,	 0x50, ATA_UDMA5, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, ATA_UDMA6, },
+	{ PCI_DEVICE_ID_AMD_CS5536_IDE,		 0x40, ATA_UDMA5, },
 	{ 0 }
 };
 
@@ -87,7 +84,7 @@
 static unsigned int amd_80w;
 static unsigned int amd_clock;
 
-static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
 static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
 
 /*
@@ -128,7 +125,7 @@
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &t);
 	amd_print("Revision:                           IDE %#x", t);
-	amd_print("Highest DMA rate:                   %s", amd_dma[amd_config->flags & AMD_UDMA]);
+	amd_print("Highest DMA rate:                   UDMA%s", amd_dma[fls(amd_config->udma_mask) - 1]);
 
 	amd_print("BM-DMA base:                        %#lx", amd_base);
 	amd_print("PCI clock:                          %d.%dMHz", amd_clock / 1000, amd_clock / 100 % 10);
@@ -221,12 +218,12 @@
 	pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn),
 		((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
 
-	switch (amd_config->flags & AMD_UDMA) {
-		case AMD_UDMA_33:  t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
-		case AMD_UDMA_66:  t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
-		case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
-		case AMD_UDMA_133: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
-		default: return;
+	switch (amd_config->udma_mask) {
+	case ATA_UDMA2: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+	case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
+	case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
+	case ATA_UDMA6: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
+	default: return;
 	}
 
 	pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t);
@@ -248,7 +245,7 @@
 		ide_config_drive_speed(drive, speed);
 
 	T = 1000000000 / amd_clock;
-	UT = T / min_t(int, max_t(int, amd_config->flags & AMD_UDMA, 1), 2);
+	UT = (amd_config->udma_mask == ATA_UDMA2) ? T : (T / 2);
 
 	ide_timing_compute(drive, speed, &t, T, UT);
 
@@ -277,29 +274,19 @@
 static void amd74xx_tune_drive(ide_drive_t *drive, u8 pio)
 {
 	if (pio == 255) {
-		amd_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+		amd_set_drive(drive, ide_find_best_pio_mode(drive));
 		return;
 	}
 
 	amd_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
 }
 
-/*
- * amd74xx_dmaproc() is a callback from upper layers that can do
- * a lot, but we use it for DMA/PIO tuning only, delegating everything
- * else to the default ide_dmaproc().
- */
-
 static int amd74xx_ide_dma_check(ide_drive_t *drive)
 {
-	int w80 = HWIF(drive)->udma_four;
+	u8 speed = ide_max_dma_mode(drive);
 
-	u8 speed = ide_find_best_mode(drive,
-		XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
-		((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) |
-		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) |
-		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0) |
-		(w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_133 ? XFER_UDMA_133 : 0));
+	if (speed == 0)
+		speed = ide_find_best_pio_mode(drive);
 
 	amd_set_drive(drive, speed);
 
@@ -334,10 +321,10 @@
  * Check 80-wire cable presence.
  */
 
-	switch (amd_config->flags & AMD_UDMA) {
+	switch (amd_config->udma_mask) {
 
-		case AMD_UDMA_133:
-		case AMD_UDMA_100:
+		case ATA_UDMA6:
+		case ATA_UDMA5:
 			pci_read_config_byte(dev, AMD_CABLE_DETECT, &t);
 			pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
 			amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
@@ -349,7 +336,7 @@
 				}
 			break;
 
-		case AMD_UDMA_66:
+		case ATA_UDMA4:
 			/* no host side cable detection */
 			amd_80w = 0x03;
 			break;
@@ -370,7 +357,7 @@
 	if ((amd_config->flags & AMD_CHECK_SERENADE) &&
 		dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
 		dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
-			amd_config->flags = AMD_UDMA_100;
+			amd_config->udma_mask = ATA_UDMA5;
 
 /*
  * Determine the system bus clock.
@@ -395,8 +382,9 @@
  */
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &t);
-	printk(KERN_INFO "%s: %s (rev %02x) %s controller\n",
-		amd_chipset->name, pci_name(dev), t, amd_dma[amd_config->flags & AMD_UDMA]);
+	printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
+		amd_chipset->name, pci_name(dev), t,
+		amd_dma[fls(amd_config->udma_mask) - 1]);
 
 /*
  * Register /proc/ide/amd74xx entry
@@ -437,12 +425,19 @@
 		return;
 
         hwif->atapi_dma = 1;
-        hwif->ultra_mask = 0x7f;
-        hwif->mwdma_mask = 0x07;
-        hwif->swdma_mask = 0x07;
 
-	if (!hwif->udma_four)
-		hwif->udma_four = (amd_80w >> hwif->channel) & 1;
+	hwif->ultra_mask = amd_config->udma_mask;
+	hwif->mwdma_mask = 0x07;
+	if ((amd_config->flags & AMD_BAD_SWDMA) == 0)
+		hwif->swdma_mask = 0x07;
+
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+		if ((amd_80w >> hwif->channel) & 1)
+			hwif->cbl = ATA_CBL_PATA80;
+		else
+			hwif->cbl = ATA_CBL_PATA40;
+	}
+
         hwif->ide_dma_check = &amd74xx_ide_dma_check;
         if (!noautodma)
                 hwif->autodma = 1;
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 8ab33fa..2761510 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -264,10 +264,11 @@
 	hwif->swdma_mask = 0x04;
 
 	pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
+
 	if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
-		hwif->udma_four = 1;
+		hwif->cbl = ATA_CBL_PATA80;
 	else
-		hwif->udma_four = 0;
+		hwif->cbl = ATA_CBL_PATA40;
 
 	hwif->dma_host_on = &atiixp_dma_host_on;
 	hwif->dma_host_off = &atiixp_dma_host_off;
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 7c57dc6..8631b6c 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/cmd64x.c		Version 1.47	Mar 19, 2007
+ * linux/drivers/ide/pci/cmd64x.c		Version 1.50	May 10, 2007
  *
  * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
  *           Due to massive hardware bugs, UltraDMA is only supported
@@ -52,9 +52,6 @@
 #define   ARTTIM23_DIS_RA2	0x04
 #define   ARTTIM23_DIS_RA3	0x08
 #define   ARTTIM23_INTR_CH1	0x10
-#define ARTTIM2		0x57
-#define ARTTIM3		0x57
-#define DRWTIM23	0x58
 #define DRWTIM2		0x58
 #define BRST		0x59
 #define DRWTIM3		0x5b
@@ -469,71 +466,43 @@
 
 static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const char *name)
 {
-	u32 class_rev = 0;
 	u8 mrdmode = 0;
 
-	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
-	class_rev &= 0xff;
+	if (dev->device == PCI_DEVICE_ID_CMD_646) {
+		u8 rev = 0;
 
-	switch(dev->device) {
-		case PCI_DEVICE_ID_CMD_643:
+		pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+
+		switch (rev) {
+		case 0x07:
+		case 0x05:
+			printk("%s: UltraDMA capable", name);
 			break;
-		case PCI_DEVICE_ID_CMD_646:
-			printk(KERN_INFO "%s: chipset revision 0x%02X, ", name, class_rev);
-			switch(class_rev) {
-				case 0x07:
-				case 0x05:
-					printk("UltraDMA Capable");
-					break;
-				case 0x03:
-					printk("MultiWord DMA Force Limited");
-					break;
-				case 0x01:
-				default:
-					printk("MultiWord DMA Limited, IRQ workaround enabled");
-					break;
-				}
-			printk("\n");
-                        break;
-		case PCI_DEVICE_ID_CMD_648:
-		case PCI_DEVICE_ID_CMD_649:
-			break;
+		case 0x03:
 		default:
+			printk("%s: MultiWord DMA force limited", name);
 			break;
+		case 0x01:
+			printk("%s: MultiWord DMA limited, "
+			       "IRQ workaround enabled\n", name);
+			break;
+		}
 	}
 
 	/* Set a good latency timer and cache line size value. */
 	(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
 	/* FIXME: pci_set_master() to ensure a good latency timer value */
 
-	/* Setup interrupts. */
-	(void) pci_read_config_byte(dev, MRDMODE, &mrdmode);
-	mrdmode &= ~(0x30);
-	(void) pci_write_config_byte(dev, MRDMODE, mrdmode);
-
-	/* Use MEMORY READ LINE for reads.
-	 * NOTE: Although not mentioned in the PCI0646U specs,
-	 *       these bits are write only and won't be read
-	 *       back as set or not.  The PCI0646U2 specs clarify
-	 *       this point.
+	/*
+	 * Enable interrupts, select MEMORY READ LINE for reads.
+	 *
+	 * NOTE: although not mentioned in the PCI0646U specs,
+	 * bits 0-1 are write only and won't be read back as
+	 * set or not -- PCI0646U2 specs clarify this point.
 	 */
-	(void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02);
-
-	/* Set reasonable active/recovery/address-setup values. */
-	(void) pci_write_config_byte(dev, ARTTIM0,  0x40);
-	(void) pci_write_config_byte(dev, DRWTIM0,  0x3f);
-	(void) pci_write_config_byte(dev, ARTTIM1,  0x40);
-	(void) pci_write_config_byte(dev, DRWTIM1,  0x3f);
-#ifdef __i386__
-	(void) pci_write_config_byte(dev, ARTTIM23, 0x1c);
-#else
-	(void) pci_write_config_byte(dev, ARTTIM23, 0x5c);
-#endif
-	(void) pci_write_config_byte(dev, DRWTIM23, 0x3f);
-	(void) pci_write_config_byte(dev, DRWTIM3,  0x3f);
-#ifdef CONFIG_PPC
-	(void) pci_write_config_byte(dev, UDIDETCR0, 0xf0);
-#endif /* CONFIG_PPC */
+	(void) pci_read_config_byte (dev, MRDMODE, &mrdmode);
+	mrdmode &= ~0x30;
+	(void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));
 
 #if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
 
@@ -548,29 +517,27 @@
 	return 0;
 }
 
-static unsigned int __devinit ata66_cmd64x(ide_hwif_t *hwif)
+static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
 {
-	u8 ata66 = 0, mask = (hwif->channel) ? 0x02 : 0x01;
+	struct pci_dev  *dev	= hwif->pci_dev;
+	u8 bmidecsr = 0, mask	= hwif->channel ? 0x02 : 0x01;
 
-	switch(hwif->pci_dev->device) {
-		case PCI_DEVICE_ID_CMD_643:
-		case PCI_DEVICE_ID_CMD_646:
-			return ata66;
-		default:
-			break;
+	switch (dev->device) {
+	case PCI_DEVICE_ID_CMD_648:
+	case PCI_DEVICE_ID_CMD_649:
+ 		pci_read_config_byte(dev, BMIDECSR, &bmidecsr);
+		return (bmidecsr & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+	default:
+		return ATA_CBL_PATA40;
 	}
-	pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66);
-	return (ata66 & mask) ? 1 : 0;
 }
 
 static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
-	unsigned int class_rev;
+	u8 rev			= 0;
 
-	hwif->autodma = 0;
-	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
-	class_rev &= 0xff;
+	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
 
 	hwif->tuneproc  = &cmd64x_tune_drive;
 	hwif->speedproc = &cmd64x_tune_chipset;
@@ -580,8 +547,8 @@
 	if (!hwif->dma_base)
 		return;
 
-	hwif->atapi_dma = 1;
-
+	hwif->atapi_dma  = 1;
+	hwif->mwdma_mask = 0x07;
 	hwif->ultra_mask = hwif->cds->udma_mask;
 
 	/*
@@ -596,16 +563,15 @@
 	 *
 	 * So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
 	 */
-	if (dev->device == PCI_DEVICE_ID_CMD_646 && class_rev < 5)
+	if (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 5)
 		hwif->ultra_mask = 0x00;
 
-	hwif->mwdma_mask = 0x07;
-
 	hwif->ide_dma_check = &cmd64x_config_drive_for_dma;
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_cmd64x(hwif);
 
-	switch(dev->device) {
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = ata66_cmd64x(hwif);
+
+	switch (dev->device) {
 	case PCI_DEVICE_ID_CMD_648:
 	case PCI_DEVICE_ID_CMD_649:
 	alt_irq_bits:
@@ -614,10 +580,10 @@
 		break;
 	case PCI_DEVICE_ID_CMD_646:
 		hwif->chipset = ide_cmd646;
-		if (class_rev == 0x01) {
+		if (rev == 0x01) {
 			hwif->ide_dma_end = &cmd646_1_ide_dma_end;
 			break;
-		} else if (class_rev >= 0x03)
+		} else if (rev >= 0x03)
 			goto alt_irq_bits;
 		/* fall thru */
 	default:
@@ -626,11 +592,9 @@
 		break;
 	}
 
-
 	if (!noautodma)
 		hwif->autodma = 1;
-	hwif->drives[0].autodma = hwif->autodma;
-	hwif->drives[1].autodma = hwif->autodma;
+	hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
 }
 
 static int __devinit init_setup_cmd64x(struct pci_dev *dev, ide_pci_device_t *d)
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 41925c4..10f61f3 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -187,7 +187,8 @@
 
 	/* if a 80 wire cable was detected */
 	pci_read_config_byte(dev, CS5535_CABLE_DETECT, &bit);
-	return (bit & 1);
+
+	return (bit & 1) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
 /****
@@ -212,8 +213,7 @@
 	hwif->ultra_mask = 0x1F;
 	hwif->mwdma_mask = 0x07;
 
-
-	hwif->udma_four = cs5535_cable_detect(hwif->pci_dev);
+	hwif->cbl = cs5535_cable_detect(hwif->pci_dev);
 
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index c33d0b0..4b6bae8 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/hpt366.c		Version 1.06	Jun 27, 2007
+ * linux/drivers/ide/pci/hpt366.c		Version 1.10	Jun 29, 2007
  *
  * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
@@ -77,7 +77,7 @@
  *   since they may tamper with its fields
  * - prefix the driver startup messages with the real chip name
  * - claim the extra 240 bytes of I/O space for all chips
- * - optimize the rate masking/filtering and the drive list lookup code
+ * - optimize the UltraDMA filtering and the drive list lookup code
  * - use pci_get_slot() to get to the function 1 of HPT36x/374
  * - cache offset of the channel's misc. control registers (MCRs) being used
  *   throughout the driver
@@ -99,9 +99,9 @@
  *   stop duplicating it for each channel by storing the pointer in the pci_dev
  *   structure: first, at the init_setup stage, point it to a static "template"
  *   with only the chip type and its specific base DPLL frequency, the highest
- *   supported DMA mode, and the chip settings table pointer filled, then, at
- *   the init_chipset stage, allocate per-chip instance  and fill it with the
- *   rest of the necessary information
+ *   UltraDMA mode, and the chip settings table pointer filled,  then, at the
+ *   init_chipset stage, allocate per-chip instance  and fill it with the rest
+ *   of the necessary information
  * - get rid of the constant thresholds in the HPT37x PCI clock detection code,
  *   switch  to calculating  PCI clock frequency based on the chip's base DPLL
  *   frequency
@@ -112,6 +112,7 @@
  *   also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
  *   unify HPT36x/37x timing setup code and the speedproc handlers by joining
  *   the register setting lists into the table indexed by the clock selected
+ * - set the correct hwif->ultra_mask for each individual chip
  *	Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
  */
 
@@ -391,7 +392,7 @@
 
 struct hpt_info {
 	u8 chip_type;		/* Chip type */
-	u8 max_mode;		/* Speeds allowed */
+	u8 max_ultra;		/* Max. UltraDMA mode allowed */
 	u8 dpll_clk;		/* DPLL clock in MHz */
 	u8 pci_clk;		/* PCI  clock in MHz */
 	u32 **settings; 	/* Chipset settings table */
@@ -430,77 +431,77 @@
 
 static struct hpt_info hpt36x __devinitdata = {
 	.chip_type	= HPT36x,
-	.max_mode	= (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1,
+	.max_ultra	= HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? 4 : 3) : 2,
 	.dpll_clk	= 0,	/* no DPLL */
 	.settings	= hpt36x_settings
 };
 
 static struct hpt_info hpt370 __devinitdata = {
 	.chip_type	= HPT370,
-	.max_mode	= HPT370_ALLOW_ATA100_5 ? 3 : 2,
+	.max_ultra	= HPT370_ALLOW_ATA100_5 ? 5 : 4,
 	.dpll_clk	= 48,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt370a __devinitdata = {
 	.chip_type	= HPT370A,
-	.max_mode	= HPT370_ALLOW_ATA100_5 ? 3 : 2,
+	.max_ultra	= HPT370_ALLOW_ATA100_5 ? 5 : 4,
 	.dpll_clk	= 48,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt374 __devinitdata = {
 	.chip_type	= HPT374,
-	.max_mode	= 3,
+	.max_ultra	= 5,
 	.dpll_clk	= 48,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt372 __devinitdata = {
 	.chip_type	= HPT372,
-	.max_mode	= HPT372_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT372_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 55,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt372a __devinitdata = {
 	.chip_type	= HPT372A,
-	.max_mode	= HPT372_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT372_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 66,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt302 __devinitdata = {
 	.chip_type	= HPT302,
-	.max_mode	= HPT302_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT372_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 66,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt371 __devinitdata = {
 	.chip_type	= HPT371,
-	.max_mode	= HPT371_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT371_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 66,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt372n __devinitdata = {
 	.chip_type	= HPT372N,
-	.max_mode	= HPT372_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT372_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 77,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt302n __devinitdata = {
 	.chip_type	= HPT302N,
-	.max_mode	= HPT302_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT302_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 77,
 	.settings	= hpt37x_settings
 };
 
 static struct hpt_info hpt371n __devinitdata = {
 	.chip_type	= HPT371N,
-	.max_mode	= HPT371_ALLOW_ATA133_6 ? 4 : 3,
+	.max_ultra	= HPT371_ALLOW_ATA133_6 ? 6 : 5,
 	.dpll_clk	= 77,
 	.settings	= hpt37x_settings
 };
@@ -523,53 +524,38 @@
 static u8 hpt3xx_udma_filter(ide_drive_t *drive)
 {
 	struct hpt_info *info	= pci_get_drvdata(HWIF(drive)->pci_dev);
-	u8 chip_type		= info->chip_type;
-	u8 mode			= info->max_mode;
 	u8 mask;
 
-	switch (mode) {
-		case 0x04:
-			mask = 0x7f;
-			break;
-		case 0x03:
+	switch (info->chip_type) {
+	case HPT370A:
+		if (!HPT370_ALLOW_ATA100_5 ||
+		    check_in_drive_list(drive, bad_ata100_5))
+			return 0x1f;
+		else
+			return 0x3f;
+	case HPT370:
+		if (!HPT370_ALLOW_ATA100_5 ||
+		    check_in_drive_list(drive, bad_ata100_5))
+			mask = 0x1f;
+		else
 			mask = 0x3f;
-			if (chip_type >= HPT374)
-				break;
-			if (!check_in_drive_list(drive, bad_ata100_5))
-				goto check_bad_ata33;
-			/* fall thru */
-		case 0x02:
+		break;
+	case HPT36x:
+		if (!HPT366_ALLOW_ATA66_4 ||
+		    check_in_drive_list(drive, bad_ata66_4))
+			mask = 0x0f;
+		else
 			mask = 0x1f;
 
-			/*
-			 * CHECK ME, Does this need to be changed to HPT374 ??
-			 */
-			if (chip_type >= HPT370)
-				goto check_bad_ata33;
-			if (HPT366_ALLOW_ATA66_4 &&
-			    !check_in_drive_list(drive, bad_ata66_4))
-				goto check_bad_ata33;
-
-			mask = 0x0f;
-			if (HPT366_ALLOW_ATA66_3 &&
-			    !check_in_drive_list(drive, bad_ata66_3))
-				goto check_bad_ata33;
-			/* fall thru */
-		case 0x01:
+		if (!HPT366_ALLOW_ATA66_3 ||
+		    check_in_drive_list(drive, bad_ata66_3))
 			mask = 0x07;
-
-		check_bad_ata33:
-			if (chip_type >= HPT370A)
-				break;
-			if (!check_in_drive_list(drive, bad_ata33))
-				break;
-			/* fall thru */
-		case 0x00:
-		default:
-			mask = 0x00;
-			break;
+		break;
+	default:
+		return 0x7f;
 	}
-	return mask;
+
+	return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;
 }
 
 static u32 get_speed_setting(u8 speed, struct hpt_info *info)
@@ -737,7 +723,7 @@
  * This is specific to the HPT366 UDMA chipset
  * by HighPoint|Triones Technologies, Inc.
  */
-static int hpt366_ide_dma_lostirq(ide_drive_t *drive)
+static void hpt366_dma_lost_irq(ide_drive_t *drive)
 {
 	struct pci_dev *dev = HWIF(drive)->pci_dev;
 	u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
@@ -749,7 +735,7 @@
 		drive->name, __FUNCTION__, mcr1, mcr3, scr1);
 	if (scr1 & 0x10)
 		pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
-	return __ide_dma_lostirq(drive);
+	ide_dma_lost_irq(drive);
 }
 
 static void hpt370_clear_engine(ide_drive_t *drive)
@@ -799,10 +785,10 @@
 	return __ide_dma_end(drive);
 }
 
-static int hpt370_ide_dma_timeout(ide_drive_t *drive)
+static void hpt370_dma_timeout(ide_drive_t *drive)
 {
 	hpt370_irq_timeout(drive);
-	return __ide_dma_timeout(drive);
+	ide_dma_timeout(drive);
 }
 
 /* returns 1 if DMA IRQ issued, 0 otherwise */
@@ -1150,7 +1136,7 @@
 		  * Select 66 MHz DPLL clock only if UltraATA/133 mode is
 		  * supported/enabled, use 50 MHz DPLL clock otherwise...
 		  */
-		if (info->max_mode == 0x04) {
+		if (info->max_ultra == 6) {
 			dpll_clk = 66;
 			clock = ATA_CLOCK_66MHZ;
 		} else if (dpll_clk) {	/* HPT36x chips don't have DPLL */
@@ -1243,7 +1229,7 @@
 	struct pci_dev	*dev		= hwif->pci_dev;
 	struct hpt_info *info		= pci_get_drvdata(dev);
 	int serialize			= HPT_SERIALIZE_IO;
-	u8  scr1 = 0, ata66		= (hwif->channel) ? 0x01 : 0x02;
+	u8  scr1 = 0, ata66		= hwif->channel ? 0x01 : 0x02;
 	u8  chip_type			= info->chip_type;
 	u8  new_mcr, old_mcr 		= 0;
 
@@ -1256,7 +1242,9 @@
 	hwif->intrproc			= &hpt3xx_intrproc;
 	hwif->maskproc			= &hpt3xx_maskproc;
 	hwif->busproc			= &hpt3xx_busproc;
-	hwif->udma_filter		= &hpt3xx_udma_filter;
+
+	if (chip_type <= HPT370A)
+		hwif->udma_filter	= &hpt3xx_udma_filter;
 
 	/*
 	 * HPT3xxN chips have some complications:
@@ -1305,7 +1293,7 @@
 		return;
 	}
 
-	hwif->ultra_mask = 0x7f;
+	hwif->ultra_mask = hwif->cds->udma_mask;
 	hwif->mwdma_mask = 0x07;
 
 	/*
@@ -1342,8 +1330,8 @@
 	} else
 		pci_read_config_byte (dev, 0x5a, &scr1);
 
-	if (!hwif->udma_four)
-		hwif->udma_four = (scr1 & ata66) ? 0 : 1;
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 
 	hwif->ide_dma_check		= &hpt366_config_drive_xfer_rate;
 
@@ -1353,9 +1341,9 @@
 	} else if (chip_type >= HPT370) {
 		hwif->dma_start 	= &hpt370_ide_dma_start;
 		hwif->ide_dma_end	= &hpt370_ide_dma_end;
-		hwif->ide_dma_timeout	= &hpt370_ide_dma_timeout;
+		hwif->dma_timeout	= &hpt370_dma_timeout;
 	} else
-		hwif->ide_dma_lostirq	= &hpt366_ide_dma_lostirq;
+		hwif->dma_lost_irq	= &hpt366_dma_lost_irq;
 
 	if (!noautodma)
 		hwif->autodma = 1;
@@ -1503,9 +1491,35 @@
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
 
-	if (rev > 6)
+	switch (rev) {
+	case 0:
+	case 1:
+	case 2:
+		/*
+		 * HPT36x chips have one channel per function and have
+		 * both channel enable bits located differently and visible
+		 * to both functions -- really stupid design decision... :-(
+		 * Bit 4 is for the primary channel, bit 5 for the secondary.
+		 */
+		d->channels = 1;
+		d->enablebits[0].mask = d->enablebits[0].val = 0x10;
+
+		d->udma_mask = HPT366_ALLOW_ATA66_3 ?
+			      (HPT366_ALLOW_ATA66_4 ? 0x1f : 0x0f) : 0x07;
+		break;
+	case 3:
+	case 4:
+		d->udma_mask = HPT370_ALLOW_ATA100_5 ? 0x3f : 0x1f;
+		break;
+	default:
 		rev = 6;
-		
+		/* fall thru */
+	case 5:
+	case 6:
+		d->udma_mask = HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f;
+		break;
+	}
+
 	d->name = chipset_names[rev];
 
 	pci_set_drvdata(dev, info[rev]);
@@ -1513,15 +1527,6 @@
 	if (rev > 2)
 		goto init_single;
 
-	/*
-	 * HPT36x chips have one channel per function and have
-	 * both channel enable bits located differently and visible
-	 * to both functions -- really stupid design decision... :-(
-	 * Bit 4 is for the primary channel, bit 5 for the secondary.
-	 */
-	d->channels = 1;
-	d->enablebits[0].mask = d->enablebits[0].val = 0x10;
-
 	if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
 		u8  mcr1 = 0, pin1 = 0, pin2 = 0;
 		int ret;
@@ -1573,6 +1578,7 @@
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+		.udma_mask	= HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f,
 		.bootable	= OFF_BOARD,
 		.extra		= 240
 	},{	/* 2 */
@@ -1584,6 +1590,7 @@
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+		.udma_mask	= HPT302_ALLOW_ATA133_6 ? 0x7f : 0x3f,
 		.bootable	= OFF_BOARD,
 		.extra		= 240
 	},{	/* 3 */
@@ -1595,6 +1602,7 @@
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+		.udma_mask	= HPT371_ALLOW_ATA133_6 ? 0x7f : 0x3f,
 		.bootable	= OFF_BOARD,
 		.extra		= 240
 	},{	/* 4 */
@@ -1606,6 +1614,7 @@
 		.channels	= 2,	/* 4 */
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+		.udma_mask	= 0x3f,
 		.bootable	= OFF_BOARD,
 		.extra		= 240
 	},{	/* 5 */
@@ -1617,6 +1626,7 @@
 		.channels	= 2,	/* 4 */
 		.autodma	= AUTODMA,
 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+		.udma_mask	= HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f,
 		.bootable	= OFF_BOARD,
 		.extra		= 240
 	}
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index c04a026..ff48c23 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -231,7 +231,7 @@
 
 static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
 {
-	u8 reg42h = 0, ata66 = 0;
+	u8 reg42h = 0;
 
 	hwif->speedproc = &it8213_tune_chipset;
 	hwif->tuneproc	= &it8213_tuneproc;
@@ -250,11 +250,11 @@
 	hwif->swdma_mask = 0x04;
 
 	pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);
-	ata66 = (reg42h & 0x02) ? 0 : 1;
 
 	hwif->ide_dma_check = &it8213_config_drive_for_dma;
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66;
+
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 
 	/*
 	 *	The BIOS often doesn't set up DMA on this controller
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 3aeb7f1..8197b65 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -491,10 +491,10 @@
  *	the needed logic onboard.
  */
 
-static unsigned int __devinit ata66_it821x(ide_hwif_t *hwif)
+static u8 __devinit ata66_it821x(ide_hwif_t *hwif)
 {
 	/* The reference driver also only does disk side */
-	return 1;
+	return ATA_CBL_PATA80;
 }
 
 /**
@@ -662,8 +662,9 @@
 	hwif->mwdma_mask = 0x07;
 
 	hwif->ide_dma_check = &it821x_config_drive_for_dma;
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_it821x(hwif);
+
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = ata66_it821x(hwif);
 
 	/*
 	 *	The BIOS often doesn't set up DMA on this controller
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index 76ed251..a6008f6 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -25,10 +25,10 @@
  *	ata66_jmicron		-	Cable check
  *	@hwif: IDE port
  *
- *	Return 1 if the cable is 80pin
+ *	Returns the cable type.
  */
 
-static int __devinit ata66_jmicron(ide_hwif_t *hwif)
+static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
 {
 	struct pci_dev *pdev = hwif->pci_dev;
 
@@ -70,16 +70,17 @@
 	{
 	case PORT_PATA0:
 		if (control & (1 << 3))	/* 40/80 pin primary */
-			return 0;
-		return 1;
+			return ATA_CBL_PATA40;
+		return ATA_CBL_PATA80;
 	case PORT_PATA1:
 		if (control5 & (1 << 19))	/* 40/80 pin secondary */
-			return 0;
-		return 1;
+			return ATA_CBL_PATA40;
+		return ATA_CBL_PATA80;
 	case PORT_SATA:
 		break;
 	}
-	return 1; /* Avoid bogus "control reaches end of non-void function" */
+	/* Avoid bogus "control reaches end of non-void function" */
+	return ATA_CBL_PATA80;
 }
 
 static void jmicron_tuneproc (ide_drive_t *drive, byte mode_wanted)
@@ -159,8 +160,9 @@
 	hwif->mwdma_mask = 0x07;
 
 	hwif->ide_dma_check = &jmicron_config_drive_for_dma;
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_jmicron(hwif);
+
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = ata66_jmicron(hwif);
 
 	hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 0765dce..ee5020d 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -225,7 +225,10 @@
 
 static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
 {
-	return get_indexed_reg(hwif, 0x0b) & 0x04;
+	if (get_indexed_reg(hwif, 0x0b) & 0x04)
+		return ATA_CBL_PATA40;
+	else
+		return ATA_CBL_PATA80;
 }
 
 static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
@@ -509,8 +512,8 @@
 
 	hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
 
-	if (!hwif->udma_four)
-		hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1;
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = pdcnew_cable_detect(hwif);
 
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 2384468..41ac4a9 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -152,8 +152,10 @@
 static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
 {
 	u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10);
+
 	pci_read_config_word(hwif->pci_dev, 0x50, &CIS);
-	return (CIS & mask) ? 1 : 0;
+
+	return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 }
 
 /*
@@ -267,18 +269,24 @@
 	return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
 }
 
-static int pdc202xx_ide_dma_lostirq(ide_drive_t *drive)
+static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
 {
-	if (HWIF(drive)->resetproc != NULL)
-		HWIF(drive)->resetproc(drive);
-	return __ide_dma_lostirq(drive);
+	ide_hwif_t *hwif = HWIF(drive);
+
+	if (hwif->resetproc != NULL)
+		hwif->resetproc(drive);
+
+	ide_dma_lost_irq(drive);
 }
 
-static int pdc202xx_ide_dma_timeout(ide_drive_t *drive)
+static void pdc202xx_dma_timeout(ide_drive_t *drive)
 {
-	if (HWIF(drive)->resetproc != NULL)
-		HWIF(drive)->resetproc(drive);
-	return __ide_dma_timeout(drive);
+	ide_hwif_t *hwif = HWIF(drive);
+
+	if (hwif->resetproc != NULL)
+		hwif->resetproc(drive);
+
+	ide_dma_timeout(drive);
 }
 
 static void pdc202xx_reset_host (ide_hwif_t *hwif)
@@ -347,12 +355,13 @@
 	hwif->err_stops_fifo = 1;
 
 	hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate;
-	hwif->ide_dma_lostirq = &pdc202xx_ide_dma_lostirq;
-	hwif->ide_dma_timeout = &pdc202xx_ide_dma_timeout;
+	hwif->dma_lost_irq = &pdc202xx_dma_lost_irq;
+	hwif->dma_timeout = &pdc202xx_dma_timeout;
 
 	if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) {
-		if (!(hwif->udma_four))
-			hwif->udma_four = (pdc202xx_old_cable_detect(hwif)) ? 0 : 1;
+		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+			hwif->cbl = pdc202xx_old_cable_detect(hwif);
+
 		hwif->dma_start = &pdc202xx_old_ide_dma_start;
 		hwif->ide_dma_end = &pdc202xx_old_ide_dma_end;
 	} 
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 8b219dd..2e0b29e 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/ide/pci/piix.c	Version 0.47	February 8, 2007
+ *  linux/drivers/ide/pci/piix.c	Version 0.50	Jun 10, 2007
  *
  *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
  *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
@@ -394,14 +394,45 @@
 	hwif->OUTB(dma_stat, hwif->dma_status);
 }
 
-static int __devinit piix_cable_detect(ide_hwif_t *hwif)
+struct ich_laptop {
+	u16 device;
+	u16 subvendor;
+	u16 subdevice;
+};
+
+/*
+ *	List of laptops that use short cables rather than 80 wire
+ */
+
+static const struct ich_laptop ich_laptop[] = {
+	/* devid, subvendor, subdev */
+	{ 0x27DF, 0x0005, 0x0280 },	/* ICH7 on Acer 5602WLMi */
+	{ 0x27DF, 0x1025, 0x0110 },	/* ICH7 on Acer 3682WLMi */
+	{ 0x27DF, 0x1043, 0x1267 },	/* ICH7 on Asus W5F */
+	{ 0x24CA, 0x1025, 0x0061 },	/* ICH4 on Acer Aspire 2023WLMi */
+	/* end marker */
+	{ 0, }
+};
+
+static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
 {
-	struct pci_dev *dev = hwif->pci_dev;
+	struct pci_dev *pdev = hwif->pci_dev;
+	const struct ich_laptop *lap = &ich_laptop[0];
 	u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
 
-	pci_read_config_byte(dev, 0x54, &reg54h);
+	/* check for specials */
+	while (lap->device) {
+		if (lap->device == pdev->device &&
+		    lap->subvendor == pdev->subsystem_vendor &&
+		    lap->subdevice == pdev->subsystem_device) {
+			return ATA_CBL_PATA40_SHORT;
+		}
+		lap++;
+	}
 
-	return (reg54h & mask) ? 1 : 0;
+	pci_read_config_byte(pdev, 0x54, &reg54h);
+
+	return (reg54h & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
 /**
@@ -444,8 +475,8 @@
 	hwif->swdma_mask = 0x04;
 
 	if (hwif->ultra_mask & 0x78) {
-		if (!hwif->udma_four)
-			hwif->udma_four = piix_cable_detect(hwif);
+		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+			hwif->cbl = piix_cable_detect(hwif);
 	}
 
 	if (no_piix_dma)
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 55bc0a3..7b87488 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -716,7 +716,7 @@
 	hwif->atapi_dma = 1;
 
 	/* we support 80c cable only. */
-	hwif->udma_four = 1;
+	hwif->cbl = ATA_CBL_PATA80;
 
 	hwif->autodma = 0;
 	if (!noautodma)
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index d9c4fd1..1371b5b 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/serverworks.c		Version 0.11	Jun 2 2007
+ * linux/drivers/ide/pci/serverworks.c		Version 0.20	Jun 3 2007
  *
  * Copyright (C) 1998-2000 Michel Aubry
  * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
@@ -151,84 +151,11 @@
 	if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 &&
 		drive->media == ide_disk && speed >= XFER_UDMA_0)
 			BUG();
-			
-	pci_read_config_byte(dev, drive_pci[drive->dn], &pio_timing);
-	pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_timing);
+
 	pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
 	pci_read_config_word(dev, 0x4A, &csb5_pio);
 	pci_read_config_byte(dev, 0x54, &ultra_enable);
 
-	/* If we are in RAID mode (eg AMI MegaIDE) then we can't it
-	   turns out trust the firmware configuration */
-
-	if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
-		goto oem_setup_failed;
-
-	/* Per Specified Design by OEM, and ASIC Architect */
-	if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
-	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
-		if (!drive->init_speed) {
-			u8 dma_stat = inb(hwif->dma_status);
-
-			if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
-			    ((dma_stat & (1<<(5+unit))) == (1<<(5+unit)))) {
-				drive->current_speed = drive->init_speed = XFER_UDMA_0 + udma_modes[(ultra_timing >> (4*unit)) & ~(0xF0)];
-				return 0;
-			} else if ((dma_timing) &&
-				   ((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) {
-				u8 dmaspeed;
-
-				switch (dma_timing & 0x77) {
-				case 0x20:
-					dmaspeed = XFER_MW_DMA_2;
-					break;
-				case 0x21:
-					dmaspeed = XFER_MW_DMA_1;
-					break;
-				case 0x77:
-					dmaspeed = XFER_MW_DMA_0;
-					break;
-				default:
-					goto dma_pio;
-				}
-
-				drive->current_speed = drive->init_speed = dmaspeed;
-				return 0;
-			}
-dma_pio:
-			if (pio_timing) {
-				u8 piospeed;
-
-				switch (pio_timing & 0x7f) {
-				case 0x20:
-					piospeed = XFER_PIO_4;
-					break;
-				case 0x22:
-					piospeed = XFER_PIO_3;
-					break;
-				case 0x34:
-					piospeed = XFER_PIO_2;
-					break;
-				case 0x47:
-					piospeed = XFER_PIO_1;
-					break;
-				case 0x5d:
-					piospeed = XFER_PIO_0;
-					break;
-				default:
-					goto oem_setup_failed;
-				}
-
-				drive->current_speed = drive->init_speed = piospeed;
-				return 0;
-			}
-		}
-	}
-
-oem_setup_failed:
-
-	pio_timing	= 0;
-	dma_timing	= 0;
 	ultra_timing	&= ~(0x0F << (4*unit));
 	ultra_enable	&= ~(0x01 << drive->dn);
 	csb5_pio	&= ~(0x0F << (4*drive->dn));
@@ -402,9 +329,9 @@
 	return dev->irq;
 }
 
-static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_svwks(ide_hwif_t *hwif)
 {
-	return 1;
+	return ATA_CBL_PATA80;
 }
 
 /* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits
@@ -414,7 +341,7 @@
  * Bit 14 clear = primary IDE channel does not have 80-pin cable.
  * Bit 14 set   = primary IDE channel has 80-pin cable.
  */
-static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
@@ -422,8 +349,8 @@
 	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
 	     dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE))
 		return ((1 << (hwif->channel + 14)) &
-			dev->subsystem_device) ? 1 : 0;
-	return 0;
+			dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+	return ATA_CBL_PATA40;
 }
 
 /* Sun Cobalt Alpine hardware avoids the 80-pin cable
@@ -432,18 +359,18 @@
  *
  * WARNING: this only works on Alpine hardware!
  */
-static unsigned int __devinit ata66_svwks_cobalt (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
 	    dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
 		return ((1 << (hwif->channel + 14)) &
-			dev->subsystem_device) ? 1 : 0;
-	return 0;
+			dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+	return ATA_CBL_PATA40;
 }
 
-static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 
@@ -462,9 +389,9 @@
 	/* Per Specified Design by OEM, and ASIC Architect */
 	if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
 	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2))
-		return 1;
+		return ATA_CBL_PATA80;
 
-	return 0;
+	return ATA_CBL_PATA40;
 }
 
 static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
@@ -495,8 +422,8 @@
 
 	hwif->ide_dma_check = &svwks_config_drive_xfer_rate;
 	if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
-		if (!hwif->udma_four)
-			hwif->udma_four = ata66_svwks(hwif);
+		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+			hwif->cbl = ata66_svwks(hwif);
 	}
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index d3185e2..d396b29 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -316,14 +316,6 @@
 	sgiioc4_clearirq(drive);
 }
 
-static int
-sgiioc4_ide_dma_lostirq(ide_drive_t * drive)
-{
-	HWIF(drive)->resetproc(drive);
-
-	return __ide_dma_lostirq(drive);
-}
-
 static void
 sgiioc4_resetproc(ide_drive_t * drive)
 {
@@ -331,6 +323,14 @@
 	sgiioc4_clearirq(drive);
 }
 
+static void
+sgiioc4_dma_lost_irq(ide_drive_t * drive)
+{
+	sgiioc4_resetproc(drive);
+
+	ide_dma_lost_irq(drive);
+}
+
 static u8
 sgiioc4_INB(unsigned long port)
 {
@@ -607,8 +607,8 @@
 	hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
 	hwif->dma_host_on = &sgiioc4_dma_host_on;
 	hwif->dma_host_off = &sgiioc4_dma_host_off;
-	hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
-	hwif->ide_dma_timeout = &__ide_dma_timeout;
+	hwif->dma_lost_irq = &sgiioc4_dma_lost_irq;
+	hwif->dma_timeout = &ide_dma_timeout;
 
 	hwif->INB = &sgiioc4_INB;
 }
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 1a4444e..1c3e354 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -933,16 +933,17 @@
  *	interface.
  */
 
-static unsigned int __devinit ata66_siimage(ide_hwif_t *hwif)
+static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
 {
 	unsigned long addr = siimage_selreg(hwif, 0);
-	if (pci_get_drvdata(hwif->pci_dev) == NULL) {
-		u8 ata66 = 0;
-		pci_read_config_byte(hwif->pci_dev, addr, &ata66);
-		return (ata66 & 0x01) ? 1 : 0;
-	}
+	u8 ata66 = 0;
 
-	return (hwif->INB(addr) & 0x01) ? 1 : 0;
+	if (pci_get_drvdata(hwif->pci_dev) == NULL)
+		pci_read_config_byte(hwif->pci_dev, addr, &ata66);
+	else
+		ata66 = hwif->INB(addr);
+
+	return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
 /**
@@ -988,8 +989,9 @@
 		hwif->atapi_dma = 1;
 
 	hwif->ide_dma_check = &siimage_config_drive_for_dma;
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_siimage(hwif);
+
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = ata66_siimage(hwif);
 
 	if (hwif->mmio) {
 		hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index ec0adad..f875183 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/sis5513.c	Version 0.20	Mar 4, 2007
+ * linux/drivers/ide/pci/sis5513.c	Version 0.25	Jun 10, 2007
  *
  * Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2002		Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
@@ -796,10 +796,33 @@
 	return 0;
 }
 
-static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif)
+struct sis_laptop {
+	u16 device;
+	u16 subvendor;
+	u16 subdevice;
+};
+
+static const struct sis_laptop sis_laptop[] = {
+	/* devid, subvendor, subdev */
+	{ 0x5513, 0x1043, 0x1107 },	/* ASUS A6K */
+	/* end marker */
+	{ 0, }
+};
+
+static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
 {
+	struct pci_dev *pdev = hwif->pci_dev;
+	const struct sis_laptop *lap = &sis_laptop[0];
 	u8 ata66 = 0;
 
+	while (lap->device) {
+		if (lap->device == pdev->device &&
+		    lap->subvendor == pdev->subsystem_vendor &&
+		    lap->subdevice == pdev->subsystem_device)
+			return ATA_CBL_PATA40_SHORT;
+		lap++;
+	}
+
 	if (chipset_family >= ATA_133) {
 		u16 regw = 0;
 		u16 reg_addr = hwif->channel ? 0x52: 0x50;
@@ -811,7 +834,8 @@
 		pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
 		ata66 = (reg48h & mask) ? 0 : 1;
 	}
-        return ata66;
+
+	return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 }
 
 static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
@@ -841,8 +865,8 @@
 	if (!chipset_family)
 		return;
 
-	if (!(hwif->udma_four))
-		hwif->udma_four = ata66_sis5513(hwif);
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = ata66_sis5513(hwif);
 
 	if (chipset_family > ATA_16) {
 		hwif->ide_dma_check = &sis5513_config_xfer_rate;
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 7c383d9..4878798 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -195,7 +195,7 @@
  * This function is called when the IDE timer expires, the drive
  * indicates that it is READY, and we were waiting for DMA to complete.
  */
-static int sl82c105_ide_dma_lostirq(ide_drive_t *drive)
+static void sl82c105_dma_lost_irq(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -222,9 +222,6 @@
 	}
 
 	sl82c105_reset_host(dev);
-
-	/* __ide_dma_lostirq would return 1, so we do as well */
-	return 1;
 }
 
 /*
@@ -244,15 +241,12 @@
 	ide_dma_start(drive);
 }
 
-static int sl82c105_ide_dma_timeout(ide_drive_t *drive)
+static void sl82c105_dma_timeout(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name));
 
-	DBG(("sl82c105_ide_dma_timeout(drive:%s)\n", drive->name));
-
-	sl82c105_reset_host(dev);
-	return __ide_dma_timeout(drive);
+	sl82c105_reset_host(HWIF(drive)->pci_dev);
+	ide_dma_timeout(drive);
 }
 
 static int sl82c105_ide_dma_on(ide_drive_t *drive)
@@ -441,9 +435,9 @@
 	hwif->ide_dma_check		= &sl82c105_ide_dma_check;
 	hwif->ide_dma_on		= &sl82c105_ide_dma_on;
 	hwif->dma_off_quietly		= &sl82c105_dma_off_quietly;
-	hwif->ide_dma_lostirq		= &sl82c105_ide_dma_lostirq;
+	hwif->dma_lost_irq		= &sl82c105_dma_lost_irq;
 	hwif->dma_start			= &sl82c105_dma_start;
-	hwif->ide_dma_timeout		= &sl82c105_ide_dma_timeout;
+	hwif->dma_timeout		= &sl82c105_dma_timeout;
 
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index c40f291..575dbbd 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -199,10 +199,9 @@
 	hwif->mwdma_mask = 0x06;
 	hwif->swdma_mask = 0x04;
 
-	if (!hwif->udma_four) {
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
 		/* bit[0(1)]: 0:80, 1:40 */
-		hwif->udma_four = (reg47 & mask) ? 0 : 1;
-	}
+		hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 
 	hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate;
 
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index cee619b..8de1f8e 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -220,13 +220,13 @@
 	hwif->ide_dma_check	= &tc86c001_config_drive_xfer_rate;
 	hwif->dma_start 	= &tc86c001_dma_start;
 
-	if (!hwif->udma_four) {
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
 		/*
 		 * System Control  1 Register bit 13 (PDIAGN):
 		 * 0=80-pin cable, 1=40-pin cable
 		 */
 		scr1 = hwif->INW(sc_base + 0x00);
-		hwif->udma_four = (scr1 & 0x2000) ? 0 : 1;
+		hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 	}
 
 	if (!noautodma)
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index a508550..d21dd2e 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -1,6 +1,6 @@
 /*
  *
- * Version 3.38
+ * Version 3.45
  *
  * VIA IDE driver for Linux. Supported southbridges:
  *
@@ -9,6 +9,7 @@
  *   vt8235, vt8237, vt8237a
  *
  * Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
  *
  * Based on the work of:
  *	Michel Aubry
@@ -33,6 +34,8 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ide.h>
+#include <linux/dmi.h>
+
 #include <asm/io.h>
 
 #ifdef CONFIG_PPC_CHRP
@@ -41,8 +44,6 @@
 
 #include "ide-timing.h"
 
-#define DISPLAY_VIA_TIMINGS
-
 #define VIA_IDE_ENABLE		0x40
 #define VIA_IDE_CONFIG		0x41
 #define VIA_FIFO_CONFIG		0x43
@@ -54,18 +55,12 @@
 #define VIA_ADDRESS_SETUP	0x4c
 #define VIA_UDMA_TIMING		0x50
 
-#define VIA_UDMA		0x007
-#define VIA_UDMA_NONE		0x000
-#define VIA_UDMA_33		0x001
-#define VIA_UDMA_66		0x002
-#define VIA_UDMA_100		0x003
-#define VIA_UDMA_133		0x004
-#define VIA_BAD_PREQ		0x010	/* Crashes if PREQ# till DDACK# set */
-#define VIA_BAD_CLK66		0x020	/* 66 MHz clock doesn't work correctly */
-#define VIA_SET_FIFO		0x040	/* Needs to have FIFO split set */
-#define VIA_NO_UNMASK		0x080	/* Doesn't work with IRQ unmasking on */
-#define VIA_BAD_ID		0x100	/* Has wrong vendor ID (0x1107) */
-#define VIA_BAD_AST		0x200	/* Don't touch Address Setup Timing */
+#define VIA_BAD_PREQ		0x01 /* Crashes if PREQ# till DDACK# set */
+#define VIA_BAD_CLK66		0x02 /* 66 MHz clock doesn't work correctly */
+#define VIA_SET_FIFO		0x04 /* Needs to have FIFO split set */
+#define VIA_NO_UNMASK		0x08 /* Doesn't work with IRQ unmasking on */
+#define VIA_BAD_ID		0x10 /* Has wrong vendor ID (0x1107) */
+#define VIA_BAD_AST		0x20 /* Don't touch Address Setup Timing */
 
 /*
  * VIA SouthBridge chips.
@@ -76,36 +71,37 @@
 	u16 id;
 	u8 rev_min;
 	u8 rev_max;
-	u16 flags;
+	u8 udma_mask;
+	u8 flags;
 } via_isa_bridges[] = {
-	{ "cx700",	PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8237s",	PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt6410",	PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8251",	PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8237",	PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8237a",	PCI_DEVICE_ID_VIA_8237A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8235",	PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8233a",	PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
-	{ "vt8233c",	PCI_DEVICE_ID_VIA_8233C_0,  0x00, 0x2f, VIA_UDMA_100 },
-	{ "vt8233",	PCI_DEVICE_ID_VIA_8233_0,   0x00, 0x2f, VIA_UDMA_100 },
-	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     0x00, 0x2f, VIA_UDMA_100 },
-	{ "vt82c686b",	PCI_DEVICE_ID_VIA_82C686,   0x40, 0x4f, VIA_UDMA_100 },
-	{ "vt82c686a",	PCI_DEVICE_ID_VIA_82C686,   0x10, 0x2f, VIA_UDMA_66 },
-	{ "vt82c686",	PCI_DEVICE_ID_VIA_82C686,   0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
-	{ "vt82c596b",	PCI_DEVICE_ID_VIA_82C596,   0x10, 0x2f, VIA_UDMA_66 },
-	{ "vt82c596a",	PCI_DEVICE_ID_VIA_82C596,   0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
-	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO },
-	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ },
-	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO },
-	{ "vt82c586a",	PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO },
-	{ "vt82c586",	PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO },
-	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK },
-	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
+	{ "cx700",	PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8237s",	PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt6410",	PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8251",	PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8237",	PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8237a",	PCI_DEVICE_ID_VIA_8237A,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8235",	PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8233a",	PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt8233c",	PCI_DEVICE_ID_VIA_8233C_0,  0x00, 0x2f, ATA_UDMA5, },
+	{ "vt8233",	PCI_DEVICE_ID_VIA_8233_0,   0x00, 0x2f, ATA_UDMA5, },
+	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     0x00, 0x2f, ATA_UDMA5, },
+	{ "vt82c686b",	PCI_DEVICE_ID_VIA_82C686,   0x40, 0x4f, ATA_UDMA5, },
+	{ "vt82c686a",	PCI_DEVICE_ID_VIA_82C686,   0x10, 0x2f, ATA_UDMA4, },
+	{ "vt82c686",	PCI_DEVICE_ID_VIA_82C686,   0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+	{ "vt82c596b",	PCI_DEVICE_ID_VIA_82C596,   0x10, 0x2f, ATA_UDMA4, },
+	{ "vt82c596a",	PCI_DEVICE_ID_VIA_82C596,   0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, ATA_UDMA2, VIA_SET_FIFO },
+	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, ATA_UDMA2, VIA_SET_FIFO | VIA_BAD_PREQ },
+	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, ATA_UDMA2, VIA_SET_FIFO },
+	{ "vt82c586a",	PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, ATA_UDMA2, VIA_SET_FIFO },
+	{ "vt82c586",	PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f,      0x00, VIA_SET_FIFO },
+	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f,      0x00, VIA_SET_FIFO | VIA_NO_UNMASK },
+	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f,      0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
 	{ NULL }
 };
 
 static unsigned int via_clock;
-static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+static char *via_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
 
 struct via82cxxx_dev
 {
@@ -140,12 +136,12 @@
 	pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn),
 		((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
 
-	switch (vdev->via_config->flags & VIA_UDMA) {
-		case VIA_UDMA_33:  t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
-		case VIA_UDMA_66:  t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
-		case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
-		case VIA_UDMA_133: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
-		default: return;
+	switch (vdev->via_config->udma_mask) {
+	case ATA_UDMA2: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+	case ATA_UDMA4: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
+	case ATA_UDMA5: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+	case ATA_UDMA6: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+	default: return;
 	}
 
 	pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t);
@@ -173,12 +169,12 @@
 
 	T = 1000000000 / via_clock;
 
-	switch (vdev->via_config->flags & VIA_UDMA) {
-		case VIA_UDMA_33:   UT = T;   break;
-		case VIA_UDMA_66:   UT = T/2; break;
-		case VIA_UDMA_100:  UT = T/3; break;
-		case VIA_UDMA_133:  UT = T/4; break;
-		default: UT = T;
+	switch (vdev->via_config->udma_mask) {
+	case ATA_UDMA2: UT = T;   break;
+	case ATA_UDMA4: UT = T/2; break;
+	case ATA_UDMA5: UT = T/3; break;
+	case ATA_UDMA6: UT = T/4; break;
+	default:	UT = T;
 	}
 
 	ide_timing_compute(drive, speed, &t, T, UT);
@@ -208,8 +204,7 @@
 static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio)
 {
 	if (pio == 255) {
-		via_set_drive(drive,
-			ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+		via_set_drive(drive, ide_find_best_pio_mode(drive));
 		return;
 	}
 
@@ -226,16 +221,10 @@
  
 static int via82cxxx_ide_dma_check (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
-	u16 w80 = hwif->udma_four;
+	u8 speed = ide_max_dma_mode(drive);
 
-	u16 speed = ide_find_best_mode(drive,
-		XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
-		(vdev->via_config->flags & VIA_UDMA ? XFER_UDMA : 0) |
-		(w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) |
-		(w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) |
-		(w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0));
+	if (speed == 0)
+		speed = ide_find_best_pio_mode(drive);
 
 	via_set_drive(drive, speed);
 
@@ -272,8 +261,8 @@
 {
 	int i;
 
-	switch (vdev->via_config->flags & VIA_UDMA) {
-		case VIA_UDMA_66:
+	switch (vdev->via_config->udma_mask) {
+		case ATA_UDMA4:
 			for (i = 24; i >= 0; i -= 8)
 				if (((u >> (i & 16)) & 8) &&
 				    ((u >> i) & 0x20) &&
@@ -286,7 +275,7 @@
 				}
 			break;
 
-		case VIA_UDMA_100:
+		case ATA_UDMA5:
 			for (i = 24; i >= 0; i -= 8)
 				if (((u >> i) & 0x10) ||
 				    (((u >> i) & 0x20) &&
@@ -298,7 +287,7 @@
 				}
 			break;
 
-		case VIA_UDMA_133:
+		case ATA_UDMA6:
 			for (i = 24; i >= 0; i -= 8)
 				if (((u >> i) & 0x10) ||
 				    (((u >> i) & 0x20) &&
@@ -353,7 +342,7 @@
 
 	via_cable_detect(vdev, u);
 
-	if ((via_config->flags & VIA_UDMA) == VIA_UDMA_66) {
+	if (via_config->udma_mask == ATA_UDMA4) {
 		/* Enable Clk66 */
 		pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008);
 	} else if (via_config->flags & VIA_BAD_CLK66) {
@@ -416,16 +405,54 @@
 	 */
 
 	pci_read_config_byte(isa, PCI_REVISION_ID, &t);
-	printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %s "
+	printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %sDMA%s "
 		"controller on pci%s\n",
 		via_config->name, t,
-		via_dma[via_config->flags & VIA_UDMA],
+		via_config->udma_mask ? "U" : "MW",
+		via_dma[via_config->udma_mask ?
+			(fls(via_config->udma_mask) - 1) : 0],
 		pci_name(dev));
 
 	pci_dev_put(isa);
 	return 0;
 }
 
+/*
+ *	Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+	{
+		.ident = "Acer Ferrari 3400",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."),
+			DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"),
+		},
+	},
+	{ }
+};
+
+static int via_cable_override(void)
+{
+	/* Systems by DMI */
+	if (dmi_check_system(cable_dmi_table))
+		return 1;
+	return 0;
+}
+
+static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
+{
+	struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
+
+	if (via_cable_override())
+		return ATA_CBL_PATA40_SHORT;
+
+	if ((vdev->via_80w >> hwif->channel) & 1)
+		return ATA_CBL_PATA80;
+	else
+		return ATA_CBL_PATA40;
+}
+
 static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
 {
 	struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
@@ -454,12 +481,14 @@
 		return;
 
 	hwif->atapi_dma = 1;
-	hwif->ultra_mask = 0x7f;
+
+	hwif->ultra_mask = vdev->via_config->udma_mask;
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-	if (!hwif->udma_four)
-		hwif->udma_four = (vdev->via_80w >> hwif->channel) & 1;
+	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+		hwif->cbl = via82cxxx_cable_detect(hwif);
+
 	hwif->ide_dma_check = &via82cxxx_ide_dma_check;
 	if (!noautodma)
 		hwif->autodma = 1;
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 45fc36f..e46f4720 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -942,8 +942,8 @@
 				return 1;
 		case XFER_UDMA_4:
 		case XFER_UDMA_3:
-			if (HWIF(drive)->udma_four == 0)
-				return 1;		
+			if (drive->hwif->cbl != ATA_CBL_PATA80)
+				return 1;
 		case XFER_UDMA_2:
 		case XFER_UDMA_1:
 		case XFER_UDMA_0:
@@ -1244,7 +1244,7 @@
 	hwif->chipset = ide_pmac;
 	hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay;
 	hwif->hold = pmif->mediabay;
-	hwif->udma_four = pmif->cable_80;
+	hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
 	hwif->drives[0].unmask = 1;
 	hwif->drives[1].unmask = 1;
 	hwif->tuneproc = pmac_ide_tuneproc;
@@ -1821,28 +1821,11 @@
 		enable = 0;
 
 	if (enable) {
-		short mode;
-		
-		map = XFER_MWDMA;
-		if (pmif->kind == controller_kl_ata4
-		    || pmif->kind == controller_un_ata6
-		    || pmif->kind == controller_k2_ata6
-		    || pmif->kind == controller_sh_ata6) {
-			map |= XFER_UDMA;
-			if (pmif->cable_80) {
-				map |= XFER_UDMA_66;
-				if (pmif->kind == controller_un_ata6 ||
-				    pmif->kind == controller_k2_ata6 ||
-				    pmif->kind == controller_sh_ata6)
-					map |= XFER_UDMA_100;
-				if (pmif->kind == controller_sh_ata6)
-					map |= XFER_UDMA_133;
-			}
-		}
-		mode = ide_find_best_mode(drive, map);
-		if (mode & XFER_UDMA)
+		u8 mode = ide_max_dma_mode(drive);
+
+		if (mode >= XFER_UDMA_0)
 			drive->using_dma = pmac_ide_udma_enable(drive, mode);
-		else if (mode & XFER_MWDMA)
+		else if (mode >= XFER_MW_DMA_0)
 			drive->using_dma = pmac_ide_mdma_enable(drive, mode);
 		hwif->OUTB(0, IDE_CONTROL_REG);
 		/* Apply settings to controller */
@@ -2004,20 +1987,19 @@
 {
 }
 
-static int
-pmac_ide_dma_lostirq (ide_drive_t *drive)
+static void
+pmac_ide_dma_lost_irq (ide_drive_t *drive)
 {
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
 	volatile struct dbdma_regs __iomem *dma;
 	unsigned long status;
 
 	if (pmif == NULL)
-		return 0;
+		return;
 	dma = pmif->dma_regs;
 
 	status = readl(&dma->status);
 	printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
-	return 0;
 }
 
 /*
@@ -2057,8 +2039,8 @@
 	hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
 	hwif->dma_host_off = &pmac_ide_dma_host_off;
 	hwif->dma_host_on = &pmac_ide_dma_host_on;
-	hwif->ide_dma_timeout = &__ide_dma_timeout;
-	hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq;
+	hwif->dma_timeout = &ide_dma_timeout;
+	hwif->dma_lost_irq = &pmac_ide_dma_lost_irq;
 
 	hwif->atapi_dma = 1;
 	switch(pmif->kind) {
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 2081413..6572211 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2280,7 +2280,7 @@
 	} while (video);
 
 	if (found_ohci_card)
-		class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+		device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
 			   IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2)));
 }
 
@@ -2295,9 +2295,9 @@
 
 	ohci = (struct ti_ohci *)host->hostdata;
 
-	class_device_create(hpsb_protocol_class, NULL, MKDEV(
-		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), 
-		NULL, "dv1394-%d", id);
+	device_create(hpsb_protocol_class, NULL, MKDEV(
+		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
+		"dv1394-%d", id);
 
 	dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
 	dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 7c13fb3..93362ee 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -599,9 +599,7 @@
 	}
 
 	SET_MODULE_OWNER(dev);
-
-	/* This used to be &host->device in Linux 2.6.20 and before. */
-	SET_NETDEV_DEV(dev, host->device.parent);
+	SET_NETDEV_DEV(dev, &host->device);
 
 	priv = netdev_priv(dev);
 	INIT_LIST_HEAD(&priv->ip_node_list);
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 83a49331..b642546 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -483,37 +483,6 @@
 	return retval;
 }
 
-/**
- * hpsb_listen_channel - enable receving a certain isochronous channel
- *
- * Reception is handled through the @hl's iso_receive op.
- */
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			unsigned int channel)
-{
-	if (channel > 63) {
-		HPSB_ERR("%s called with invalid channel", __FUNCTION__);
-		return -EINVAL;
-	}
-	if (host->iso_listen_count[channel]++ == 0)
-		return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
-	return 0;
-}
-
-/**
- * hpsb_unlisten_channel - disable receving a certain isochronous channel
- */
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			   unsigned int channel)
-{
-	if (channel > 63) {
-		HPSB_ERR("%s called with invalid channel", __FUNCTION__);
-		return;
-	}
-	if (--host->iso_listen_count[channel] == 0)
-		host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
-}
-
 static void init_hpsb_highlevel(struct hpsb_host *host)
 {
 	INIT_LIST_HEAD(&dummy_zero_addr.host_list);
@@ -570,20 +539,6 @@
 	read_unlock_irqrestore(&hl_irqs_lock, flags);
 }
 
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length)
-{
-	unsigned long flags;
-	struct hpsb_highlevel *hl;
-	int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
-
-	read_lock_irqsave(&hl_irqs_lock, flags);
-	list_for_each_entry(hl, &hl_irqs, irq_list) {
-		if (hl->iso_receive)
-			hl->iso_receive(host, channel, data, length);
-	}
-	read_unlock_irqrestore(&hl_irqs_lock, flags);
-}
-
 void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
 			   void *data, size_t length)
 {
diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h
index 63474f7..eb9fe32 100644
--- a/drivers/ieee1394/highlevel.h
+++ b/drivers/ieee1394/highlevel.h
@@ -26,9 +26,7 @@
 struct hpsb_highlevel {
 	const char *name;
 
-	/* Any of the following pointers can legally be NULL, except for
-	 * iso_receive which can only be NULL when you don't request
-	 * channels. */
+	/* Any of the following pointers can legally be NULL. */
 
 	/* New host initialized.  Will also be called during
 	 * hpsb_register_highlevel for all hosts already installed. */
@@ -43,13 +41,6 @@
 	 * You can not expect to be able to do stock hpsb_reads. */
 	void (*host_reset)(struct hpsb_host *host);
 
-	/* An isochronous packet was received.  Channel contains the channel
-	 * number for your convenience, it is also contained in the included
-	 * packet header (first quadlet, CRCs are missing).  You may get called
-	 * for channel/host combinations you did not request. */
-	void (*iso_receive)(struct hpsb_host *host, int channel,
-			    quadlet_t *data, size_t length);
-
 	/* A write request was received on either the FCP_COMMAND (direction =
 	 * 0) or the FCP_RESPONSE (direction = 1) register.  The cts arg
 	 * contains the cts field (first byte of data). */
@@ -109,7 +100,6 @@
 int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
 		     u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
 		     u16 flags);
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length);
 void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
 			   void *data, size_t length);
 
@@ -125,10 +115,6 @@
 			    struct hpsb_address_ops *ops, u64 start, u64 end);
 int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
 			      u64 start);
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			unsigned int channel);
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-			   unsigned int channel);
 
 void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
 void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index bd0755c..8dd09d8 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -154,15 +154,16 @@
 
 	memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
 	h->device.parent = dev;
+	set_dev_node(&h->device, dev_to_node(dev));
 	snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
 
-	h->class_dev.dev = &h->device;
-	h->class_dev.class = &hpsb_host_class;
-	snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id);
+	h->host_dev.parent = &h->device;
+	h->host_dev.class = &hpsb_host_class;
+	snprintf(h->host_dev.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
 
 	if (device_register(&h->device))
 		goto fail;
-	if (class_device_register(&h->class_dev)) {
+	if (device_register(&h->host_dev)) {
 		device_unregister(&h->device);
 		goto fail;
 	}
@@ -202,7 +203,7 @@
 	host->driver = &dummy_driver;
 	highlevel_remove_host(host);
 
-	class_device_unregister(&host->class_dev);
+	device_unregister(&host->host_dev);
 	device_unregister(&host->device);
 }
 
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index feb55d0..e4e8aeb 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -28,8 +28,6 @@
 	struct timer_list timeout;
 	unsigned long timeout_interval;
 
-	unsigned char iso_listen_count[64];
-
 	int node_count;      /* number of identified nodes on this bus */
 	int selfid_count;    /* total number of SelfIDs received */
 	int nodes_active;    /* number of nodes with active link layer */
@@ -57,7 +55,7 @@
 	struct hpsb_host_driver *driver;
 	struct pci_dev *pdev;
 	struct device device;
-	struct class_device class_dev;
+	struct device host_dev;
 
 	struct delayed_work delayed_reset;
 	unsigned config_roms:31;
@@ -99,12 +97,6 @@
 	/* Cancel all outstanding async requests without resetting the bus.
 	 * Return void. */
 	CANCEL_REQUESTS,
-
-	/* Start or stop receiving isochronous channel in arg.  Return void.
-	 * This acts as an optimization hint, hosts are not required not to
-	 * listen on unrequested channels. */
-	ISO_LISTEN_CHANNEL,
-	ISO_UNLISTEN_CHANNEL
 };
 
 enum isoctl_cmd {
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 8f71b6a..0fc8c6e 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -1028,11 +1028,6 @@
 		handle_incoming_packet(host, tcode, data, size, write_acked);
 		break;
 
-
-	case TCODE_ISO_DATA:
-		highlevel_iso_receive(host, data, size);
-		break;
-
 	case TCODE_CYCLE_START:
 		/* simply ignore this packet if it is passed on */
 		break;
@@ -1316,7 +1311,6 @@
 EXPORT_SYMBOL(hpsb_make_lockpacket);
 EXPORT_SYMBOL(hpsb_make_lock64packet);
 EXPORT_SYMBOL(hpsb_make_phypacket);
-EXPORT_SYMBOL(hpsb_make_isopacket);
 EXPORT_SYMBOL(hpsb_read);
 EXPORT_SYMBOL(hpsb_write);
 EXPORT_SYMBOL(hpsb_packet_success);
@@ -1327,8 +1321,6 @@
 EXPORT_SYMBOL(hpsb_register_addrspace);
 EXPORT_SYMBOL(hpsb_unregister_addrspace);
 EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
-EXPORT_SYMBOL(hpsb_listen_channel);
-EXPORT_SYMBOL(hpsb_unlisten_channel);
 EXPORT_SYMBOL(hpsb_get_hostinfo);
 EXPORT_SYMBOL(hpsb_create_hostinfo);
 EXPORT_SYMBOL(hpsb_destroy_hostinfo);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index ad52652..21d50f7 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -24,9 +24,8 @@
 
 	nodeid_t node_id;
 
-	/* Async and Iso types should be clear, raw means send-as-is, do not
-	 * CRC!  Byte swapping shall still be done in this case. */
-	enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
+	/* hpsb_raw = send as-is, do not CRC (but still byte-swap it) */
+	enum { hpsb_async, hpsb_raw } __attribute__((packed)) type;
 
 	/* Okay, this is core internal and a no care for hosts.
 	 * queued   = queued for sending
@@ -37,7 +36,7 @@
 		hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
 	} __attribute__((packed)) state;
 
-	/* These are core internal. */
+	/* These are core-internal. */
 	signed char tlabel;
 	signed char ack_code;
 	unsigned char tcode;
@@ -62,11 +61,15 @@
 	/* Store jiffies for implementing bus timeouts. */
 	unsigned long sendtime;
 
-	/* Sizes are in bytes. *data can be DMA-mapped. */
+	/* Core-internal.  */
 	size_t allocated_data_size;	/* as allocated */
+
+	/* Sizes are in bytes. To be set by caller of hpsb_alloc_packet. */
 	size_t data_size;		/* as filled in */
 	size_t header_size;		/* as filled in, not counting the CRC */
-	quadlet_t *data;
+
+	/* Buffers */
+	quadlet_t *data;		/* can be DMA-mapped */
 	quadlet_t header[5];
 	quadlet_t embedded_data[0];	/* keep as last member */
 };
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 40078ce..c39c70a 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -89,18 +89,6 @@
 	packet->expect_response = 1;
 }
 
-static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
-			    int tag, int sync)
-{
-	packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
-	    | (TCODE_ISO_DATA << 4) | sync;
-
-	packet->header_size = 4;
-	packet->data_size = length;
-	packet->type = hpsb_iso;
-	packet->tcode = TCODE_ISO_DATA;
-}
-
 static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
 {
 	packet->header[0] = data;
@@ -491,24 +479,6 @@
 	return p;
 }
 
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
-					int length, int channel,
-					int tag, int sync)
-{
-	struct hpsb_packet *p;
-
-	p = hpsb_alloc_packet(length);
-	if (!p)
-		return NULL;
-
-	p->host = host;
-	fill_iso_packet(p, length, channel, tag, sync);
-
-	p->generation = get_hpsb_generation(host);
-
-	return p;
-}
-
 /*
  * FIXME - these functions should probably read from / write to user space to
  * avoid in kernel buffers for user space callers
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
index 86b8ee6..d2d5bc3 100644
--- a/drivers/ieee1394/ieee1394_transactions.h
+++ b/drivers/ieee1394/ieee1394_transactions.h
@@ -19,8 +19,6 @@
 					   nodeid_t node, u64 addr, int extcode,
 					   octlet_t *data, octlet_t arg);
 struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data);
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, int length,
-					int channel, int tag, int sync);
 struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
 					  nodeid_t node, u64 addr,
 					  quadlet_t *buffer, size_t length);
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 81b3864..c4d3d41 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -19,6 +19,7 @@
 #include <linux/mutex.h>
 #include <linux/freezer.h>
 #include <asm/atomic.h>
+#include <asm/semaphore.h>
 
 #include "csr.h"
 #include "highlevel.h"
@@ -145,8 +146,6 @@
  * but now we are much simpler because of the LDM.
  */
 
-static DEFINE_MUTEX(nodemgr_serialize);
-
 struct host_info {
 	struct hpsb_host *host;
 	struct list_head list;
@@ -154,7 +153,7 @@
 };
 
 static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
 			  char *buffer, int buffer_size);
 static void nodemgr_resume_ne(struct node_entry *ne);
 static void nodemgr_remove_ne(struct node_entry *ne);
@@ -165,37 +164,38 @@
 	.match		= nodemgr_bus_match,
 };
 
-static void host_cls_release(struct class_device *class_dev)
+static void host_cls_release(struct device *dev)
 {
-	put_device(&container_of((class_dev), struct hpsb_host, class_dev)->device);
+	put_device(&container_of((dev), struct hpsb_host, host_dev)->device);
 }
 
 struct class hpsb_host_class = {
 	.name		= "ieee1394_host",
-	.release	= host_cls_release,
+	.dev_release	= host_cls_release,
 };
 
-static void ne_cls_release(struct class_device *class_dev)
+static void ne_cls_release(struct device *dev)
 {
-	put_device(&container_of((class_dev), struct node_entry, class_dev)->device);
+	put_device(&container_of((dev), struct node_entry, node_dev)->device);
 }
 
 static struct class nodemgr_ne_class = {
 	.name		= "ieee1394_node",
-	.release	= ne_cls_release,
+	.dev_release	= ne_cls_release,
 };
 
-static void ud_cls_release(struct class_device *class_dev)
+static void ud_cls_release(struct device *dev)
 {
-	put_device(&container_of((class_dev), struct unit_directory, class_dev)->device);
+	put_device(&container_of((dev), struct unit_directory, unit_dev)->device);
 }
 
 /* The name here is only so that unit directory hotplug works with old
- * style hotplug, which only ever did unit directories anyway. */
+ * style hotplug, which only ever did unit directories anyway.
+ */
 static struct class nodemgr_ud_class = {
 	.name		= "ieee1394",
-	.release	= ud_cls_release,
-	.uevent		= nodemgr_uevent,
+	.dev_release	= ud_cls_release,
+	.dev_uevent	= nodemgr_uevent,
 };
 
 static struct hpsb_highlevel nodemgr_highlevel;
@@ -730,11 +730,11 @@
 
 static void nodemgr_remove_uds(struct node_entry *ne)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct unit_directory *tmp, *ud;
 
-	/* Iteration over nodemgr_ud_class.children has to be protected by
-	 * nodemgr_ud_class.sem, but class_device_unregister() will eventually
+	/* Iteration over nodemgr_ud_class.devices has to be protected by
+	 * nodemgr_ud_class.sem, but device_unregister() will eventually
 	 * take nodemgr_ud_class.sem too. Therefore pick out one ud at a time,
 	 * release the semaphore, and then unregister the ud. Since this code
 	 * may be called from other contexts besides the knodemgrds, protect the
@@ -744,9 +744,9 @@
 	for (;;) {
 		ud = NULL;
 		down(&nodemgr_ud_class.sem);
-		list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-			tmp = container_of(cdev, struct unit_directory,
-					   class_dev);
+		list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+			tmp = container_of(dev, struct unit_directory,
+					   unit_dev);
 			if (tmp->ne == ne) {
 				ud = tmp;
 				break;
@@ -755,7 +755,7 @@
 		up(&nodemgr_ud_class.sem);
 		if (ud == NULL)
 			break;
-		class_device_unregister(&ud->class_dev);
+		device_unregister(&ud->unit_dev);
 		device_unregister(&ud->device);
 	}
 	mutex_unlock(&nodemgr_serialize_remove_uds);
@@ -772,10 +772,9 @@
 
 	HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
 		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
-
 	nodemgr_remove_uds(ne);
 
-	class_device_unregister(&ne->class_dev);
+	device_unregister(&ne->node_dev);
 	device_unregister(dev);
 
 	put_device(dev);
@@ -783,7 +782,9 @@
 
 static int __nodemgr_remove_host_dev(struct device *dev, void *data)
 {
-	nodemgr_remove_ne(container_of(dev, struct node_entry, device));
+	if (dev->bus == &ieee1394_bus_type)
+		nodemgr_remove_ne(container_of(dev, struct node_entry,
+				  device));
 	return 0;
 }
 
@@ -850,14 +851,14 @@
 	snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx",
 		 (unsigned long long)(ne->guid));
 
-	ne->class_dev.dev = &ne->device;
-	ne->class_dev.class = &nodemgr_ne_class;
-	snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx",
-		 (unsigned long long)(ne->guid));
+	ne->node_dev.parent = &ne->device;
+	ne->node_dev.class = &nodemgr_ne_class;
+	snprintf(ne->node_dev.bus_id, BUS_ID_SIZE, "%016Lx",
+		(unsigned long long)(ne->guid));
 
 	if (device_register(&ne->device))
 		goto fail_devreg;
-	if (class_device_register(&ne->class_dev))
+	if (device_register(&ne->node_dev))
 		goto fail_classdevreg;
 	get_device(&ne->device);
 
@@ -885,12 +886,12 @@
 
 static struct node_entry *find_entry_by_guid(u64 guid)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct node_entry *ne, *ret_ne = NULL;
 
 	down(&nodemgr_ne_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 
 		if (ne->guid == guid) {
 			ret_ne = ne;
@@ -906,12 +907,12 @@
 static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
 					       nodeid_t nodeid)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct node_entry *ne, *ret_ne = NULL;
 
 	down(&nodemgr_ne_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 
 		if (ne->host == host && ne->nodeid == nodeid) {
 			ret_ne = ne;
@@ -935,14 +936,14 @@
 	snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
 		 ne->device.bus_id, ud->id);
 
-	ud->class_dev.dev = &ud->device;
-	ud->class_dev.class = &nodemgr_ud_class;
-	snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
+	ud->unit_dev.parent = &ud->device;
+	ud->unit_dev.class = &nodemgr_ud_class;
+	snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u",
 		 ne->device.bus_id, ud->id);
 
 	if (device_register(&ud->device))
 		goto fail_devreg;
-	if (class_device_register(&ud->class_dev))
+	if (device_register(&ud->unit_dev))
 		goto fail_classdevreg;
 	get_device(&ud->device);
 
@@ -1159,7 +1160,7 @@
 
 #ifdef CONFIG_HOTPLUG
 
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
 			  char *buffer, int buffer_size)
 {
 	struct unit_directory *ud;
@@ -1169,10 +1170,10 @@
 	/* ieee1394:venNmoNspNverN */
 	char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
 
-	if (!cdev)
+	if (!dev)
 		return -ENODEV;
 
-	ud = container_of(cdev, struct unit_directory, class_dev);
+	ud = container_of(dev, struct unit_directory, unit_dev);
 
 	if (ud->ne->in_limbo || ud->ignore_driver)
 		return -ENODEV;
@@ -1207,7 +1208,7 @@
 
 #else
 
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
 			  char *buffer, int buffer_size)
 {
 	return -ENODEV;
@@ -1378,8 +1379,10 @@
 
 static void nodemgr_suspend_ne(struct node_entry *ne)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct unit_directory *ud;
+	struct device_driver *drv;
+	int error;
 
 	HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
 		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
@@ -1388,15 +1391,24 @@
 	WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
 
 	down(&nodemgr_ud_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-		ud = container_of(cdev, struct unit_directory, class_dev);
+	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+		ud = container_of(dev, struct unit_directory, unit_dev);
 		if (ud->ne != ne)
 			continue;
 
-		if (ud->device.driver &&
-		    (!ud->device.driver->suspend ||
-		      ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
+		drv = get_driver(ud->device.driver);
+		if (!drv)
+			continue;
+
+		error = 1; /* release if suspend is not implemented */
+		if (drv->suspend) {
+			down(&ud->device.sem);
+			error = drv->suspend(&ud->device, PMSG_SUSPEND);
+			up(&ud->device.sem);
+		}
+		if (error)
 			device_release_driver(&ud->device);
+		put_driver(drv);
 	}
 	up(&nodemgr_ud_class.sem);
 }
@@ -1404,20 +1416,29 @@
 
 static void nodemgr_resume_ne(struct node_entry *ne)
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct unit_directory *ud;
+	struct device_driver *drv;
 
 	ne->in_limbo = 0;
 	device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
 
 	down(&nodemgr_ud_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-		ud = container_of(cdev, struct unit_directory, class_dev);
+	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+		ud = container_of(dev, struct unit_directory, unit_dev);
 		if (ud->ne != ne)
 			continue;
 
-		if (ud->device.driver && ud->device.driver->resume)
-			ud->device.driver->resume(&ud->device);
+		drv = get_driver(ud->device.driver);
+		if (!drv)
+			continue;
+
+		if (drv->resume) {
+			down(&ud->device.sem);
+			drv->resume(&ud->device);
+			up(&ud->device.sem);
+		}
+		put_driver(drv);
 	}
 	up(&nodemgr_ud_class.sem);
 
@@ -1428,23 +1449,32 @@
 
 static void nodemgr_update_pdrv(struct node_entry *ne)
 {
+	struct device *dev;
 	struct unit_directory *ud;
+	struct device_driver *drv;
 	struct hpsb_protocol_driver *pdrv;
-	struct class_device *cdev;
+	int error;
 
 	down(&nodemgr_ud_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
-		ud = container_of(cdev, struct unit_directory, class_dev);
+	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+		ud = container_of(dev, struct unit_directory, unit_dev);
 		if (ud->ne != ne)
 			continue;
 
-		if (ud->device.driver) {
-			pdrv = container_of(ud->device.driver,
-					    struct hpsb_protocol_driver,
-					    driver);
-			if (pdrv->update && pdrv->update(ud))
-				device_release_driver(&ud->device);
+		drv = get_driver(ud->device.driver);
+		if (!drv)
+			continue;
+
+		error = 0;
+		pdrv = container_of(drv, struct hpsb_protocol_driver, driver);
+		if (pdrv->update) {
+			down(&ud->device.sem);
+			error = pdrv->update(ud);
+			up(&ud->device.sem);
 		}
+		if (error)
+			device_release_driver(&ud->device);
+		put_driver(drv);
 	}
 	up(&nodemgr_ud_class.sem);
 }
@@ -1509,7 +1539,7 @@
 static void nodemgr_node_probe(struct host_info *hi, int generation)
 {
 	struct hpsb_host *host = hi->host;
-	struct class_device *cdev;
+	struct device *dev;
 	struct node_entry *ne;
 
 	/* Do some processing of the nodes we've probed. This pulls them
@@ -1522,13 +1552,13 @@
 	 * improvement...) */
 
 	down(&nodemgr_ne_class.sem);
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 		if (!ne->needs_probe)
 			nodemgr_probe_ne(hi, ne, generation);
 	}
-	list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
-		ne = container_of(cdev, struct node_entry, class_dev);
+	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+		ne = container_of(dev, struct node_entry, node_dev);
 		if (ne->needs_probe)
 			nodemgr_probe_ne(hi, ne, generation);
 	}
@@ -1686,18 +1716,12 @@
 		if (kthread_should_stop())
 			goto exit;
 
-		if (mutex_lock_interruptible(&nodemgr_serialize)) {
-			if (try_to_freeze())
-				continue;
-			goto exit;
-		}
-
 		/* Pause for 1/4 second in 1/16 second intervals,
 		 * to make sure things settle down. */
 		g = get_hpsb_generation(host);
 		for (i = 0; i < 4 ; i++) {
 			if (msleep_interruptible(63) || kthread_should_stop())
-				goto unlock_exit;
+				goto exit;
 
 			/* Now get the generation in which the node ID's we collect
 			 * are valid.  During the bus scan we will use this generation
@@ -1715,7 +1739,6 @@
 		if (!nodemgr_check_irm_capability(host, reset_cycles) ||
 		    !nodemgr_do_irm_duties(host, reset_cycles)) {
 			reset_cycles++;
-			mutex_unlock(&nodemgr_serialize);
 			continue;
 		}
 		reset_cycles = 0;
@@ -1732,11 +1755,7 @@
 
 		/* Update some of our sysfs symlinks */
 		nodemgr_update_host_dev_links(host);
-
-		mutex_unlock(&nodemgr_serialize);
 	}
-unlock_exit:
-	mutex_unlock(&nodemgr_serialize);
 exit:
 	HPSB_VERBOSE("NodeMgr: Exiting thread");
 	return 0;
@@ -1756,13 +1775,13 @@
  */
 int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
 {
-	struct class_device *cdev;
+	struct device *dev;
 	struct hpsb_host *host;
 	int error = 0;
 
 	down(&hpsb_host_class.sem);
-	list_for_each_entry(cdev, &hpsb_host_class.children, node) {
-		host = container_of(cdev, struct hpsb_host, class_dev);
+	list_for_each_entry(dev, &hpsb_host_class.devices, node) {
+		host = container_of(dev, struct hpsb_host, host_dev);
 
 		if ((error = cb(host, data)))
 			break;
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 4530b29..919e92e 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -84,7 +84,7 @@
 	int length;		/* Number of quadlets */
 
 	struct device device;
-	struct class_device class_dev;
+	struct device unit_dev;
 
 	struct csr1212_keyval *ud_kv;
 	u32 lun;		/* logical unit number immediate value */
@@ -107,7 +107,7 @@
 	u32 capabilities;
 
 	struct device device;
-	struct class_device class_dev;
+	struct device node_dev;
 
 	/* Means this node is not attached anymore */
 	int in_limbo;
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 5dadfd2..5667c81 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -138,19 +138,6 @@
 #define DBGMSG(fmt, args...) do {} while (0)
 #endif
 
-#ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG
-#define OHCI_DMA_ALLOC(fmt, args...) \
-	HPSB_ERR("%s(%s)alloc(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
-		++global_outstanding_dmas, ## args)
-#define OHCI_DMA_FREE(fmt, args...) \
-	HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
-		--global_outstanding_dmas, ## args)
-static int global_outstanding_dmas = 0;
-#else
-#define OHCI_DMA_ALLOC(fmt, args...) do {} while (0)
-#define OHCI_DMA_FREE(fmt, args...) do {} while (0)
-#endif
-
 /* print general (card independent) information */
 #define PRINT_G(level, fmt, args...) \
 printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
@@ -170,7 +157,6 @@
 static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
 			     enum context_type type, int ctx, int num_desc,
 			     int buf_size, int split_buf_size, int context_base);
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d);
 static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
 
 static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
@@ -533,9 +519,6 @@
 	initialize_dma_trm_ctx(&ohci->at_req_context);
 	initialize_dma_trm_ctx(&ohci->at_resp_context);
 	
-	/* Initialize IR Legacy DMA channel mask */
-	ohci->ir_legacy_channels = 0;
-
 	/* Accept AR requests from all nodes */
 	reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
 
@@ -733,7 +716,6 @@
                                 pci_map_single(ohci->dev, packet->data,
                                                packet->data_size,
                                                PCI_DMA_TODEVICE));
-			OHCI_DMA_ALLOC("single, block transmit packet");
 
                         d->prg_cpu[idx]->end.branchAddress = 0;
                         d->prg_cpu[idx]->end.status = 0;
@@ -783,7 +765,6 @@
                 d->prg_cpu[idx]->end.address = cpu_to_le32(
 				pci_map_single(ohci->dev, packet->data,
 				packet->data_size, PCI_DMA_TODEVICE));
-		OHCI_DMA_ALLOC("single, iso transmit packet");
 
                 d->prg_cpu[idx]->end.branchAddress = 0;
                 d->prg_cpu[idx]->end.status = 0;
@@ -884,36 +865,9 @@
 		return -EOVERFLOW;
 	}
 
-	/* Decide whether we have an iso, a request, or a response packet */
 	if (packet->type == hpsb_raw)
 		d = &ohci->at_req_context;
-	else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) {
-		/* The legacy IT DMA context is initialized on first
-		 * use.  However, the alloc cannot be run from
-		 * interrupt context, so we bail out if that is the
-		 * case. I don't see anyone sending ISO packets from
-		 * interrupt context anyway... */
-
-		if (ohci->it_legacy_context.ohci == NULL) {
-			if (in_interrupt()) {
-				PRINT(KERN_ERR,
-				      "legacy IT context cannot be initialized during interrupt");
-				return -EINVAL;
-			}
-
-			if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context,
-					      DMA_CTX_ISO, 0, IT_NUM_DESC,
-					      OHCI1394_IsoXmitContextBase) < 0) {
-				PRINT(KERN_ERR,
-				      "error initializing legacy IT context");
-				return -ENOMEM;
-			}
-
-			initialize_dma_trm_ctx(&ohci->it_legacy_context);
-		}
-
-		d = &ohci->it_legacy_context;
-	} else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
+	else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
 		d = &ohci->at_resp_context;
 	else
 		d = &ohci->at_req_context;
@@ -932,9 +886,7 @@
 static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
 {
 	struct ti_ohci *ohci = host->hostdata;
-	int retval = 0;
-	unsigned long flags;
-	int phy_reg;
+	int retval = 0, phy_reg;
 
 	switch (cmd) {
 	case RESET_BUS:
@@ -1027,117 +979,6 @@
 		dma_trm_reset(&ohci->at_resp_context);
 		break;
 
-	case ISO_LISTEN_CHANNEL:
-        {
-		u64 mask;
-		struct dma_rcv_ctx *d = &ohci->ir_legacy_context;
-		int ir_legacy_active;
-
-		if (arg<0 || arg>63) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 listen channel %d is out of range",
-			      __FUNCTION__, arg);
-			return -EFAULT;
-		}
-
-		mask = (u64)0x1<<arg;
-
-                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
-		if (ohci->ISO_channel_usage & mask) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 listen channel %d is already used",
-			      __FUNCTION__, arg);
-			spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-			return -EFAULT;
-		}
-
-		ir_legacy_active = ohci->ir_legacy_channels;
-
-		ohci->ISO_channel_usage |= mask;
-		ohci->ir_legacy_channels |= mask;
-
-                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-
-		if (!ir_legacy_active) {
-			if (ohci1394_register_iso_tasklet(ohci,
-					  &ohci->ir_legacy_tasklet) < 0) {
-				PRINT(KERN_ERR, "No IR DMA context available");
-				return -EBUSY;
-			}
-
-			/* the IR context can be assigned to any DMA context
-			 * by ohci1394_register_iso_tasklet */
-			d->ctx = ohci->ir_legacy_tasklet.context;
-			d->ctrlSet = OHCI1394_IsoRcvContextControlSet +
-				32*d->ctx;
-			d->ctrlClear = OHCI1394_IsoRcvContextControlClear +
-				32*d->ctx;
-			d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
-			d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
-
-			initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
-
-			if (printk_ratelimit())
-				DBGMSG("IR legacy activated");
-		}
-
-                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
-		if (arg>31)
-			reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
-				  1<<(arg-32));
-		else
-			reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet,
-				  1<<arg);
-
-                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-                DBGMSG("Listening enabled on channel %d", arg);
-                break;
-        }
-	case ISO_UNLISTEN_CHANNEL:
-        {
-		u64 mask;
-
-		if (arg<0 || arg>63) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 unlisten channel %d is out of range",
-			      __FUNCTION__, arg);
-			return -EFAULT;
-		}
-
-		mask = (u64)0x1<<arg;
-
-                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
-		if (!(ohci->ISO_channel_usage & mask)) {
-			PRINT(KERN_ERR,
-			      "%s: IS0 unlisten channel %d is not used",
-			      __FUNCTION__, arg);
-			spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-			return -EFAULT;
-		}
-
-		ohci->ISO_channel_usage &= ~mask;
-		ohci->ir_legacy_channels &= ~mask;
-
-		if (arg>31)
-			reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear,
-				  1<<(arg-32));
-		else
-			reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear,
-				  1<<arg);
-
-                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-                DBGMSG("Listening disabled on channel %d", arg);
-
-		if (ohci->ir_legacy_channels == 0) {
-			stop_dma_rcv_ctx(&ohci->ir_legacy_context);
-			DBGMSG("ISO legacy receive context stopped");
-		}
-
-                break;
-        }
 	default:
 		PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet",
 			cmd);
@@ -2869,12 +2710,10 @@
 		list_del_init(&packet->driver_list);
 		hpsb_packet_sent(ohci->host, packet, ack);
 
-		if (datasize) {
+		if (datasize)
 			pci_unmap_single(ohci->dev,
 					 cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address),
 					 datasize, PCI_DMA_TODEVICE);
-			OHCI_DMA_FREE("single Xmit data packet");
-		}
 
 		d->sent_ind = (d->sent_ind+1)%d->num_desc;
 		d->free_prgs++;
@@ -2885,22 +2724,6 @@
 	spin_unlock_irqrestore(&d->lock, flags);
 }
 
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d)
-{
-	if (d->ctrlClear) {
-		ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
-
-		if (d->type == DMA_CTX_ISO) {
-			/* disable interrupts */
-			reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx);
-			ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet);
-		} else {
-			tasklet_kill(&d->task);
-		}
-	}
-}
-
-
 static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
 {
 	int i;
@@ -2913,23 +2736,19 @@
 
 	if (d->buf_cpu) {
 		for (i=0; i<d->num_desc; i++)
-			if (d->buf_cpu[i] && d->buf_bus[i]) {
+			if (d->buf_cpu[i] && d->buf_bus[i])
 				pci_free_consistent(
 					ohci->dev, d->buf_size,
 					d->buf_cpu[i], d->buf_bus[i]);
-				OHCI_DMA_FREE("consistent dma_rcv buf[%d]", i);
-			}
 		kfree(d->buf_cpu);
 		kfree(d->buf_bus);
 	}
 	if (d->prg_cpu) {
 		for (i=0; i<d->num_desc; i++)
-			if (d->prg_cpu[i] && d->prg_bus[i]) {
-				pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
-				OHCI_DMA_FREE("consistent dma_rcv prg[%d]", i);
-			}
+			if (d->prg_cpu[i] && d->prg_bus[i])
+				pci_pool_free(d->prg_pool, d->prg_cpu[i],
+					      d->prg_bus[i]);
 		pci_pool_destroy(d->prg_pool);
-		OHCI_DMA_FREE("dma_rcv prg pool");
 		kfree(d->prg_cpu);
 		kfree(d->prg_bus);
 	}
@@ -2998,13 +2817,10 @@
 	}
 	num_allocs++;
 
-	OHCI_DMA_ALLOC("dma_rcv prg pool");
-
 	for (i=0; i<d->num_desc; i++) {
 		d->buf_cpu[i] = pci_alloc_consistent(ohci->dev,
 						     d->buf_size,
 						     d->buf_bus+i);
-		OHCI_DMA_ALLOC("consistent dma_rcv buf[%d]", i);
 
 		if (d->buf_cpu[i] != NULL) {
 			memset(d->buf_cpu[i], 0, d->buf_size);
@@ -3016,7 +2832,6 @@
 		}
 
 		d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
-		OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i);
 
                 if (d->prg_cpu[i] != NULL) {
                         memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
@@ -3030,18 +2845,11 @@
 
         spin_lock_init(&d->lock);
 
-	if (type == DMA_CTX_ISO) {
-		ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet,
-					  OHCI_ISO_MULTICHANNEL_RECEIVE,
-					  dma_rcv_tasklet, (unsigned long) d);
-	} else {
-		d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-		d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-		d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+	d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+	d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+	d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
 
-		tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d);
-	}
-
+	tasklet_init(&d->task, dma_rcv_tasklet, (unsigned long) d);
 	return 0;
 }
 
@@ -3057,12 +2865,10 @@
 
 	if (d->prg_cpu) {
 		for (i=0; i<d->num_desc; i++)
-			if (d->prg_cpu[i] && d->prg_bus[i]) {
-				pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
-				OHCI_DMA_FREE("pool dma_trm prg[%d]", i);
-			}
+			if (d->prg_cpu[i] && d->prg_bus[i])
+				pci_pool_free(d->prg_pool, d->prg_cpu[i],
+					      d->prg_bus[i]);
 		pci_pool_destroy(d->prg_pool);
-		OHCI_DMA_FREE("dma_trm prg pool");
 		kfree(d->prg_cpu);
 		kfree(d->prg_bus);
 	}
@@ -3108,11 +2914,8 @@
 	}
 	num_allocs++;
 
-	OHCI_DMA_ALLOC("dma_rcv prg pool");
-
 	for (i = 0; i < d->num_desc; i++) {
 		d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
-		OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i);
 
                 if (d->prg_cpu[i] != NULL) {
                         memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
@@ -3127,28 +2930,10 @@
         spin_lock_init(&d->lock);
 
 	/* initialize tasklet */
-	if (type == DMA_CTX_ISO) {
-		ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT,
-					  dma_trm_tasklet, (unsigned long) d);
-		if (ohci1394_register_iso_tasklet(ohci,
-						  &ohci->it_legacy_tasklet) < 0) {
-			PRINT(KERN_ERR, "No IT DMA context available");
-			free_dma_trm_ctx(d);
-			return -EBUSY;
-		}
-
-		/* IT can be assigned to any context by register_iso_tasklet */
-		d->ctx = ohci->it_legacy_tasklet.context;
-		d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx;
-		d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx;
-		d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx;
-	} else {
-		d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-		d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-		d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
-		tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d);
-	}
-
+	d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+	d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+	d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+	tasklet_init(&d->task, dma_trm_tasklet, (unsigned long)d);
 	return 0;
 }
 
@@ -3294,7 +3079,6 @@
 	ohci->csr_config_rom_cpu =
 		pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
 				     &ohci->csr_config_rom_bus);
-	OHCI_DMA_ALLOC("consistent csr_config_rom");
 	if (ohci->csr_config_rom_cpu == NULL)
 		FAIL(-ENOMEM, "Failed to allocate buffer config rom");
 	ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
@@ -3303,8 +3087,6 @@
 	ohci->selfid_buf_cpu =
 		pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
                       &ohci->selfid_buf_bus);
-	OHCI_DMA_ALLOC("consistent selfid_buf");
-
 	if (ohci->selfid_buf_cpu == NULL)
 		FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets");
 	ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
@@ -3377,20 +3159,6 @@
 	ohci->ISO_channel_usage = 0;
         spin_lock_init(&ohci->IR_channel_lock);
 
-	/* Allocate the IR DMA context right here so we don't have
-	 * to do it in interrupt path - note that this doesn't
-	 * waste much memory and avoids the jugglery required to
-	 * allocate it in IRQ path. */
-	if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
-			      DMA_CTX_ISO, 0, IR_NUM_DESC,
-			      IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
-			      OHCI1394_IsoRcvContextBase) < 0) {
-		FAIL(-ENOMEM, "Cannot allocate IR Legacy DMA context");
-	}
-
-	/* We hopefully don't have to pre-allocate IT DMA like we did
-	 * for IR DMA above. Allocate it on-demand and mark inactive. */
-	ohci->it_legacy_context.ohci = NULL;
 	spin_lock_init(&ohci->event_lock);
 
 	/*
@@ -3483,20 +3251,16 @@
 		free_dma_rcv_ctx(&ohci->ar_resp_context);
 		free_dma_trm_ctx(&ohci->at_req_context);
 		free_dma_trm_ctx(&ohci->at_resp_context);
-		free_dma_rcv_ctx(&ohci->ir_legacy_context);
-		free_dma_trm_ctx(&ohci->it_legacy_context);
 
 	case OHCI_INIT_HAVE_SELFID_BUFFER:
 		pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
 				    ohci->selfid_buf_cpu,
 				    ohci->selfid_buf_bus);
-		OHCI_DMA_FREE("consistent selfid_buf");
 
 	case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
 		pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
 				    ohci->csr_config_rom_cpu,
 				    ohci->csr_config_rom_bus);
-		OHCI_DMA_FREE("consistent csr_config_rom");
 
 	case OHCI_INIT_HAVE_IOMAPPING:
 		iounmap(ohci->registers);
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index f1ad539..4320bf01 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -190,23 +190,10 @@
 	unsigned long ir_multichannel_used; /* ditto */
         spinlock_t IR_channel_lock;
 
-	/* iso receive (legacy API) */
-	u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage;
-				   it only accounts for channels listened to
-				   by the legacy API, so that we can know when
-				   it is safe to free the legacy API context */
-
-	struct dma_rcv_ctx ir_legacy_context;
-	struct ohci1394_iso_tasklet ir_legacy_tasklet;
-
         /* iso transmit */
 	int nb_iso_xmit_ctx;
 	unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
 
-	/* iso transmit (legacy API) */
-	struct dma_trm_ctx it_legacy_context;
-	struct ohci1394_iso_tasklet it_legacy_tasklet;
-
         u64 ISO_channel_usage;
 
         /* IEEE-1394 part follows */
@@ -221,7 +208,6 @@
 
 	/* Tasklets for iso receive and transmit, used by video1394
 	 * and dv1394 */
-
 	struct list_head iso_tasklet_list;
 	spinlock_t iso_tasklet_list_lock;
 
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 0742bef..d1a5bcd 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -477,7 +477,11 @@
         struct lynx_send_data *d;
         struct hpsb_packet *packet;
 
+#if 0 /* has been removed from ieee1394 core */
         d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
+#else
+	d = &lynx->async;
+#endif
         if (!list_empty(&d->pcl_queue)) {
                 PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo");
                 BUG();
@@ -511,9 +515,11 @@
         case hpsb_async:
                 pcl.buffer[0].control |= PCL_CMD_XMT;
                 break;
+#if 0 /* has been removed from ieee1394 core */
         case hpsb_iso:
                 pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
                 break;
+#endif
         case hpsb_raw:
                 pcl.buffer[0].control |= PCL_CMD_UNFXMT;
                 break;
@@ -542,9 +548,11 @@
         case hpsb_raw:
                 d = &lynx->async;
                 break;
+#if 0 /* has been removed from ieee1394 core */
         case hpsb_iso:
                 d = &lynx->iso_send;
                 break;
+#endif
         default:
                 PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
                       packet->type);
@@ -797,7 +805,7 @@
 		}
 
                 break;
-
+#if 0 /* has been removed from ieee1394 core */
         case ISO_LISTEN_CHANNEL:
                 spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
 
@@ -819,7 +827,7 @@
 
                 spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
                 break;
-
+#endif
         default:
                 PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd);
                 retval = -1;
@@ -1009,11 +1017,11 @@
                                 pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
                                                  packet->data_size, PCI_DMA_TODEVICE);
                         }
-
+#if 0 /* has been removed from ieee1394 core */
                         if (!list_empty(&lynx->iso_send.queue)) {
                                 send_next(lynx, hpsb_iso);
                         }
-
+#endif
                         spin_unlock(&lynx->iso_send.queue_lock);
 
                         if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h
index 50daabf..a06aaad 100644
--- a/drivers/ieee1394/raw1394-private.h
+++ b/drivers/ieee1394/raw1394-private.h
@@ -36,11 +36,6 @@
 
         u8 __user *fcp_buffer;
 
-	/* old ISO API */
-        u64 listen_channels;
-        quadlet_t __user *iso_buffer;
-        size_t iso_buffer_length;
-
         u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
 
 	/* new rawiso API */
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index f1d05ee..336e5ff 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -98,21 +98,6 @@
 
 static void queue_complete_cb(struct pending_request *req);
 
-#include <asm/current.h>
-static void print_old_iso_deprecation(void)
-{
-	static pid_t p;
-
-	if (p == current->pid)
-		return;
-	p = current->pid;
-	printk(KERN_WARNING "raw1394: WARNING - Program \"%s\" uses unsupported"
-	       " isochronous request types which will be removed in a next"
-	       " kernel release\n", current->comm);
-	printk(KERN_WARNING "raw1394: Update your software to use libraw1394's"
-	       " newer interface\n");
-}
-
 static struct pending_request *__alloc_pending_request(gfp_t flags)
 {
 	struct pending_request *req;
@@ -297,67 +282,6 @@
 	spin_unlock_irqrestore(&host_info_lock, flags);
 }
 
-static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
-			size_t length)
-{
-	unsigned long flags;
-	struct host_info *hi;
-	struct file_info *fi;
-	struct pending_request *req, *req_next;
-	struct iso_block_store *ibs = NULL;
-	LIST_HEAD(reqs);
-
-	if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
-		HPSB_INFO("dropped iso packet");
-		return;
-	}
-
-	spin_lock_irqsave(&host_info_lock, flags);
-	hi = find_host_info(host);
-
-	if (hi != NULL) {
-		list_for_each_entry(fi, &hi->file_info_list, list) {
-			if (!(fi->listen_channels & (1ULL << channel)))
-				continue;
-
-			req = __alloc_pending_request(GFP_ATOMIC);
-			if (!req)
-				break;
-
-			if (!ibs) {
-				ibs = kmalloc(sizeof(*ibs) + length,
-					      GFP_ATOMIC);
-				if (!ibs) {
-					kfree(req);
-					break;
-				}
-
-				atomic_add(length, &iso_buffer_size);
-				atomic_set(&ibs->refcount, 0);
-				ibs->data_size = length;
-				memcpy(ibs->data, data, length);
-			}
-
-			atomic_inc(&ibs->refcount);
-
-			req->file_info = fi;
-			req->ibs = ibs;
-			req->data = ibs->data;
-			req->req.type = RAW1394_REQ_ISO_RECEIVE;
-			req->req.generation = get_hpsb_generation(host);
-			req->req.misc = 0;
-			req->req.recvb = ptr2int(fi->iso_buffer);
-			req->req.length = min(length, fi->iso_buffer_length);
-
-			list_add_tail(&req->list, &reqs);
-		}
-	}
-	spin_unlock_irqrestore(&host_info_lock, flags);
-
-	list_for_each_entry_safe(req, req_next, &reqs, list)
-	    queue_complete_req(req);
-}
-
 static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
 			int cts, u8 * data, size_t length)
 {
@@ -434,7 +358,11 @@
 
 	__u64 sendb;
 	__u64 recvb;
-} __attribute__((packed));
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
 
 static const char __user *raw1394_compat_write(const char __user *buf)
 {
@@ -459,7 +387,7 @@
 static int
 raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
 {
-	struct compat_raw1394_req __user *cr = (typeof(cr)) r;
+	struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
 	if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||
 	    P(type) ||
 	    P(error) ||
@@ -587,7 +515,7 @@
 
 	req->req.length = 0;
 	queue_complete_req(req);
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int state_initialized(struct file_info *fi, struct pending_request *req)
@@ -601,7 +529,7 @@
 		req->req.generation = atomic_read(&internal_generation);
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	switch (req->req.type) {
@@ -673,44 +601,7 @@
 	}
 
 	queue_complete_req(req);
-	return sizeof(struct raw1394_request);
-}
-
-static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
-{
-	int channel = req->req.misc;
-
-	if ((channel > 63) || (channel < -64)) {
-		req->req.error = RAW1394_ERROR_INVALID_ARG;
-	} else if (channel >= 0) {
-		/* allocate channel req.misc */
-		if (fi->listen_channels & (1ULL << channel)) {
-			req->req.error = RAW1394_ERROR_ALREADY;
-		} else {
-			if (hpsb_listen_channel
-			    (&raw1394_highlevel, fi->host, channel)) {
-				req->req.error = RAW1394_ERROR_ALREADY;
-			} else {
-				fi->listen_channels |= 1ULL << channel;
-				fi->iso_buffer = int2ptr(req->req.recvb);
-				fi->iso_buffer_length = req->req.length;
-			}
-		}
-	} else {
-		/* deallocate channel (one's complement neg) req.misc */
-		channel = ~channel;
-
-		if (fi->listen_channels & (1ULL << channel)) {
-			hpsb_unlisten_channel(&raw1394_highlevel, fi->host,
-					      channel);
-			fi->listen_channels &= ~(1ULL << channel);
-		} else {
-			req->req.error = RAW1394_ERROR_INVALID_ARG;
-		}
-	}
-
-	req->req.length = 0;
-	queue_complete_req(req);
+	return 0;
 }
 
 static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
@@ -865,7 +756,7 @@
 	if (req->req.error) {
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	hpsb_set_packet_complete_task(packet,
@@ -883,51 +774,7 @@
 		hpsb_free_tlabel(packet);
 		queue_complete_req(req);
 	}
-	return sizeof(struct raw1394_request);
-}
-
-static int handle_iso_send(struct file_info *fi, struct pending_request *req,
-			   int channel)
-{
-	unsigned long flags;
-	struct hpsb_packet *packet;
-
-	packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,
-				     (req->req.misc >> 16) & 0x3,
-				     req->req.misc & 0xf);
-	if (!packet)
-		return -ENOMEM;
-
-	packet->speed_code = req->req.address & 0x3;
-
-	req->packet = packet;
-
-	if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-			   req->req.length)) {
-		req->req.error = RAW1394_ERROR_MEMFAULT;
-		req->req.length = 0;
-		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
-	}
-
-	req->req.length = 0;
-	hpsb_set_packet_complete_task(packet,
-				      (void (*)(void *))queue_complete_req,
-				      req);
-
-	spin_lock_irqsave(&fi->reqlists_lock, flags);
-	list_add_tail(&req->list, &fi->req_pending);
-	spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-	/* Update the generation of the packet just before sending. */
-	packet->generation = req->req.generation;
-
-	if (hpsb_send_packet(packet) < 0) {
-		req->req.error = RAW1394_ERROR_SEND_ERROR;
-		queue_complete_req(req);
-	}
-
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int handle_async_send(struct file_info *fi, struct pending_request *req)
@@ -943,7 +790,7 @@
 		req->req.error = RAW1394_ERROR_INVALID_ARG;
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	data_size = req->req.length - header_length;
@@ -957,7 +804,7 @@
 		req->req.error = RAW1394_ERROR_MEMFAULT;
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	if (copy_from_user
@@ -966,7 +813,7 @@
 		req->req.error = RAW1394_ERROR_MEMFAULT;
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	packet->type = hpsb_async;
@@ -994,7 +841,7 @@
 		queue_complete_req(req);
 	}
 
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
@@ -1869,7 +1716,7 @@
 		spin_lock_irqsave(&host_info_lock, flags);
 		list_add_tail(&addr->addr_list, &fi->addr_list);
 		spin_unlock_irqrestore(&host_info_lock, flags);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 	retval =
 	    hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
@@ -1887,7 +1734,7 @@
 		return (-EALREADY);
 	}
 	free_pending_request(req);	/* immediate success or fail */
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int arm_unregister(struct file_info *fi, struct pending_request *req)
@@ -1955,7 +1802,7 @@
 		vfree(addr->addr_space_buffer);
 		kfree(addr);
 		free_pending_request(req);	/* immediate success or fail */
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 	retval =
 	    hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
@@ -1971,7 +1818,7 @@
 	vfree(addr->addr_space_buffer);
 	kfree(addr);
 	free_pending_request(req);	/* immediate success or fail */
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 /* Copy data from ARM buffer(s) to user buffer. */
@@ -2013,7 +1860,7 @@
 				 * queue no response, and therefore nobody
 				 * will free it. */
 				free_pending_request(req);
-				return sizeof(struct raw1394_request);
+				return 0;
 			} else {
 				DBGMSG("arm_get_buf request exceeded mapping");
 				spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2065,7 +1912,7 @@
 				 * queue no response, and therefore nobody
 				 * will free it. */
 				free_pending_request(req);
-				return sizeof(struct raw1394_request);
+				return 0;
 			} else {
 				DBGMSG("arm_set_buf request exceeded mapping");
 				spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2086,7 +1933,7 @@
 	    (req->req.misc == RAW1394_NOTIFY_ON)) {
 		fi->notification = (u8) req->req.misc;
 		free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 	/* error EINVAL (22) invalid argument */
 	return (-EINVAL);
@@ -2119,12 +1966,12 @@
 		req->req.length = 0;
 		queue_complete_req(req);
 	}
-	return sizeof(struct raw1394_request);
+	return 0;
 }
 
 static int get_config_rom(struct file_info *fi, struct pending_request *req)
 {
-	int ret = sizeof(struct raw1394_request);
+	int ret = 0;
 	quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
 	int status;
 
@@ -2154,7 +2001,7 @@
 
 static int update_config_rom(struct file_info *fi, struct pending_request *req)
 {
-	int ret = sizeof(struct raw1394_request);
+	int ret = 0;
 	quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
@@ -2221,7 +2068,7 @@
 
 			hpsb_update_config_rom_image(fi->host);
 			free_pending_request(req);
-			return sizeof(struct raw1394_request);
+			return 0;
 		}
 	}
 
@@ -2286,7 +2133,7 @@
 		/* we have to free the request, because we queue no response,
 		 * and therefore nobody will free it */
 		free_pending_request(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	} else {
 		for (dentry =
 		     fi->csr1212_dirs[dr]->value.directory.dentries_head;
@@ -2311,11 +2158,7 @@
 
 	case RAW1394_REQ_ECHO:
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
-
-	case RAW1394_REQ_ISO_SEND:
-		print_old_iso_deprecation();
-		return handle_iso_send(fi, req, node);
+		return 0;
 
 	case RAW1394_REQ_ARM_REGISTER:
 		return arm_register(fi, req);
@@ -2332,27 +2175,30 @@
 	case RAW1394_REQ_RESET_NOTIFY:
 		return reset_notification(fi, req);
 
+	case RAW1394_REQ_ISO_SEND:
 	case RAW1394_REQ_ISO_LISTEN:
-		print_old_iso_deprecation();
-		handle_iso_listen(fi, req);
-		return sizeof(struct raw1394_request);
+		printk(KERN_DEBUG "raw1394: old iso ABI has been removed\n");
+		req->req.error = RAW1394_ERROR_COMPAT;
+		req->req.misc = RAW1394_KERNELAPI_VERSION;
+		queue_complete_req(req);
+		return 0;
 
 	case RAW1394_REQ_FCP_LISTEN:
 		handle_fcp_listen(fi, req);
-		return sizeof(struct raw1394_request);
+		return 0;
 
 	case RAW1394_REQ_RESET_BUS:
 		if (req->req.misc == RAW1394_LONG_RESET) {
 			DBGMSG("busreset called (type: LONG)");
 			hpsb_reset_bus(fi->host, LONG_RESET);
 			free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
-			return sizeof(struct raw1394_request);
+			return 0;
 		}
 		if (req->req.misc == RAW1394_SHORT_RESET) {
 			DBGMSG("busreset called (type: SHORT)");
 			hpsb_reset_bus(fi->host, SHORT_RESET);
 			free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
-			return sizeof(struct raw1394_request);
+			return 0;
 		}
 		/* error EINVAL (22) invalid argument */
 		return (-EINVAL);
@@ -2371,7 +2217,7 @@
 		req->req.generation = get_hpsb_generation(fi->host);
 		req->req.length = 0;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	switch (req->req.type) {
@@ -2384,7 +2230,7 @@
 	if (req->req.length == 0) {
 		req->req.error = RAW1394_ERROR_INVALID_ARG;
 		queue_complete_req(req);
-		return sizeof(struct raw1394_request);
+		return 0;
 	}
 
 	return handle_async_request(fi, req, node);
@@ -2395,7 +2241,7 @@
 {
 	struct file_info *fi = (struct file_info *)file->private_data;
 	struct pending_request *req;
-	ssize_t retval = 0;
+	ssize_t retval = -EBADFD;
 
 #ifdef CONFIG_COMPAT
 	if (count == sizeof(struct compat_raw1394_req) &&
@@ -2437,6 +2283,9 @@
 
 	if (retval < 0) {
 		free_pending_request(req);
+	} else {
+		BUG_ON(retval);
+		retval = count;
 	}
 
 	return retval;
@@ -2802,6 +2651,103 @@
 	return -EINVAL;
 }
 
+#ifdef CONFIG_COMPAT
+struct raw1394_iso_packets32 {
+        __u32 n_packets;
+        compat_uptr_t infos;
+} __attribute__((packed));
+
+struct raw1394_cycle_timer32 {
+        __u32 cycle_timer;
+        __u64 local_time;
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
+
+#define RAW1394_IOC_ISO_RECV_PACKETS32          \
+        _IOW ('#', 0x25, struct raw1394_iso_packets32)
+#define RAW1394_IOC_ISO_XMIT_PACKETS32          \
+        _IOW ('#', 0x27, struct raw1394_iso_packets32)
+#define RAW1394_IOC_GET_CYCLE_TIMER32           \
+        _IOR ('#', 0x30, struct raw1394_cycle_timer32)
+
+static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
+                                          struct raw1394_iso_packets32 __user *arg)
+{
+	compat_uptr_t infos32;
+	void *infos;
+	long err = -EFAULT;
+	struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets));
+
+	if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) &&
+	    !copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
+		infos = compat_ptr(infos32);
+		if (!copy_to_user(&dst->infos, &infos, sizeof infos))
+			err = raw1394_ioctl(NULL, file, cmd, (unsigned long)dst);
+	}
+	return err;
+}
+
+static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr)
+{
+	struct raw1394_cycle_timer32 ct;
+	int err;
+
+	err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
+	if (!err)
+		if (copy_to_user(uaddr, &ct, sizeof(ct)))
+			err = -EFAULT;
+	return err;
+}
+
+static long raw1394_compat_ioctl(struct file *file,
+				 unsigned int cmd, unsigned long arg)
+{
+	struct file_info *fi = file->private_data;
+	void __user *argp = (void __user *)arg;
+	long err;
+
+	lock_kernel();
+	switch (cmd) {
+	/* These requests have same format as long as 'int' has same size. */
+	case RAW1394_IOC_ISO_RECV_INIT:
+	case RAW1394_IOC_ISO_RECV_START:
+	case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
+	case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
+	case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:
+	case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
+	case RAW1394_IOC_ISO_RECV_FLUSH:
+	case RAW1394_IOC_ISO_XMIT_RECV_STOP:
+	case RAW1394_IOC_ISO_XMIT_INIT:
+	case RAW1394_IOC_ISO_XMIT_START:
+	case RAW1394_IOC_ISO_XMIT_SYNC:
+	case RAW1394_IOC_ISO_GET_STATUS:
+	case RAW1394_IOC_ISO_SHUTDOWN:
+	case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+		err = raw1394_ioctl(NULL, file, cmd, arg);
+		break;
+	/* These request have different format. */
+	case RAW1394_IOC_ISO_RECV_PACKETS32:
+		err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp);
+		break;
+	case RAW1394_IOC_ISO_XMIT_PACKETS32:
+		err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp);
+		break;
+	case RAW1394_IOC_GET_CYCLE_TIMER32:
+		err = raw1394_read_cycle_timer32(fi, argp);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+	unlock_kernel();
+
+	return err;
+}
+#endif
+
 static unsigned int raw1394_poll(struct file *file, poll_table * pt)
 {
 	struct file_info *fi = file->private_data;
@@ -2861,14 +2807,7 @@
 	if (fi->iso_state != RAW1394_ISO_INACTIVE)
 		raw1394_iso_shutdown(fi);
 
-	for (i = 0; i < 64; i++) {
-		if (fi->listen_channels & (1ULL << i)) {
-			hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
-		}
-	}
-
 	spin_lock_irqsave(&host_info_lock, flags);
-	fi->listen_channels = 0;
 
 	fail = 0;
 	/* set address-entries invalid */
@@ -3030,7 +2969,6 @@
 	.add_host = add_host,
 	.remove_host = remove_host,
 	.host_reset = host_reset,
-	.iso_receive = iso_receive,
 	.fcp_request = fcp_request,
 };
 
@@ -3041,7 +2979,9 @@
 	.write = raw1394_write,
 	.mmap = raw1394_mmap,
 	.ioctl = raw1394_ioctl,
-	// .compat_ioctl = ... someone needs to do this
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = raw1394_compat_ioctl,
+#endif
 	.poll = raw1394_poll,
 	.open = raw1394_open,
 	.release = raw1394_release,
@@ -3054,9 +2994,9 @@
 	hpsb_register_highlevel(&raw1394_highlevel);
 
 	if (IS_ERR
-	    (class_device_create
-	     (hpsb_protocol_class, NULL,
-	      MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL,
+	    (device_create(
+	      hpsb_protocol_class, NULL,
+	      MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
 	      RAW1394_DEVICE_NAME))) {
 		ret = -EFAULT;
 		goto out_unreg;
@@ -3083,9 +3023,9 @@
 	goto out;
 
       out_dev:
-	class_device_destroy(hpsb_protocol_class,
-			     MKDEV(IEEE1394_MAJOR,
-				   IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+	device_destroy(hpsb_protocol_class,
+		       MKDEV(IEEE1394_MAJOR,
+			     IEEE1394_MINOR_BLOCK_RAW1394 * 16));
       out_unreg:
 	hpsb_unregister_highlevel(&raw1394_highlevel);
       out:
@@ -3094,9 +3034,9 @@
 
 static void __exit cleanup_raw1394(void)
 {
-	class_device_destroy(hpsb_protocol_class,
-			     MKDEV(IEEE1394_MAJOR,
-				   IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+	device_destroy(hpsb_protocol_class,
+		       MKDEV(IEEE1394_MAJOR,
+			     IEEE1394_MINOR_BLOCK_RAW1394 * 16));
 	cdev_del(&raw1394_cdev);
 	hpsb_unregister_highlevel(&raw1394_highlevel);
 	hpsb_unregister_protocol(&raw1394_driver);
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
index 7bd22ee..963ac20 100644
--- a/drivers/ieee1394/raw1394.h
+++ b/drivers/ieee1394/raw1394.h
@@ -17,11 +17,11 @@
 #define RAW1394_REQ_ASYNC_WRITE     101
 #define RAW1394_REQ_LOCK            102
 #define RAW1394_REQ_LOCK64          103
-#define RAW1394_REQ_ISO_SEND        104
+#define RAW1394_REQ_ISO_SEND        104 /* removed ABI, now a no-op */
 #define RAW1394_REQ_ASYNC_SEND      105
 #define RAW1394_REQ_ASYNC_STREAM    106
 
-#define RAW1394_REQ_ISO_LISTEN      200
+#define RAW1394_REQ_ISO_LISTEN      200 /* removed ABI, now a no-op */
 #define RAW1394_REQ_FCP_LISTEN      201
 #define RAW1394_REQ_RESET_BUS       202
 #define RAW1394_REQ_GET_ROM         203
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 3f873cc7..e0c385a 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -118,14 +118,13 @@
 		 "(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");
 
 /*
- * Set serialize_io to 1 if you'd like only one scsi command sent
- * down to us at a time (debugging). This might be necessary for very
- * badly behaved sbp2 devices.
+ * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
+ * This is and always has been buggy in multiple subtle ways. See above TODOs.
  */
 static int sbp2_serialize_io = 1;
-module_param_named(serialize_io, sbp2_serialize_io, int, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers "
-		 "(default = 1, faster = 0)");
+module_param_named(serialize_io, sbp2_serialize_io, bool, 0444);
+MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
+		 "(default = Y, faster but buggy = N)");
 
 /*
  * Bump up max_sectors if you'd like to support very large sized
@@ -154,9 +153,9 @@
  * are possible on OXFW911 and newer Oxsemi bridges.
  */
 static int sbp2_exclusive_login = 1;
-module_param_named(exclusive_login, sbp2_exclusive_login, int, 0644);
+module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644);
 MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
-		 "(default = 1)");
+		 "(default = Y, use N for concurrent initiators)");
 
 /*
  * If any of the following workarounds is required for your device to work,
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 44402b9..333a4bb 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -67,7 +67,7 @@
 #define ORB_SET_LUN(v)			((v) & 0xffff)
 #define ORB_SET_FUNCTION(v)		(((v) & 0xf) << 16)
 #define ORB_SET_RECONNECT(v)		(((v) & 0xf) << 20)
-#define ORB_SET_EXCLUSIVE(v)		(((v) & 0x1) << 28)
+#define ORB_SET_EXCLUSIVE(v)		((v) ? 1 << 28 : 0)
 #define ORB_SET_LOGIN_RESP_LENGTH(v)	((v) & 0xffff)
 #define ORB_SET_PASSWD_LENGTH(v)	(((v) & 0xffff) << 16)
 
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 87ebd08..bd28adf 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1340,9 +1340,9 @@
 	hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
 
 	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
-	class_device_create(hpsb_protocol_class, NULL, MKDEV(
-		IEEE1394_MAJOR,	minor), 
-		NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+	device_create(hpsb_protocol_class, NULL,
+		      MKDEV(IEEE1394_MAJOR, minor),
+		      "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
 }
 
 
@@ -1351,8 +1351,8 @@
 	struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
 
 	if (ohci)
-		class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
-			IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
+		device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+			       IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
 	return;
 }
 
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index be6b93c..ab4b2d9 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -30,6 +30,7 @@
 	wait_queue_head_t wait;
 	struct evdev_client *grab;
 	struct list_head client_list;
+	struct device dev;
 };
 
 struct evdev_client {
@@ -94,8 +95,10 @@
 	return input_flush_device(&evdev->handle, file);
 }
 
-static void evdev_free(struct evdev *evdev)
+static void evdev_free(struct device *dev)
 {
+	struct evdev *evdev = container_of(dev, struct evdev, dev);
+
 	evdev_table[evdev->minor] = NULL;
 	kfree(evdev);
 }
@@ -114,12 +117,10 @@
 	list_del(&client->node);
 	kfree(client);
 
-	if (!--evdev->open) {
-		if (evdev->exist)
-			input_close_device(&evdev->handle);
-		else
-			evdev_free(evdev);
-	}
+	if (!--evdev->open && evdev->exist)
+		input_close_device(&evdev->handle);
+
+	put_device(&evdev->dev);
 
 	return 0;
 }
@@ -139,24 +140,32 @@
 	if (!evdev || !evdev->exist)
 		return -ENODEV;
 
+	get_device(&evdev->dev);
+
 	client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_evdev;
+	}
 
 	client->evdev = evdev;
 	list_add_tail(&client->node, &evdev->client_list);
 
 	if (!evdev->open++ && evdev->exist) {
 		error = input_open_device(&evdev->handle);
-		if (error) {
-			list_del(&client->node);
-			kfree(client);
-			return error;
-		}
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_evdev:
+	put_device(&evdev->dev);
+	return error;
 }
 
 #ifdef CONFIG_COMPAT
@@ -625,8 +634,6 @@
 			 const struct input_device_id *id)
 {
 	struct evdev *evdev;
-	struct class_device *cdev;
-	dev_t devt;
 	int minor;
 	int error;
 
@@ -649,38 +656,32 @@
 	evdev->handle.name = evdev->name;
 	evdev->handle.handler = handler;
 	evdev->handle.private = evdev;
-	sprintf(evdev->name, "event%d", minor);
+	snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
+
+	snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id),
+		 "event%d", minor);
+	evdev->dev.class = &input_class;
+	evdev->dev.parent = &dev->dev;
+	evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
+	evdev->dev.release = evdev_free;
+	device_initialize(&evdev->dev);
 
 	evdev_table[minor] = evdev;
 
-	devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-
-	cdev = class_device_create(&input_class, &dev->cdev, devt,
-				   dev->cdev.dev, evdev->name);
-	if (IS_ERR(cdev)) {
-		error = PTR_ERR(cdev);
-		goto err_free_evdev;
-	}
-
-	/* temporary symlink to keep userspace happy */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, evdev->name);
+	error = device_add(&evdev->dev);
 	if (error)
-		goto err_cdev_destroy;
+		goto err_free_evdev;
 
 	error = input_register_handle(&evdev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_evdev;
 
 	return 0;
 
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
+ err_delete_evdev:
+	device_del(&evdev->dev);
  err_free_evdev:
-	kfree(evdev);
-	evdev_table[minor] = NULL;
+	put_device(&evdev->dev);
 	return error;
 }
 
@@ -690,10 +691,8 @@
 	struct evdev_client *client;
 
 	input_unregister_handle(handle);
+	device_del(&evdev->dev);
 
-	sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
-	class_device_destroy(&input_class,
-			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
 	evdev->exist = 0;
 
 	if (evdev->open) {
@@ -702,8 +701,9 @@
 		list_for_each_entry(client, &evdev->client_list, node)
 			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 		wake_up_interruptible(&evdev->wait);
-	} else
-		evdev_free(evdev);
+	}
+
+	put_device(&evdev->dev);
 }
 
 static const struct input_device_id evdev_ids[] = {
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccd8aba..75b4d2a 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -442,7 +442,7 @@
 		printk(KERN_ERR
 			"input: failed to attach handler %s to device %s, "
 			"error: %d\n",
-			handler->name, kobject_name(&dev->cdev.kobj), error);
+			handler->name, kobject_name(&dev->dev.kobj), error);
 
 	return error;
 }
@@ -527,7 +527,7 @@
 static int input_devices_seq_show(struct seq_file *seq, void *v)
 {
 	struct input_dev *dev = container_of(v, struct input_dev, node);
-	const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+	const char *path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
 	struct input_handle *handle;
 
 	seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
@@ -682,15 +682,17 @@
 static inline void input_proc_exit(void) { }
 #endif
 
-#define INPUT_DEV_STRING_ATTR_SHOW(name)					\
-static ssize_t input_dev_show_##name(struct class_device *dev, char *buf)	\
-{										\
-	struct input_dev *input_dev = to_input_dev(dev);			\
-										\
-	return scnprintf(buf, PAGE_SIZE, "%s\n",				\
-			 input_dev->name ? input_dev->name : "");		\
-}										\
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
+#define INPUT_DEV_STRING_ATTR_SHOW(name)				\
+static ssize_t input_dev_show_##name(struct device *dev,		\
+				     struct device_attribute *attr,	\
+				     char *buf)				\
+{									\
+	struct input_dev *input_dev = to_input_dev(dev);		\
+									\
+	return scnprintf(buf, PAGE_SIZE, "%s\n",			\
+			 input_dev->name ? input_dev->name : "");	\
+}									\
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL)
 
 INPUT_DEV_STRING_ATTR_SHOW(name);
 INPUT_DEV_STRING_ATTR_SHOW(phys);
@@ -744,7 +746,9 @@
 	return len;
 }
 
-static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+static ssize_t input_dev_show_modalias(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
 {
 	struct input_dev *id = to_input_dev(dev);
 	ssize_t len;
@@ -753,13 +757,13 @@
 
 	return min_t(int, len, PAGE_SIZE);
 }
-static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
+static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
 
 static struct attribute *input_dev_attrs[] = {
-	&class_device_attr_name.attr,
-	&class_device_attr_phys.attr,
-	&class_device_attr_uniq.attr,
-	&class_device_attr_modalias.attr,
+	&dev_attr_name.attr,
+	&dev_attr_phys.attr,
+	&dev_attr_uniq.attr,
+	&dev_attr_modalias.attr,
 	NULL
 };
 
@@ -767,13 +771,15 @@
 	.attrs	= input_dev_attrs,
 };
 
-#define INPUT_DEV_ID_ATTR(name)							\
-static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf)	\
-{										\
-	struct input_dev *input_dev = to_input_dev(dev);			\
-	return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name);		\
-}										\
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
+#define INPUT_DEV_ID_ATTR(name)						\
+static ssize_t input_dev_show_id_##name(struct device *dev,		\
+					struct device_attribute *attr,	\
+					char *buf)			\
+{									\
+	struct input_dev *input_dev = to_input_dev(dev);		\
+	return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name);	\
+}									\
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL)
 
 INPUT_DEV_ID_ATTR(bustype);
 INPUT_DEV_ID_ATTR(vendor);
@@ -781,10 +787,10 @@
 INPUT_DEV_ID_ATTR(version);
 
 static struct attribute *input_dev_id_attrs[] = {
-	&class_device_attr_bustype.attr,
-	&class_device_attr_vendor.attr,
-	&class_device_attr_product.attr,
-	&class_device_attr_version.attr,
+	&dev_attr_bustype.attr,
+	&dev_attr_vendor.attr,
+	&dev_attr_product.attr,
+	&dev_attr_version.attr,
 	NULL
 };
 
@@ -813,15 +819,17 @@
 	return len;
 }
 
-#define INPUT_DEV_CAP_ATTR(ev, bm)						\
-static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf)	\
-{										\
-	struct input_dev *input_dev = to_input_dev(dev);			\
-	int len = input_print_bitmap(buf, PAGE_SIZE,				\
-				     input_dev->bm##bit, ev##_MAX, 1);		\
-	return min_t(int, len, PAGE_SIZE);					\
-}										\
-static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
+#define INPUT_DEV_CAP_ATTR(ev, bm)					\
+static ssize_t input_dev_show_cap_##bm(struct device *dev,		\
+				       struct device_attribute *attr,	\
+				       char *buf)			\
+{									\
+	struct input_dev *input_dev = to_input_dev(dev);		\
+	int len = input_print_bitmap(buf, PAGE_SIZE,			\
+				     input_dev->bm##bit, ev##_MAX, 1);	\
+	return min_t(int, len, PAGE_SIZE);				\
+}									\
+static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
 
 INPUT_DEV_CAP_ATTR(EV, ev);
 INPUT_DEV_CAP_ATTR(KEY, key);
@@ -834,15 +842,15 @@
 INPUT_DEV_CAP_ATTR(SW, sw);
 
 static struct attribute *input_dev_caps_attrs[] = {
-	&class_device_attr_ev.attr,
-	&class_device_attr_key.attr,
-	&class_device_attr_rel.attr,
-	&class_device_attr_abs.attr,
-	&class_device_attr_msc.attr,
-	&class_device_attr_led.attr,
-	&class_device_attr_snd.attr,
-	&class_device_attr_ff.attr,
-	&class_device_attr_sw.attr,
+	&dev_attr_ev.attr,
+	&dev_attr_key.attr,
+	&dev_attr_rel.attr,
+	&dev_attr_abs.attr,
+	&dev_attr_msc.attr,
+	&dev_attr_led.attr,
+	&dev_attr_snd.attr,
+	&dev_attr_ff.attr,
+	&dev_attr_sw.attr,
 	NULL
 };
 
@@ -858,9 +866,9 @@
 	NULL
 };
 
-static void input_dev_release(struct class_device *class_dev)
+static void input_dev_release(struct device *device)
 {
-	struct input_dev *dev = to_input_dev(class_dev);
+	struct input_dev *dev = to_input_dev(device);
 
 	input_ff_destroy(dev);
 	kfree(dev);
@@ -947,10 +955,10 @@
 			return err;					\
 	} while (0)
 
-static int input_dev_uevent(struct class_device *cdev, char **envp,
+static int input_dev_uevent(struct device *device, char **envp,
 			    int num_envp, char *buffer, int buffer_size)
 {
-	struct input_dev *dev = to_input_dev(cdev);
+	struct input_dev *dev = to_input_dev(device);
 	int i = 0;
 	int len = 0;
 
@@ -988,10 +996,14 @@
 	return 0;
 }
 
+static struct device_type input_dev_type = {
+	.groups		= input_dev_attr_groups,
+	.release	= input_dev_release,
+	.uevent		= input_dev_uevent,
+};
+
 struct class input_class = {
-	.name			= "input",
-	.release		= input_dev_release,
-	.uevent			= input_dev_uevent,
+	.name		= "input",
 };
 EXPORT_SYMBOL_GPL(input_class);
 
@@ -1010,9 +1022,9 @@
 
 	dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
 	if (dev) {
-		dev->cdev.class = &input_class;
-		dev->cdev.groups = input_dev_attr_groups;
-		class_device_initialize(&dev->cdev);
+		dev->dev.type = &input_dev_type;
+		dev->dev.class = &input_class;
+		device_initialize(&dev->dev);
 		mutex_init(&dev->mutex);
 		INIT_LIST_HEAD(&dev->h_list);
 		INIT_LIST_HEAD(&dev->node);
@@ -1131,17 +1143,17 @@
 
 	list_add_tail(&dev->node, &input_dev_list);
 
-	snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+	snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
 		 "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
 
-	if (!dev->cdev.dev)
-		dev->cdev.dev = dev->dev.parent;
+	if (dev->cdev.dev)
+		dev->dev.parent = dev->cdev.dev;
 
-	error = class_device_add(&dev->cdev);
+	error = device_add(&dev->dev);
 	if (error)
 		return error;
 
-	path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
 	printk(KERN_INFO "input: %s as %s\n",
 		dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
 	kfree(path);
@@ -1173,7 +1185,7 @@
 
 	list_del_init(&dev->node);
 
-	class_device_unregister(&dev->cdev);
+	device_unregister(&dev->dev);
 
 	input_wakeup_procfs_readers();
 }
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 10e3b7b..a9a0180 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -43,6 +43,8 @@
 	struct input_handle handle;
 	wait_queue_head_t wait;
 	struct list_head client_list;
+	struct device dev;
+
 	struct js_corr corr[ABS_MAX + 1];
 	struct JS_DATA_SAVE_TYPE glue;
 	int nabs;
@@ -138,8 +140,10 @@
 	return retval < 0 ? retval : 0;
 }
 
-static void joydev_free(struct joydev *joydev)
+static void joydev_free(struct device *dev)
 {
+	struct joydev *joydev = container_of(dev, struct joydev, dev);
+
 	joydev_table[joydev->minor] = NULL;
 	kfree(joydev);
 }
@@ -154,12 +158,10 @@
 	list_del(&client->node);
 	kfree(client);
 
-	if (!--joydev->open) {
-		if (joydev->exist)
-			input_close_device(&joydev->handle);
-		else
-			joydev_free(joydev);
-	}
+	if (!--joydev->open && joydev->exist)
+		input_close_device(&joydev->handle);
+
+	put_device(&joydev->dev);
 
 	return 0;
 }
@@ -178,24 +180,32 @@
 	if (!joydev || !joydev->exist)
 		return -ENODEV;
 
+	get_device(&joydev->dev);
+
 	client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_joydev;
+	}
 
 	client->joydev = joydev;
 	list_add_tail(&client->node, &joydev->client_list);
 
 	if (!joydev->open++ && joydev->exist) {
 		error = input_open_device(&joydev->handle);
-		if (error) {
-			list_del(&client->node);
-			kfree(client);
-			return error;
-		}
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_joydev:
+	put_device(&joydev->dev);
+	return error;
 }
 
 static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
@@ -481,8 +491,6 @@
 			  const struct input_device_id *id)
 {
 	struct joydev *joydev;
-	struct class_device *cdev;
-	dev_t devt;
 	int i, j, t, minor;
 	int error;
 
@@ -505,7 +513,7 @@
 	joydev->handle.name = joydev->name;
 	joydev->handle.handler = handler;
 	joydev->handle.private = joydev;
-	sprintf(joydev->name, "js%d", minor);
+	snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
 
 	for (i = 0; i < ABS_MAX + 1; i++)
 		if (test_bit(i, dev->absbit)) {
@@ -547,36 +555,30 @@
 		joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
 	}
 
+	snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id),
+		 "js%d", minor);
+	joydev->dev.class = &input_class;
+	joydev->dev.parent = &dev->dev;
+	joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
+	joydev->dev.release = joydev_free;
+	device_initialize(&joydev->dev);
+
 	joydev_table[minor] = joydev;
 
-	devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
-
-	cdev = class_device_create(&input_class, &dev->cdev, devt,
-				   dev->cdev.dev, joydev->name);
-	if (IS_ERR(cdev)) {
-		error = PTR_ERR(cdev);
-		goto err_free_joydev;
-	}
-
-	/* temporary symlink to keep userspace happy */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, joydev->name);
+	error = device_add(&joydev->dev);
 	if (error)
-		goto err_cdev_destroy;
+		goto err_free_joydev;
 
 	error = input_register_handle(&joydev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_joydev;
 
 	return 0;
 
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
+ err_delete_joydev:
+	device_del(&joydev->dev);
  err_free_joydev:
-	joydev_table[minor] = NULL;
-	kfree(joydev);
+	put_device(&joydev->dev);
 	return error;
 }
 
@@ -587,9 +589,8 @@
 	struct joydev_client *client;
 
 	input_unregister_handle(handle);
+	device_del(&joydev->dev);
 
-	sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
-	class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
 	joydev->exist = 0;
 
 	if (joydev->open) {
@@ -597,8 +598,9 @@
 		list_for_each_entry(client, &joydev->client_list, node)
 			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 		wake_up_interruptible(&joydev->wait);
-	} else
-		joydev_free(joydev);
+	}
+
+	put_device(&joydev->dev);
 }
 
 static const struct input_device_id joydev_blacklist[] = {
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index b002345..12db72d 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -268,4 +268,11 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called xpad.
 
+config JOYSTICK_XPAD_FF
+	bool "X-Box gamepad rumble support"
+	depends on JOYSTICK_XPAD && INPUT
+	select INPUT_FF_MEMLESS
+	---help---
+	  Say Y here if you want to take advantage of xbox 360 rumble features.
+
 endif
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 555319e..4ed3a3e 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -320,10 +320,10 @@
 
 static int dig_mode_start(struct gameport *gameport, u32 *packet)
 {
-	int i, seq_len = sizeof(init_seq)/sizeof(int);
+	int i;
 	int flags, tries = 0, bads = 0;
 
-	for (i = 0; i < seq_len; i++) {     /* Send magic sequence */
+	for (i = 0; i < ARRAY_SIZE(init_seq); i++) {     /* Send magic sequence */
 		if (init_seq[i])
 			gameport_trigger(gameport);
 		udelay(GRIP_INIT_DELAY);
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 8c8cd95..244089c 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -8,6 +8,7 @@
  *                    Ivan Hawkes <blackhawk@ivanhawkes.com>
  *               2005 Dominic Cerquetti <binary1230@yahoo.com>
  *               2006 Adam Buchbinder <adam.buchbinder@gmail.com>
+ *               2007 Jan Kratochvil <honza@jikos.cz>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -28,6 +29,7 @@
  *  - information from     http://euc.jp/periphs/xbox-controller.ja.html
  *  - the iForce driver    drivers/char/joystick/iforce.c
  *  - the skeleton-driver  drivers/usb/usb-skeleton.c
+ *  - Xbox 360 information http://www.free60.org/wiki/Gamepad
  *
  * Thanks to:
  *  - ITO Takayuki for providing essential xpad information on his website
@@ -88,6 +90,9 @@
 #define MAP_DPAD_TO_AXES       1
 #define MAP_DPAD_UNKNOWN       -1
 
+#define XTYPE_XBOX        0
+#define XTYPE_XBOX360     1
+
 static int dpad_to_buttons;
 module_param(dpad_to_buttons, bool, S_IRUGO);
 MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
@@ -97,40 +102,42 @@
 	u16 idProduct;
 	char *name;
 	u8 dpad_mapping;
+	u8 xtype;
 } xpad_device[] = {
-	{ 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES },
-	{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES },
-	{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES },
-	{ 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES },
-	{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS },
-	{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES },
-	{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES },
-	{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES },
-	{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES },
-	{ 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS },
-	{ 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES },
-	{ 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS },
-	{ 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES },
-	{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES },
-	{ 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES },
-	{ 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES },
-	{ 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES},
-	{ 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES },
-	{ 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES },
-	{ 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES },
-	{ 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES },
-	{ 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES },
-	{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES },
-	{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES },
-	{ 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS },
-	{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS },
-	{ 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES },
-	{ 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN }
+	{ 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+	{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+	{ 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+	{ 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+	{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+	{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
+	{ 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+	{ 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX }
 };
 
 static const signed short xpad_btn[] = {
@@ -146,6 +153,12 @@
 	-1				/* terminating entry */
 };
 
+static const signed short xpad360_btn[] = {  /* buttons for x360 controller */
+	BTN_TL, BTN_TR,		/* Button LB/RB */
+	BTN_MODE,		/* The big X button */
+	-1
+};
+
 static const signed short xpad_abs[] = {
 	ABS_X, ABS_Y,		/* left stick */
 	ABS_RX, ABS_RY,		/* right stick */
@@ -159,8 +172,12 @@
 	-1			/* terminating entry */
 };
 
+/* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only
+ * USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols,
+ * but we need only one of them. */
 static struct usb_device_id xpad_table [] = {
 	{ USB_INTERFACE_INFO('X', 'B', 0) },	/* X-Box USB-IF not approved class */
+	{ USB_DEVICE_INTERFACE_PROTOCOL(0x045e, 0x028e, 1) },	/* X-Box 360 controller */
 	{ }
 };
 
@@ -174,9 +191,16 @@
 	unsigned char *idata;		/* input data */
 	dma_addr_t idata_dma;
 
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+	struct urb *irq_out;		/* urb for interrupt out report */
+	unsigned char *odata;		/* output data */
+	dma_addr_t odata_dma;
+#endif
+
 	char phys[65];			/* physical device path */
 
 	int dpad_mapping;		/* map d-pad to buttons or to axes */
+	int xtype;			/* type of xbox device */
 };
 
 /*
@@ -212,8 +236,8 @@
 	} else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ {
 		input_report_key(dev, BTN_LEFT,  data[2] & 0x04);
 		input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
-		input_report_key(dev, BTN_0,     data[2] & 0x01); // up
-		input_report_key(dev, BTN_1,     data[2] & 0x02); // down
+		input_report_key(dev, BTN_0,     data[2] & 0x01); /* up */
+		input_report_key(dev, BTN_1,     data[2] & 0x02); /* down */
 	}
 
 	/* start/back buttons and stick press left/right */
@@ -235,6 +259,64 @@
 	input_sync(dev);
 }
 
+/*
+ *	xpad360_process_packet
+ *
+ *	Completes a request by converting the data into events for the
+ *	input subsystem. It is version for xbox 360 controller
+ *
+ *	The used report descriptor was taken from:
+ *		http://www.free60.org/wiki/Gamepad
+ */
+
+static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
+{
+	struct input_dev *dev = xpad->dev;
+
+	/* digital pad */
+	if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
+		input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04));
+		input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01));
+	} else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) {
+		/* dpad as buttons (right, left, down, up) */
+		input_report_key(dev, BTN_LEFT, data[2] & 0x04);
+		input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
+		input_report_key(dev, BTN_0, data[2] & 0x01);	/* up */
+		input_report_key(dev, BTN_1, data[2] & 0x02);	/* down */
+	}
+
+	/* start/back buttons */
+	input_report_key(dev, BTN_START,  data[2] & 0x10);
+	input_report_key(dev, BTN_BACK,   data[2] & 0x20);
+
+	/* stick press left/right */
+	input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
+	input_report_key(dev, BTN_THUMBR, data[2] & 0x80);
+
+	/* buttons A,B,X,Y,TL,TR and MODE */
+	input_report_key(dev, BTN_A,	data[3] & 0x10);
+	input_report_key(dev, BTN_B,	data[3] & 0x20);
+	input_report_key(dev, BTN_X,	data[3] & 0x40);
+	input_report_key(dev, BTN_Y,	data[3] & 0x80);
+	input_report_key(dev, BTN_TL,	data[3] & 0x01);
+	input_report_key(dev, BTN_TR,	data[3] & 0x02);
+	input_report_key(dev, BTN_MODE,	data[3] & 0x04);
+
+	/* left stick */
+	input_report_abs(dev, ABS_X, (__s16) (((__s16)data[7] << 8) | (__s16)data[6]));
+	input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[9] << 8) | (__s16)data[8]));
+
+	/* right stick */
+	input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[11] << 8) | (__s16)data[10]));
+	input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[13] << 8) | (__s16)data[12]));
+
+	/* triggers left/right */
+	input_report_abs(dev, ABS_Z, data[4]);
+	input_report_abs(dev, ABS_RZ, data[5]);
+
+	input_sync(dev);
+}
+
 static void xpad_irq_in(struct urb *urb)
 {
 	struct usb_xpad *xpad = urb->context;
@@ -255,7 +337,10 @@
 		goto exit;
 	}
 
-	xpad_process_packet(xpad, 0, xpad->idata);
+	if (xpad->xtype == XTYPE_XBOX360)
+		xpad360_process_packet(xpad, 0, xpad->idata);
+	else
+		xpad_process_packet(xpad, 0, xpad->idata);
 
 exit:
 	retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -264,7 +349,114 @@
 		     __FUNCTION__, retval);
 }
 
-static int xpad_open (struct input_dev *dev)
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+static void xpad_irq_out(struct urb *urb)
+{
+	int retval;
+
+	switch (urb->status) {
+		case 0:
+		/* success */
+		break;
+		case -ECONNRESET:
+		case -ENOENT:
+		case -ESHUTDOWN:
+			/* this urb is terminated, clean up */
+			dbg("%s - urb shutting down with status: %d",  __FUNCTION__, urb->status);
+			return;
+		default:
+			dbg("%s - nonzero urb status received: %d",  __FUNCTION__, urb->status);
+			goto exit;
+	}
+
+exit:
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval)
+		err("%s - usb_submit_urb failed with result %d",
+		   __FUNCTION__, retval);
+}
+
+static int xpad_play_effect(struct input_dev *dev, void *data,
+			    struct ff_effect *effect)
+{
+	struct usb_xpad *xpad = input_get_drvdata(dev);
+
+	if (effect->type == FF_RUMBLE) {
+		__u16 strong = effect->u.rumble.strong_magnitude;
+		__u16 weak = effect->u.rumble.weak_magnitude;
+		xpad->odata[0] = 0x00;
+		xpad->odata[1] = 0x08;
+		xpad->odata[2] = 0x00;
+		xpad->odata[3] = strong / 256;
+		xpad->odata[4] = weak / 256;
+		xpad->odata[5] = 0x00;
+		xpad->odata[6] = 0x00;
+		xpad->odata[7] = 0x00;
+		usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+	}
+
+	return 0;
+}
+
+static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad)
+{
+	struct usb_endpoint_descriptor *ep_irq_out;
+	int error = -ENOMEM;
+
+	if (xpad->xtype != XTYPE_XBOX360)
+		return 0;
+
+	xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
+				       GFP_ATOMIC, &xpad->odata_dma );
+	if (!xpad->odata)
+		goto fail1;
+
+	xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
+	if (!xpad->irq_out)
+		goto fail2;
+
+	ep_irq_out = &intf->cur_altsetting->endpoint[1].desc;
+	usb_fill_int_urb(xpad->irq_out, xpad->udev,
+			 usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
+			 xpad->odata, XPAD_PKT_LEN,
+			 xpad_irq_out, xpad, ep_irq_out->bInterval);
+	xpad->irq_out->transfer_dma = xpad->odata_dma;
+	xpad->irq_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
+
+	error = input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
+	if (error)
+		goto fail2;
+
+	return 0;
+
+ fail2:	usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
+ fail1:	return error;
+}
+
+static void xpad_stop_ff(struct usb_xpad *xpad)
+{
+	if (xpad->xtype == XTYPE_XBOX360)
+		usb_kill_urb(xpad->irq_out);
+}
+
+static void xpad_deinit_ff(struct usb_xpad *xpad)
+{
+	if (xpad->xtype == XTYPE_XBOX360) {
+		usb_free_urb(xpad->irq_out);
+		usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
+				xpad->odata, xpad->odata_dma);
+	}
+}
+
+#else
+static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }
+static void xpad_stop_ff(struct usb_xpad *xpad) { }
+static void xpad_deinit_ff(struct usb_xpad *xpad) { }
+#endif
+
+static int xpad_open(struct input_dev *dev)
 {
 	struct usb_xpad *xpad = input_get_drvdata(dev);
 
@@ -275,11 +467,12 @@
 	return 0;
 }
 
-static void xpad_close (struct input_dev *dev)
+static void xpad_close(struct input_dev *dev)
 {
 	struct usb_xpad *xpad = input_get_drvdata(dev);
 
 	usb_kill_urb(xpad->irq_in);
+	xpad_stop_ff(xpad);
 }
 
 static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
@@ -335,6 +528,7 @@
 
 	xpad->udev = udev;
 	xpad->dpad_mapping = xpad_device[i].dpad_mapping;
+	xpad->xtype = xpad_device[i].xtype;
 	if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
 		xpad->dpad_mapping = dpad_to_buttons;
 	xpad->dev = input_dev;
@@ -356,6 +550,9 @@
 	/* set up buttons */
 	for (i = 0; xpad_btn[i] >= 0; i++)
 		set_bit(xpad_btn[i], input_dev->keybit);
+	if (xpad->xtype == XTYPE_XBOX360)
+		for (i = 0; xpad360_btn[i] >= 0; i++)
+			set_bit(xpad360_btn[i], input_dev->keybit);
 	if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
 		for (i = 0; xpad_btn_pad[i] >= 0; i++)
 			set_bit(xpad_btn_pad[i], input_dev->keybit);
@@ -367,6 +564,10 @@
 		for (i = 0; xpad_abs_pad[i] >= 0; i++)
 		    xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
 
+	error = xpad_init_ff(intf, xpad);
+	if (error)
+		goto fail2;
+
 	ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
 	usb_fill_int_urb(xpad->irq_in, udev,
 			 usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
@@ -396,10 +597,10 @@
 
 	usb_set_intfdata(intf, NULL);
 	if (xpad) {
-		usb_kill_urb(xpad->irq_in);
 		input_unregister_device(xpad->dev);
+		xpad_deinit_ff(xpad);
 		usb_free_urb(xpad->irq_in);
-		usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN,
+		usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
 				xpad->idata, xpad->idata_dma);
 		kfree(xpad);
 	}
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 9950fcb..41fc3d0 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -89,7 +89,7 @@
 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
 	173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
-	159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
+	159,  0,115,  0,164,  0,  0,116,158,  0,172,166,  0,  0,  0,142,
 	157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
 	226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
 	  0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
@@ -111,7 +111,7 @@
 	 82, 83, 80, 76, 77, 72, 69, 98,  0, 96, 81,  0, 78, 73, 55,183,
 
 	184,185,186,187, 74, 94, 92, 93,  0,  0,  0,125,126,127,112,  0,
-	  0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168,
+	  0,139,172,163,165,115,152,172,166,140,160,154,113,114,167,168,
 	148,149,147,140
 };
 
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c
index f9e82c9..ebe5eac 100644
--- a/drivers/input/keyboard/pxa27x_keyboard.c
+++ b/drivers/input/keyboard/pxa27x_keyboard.c
@@ -140,7 +140,7 @@
 		KPREC = pdata->reg_kprec;
 
 		/* Enable unit clock */
-		pxa_set_cken(CKEN19_KEYPAD, 1);
+		pxa_set_cken(CKEN_KEYPAD, 1);
 	}
 
 	mutex_unlock(&input_dev->mutex);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 88e2907..9b26574 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -65,9 +65,13 @@
 config INPUT_WISTRON_BTNS
 	tristate "x86 Wistron laptop button interface"
 	depends on X86 && !X86_64
+	select INPUT_POLLDEV
+	select NEW_LEDS
+	select LEDS_CLASS
 	help
 	  Say Y here for support of Winstron laptop button interface, used on
-	  laptops of various brands, including Acer and Fujitsu-Siemens.
+	  laptops of various brands, including Acer and Fujitsu-Siemens. If
+	  available, mail and wifi leds will be controlable via /sys/class/leds.
 
 	  To compile this driver as a module, choose M here: the module will
 	  be called wistron_btns.
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 961aad7..60121f1 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -20,37 +20,31 @@
 #include <linux/io.h>
 #include <linux/dmi.h>
 #include <linux/init.h>
-#include <linux/input.h>
+#include <linux/input-polldev.h>
 #include <linux/interrupt.h>
+#include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/mc146818rtc.h>
 #include <linux/module.h>
 #include <linux/preempt.h>
 #include <linux/string.h>
-#include <linux/timer.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
+#include <linux/leds.h>
 
-/*
- * Number of attempts to read data from queue per poll;
- * the queue can hold up to 31 entries
- */
-#define MAX_POLL_ITERATIONS 64
-
-#define POLL_FREQUENCY 10 /* Number of polls per second */
-
-#if POLL_FREQUENCY > HZ
-#error "POLL_FREQUENCY too high"
-#endif
+/* How often we poll keys - msecs */
+#define POLL_INTERVAL_DEFAULT	500 /* when idle */
+#define POLL_INTERVAL_BURST	100 /* when a key was recently pressed */
 
 /* BIOS subsystem IDs */
 #define WIFI		0x35
 #define BLUETOOTH	0x34
+#define MAIL_LED	0x31
 
 MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
 MODULE_DESCRIPTION("Wistron laptop button driver");
 MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.2");
+MODULE_VERSION("0.3");
 
 static int force; /* = 0; */
 module_param(force, bool, 0);
@@ -248,9 +242,10 @@
 #define FE_WIFI_LED 0x02
 #define FE_UNTESTED 0x80
 
-static const struct key_entry *keymap; /* = NULL; Current key map */
+static struct key_entry *keymap; /* = NULL; Current key map */
 static int have_wifi;
 static int have_bluetooth;
+static int have_leds;
 
 static int __init dmi_matched(struct dmi_system_id *dmi)
 {
@@ -263,6 +258,8 @@
 		else if (key->type == KE_BLUETOOTH)
 			have_bluetooth = 1;
 	}
+	have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED);
+
 	return 1;
 }
 
@@ -966,21 +963,249 @@
 
  /* Input layer interface */
 
-static struct input_dev *input_dev;
+static struct input_polled_dev *wistron_idev;
+static unsigned long jiffies_last_press;
+static int wifi_enabled;
+static int bluetooth_enabled;
+
+static void report_key(struct input_dev *dev, unsigned int keycode)
+{
+	input_report_key(dev, keycode, 1);
+	input_sync(dev);
+	input_report_key(dev, keycode, 0);
+	input_sync(dev);
+}
+
+static void report_switch(struct input_dev *dev, unsigned int code, int value)
+{
+	input_report_switch(dev, code, value);
+	input_sync(dev);
+}
+
+
+ /* led management */
+static void wistron_mail_led_set(struct led_classdev *led_cdev,
+				enum led_brightness value)
+{
+	bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0);
+}
+
+/* same as setting up wifi card, but for laptops on which the led is managed */
+static void wistron_wifi_led_set(struct led_classdev *led_cdev,
+				enum led_brightness value)
+{
+	bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0);
+}
+
+static struct led_classdev wistron_mail_led = {
+	.name			= "mail:green",
+	.brightness_set		= wistron_mail_led_set,
+};
+
+static struct led_classdev wistron_wifi_led = {
+	.name			= "wifi:red",
+	.brightness_set		= wistron_wifi_led_set,
+};
+
+static void __devinit wistron_led_init(struct device *parent)
+{
+	if (have_leds & FE_WIFI_LED) {
+		u16 wifi = bios_get_default_setting(WIFI);
+		if (wifi & 1) {
+			wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF;
+			if (led_classdev_register(parent, &wistron_wifi_led))
+				have_leds &= ~FE_WIFI_LED;
+			else
+				bios_set_state(WIFI, wistron_wifi_led.brightness);
+
+		} else
+			have_leds &= ~FE_WIFI_LED;
+	}
+
+	if (have_leds & FE_MAIL_LED) {
+		/* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */
+		wistron_mail_led.brightness = LED_OFF;
+		if (led_classdev_register(parent, &wistron_mail_led))
+			have_leds &= ~FE_MAIL_LED;
+		else
+			bios_set_state(MAIL_LED, wistron_mail_led.brightness);
+	}
+}
+
+static void __devexit wistron_led_remove(void)
+{
+	if (have_leds & FE_MAIL_LED)
+		led_classdev_unregister(&wistron_mail_led);
+
+	if (have_leds & FE_WIFI_LED)
+		led_classdev_unregister(&wistron_wifi_led);
+}
+
+static inline void wistron_led_suspend(void)
+{
+	if (have_leds & FE_MAIL_LED)
+		led_classdev_suspend(&wistron_mail_led);
+
+	if (have_leds & FE_WIFI_LED)
+		led_classdev_suspend(&wistron_wifi_led);
+}
+
+static inline void wistron_led_resume(void)
+{
+	if (have_leds & FE_MAIL_LED)
+		led_classdev_resume(&wistron_mail_led);
+
+	if (have_leds & FE_WIFI_LED)
+		led_classdev_resume(&wistron_wifi_led);
+}
+
+static struct key_entry *wistron_get_entry_by_scancode(int code)
+{
+	struct key_entry *key;
+
+	for (key = keymap; key->type != KE_END; key++)
+		if (code == key->code)
+			return key;
+
+	return NULL;
+}
+
+static struct key_entry *wistron_get_entry_by_keycode(int keycode)
+{
+	struct key_entry *key;
+
+	for (key = keymap; key->type != KE_END; key++)
+		if (key->type == KE_KEY && keycode == key->keycode)
+			return key;
+
+	return NULL;
+}
+
+static void handle_key(u8 code)
+{
+	const struct key_entry *key = wistron_get_entry_by_scancode(code);
+
+	if (key) {
+		switch (key->type) {
+		case KE_KEY:
+			report_key(wistron_idev->input, key->keycode);
+			break;
+
+		case KE_SW:
+			report_switch(wistron_idev->input,
+				      key->sw.code, key->sw.value);
+			break;
+
+		case KE_WIFI:
+			if (have_wifi) {
+				wifi_enabled = !wifi_enabled;
+				bios_set_state(WIFI, wifi_enabled);
+			}
+			break;
+
+		case KE_BLUETOOTH:
+			if (have_bluetooth) {
+				bluetooth_enabled = !bluetooth_enabled;
+				bios_set_state(BLUETOOTH, bluetooth_enabled);
+			}
+			break;
+
+		default:
+			BUG();
+		}
+		jiffies_last_press = jiffies;
+	} else
+		printk(KERN_NOTICE
+			"wistron_btns: Unknown key code %02X\n", code);
+}
+
+static void poll_bios(bool discard)
+{
+	u8 qlen;
+	u16 val;
+
+	for (;;) {
+		qlen = CMOS_READ(cmos_address);
+		if (qlen == 0)
+			break;
+		val = bios_pop_queue();
+		if (val != 0 && !discard)
+			handle_key((u8)val);
+	}
+}
+
+static void wistron_flush(struct input_polled_dev *dev)
+{
+	/* Flush stale event queue */
+	poll_bios(true);
+}
+
+static void wistron_poll(struct input_polled_dev *dev)
+{
+	poll_bios(false);
+
+	/* Increase poll frequency if user is currently pressing keys (< 2s ago) */
+	if (time_before(jiffies, jiffies_last_press + 2 * HZ))
+		dev->poll_interval = POLL_INTERVAL_BURST;
+	else
+		dev->poll_interval = POLL_INTERVAL_DEFAULT;
+}
+
+static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+	const struct key_entry *key = wistron_get_entry_by_scancode(scancode);
+
+	if (key && key->type == KE_KEY) {
+		*keycode = key->keycode;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+	struct key_entry *key;
+	int old_keycode;
+
+	if (keycode < 0 || keycode > KEY_MAX)
+		return -EINVAL;
+
+	key = wistron_get_entry_by_scancode(scancode);
+	if (key && key->type == KE_KEY) {
+		old_keycode = key->keycode;
+		key->keycode = keycode;
+		set_bit(keycode, dev->keybit);
+		if (!wistron_get_entry_by_keycode(old_keycode))
+			clear_bit(old_keycode, dev->keybit);
+		return 0;
+	}
+
+	return -EINVAL;
+}
 
 static int __devinit setup_input_dev(void)
 {
 	const struct key_entry *key;
+	struct input_dev *input_dev;
 	int error;
 
-	input_dev = input_allocate_device();
-	if (!input_dev)
+	wistron_idev = input_allocate_polled_device();
+	if (!wistron_idev)
 		return -ENOMEM;
 
+	wistron_idev->flush = wistron_flush;
+	wistron_idev->poll = wistron_poll;
+	wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
+
+	input_dev = wistron_idev->input;
 	input_dev->name = "Wistron laptop buttons";
 	input_dev->phys = "wistron/input0";
 	input_dev->id.bustype = BUS_HOST;
-	input_dev->cdev.dev = &wistron_device->dev;
+	input_dev->dev.parent = &wistron_device->dev;
+
+	input_dev->getkeycode = wistron_getkeycode;
+	input_dev->setkeycode = wistron_setkeycode;
 
 	for (key = keymap; key->type != KE_END; key++) {
 		switch (key->type) {
@@ -995,7 +1220,7 @@
 				break;
 
 			default:
-				;
+				break;
 		}
 	}
 
@@ -1005,100 +1230,20 @@
 			"please report success or failure to eric.piel"
 			"@tremplin-utc.net\n");
 
-	error = input_register_device(input_dev);
+	error = input_register_polled_device(wistron_idev);
 	if (error) {
-		input_free_device(input_dev);
+		input_free_polled_device(wistron_idev);
 		return error;
 	}
 
 	return 0;
 }
 
-static void report_key(unsigned keycode)
-{
-	input_report_key(input_dev, keycode, 1);
-	input_sync(input_dev);
-	input_report_key(input_dev, keycode, 0);
-	input_sync(input_dev);
-}
-
-static void report_switch(unsigned code, int value)
-{
-	input_report_switch(input_dev, code, value);
-	input_sync(input_dev);
-}
-
- /* Driver core */
-
-static int wifi_enabled;
-static int bluetooth_enabled;
-
-static void poll_bios(unsigned long);
-
-static struct timer_list poll_timer = TIMER_INITIALIZER(poll_bios, 0, 0);
-
-static void handle_key(u8 code)
-{
-	const struct key_entry *key;
-
-	for (key = keymap; key->type != KE_END; key++) {
-		if (code == key->code) {
-			switch (key->type) {
-			case KE_KEY:
-				report_key(key->keycode);
-				break;
-
-			case KE_SW:
-				report_switch(key->sw.code, key->sw.value);
-				break;
-
-			case KE_WIFI:
-				if (have_wifi) {
-					wifi_enabled = !wifi_enabled;
-					bios_set_state(WIFI, wifi_enabled);
-				}
-				break;
-
-			case KE_BLUETOOTH:
-				if (have_bluetooth) {
-					bluetooth_enabled = !bluetooth_enabled;
-					bios_set_state(BLUETOOTH, bluetooth_enabled);
-				}
-				break;
-
-			case KE_END:
-				break;
-			default:
-				BUG();
-			}
-			return;
-		}
-	}
-	printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code);
-}
-
-static void poll_bios(unsigned long discard)
-{
-	u8 qlen;
-	u16 val;
-
-	for (;;) {
-		qlen = CMOS_READ(cmos_address);
-		if (qlen == 0)
-			break;
-		val = bios_pop_queue();
-		if (val != 0 && !discard)
-			handle_key((u8)val);
-	}
-
-	mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
-}
+/* Driver core */
 
 static int __devinit wistron_probe(struct platform_device *dev)
 {
-	int err = setup_input_dev();
-	if (err)
-		return err;
+	int err;
 
 	bios_attach();
 	cmos_address = bios_get_cmos_address();
@@ -1125,15 +1270,21 @@
 			bios_set_state(BLUETOOTH, bluetooth_enabled);
 	}
 
-	poll_bios(1); /* Flush stale event queue and arm timer */
+	wistron_led_init(&dev->dev);
+	err = setup_input_dev();
+	if (err) {
+		bios_detach();
+		return err;
+	}
 
 	return 0;
 }
 
 static int __devexit wistron_remove(struct platform_device *dev)
 {
-	del_timer_sync(&poll_timer);
-	input_unregister_device(input_dev);
+	wistron_led_remove();
+	input_unregister_polled_device(wistron_idev);
+	input_free_polled_device(wistron_idev);
 	bios_detach();
 
 	return 0;
@@ -1142,14 +1293,13 @@
 #ifdef CONFIG_PM
 static int wistron_suspend(struct platform_device *dev, pm_message_t state)
 {
-	del_timer_sync(&poll_timer);
-
 	if (have_wifi)
 		bios_set_state(WIFI, 0);
 
 	if (have_bluetooth)
 		bios_set_state(BLUETOOTH, 0);
 
+	wistron_led_suspend();
 	return 0;
 }
 
@@ -1161,7 +1311,8 @@
 	if (have_bluetooth)
 		bios_set_state(BLUETOOTH, bluetooth_enabled);
 
-	poll_bios(1);
+	wistron_led_resume();
+	poll_bios(true);
 
 	return 0;
 }
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 50e06e8..7bbea09 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -216,4 +216,20 @@
 	help
 	  Say Y here to support HIL pointers.
 
+config MOUSE_GPIO
+	tristate "GPIO mouse"
+	depends on GENERIC_GPIO
+	select INPUT_POLLDEV
+	help
+	  This driver simulates a mouse on GPIO lines of various CPUs (and some
+	  other chips).
+
+	  Say Y here if your device has buttons or a simple joystick connected
+	  directly to GPIO lines. Your board-specific setup logic must also
+	  provide a platform device and platform data saying which GPIOs are
+	  used.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gpio_mouse.
+
 endif
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index aa4ba87..9e6e363 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_MOUSE_SERIAL)	+= sermouse.o
 obj-$(CONFIG_MOUSE_HIL)		+= hil_ptr.o
 obj-$(CONFIG_MOUSE_VSXXXAA)	+= vsxxxaa.o
+obj-$(CONFIG_MOUSE_GPIO)	+= gpio_mouse.o
 
 psmouse-objs := psmouse-base.o synaptics.o
 
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
new file mode 100644
index 0000000..0936d6b
--- /dev/null
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -0,0 +1,196 @@
+/*
+ * Driver for simulating a mouse on GPIO lines.
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/input-polldev.h>
+#include <linux/gpio_mouse.h>
+
+#include <asm/gpio.h>
+
+/*
+ * Timer function which is run every scan_ms ms when the device is opened.
+ * The dev input varaible is set to the the input_dev pointer.
+ */
+static void gpio_mouse_scan(struct input_polled_dev *dev)
+{
+	struct gpio_mouse_platform_data *gpio = dev->private;
+	struct input_dev *input = dev->input;
+	int x, y;
+
+	if (gpio->bleft >= 0)
+		input_report_key(input, BTN_LEFT,
+				gpio_get_value(gpio->bleft) ^ gpio->polarity);
+	if (gpio->bmiddle >= 0)
+		input_report_key(input, BTN_MIDDLE,
+				gpio_get_value(gpio->bmiddle) ^ gpio->polarity);
+	if (gpio->bright >= 0)
+		input_report_key(input, BTN_RIGHT,
+				gpio_get_value(gpio->bright) ^ gpio->polarity);
+
+	x = (gpio_get_value(gpio->right) ^ gpio->polarity)
+		- (gpio_get_value(gpio->left) ^ gpio->polarity);
+	y = (gpio_get_value(gpio->down) ^ gpio->polarity)
+		- (gpio_get_value(gpio->up) ^ gpio->polarity);
+
+	input_report_rel(input, REL_X, x);
+	input_report_rel(input, REL_Y, y);
+	input_sync(input);
+}
+
+static int __init gpio_mouse_probe(struct platform_device *pdev)
+{
+	struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
+	struct input_polled_dev *input_poll;
+	struct input_dev *input;
+	int pin, i;
+	int error;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data\n");
+		error = -ENXIO;
+		goto out;
+	}
+
+	if (pdata->scan_ms < 0) {
+		dev_err(&pdev->dev, "invalid scan time\n");
+		error = -EINVAL;
+		goto out;
+	}
+
+	for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
+		pin = pdata->pins[i];
+
+		if (pin < 0) {
+
+			if (i <= GPIO_MOUSE_PIN_RIGHT) {
+				/* Mouse direction is required. */
+				dev_err(&pdev->dev,
+					"missing GPIO for directions\n");
+				error = -EINVAL;
+				goto out_free_gpios;
+			}
+
+			if (i == GPIO_MOUSE_PIN_BLEFT)
+				dev_dbg(&pdev->dev, "no left button defined\n");
+
+		} else {
+			error = gpio_request(pin, "gpio_mouse");
+			if (error) {
+				dev_err(&pdev->dev, "fail %d pin (%d idx)\n",
+					pin, i);
+				goto out_free_gpios;
+			}
+
+			gpio_direction_input(pin);
+		}
+	}
+
+	input_poll = input_allocate_polled_device();
+	if (!input_poll) {
+		dev_err(&pdev->dev, "not enough memory for input device\n");
+		error = -ENOMEM;
+		goto out_free_gpios;
+	}
+
+	platform_set_drvdata(pdev, input_poll);
+
+	/* set input-polldev handlers */
+	input_poll->private = pdata;
+	input_poll->poll = gpio_mouse_scan;
+	input_poll->poll_interval = pdata->scan_ms;
+
+	input = input_poll->input;
+	input->name = pdev->name;
+	input->id.bustype = BUS_HOST;
+	input->dev.parent = &pdev->dev;
+
+	input_set_capability(input, EV_REL, REL_X);
+	input_set_capability(input, EV_REL, REL_Y);
+	if (pdata->bleft >= 0)
+		input_set_capability(input, EV_KEY, BTN_LEFT);
+	if (pdata->bmiddle >= 0)
+		input_set_capability(input, EV_KEY, BTN_MIDDLE);
+	if (pdata->bright >= 0)
+		input_set_capability(input, EV_KEY, BTN_RIGHT);
+
+	error = input_register_polled_device(input_poll);
+	if (error) {
+		dev_err(&pdev->dev, "could not register input device\n");
+		goto out_free_polldev;
+	}
+
+	dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n",
+			pdata->scan_ms,
+			pdata->bleft < 0 ? "" : "left ",
+			pdata->bmiddle < 0 ? "" : "middle ",
+			pdata->bright < 0 ? "" : "right");
+
+	return 0;
+
+ out_free_polldev:
+	input_free_polled_device(input_poll);
+	platform_set_drvdata(pdev, NULL);
+
+ out_free_gpios:
+	while (--i >= 0) {
+		pin = pdata->pins[i];
+		if (pin)
+			gpio_free(pin);
+	}
+ out:
+	return error;
+}
+
+static int __devexit gpio_mouse_remove(struct platform_device *pdev)
+{
+	struct input_polled_dev *input = platform_get_drvdata(pdev);
+	struct gpio_mouse_platform_data *pdata = input->private;
+	int pin, i;
+
+	input_unregister_polled_device(input);
+	input_free_polled_device(input);
+
+	for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
+		pin = pdata->pins[i];
+		if (pin >= 0)
+			gpio_free(pin);
+	}
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+struct platform_driver gpio_mouse_device_driver = {
+	.remove		= __devexit_p(gpio_mouse_remove),
+	.driver		= {
+		.name	= "gpio_mouse",
+	}
+};
+
+static int __init gpio_mouse_init(void)
+{
+	return platform_driver_probe(&gpio_mouse_device_driver,
+			gpio_mouse_probe);
+}
+module_init(gpio_mouse_init);
+
+static void __exit gpio_mouse_exit(void)
+{
+	platform_driver_unregister(&gpio_mouse_device_driver);
+}
+module_exit(gpio_mouse_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("GPIO mouse driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index f15f695..b9f0fb2 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -178,6 +178,15 @@
 	}
 
 /*
+ * Cortron PS2 Trackball reports SIDE button on the 4th bit of the first
+ * byte.
+ */
+	if (psmouse->type == PSMOUSE_CORTRON) {
+		input_report_key(dev, BTN_SIDE, (packet[0] >> 3) & 1);
+		packet[0] |= 0x08;
+	}
+
+/*
  * Generic PS/2 Mouse
  */
 
@@ -539,6 +548,20 @@
 	return 0;
 }
 
+/*
+ * Cortron PS/2 protocol detection. There's no special way to detect it, so it
+ * must be forced by sysfs protocol writing.
+ */
+static int cortron_detect(struct psmouse *psmouse, int set_properties)
+{
+	if (set_properties) {
+		psmouse->vendor = "Cortron";
+		psmouse->name = "PS/2 Trackball";
+		set_bit(BTN_SIDE, psmouse->dev->keybit);
+	}
+
+	return 0;
+}
 
 /*
  * psmouse_extensions() probes for any extensions to the basic PS/2 protocol
@@ -740,6 +763,12 @@
 	},
 #endif
 	{
+		.type		= PSMOUSE_CORTRON,
+		.name		= "CortronPS/2",
+		.alias		= "cortps",
+		.detect		= cortron_detect,
+	},
+	{
 		.type		= PSMOUSE_AUTO,
 		.name		= "auto",
 		.alias		= "any",
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 3964e8a..27a6883 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -88,6 +88,7 @@
 	PSMOUSE_LIFEBOOK,
 	PSMOUSE_TRACKPOINT,
 	PSMOUSE_TOUCHKIT_PS2,
+	PSMOUSE_CORTRON,
 	PSMOUSE_AUTO		/* This one should always be last */
 };
 
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 3f4866d..9173916 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -64,6 +64,7 @@
 	wait_queue_head_t wait;
 	struct list_head client_list;
 	struct input_handle handle;
+	struct device dev;
 
 	struct list_head mixdev_node;
 	int mixdev_open;
@@ -112,7 +113,7 @@
 static struct input_handler mousedev_handler;
 
 static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
-static struct mousedev mousedev_mix;
+static struct mousedev *mousedev_mix;
 static LIST_HEAD(mousedev_mix_list);
 
 #define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
@@ -218,10 +219,10 @@
 
 	if (value) {
 		set_bit(index, &mousedev->packet.buttons);
-		set_bit(index, &mousedev_mix.packet.buttons);
+		set_bit(index, &mousedev_mix->packet.buttons);
 	} else {
 		clear_bit(index, &mousedev->packet.buttons);
-		clear_bit(index, &mousedev_mix.packet.buttons);
+		clear_bit(index, &mousedev_mix->packet.buttons);
 	}
 }
 
@@ -287,11 +288,11 @@
 			 * motion packet so we won't mess current position.
 			 */
 			set_bit(0, &mousedev->packet.buttons);
-			set_bit(0, &mousedev_mix.packet.buttons);
-			mousedev_notify_readers(mousedev, &mousedev_mix.packet);
-			mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
+			set_bit(0, &mousedev_mix->packet.buttons);
+			mousedev_notify_readers(mousedev, &mousedev_mix->packet);
+			mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet);
 			clear_bit(0, &mousedev->packet.buttons);
-			clear_bit(0, &mousedev_mix.packet.buttons);
+			clear_bit(0, &mousedev_mix->packet.buttons);
 		}
 		mousedev->touch = mousedev->pkt_count = 0;
 		mousedev->frac_dx = 0;
@@ -343,7 +344,7 @@
 				}
 
 				mousedev_notify_readers(mousedev, &mousedev->packet);
-				mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
+				mousedev_notify_readers(mousedev_mix, &mousedev->packet);
 
 				mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
 				mousedev->packet.abs_event = 0;
@@ -362,8 +363,10 @@
 	return retval < 0 ? retval : 0;
 }
 
-static void mousedev_free(struct mousedev *mousedev)
+static void mousedev_free(struct device *dev)
 {
+	struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
+
 	mousedev_table[mousedev->minor] = NULL;
 	kfree(mousedev);
 }
@@ -372,15 +375,16 @@
 {
 	int error;
 
-	if (mousedev_mix.open) {
+	if (mousedev_mix->open) {
 		error = input_open_device(&mousedev->handle);
 		if (error)
 			return error;
 
 		mousedev->open++;
-		mousedev->mixdev_open++;
+		mousedev->mixdev_open = 1;
 	}
 
+	get_device(&mousedev->dev);
 	list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
 
 	return 0;
@@ -395,36 +399,40 @@
 	}
 
 	list_del_init(&mousedev->mixdev_node);
+	put_device(&mousedev->dev);
 }
 
 static void mixdev_open_devices(void)
 {
 	struct mousedev *mousedev;
 
+	if (mousedev_mix->open++)
+		return;
+
 	list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
-		if (mousedev->exist && !mousedev->open) {
-			if (input_open_device(&mousedev->handle))
-				continue;
+		if (!mousedev->mixdev_open) {
+			if (!mousedev->open && mousedev->exist)
+				if (input_open_device(&mousedev->handle))
+					continue;
 
 			mousedev->open++;
-			mousedev->mixdev_open++;
+			mousedev->mixdev_open = 1;
 		}
 	}
 }
 
 static void mixdev_close_devices(void)
 {
-	struct mousedev *mousedev, *next;
+	struct mousedev *mousedev;
 
-	list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
+	if (--mousedev_mix->open)
+		return;
+
+	list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
 		if (mousedev->mixdev_open) {
 			mousedev->mixdev_open = 0;
-			if (!--mousedev->open) {
-				if (mousedev->exist)
-					input_close_device(&mousedev->handle);
-				else
-					mousedev_free(mousedev);
-			}
+			if (!--mousedev->open && mousedev->exist)
+				input_close_device(&mousedev->handle);
 		}
 	}
 }
@@ -439,14 +447,12 @@
 	list_del(&client->node);
 	kfree(client);
 
-	if (!--mousedev->open) {
-		if (mousedev->minor == MOUSEDEV_MIX)
-			mixdev_close_devices();
-		else if (mousedev->exist)
-			input_close_device(&mousedev->handle);
-		else
-			mousedev_free(mousedev);
-	}
+	if (mousedev->minor == MOUSEDEV_MIX)
+		mixdev_close_devices();
+	else if (!--mousedev->open && mousedev->exist)
+		input_close_device(&mousedev->handle);
+
+	put_device(&mousedev->dev);
 
 	return 0;
 }
@@ -473,9 +479,13 @@
 	if (!mousedev)
 		return -ENODEV;
 
+	get_device(&mousedev->dev);
+
 	client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_mousedev;
+	}
 
 	spin_lock_init(&client->packet_lock);
 	client->pos_x = xres / 2;
@@ -483,21 +493,23 @@
 	client->mousedev = mousedev;
 	list_add_tail(&client->node, &mousedev->client_list);
 
-	if (!mousedev->open++) {
-		if (mousedev->minor == MOUSEDEV_MIX)
-			mixdev_open_devices();
-		else if (mousedev->exist) {
-			error = input_open_device(&mousedev->handle);
-			if (error) {
-				list_del(&client->node);
-				kfree(client);
-				return error;
-			}
-		}
+	if (mousedev->minor == MOUSEDEV_MIX)
+		mixdev_open_devices();
+	else if (!mousedev->open++ && mousedev->exist) {
+		error = input_open_device(&mousedev->handle);
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_mousedev:
+	put_device(&mousedev->dev);
+	return error;
 }
 
 static inline int mousedev_limit_delta(int delta, int limit)
@@ -680,12 +692,80 @@
 	.fasync =	mousedev_fasync,
 };
 
+static struct mousedev *mousedev_create(struct input_dev *dev,
+					struct input_handler *handler,
+					int minor)
+{
+	struct mousedev *mousedev;
+	int error;
+
+	mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
+	if (!mousedev) {
+		error = -ENOMEM;
+		goto err_out;
+	}
+
+	INIT_LIST_HEAD(&mousedev->client_list);
+	INIT_LIST_HEAD(&mousedev->mixdev_node);
+	init_waitqueue_head(&mousedev->wait);
+
+	if (minor == MOUSEDEV_MIX)
+		strlcpy(mousedev->name, "mice", sizeof(mousedev->name));
+	else
+		snprintf(mousedev->name, sizeof(mousedev->name),
+			 "mouse%d", minor);
+
+	mousedev->minor = minor;
+	mousedev->exist = 1;
+	mousedev->handle.dev = dev;
+	mousedev->handle.name = mousedev->name;
+	mousedev->handle.handler = handler;
+	mousedev->handle.private = mousedev;
+
+	strlcpy(mousedev->dev.bus_id, mousedev->name,
+		sizeof(mousedev->dev.bus_id));
+	mousedev->dev.class = &input_class;
+	if (dev)
+		mousedev->dev.parent = &dev->dev;
+	mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
+	mousedev->dev.release = mousedev_free;
+	device_initialize(&mousedev->dev);
+
+	mousedev_table[minor] = mousedev;
+
+	error = device_add(&mousedev->dev);
+	if (error)
+		goto err_free_mousedev;
+
+	return mousedev;
+
+ err_free_mousedev:
+	put_device(&mousedev->dev);
+ err_out:
+	return ERR_PTR(error);
+}
+
+static void mousedev_destroy(struct mousedev *mousedev)
+{
+	struct mousedev_client *client;
+
+	device_del(&mousedev->dev);
+	mousedev->exist = 0;
+
+	if (mousedev->open) {
+		input_close_device(&mousedev->handle);
+		list_for_each_entry(client, &mousedev->client_list, node)
+			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+		wake_up_interruptible(&mousedev->wait);
+	}
+
+	put_device(&mousedev->dev);
+}
+
 static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
 			    const struct input_device_id *id)
 {
 	struct mousedev *mousedev;
-	struct class_device *cdev;
-	dev_t devt;
 	int minor;
 	int error;
 
@@ -695,42 +775,13 @@
 		return -ENFILE;
 	}
 
-	mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
-	if (!mousedev)
-		return -ENOMEM;
-
-	INIT_LIST_HEAD(&mousedev->client_list);
-	INIT_LIST_HEAD(&mousedev->mixdev_node);
-	init_waitqueue_head(&mousedev->wait);
-
-	mousedev->minor = minor;
-	mousedev->exist = 1;
-	mousedev->handle.dev = dev;
-	mousedev->handle.name = mousedev->name;
-	mousedev->handle.handler = handler;
-	mousedev->handle.private = mousedev;
-	sprintf(mousedev->name, "mouse%d", minor);
-
-	mousedev_table[minor] = mousedev;
-
-	devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
-
-	cdev = class_device_create(&input_class, &dev->cdev, devt,
-				   dev->cdev.dev, mousedev->name);
-	if (IS_ERR(cdev)) {
-		error = PTR_ERR(cdev);
-		goto err_free_mousedev;
-	}
-
-	/* temporary symlink to keep userspace happy */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, mousedev->name);
-	if (error)
-		goto err_cdev_destroy;
+	mousedev = mousedev_create(dev, handler, minor);
+	if (IS_ERR(mousedev))
+		return PTR_ERR(mousedev);
 
 	error = input_register_handle(&mousedev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_mousedev;
 
 	error = mixdev_add_device(mousedev);
 	if (error)
@@ -740,37 +791,18 @@
 
  err_unregister_handle:
 	input_unregister_handle(&mousedev->handle);
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
- err_free_mousedev:
-	mousedev_table[minor] = NULL;
-	kfree(mousedev);
+ err_delete_mousedev:
+	device_unregister(&mousedev->dev);
 	return error;
 }
 
 static void mousedev_disconnect(struct input_handle *handle)
 {
 	struct mousedev *mousedev = handle->private;
-	struct mousedev_client *client;
-
-	input_unregister_handle(handle);
-
-	sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
-	class_device_destroy(&input_class,
-			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
-	mousedev->exist = 0;
 
 	mixdev_remove_device(mousedev);
-
-	if (mousedev->open) {
-		input_close_device(handle);
-		list_for_each_entry(client, &mousedev->client_list, node)
-			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
-		wake_up_interruptible(&mousedev->wait);
-	} else
-		mousedev_free(mousedev);
+	input_unregister_handle(handle);
+	mousedev_destroy(mousedev);
 }
 
 static const struct input_device_id mousedev_ids[] = {
@@ -822,25 +854,16 @@
 
 static int __init mousedev_init(void)
 {
-	struct class_device *cdev;
 	int error;
 
+	mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
+	if (IS_ERR(mousedev_mix))
+		return PTR_ERR(mousedev_mix);
+
 	error = input_register_handler(&mousedev_handler);
-	if (error)
+	if (error) {
+		mousedev_destroy(mousedev_mix);
 		return error;
-
-	memset(&mousedev_mix, 0, sizeof(struct mousedev));
-	INIT_LIST_HEAD(&mousedev_mix.client_list);
-	init_waitqueue_head(&mousedev_mix.wait);
-	mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
-	mousedev_mix.exist = 1;
-	mousedev_mix.minor = MOUSEDEV_MIX;
-
-	cdev = class_device_create(&input_class, NULL,
-			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
-	if (IS_ERR(cdev)) {
-		input_unregister_handler(&mousedev_handler);
-		return PTR_ERR(cdev);
 	}
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -863,9 +886,8 @@
 	if (psaux_registered)
 		misc_deregister(&psaux_mouse);
 #endif
-	class_device_destroy(&input_class,
-			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
 	input_unregister_handler(&mousedev_handler);
+	mousedev_destroy(mousedev_mix);
 }
 
 module_init(mousedev_init);
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 8873576..0403622 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -160,7 +160,7 @@
 {
 	struct serio_raw_list *list = file->private_data;
 	struct serio_raw *serio_raw = list->serio_raw;
-	char c;
+	char uninitialized_var(c);
 	ssize_t retval = 0;
 
 	if (!serio_raw->serio)
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index cc0a498..94683f5 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -82,8 +82,8 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.5 (May-15-2004)"
-#define DRIVER_AUTHOR  "Bryan W. Headley/Chris Atenasio"
+#define DRIVER_VERSION "v2.3 (May 2, 2007)"
+#define DRIVER_AUTHOR  "Bryan W. Headley/Chris Atenasio/Cedric Brun/Rene van Paassen"
 #define DRIVER_DESC    "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)"
 
 /*
@@ -112,7 +112,7 @@
  * (returned as Report 3 - absolute coordinates from the mouse)
  *
  *        bit7  bit6  bit5  bit4  bit3  bit2  bit1  bit0
- * byte0   0     0     0     0     0     0     1     0
+ * byte0   0     0     0     0     0     0     1     1
  * byte1  X7    X6    X5    X4    X3    X2    X1    X0
  * byte2  X15   X14   X13   X12   X11   X10   X9    X8
  * byte3  Y7    Y6    Y5    Y4    Y3    Y2    Y1    Y0
@@ -134,7 +134,7 @@
  * (returned as Report 5 - macrokeys from the mouse)
  *
  *        bit7  bit6  bit5  bit4  bit3  bit2  bit1  bit0
- * byte0   0     0     0     0     0     1     0     0
+ * byte0   0     0     0     0     0     1     0     1
  * byte1   0     0     0    BS2   BS    Tip   IR    DV
  * byte2   0     0     0     0     0     0     1     0
  * byte3   0     0     0    K4    K3    K2    K1    K0
@@ -218,15 +218,9 @@
 #define AIPTEK_WHEEL_DISABLE				(-10101)
 
 	/* ToolCode values, which BTW are 0x140 .. 0x14f
-	 * We have things set up such that if TOOL_BUTTON_FIRED_BIT is
-	 * not set, we'll send one instance of AIPTEK_TOOL_BUTTON_xxx.
-	 *
-	 * Whenever the user resets the value, TOOL_BUTTON_FIRED_BIT will
-	 * get reset.
+	 * We have things set up such that if the tool button has changed,
+	 * the tools get reset.
 	 */
-#define TOOL_BUTTON(x)					((x) & 0x14f)
-#define TOOL_BUTTON_FIRED(x)				((x) & 0x200)
-#define TOOL_BUTTON_FIRED_BIT				0x200
 	/* toolMode codes
 	 */
 #define AIPTEK_TOOL_BUTTON_PEN_MODE			BTN_TOOL_PEN
@@ -264,9 +258,9 @@
 
 	/* Mouse button programming
 	 */
-#define AIPTEK_MOUSE_LEFT_BUTTON		0x01
-#define AIPTEK_MOUSE_RIGHT_BUTTON		0x02
-#define AIPTEK_MOUSE_MIDDLE_BUTTON		0x04
+#define AIPTEK_MOUSE_LEFT_BUTTON		0x04
+#define AIPTEK_MOUSE_RIGHT_BUTTON		0x08
+#define AIPTEK_MOUSE_MIDDLE_BUTTON		0x10
 
 	/* Stylus button programming
 	 */
@@ -294,7 +288,6 @@
 	int modelCode;		/* Tablet model code (not unique) */
 	int firmwareCode;	/* prom/eeprom version            */
 	char usbPath[64 + 1];	/* device's physical usb path     */
-	char inputPath[64 + 1];	/* input device path              */
 };
 
 struct aiptek_settings {
@@ -327,9 +320,32 @@
 	int inDelay;				/* jitter: in jitter delay?      */
 	unsigned long endDelay;			/* jitter: time when delay ends  */
 	int previousJitterable;			/* jitterable prev value     */
+
+	int lastMacro;				/* macro key to reset            */
+	int previousToolMode;			/* pen, pencil, brush, etc. tool */
 	unsigned char *data;			/* incoming packet data          */
 };
 
+static const int eventTypes[] = {
+        EV_KEY, EV_ABS, EV_REL, EV_MSC,
+};
+
+static const int absEvents[] = {
+        ABS_X, ABS_Y, ABS_PRESSURE, ABS_TILT_X, ABS_TILT_Y,
+        ABS_WHEEL, ABS_MISC,
+};
+
+static const int relEvents[] = {
+        REL_X, REL_Y, REL_WHEEL,
+};
+
+static const int buttonEvents[] = {
+	BTN_LEFT, BTN_RIGHT, BTN_MIDDLE,
+	BTN_TOOL_PEN, BTN_TOOL_RUBBER, BTN_TOOL_PENCIL, BTN_TOOL_AIRBRUSH,
+	BTN_TOOL_BRUSH, BTN_TOOL_MOUSE, BTN_TOOL_LENS, BTN_TOUCH,
+	BTN_STYLUS, BTN_STYLUS2,
+};
+
 /*
  * Permit easy lookup of keyboard events to send, versus
  * the bitmap which comes from the tablet. This hides the
@@ -345,23 +361,39 @@
 };
 
 /***********************************************************************
- * Relative reports deliver values in 2's complement format to
- * deal with negative offsets.
+ * Map values to strings and back. Every map shoudl have the following
+ * as its last element: { NULL, AIPTEK_INVALID_VALUE }.
  */
-static int aiptek_convert_from_2s_complement(unsigned char c)
-{
-	int ret;
-	unsigned char b = c;
-	int negate = 0;
+#define AIPTEK_INVALID_VALUE	-1
 
-	if ((b & 0x80) != 0) {
-		b = ~b;
-		b--;
-		negate = 1;
-	}
-	ret = b;
-	ret = (negate == 1) ? -ret : ret;
-	return ret;
+struct aiptek_map {
+	const char *string;
+	int value;
+};
+
+static int map_str_to_val(const struct aiptek_map *map, const char *str, size_t count)
+{
+	const struct aiptek_map *p;
+
+	if (str[count - 1] == '\n')
+		count--;
+
+	for (p = map; p->string; p++)
+	        if (!strncmp(str, p->string, count))
+			return p->value;
+
+	return AIPTEK_INVALID_VALUE;
+}
+
+static const char *map_val_to_str(const struct aiptek_map *map, int val)
+{
+	const struct aiptek_map *p;
+
+	for (p = map; p->value != AIPTEK_INVALID_VALUE; p++)
+		if (val == p->value)
+			return p->string;
+
+	return "unknown";
 }
 
 /***********************************************************************
@@ -385,6 +417,9 @@
  * Proximity. Why two events? I thought it interesting to know if the
  * Proximity event occurred while the tablet was in absolute or relative
  * mode.
+ * Update: REL_MISC proved not to be such a good idea. With REL_MISC you
+ * get an event transmitted each time. ABS_MISC works better, since it
+ * can be set and re-set. Thus, only using ABS_MISC from now on.
  *
  * Other tablets use the notion of a certain minimum stylus pressure
  * to infer proximity. While that could have been done, that is yet
@@ -441,8 +476,8 @@
 			aiptek->diagnostic =
 			    AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE;
 		} else {
-			x = aiptek_convert_from_2s_complement(data[2]);
-			y = aiptek_convert_from_2s_complement(data[3]);
+			x = (signed char) data[2];
+			y = (signed char) data[3];
 
 			/* jitterable keeps track of whether any button has been pressed.
 			 * We're also using it to remap the physical mouse button mask
@@ -451,18 +486,20 @@
 			 * that a non-zero value indicates that one or more
 			 * mouse button was pressed.)
 			 */
-			jitterable = data[5] & 0x07;
+			jitterable = data[1] & 0x07;
 
-			left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
-			right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
-			middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
+			left = (data[1] & aiptek->curSetting.mouseButtonLeft >> 2) != 0 ? 1 : 0;
+			right = (data[1] & aiptek->curSetting.mouseButtonRight >> 2) != 0 ? 1 : 0;
+			middle = (data[1] & aiptek->curSetting.mouseButtonMiddle >> 2) != 0 ? 1 : 0;
 
 			input_report_key(inputdev, BTN_LEFT, left);
 			input_report_key(inputdev, BTN_MIDDLE, middle);
 			input_report_key(inputdev, BTN_RIGHT, right);
+
+			input_report_abs(inputdev, ABS_MISC,
+					 1 | AIPTEK_REPORT_TOOL_UNKNOWN);
 			input_report_rel(inputdev, REL_X, x);
 			input_report_rel(inputdev, REL_Y, y);
-			input_report_rel(inputdev, REL_MISC, 1 | AIPTEK_REPORT_TOOL_UNKNOWN);
 
 			/* Wheel support is in the form of a single-event
 			 * firing.
@@ -472,6 +509,11 @@
 						 aiptek->curSetting.wheel);
 				aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
 			}
+			if (aiptek->lastMacro != -1) {
+			        input_report_key(inputdev,
+						 macroKeyEvents[aiptek->lastMacro], 0);
+				aiptek->lastMacro = -1;
+			}
 			input_sync(inputdev);
 		}
 	}
@@ -489,8 +531,8 @@
 			y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
 			z = le16_to_cpu(get_unaligned((__le16 *) (data + 6)));
 
-			p = (data[5] & 0x01) != 0 ? 1 : 0;
-			dv = (data[5] & 0x02) != 0 ? 1 : 0;
+			dv = (data[5] & 0x01) != 0 ? 1 : 0;
+			p = (data[5] & 0x02) != 0 ? 1 : 0;
 			tip = (data[5] & 0x04) != 0 ? 1 : 0;
 
 			/* Use jitterable to re-arrange button masks
@@ -505,16 +547,18 @@
 			 * all 'bad' reports...
 			 */
 			if (dv != 0) {
-				/* If we've not already sent a tool_button_?? code, do
-				 * so now. Then set FIRED_BIT so it won't be resent unless
-				 * the user forces FIRED_BIT off.
+				/* If the selected tool changed, reset the old
+				 * tool key, and set the new one.
 				 */
-				if (TOOL_BUTTON_FIRED
-				    (aiptek->curSetting.toolMode) == 0) {
+				if (aiptek->previousToolMode !=
+				    aiptek->curSetting.toolMode) {
+				        input_report_key(inputdev,
+							 aiptek->previousToolMode, 0);
 					input_report_key(inputdev,
-							 TOOL_BUTTON(aiptek->curSetting.toolMode),
+							 aiptek->curSetting.toolMode,
 							 1);
-					aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+					aiptek->previousToolMode =
+					          aiptek->curSetting.toolMode;
 				}
 
 				if (p != 0) {
@@ -550,6 +594,11 @@
 					}
 				}
 				input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_STYLUS);
+				if (aiptek->lastMacro != -1) {
+			                input_report_key(inputdev,
+							 macroKeyEvents[aiptek->lastMacro], 0);
+					aiptek->lastMacro = -1;
+				}
 				input_sync(inputdev);
 			}
 		}
@@ -568,23 +617,25 @@
 
 			jitterable = data[5] & 0x1c;
 
-			p = (data[5] & 0x01) != 0 ? 1 : 0;
-			dv = (data[5] & 0x02) != 0 ? 1 : 0;
+			dv = (data[5] & 0x01) != 0 ? 1 : 0;
+			p = (data[5] & 0x02) != 0 ? 1 : 0;
 			left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
 			right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
 			middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
 
 			if (dv != 0) {
-				/* If we've not already sent a tool_button_?? code, do
-				 * so now. Then set FIRED_BIT so it won't be resent unless
-				 * the user forces FIRED_BIT off.
+				/* If the selected tool changed, reset the old
+				 * tool key, and set the new one.
 				 */
-				if (TOOL_BUTTON_FIRED
-				    (aiptek->curSetting.toolMode) == 0) {
+				if (aiptek->previousToolMode !=
+				    aiptek->curSetting.toolMode) {
+				        input_report_key(inputdev,
+							 aiptek->previousToolMode, 0);
 					input_report_key(inputdev,
-							 TOOL_BUTTON(aiptek->curSetting.toolMode),
+							 aiptek->curSetting.toolMode,
 							 1);
-					aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+					aiptek->previousToolMode =
+					          aiptek->curSetting.toolMode;
 				}
 
 				if (p != 0) {
@@ -605,7 +656,12 @@
 						aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
 					}
 				}
-				input_report_rel(inputdev, REL_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+				input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+				if (aiptek->lastMacro != -1) {
+			                input_report_key(inputdev,
+							 macroKeyEvents[aiptek->lastMacro], 0);
+				        aiptek->lastMacro = -1;
+				}
 				input_sync(inputdev);
 			}
 		}
@@ -615,98 +671,83 @@
 	else if (data[0] == 4) {
 		jitterable = data[1] & 0x18;
 
-		p = (data[1] & 0x01) != 0 ? 1 : 0;
-		dv = (data[1] & 0x02) != 0 ? 1 : 0;
+		dv = (data[1] & 0x01) != 0 ? 1 : 0;
+		p = (data[1] & 0x02) != 0 ? 1 : 0;
 		tip = (data[1] & 0x04) != 0 ? 1 : 0;
 		bs = (data[1] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0;
 		pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
 
-		macro = data[3];
+		macro = dv && p && tip && !(data[3] & 1) ? (data[3] >> 1) : -1;
 		z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
 
-		if (dv != 0) {
-			/* If we've not already sent a tool_button_?? code, do
-			 * so now. Then set FIRED_BIT so it won't be resent unless
-			 * the user forces FIRED_BIT off.
+		if (dv) {
+		        /* If the selected tool changed, reset the old
+			 * tool key, and set the new one.
 			 */
-			if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+		        if (aiptek->previousToolMode !=
+			    aiptek->curSetting.toolMode) {
+			        input_report_key(inputdev,
+						 aiptek->previousToolMode, 0);
 				input_report_key(inputdev,
-						 TOOL_BUTTON(aiptek->curSetting.toolMode),
+						 aiptek->curSetting.toolMode,
 						 1);
-				aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+				aiptek->previousToolMode =
+				        aiptek->curSetting.toolMode;
 			}
-
-			if (p != 0) {
-				input_report_key(inputdev, BTN_TOUCH, tip);
-				input_report_key(inputdev, BTN_STYLUS, bs);
-				input_report_key(inputdev, BTN_STYLUS2, pck);
-				input_report_abs(inputdev, ABS_PRESSURE, z);
-			}
-
-			/* For safety, we're sending key 'break' codes for the
-			 * neighboring macro keys.
-			 */
-			if (macro > 0) {
-				input_report_key(inputdev,
-						 macroKeyEvents[macro - 1], 0);
-			}
-			if (macro < 25) {
-				input_report_key(inputdev,
-						 macroKeyEvents[macro + 1], 0);
-			}
-			input_report_key(inputdev, macroKeyEvents[macro], p);
-			input_report_abs(inputdev, ABS_MISC,
-					 p | AIPTEK_REPORT_TOOL_STYLUS);
-			input_sync(inputdev);
 		}
+
+		if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+		        input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+			aiptek->lastMacro = -1;
+		}
+
+		if (macro != -1 && macro != aiptek->lastMacro) {
+			input_report_key(inputdev, macroKeyEvents[macro], 1);
+			aiptek->lastMacro = macro;
+		}
+		input_report_abs(inputdev, ABS_MISC,
+				 p | AIPTEK_REPORT_TOOL_STYLUS);
+		input_sync(inputdev);
 	}
 	/* Report 5s come from the macro keys when pressed by mouse
 	 */
 	else if (data[0] == 5) {
 		jitterable = data[1] & 0x1c;
 
-		p = (data[1] & 0x01) != 0 ? 1 : 0;
-		dv = (data[1] & 0x02) != 0 ? 1 : 0;
+		dv = (data[1] & 0x01) != 0 ? 1 : 0;
+		p = (data[1] & 0x02) != 0 ? 1 : 0;
 		left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
 		right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
 		middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
-		macro = data[3];
+		macro = dv && p && left && !(data[3] & 1) ? (data[3] >> 1) : 0;
 
-		if (dv != 0) {
-			/* If we've not already sent a tool_button_?? code, do
-			 * so now. Then set FIRED_BIT so it won't be resent unless
-			 * the user forces FIRED_BIT off.
+		if (dv) {
+		        /* If the selected tool changed, reset the old
+			 * tool key, and set the new one.
 			 */
-			if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
-				input_report_key(inputdev,
-						 TOOL_BUTTON(aiptek->curSetting.toolMode),
-						 1);
-				aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+		        if (aiptek->previousToolMode !=
+			    aiptek->curSetting.toolMode) {
+		                input_report_key(inputdev,
+						 aiptek->previousToolMode, 0);
+			        input_report_key(inputdev,
+						 aiptek->curSetting.toolMode, 1);
+			        aiptek->previousToolMode = aiptek->curSetting.toolMode;
 			}
-
-			if (p != 0) {
-				input_report_key(inputdev, BTN_LEFT, left);
-				input_report_key(inputdev, BTN_MIDDLE, middle);
-				input_report_key(inputdev, BTN_RIGHT, right);
-			}
-
-			/* For safety, we're sending key 'break' codes for the
-			 * neighboring macro keys.
-			 */
-			if (macro > 0) {
-				input_report_key(inputdev,
-						 macroKeyEvents[macro - 1], 0);
-			}
-			if (macro < 25) {
-				input_report_key(inputdev,
-						 macroKeyEvents[macro + 1], 0);
-			}
-
-			input_report_key(inputdev, macroKeyEvents[macro], 1);
-			input_report_rel(inputdev, ABS_MISC,
-					 p | AIPTEK_REPORT_TOOL_MOUSE);
-			input_sync(inputdev);
 		}
+
+		if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+		        input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+			aiptek->lastMacro = -1;
+		}
+
+		if (macro != -1 && macro != aiptek->lastMacro) {
+			input_report_key(inputdev, macroKeyEvents[macro], 1);
+			aiptek->lastMacro = macro;
+		}
+
+		input_report_abs(inputdev, ABS_MISC,
+				 p | AIPTEK_REPORT_TOOL_MOUSE);
+		input_sync(inputdev);
 	}
 	/* We have no idea which tool can generate a report 6. Theoretically,
 	 * neither need to, having been given reports 4 & 5 for such use.
@@ -725,15 +766,18 @@
 					 0);
 		}
 
-		/* If we've not already sent a tool_button_?? code, do
-		 * so now. Then set FIRED_BIT so it won't be resent unless
-		 * the user forces FIRED_BIT off.
-		 */
-		if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+		/* If the selected tool changed, reset the old
+		   tool key, and set the new one.
+		*/
+		if (aiptek->previousToolMode !=
+		    aiptek->curSetting.toolMode) {
+		        input_report_key(inputdev,
+					 aiptek->previousToolMode, 0);
 			input_report_key(inputdev,
-					 TOOL_BUTTON(aiptek->curSetting.
-						     toolMode), 1);
-			aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+					 aiptek->curSetting.toolMode,
+					 1);
+			aiptek->previousToolMode =
+				aiptek->curSetting.toolMode;
 		}
 
 		input_report_key(inputdev, macroKeyEvents[macro], 1);
@@ -1007,9 +1051,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "%dx%d\n",
 			aiptek->inputdev->absmax[ABS_X] + 1,
 			aiptek->inputdev->absmax[ABS_Y] + 1);
@@ -1024,117 +1065,35 @@
 static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL);
 
 /***********************************************************************
- * support routines for the 'product_id' file
- */
-static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-
-	if (aiptek == NULL)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "0x%04x\n",
-			aiptek->inputdev->id.product);
-}
-
-static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL);
-
-/***********************************************************************
- * support routines for the 'vendor_id' file
- */
-static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-
-	if (aiptek == NULL)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor);
-}
-
-static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL);
-
-/***********************************************************************
- * support routines for the 'vendor' file
- */
-static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-	int retval;
-
-	if (aiptek == NULL)
-		return 0;
-
-	retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer);
-	return retval;
-}
-
-static DEVICE_ATTR(vendor, S_IRUGO, show_tabletManufacturer, NULL);
-
-/***********************************************************************
- * support routines for the 'product' file
- */
-static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-	int retval;
-
-	if (aiptek == NULL)
-		return 0;
-
-	retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product);
-	return retval;
-}
-
-static DEVICE_ATTR(product, S_IRUGO, show_tabletProduct, NULL);
-
-/***********************************************************************
  * support routines for the 'pointer_mode' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
+static struct aiptek_map pointer_mode_map[] = {
+	{ "stylus",	AIPTEK_POINTER_ONLY_STYLUS_MODE },
+	{ "mouse",	AIPTEK_POINTER_ONLY_MOUSE_MODE },
+	{ "either",	AIPTEK_POINTER_EITHER_MODE },
+	{ NULL,		AIPTEK_INVALID_VALUE }
+};
+
 static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.pointerMode) {
-	case AIPTEK_POINTER_ONLY_STYLUS_MODE:
-		s = "stylus";
-		break;
-
-	case AIPTEK_POINTER_ONLY_MOUSE_MODE:
-		s = "mouse";
-		break;
-
-	case AIPTEK_POINTER_EITHER_MODE:
-		s = "either";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(pointer_mode_map,
+					aiptek->curSetting.pointerMode));
 }
 
 static ssize_t
 store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	if (aiptek == NULL)
-		return 0;
+	int new_mode = map_str_to_val(pointer_mode_map, buf, count);
 
-	if (strcmp(buf, "stylus") == 0) {
-		aiptek->newSetting.pointerMode =
-		    AIPTEK_POINTER_ONLY_STYLUS_MODE;
-	} else if (strcmp(buf, "mouse") == 0) {
-		aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_MOUSE_MODE;
-	} else if (strcmp(buf, "either") == 0) {
-		aiptek->newSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE;
-	}
+	if (new_mode == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
+
+	aiptek->newSetting.pointerMode = new_mode;
 	return count;
 }
 
@@ -1146,44 +1105,32 @@
  * support routines for the 'coordinate_mode' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
+
+static struct aiptek_map coordinate_mode_map[] = {
+	{ "absolute",	AIPTEK_COORDINATE_ABSOLUTE_MODE },
+	{ "relative",	AIPTEK_COORDINATE_RELATIVE_MODE },
+	{ NULL,		AIPTEK_INVALID_VALUE }
+};
+
 static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.coordinateMode) {
-	case AIPTEK_COORDINATE_ABSOLUTE_MODE:
-		s = "absolute";
-		break;
-
-	case AIPTEK_COORDINATE_RELATIVE_MODE:
-		s = "relative";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(coordinate_mode_map,
+					aiptek->curSetting.coordinateMode));
 }
 
 static ssize_t
 store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	if (aiptek == NULL)
-		return 0;
+	int new_mode = map_str_to_val(coordinate_mode_map, buf, count);
 
-	if (strcmp(buf, "absolute") == 0) {
-		aiptek->newSetting.pointerMode =
-		    AIPTEK_COORDINATE_ABSOLUTE_MODE;
-	} else if (strcmp(buf, "relative") == 0) {
-		aiptek->newSetting.pointerMode =
-		    AIPTEK_COORDINATE_RELATIVE_MODE;
-	}
+	if (new_mode == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
+
+	aiptek->newSetting.coordinateMode = new_mode;
 	return count;
 }
 
@@ -1195,73 +1142,37 @@
  * support routines for the 'tool_mode' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
+
+static struct aiptek_map tool_mode_map[] = {
+	{ "mouse",	AIPTEK_TOOL_BUTTON_MOUSE_MODE },
+	{ "eraser",	AIPTEK_TOOL_BUTTON_ERASER_MODE },
+	{ "pencil",	AIPTEK_TOOL_BUTTON_PENCIL_MODE },
+	{ "pen",	AIPTEK_TOOL_BUTTON_PEN_MODE },
+	{ "brush",	AIPTEK_TOOL_BUTTON_BRUSH_MODE },
+	{ "airbrush",	AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE },
+	{ "lens",	AIPTEK_TOOL_BUTTON_LENS_MODE },
+	{ NULL,		AIPTEK_INVALID_VALUE }
+};
+
 static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (TOOL_BUTTON(aiptek->curSetting.toolMode)) {
-	case AIPTEK_TOOL_BUTTON_MOUSE_MODE:
-		s = "mouse";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_ERASER_MODE:
-		s = "eraser";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_PENCIL_MODE:
-		s = "pencil";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_PEN_MODE:
-		s = "pen";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_BRUSH_MODE:
-		s = "brush";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE:
-		s = "airbrush";
-		break;
-
-	case AIPTEK_TOOL_BUTTON_LENS_MODE:
-		s = "lens";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(tool_mode_map,
+					aiptek->curSetting.toolMode));
 }
 
 static ssize_t
 store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	if (aiptek == NULL)
-		return 0;
+	int new_mode = map_str_to_val(tool_mode_map, buf, count);
 
-	if (strcmp(buf, "mouse") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_MOUSE_MODE;
-	} else if (strcmp(buf, "eraser") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_ERASER_MODE;
-	} else if (strcmp(buf, "pencil") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PENCIL_MODE;
-	} else if (strcmp(buf, "pen") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE;
-	} else if (strcmp(buf, "brush") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_BRUSH_MODE;
-	} else if (strcmp(buf, "airbrush") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE;
-	} else if (strcmp(buf, "lens") == 0) {
-		aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_LENS_MODE;
-	}
+	if (new_mode == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
+	aiptek->newSetting.toolMode = new_mode;
 	return count;
 }
 
@@ -1277,9 +1188,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) {
 		return snprintf(buf, PAGE_SIZE, "disable\n");
 	} else {
@@ -1294,9 +1202,6 @@
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	int x;
 
-	if (aiptek == NULL)
-		return 0;
-
 	if (strcmp(buf, "disable") == 0) {
 		aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE;
 	} else {
@@ -1319,9 +1224,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) {
 		return snprintf(buf, PAGE_SIZE, "disable\n");
 	} else {
@@ -1336,9 +1238,6 @@
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	int y;
 
-	if (aiptek == NULL)
-		return 0;
-
 	if (strcmp(buf, "disable") == 0) {
 		aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE;
 	} else {
@@ -1361,9 +1260,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay);
 }
 
@@ -1372,9 +1268,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10);
 	return count;
 }
@@ -1391,9 +1284,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 			aiptek->curSetting.programmableDelay);
 }
@@ -1403,9 +1293,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10);
 	return count;
 }
@@ -1415,23 +1302,6 @@
 		   show_tabletProgrammableDelay, store_tabletProgrammableDelay);
 
 /***********************************************************************
- * support routines for the 'input_path' file. Note that this file
- * only displays current setting.
- */
-static ssize_t show_tabletInputDevice(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-
-	if (aiptek == NULL)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "/dev/input/%s\n",
-			aiptek->features.inputPath);
-}
-
-static DEVICE_ATTR(input_path, S_IRUGO, show_tabletInputDevice, NULL);
-
-/***********************************************************************
  * support routines for the 'event_count' file. Note that this file
  * only displays current setting.
  */
@@ -1439,9 +1309,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount);
 }
 
@@ -1456,9 +1323,6 @@
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	char *retMsg;
 
-	if (aiptek == NULL)
-		return 0;
-
 	switch (aiptek->diagnostic) {
 	case AIPTEK_DIAGNOSTIC_NA:
 		retMsg = "no errors\n";
@@ -1493,45 +1357,32 @@
  * support routines for the 'stylus_upper' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
+
+static struct aiptek_map stylus_button_map[] = {
+	{ "upper",	AIPTEK_STYLUS_UPPER_BUTTON },
+	{ "lower",	AIPTEK_STYLUS_LOWER_BUTTON },
+	{ NULL,		AIPTEK_INVALID_VALUE }
+};
+
 static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.stylusButtonUpper) {
-	case AIPTEK_STYLUS_UPPER_BUTTON:
-		s = "upper";
-		break;
-
-	case AIPTEK_STYLUS_LOWER_BUTTON:
-		s = "lower";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(stylus_button_map,
+					aiptek->curSetting.stylusButtonUpper));
 }
 
 static ssize_t
 store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
+	int new_button = map_str_to_val(stylus_button_map, buf, count);
 
-	if (aiptek == NULL)
-		return 0;
+	if (new_button == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
-	if (strcmp(buf, "upper") == 0) {
-		aiptek->newSetting.stylusButtonUpper =
-		    AIPTEK_STYLUS_UPPER_BUTTON;
-	} else if (strcmp(buf, "lower") == 0) {
-		aiptek->newSetting.stylusButtonUpper =
-		    AIPTEK_STYLUS_LOWER_BUTTON;
-	}
+	aiptek->newSetting.stylusButtonUpper = new_button;
 	return count;
 }
 
@@ -1543,45 +1394,26 @@
  * support routines for the 'stylus_lower' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
+
 static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.stylusButtonLower) {
-	case AIPTEK_STYLUS_UPPER_BUTTON:
-		s = "upper";
-		break;
-
-	case AIPTEK_STYLUS_LOWER_BUTTON:
-		s = "lower";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(stylus_button_map,
+					aiptek->curSetting.stylusButtonLower));
 }
 
 static ssize_t
 store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
+	int new_button = map_str_to_val(stylus_button_map, buf, count);
 
-	if (aiptek == NULL)
-		return 0;
+	if (new_button == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
-	if (strcmp(buf, "upper") == 0) {
-		aiptek->newSetting.stylusButtonLower =
-		    AIPTEK_STYLUS_UPPER_BUTTON;
-	} else if (strcmp(buf, "lower") == 0) {
-		aiptek->newSetting.stylusButtonLower =
-		    AIPTEK_STYLUS_LOWER_BUTTON;
-	}
+	aiptek->newSetting.stylusButtonLower = new_button;
 	return count;
 }
 
@@ -1593,49 +1425,33 @@
  * support routines for the 'mouse_left' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
+
+static struct aiptek_map mouse_button_map[] = {
+	{ "left",	AIPTEK_MOUSE_LEFT_BUTTON },
+	{ "middle",	AIPTEK_MOUSE_MIDDLE_BUTTON },
+	{ "right",	AIPTEK_MOUSE_RIGHT_BUTTON },
+	{ NULL,		AIPTEK_INVALID_VALUE }
+};
+
 static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.mouseButtonLeft) {
-	case AIPTEK_MOUSE_LEFT_BUTTON:
-		s = "left";
-		break;
-
-	case AIPTEK_MOUSE_MIDDLE_BUTTON:
-		s = "middle";
-		break;
-
-	case AIPTEK_MOUSE_RIGHT_BUTTON:
-		s = "right";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(mouse_button_map,
+					aiptek->curSetting.mouseButtonLeft));
 }
 
 static ssize_t
 store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
+	int new_button = map_str_to_val(mouse_button_map, buf, count);
 
-	if (aiptek == NULL)
-		return 0;
+	if (new_button == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
-	if (strcmp(buf, "left") == 0) {
-		aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON;
-	} else if (strcmp(buf, "middle") == 0) {
-		aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_MIDDLE_BUTTON;
-	} else if (strcmp(buf, "right") == 0) {
-		aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_RIGHT_BUTTON;
-	}
+	aiptek->newSetting.mouseButtonLeft = new_button;
 	return count;
 }
 
@@ -1650,48 +1466,22 @@
 static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.mouseButtonMiddle) {
-	case AIPTEK_MOUSE_LEFT_BUTTON:
-		s = "left";
-		break;
-
-	case AIPTEK_MOUSE_MIDDLE_BUTTON:
-		s = "middle";
-		break;
-
-	case AIPTEK_MOUSE_RIGHT_BUTTON:
-		s = "right";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(mouse_button_map,
+					aiptek->curSetting.mouseButtonMiddle));
 }
 
 static ssize_t
 store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
+	int new_button = map_str_to_val(mouse_button_map, buf, count);
 
-	if (aiptek == NULL)
-		return 0;
+	if (new_button == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
-	if (strcmp(buf, "left") == 0) {
-		aiptek->newSetting.mouseButtonMiddle = AIPTEK_MOUSE_LEFT_BUTTON;
-	} else if (strcmp(buf, "middle") == 0) {
-		aiptek->newSetting.mouseButtonMiddle =
-		    AIPTEK_MOUSE_MIDDLE_BUTTON;
-	} else if (strcmp(buf, "right") == 0) {
-		aiptek->newSetting.mouseButtonMiddle =
-		    AIPTEK_MOUSE_RIGHT_BUTTON;
-	}
+	aiptek->newSetting.mouseButtonMiddle = new_button;
 	return count;
 }
 
@@ -1706,47 +1496,22 @@
 static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	char *s;
 
-	if (aiptek == NULL)
-		return 0;
-
-	switch (aiptek->curSetting.mouseButtonRight) {
-	case AIPTEK_MOUSE_LEFT_BUTTON:
-		s = "left";
-		break;
-
-	case AIPTEK_MOUSE_MIDDLE_BUTTON:
-		s = "middle";
-		break;
-
-	case AIPTEK_MOUSE_RIGHT_BUTTON:
-		s = "right";
-		break;
-
-	default:
-		s = "unknown";
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%s\n", s);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			map_val_to_str(mouse_button_map,
+					aiptek->curSetting.mouseButtonRight));
 }
 
 static ssize_t
 store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
+	int new_button = map_str_to_val(mouse_button_map, buf, count);
 
-	if (aiptek == NULL)
-		return 0;
+	if (new_button == AIPTEK_INVALID_VALUE)
+		return -EINVAL;
 
-	if (strcmp(buf, "left") == 0) {
-		aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_LEFT_BUTTON;
-	} else if (strcmp(buf, "middle") == 0) {
-		aiptek->newSetting.mouseButtonRight =
-		    AIPTEK_MOUSE_MIDDLE_BUTTON;
-	} else if (strcmp(buf, "right") == 0) {
-		aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON;
-	}
+	aiptek->newSetting.mouseButtonRight = new_button;
 	return count;
 }
 
@@ -1762,9 +1527,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) {
 		return snprintf(buf, PAGE_SIZE, "disable\n");
 	} else {
@@ -1778,9 +1540,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10);
 	return count;
 }
@@ -1794,11 +1553,6 @@
  */
 static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct aiptek *aiptek = dev_get_drvdata(dev);
-
-	if (aiptek == NULL)
-		return 0;
-
 	/* There is nothing useful to display, so a one-line manual
 	 * is in order...
 	 */
@@ -1811,9 +1565,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	/* We do not care what you write to this file. Merely the action
 	 * of writing to this file triggers a tablet reprogramming.
 	 */
@@ -1837,9 +1588,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode);
 }
 
@@ -1853,9 +1601,6 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode);
 }
 
@@ -1869,86 +1614,39 @@
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
-	if (aiptek == NULL)
-		return 0;
-
 	return snprintf(buf, PAGE_SIZE, "%04x\n",
 			aiptek->features.firmwareCode);
 }
 
 static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL);
 
-/***********************************************************************
- * This routine removes all existing sysfs files managed by this device
- * driver.
- */
-static void aiptek_delete_files(struct device *dev)
-{
-	device_remove_file(dev, &dev_attr_size);
-	device_remove_file(dev, &dev_attr_product_id);
-	device_remove_file(dev, &dev_attr_vendor_id);
-	device_remove_file(dev, &dev_attr_vendor);
-	device_remove_file(dev, &dev_attr_product);
-	device_remove_file(dev, &dev_attr_pointer_mode);
-	device_remove_file(dev, &dev_attr_coordinate_mode);
-	device_remove_file(dev, &dev_attr_tool_mode);
-	device_remove_file(dev, &dev_attr_xtilt);
-	device_remove_file(dev, &dev_attr_ytilt);
-	device_remove_file(dev, &dev_attr_jitter);
-	device_remove_file(dev, &dev_attr_delay);
-	device_remove_file(dev, &dev_attr_input_path);
-	device_remove_file(dev, &dev_attr_event_count);
-	device_remove_file(dev, &dev_attr_diagnostic);
-	device_remove_file(dev, &dev_attr_odm_code);
-	device_remove_file(dev, &dev_attr_model_code);
-	device_remove_file(dev, &dev_attr_firmware_code);
-	device_remove_file(dev, &dev_attr_stylus_lower);
-	device_remove_file(dev, &dev_attr_stylus_upper);
-	device_remove_file(dev, &dev_attr_mouse_left);
-	device_remove_file(dev, &dev_attr_mouse_middle);
-	device_remove_file(dev, &dev_attr_mouse_right);
-	device_remove_file(dev, &dev_attr_wheel);
-	device_remove_file(dev, &dev_attr_execute);
-}
+static struct attribute *aiptek_attributes[] = {
+	&dev_attr_size.attr,
+	&dev_attr_pointer_mode.attr,
+	&dev_attr_coordinate_mode.attr,
+	&dev_attr_tool_mode.attr,
+	&dev_attr_xtilt.attr,
+	&dev_attr_ytilt.attr,
+	&dev_attr_jitter.attr,
+	&dev_attr_delay.attr,
+	&dev_attr_event_count.attr,
+	&dev_attr_diagnostic.attr,
+	&dev_attr_odm_code.attr,
+	&dev_attr_model_code.attr,
+	&dev_attr_firmware_code.attr,
+	&dev_attr_stylus_lower.attr,
+	&dev_attr_stylus_upper.attr,
+	&dev_attr_mouse_left.attr,
+	&dev_attr_mouse_middle.attr,
+	&dev_attr_mouse_right.attr,
+	&dev_attr_wheel.attr,
+	&dev_attr_execute.attr,
+	NULL
+};
 
-/***********************************************************************
- * This routine creates the sysfs files managed by this device
- * driver.
- */
-static int aiptek_add_files(struct device *dev)
-{
-	int ret;
-
-	if ((ret = device_create_file(dev, &dev_attr_size)) ||
-	    (ret = device_create_file(dev, &dev_attr_product_id)) ||
-	    (ret = device_create_file(dev, &dev_attr_vendor_id)) ||
-	    (ret = device_create_file(dev, &dev_attr_vendor)) ||
-	    (ret = device_create_file(dev, &dev_attr_product)) ||
-	    (ret = device_create_file(dev, &dev_attr_pointer_mode)) ||
-	    (ret = device_create_file(dev, &dev_attr_coordinate_mode)) ||
-	    (ret = device_create_file(dev, &dev_attr_tool_mode)) ||
-	    (ret = device_create_file(dev, &dev_attr_xtilt)) ||
-	    (ret = device_create_file(dev, &dev_attr_ytilt)) ||
-	    (ret = device_create_file(dev, &dev_attr_jitter)) ||
-	    (ret = device_create_file(dev, &dev_attr_delay)) ||
-	    (ret = device_create_file(dev, &dev_attr_input_path)) ||
-	    (ret = device_create_file(dev, &dev_attr_event_count)) ||
-	    (ret = device_create_file(dev, &dev_attr_diagnostic)) ||
-	    (ret = device_create_file(dev, &dev_attr_odm_code)) ||
-	    (ret = device_create_file(dev, &dev_attr_model_code)) ||
-	    (ret = device_create_file(dev, &dev_attr_firmware_code)) ||
-	    (ret = device_create_file(dev, &dev_attr_stylus_lower)) ||
-	    (ret = device_create_file(dev, &dev_attr_stylus_upper)) ||
-	    (ret = device_create_file(dev, &dev_attr_mouse_left)) ||
-	    (ret = device_create_file(dev, &dev_attr_mouse_middle)) ||
-	    (ret = device_create_file(dev, &dev_attr_mouse_right)) ||
-	    (ret = device_create_file(dev, &dev_attr_wheel)) ||
-	    (ret = device_create_file(dev, &dev_attr_execute))) {
-		err("aiptek: killing own sysfs device files\n");
-		aiptek_delete_files(dev);
-	}
-	return ret;
-}
+static struct attribute_group aiptek_attribute_group = {
+	.attrs	= aiptek_attributes,
+};
 
 /***********************************************************************
  * This routine is called when a tablet has been identified. It basically
@@ -1961,8 +1659,6 @@
 	struct usb_endpoint_descriptor *endpoint;
 	struct aiptek *aiptek;
 	struct input_dev *inputdev;
-	struct input_handle *inputhandle;
-	struct list_head *node, *next;
 	int i;
 	int speeds[] = { 0,
 		AIPTEK_PROGRAMMABLE_DELAY_50,
@@ -1984,17 +1680,23 @@
 
 	aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL);
 	inputdev = input_allocate_device();
-	if (!aiptek || !inputdev)
+	if (!aiptek || !inputdev) {
+		warn("aiptek: cannot allocate memory or input device");
 		goto fail1;
+        }
 
 	aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
 					GFP_ATOMIC, &aiptek->data_dma);
-	if (!aiptek->data)
+        if (!aiptek->data) {
+		warn("aiptek: cannot allocate usb buffer");
 		goto fail1;
+	}
 
 	aiptek->urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!aiptek->urb)
+	if (!aiptek->urb) {
+	        warn("aiptek: cannot allocate urb");
 		goto fail2;
+	}
 
 	aiptek->inputdev = inputdev;
 	aiptek->usbdev = usbdev;
@@ -2002,6 +1704,7 @@
 	aiptek->inDelay = 0;
 	aiptek->endDelay = 0;
 	aiptek->previousJitterable = 0;
+	aiptek->lastMacro = -1;
 
 	/* Set up the curSettings struct. Said struct contains the current
 	 * programmable parameters. The newSetting struct contains changes
@@ -2054,36 +1757,23 @@
 	/* Now program the capacities of the tablet, in terms of being
 	 * an input device.
 	 */
-	inputdev->evbit[0] |= BIT(EV_KEY)
-	    | BIT(EV_ABS)
-	    | BIT(EV_REL)
-	    | BIT(EV_MSC);
+	for (i = 0; i < ARRAY_SIZE(eventTypes); ++i)
+	        __set_bit(eventTypes[i], inputdev->evbit);
 
-	inputdev->absbit[0] |= BIT(ABS_MISC);
+	for (i = 0; i < ARRAY_SIZE(absEvents); ++i)
+	        __set_bit(absEvents[i], inputdev->absbit);
 
-	inputdev->relbit[0] |=
-	    (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC));
+	for (i = 0; i < ARRAY_SIZE(relEvents); ++i)
+	        __set_bit(relEvents[i], inputdev->relbit);
 
-	inputdev->keybit[LONG(BTN_LEFT)] |=
-	    (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE));
+	__set_bit(MSC_SERIAL, inputdev->mscbit);
 
-	inputdev->keybit[LONG(BTN_DIGI)] |=
-	    (BIT(BTN_TOOL_PEN) |
-	     BIT(BTN_TOOL_RUBBER) |
-	     BIT(BTN_TOOL_PENCIL) |
-	     BIT(BTN_TOOL_AIRBRUSH) |
-	     BIT(BTN_TOOL_BRUSH) |
-	     BIT(BTN_TOOL_MOUSE) |
-	     BIT(BTN_TOOL_LENS) |
-	     BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2));
+	/* Set up key and button codes */
+	for (i = 0; i < ARRAY_SIZE(buttonEvents); ++i)
+		__set_bit(buttonEvents[i], inputdev->keybit);
 
-	inputdev->mscbit[0] = BIT(MSC_SERIAL);
-
-	/* Programming the tablet macro keys needs to be done with a for loop
-	 * as the keycodes are discontiguous.
-	 */
 	for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i)
-		set_bit(macroKeyEvents[i], inputdev->keybit);
+		__set_bit(macroKeyEvents[i], inputdev->keybit);
 
 	/*
 	 * Program the input device coordinate capacities. We do not yet
@@ -2134,25 +1824,11 @@
 		}
 	}
 
-	/* Register the tablet as an Input Device
-	 */
-	err = input_register_device(aiptek->inputdev);
-	if (err)
+	/* Murphy says that some day someone will have a tablet that fails the
+	   above test. That's you, Frederic Rodrigo */
+	if (i == ARRAY_SIZE(speeds)) {
+		info("input: Aiptek tried all speeds, no sane response");
 		goto fail2;
-
-	/* We now will look for the evdev device which is mapped to
-	 * the tablet. The partial name is kept in the link list of
-	 * input_handles associated with this input device.
-	 * What identifies an evdev input_handler is that it begins
-	 * with 'event', continues with a digit, and that in turn
-	 * is mapped to input/eventN.
-	 */
-	list_for_each_safe(node, next, &inputdev->h_list) {
-		inputhandle = to_handle(node);
-		if (strncmp(inputhandle->name, "event", 5) == 0) {
-			strcpy(aiptek->features.inputPath, inputhandle->name);
-			break;
-		}
 	}
 
 	/* Associate this driver's struct with the usb interface.
@@ -2161,18 +1837,27 @@
 
 	/* Set up the sysfs files
 	 */
-	aiptek_add_files(&intf->dev);
+	err = sysfs_create_group(&intf->dev.kobj, &aiptek_attribute_group);
+	if (err) {
+		warn("aiptek: cannot create sysfs group err: %d", err);
+		goto fail3;
+        }
 
-	/* Make sure the evdev module is loaded. Assuming evdev IS a module :-)
+	/* Register the tablet as an Input Device
 	 */
-	if (request_module("evdev") != 0)
-		info("aiptek: error loading 'evdev' module");
-
+	err = input_register_device(aiptek->inputdev);
+	if (err) {
+		warn("aiptek: input_register_device returned err: %d", err);
+		goto fail4;
+        }
 	return 0;
 
+ fail4:	sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
+ fail3: usb_free_urb(aiptek->urb);
  fail2:	usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
 			aiptek->data_dma);
- fail1:	input_free_device(inputdev);
+ fail1: usb_set_intfdata(intf, NULL);
+	input_free_device(inputdev);
 	kfree(aiptek);
 	return err;
 }
@@ -2192,7 +1877,7 @@
 		 */
 		usb_kill_urb(aiptek->urb);
 		input_unregister_device(aiptek->inputdev);
-		aiptek_delete_files(&intf->dev);
+		sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
 		usb_free_urb(aiptek->urb);
 		usb_buffer_free(interface_to_usbdev(intf),
 				AIPTEK_PACKET_LENGTH,
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index ef01a80..6542edb 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -11,7 +11,7 @@
  *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
  *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
  *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris@mech.kuleuven.ac.be>
- *  Copyright (c) 2002-2006 Ping Cheng		<pingc@wacom.com>
+ *  Copyright (c) 2002-2007 Ping Cheng		<pingc@wacom.com>
  *
  *  ChangeLog:
  *      v0.1 (vp)  - Initial release
@@ -62,8 +62,9 @@
  *                 - Minor data report fix
  *      v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c,
  *		   - where wacom_sys.c deals with system specific code,
- * 		   - and wacom_wac.c deals with Wacom specific code
+ *		   - and wacom_wac.c deals with Wacom specific code
  *		   - Support Intuos3 4x6
+ *      v1.47 (pc) - Added support for Bamboo
  */
 
 /*
@@ -84,7 +85,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.46"
+#define DRIVER_VERSION "v1.47"
 #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
 #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
 #define DRIVER_LICENSE "GPL"
@@ -123,6 +124,7 @@
 extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern __u16 wacom_le16_to_cpu(unsigned char *data);
 extern __u16 wacom_be16_to_cpu(unsigned char *data);
 extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 83bddef..064e123 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -138,6 +138,12 @@
 	usb_kill_urb(wacom->irq);
 }
 
+void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_1) | BIT(BTN_5);
+	input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+}
+
 void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 {
 	input_dev->evbit[0] |= BIT(EV_MSC);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 7661f03..fc03ba2 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -178,7 +178,8 @@
 
 			case 2: /* Mouse with wheel */
 				wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);
-				if (wacom->features->type == WACOM_G4) {
+				if (wacom->features->type == WACOM_G4 ||
+						wacom->features->type == WACOM_MO) {
 					rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
 					wacom_report_rel(wcombo, REL_WHEEL, -rw);
 				} else
@@ -190,7 +191,8 @@
 				id = CURSOR_DEVICE_ID;
 				wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
 				wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
-				if (wacom->features->type == WACOM_G4)
+				if (wacom->features->type == WACOM_G4 ||
+						wacom->features->type == WACOM_MO)
 					wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f);
 				else
 					wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
@@ -226,7 +228,8 @@
 	}
 
 	/* send pad data */
-	if (wacom->features->type == WACOM_G4) {
+	switch (wacom->features->type) {
+	    case WACOM_G4:
 		if (data[7] & 0xf8) {
 			wacom_input_sync(wcombo); /* sync last event */
 			wacom->id[1] = 1;
@@ -247,6 +250,33 @@
 			wacom_report_abs(wcombo, ABS_MISC, 0);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 		}
+		break;
+	    case WACOM_MO:
+		if ((data[7] & 0xf8) || (data[8] & 0x80)) {
+			wacom_input_sync(wcombo); /* sync last event */
+			wacom->id[1] = 1;
+			wacom->serial[1] = (data[7] & 0xf8);
+			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
+			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
+			wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
+			wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
+			wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
+			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
+			wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+		} else if (wacom->id[1]) {
+			wacom_input_sync(wcombo); /* sync last event */
+			wacom->id[1] = 0;
+			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
+			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
+			wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
+			wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
+			wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
+			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
+			wacom_report_abs(wcombo, ABS_MISC, 0);
+			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+		}
+		break;
 	}
 	return 1;
 }
@@ -331,7 +361,7 @@
 			wacom_report_key(wcombo, BTN_EXTRA, 0);
 			wacom_report_abs(wcombo, ABS_THROTTLE, 0);
 			wacom_report_abs(wcombo, ABS_RZ, 0);
- 		} else {
+		} else {
 			wacom_report_abs(wcombo, ABS_PRESSURE, 0);
 			wacom_report_abs(wcombo, ABS_TILT_X, 0);
 			wacom_report_abs(wcombo, ABS_TILT_Y, 0);
@@ -423,9 +453,9 @@
                 return result-1;
 
 	/* Only large I3 and I1 & I2 support Lense Cursor */
- 	if((wacom->tool[idx] == BTN_TOOL_LENS)
+	if ((wacom->tool[idx] == BTN_TOOL_LENS)
 			&& ((wacom->features->type == INTUOS3)
-		 	|| (wacom->features->type == INTUOS3S)))
+			|| (wacom->features->type == INTUOS3S)))
 		return 0;
 
 	/* Cintiq doesn't send data when RDY bit isn't set */
@@ -517,6 +547,7 @@
 			break;
 		case WACOM_G4:
 		case GRAPHIRE:
+		case WACOM_MO:
 			return (wacom_graphire_irq(wacom_wac, wcombo));
 			break;
 		case PTU:
@@ -538,6 +569,8 @@
 void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 {
 	switch (wacom_wac->features->type) {
+		case WACOM_MO:
+			input_dev_mo(input_dev, wacom_wac);
 		case WACOM_G4:
 			input_dev_g4(input_dev, wacom_wac);
 			/* fall through */
@@ -579,6 +612,7 @@
 	{ "Wacom Volito2 4x5",   8,   5104,  3712,  511, 63, GRAPHIRE },
 	{ "Wacom Volito2 2x3",   8,   3248,  2320,  511, 63, GRAPHIRE },
 	{ "Wacom PenPartner2",   8,   3250,  2320,  255, 63, GRAPHIRE },
+	{ "Wacom Bamboo",        9,  14760,  9225,  511, 63, WACOM_MO },
 	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 31, INTUOS },
 	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 31, INTUOS },
 	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 31, INTUOS },
@@ -627,6 +661,7 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index a5e12e8..a302e22 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -25,6 +25,7 @@
 	INTUOS3,
 	INTUOS3L,
 	CINTIQ,
+	WACOM_MO,
 	MAX_TYPE
 };
 
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index e5cca9b..6937177 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -177,6 +177,7 @@
 	  - some other eTurboTouch
 	  - Gunze AHL61
 	  - DMC TSC-10/25
+	  - IRTOUCHSYSTEMS/UNITOP
 
 	  Have a look at <http://linux.chapter7.ch/touchkit/> for
 	  a usage description and the required user-space stuff.
@@ -219,4 +220,9 @@
 	bool "DMC TSC-10/25 device support" if EMBEDDED
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
+config TOUCHSCREEN_USB_IRTOUCH
+	default y
+	bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
 endif
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index e3f2285..b407028 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -9,6 +9,7 @@
  *  - eTurboTouch
  *  - Gunze AHL61
  *  - DMC TSC-10/25
+ *  - IRTOUCHSYSTEMS/UNITOP
  *
  * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -110,6 +111,7 @@
 	DEVTYPE_ETURBO,
 	DEVTYPE_GUNZE,
 	DEVTYPE_DMC_TSC10,
+	DEVTYPE_IRTOUCH,
 };
 
 static struct usb_device_id usbtouch_devices[] = {
@@ -150,6 +152,11 @@
 	{USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
 #endif
 
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+	{USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
+	{USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
+#endif
+
 	{}
 };
 
@@ -416,6 +423,21 @@
 
 
 /*****************************************************************************
+ * IRTOUCH Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+	dev->x = (pkt[3] << 8) | pkt[2];
+	dev->y = (pkt[5] << 8) | pkt[4];
+	dev->touch = (pkt[1] & 0x03) ? 1 : 0;
+
+	return 1;
+}
+#endif
+
+
+/*****************************************************************************
  * the different device descriptors
  */
 static struct usbtouch_device_info usbtouch_dev_info[] = {
@@ -504,6 +526,17 @@
 		.read_data	= dmc_tsc10_read_data,
 	},
 #endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+	[DEVTYPE_IRTOUCH] = {
+		.min_xc		= 0x0,
+		.max_xc		= 0x0fff,
+		.min_yc		= 0x0,
+		.max_yc		= 0x0fff,
+		.rept_size	= 8,
+		.read_data	= irtouch_read_data,
+	},
+#endif
 };
 
 
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 2db3648..d2f882e 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -109,9 +109,11 @@
 	int open;
 	int minor;
 	char name[8];
+	struct input_handle handle;
 	wait_queue_head_t wait;
 	struct list_head client_list;
-	struct input_handle handle;
+	struct device dev;
+
 	int x, y, pressure;
 	struct ts_calibration cal;
 };
@@ -163,9 +165,13 @@
 	if (!tsdev || !tsdev->exist)
 		return -ENODEV;
 
+	get_device(&tsdev->dev);
+
 	client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
-	if (!client)
-		return -ENOMEM;
+	if (!client) {
+		error = -ENOMEM;
+		goto err_put_tsdev;
+	}
 
 	client->tsdev = tsdev;
 	client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
@@ -173,19 +179,25 @@
 
 	if (!tsdev->open++ && tsdev->exist) {
 		error = input_open_device(&tsdev->handle);
-		if (error) {
-			list_del(&client->node);
-			kfree(client);
-			return error;
-		}
+		if (error)
+			goto err_free_client;
 	}
 
 	file->private_data = client;
 	return 0;
+
+ err_free_client:
+	list_del(&client->node);
+	kfree(client);
+ err_put_tsdev:
+	put_device(&tsdev->dev);
+	return error;
 }
 
-static void tsdev_free(struct tsdev *tsdev)
+static void tsdev_free(struct device *dev)
 {
+	struct tsdev *tsdev = container_of(dev, struct tsdev, dev);
+
 	tsdev_table[tsdev->minor] = NULL;
 	kfree(tsdev);
 }
@@ -200,12 +212,10 @@
 	list_del(&client->node);
 	kfree(client);
 
-	if (!--tsdev->open) {
-		if (tsdev->exist)
-			input_close_device(&tsdev->handle);
-		else
-			tsdev_free(tsdev);
-	}
+	if (!--tsdev->open && tsdev->exist)
+		input_close_device(&tsdev->handle);
+
+	put_device(&tsdev->dev);
 
 	return 0;
 }
@@ -361,7 +371,7 @@
 		int x, y, tmp;
 
 		do_gettimeofday(&time);
-		client->event[client->head].millisecs = time.tv_usec / 100;
+		client->event[client->head].millisecs = time.tv_usec / 1000;
 		client->event[client->head].pressure = tsdev->pressure;
 
 		x = tsdev->x;
@@ -388,8 +398,6 @@
 			 const struct input_device_id *id)
 {
 	struct tsdev *tsdev;
-	struct class_device *cdev;
-	dev_t devt;
 	int minor, delta;
 	int error;
 
@@ -407,14 +415,13 @@
 	INIT_LIST_HEAD(&tsdev->client_list);
 	init_waitqueue_head(&tsdev->wait);
 
-	sprintf(tsdev->name, "ts%d", minor);
-
 	tsdev->exist = 1;
 	tsdev->minor = minor;
 	tsdev->handle.dev = dev;
 	tsdev->handle.name = tsdev->name;
 	tsdev->handle.handler = handler;
 	tsdev->handle.private = tsdev;
+	snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor);
 
 	/* Precompute the rough calibration matrix */
 	delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1;
@@ -429,36 +436,30 @@
 	tsdev->cal.yscale = (yres << 8) / delta;
 	tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
 
+	snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id),
+		 "ts%d", minor);
+	tsdev->dev.class = &input_class;
+	tsdev->dev.parent = &dev->dev;
+	tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor);
+	tsdev->dev.release = tsdev_free;
+	device_initialize(&tsdev->dev);
+
 	tsdev_table[minor] = tsdev;
 
-	devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
-
-	cdev = class_device_create(&input_class, &dev->cdev, devt,
-				   dev->cdev.dev, tsdev->name);
-	if (IS_ERR(cdev)) {
-		error = PTR_ERR(cdev);
-		goto err_free_tsdev;
-	}
-
-	/* temporary symlink to keep userspace happy */
-	error = sysfs_create_link(&input_class.subsys.kobj,
-				  &cdev->kobj, tsdev->name);
+	error = device_add(&tsdev->dev);
 	if (error)
-		goto err_cdev_destroy;
+		goto err_free_tsdev;
 
 	error = input_register_handle(&tsdev->handle);
 	if (error)
-		goto err_remove_link;
+		goto err_delete_tsdev;
 
 	return 0;
 
- err_remove_link:
-	sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
- err_cdev_destroy:
-	class_device_destroy(&input_class, devt);
+ err_delete_tsdev:
+	device_del(&tsdev->dev);
  err_free_tsdev:
-	tsdev_table[minor] = NULL;
-	kfree(tsdev);
+	put_device(&tsdev->dev);
 	return error;
 }
 
@@ -468,10 +469,8 @@
 	struct tsdev_client *client;
 
 	input_unregister_handle(handle);
+	device_del(&tsdev->dev);
 
-	sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
-	class_device_destroy(&input_class,
-			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
 	tsdev->exist = 0;
 
 	if (tsdev->open) {
@@ -479,8 +478,9 @@
 		list_for_each_entry(client, &tsdev->client_list, node)
 			kill_fasync(&client->fasync, SIGIO, POLL_HUP);
 		wake_up_interruptible(&tsdev->wait);
-	} else
-		tsdev_free(tsdev);
+	}
+
+	put_device(&tsdev->dev);
 }
 
 static const struct input_device_id tsdev_ids[] = {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 616eee9..bd601ef 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -34,6 +34,11 @@
 	  If you choose to build module, its name will be phantom. If unsure,
 	  say N here.
 
+config EEPROM_93CX6
+	tristate "EEPROM 93CX6 support"
+	---help---
+	  This is a driver for the EEPROM chipsets 93c46 and 93c66.
+	  The driver supports both read as well as write commands.
 
 	  If unsure, say N.
 
@@ -187,5 +192,4 @@
 
 	  If you are not sure, say Y here.
 
-
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 8abbf2f..b5ce0e3 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -14,3 +14,4 @@
 obj-$(CONFIG_SGI_IOC4)		+= ioc4.o
 obj-$(CONFIG_SONY_LAPTOP)	+= sony-laptop.o
 obj-$(CONFIG_THINKPAD_ACPI)	+= thinkpad_acpi.o
+obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
new file mode 100644
index 0000000..ea55654
--- /dev/null
+++ b/drivers/misc/eeprom_93cx6.c
@@ -0,0 +1,241 @@
+/*
+	Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
+	<http://rt2x00.serialmonkey.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.
+ */
+
+/*
+	Module: eeprom_93cx6
+	Abstract: EEPROM reader routines for 93cx6 chipsets.
+	Supported chipsets: 93c46 & 93c66.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/eeprom_93cx6.h>
+
+MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
+MODULE_LICENSE("GPL");
+
+static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
+{
+	eeprom->reg_data_clock = 1;
+	eeprom->register_write(eeprom);
+
+	/*
+	 * Add a short delay for the pulse to work.
+	 * According to the specifications the "maximum minimum"
+	 * time should be 450ns.
+	 */
+	ndelay(450);
+}
+
+static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
+{
+	eeprom->reg_data_clock = 0;
+	eeprom->register_write(eeprom);
+
+	/*
+	 * Add a short delay for the pulse to work.
+	 * According to the specifications the "maximum minimum"
+	 * time should be 450ns.
+	 */
+	ndelay(450);
+}
+
+static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
+{
+	/*
+	 * Clear all flags, and enable chip select.
+	 */
+	eeprom->register_read(eeprom);
+	eeprom->reg_data_in = 0;
+	eeprom->reg_data_out = 0;
+	eeprom->reg_data_clock = 0;
+	eeprom->reg_chip_select = 1;
+	eeprom->register_write(eeprom);
+
+	/*
+	 * kick a pulse.
+	 */
+	eeprom_93cx6_pulse_high(eeprom);
+	eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
+{
+	/*
+	 * Clear chip_select and data_in flags.
+	 */
+	eeprom->register_read(eeprom);
+	eeprom->reg_data_in = 0;
+	eeprom->reg_chip_select = 0;
+	eeprom->register_write(eeprom);
+
+	/*
+	 * kick a pulse.
+	 */
+	eeprom_93cx6_pulse_high(eeprom);
+	eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
+	const u16 data, const u16 count)
+{
+	unsigned int i;
+
+	eeprom->register_read(eeprom);
+
+	/*
+	 * Clear data flags.
+	 */
+	eeprom->reg_data_in = 0;
+	eeprom->reg_data_out = 0;
+
+	/*
+	 * Start writing all bits.
+	 */
+	for (i = count; i > 0; i--) {
+		/*
+		 * Check if this bit needs to be set.
+		 */
+		eeprom->reg_data_in = !!(data & (1 << (i - 1)));
+
+		/*
+		 * Write the bit to the eeprom register.
+		 */
+		eeprom->register_write(eeprom);
+
+		/*
+		 * Kick a pulse.
+		 */
+		eeprom_93cx6_pulse_high(eeprom);
+		eeprom_93cx6_pulse_low(eeprom);
+	}
+
+	eeprom->reg_data_in = 0;
+	eeprom->register_write(eeprom);
+}
+
+static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
+	u16 *data, const u16 count)
+{
+	unsigned int i;
+	u16 buf = 0;
+
+	eeprom->register_read(eeprom);
+
+	/*
+	 * Clear data flags.
+	 */
+	eeprom->reg_data_in = 0;
+	eeprom->reg_data_out = 0;
+
+	/*
+	 * Start reading all bits.
+	 */
+	for (i = count; i > 0; i--) {
+		eeprom_93cx6_pulse_high(eeprom);
+
+		eeprom->register_read(eeprom);
+
+		/*
+		 * Clear data_in flag.
+		 */
+		eeprom->reg_data_in = 0;
+
+		/*
+		 * Read if the bit has been set.
+		 */
+		if (eeprom->reg_data_out)
+			buf |= (1 << (i - 1));
+
+		eeprom_93cx6_pulse_low(eeprom);
+	}
+
+	*data = buf;
+}
+
+/**
+ * eeprom_93cx6_read - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ *
+ * This function will read the eeprom data as host-endian word
+ * into the given data pointer.
+ */
+void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
+	u16 *data)
+{
+	u16 command;
+
+	/*
+	 * Initialize the eeprom register
+	 */
+	eeprom_93cx6_startup(eeprom);
+
+	/*
+	 * Select the read opcode and the word to be read.
+	 */
+	command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
+	eeprom_93cx6_write_bits(eeprom, command,
+		PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+
+	/*
+	 * Read the requested 16 bits.
+	 */
+	eeprom_93cx6_read_bits(eeprom, data, 16);
+
+	/*
+	 * Cleanup eeprom register.
+	 */
+	eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
+
+/**
+ * eeprom_93cx6_multiread - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ * @words: Number of words that should be read.
+ *
+ * This function will read all requested words from the eeprom,
+ * this is done by calling eeprom_93cx6_read() multiple times.
+ * But with the additional change that while the eeprom_93cx6_read
+ * will return host ordered bytes, this method will return little
+ * endian words.
+ */
+void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
+	__le16 *data, const u16 words)
+{
+	unsigned int i;
+	u16 tmp;
+
+	for (i = 0; i < words; i++) {
+		tmp = 0;
+		eeprom_93cx6_read(eeprom, word + i, &tmp);
+		data[i] = cpu_to_le16(tmp);
+	}
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
+
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index 9320a8c..a49cb97 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -14,3 +14,21 @@
 	  mount the filesystem. Almost everyone wishing MMC support
 	  should say Y or M here.
 
+config MMC_BLOCK_BOUNCE
+	bool "Use bounce buffer for simple hosts"
+	depends on MMC_BLOCK
+	default y
+	help
+	  SD/MMC is a high latency protocol where it is crucial to
+	  send large requests in order to get high performance. Many
+	  controllers, however, are restricted to continuous memory
+	  (i.e. they can't do scatter-gather), something the kernel
+	  rarely can provide.
+
+	  Say Y here to help these restricted hosts by bouncing
+	  requests back and forth from a large buffer. You will get
+	  a big performance gain at the cost of up to 64 KiB of
+	  physical memory.
+
+	  If unsure, say Y here.
+
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 540ff4b..cbd4b6e 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -262,7 +262,9 @@
 		}
 
 		brq.data.sg = mq->sg;
-		brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
+		brq.data.sg_len = mmc_queue_map_sg(mq);
+
+		mmc_queue_bounce_pre(mq);
 
 		if (brq.data.blocks !=
 		    (req->nr_sectors >> (md->block_bits - 9))) {
@@ -279,6 +281,9 @@
 		}
 
 		mmc_wait_for_req(card->host, &brq.mrq);
+
+		mmc_queue_bounce_post(mq);
+
 		if (brq.cmd.error) {
 			printk(KERN_ERR "%s: error %d sending read/write command\n",
 			       req->rq_disk->disk_name, brq.cmd.error);
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index dd97bc7..4fb2089 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -17,6 +17,8 @@
 #include <linux/mmc/host.h>
 #include "queue.h"
 
+#define MMC_QUEUE_BOUNCESZ	65536
+
 #define MMC_QUEUE_SUSPENDED	(1 << 0)
 
 /*
@@ -118,6 +120,7 @@
 	struct mmc_host *host = card->host;
 	u64 limit = BLK_BOUNCE_HIGH;
 	int ret;
+	unsigned int bouncesz;
 
 	if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
 		limit = *mmc_dev(host)->dma_mask;
@@ -127,21 +130,61 @@
 	if (!mq->queue)
 		return -ENOMEM;
 
-	blk_queue_prep_rq(mq->queue, mmc_prep_request);
-	blk_queue_bounce_limit(mq->queue, limit);
-	blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
-	blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
-	blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
-	blk_queue_max_segment_size(mq->queue, host->max_seg_size);
-
 	mq->queue->queuedata = mq;
 	mq->req = NULL;
 
-	mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs,
-			 GFP_KERNEL);
-	if (!mq->sg) {
-		ret = -ENOMEM;
-		goto cleanup_queue;
+	blk_queue_prep_rq(mq->queue, mmc_prep_request);
+
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+	if (host->max_hw_segs == 1) {
+		bouncesz = MMC_QUEUE_BOUNCESZ;
+
+		if (bouncesz > host->max_req_size)
+			bouncesz = host->max_req_size;
+		if (bouncesz > host->max_seg_size)
+			bouncesz = host->max_seg_size;
+
+		mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+		if (!mq->bounce_buf) {
+			printk(KERN_WARNING "%s: unable to allocate "
+				"bounce buffer\n", mmc_card_name(card));
+		} else {
+			blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH);
+			blk_queue_max_sectors(mq->queue, bouncesz / 512);
+			blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
+			blk_queue_max_hw_segments(mq->queue, bouncesz / 512);
+			blk_queue_max_segment_size(mq->queue, bouncesz);
+
+			mq->sg = kmalloc(sizeof(struct scatterlist),
+				GFP_KERNEL);
+			if (!mq->sg) {
+				ret = -ENOMEM;
+				goto free_bounce_buf;
+			}
+
+			mq->bounce_sg = kmalloc(sizeof(struct scatterlist) *
+				bouncesz / 512, GFP_KERNEL);
+			if (!mq->bounce_sg) {
+				ret = -ENOMEM;
+				goto free_sg;
+			}
+		}
+	}
+#endif
+
+	if (!mq->bounce_buf) {
+		blk_queue_bounce_limit(mq->queue, limit);
+		blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
+		blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
+		blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
+		blk_queue_max_segment_size(mq->queue, host->max_seg_size);
+
+		mq->sg = kmalloc(sizeof(struct scatterlist) *
+			host->max_phys_segs, GFP_KERNEL);
+		if (!mq->sg) {
+			ret = -ENOMEM;
+			goto cleanup_queue;
+		}
 	}
 
 	init_MUTEX(&mq->thread_sem);
@@ -149,14 +192,21 @@
 	mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
 	if (IS_ERR(mq->thread)) {
 		ret = PTR_ERR(mq->thread);
-		goto free_sg;
+		goto free_bounce_sg;
 	}
 
 	return 0;
-
+ free_bounce_sg:
+ 	if (mq->bounce_sg)
+ 		kfree(mq->bounce_sg);
+ 	mq->bounce_sg = NULL;
  free_sg:
 	kfree(mq->sg);
 	mq->sg = NULL;
+ free_bounce_buf:
+	if (mq->bounce_buf)
+		kfree(mq->bounce_buf);
+	mq->bounce_buf = NULL;
  cleanup_queue:
 	blk_cleanup_queue(mq->queue);
 	return ret;
@@ -178,9 +228,17 @@
 	/* Then terminate our worker thread */
 	kthread_stop(mq->thread);
 
+ 	if (mq->bounce_sg)
+ 		kfree(mq->bounce_sg);
+ 	mq->bounce_sg = NULL;
+
 	kfree(mq->sg);
 	mq->sg = NULL;
 
+	if (mq->bounce_buf)
+		kfree(mq->bounce_buf);
+	mq->bounce_buf = NULL;
+
 	blk_cleanup_queue(mq->queue);
 
 	mq->card = NULL;
@@ -231,3 +289,108 @@
 	}
 }
 
+static void copy_sg(struct scatterlist *dst, unsigned int dst_len,
+	struct scatterlist *src, unsigned int src_len)
+{
+	unsigned int chunk;
+	char *dst_buf, *src_buf;
+	unsigned int dst_size, src_size;
+
+	dst_buf = NULL;
+	src_buf = NULL;
+	dst_size = 0;
+	src_size = 0;
+
+	while (src_len) {
+		BUG_ON(dst_len == 0);
+
+		if (dst_size == 0) {
+			dst_buf = page_address(dst->page) + dst->offset;
+			dst_size = dst->length;
+		}
+
+		if (src_size == 0) {
+			src_buf = page_address(src->page) + src->offset;
+			src_size = src->length;
+		}
+
+		chunk = min(dst_size, src_size);
+
+		memcpy(dst_buf, src_buf, chunk);
+
+		dst_buf += chunk;
+		src_buf += chunk;
+		dst_size -= chunk;
+		src_size -= chunk;
+
+		if (dst_size == 0) {
+			dst++;
+			dst_len--;
+		}
+
+		if (src_size == 0) {
+			src++;
+			src_len--;
+		}
+	}
+}
+
+unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
+{
+	unsigned int sg_len;
+
+	if (!mq->bounce_buf)
+		return blk_rq_map_sg(mq->queue, mq->req, mq->sg);
+
+	BUG_ON(!mq->bounce_sg);
+
+	sg_len = blk_rq_map_sg(mq->queue, mq->req, mq->bounce_sg);
+
+	mq->bounce_sg_len = sg_len;
+
+	/*
+	 * Shortcut in the event we only get a single entry.
+	 */
+	if (sg_len == 1) {
+		memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist));
+		return 1;
+	}
+
+	mq->sg[0].page = virt_to_page(mq->bounce_buf);
+	mq->sg[0].offset = offset_in_page(mq->bounce_buf);
+	mq->sg[0].length = 0;
+
+	while (sg_len) {
+		mq->sg[0].length += mq->bounce_sg[sg_len - 1].length;
+		sg_len--;
+	}
+
+	return 1;
+}
+
+void mmc_queue_bounce_pre(struct mmc_queue *mq)
+{
+	if (!mq->bounce_buf)
+		return;
+
+	if (mq->bounce_sg_len == 1)
+		return;
+	if (rq_data_dir(mq->req) != WRITE)
+		return;
+
+	copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len);
+}
+
+void mmc_queue_bounce_post(struct mmc_queue *mq)
+{
+	if (!mq->bounce_buf)
+		return;
+
+	if (mq->bounce_sg_len == 1)
+		return;
+	if (rq_data_dir(mq->req) != READ)
+		return;
+
+	copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1);
+}
+
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 1590b3f..64e66e0 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -14,6 +14,9 @@
 	void			*data;
 	struct request_queue	*queue;
 	struct scatterlist	*sg;
+	char			*bounce_buf;
+	struct scatterlist	*bounce_sg;
+	unsigned int		bounce_sg_len;
 };
 
 extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
@@ -21,4 +24,8 @@
 extern void mmc_queue_suspend(struct mmc_queue *);
 extern void mmc_queue_resume(struct mmc_queue *);
 
+extern unsigned int mmc_queue_map_sg(struct mmc_queue *);
+extern void mmc_queue_bounce_pre(struct mmc_queue *);
+extern void mmc_queue_bounce_post(struct mmc_queue *);
+
 #endif
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 1075b02..3fdd08c 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -7,5 +7,6 @@
 endif
 
 obj-$(CONFIG_MMC)		+= mmc_core.o
-mmc_core-y			:= core.o sysfs.o mmc.o mmc_ops.o sd.o sd_ops.o
+mmc_core-y			:= core.o sysfs.o bus.o host.o \
+				   mmc.o mmc_ops.o sd.o sd_ops.o
 
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
new file mode 100644
index 0000000..348b566
--- /dev/null
+++ b/drivers/mmc/core/bus.c
@@ -0,0 +1,253 @@
+/*
+ *  linux/drivers/mmc/core/bus.c
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright (C) 2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  MMC card bus driver model
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include "sysfs.h"
+#include "core.h"
+#include "bus.h"
+
+#define dev_to_mmc_card(d)	container_of(d, struct mmc_card, dev)
+#define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
+
+static ssize_t mmc_type_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	switch (card->type) {
+	case MMC_TYPE_MMC:
+		return sprintf(buf, "MMC\n");
+	case MMC_TYPE_SD:
+		return sprintf(buf, "SD\n");
+	default:
+		return -EFAULT;
+	}
+}
+
+static struct device_attribute mmc_dev_attrs[] = {
+	MMC_ATTR_RO(type),
+	__ATTR_NULL,
+};
+
+/*
+ * This currently matches any MMC driver to any MMC card - drivers
+ * themselves make the decision whether to drive this card in their
+ * probe method.
+ */
+static int mmc_bus_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static int
+mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
+		int buf_size)
+{
+	struct mmc_card *card = dev_to_mmc_card(dev);
+	int retval = 0, i = 0, length = 0;
+
+#define add_env(fmt,val) do {					\
+	retval = add_uevent_var(envp, num_envp, &i,		\
+				buf, buf_size, &length,		\
+				fmt, val);			\
+	if (retval)						\
+		return retval;					\
+} while (0);
+
+	switch (card->type) {
+	case MMC_TYPE_MMC:
+		add_env("MMC_TYPE=%s", "MMC");
+		break;
+	case MMC_TYPE_SD:
+		add_env("MMC_TYPE=%s", "SD");
+		break;
+	}
+
+	add_env("MMC_NAME=%s", mmc_card_name(card));
+
+#undef add_env
+
+	envp[i] = NULL;
+
+	return 0;
+}
+
+static int mmc_bus_probe(struct device *dev)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	return drv->probe(card);
+}
+
+static int mmc_bus_remove(struct device *dev)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	drv->remove(card);
+
+	return 0;
+}
+
+static int mmc_bus_suspend(struct device *dev, pm_message_t state)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+	int ret = 0;
+
+	if (dev->driver && drv->suspend)
+		ret = drv->suspend(card, state);
+	return ret;
+}
+
+static int mmc_bus_resume(struct device *dev)
+{
+	struct mmc_driver *drv = to_mmc_driver(dev->driver);
+	struct mmc_card *card = dev_to_mmc_card(dev);
+	int ret = 0;
+
+	if (dev->driver && drv->resume)
+		ret = drv->resume(card);
+	return ret;
+}
+
+static struct bus_type mmc_bus_type = {
+	.name		= "mmc",
+	.dev_attrs	= mmc_dev_attrs,
+	.match		= mmc_bus_match,
+	.uevent		= mmc_bus_uevent,
+	.probe		= mmc_bus_probe,
+	.remove		= mmc_bus_remove,
+	.suspend	= mmc_bus_suspend,
+	.resume		= mmc_bus_resume,
+};
+
+int mmc_register_bus(void)
+{
+	return bus_register(&mmc_bus_type);
+}
+
+void mmc_unregister_bus(void)
+{
+	bus_unregister(&mmc_bus_type);
+}
+
+/**
+ *	mmc_register_driver - register a media driver
+ *	@drv: MMC media driver
+ */
+int mmc_register_driver(struct mmc_driver *drv)
+{
+	drv->drv.bus = &mmc_bus_type;
+	return driver_register(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_register_driver);
+
+/**
+ *	mmc_unregister_driver - unregister a media driver
+ *	@drv: MMC media driver
+ */
+void mmc_unregister_driver(struct mmc_driver *drv)
+{
+	drv->drv.bus = &mmc_bus_type;
+	driver_unregister(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_unregister_driver);
+
+static void mmc_release_card(struct device *dev)
+{
+	struct mmc_card *card = dev_to_mmc_card(dev);
+
+	kfree(card);
+}
+
+/*
+ * Allocate and initialise a new MMC card structure.
+ */
+struct mmc_card *mmc_alloc_card(struct mmc_host *host)
+{
+	struct mmc_card *card;
+
+	card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
+	if (!card)
+		return ERR_PTR(-ENOMEM);
+
+	memset(card, 0, sizeof(struct mmc_card));
+
+	card->host = host;
+
+	device_initialize(&card->dev);
+
+	card->dev.parent = mmc_classdev(host);
+	card->dev.bus = &mmc_bus_type;
+	card->dev.release = mmc_release_card;
+
+	return card;
+}
+
+/*
+ * Register a new MMC card with the driver model.
+ */
+int mmc_add_card(struct mmc_card *card)
+{
+	int ret;
+
+	snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+		 "%s:%04x", mmc_hostname(card->host), card->rca);
+
+	card->dev.uevent_suppress = 1;
+
+	ret = device_add(&card->dev);
+	if (ret)
+		return ret;
+
+	if (card->host->bus_ops->sysfs_add) {
+		ret = card->host->bus_ops->sysfs_add(card->host, card);
+		if (ret) {
+			device_del(&card->dev);
+			return ret;
+		 }
+	}
+
+	card->dev.uevent_suppress = 0;
+
+	kobject_uevent(&card->dev.kobj, KOBJ_ADD);
+
+	mmc_card_set_present(card);
+
+	return 0;
+}
+
+/*
+ * Unregister a new MMC card with the driver model, and
+ * (eventually) free it.
+ */
+void mmc_remove_card(struct mmc_card *card)
+{
+	if (mmc_card_present(card)) {
+		if (card->host->bus_ops->sysfs_remove)
+			card->host->bus_ops->sysfs_remove(card->host, card);
+		device_del(&card->dev);
+	}
+
+	put_device(&card->dev);
+}
+
diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h
new file mode 100644
index 0000000..4f35431
--- /dev/null
+++ b/drivers/mmc/core/bus.h
@@ -0,0 +1,22 @@
+/*
+ *  linux/drivers/mmc/core/bus.h
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _MMC_CORE_BUS_H
+#define _MMC_CORE_BUS_H
+
+struct mmc_card *mmc_alloc_card(struct mmc_host *host);
+int mmc_add_card(struct mmc_card *card);
+void mmc_remove_card(struct mmc_card *card);
+
+int mmc_register_bus(void);
+void mmc_unregister_bus(void);
+
+#endif
+
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7385acf..b5d8a6d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -27,7 +27,8 @@
 #include <linux/mmc/sd.h>
 
 #include "core.h"
-#include "sysfs.h"
+#include "bus.h"
+#include "host.h"
 
 #include "mmc_ops.h"
 #include "sd_ops.h"
@@ -35,6 +36,25 @@
 extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
 extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
 
+static struct workqueue_struct *workqueue;
+
+/*
+ * Internal function. Schedule delayed work in the MMC work queue.
+ */
+static int mmc_schedule_delayed_work(struct delayed_work *work,
+				     unsigned long delay)
+{
+	return queue_delayed_work(workqueue, work, delay);
+}
+
+/*
+ * Internal function. Flush all scheduled work from the MMC work queue.
+ */
+static void mmc_flush_scheduled_work(void)
+{
+	flush_workqueue(workqueue);
+}
+
 /**
  *	mmc_request_done - finish processing an MMC request
  *	@host: MMC host which completed request
@@ -369,22 +389,6 @@
 }
 
 /*
- * Allocate a new MMC card
- */
-struct mmc_card *mmc_alloc_card(struct mmc_host *host)
-{
-	struct mmc_card *card;
-
-	card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
-	if (!card)
-		return ERR_PTR(-ENOMEM);
-
-	mmc_init_card(card, host);
-
-	return card;
-}
-
-/*
  * Apply power to the MMC stack.  This is a two-stage process.
  * First, we enable power to the card without the clock running.
  * We then wait a bit for the power to stabilise.  Finally,
@@ -512,7 +516,7 @@
 EXPORT_SYMBOL(mmc_detect_change);
 
 
-static void mmc_rescan(struct work_struct *work)
+void mmc_rescan(struct work_struct *work)
 {
 	struct mmc_host *host =
 		container_of(work, struct mmc_host, detect.work);
@@ -561,69 +565,13 @@
 	}
 }
 
-
-/**
- *	mmc_alloc_host - initialise the per-host structure.
- *	@extra: sizeof private data structure
- *	@dev: pointer to host device model structure
- *
- *	Initialise the per-host structure.
- */
-struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+void mmc_start_host(struct mmc_host *host)
 {
-	struct mmc_host *host;
-
-	host = mmc_alloc_host_sysfs(extra, dev);
-	if (host) {
-		spin_lock_init(&host->lock);
-		init_waitqueue_head(&host->wq);
-		INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-
-		/*
-		 * By default, hosts do not support SGIO or large requests.
-		 * They have to set these according to their abilities.
-		 */
-		host->max_hw_segs = 1;
-		host->max_phys_segs = 1;
-		host->max_seg_size = PAGE_CACHE_SIZE;
-
-		host->max_req_size = PAGE_CACHE_SIZE;
-		host->max_blk_size = 512;
-		host->max_blk_count = PAGE_CACHE_SIZE / 512;
-	}
-
-	return host;
+	mmc_power_off(host);
+	mmc_detect_change(host, 0);
 }
 
-EXPORT_SYMBOL(mmc_alloc_host);
-
-/**
- *	mmc_add_host - initialise host hardware
- *	@host: mmc host
- */
-int mmc_add_host(struct mmc_host *host)
-{
-	int ret;
-
-	ret = mmc_add_host_sysfs(host);
-	if (ret == 0) {
-		mmc_power_off(host);
-		mmc_detect_change(host, 0);
-	}
-
-	return ret;
-}
-
-EXPORT_SYMBOL(mmc_add_host);
-
-/**
- *	mmc_remove_host - remove host hardware
- *	@host: mmc host
- *
- *	Unregister and remove all cards associated with this host,
- *	and power down the MMC bus.
- */
-void mmc_remove_host(struct mmc_host *host)
+void mmc_stop_host(struct mmc_host *host)
 {
 #ifdef CONFIG_MMC_DEBUG
 	unsigned long flags;
@@ -648,24 +596,8 @@
 	BUG_ON(host->card);
 
 	mmc_power_off(host);
-	mmc_remove_host_sysfs(host);
 }
 
-EXPORT_SYMBOL(mmc_remove_host);
-
-/**
- *	mmc_free_host - free the host structure
- *	@host: mmc host
- *
- *	Free the host once all references to it have been dropped.
- */
-void mmc_free_host(struct mmc_host *host)
-{
-	mmc_free_host_sysfs(host);
-}
-
-EXPORT_SYMBOL(mmc_free_host);
-
 #ifdef CONFIG_PM
 
 /**
@@ -726,4 +658,31 @@
 
 #endif
 
+static int __init mmc_init(void)
+{
+	int ret;
+
+	workqueue = create_singlethread_workqueue("kmmcd");
+	if (!workqueue)
+		return -ENOMEM;
+
+	ret = mmc_register_bus();
+	if (ret == 0) {
+		ret = mmc_register_host_class();
+		if (ret)
+			mmc_unregister_bus();
+	}
+	return ret;
+}
+
+static void __exit mmc_exit(void)
+{
+	mmc_unregister_host_class();
+	mmc_unregister_bus();
+	destroy_workqueue(workqueue);
+}
+
+module_init(mmc_init);
+module_exit(mmc_exit);
+
 MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 177264d..ae006b3 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -18,6 +18,8 @@
 struct mmc_bus_ops {
 	void (*remove)(struct mmc_host *);
 	void (*detect)(struct mmc_host *);
+	int (*sysfs_add)(struct mmc_host *, struct mmc_card *card);
+	void (*sysfs_remove)(struct mmc_host *, struct mmc_card *card);
 	void (*suspend)(struct mmc_host *);
 	void (*resume)(struct mmc_host *);
 };
@@ -54,8 +56,6 @@
 u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
 void mmc_set_timing(struct mmc_host *host, unsigned int timing);
 
-struct mmc_card *mmc_alloc_card(struct mmc_host *host);
-
 static inline void mmc_delay(unsigned int ms)
 {
 	if (ms < 1000 / HZ) {
@@ -66,5 +66,9 @@
 	}
 }
 
+void mmc_rescan(struct work_struct *work);
+void mmc_start_host(struct mmc_host *host);
+void mmc_stop_host(struct mmc_host *host);
+
 #endif
 
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
new file mode 100644
index 0000000..1433d95
--- /dev/null
+++ b/drivers/mmc/core/host.c
@@ -0,0 +1,156 @@
+/*
+ *  linux/drivers/mmc/core/host.c
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright (C) 2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  MMC host class device management
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/idr.h>
+#include <linux/pagemap.h>
+
+#include <linux/mmc/host.h>
+
+#include "core.h"
+#include "host.h"
+
+#define cls_dev_to_mmc_host(d)	container_of(d, struct mmc_host, class_dev)
+
+static void mmc_host_classdev_release(struct device *dev)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+	kfree(host);
+}
+
+static struct class mmc_host_class = {
+	.name		= "mmc_host",
+	.dev_release	= mmc_host_classdev_release,
+};
+
+int mmc_register_host_class(void)
+{
+	return class_register(&mmc_host_class);
+}
+
+void mmc_unregister_host_class(void)
+{
+	class_unregister(&mmc_host_class);
+}
+
+static DEFINE_IDR(mmc_host_idr);
+static DEFINE_SPINLOCK(mmc_host_lock);
+
+/**
+ *	mmc_alloc_host - initialise the per-host structure.
+ *	@extra: sizeof private data structure
+ *	@dev: pointer to host device model structure
+ *
+ *	Initialise the per-host structure.
+ */
+struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+{
+	struct mmc_host *host;
+
+	host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+	if (!host)
+		return NULL;
+
+	memset(host, 0, sizeof(struct mmc_host) + extra);
+
+	host->parent = dev;
+	host->class_dev.parent = dev;
+	host->class_dev.class = &mmc_host_class;
+	device_initialize(&host->class_dev);
+
+	spin_lock_init(&host->lock);
+	init_waitqueue_head(&host->wq);
+	INIT_DELAYED_WORK(&host->detect, mmc_rescan);
+
+	/*
+	 * By default, hosts do not support SGIO or large requests.
+	 * They have to set these according to their abilities.
+	 */
+	host->max_hw_segs = 1;
+	host->max_phys_segs = 1;
+	host->max_seg_size = PAGE_CACHE_SIZE;
+
+	host->max_req_size = PAGE_CACHE_SIZE;
+	host->max_blk_size = 512;
+	host->max_blk_count = PAGE_CACHE_SIZE / 512;
+
+	return host;
+}
+
+EXPORT_SYMBOL(mmc_alloc_host);
+
+/**
+ *	mmc_add_host - initialise host hardware
+ *	@host: mmc host
+ */
+int mmc_add_host(struct mmc_host *host)
+{
+	int err;
+
+	if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+		return -ENOMEM;
+
+	spin_lock(&mmc_host_lock);
+	err = idr_get_new(&mmc_host_idr, host, &host->index);
+	spin_unlock(&mmc_host_lock);
+	if (err)
+		return err;
+
+	snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
+		 "mmc%d", host->index);
+
+	err = device_add(&host->class_dev);
+	if (err)
+		return err;
+
+	mmc_start_host(host);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_add_host);
+
+/**
+ *	mmc_remove_host - remove host hardware
+ *	@host: mmc host
+ *
+ *	Unregister and remove all cards associated with this host,
+ *	and power down the MMC bus.
+ */
+void mmc_remove_host(struct mmc_host *host)
+{
+	mmc_stop_host(host);
+
+	device_del(&host->class_dev);
+
+	spin_lock(&mmc_host_lock);
+	idr_remove(&mmc_host_idr, host->index);
+	spin_unlock(&mmc_host_lock);
+}
+
+EXPORT_SYMBOL(mmc_remove_host);
+
+/**
+ *	mmc_free_host - free the host structure
+ *	@host: mmc host
+ *
+ *	Free the host once all references to it have been dropped.
+ */
+void mmc_free_host(struct mmc_host *host)
+{
+	put_device(&host->class_dev);
+}
+
+EXPORT_SYMBOL(mmc_free_host);
+
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
new file mode 100644
index 0000000..c2dc3d2
--- /dev/null
+++ b/drivers/mmc/core/host.h
@@ -0,0 +1,18 @@
+/*
+ *  linux/drivers/mmc/core/host.h
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _MMC_CORE_HOST_H
+#define _MMC_CORE_HOST_H
+
+int mmc_register_host_class(void);
+void mmc_unregister_host_class(void);
+
+#endif
+
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 42cc286..66f85bf 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -18,6 +18,7 @@
 
 #include "core.h"
 #include "sysfs.h"
+#include "bus.h"
 #include "mmc_ops.h"
 
 static const unsigned int tran_exp[] = {
@@ -236,7 +237,7 @@
  * In the case of a resume, "curcard" will contain the card
  * we're trying to reinitialise.
  */
-static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	struct mmc_card *oldcard)
 {
 	struct mmc_card *card;
@@ -413,8 +414,7 @@
 	mmc_release_host(host);
 
 	if (err != MMC_ERR_NONE) {
-		mmc_remove_card(host->card);
-		host->card = NULL;
+		mmc_remove(host);
 
 		mmc_claim_host(host);
 		mmc_detach_bus(host);
@@ -422,6 +422,53 @@
 	}
 }
 
+MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+	card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+	card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
+MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
+
+static struct device_attribute mmc_dev_attrs[] = {
+	MMC_ATTR_RO(cid),
+	MMC_ATTR_RO(csd),
+	MMC_ATTR_RO(date),
+	MMC_ATTR_RO(fwrev),
+	MMC_ATTR_RO(hwrev),
+	MMC_ATTR_RO(manfid),
+	MMC_ATTR_RO(name),
+	MMC_ATTR_RO(oemid),
+	MMC_ATTR_RO(serial),
+	__ATTR_NULL,
+};
+
+/*
+ * Adds sysfs entries as relevant.
+ */
+static int mmc_sysfs_add(struct mmc_host *host, struct mmc_card *card)
+{
+	int ret;
+
+	ret = mmc_add_attrs(card, mmc_dev_attrs);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * Removes the sysfs entries added by mmc_sysfs_add().
+ */
+static void mmc_sysfs_remove(struct mmc_host *host, struct mmc_card *card)
+{
+	mmc_remove_attrs(card, mmc_dev_attrs);
+}
+
 #ifdef CONFIG_MMC_UNSAFE_RESUME
 
 /*
@@ -453,11 +500,9 @@
 
 	mmc_claim_host(host);
 
-	err = mmc_sd_init_card(host, host->ocr, host->card);
+	err = mmc_init_card(host, host->ocr, host->card);
 	if (err != MMC_ERR_NONE) {
-		mmc_remove_card(host->card);
-		host->card = NULL;
-
+		mmc_remove(host);
 		mmc_detach_bus(host);
 	}
 
@@ -474,6 +519,8 @@
 static const struct mmc_bus_ops mmc_ops = {
 	.remove = mmc_remove,
 	.detect = mmc_detect,
+	.sysfs_add = mmc_sysfs_add,
+	.sysfs_remove = mmc_sysfs_remove,
 	.suspend = mmc_suspend,
 	.resume = mmc_resume,
 };
@@ -512,13 +559,13 @@
 	/*
 	 * Detect and init the card.
 	 */
-	err = mmc_sd_init_card(host, host->ocr, NULL);
+	err = mmc_init_card(host, host->ocr, NULL);
 	if (err != MMC_ERR_NONE)
 		goto err;
 
 	mmc_release_host(host);
 
-	err = mmc_register_card(host->card);
+	err = mmc_add_card(host->card);
 	if (err)
 		goto reclaim_host;
 
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 918477c..1240684 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -19,11 +19,10 @@
 
 #include "core.h"
 #include "sysfs.h"
+#include "bus.h"
 #include "mmc_ops.h"
 #include "sd_ops.h"
 
-#include "core.h"
-
 static const unsigned int tran_exp[] = {
 	10000,		100000,		1000000,	10000000,
 	0,		0,		0,		0
@@ -487,8 +486,7 @@
 	mmc_release_host(host);
 
 	if (err != MMC_ERR_NONE) {
-		mmc_remove_card(host->card);
-		host->card = NULL;
+		mmc_sd_remove(host);
 
 		mmc_claim_host(host);
 		mmc_detach_bus(host);
@@ -496,6 +494,55 @@
 	}
 }
 
+MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+	card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+	card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR_FN(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
+MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
+MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
+
+static struct device_attribute mmc_sd_dev_attrs[] = {
+	MMC_ATTR_RO(cid),
+	MMC_ATTR_RO(csd),
+	MMC_ATTR_RO(scr),
+	MMC_ATTR_RO(date),
+	MMC_ATTR_RO(fwrev),
+	MMC_ATTR_RO(hwrev),
+	MMC_ATTR_RO(manfid),
+	MMC_ATTR_RO(name),
+	MMC_ATTR_RO(oemid),
+	MMC_ATTR_RO(serial),
+	__ATTR_NULL,
+};
+
+/*
+ * Adds sysfs entries as relevant.
+ */
+static int mmc_sd_sysfs_add(struct mmc_host *host, struct mmc_card *card)
+{
+	int ret;
+
+	ret = mmc_add_attrs(card, mmc_sd_dev_attrs);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * Removes the sysfs entries added by mmc_sysfs_add().
+ */
+static void mmc_sd_sysfs_remove(struct mmc_host *host, struct mmc_card *card)
+{
+	mmc_remove_attrs(card, mmc_sd_dev_attrs);
+}
+
 #ifdef CONFIG_MMC_UNSAFE_RESUME
 
 /*
@@ -529,9 +576,7 @@
 
 	err = mmc_sd_init_card(host, host->ocr, host->card);
 	if (err != MMC_ERR_NONE) {
-		mmc_remove_card(host->card);
-		host->card = NULL;
-
+		mmc_sd_remove(host);
 		mmc_detach_bus(host);
 	}
 
@@ -548,6 +593,8 @@
 static const struct mmc_bus_ops mmc_sd_ops = {
 	.remove = mmc_sd_remove,
 	.detect = mmc_sd_detect,
+	.sysfs_add = mmc_sd_sysfs_add,
+	.sysfs_remove = mmc_sd_sysfs_remove,
 	.suspend = mmc_sd_suspend,
 	.resume = mmc_sd_resume,
 };
@@ -599,7 +646,7 @@
 
 	mmc_release_host(host);
 
-	err = mmc_register_card(host->card);
+	err = mmc_add_card(host->card);
 	if (err)
 		goto reclaim_host;
 
diff --git a/drivers/mmc/core/sysfs.c b/drivers/mmc/core/sysfs.c
index 843b1fb..00a97e7 100644
--- a/drivers/mmc/core/sysfs.c
+++ b/drivers/mmc/core/sysfs.c
@@ -2,6 +2,7 @@
  *  linux/drivers/mmc/core/sysfs.c
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -9,352 +10,34 @@
  *
  *  MMC sysfs/driver model support.
  */
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/device.h>
-#include <linux/idr.h>
-#include <linux/workqueue.h>
 
 #include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
 
 #include "sysfs.h"
 
-#define dev_to_mmc_card(d)	container_of(d, struct mmc_card, dev)
-#define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
-#define cls_dev_to_mmc_host(d)	container_of(d, struct mmc_host, class_dev)
-
-#define MMC_ATTR(name, fmt, args...)					\
-static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	struct mmc_card *card = dev_to_mmc_card(dev);			\
-	return sprintf(buf, fmt, args);					\
-}
-
-MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
-	card->raw_cid[2], card->raw_cid[3]);
-MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
-	card->raw_csd[2], card->raw_csd[3]);
-MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
-MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
-MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
-MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
-MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
-MMC_ATTR(name, "%s\n", card->cid.prod_name);
-MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
-MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
-
-#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
-
-static struct device_attribute mmc_dev_attrs[] = {
-	MMC_ATTR_RO(cid),
-	MMC_ATTR_RO(csd),
-	MMC_ATTR_RO(date),
-	MMC_ATTR_RO(fwrev),
-	MMC_ATTR_RO(hwrev),
-	MMC_ATTR_RO(manfid),
-	MMC_ATTR_RO(name),
-	MMC_ATTR_RO(oemid),
-	MMC_ATTR_RO(serial),
-	__ATTR_NULL
-};
-
-static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
-
-
-static void mmc_release_card(struct device *dev)
+int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs)
 {
-	struct mmc_card *card = dev_to_mmc_card(dev);
+	int error = 0;
+	int i;
 
-	kfree(card);
-}
-
-/*
- * This currently matches any MMC driver to any MMC card - drivers
- * themselves make the decision whether to drive this card in their
- * probe method.
- */
-static int mmc_bus_match(struct device *dev, struct device_driver *drv)
-{
-	return 1;
-}
-
-static int
-mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
-		int buf_size)
-{
-	struct mmc_card *card = dev_to_mmc_card(dev);
-	char ccc[13];
-	int retval = 0, i = 0, length = 0;
-
-#define add_env(fmt,val) do {					\
-	retval = add_uevent_var(envp, num_envp, &i,		\
-				buf, buf_size, &length,		\
-				fmt, val);			\
-	if (retval)						\
-		return retval;					\
-} while (0);
-
-	for (i = 0; i < 12; i++)
-		ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
-	ccc[12] = '\0';
-
-	add_env("MMC_CCC=%s", ccc);
-	add_env("MMC_MANFID=%06x", card->cid.manfid);
-	add_env("MMC_NAME=%s", mmc_card_name(card));
-	add_env("MMC_OEMID=%04x", card->cid.oemid);
-#undef add_env
-	envp[i] = NULL;
-
-	return 0;
-}
-
-static int mmc_bus_suspend(struct device *dev, pm_message_t state)
-{
-	struct mmc_driver *drv = to_mmc_driver(dev->driver);
-	struct mmc_card *card = dev_to_mmc_card(dev);
-	int ret = 0;
-
-	if (dev->driver && drv->suspend)
-		ret = drv->suspend(card, state);
-	return ret;
-}
-
-static int mmc_bus_resume(struct device *dev)
-{
-	struct mmc_driver *drv = to_mmc_driver(dev->driver);
-	struct mmc_card *card = dev_to_mmc_card(dev);
-	int ret = 0;
-
-	if (dev->driver && drv->resume)
-		ret = drv->resume(card);
-	return ret;
-}
-
-static int mmc_bus_probe(struct device *dev)
-{
-	struct mmc_driver *drv = to_mmc_driver(dev->driver);
-	struct mmc_card *card = dev_to_mmc_card(dev);
-
-	return drv->probe(card);
-}
-
-static int mmc_bus_remove(struct device *dev)
-{
-	struct mmc_driver *drv = to_mmc_driver(dev->driver);
-	struct mmc_card *card = dev_to_mmc_card(dev);
-
-	drv->remove(card);
-
-	return 0;
-}
-
-static struct bus_type mmc_bus_type = {
-	.name		= "mmc",
-	.dev_attrs	= mmc_dev_attrs,
-	.match		= mmc_bus_match,
-	.uevent		= mmc_bus_uevent,
-	.probe		= mmc_bus_probe,
-	.remove		= mmc_bus_remove,
-	.suspend	= mmc_bus_suspend,
-	.resume		= mmc_bus_resume,
-};
-
-/**
- *	mmc_register_driver - register a media driver
- *	@drv: MMC media driver
- */
-int mmc_register_driver(struct mmc_driver *drv)
-{
-	drv->drv.bus = &mmc_bus_type;
-	return driver_register(&drv->drv);
-}
-
-EXPORT_SYMBOL(mmc_register_driver);
-
-/**
- *	mmc_unregister_driver - unregister a media driver
- *	@drv: MMC media driver
- */
-void mmc_unregister_driver(struct mmc_driver *drv)
-{
-	drv->drv.bus = &mmc_bus_type;
-	driver_unregister(&drv->drv);
-}
-
-EXPORT_SYMBOL(mmc_unregister_driver);
-
-
-/*
- * Internal function.  Initialise a MMC card structure.
- */
-void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
-{
-	memset(card, 0, sizeof(struct mmc_card));
-	card->host = host;
-	device_initialize(&card->dev);
-	card->dev.parent = mmc_classdev(host);
-	card->dev.bus = &mmc_bus_type;
-	card->dev.release = mmc_release_card;
-}
-
-/*
- * Internal function.  Register a new MMC card with the driver model.
- */
-int mmc_register_card(struct mmc_card *card)
-{
-	int ret;
-
-	snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
-		 "%s:%04x", mmc_hostname(card->host), card->rca);
-
-	ret = device_add(&card->dev);
-	if (ret == 0) {
-		if (mmc_card_sd(card)) {
-			ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
-			if (ret)
-				device_del(&card->dev);
+	for (i = 0; attr_name(attrs[i]); i++) {
+		error = device_create_file(&card->dev, &attrs[i]);
+		if (error) {
+			while (--i >= 0)
+				device_remove_file(&card->dev, &attrs[i]);
+			break;
 		}
 	}
-	if (ret == 0)
-		mmc_card_set_present(card);
-	return ret;
+
+	return error;
 }
 
-/*
- * Internal function.  Unregister a new MMC card with the
- * driver model, and (eventually) free it.
- */
-void mmc_remove_card(struct mmc_card *card)
+void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs)
 {
-	if (mmc_card_present(card)) {
-		if (mmc_card_sd(card))
-			device_remove_file(&card->dev, &mmc_dev_attr_scr);
+	int i;
 
-		device_del(&card->dev);
-	}
-
-	put_device(&card->dev);
+	for (i = 0; attr_name(attrs[i]); i++)
+		device_remove_file(&card->dev, &attrs[i]);
 }
 
-
-static void mmc_host_classdev_release(struct device *dev)
-{
-	struct mmc_host *host = cls_dev_to_mmc_host(dev);
-	kfree(host);
-}
-
-static struct class mmc_host_class = {
-	.name		= "mmc_host",
-	.dev_release	= mmc_host_classdev_release,
-};
-
-static DEFINE_IDR(mmc_host_idr);
-static DEFINE_SPINLOCK(mmc_host_lock);
-
-/*
- * Internal function. Allocate a new MMC host.
- */
-struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
-{
-	struct mmc_host *host;
-
-	host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
-	if (host) {
-		memset(host, 0, sizeof(struct mmc_host) + extra);
-
-		host->parent = dev;
-		host->class_dev.parent = dev;
-		host->class_dev.class = &mmc_host_class;
-		device_initialize(&host->class_dev);
-	}
-
-	return host;
-}
-
-/*
- * Internal function. Register a new MMC host with the MMC class.
- */
-int mmc_add_host_sysfs(struct mmc_host *host)
-{
-	int err;
-
-	if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
-		return -ENOMEM;
-
-	spin_lock(&mmc_host_lock);
-	err = idr_get_new(&mmc_host_idr, host, &host->index);
-	spin_unlock(&mmc_host_lock);
-	if (err)
-		return err;
-
-	snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
-		 "mmc%d", host->index);
-
-	return device_add(&host->class_dev);
-}
-
-/*
- * Internal function. Unregister a MMC host with the MMC class.
- */
-void mmc_remove_host_sysfs(struct mmc_host *host)
-{
-	device_del(&host->class_dev);
-
-	spin_lock(&mmc_host_lock);
-	idr_remove(&mmc_host_idr, host->index);
-	spin_unlock(&mmc_host_lock);
-}
-
-/*
- * Internal function. Free a MMC host.
- */
-void mmc_free_host_sysfs(struct mmc_host *host)
-{
-	put_device(&host->class_dev);
-}
-
-static struct workqueue_struct *workqueue;
-
-/*
- * Internal function. Schedule delayed work in the MMC work queue.
- */
-int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
-{
-	return queue_delayed_work(workqueue, work, delay);
-}
-
-/*
- * Internal function. Flush all scheduled work from the MMC work queue.
- */
-void mmc_flush_scheduled_work(void)
-{
-	flush_workqueue(workqueue);
-}
-
-static int __init mmc_init(void)
-{
-	int ret;
-
-	workqueue = create_singlethread_workqueue("kmmcd");
-	if (!workqueue)
-		return -ENOMEM;
-
-	ret = bus_register(&mmc_bus_type);
-	if (ret == 0) {
-		ret = class_register(&mmc_host_class);
-		if (ret)
-			bus_unregister(&mmc_bus_type);
-	}
-	return ret;
-}
-
-static void __exit mmc_exit(void)
-{
-	class_unregister(&mmc_host_class);
-	bus_unregister(&mmc_bus_type);
-	destroy_workqueue(workqueue);
-}
-
-module_init(mmc_init);
-module_exit(mmc_exit);
diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h
index 80e29b3..4b8f670 100644
--- a/drivers/mmc/core/sysfs.h
+++ b/drivers/mmc/core/sysfs.h
@@ -11,17 +11,16 @@
 #ifndef _MMC_CORE_SYSFS_H
 #define _MMC_CORE_SYSFS_H
 
-void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
-int mmc_register_card(struct mmc_card *card);
-void mmc_remove_card(struct mmc_card *card);
+#define MMC_ATTR_FN(name, fmt, args...)					\
+static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)	\
+{									\
+	struct mmc_card *card = container_of(dev, struct mmc_card, dev);\
+	return sprintf(buf, fmt, args);					\
+}
 
-struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
-int mmc_add_host_sysfs(struct mmc_host *host);
-void mmc_remove_host_sysfs(struct mmc_host *host);
-void mmc_free_host_sysfs(struct mmc_host *host);
+#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
 
-int mmc_schedule_work(struct work_struct *work);
-int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
-void mmc_flush_scheduled_work(void);
+int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs);
+void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs);
 
 #endif
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index 5b00c19..28c8818 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -78,8 +78,6 @@
 
 #define DRIVER_NAME "at91_mci"
 
-#undef	SUPPORT_4WIRE
-
 #define FL_SENT_COMMAND	(1 << 0)
 #define FL_SENT_STOP	(1 << 1)
 
@@ -131,7 +129,7 @@
 /*
  * Copy from sg to a dma block - used for transfers
  */
-static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
+static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
 {
 	unsigned int len, i, size;
 	unsigned *dmabuf = host->buffer;
@@ -180,7 +178,7 @@
 /*
  * Prepare a dma read
  */
-static void at91mci_pre_dma_read(struct at91mci_host *host)
+static void at91_mci_pre_dma_read(struct at91mci_host *host)
 {
 	int i;
 	struct scatterlist *sg;
@@ -248,7 +246,7 @@
 /*
  * Handle after a dma read
  */
-static void at91mci_post_dma_read(struct at91mci_host *host)
+static void at91_mci_post_dma_read(struct at91mci_host *host)
 {
 	struct mmc_command *cmd;
 	struct mmc_data *data;
@@ -268,8 +266,6 @@
 	}
 
 	while (host->in_use_index < host->transfer_index) {
-		unsigned int *buffer;
-
 		struct scatterlist *sg;
 
 		pr_debug("finishing index %d\n", host->in_use_index);
@@ -280,29 +276,31 @@
 
 		dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
 
-		/* Swap the contents of the buffer */
-		buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
-		pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
-
 		data->bytes_xfered += sg->length;
 
 		if (cpu_is_at91rm9200()) {	/* AT91RM9200 errata */
+			unsigned int *buffer;
 			int index;
 
+			/* Swap the contents of the buffer */
+			buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+			pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
+
 			for (index = 0; index < (sg->length / 4); index++)
 				buffer[index] = swab32(buffer[index]);
+
+			kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
 		}
 
-		kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
 		flush_dcache_page(sg->page);
 	}
 
 	/* Is there another transfer to trigger? */
 	if (host->transfer_index < data->sg_len)
-		at91mci_pre_dma_read(host);
+		at91_mci_pre_dma_read(host);
 	else {
+		at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
 		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
-		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
 	}
 
 	pr_debug("post dma read done\n");
@@ -323,7 +321,6 @@
 
 	/* Now wait for cmd ready */
 	at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
-	at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
 
 	cmd = host->cmd;
 	if (!cmd) return;
@@ -331,18 +328,53 @@
 	data = cmd->data;
 	if (!data) return;
 
+	if (cmd->data->flags & MMC_DATA_MULTI) {
+		pr_debug("multiple write : wait for BLKE...\n");
+		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
+	} else
+		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
+
 	data->bytes_xfered = host->total_length;
 }
 
+/*Handle after command sent ready*/
+static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
+{
+	if (!host->cmd)
+		return 1;
+	else if (!host->cmd->data) {
+		if (host->flags & FL_SENT_STOP) {
+			/*After multi block write, we must wait for NOTBUSY*/
+			at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
+		} else return 1;
+	} else if (host->cmd->data->flags & MMC_DATA_WRITE) {
+		/*After sendding multi-block-write command, start DMA transfer*/
+		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE);
+		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
+		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
+	}
+
+	/* command not completed, have to wait */
+	return 0;
+}
+
+
 /*
  * Enable the controller
  */
 static void at91_mci_enable(struct at91mci_host *host)
 {
+	unsigned int mr;
+
 	at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
 	at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
 	at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
-	at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a);
+	mr = AT91_MCI_PDCMODE | 0x34a;
+
+	if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+		mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
+
+	at91_mci_write(host, AT91_MCI_MR, mr);
 
 	/* use Slot A or B (only one at same time) */
 	at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
@@ -358,9 +390,8 @@
 
 /*
  * Send a command
- * return the interrupts to enable
  */
-static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
+static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
 {
 	unsigned int cmdr, mr;
 	unsigned int block_length;
@@ -371,8 +402,7 @@
 
 	host->cmd = cmd;
 
-	/* Not sure if this is needed */
-#if 0
+	/* Needed for leaving busy state before CMD1 */
 	if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
 		pr_debug("Clearing timeout\n");
 		at91_mci_write(host, AT91_MCI_ARGR, 0);
@@ -382,7 +412,7 @@
 			pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
 		}
 	}
-#endif
+
 	cmdr = cmd->opcode;
 
 	if (mmc_resp_type(cmd) == MMC_RSP_NONE)
@@ -439,50 +469,48 @@
 		at91_mci_write(host, ATMEL_PDC_TCR, 0);
 		at91_mci_write(host, ATMEL_PDC_TNPR, 0);
 		at91_mci_write(host, ATMEL_PDC_TNCR, 0);
+		ier = AT91_MCI_CMDRDY;
+	} else {
+		/* zero block length and PDC mode */
+		mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
+		at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
 
-		at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
-		at91_mci_write(host, AT91_MCI_CMDR, cmdr);
-		return AT91_MCI_CMDRDY;
-	}
+		/*
+		 * Disable the PDC controller
+		 */
+		at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
 
-	mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;	/* zero block length and PDC mode */
-	at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
+		if (cmdr & AT91_MCI_TRCMD_START) {
+			data->bytes_xfered = 0;
+			host->transfer_index = 0;
+			host->in_use_index = 0;
+			if (cmdr & AT91_MCI_TRDIR) {
+				/*
+				 * Handle a read
+				 */
+				host->buffer = NULL;
+				host->total_length = 0;
 
-	/*
-	 * Disable the PDC controller
-	 */
-	at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
+				at91_mci_pre_dma_read(host);
+				ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
+			}
+			else {
+				/*
+				 * Handle a write
+				 */
+				host->total_length = block_length * blocks;
+				host->buffer = dma_alloc_coherent(NULL,
+						host->total_length,
+						&host->physical_address, GFP_KERNEL);
 
-	if (cmdr & AT91_MCI_TRCMD_START) {
-		data->bytes_xfered = 0;
-		host->transfer_index = 0;
-		host->in_use_index = 0;
-		if (cmdr & AT91_MCI_TRDIR) {
-			/*
-			 * Handle a read
-			 */
-			host->buffer = NULL;
-			host->total_length = 0;
+				at91_mci_sg_to_dma(host, data);
 
-			at91mci_pre_dma_read(host);
-			ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
-		}
-		else {
-			/*
-			 * Handle a write
-			 */
-			host->total_length = block_length * blocks;
-			host->buffer = dma_alloc_coherent(NULL,
-						  host->total_length,
-						  &host->physical_address, GFP_KERNEL);
+				pr_debug("Transmitting %d bytes\n", host->total_length);
 
-			at91mci_sg_to_dma(host, data);
-
-			pr_debug("Transmitting %d bytes\n", host->total_length);
-
-			at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
-			at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
-			ier = AT91_MCI_TXBUFE;
+				at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
+				at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
+				ier = AT91_MCI_CMDRDY;
+			}
 		}
 	}
 
@@ -497,39 +525,24 @@
 	if (cmdr & AT91_MCI_TRCMD_START) {
 		if (cmdr & AT91_MCI_TRDIR)
 			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
-		else
-			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
 	}
-	return ier;
-}
 
-/*
- * Wait for a command to complete
- */
-static void at91mci_process_command(struct at91mci_host *host, struct mmc_command *cmd)
-{
-	unsigned int ier;
-
-	ier = at91_mci_send_command(host, cmd);
-
-	pr_debug("setting ier to %08X\n", ier);
-
-	/* Stop on errors or the required value */
+	/* Enable selected interrupts */
 	at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
 }
 
 /*
  * Process the next step in the request
  */
-static void at91mci_process_next(struct at91mci_host *host)
+static void at91_mci_process_next(struct at91mci_host *host)
 {
 	if (!(host->flags & FL_SENT_COMMAND)) {
 		host->flags |= FL_SENT_COMMAND;
-		at91mci_process_command(host, host->request->cmd);
+		at91_mci_send_command(host, host->request->cmd);
 	}
 	else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
 		host->flags |= FL_SENT_STOP;
-		at91mci_process_command(host, host->request->stop);
+		at91_mci_send_command(host, host->request->stop);
 	}
 	else
 		mmc_request_done(host->mmc, host->request);
@@ -538,7 +551,7 @@
 /*
  * Handle a command that has been completed
  */
-static void at91mci_completed_command(struct at91mci_host *host)
+static void at91_mci_completed_command(struct at91mci_host *host)
 {
 	struct mmc_command *cmd = host->cmd;
 	unsigned int status;
@@ -583,7 +596,7 @@
 	else
 		cmd->error = MMC_ERR_NONE;
 
-	at91mci_process_next(host);
+	at91_mci_process_next(host);
 }
 
 /*
@@ -595,7 +608,7 @@
 	host->request = mrq;
 	host->flags = 0;
 
-	at91mci_process_next(host);
+	at91_mci_process_next(host);
 }
 
 /*
@@ -698,29 +711,33 @@
 			at91_mci_handle_transmitted(host);
 		}
 
+		if (int_status & AT91_MCI_ENDRX) {
+			pr_debug("ENDRX\n");
+			at91_mci_post_dma_read(host);
+		}
+
 		if (int_status & AT91_MCI_RXBUFF) {
 			pr_debug("RX buffer full\n");
-			at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
+			at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
+			at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
+			completed = 1;
 		}
 
 		if (int_status & AT91_MCI_ENDTX)
 			pr_debug("Transmit has ended\n");
 
-		if (int_status & AT91_MCI_ENDRX) {
-			pr_debug("Receive has ended\n");
-			at91mci_post_dma_read(host);
-		}
-
 		if (int_status & AT91_MCI_NOTBUSY) {
 			pr_debug("Card is ready\n");
-			at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
+			completed = 1;
 		}
 
 		if (int_status & AT91_MCI_DTIP)
 			pr_debug("Data transfer in progress\n");
 
-		if (int_status & AT91_MCI_BLKE)
+		if (int_status & AT91_MCI_BLKE) {
 			pr_debug("Block transfer has ended\n");
+			completed = 1;
+		}
 
 		if (int_status & AT91_MCI_TXRDY)
 			pr_debug("Ready to transmit\n");
@@ -730,14 +747,14 @@
 
 		if (int_status & AT91_MCI_CMDRDY) {
 			pr_debug("Command ready\n");
-			completed = 1;
+			completed = at91_mci_handle_cmdrdy(host);
 		}
 	}
 
 	if (completed) {
 		pr_debug("Completed command\n");
 		at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
-		at91mci_completed_command(host);
+		at91_mci_completed_command(host);
 	} else
 		at91_mci_write(host, AT91_MCI_IDR, int_status);
 
@@ -830,11 +847,11 @@
 	host->bus_mode = 0;
 	host->board = pdev->dev.platform_data;
 	if (host->board->wire4) {
-#ifdef SUPPORT_4WIRE
-		mmc->caps |= MMC_CAP_4_BIT_DATA;
-#else
-		printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
-#endif
+		if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+			mmc->caps |= MMC_CAP_4_BIT_DATA;
+		else
+			printk("AT91 MMC: 4 wire bus mode not supported"
+				" - using 1 wire\n");
 	}
 
 	/*
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a359efd..10d15c3 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -70,6 +70,14 @@
 		.driver_data	= SDHCI_QUIRK_SINGLE_POWER_WRITE,
 	},
 
+	{
+		.vendor		= PCI_VENDOR_ID_ENE,
+		.device		= PCI_DEVICE_ID_ENE_CB712_SD_2,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= SDHCI_QUIRK_SINGLE_POWER_WRITE,
+	},
+
 	{	/* Generic SD host controller */
 		PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
 	},
@@ -1022,7 +1030,7 @@
 		writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS);
 	}
 
-	intmask &= SDHCI_INT_BUS_POWER;
+	intmask &= ~SDHCI_INT_BUS_POWER;
 
 	if (intmask) {
 		printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
index 78872c3..b96ac8e 100644
--- a/drivers/mtd/devices/docprobe.c
+++ b/drivers/mtd/devices/docprobe.c
@@ -84,7 +84,7 @@
 #elif defined(CONFIG_MOMENCO_OCELOT)
 	0x2f000000,
         0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
         0xff000000,
 ##else
 #warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index b665e4a..f88ebc5 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -258,12 +258,6 @@
 	help
 	  Support for the flash chip on Tsunami TIG bus.
 
-config MTD_LASAT
-	tristate "LASAT flash device"
-	depends on LASAT && MTD_CFI
-	help
-	  Support for the flash chips on the Lasat 100 and 200 boards.
-
 config MTD_NETtel
 	tristate "CFI flash device on SnapGear/SecureEdge"
 	depends on X86 && MTD_PARTITIONS && MTD_JEDECPROBE
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 3acbb5d..970b189 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -47,7 +47,6 @@
 obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
 obj-$(CONFIG_MTD_PCI)		+= pci.o
 obj-$(CONFIG_MTD_ALCHEMY)       += alchemy-flash.o
-obj-$(CONFIG_MTD_LASAT)		+= lasat.o
 obj-$(CONFIG_MTD_AUTCPU12)	+= autcpu12-nvram.o
 obj-$(CONFIG_MTD_EDB7312)	+= edb7312.o
 obj-$(CONFIG_MTD_IMPA7)		+= impa7.o
diff --git a/drivers/mtd/maps/lasat.c b/drivers/mtd/maps/lasat.c
deleted file mode 100644
index e343763..0000000
--- a/drivers/mtd/maps/lasat.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Flash device on Lasat 100 and 200 boards
- *
- * (C) 2002 Brian Murphy <brian@murphy.dk>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * $Id: lasat.c,v 1.9 2004/11/04 13:24:15 gleixner Exp $
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/lasat/lasat.h>
-
-static struct mtd_info *lasat_mtd;
-
-static struct mtd_partition partition_info[LASAT_MTD_LAST];
-static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"};
-
-static void lasat_set_vpp(struct map_info *map, int vpp)
-{
-	if (vpp)
-	    *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
-	else
-	    *lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit);
-}
-
-static struct map_info lasat_map = {
-	.name = "LASAT flash",
-	.bankwidth = 4,
-	.set_vpp = lasat_set_vpp
-};
-
-static int __init init_lasat(void)
-{
-	int i;
-	/* since we use AMD chips and set_vpp is not implimented
-	 * for these (yet) we still have to permanently enable flash write */
-	printk(KERN_NOTICE "Unprotecting flash\n");
-	ENABLE_VPP((&lasat_map));
-
-	lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER);
-	lasat_map.virt = ioremap_nocache(
-		        lasat_map.phys, lasat_board_info.li_flash_size);
-	lasat_map.size = lasat_board_info.li_flash_size;
-
-	simple_map_init(&lasat_map);
-
-	for (i=0; i < LASAT_MTD_LAST; i++)
-		partition_info[i].name = lasat_mtd_partnames[i];
-
-	lasat_mtd = do_map_probe("cfi_probe", &lasat_map);
-
-	if (!lasat_mtd)
-	    lasat_mtd = do_map_probe("jedec_probe", &lasat_map);
-
-	if (lasat_mtd) {
-		u32 size, offset = 0;
-
-		lasat_mtd->owner = THIS_MODULE;
-
-		for (i=0; i < LASAT_MTD_LAST; i++) {
-			size = lasat_flash_partition_size(i);
-			partition_info[i].size = size;
-			partition_info[i].offset = offset;
-			offset += size;
-		}
-
-		add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST );
-		return 0;
-	}
-
-	iounmap(lasat_map.virt);
-	return -ENXIO;
-}
-
-static void __exit cleanup_lasat(void)
-{
-	if (lasat_mtd) {
-		del_mtd_partitions(lasat_mtd);
-		map_destroy(lasat_mtd);
-	}
-	if (lasat_map.virt) {
-		iounmap(lasat_map.virt);
-		lasat_map.virt = 0;
-	}
-}
-
-module_init(init_lasat);
-module_exit(cleanup_lasat);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Brian Murphy <brian@murphy.dk>");
-MODULE_DESCRIPTION("Lasat Safepipe/Masquerade MTD map driver");
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 595208f..17c8680 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -59,7 +59,7 @@
 #elif defined(CONFIG_MOMENCO_OCELOT)
 	0x2f000000,
 	0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
 	0xff000000,
 #else
 #warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index da1a22c..ab18343 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -990,7 +990,7 @@
 				if (skb != NULL) {
 					skb_reserve(skb, 2);	/* 16 byte alignment */
 					skb_put(skb,totlen);
-					eth_copy_and_sum(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen,0);
+					skb_copy_to_linear_data(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen);
 					skb->protocol = eth_type_trans(skb, dev);
 					netif_rx(skb);
 					dev->last_rx = jiffies;
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index f26ca33..6deb20f 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -324,7 +324,7 @@
 	{"3c980C Python-T",
 	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
 	{"3cSOHO100-TX Hurricane",
-	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
 	{"3c555 Laptop Hurricane",
 	 PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT|HAS_HWCKSM, 128, },
 	{"3c556 Laptop Tornado",
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index 0877fc3..e89ace1 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -333,9 +333,9 @@
 
                         skb_reserve (skb, 2);           /* 16 byte align */
                         skb_put (skb, len);             /* make room */
-                        eth_copy_and_sum(skb,
+                        skb_copy_to_linear_data(skb,
                                          (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
-                                         len, 0);
+                                         len);
                         skb->protocol = eth_type_trans (skb, dev);
 			netif_rx (skb);
 			dev->last_rx = jiffies;
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index a804965..58bbc3e 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -107,11 +107,6 @@
 
 #define PFX			DRV_NAME ": "
 
-#ifndef TRUE
-#define FALSE 0
-#define TRUE (!FALSE)
-#endif
-
 #define CP_DEF_MSG_ENABLE	(NETIF_MSG_DRV		| \
 				 NETIF_MSG_PROBE 	| \
 				 NETIF_MSG_LINK)
@@ -661,7 +656,7 @@
 	if (status & (TxOK | TxErr | TxEmpty | SWInt))
 		cp_tx(cp);
 	if (status & LinkChg)
-		mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+		mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
 
 	spin_unlock(&cp->lock);
 
@@ -1188,7 +1183,7 @@
 		goto err_out_hw;
 
 	netif_carrier_off(dev);
-	mii_check_media(&cp->mii_if, netif_msg_link(cp), TRUE);
+	mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
 	netif_start_queue(dev);
 
 	return 0;
@@ -2050,7 +2045,7 @@
 
 	spin_lock_irqsave (&cp->lock, flags);
 
-	mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+	mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
 
 	spin_unlock_irqrestore (&cp->lock, flags);
 
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index a844b1f..21a6ccb 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -2017,7 +2017,7 @@
 #if RX_BUF_IDX == 3
 			wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
 #else
-			eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+			skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size);
 #endif
 			skb_put (skb, pkt_size);
 
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 414de5b..04ddec0 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -73,6 +73,9 @@
 	u32 *reg_offset;		/* Register mapping table */
 	spinlock_t page_lock;		/* Page register locks */
 	unsigned long priv;		/* Private field to store bus IDs etc. */
+#ifdef AX88796_PLATFORM
+	unsigned char rxcr_base;	/* default value for RXCR */
+#endif
 };
 
 /* The maximum number of 8390 interrupt service routines called per IRQ. */
@@ -86,11 +89,19 @@
 /* Some generic ethernet register configurations. */
 #define E8390_TX_IRQ_MASK	0xa	/* For register EN0_ISR */
 #define E8390_RX_IRQ_MASK	0x5
+
+#ifdef AX88796_PLATFORM
+#define E8390_RXCONFIG		(ei_status.rxcr_base | 0x04)
+#define E8390_RXOFF		(ei_status.rxcr_base | 0x20)
+#else
 #define E8390_RXCONFIG		0x4	/* EN0_RXCR: broadcasts, no multicast,errors */
 #define E8390_RXOFF		0x20	/* EN0_RXCR: Accept no packets */
+#endif
+
 #define E8390_TXCONFIG		0x00	/* EN0_TXCR: Normal transmit mode */
 #define E8390_TXOFF		0x02	/* EN0_TXCR: Transmitter off */
 
+
 /*  Register accessed at EN_CMD, the 8390 base addr.  */
 #define E8390_STOP	0x01	/* Stop and reset the chip */
 #define E8390_START	0x02	/* Start the chip, clear reset */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b49375a..d4e39ff 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3,10 +3,7 @@
 # Network device configuration
 #
 
-menu "Network device support"
-	depends on NET
-
-config NETDEVICES
+menuconfig NETDEVICES
 	default y if UML
 	bool "Network device support"
 	---help---
@@ -28,6 +25,14 @@
 # that for each of the symbols.
 if NETDEVICES
 
+config NETDEVICES_MULTIQUEUE
+	bool "Netdevice multiple hardware queue support"
+	---help---
+	  Say Y here if you want to allow the network stack to use multiple
+	  hardware TX queues on an ethernet device.
+
+	  Most people will say N here.
+
 config IFB
 	tristate "Intermediate Functional Block support"
 	depends on NET_CLS_ACT
@@ -151,11 +156,9 @@
 #	Ethernet
 #
 
-menu "Ethernet (10 or 100Mbit)"
-	depends on !UML
-
-config NET_ETHERNET
+menuconfig NET_ETHERNET
 	bool "Ethernet (10 or 100Mbit)"
+	depends on !UML
 	---help---
 	  Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
 	  type of Local Area Network (LAN) in universities and companies.
@@ -180,9 +183,10 @@
 	  kernel: saying N will just cause the configurator to skip all
 	  the questions about Ethernet network cards. If unsure, say N.
 
+if NET_ETHERNET
+
 config MII
 	tristate "Generic Media Independent Interface device support"
-	depends on NET_ETHERNET
 	help
 	  Most ethernet controllers have MII transceiver either as an external
 	  or internal device.  It is safe to say Y or M here even if your
@@ -190,7 +194,7 @@
 
 config MACB
 	tristate "Atmel MACB support"
-	depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263)
+	depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263
 	select MII
 	help
 	  The Atmel MACB ethernet interface is found on many AT32 and AT91
@@ -201,9 +205,18 @@
 
 source "drivers/net/arm/Kconfig"
 
+config AX88796
+	tristate "ASIX AX88796 NE2000 clone support"
+	depends on ARM || MIPS
+	select CRC32
+	select MII
+	help
+	  AX88796 driver, using platform bus to provide
+	  chip detection and resources
+
 config MACE
 	tristate "MACE (Power Mac ethernet) support"
-	depends on NET_ETHERNET && PPC_PMAC && PPC32
+	depends on PPC_PMAC && PPC32
 	select CRC32
 	help
 	  Power Macintoshes and clones with Ethernet built-in on the
@@ -226,7 +239,7 @@
 
 config BMAC
 	tristate "BMAC (G3 ethernet) support"
-	depends on NET_ETHERNET && PPC_PMAC && PPC32
+	depends on PPC_PMAC && PPC32
 	select CRC32
 	help
 	  Say Y for support of BMAC Ethernet interfaces. These are used on G3
@@ -237,7 +250,7 @@
 
 config ARIADNE
 	tristate "Ariadne support"
-	depends on NET_ETHERNET && ZORRO
+	depends on ZORRO
 	help
 	  If you have a Village Tronic Ariadne Ethernet adapter, say Y.
 	  Otherwise, say N.
@@ -247,7 +260,7 @@
 
 config A2065
 	tristate "A2065 support"
-	depends on NET_ETHERNET && ZORRO
+	depends on ZORRO
 	select CRC32
 	help
 	  If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
@@ -258,7 +271,7 @@
 
 config HYDRA
 	tristate "Hydra support"
-	depends on NET_ETHERNET && ZORRO
+	depends on ZORRO
 	select CRC32
 	help
 	  If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
@@ -268,7 +281,7 @@
 
 config ZORRO8390
 	tristate "Zorro NS8390-based Ethernet support"
-	depends on NET_ETHERNET && ZORRO
+	depends on ZORRO
 	select CRC32
 	help
 	  This driver is for Zorro Ethernet cards using an NS8390-compatible
@@ -281,7 +294,7 @@
 
 config APNE
 	tristate "PCMCIA NE2000 support"
-	depends on NET_ETHERNET && AMIGA_PCMCIA
+	depends on AMIGA_PCMCIA
 	select CRC32
 	help
 	  If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
@@ -292,7 +305,7 @@
 
 config APOLLO_ELPLUS
 	tristate "Apollo 3c505 support"
-	depends on NET_ETHERNET && APOLLO
+	depends on APOLLO
 	help
 	  Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card.
 	  If you don't have one made for Apollos, you can use one from a PC,
@@ -301,7 +314,7 @@
 
 config MAC8390
 	bool "Macintosh NS 8390 based ethernet cards"
-	depends on NET_ETHERNET && MAC
+	depends on MAC
 	select CRC32
 	help
 	  If you want to include a driver to support Nubus or LC-PDS
@@ -311,7 +324,7 @@
 
 config MAC89x0
 	tristate "Macintosh CS89x0 based ethernet cards"
-	depends on NET_ETHERNET && MAC
+	depends on MAC
 	---help---
 	  Support for CS89x0 chipset based Ethernet cards.  If you have a
 	  Nubus or LC-PDS network (Ethernet) card of this type, say Y and
@@ -324,7 +337,7 @@
 
 config MACSONIC
 	tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
-	depends on NET_ETHERNET && MAC
+	depends on MAC
 	---help---
 	  Support for NatSemi SONIC based Ethernet devices.  This includes
 	  the onboard Ethernet in many Quadras as well as some LC-PDS,
@@ -338,7 +351,7 @@
 
 config MACMACE
 	bool "Macintosh (AV) onboard MACE ethernet"
-	depends on NET_ETHERNET && MAC
+	depends on MAC
 	select CRC32
 	help
 	  Support for the onboard AMD 79C940 MACE Ethernet controller used in
@@ -348,7 +361,7 @@
 
 config MVME147_NET
 	tristate "MVME147 (Lance) Ethernet support"
-	depends on NET_ETHERNET && MVME147
+	depends on MVME147
 	select CRC32
 	help
 	  Support for the on-board Ethernet interface on the Motorola MVME147
@@ -358,7 +371,7 @@
 
 config MVME16x_NET
 	tristate "MVME16x Ethernet support"
-	depends on NET_ETHERNET && MVME16x
+	depends on MVME16x
 	help
 	  This is the driver for the Ethernet interface on the Motorola
 	  MVME162, 166, 167, 172 and 177 boards.  Say Y here to include the
@@ -367,7 +380,7 @@
 
 config BVME6000_NET
 	tristate "BVME6000 Ethernet support"
-	depends on NET_ETHERNET && BVME6000
+	depends on BVME6000
 	help
 	  This is the driver for the Ethernet interface on BVME4000 and
 	  BVME6000 VME boards.  Say Y here to include the driver for this chip
@@ -376,7 +389,7 @@
 
 config ATARILANCE
 	tristate "Atari Lance support"
-	depends on NET_ETHERNET && ATARI
+	depends on ATARI
 	help
 	  Say Y to include support for several Atari Ethernet adapters based
 	  on the AMD Lance chipset: RieblCard (with or without battery), or
@@ -384,7 +397,7 @@
 
 config ATARI_BIONET
 	tristate "BioNet-100 support"
-	depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
+	depends on ATARI && ATARI_ACSI && BROKEN
 	help
 	  Say Y to include support for BioData's BioNet-100 Ethernet adapter
 	  for the ACSI port. The driver works (has to work...) with a polled
@@ -392,7 +405,7 @@
 
 config ATARI_PAMSNET
 	tristate "PAMsNet support"
-	depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
+	depends on ATARI && ATARI_ACSI && BROKEN
 	help
 	  Say Y to include support for the PAMsNet Ethernet adapter for the
 	  ACSI port ("ACSI node"). The driver works (has to work...) with a
@@ -400,7 +413,7 @@
 
 config SUN3LANCE
 	tristate "Sun3/Sun3x on-board LANCE support"
-	depends on NET_ETHERNET && (SUN3 || SUN3X)
+	depends on SUN3 || SUN3X
 	help
 	  Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
 	  featured an AMD Lance 10Mbit Ethernet controller on board; say Y
@@ -413,7 +426,7 @@
 
 config SUN3_82586
 	bool "Sun3 on-board Intel 82586 support"
-	depends on NET_ETHERNET && SUN3
+	depends on SUN3
 	help
 	  This driver enables support for the on-board Intel 82586 based
 	  Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards.  Note
@@ -422,7 +435,7 @@
 
 config HPLANCE
 	bool "HP on-board LANCE support"
-	depends on NET_ETHERNET && DIO
+	depends on DIO
 	select CRC32
 	help
 	  If you want to use the builtin "LANCE" Ethernet controller on an
@@ -430,21 +443,28 @@
 
 config LASI_82596
 	tristate "Lasi ethernet"
-	depends on NET_ETHERNET && GSC
+	depends on GSC
 	help
 	  Say Y here to support the builtin Intel 82596 ethernet controller
 	  found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
 
+config SNI_82596
+	tristate "SNI RM ethernet"
+	depends on NET_ETHERNET && SNI_RM
+	help
+	  Say Y here to support the on-board Intel 82596 ethernet controller
+	  built into SNI RM machines.
+
 config MIPS_JAZZ_SONIC
 	tristate "MIPS JAZZ onboard SONIC Ethernet support"
-	depends on NET_ETHERNET && MACH_JAZZ
+	depends on MACH_JAZZ
 	help
 	  This is the driver for the onboard card of MIPS Magnum 4000,
 	  Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
 
 config MIPS_AU1X00_ENET
 	bool "MIPS AU1000 Ethernet support"
-	depends on NET_ETHERNET && SOC_AU1X00
+	depends on SOC_AU1X00
 	select PHYLIB
 	select CRC32
 	help
@@ -453,11 +473,11 @@
 
 config NET_SB1250_MAC
 	tristate "SB1250 Ethernet support"
-	depends on NET_ETHERNET && SIBYTE_SB1xxx_SOC
+	depends on SIBYTE_SB1xxx_SOC
 
 config SGI_IOC3_ETH
 	bool "SGI IOC3 Ethernet"
-	depends on NET_ETHERNET && PCI && SGI_IP27
+	depends on PCI && SGI_IP27
 	select CRC32
 	select MII
 	help
@@ -487,7 +507,7 @@
 
 config MIPS_SIM_NET
 	tristate "MIPS simulator Network device"
-	depends on NET_ETHERNET && MIPS_SIM
+	depends on MIPS_SIM
 	help
 	  The MIPSNET device is a simple Ethernet network device which is
 	  emulated by the MIPS Simulator.
@@ -495,11 +515,11 @@
 
 config SGI_O2MACE_ETH
 	tristate "SGI O2 MACE Fast Ethernet support"
-	depends on NET_ETHERNET && SGI_IP32=y
+	depends on SGI_IP32=y
 
 config STNIC
 	tristate "National DP83902AV  support"
-	depends on NET_ETHERNET && SUPERH
+	depends on SUPERH
 	select CRC32
 	help
 	  Support for cards based on the National Semiconductor DP83902AV
@@ -511,7 +531,7 @@
 
 config SUNLANCE
 	tristate "Sun LANCE support"
-	depends on NET_ETHERNET && SBUS
+	depends on SBUS
 	select CRC32
 	help
 	  This driver supports the "le" interface present on all 32-bit Sparc
@@ -524,7 +544,7 @@
 
 config HAPPYMEAL
 	tristate "Sun Happy Meal 10/100baseT support"
-	depends on NET_ETHERNET && (SBUS || PCI)
+	depends on SBUS || PCI
 	select CRC32
 	help
 	  This driver supports the "hme" interface present on most Ultra
@@ -537,7 +557,7 @@
 
 config SUNBMAC
 	tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)"
-	depends on NET_ETHERNET && SBUS && EXPERIMENTAL
+	depends on SBUS && EXPERIMENTAL
 	select CRC32
 	help
 	  This driver supports the "be" interface available as an Sbus option.
@@ -548,7 +568,7 @@
 
 config SUNQE
 	tristate "Sun QuadEthernet support"
-	depends on NET_ETHERNET && SBUS
+	depends on SBUS
 	select CRC32
 	help
 	  This driver supports the "qe" 10baseT Ethernet device, available as
@@ -560,7 +580,7 @@
 
 config SUNGEM
 	tristate "Sun GEM support"
-	depends on NET_ETHERNET && PCI
+	depends on PCI
 	select CRC32
 	help
 	  Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0.  See also
@@ -568,7 +588,7 @@
 
 config CASSINI
 	tristate "Sun Cassini support"
-	depends on NET_ETHERNET && PCI
+	depends on PCI
 	select CRC32
 	help
 	  Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
@@ -576,7 +596,7 @@
 
 config NET_VENDOR_3COM
 	bool "3COM cards"
-	depends on NET_ETHERNET && (ISA || EISA || MCA || PCI)
+	depends on ISA || EISA || MCA || PCI
 	help
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -736,7 +756,7 @@
 
 config LANCE
 	tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
-	depends on NET_ETHERNET && ISA && ISA_DMA_API
+	depends on ISA && ISA_DMA_API
 	help
 	  If you have a network (Ethernet) card of this type, say Y and read
 	  the Ethernet-HOWTO, available from
@@ -748,7 +768,7 @@
 
 config NET_VENDOR_SMC
 	bool "Western Digital/SMC cards"
-	depends on NET_ETHERNET && (ISA || MCA || EISA || MAC)
+	depends on ISA || MCA || EISA || MAC
 	help
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -818,24 +838,6 @@
 	  <file:Documentation/networking/net-modules.txt>. The module
 	  will be called smc-ultra32.
 
-config SMC91X
-	tristate "SMC 91C9x/91C1xxx support"
-	select CRC32
-	select MII
-	depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN)
-	help
-	  This is a driver for SMC's 91x series of Ethernet chipsets,
-	  including the SMC91C94 and the SMC91C111. Say Y if you want it
-	  compiled into the kernel, and read the file
-	  <file:Documentation/networking/smc9.txt>  and the Ethernet-HOWTO,
-	  available from  <http://www.linuxdoc.org/docs.html#howto>.
-
-	  This driver is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called smc91x.  If you want to compile it as a
-	  module, say M here and read <file:Documentation/kbuild/modules.txt>
-	  as well as <file:Documentation/networking/net-modules.txt>.
-
 config SMC9194
 	tristate "SMC 9194 support"
 	depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
@@ -852,10 +854,28 @@
 	  <file:Documentation/networking/net-modules.txt>. The module
 	  will be called smc9194.
 
+config SMC91X
+	tristate "SMC 91C9x/91C1xxx support"
+	select CRC32
+	select MII
+	depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN
+	help
+	  This is a driver for SMC's 91x series of Ethernet chipsets,
+	  including the SMC91C94 and the SMC91C111. Say Y if you want it
+	  compiled into the kernel, and read the file
+	  <file:Documentation/networking/smc9.txt>  and the Ethernet-HOWTO,
+	  available from  <http://www.linuxdoc.org/docs.html#howto>.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called smc91x.  If you want to compile it as a
+	  module, say M here and read <file:Documentation/kbuild/modules.txt>
+	  as well as <file:Documentation/networking/net-modules.txt>.
+
 config NET_NETX
 	tristate "NetX Ethernet support"
 	select MII
-	depends on NET_ETHERNET && ARCH_NETX
+	depends on ARCH_NETX
 	help
 	  This is support for the Hilscher netX builtin Ethernet ports
 
@@ -865,7 +885,7 @@
 
 config DM9000
 	tristate "DM9000 support"
-	depends on (ARM || MIPS) && NET_ETHERNET
+	depends on ARM || MIPS
 	select CRC32
 	select MII
 	---help---
@@ -879,7 +899,7 @@
 	tristate "SMSC LAN911[5678] support"
 	select CRC32
 	select MII
-	depends on NET_ETHERNET && ARCH_PXA
+	depends on ARCH_PXA
 	help
 	  This is a driver for SMSC's LAN911x series of Ethernet chipsets
 	  including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@ -893,7 +913,7 @@
 
 config NET_VENDOR_RACAL
 	bool "Racal-Interlan (Micom) NI cards"
-	depends on NET_ETHERNET && ISA
+	depends on ISA
 	help
 	  If you have a network (Ethernet) card belonging to this class, such
 	  as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
@@ -945,7 +965,7 @@
 
 config AT1700
 	tristate "AT1700/1720 support (EXPERIMENTAL)"
-	depends on NET_ETHERNET && (ISA || MCA_LEGACY) && EXPERIMENTAL
+	depends on (ISA || MCA_LEGACY) && EXPERIMENTAL
 	select CRC32
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -958,7 +978,7 @@
 
 config DEPCA
 	tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
-	depends on NET_ETHERNET && (ISA || EISA || MCA)
+	depends on ISA || EISA || MCA
 	select CRC32
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -972,7 +992,7 @@
 
 config HP100
 	tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
-	depends on NET_ETHERNET && (ISA || EISA || PCI)
+	depends on ISA || EISA || PCI
 	help
 	  If you have a network (Ethernet) card of this type, say Y and read
 	  the Ethernet-HOWTO, available from
@@ -984,7 +1004,7 @@
 
 config NET_ISA
 	bool "Other ISA cards"
-	depends on NET_ETHERNET && ISA
+	depends on ISA
 	---help---
 	  If your network (Ethernet) card hasn't been mentioned yet and its
 	  bus system (that's the way the cards talks to the other components
@@ -1147,7 +1167,7 @@
 
 config NE2_MCA
 	tristate "NE/2 (ne2000 MCA version) support"
-	depends on NET_ETHERNET && MCA_LEGACY
+	depends on MCA_LEGACY
 	select CRC32
 	help
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -1160,7 +1180,7 @@
 
 config IBMLANA
 	tristate "IBM LAN Adapter/A support"
-	depends on NET_ETHERNET && MCA && MCA_LEGACY
+	depends on MCA && MCA_LEGACY
 	---help---
 	  This is a Micro Channel Ethernet adapter.  You need to set
 	  CONFIG_MCA to use this driver.  It is both available as an in-kernel
@@ -1176,7 +1196,7 @@
 
 config IBMVETH
 	tristate "IBM LAN Virtual Ethernet support"
-	depends on NET_ETHERNET && PPC_PSERIES
+	depends on PPC_PSERIES
 	---help---
 	  This driver supports virtual ethernet adapters on newer IBM iSeries
 	  and pSeries systems.
@@ -1257,7 +1277,7 @@
 
 config NET_PCI
 	bool "EISA, VLB, PCI and on board controllers"
-	depends on NET_ETHERNET && (ISA || EISA || PCI)
+	depends on ISA || EISA || PCI
 	help
 	  This is another class of network cards which attach directly to the
 	  bus. If you have one of those, say Y and read the Ethernet-HOWTO,
@@ -1313,6 +1333,7 @@
 	  To compile this driver as a module, choose M here and read
 	  <file:Documentation/networking/net-modules.txt>. The module
 	  will be called amd8111e.
+
 config AMD8111E_NAPI
 	bool "Enable NAPI support"
 	depends on AMD8111_ETH
@@ -1778,7 +1799,7 @@
 
 config NET_POCKET
 	bool "Pocket and portable adapters"
-	depends on NET_ETHERNET && PARPORT
+	depends on PARPORT
 	---help---
 	  Cute little network (Ethernet) devices which attach to the parallel
 	  port ("pocket adapters"), commonly used with laptops. If you have
@@ -1847,14 +1868,14 @@
 
 config SGISEEQ
 	tristate "SGI Seeq ethernet controller support"
-	depends on NET_ETHERNET && SGI_IP22
+	depends on SGI_IP22
 	help
 	  Say Y here if you have an Seeq based Ethernet network card. This is
 	  used in many Silicon Graphics machines.
 
 config DECLANCE
 	tristate "DEC LANCE ethernet controller support"
-	depends on NET_ETHERNET && MACH_DECSTATION
+	depends on MACH_DECSTATION
 	select CRC32
 	help
 	  This driver is for the series of Ethernet controllers produced by
@@ -1884,7 +1905,7 @@
 
 config NE_H8300
 	tristate "NE2000 compatible support for H8/300"
-	depends on H8300 && NET_ETHERNET
+	depends on H8300
 	help
 	  Say Y here if you want to use the NE2000 compatible
 	  controller on the Renesas H8/300 processor.
@@ -1892,7 +1913,7 @@
 source "drivers/net/fec_8xx/Kconfig"
 source "drivers/net/fs_enet/Kconfig"
 
-endmenu
+endif # NET_ETHERNET
 
 #
 #	Gigabit Ethernet
@@ -2101,7 +2122,7 @@
 	  with better performance and more complete ethtool support.
 
 	  It does not support the link failover and network management 
-	  features that "portable" vendor supplied sk98lin driver does.
+	  features available in the hardware.
 
 	  This driver supports adapters based on the original Yukon chipset:
 	  Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
@@ -2114,7 +2135,7 @@
 	  will be called skge.  This is recommended.
 
 config SKY2
-	tristate "SysKonnect Yukon2 support (EXPERIMENTAL)"
+	tristate "SysKonnect Yukon2 support"
 	depends on PCI
 	select CRC32
 	---help---
@@ -2129,92 +2150,15 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called sky2.  This is recommended.
 
-config SK98LIN
-	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)"
-	depends on PCI
-	---help---
-	  Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
-	  compliant Gigabit Ethernet Adapter.
+config SKY2_DEBUG
+       bool "Debugging interface"
+       depends on SKY2 && DEBUG_FS
+       help
+	 This option adds the ability to dump driver state for debugging.
+	 The file debugfs/sky2/ethX displays the state of the internal
+	 transmit and receive rings.
 
-	  This driver supports the original Yukon chipset. This driver is
-	  deprecated and will be removed from the kernel in the near future,
-	  it has been replaced by the skge driver. skge is cleaner and
-	  seems to work better.
-
-	  This driver does not support the newer Yukon2 chipset. A separate
-	  driver, sky2, is provided to support Yukon2-based adapters.
-
-	  The following adapters are supported by this driver:
-	    - 3Com 3C940 Gigabit LOM Ethernet Adapter
-	    - 3Com 3C941 Gigabit LOM Ethernet Adapter
-	    - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter
-	    - Allied Telesyn AT-2971T Gigabit Ethernet Adapter
-	    - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
-	    - EG1032 v2 Instant Gigabit Network Adapter
-	    - EG1064 v2 Instant Gigabit Network Adapter
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte)
-	    - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill)
-	    - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel)
-	    - Marvell RDK-8001 Adapter
-	    - Marvell RDK-8002 Adapter
-	    - Marvell RDK-8003 Adapter
-	    - Marvell RDK-8004 Adapter
-	    - Marvell RDK-8006 Adapter
-	    - Marvell RDK-8007 Adapter
-	    - Marvell RDK-8008 Adapter
-	    - Marvell RDK-8009 Adapter
-	    - Marvell RDK-8010 Adapter
-	    - Marvell RDK-8011 Adapter
-	    - Marvell RDK-8012 Adapter
-	    - Marvell RDK-8052 Adapter
-	    - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit)
-	    - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit)
-	    - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
-	    - SK-9521 10/100/1000Base-T Adapter
-	    - SK-9521 V2.0 10/100/1000Base-T Adapter
-	    - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)
-	    - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter
-	    - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)
-	    - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)
-	    - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter
-	    - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)
-	    - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)
-	    - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter
-	    - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)
-	    - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter
-	    - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)
-	    - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter
-	    - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)
-	    - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)
-	    - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter
-	    - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link)
-	    - SMC EZ Card 1000 (SMC9452TXV.2)
-	  
-	  The adapters support Jumbo Frames.
-	  The dual link adapters support link-failover and dual port features.
-	  Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support 
-	  the scatter-gather functionality with sendfile(). Please refer to 
-	  <file:Documentation/networking/sk98lin.txt> for more information about
-	  optional driver parameters.
-	  Questions concerning this driver may be addressed to:
-	      <linux@syskonnect.de>
-	  
-	  If you want to compile this driver as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/kbuild/modules.txt>. The module will
-	  be called sk98lin. This is recommended.
+	 If unsure, say N.
 
 config VIA_VELOCITY
 	tristate "VIA Velocity support"
@@ -2264,6 +2208,16 @@
 	     To compile this driver as a module, choose M here: the module
 	     will be called tsi108_eth.
 
+config GELIC_NET
+	tristate "PS3 Gigabit Ethernet driver"
+	depends on PPC_PS3
+	help
+	  This driver supports the network device on the PS3 game
+	  console.  This driver has built-in support for Ethernet.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ps3_gelic.
+
 config GIANFAR
 	tristate "Gianfar Ethernet"
 	depends on 85xx || 83xx || PPC_86xx
@@ -2303,7 +2257,7 @@
 
 config MV643XX_ETH
 	tristate "MV-643XX Ethernet support"
-	depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MV64X60 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32)
+	depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32)
 	select MII
 	help
 	  This driver supports the gigabit Ethernet on the Marvell MV643XX
@@ -2838,6 +2792,19 @@
 	  which can lead to bad results if the ATM peer loses state and
 	  changes its encapsulation unilaterally.
 
+config PPPOL2TP
+	tristate "PPP over L2TP (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && PPP
+	help
+	  Support for PPP-over-L2TP socket family. L2TP is a protocol
+	  used by ISPs and enterprises to tunnel PPP traffic over UDP
+	  tunnels. L2TP is replacing PPTP for VPN uses.
+
+	  This kernel component handles only L2TP data packets: a
+	  userland daemon handles L2TP the control protocol (tunnel
+	  and session setup). One such daemon is OpenL2TP
+	  (http://openl2tp.sourceforge.net/).
+
 config SLIP
 	tristate "SLIP (serial line) support"
 	---help---
@@ -2948,8 +2915,6 @@
 	If you want to log kernel messages over the network, enable this.
 	See <file:Documentation/networking/netconsole.txt> for details.
 
-endif #NETDEVICES
-
 config NETPOLL
 	def_bool NETCONSOLE
 
@@ -2961,4 +2926,4 @@
 config NET_POLL_CONTROLLER
 	def_bool NETPOLL
 
-endmenu
+endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a77affa..a2241e6 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -60,10 +60,11 @@
 obj-$(CONFIG_BNX2) += bnx2.o
 spidernet-y += spider_net.o spider_net_ethtool.o
 obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o
+obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
+ps3_gelic-objs += ps3_gelic_net.o
 obj-$(CONFIG_TC35815) += tc35815.o
 obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SKY2) += sky2.o
-obj-$(CONFIG_SK98LIN) += sk98lin/
 obj-$(CONFIG_SKFP) += skfp/
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
 obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
@@ -107,6 +108,7 @@
 obj-$(CONFIG_B44) += b44.o
 obj-$(CONFIG_FORCEDETH) += forcedeth.o
 obj-$(CONFIG_NE_H8300) += ne-h8300.o
+obj-$(CONFIG_AX88796) += ax88796.o
 
 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
@@ -119,6 +121,7 @@
 obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
 obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
 obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
+obj-$(CONFIG_PPPOL2TP) += pppox.o pppol2tp.o
 
 obj-$(CONFIG_SLIP) += slip.o
 obj-$(CONFIG_SLHC) += slhc.o
@@ -157,6 +160,7 @@
 obj-$(CONFIG_AC3200) += ac3200.o 8390.o
 obj-$(CONFIG_APRICOT) += 82596.o
 obj-$(CONFIG_LASI_82596) += lasi_82596.o
+obj-$(CONFIG_SNI_82596) += sni_82596.o
 obj-$(CONFIG_MVME16x_NET) += 82596.o
 obj-$(CONFIG_BVME6000_NET) += 82596.o
 obj-$(CONFIG_SC92031) += sc92031.o
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 81d5a37..a45de69 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -322,9 +322,9 @@
 
 			skb_reserve (skb, 2);		/* 16 byte align */
 			skb_put (skb, len);		/* make room */
-			eth_copy_and_sum(skb,
+			skb_copy_to_linear_data(skb,
 					 (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
-					 len, 0);
+					 len);
 			skb->protocol = eth_type_trans (skb, dev);
 			netif_rx (skb);
 			dev->last_rx = jiffies;
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 04382f9..b78a4e5 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -159,10 +159,6 @@
 };
 MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
 
-#ifndef SET_NETDEV_DEV
-#define SET_NETDEV_DEV(net, pdev)	do{} while(0)
-#endif
-
 #define ace_sync_irq(irq)	synchronize_irq(irq)
 
 #ifndef offset_in_page
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index a241ae7..bc5a38a 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -746,7 +746,7 @@
 
 	    skb_reserve(skb,2);		/* 16 byte align */
 	    skb_put(skb,pkt_len);	/* Make room */
-	    eth_copy_and_sum(skb, (char *)priv->rx_buff[entry], pkt_len,0);
+	    skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len);
 	    skb->protocol=eth_type_trans(skb,dev);
 #if 0
 	    printk(KERN_DEBUG "RX pkt type 0x%04x from ",
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 678e4f4..5bf2d33 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -4,7 +4,7 @@
 #
 config ARM_AM79C961A
 	bool "ARM EBSA110 AM79C961A support"
-	depends on NET_ETHERNET && ARM && ARCH_EBSA110
+	depends on ARM && ARCH_EBSA110
 	select CRC32
 	help
 	  If you wish to compile a kernel for the EBSA-110, then you should
@@ -12,21 +12,21 @@
 
 config ARM_ETHER1
 	tristate "Acorn Ether1 support"
-	depends on NET_ETHERNET && ARM && ARCH_ACORN
+	depends on ARM && ARCH_ACORN
 	help
 	  If you have an Acorn system with one of these (AKA25) network cards,
 	  you should say Y to this option if you wish to use it with Linux.
 
 config ARM_ETHER3
 	tristate "Acorn/ANT Ether3 support"
-	depends on NET_ETHERNET && ARM && ARCH_ACORN
+	depends on ARM && ARCH_ACORN
 	help
 	  If you have an Acorn system with one of these network cards, you
 	  should say Y to this option if you wish to use it with Linux.
 
 config ARM_ETHERH
 	tristate "I-cubed EtherH/ANT EtherM support"
-	depends on NET_ETHERNET && ARM && ARCH_ACORN
+	depends on ARM && ARCH_ACORN
 	select CRC32
 	help
 	  If you have an Acorn system with one of these network cards, you
@@ -34,7 +34,7 @@
 
 config ARM_AT91_ETHER
 	tristate "AT91RM9200 Ethernet support"
-	depends on NET_ETHERNET && ARM && ARCH_AT91RM9200
+	depends on ARM && ARCH_AT91RM9200
 	select MII
 	help
 	  If you wish to compile a kernel for the AT91RM9200 and enable
@@ -42,7 +42,7 @@
 
 config EP93XX_ETH
 	tristate "EP93xx Ethernet support"
-	depends on NET_ETHERNET && ARM && ARCH_EP93XX
+	depends on ARM && ARCH_EP93XX
 	help
 	  This is a driver for the ethernet hardware included in EP93xx CPUs.
 	  Say Y if you are building a kernel for EP93xx based devices.
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 2438c5b..f6ece1d 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -258,7 +258,7 @@
 			skb_reserve(skb, 2);
 			dma_sync_single(NULL, ep->descs->rdesc[entry].buf_addr,
 						length, DMA_FROM_DEVICE);
-			eth_copy_and_sum(skb, ep->rx_buf[entry], length, 0);
+			skb_copy_to_linear_data(skb, ep->rx_buf[entry], length);
 			skb_put(skb, length);
 			skb->protocol = eth_type_trans(skb, dev);
 
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
index 5471440..f735637 100644
--- a/drivers/net/atari_pamsnet.c
+++ b/drivers/net/atari_pamsnet.c
@@ -295,10 +295,7 @@
 /* Setup the DMA counter */
 
 static void
-setup_dma (address, rw_flag, num_blocks)
-	void *address;
-	unsigned rw_flag;
-	int num_blocks;
+setup_dma (void *address, unsigned rw_flag, int num_blocks)
 {
 	WRITEMODE((unsigned) rw_flag          | DMA_FDC | SEC_COUNT | REG_ACSI |
 		  A1);
@@ -317,9 +314,7 @@
 /* Send the first byte of an command block */
 
 static int
-send_first (target, byte)
-	int target;
-	unsigned char byte;
+send_first (int target, unsigned char byte)
 {
 	rw = READ;
 	acsi_delay_end(COMMAND_DELAY);
@@ -338,10 +333,7 @@
 /* Send the rest of an command block */
 
 static int
-send_1_5 (lun, command, dma)
-	int lun;
-	unsigned char *command;
-	int dma;
+send_1_5 (int lun, unsigned char *command, int dma)
 {
 	int i, j;
 
@@ -371,8 +363,7 @@
 /* Calculate the number of received bytes */
 
 static int
-calc_received (start_address)
-	void *start_address;
+calc_received (void *start_address)
 {
 	return (int)(
 		(((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW)
@@ -384,8 +375,7 @@
 /* start() starts the PAM's DMA adaptor */
 
 static void
-start (target)
-	int target;
+start (int target)
 {
 	send_first(target, START);
 }
@@ -393,8 +383,7 @@
 /* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */
 
 static int
-stop (target)
-	int target;
+stop (int target)
 {
 	int ret = -1;
 	unsigned char cmd_buffer[5];
@@ -415,8 +404,7 @@
 /* testpkt() returns the number of received packets waiting in the queue */
 
 static int
-testpkt(target)
-	int target;
+testpkt(int target)
 {
 	int ret = -1;
 
@@ -431,9 +419,7 @@
 /* Please note: The buffer is for internal use only but must be defined!   */
 
 static int
-inquiry (target, buffer)
-	int target;
-	unsigned char *buffer;
+inquiry (int target, unsigned char *buffer)
 {
 	int ret = -1;
 	unsigned char *vbuffer = phys_to_virt((unsigned long)buffer);
@@ -468,9 +454,7 @@
  */
 
 static HADDR
-*read_hw_addr(target, buffer)
-	int target;
-	unsigned char *buffer;
+*read_hw_addr(int target, unsigned char *buffer)
 {
 	HADDR *ret = 0;
 	unsigned char cmd_buffer[5];
@@ -491,9 +475,7 @@
 }
 
 static irqreturn_t
-pamsnet_intr(irq, data, fp)
-	int irq;
-	void *data;
+pamsnet_intr(int irq, void *data)
 {
 	return IRQ_HANDLED;
 }
@@ -501,9 +483,7 @@
 /* receivepkt() loads a packet to a given buffer and returns its length */
 
 static int
-receivepkt (target, buffer)
-	int target;
-	unsigned char *buffer;
+receivepkt (int target, unsigned char *buffer)
 {
 	int ret = -1;
 	unsigned char cmd_buffer[5];
@@ -526,10 +506,7 @@
              successfully */
 
 static int
-sendpkt (target, buffer, length)
-	int target;
-	unsigned char *buffer;
-	int length;
+sendpkt (int target, unsigned char *buffer, int length)
 {
 	int ret = -1;
 	unsigned char cmd_buffer[5];
@@ -665,7 +642,8 @@
    there is non-reboot way to recover if something goes wrong.
  */
 static int
-pamsnet_open(struct net_device *dev) {
+pamsnet_open(struct net_device *dev)
+{
 	struct net_local *lp = netdev_priv(dev);
 
 	if (pamsnet_debug > 0)
@@ -694,7 +672,8 @@
 }
 
 static int
-pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) {
+pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
 	struct net_local *lp = netdev_priv(dev);
 	unsigned long flags;
 
@@ -741,7 +720,8 @@
 /* We have a good packet(s), get it/them out of the buffers.
  */
 static void
-pamsnet_poll_rx(struct net_device *dev) {
+pamsnet_poll_rx(struct net_device *dev)
+{
 	struct net_local *lp = netdev_priv(dev);
 	int boguscount;
 	int pkt_len;
@@ -816,7 +796,8 @@
  * passes them to the higher layers and restarts the timer.
  */
 static void
-pamsnet_tick(unsigned long data) {
+pamsnet_tick(unsigned long data)
+{
 	struct net_device	 *dev = (struct net_device *)data;
 	struct net_local *lp = netdev_priv(dev);
 
@@ -832,7 +813,8 @@
 /* The inverse routine to pamsnet_open().
  */
 static int
-pamsnet_close(struct net_device *dev) {
+pamsnet_close(struct net_device *dev)
+{
 	struct net_local *lp = netdev_priv(dev);
 
 	if (pamsnet_debug > 0)
diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
index 6862c11..3bb40dd4 100644
--- a/drivers/net/atl1/atl1_main.c
+++ b/drivers/net/atl1/atl1_main.c
@@ -634,14 +634,13 @@
 	struct atl1_buffer *buffer_info;
 	u16 sw_tpd_next_to_clean;
 	u16 cmb_tpd_next_to_clean;
-	u8 update = 0;
 
 	sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
 	cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
 
 	while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
 		struct tx_packet_desc *tpd;
-		update = 1;
+
 		tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
 		buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
 		if (buffer_info->dma) {
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index c27cfce..e86b369 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -1205,8 +1205,8 @@
 				continue;
 			}
 			skb_reserve(skb, 2);	/* 16 byte IP header align */
-			eth_copy_and_sum(skb,
-				(unsigned char *)pDB->vaddr, frmlen, 0);
+			skb_copy_to_linear_data(skb,
+				(unsigned char *)pDB->vaddr, frmlen);
 			skb_put(skb, frmlen);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);	/* pass the packet to upper layers */
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
new file mode 100644
index 0000000..d19874b
--- /dev/null
+++ b/drivers/net/ax88796.c
@@ -0,0 +1,952 @@
+/* drivers/net/ax88796.c
+ *
+ * Copyright 2005,2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Asix AX88796 10/100 Ethernet controller support
+ *	Based on ne.c, by Donald Becker, et-al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/isapnp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+
+#include <net/ax88796.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+static int phy_debug = 0;
+
+/* Rename the lib8390.c functions to show that they are in this driver */
+#define __ei_open       ax_ei_open
+#define __ei_close      ax_ei_close
+#define __ei_poll	ax_ei_poll
+#define __ei_tx_timeout ax_ei_tx_timeout
+#define __ei_interrupt  ax_ei_interrupt
+#define ____alloc_ei_netdev ax__alloc_ei_netdev
+#define __NS8390_init   ax_NS8390_init
+
+/* force unsigned long back to 'void __iomem *' */
+#define ax_convert_addr(_a) ((void __force __iomem *)(_a))
+
+#define ei_inb(_a)	readb(ax_convert_addr(_a))
+#define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a))
+
+#define ei_inb_p(_a)	ei_inb(_a)
+#define ei_outb_p(_v, _a) ei_outb(_v, _a)
+
+/* define EI_SHIFT() to take into account our register offsets */
+#define EI_SHIFT(x)     (ei_local->reg_offset[(x)])
+
+/* Ensure we have our RCR base value */
+#define AX88796_PLATFORM
+
+static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n";
+
+#include "lib8390.c"
+
+#define DRV_NAME "ax88796"
+#define DRV_VERSION "1.00"
+
+/* from ne.c */
+#define NE_CMD		EI_SHIFT(0x00)
+#define NE_RESET	EI_SHIFT(0x1f)
+#define NE_DATAPORT	EI_SHIFT(0x10)
+
+#define NE1SM_START_PG	0x20	/* First page of TX buffer */
+#define NE1SM_STOP_PG 	0x40	/* Last page +1 of RX ring */
+#define NESM_START_PG	0x40	/* First page of TX buffer */
+#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
+
+/* device private data */
+
+struct ax_device {
+	struct timer_list	 mii_timer;
+	spinlock_t		 mii_lock;
+	struct mii_if_info	 mii;
+
+	u32			 msg_enable;
+	void __iomem		*map2;
+	struct platform_device	*dev;
+	struct resource		*mem;
+	struct resource		*mem2;
+	struct ax_plat_data	*plat;
+
+	unsigned char		 running;
+	unsigned char		 resume_open;
+
+	u32			 reg_offsets[0x20];
+};
+
+static inline struct ax_device *to_ax_dev(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	return (struct ax_device *)(ei_local+1);
+}
+
+/* ax_initial_check
+ *
+ * do an initial probe for the card to check wether it exists
+ * and is functional
+ */
+
+static int ax_initial_check(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	void __iomem *ioaddr = ei_local->mem;
+	int reg0;
+	int regd;
+
+	reg0 = ei_inb(ioaddr);
+	if (reg0 == 0xFF)
+		return -ENODEV;
+
+	ei_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+	regd = ei_inb(ioaddr + 0x0d);
+	ei_outb(0xff, ioaddr + 0x0d);
+	ei_outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+	ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+	if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
+		ei_outb(reg0, ioaddr);
+		ei_outb(regd, ioaddr + 0x0d);	/* Restore the old values. */
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/* Hard reset the card.  This used to pause for the same period that a
+   8390 reset command required, but that shouldn't be necessary. */
+
+static void ax_reset_8390(struct net_device *dev)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	unsigned long reset_start_time = jiffies;
+	void __iomem *addr = (void __iomem *)dev->base_addr;
+
+	if (ei_debug > 1)
+		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+
+	ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
+
+	ei_status.txing = 0;
+	ei_status.dmaing = 0;
+
+	/* This check _should_not_ be necessary, omit eventually. */
+	while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
+		if (jiffies - reset_start_time > 2*HZ/100) {
+			printk(KERN_WARNING "%s: %s did not complete.\n",
+			       __FUNCTION__, dev->name);
+			break;
+		}
+	}
+
+	ei_outb(ENISR_RESET, addr + EN0_ISR);	/* Ack intr. */
+}
+
+
+static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+			    int ring_page)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	void __iomem *nic_base = ei_local->mem;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) {
+		printk(KERN_EMERG "%s: DMAing conflict in %s [DMAstat:%d][irqlock:%d].\n",
+			dev->name, __FUNCTION__,
+		       ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+	ei_outb(0, nic_base + EN0_RCNTHI);
+	ei_outb(0, nic_base + EN0_RSARLO);		/* On page boundary */
+	ei_outb(ring_page, nic_base + EN0_RSARHI);
+	ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	if (ei_status.word16)
+		readsw(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+	else
+		readsb(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+
+	le16_to_cpus(&hdr->count);
+}
+
+
+/* Block input and output, similar to the Crynwr packet driver.  If you
+   are porting to a new ethercard, look at the packet driver source for hints.
+   The NEx000 doesn't share the on-board packet memory -- you have to put
+   the packet out through the "remote DMA" dataport using ei_outb. */
+
+static void ax_block_input(struct net_device *dev, int count,
+			   struct sk_buff *skb, int ring_offset)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	void __iomem *nic_base = ei_local->mem;
+	char *buf = skb->data;
+
+	if (ei_status.dmaing) {
+		printk(KERN_EMERG "%s: DMAing conflict in ax_block_input "
+			"[DMAstat:%d][irqlock:%d].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+
+	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
+	ei_outb(count >> 8, nic_base + EN0_RCNTHI);
+	ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
+	ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);
+	ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	if (ei_status.word16) {
+		readsw(nic_base + NE_DATAPORT, buf, count >> 1);
+		if (count & 0x01)
+			buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
+
+	} else {
+		readsb(nic_base + NE_DATAPORT, buf, count);
+	}
+
+	ei_status.dmaing &= ~1;
+}
+
+static void ax_block_output(struct net_device *dev, int count,
+			    const unsigned char *buf, const int start_page)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	void __iomem *nic_base = ei_local->mem;
+	unsigned long dma_start;
+
+	/* Round the count up for word writes.  Do we need to do this?
+	   What effect will an odd byte count have on the 8390?
+	   I should check someday. */
+
+	if (ei_status.word16 && (count & 0x01))
+		count++;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) {
+		printk(KERN_EMERG "%s: DMAing conflict in %s."
+			"[DMAstat:%d][irqlock:%d]\n",
+			dev->name, __FUNCTION__,
+		       ei_status.dmaing, ei_status.irqlock);
+		return;
+	}
+
+	ei_status.dmaing |= 0x01;
+	/* We should already be in page 0, but to be safe... */
+	ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+	ei_outb(ENISR_RDC, nic_base + EN0_ISR);
+
+	/* Now the normal output. */
+	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
+	ei_outb(count >> 8,   nic_base + EN0_RCNTHI);
+	ei_outb(0x00, nic_base + EN0_RSARLO);
+	ei_outb(start_page, nic_base + EN0_RSARHI);
+
+	ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+	if (ei_status.word16) {
+		writesw(nic_base + NE_DATAPORT, buf, count>>1);
+	} else {
+		writesb(nic_base + NE_DATAPORT, buf, count);
+	}
+
+	dma_start = jiffies;
+
+	while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
+		if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
+			printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+			ax_reset_8390(dev);
+			ax_NS8390_init(dev,1);
+			break;
+		}
+	}
+
+	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+	return;
+}
+
+/* definitions for accessing MII/EEPROM interface */
+
+#define AX_MEMR			EI_SHIFT(0x14)
+#define AX_MEMR_MDC		(1<<0)
+#define AX_MEMR_MDIR		(1<<1)
+#define AX_MEMR_MDI		(1<<2)
+#define AX_MEMR_MDO		(1<<3)
+#define AX_MEMR_EECS		(1<<4)
+#define AX_MEMR_EEI		(1<<5)
+#define AX_MEMR_EEO		(1<<6)
+#define AX_MEMR_EECLK		(1<<7)
+
+/* ax_mii_ei_outbits
+ *
+ * write the specified set of bits to the phy
+*/
+
+static void
+ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len)
+{
+	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
+	unsigned int memr;
+
+	/* clock low, data to output mode */
+	memr = ei_inb(memr_addr);
+	memr &= ~(AX_MEMR_MDC | AX_MEMR_MDIR);
+	ei_outb(memr, memr_addr);
+
+	for (len--; len >= 0; len--) {
+		if (bits & (1 << len))
+			memr |= AX_MEMR_MDO;
+		else
+			memr &= ~AX_MEMR_MDO;
+
+		ei_outb(memr, memr_addr);
+
+		/* clock high */
+
+		ei_outb(memr | AX_MEMR_MDC, memr_addr);
+		udelay(1);
+
+		/* clock low */
+		ei_outb(memr, memr_addr);
+	}
+
+	/* leaves the clock line low, mdir input */
+	memr |= AX_MEMR_MDIR;
+	ei_outb(memr, (void __iomem *)dev->base_addr + AX_MEMR);
+}
+
+/* ax_phy_ei_inbits
+ *
+ * read a specified number of bits from the phy
+*/
+
+static unsigned int
+ax_phy_ei_inbits(struct net_device *dev, int no)
+{
+	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
+	unsigned int memr;
+	unsigned int result = 0;
+
+	/* clock low, data to input mode */
+	memr = ei_inb(memr_addr);
+	memr &= ~AX_MEMR_MDC;
+	memr |= AX_MEMR_MDIR;
+	ei_outb(memr, memr_addr);
+
+	for (no--; no >= 0; no--) {
+		ei_outb(memr | AX_MEMR_MDC, memr_addr);
+
+		udelay(1);
+
+		if (ei_inb(memr_addr) & AX_MEMR_MDI)
+			result |= (1<<no);
+
+		ei_outb(memr, memr_addr);
+	}
+
+	return result;
+}
+
+/* ax_phy_issueaddr
+ *
+ * use the low level bit shifting routines to send the address
+ * and command to the specified phy
+*/
+
+static void
+ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc)
+{
+	if (phy_debug)
+		pr_debug("%s: dev %p, %04x, %04x, %d\n",
+			__FUNCTION__, dev, phy_addr, reg, opc);
+
+	ax_mii_ei_outbits(dev, 0x3f, 6);	/* pre-amble */
+	ax_mii_ei_outbits(dev, 1, 2);		/* frame-start */
+	ax_mii_ei_outbits(dev, opc, 2);		/* op code */
+	ax_mii_ei_outbits(dev, phy_addr, 5);	/* phy address */
+	ax_mii_ei_outbits(dev, reg, 5);		/* reg address */
+}
+
+static int
+ax_phy_read(struct net_device *dev, int phy_addr, int reg)
+{
+	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+	unsigned long flags;
+ 	unsigned int result;
+
+      	spin_lock_irqsave(&ei_local->page_lock, flags);
+
+	ax_phy_issueaddr(dev, phy_addr, reg, 2);
+
+	result = ax_phy_ei_inbits(dev, 17);
+	result &= ~(3<<16);
+
+      	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+	if (phy_debug)
+		pr_debug("%s: %04x.%04x => read %04x\n", __FUNCTION__,
+			 phy_addr, reg, result);
+
+	return result;
+}
+
+static void
+ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value)
+{
+	struct ei_device *ei = (struct ei_device *) netdev_priv(dev);
+	unsigned long flags;
+
+	printk(KERN_DEBUG "%s: %p, %04x, %04x %04x\n",
+	       __FUNCTION__, dev, phy_addr, reg, value);
+
+      	spin_lock_irqsave(&ei->page_lock, flags);
+
+	ax_phy_issueaddr(dev, phy_addr, reg, 1);
+	ax_mii_ei_outbits(dev, 2, 2);		/* send TA */
+	ax_mii_ei_outbits(dev, value, 16);
+
+      	spin_unlock_irqrestore(&ei->page_lock, flags);
+}
+
+static void ax_mii_expiry(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct ax_device  *ax = to_ax_dev(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ax->mii_lock, flags);
+	mii_check_media(&ax->mii, netif_msg_link(ax), 0);
+	spin_unlock_irqrestore(&ax->mii_lock, flags);
+
+	if (ax->running) {
+		ax->mii_timer.expires = jiffies + HZ*2;
+		add_timer(&ax->mii_timer);
+	}
+}
+
+static int ax_open(struct net_device *dev)
+{
+	struct ax_device  *ax = to_ax_dev(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
+	int ret;
+
+	dev_dbg(ax->dev, "%s: open\n", dev->name);
+
+	ret = request_irq(dev->irq, ax_ei_interrupt, 0, dev->name, dev);
+	if (ret)
+		return ret;
+
+	ret = ax_ei_open(dev);
+	if (ret)
+		return ret;
+
+	/* turn the phy on (if turned off) */
+
+	ei_outb(ax->plat->gpoc_val, ei_local->mem + EI_SHIFT(0x17));
+	ax->running = 1;
+
+	/* start the MII timer */
+
+	init_timer(&ax->mii_timer);
+
+	ax->mii_timer.expires  = jiffies+1;
+	ax->mii_timer.data     = (unsigned long) dev;
+	ax->mii_timer.function = ax_mii_expiry;
+
+	add_timer(&ax->mii_timer);
+
+	return 0;
+}
+
+static int ax_close(struct net_device *dev)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	struct ei_device *ei_local = netdev_priv(dev);
+
+	dev_dbg(ax->dev, "%s: close\n", dev->name);
+
+	/* turn the phy off */
+
+	ei_outb(ax->plat->gpoc_val | (1<<6),
+	       ei_local->mem + EI_SHIFT(0x17));
+
+	ax->running = 0;
+	wmb();
+
+	del_timer_sync(&ax->mii_timer);
+	ax_ei_close(dev);
+
+	free_irq(dev->irq, dev);
+	return 0;
+}
+
+static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	unsigned long flags;
+	int rc;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&ax->mii_lock, flags);
+	rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL);
+	spin_unlock_irqrestore(&ax->mii_lock, flags);
+
+	return rc;
+}
+
+/* ethtool ops */
+
+static void ax_get_drvinfo(struct net_device *dev,
+			   struct ethtool_drvinfo *info)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, ax->dev->name);
+}
+
+static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ax->mii_lock, flags);
+	mii_ethtool_gset(&ax->mii, cmd);
+	spin_lock_irqsave(&ax->mii_lock, flags);
+
+	return 0;
+}
+
+static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&ax->mii_lock, flags);
+	rc = mii_ethtool_sset(&ax->mii, cmd);
+	spin_lock_irqsave(&ax->mii_lock, flags);
+
+	return rc;
+}
+
+static int ax_nway_reset(struct net_device *dev)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	return mii_nway_restart(&ax->mii);
+}
+
+static u32 ax_get_link(struct net_device *dev)
+{
+	struct ax_device *ax = to_ax_dev(dev);
+	return mii_link_ok(&ax->mii);
+}
+
+static const struct ethtool_ops ax_ethtool_ops = {
+	.get_drvinfo		= ax_get_drvinfo,
+	.get_settings		= ax_get_settings,
+	.set_settings		= ax_set_settings,
+	.nway_reset		= ax_nway_reset,
+	.get_link		= ax_get_link,
+	.get_perm_addr		= ethtool_op_get_perm_addr,
+};
+
+/* setup code */
+
+static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
+{
+	void __iomem *ioaddr = ei_local->mem;
+	struct ax_device *ax = to_ax_dev(dev);
+
+	/* Select page 0*/
+	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr + E8390_CMD);
+
+	/* set to byte access */
+	ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);
+	ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));
+}
+
+/* ax_init_dev
+ *
+ * initialise the specified device, taking care to note the MAC
+ * address it may already have (if configured), ensure
+ * the device is ready to be used by lib8390.c and registerd with
+ * the network layer.
+ */
+
+static int ax_init_dev(struct net_device *dev, int first_init)
+{
+	struct ei_device *ei_local = netdev_priv(dev);
+	struct ax_device *ax = to_ax_dev(dev);
+	void __iomem *ioaddr = ei_local->mem;
+	unsigned int start_page;
+	unsigned int stop_page;
+	int ret;
+	int i;
+
+	ret = ax_initial_check(dev);
+	if (ret)
+		goto err_out;
+
+	/* setup goes here */
+
+	ax_initial_setup(dev, ei_local);
+
+	/* read the mac from the card prom if we need it */
+
+	if (first_init && ax->plat->flags & AXFLG_HAS_EEPROM) {
+		unsigned char SA_prom[32];
+
+		for(i = 0; i < sizeof(SA_prom); i+=2) {
+			SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
+			SA_prom[i+1] = ei_inb(ioaddr + NE_DATAPORT);
+		}
+
+		if (ax->plat->wordlength == 2)
+			for (i = 0; i < 16; i++)
+				SA_prom[i] = SA_prom[i+i];
+
+		memcpy(dev->dev_addr,  SA_prom, 6);
+	}
+
+	if (ax->plat->wordlength == 2) {
+		/* We must set the 8390 for word mode. */
+		ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);
+		start_page = NESM_START_PG;
+		stop_page = NESM_STOP_PG;
+	} else {
+		start_page = NE1SM_START_PG;
+		stop_page = NE1SM_STOP_PG;
+	}
+
+	/* load the mac-address from the device if this is the
+	 * first time we've initialised */
+
+	if (first_init && ax->plat->flags & AXFLG_MAC_FROMDEV) {
+		ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+			ei_local->mem + E8390_CMD); /* 0x61 */
+
+		for (i = 0 ; i < ETHER_ADDR_LEN ; i++)
+			dev->dev_addr[i] = ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
+	}
+
+	ax_reset_8390(dev);
+
+	ei_status.name = "AX88796";
+	ei_status.tx_start_page = start_page;
+	ei_status.stop_page = stop_page;
+	ei_status.word16 = (ax->plat->wordlength == 2);
+	ei_status.rx_start_page = start_page + TX_PAGES;
+
+#ifdef PACKETBUF_MEMSIZE
+	 /* Allow the packet buffer size to be overridden by know-it-alls. */
+	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+	ei_status.reset_8390	= &ax_reset_8390;
+	ei_status.block_input	= &ax_block_input;
+	ei_status.block_output	= &ax_block_output;
+	ei_status.get_8390_hdr	= &ax_get_8390_hdr;
+	ei_status.priv = 0;
+
+	dev->open		= ax_open;
+	dev->stop		= ax_close;
+	dev->do_ioctl		= ax_ioctl;
+	dev->ethtool_ops	= &ax_ethtool_ops;
+
+	ax->msg_enable		= NETIF_MSG_LINK;
+	ax->mii.phy_id_mask	= 0x1f;
+	ax->mii.reg_num_mask	= 0x1f;
+	ax->mii.phy_id		= 0x10;		/* onboard phy */
+	ax->mii.force_media	= 0;
+	ax->mii.full_duplex	= 0;
+	ax->mii.mdio_read	= ax_phy_read;
+	ax->mii.mdio_write	= ax_phy_write;
+	ax->mii.dev		= dev;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ax_ei_poll;
+#endif
+	ax_NS8390_init(dev, 0);
+
+	if (first_init) {
+		printk("AX88796: %dbit, irq %d, %lx, MAC: ",
+		       ei_status.word16 ? 16:8, dev->irq, dev->base_addr);
+
+		for (i = 0; i < ETHER_ADDR_LEN; i++)
+			printk("%2.2x%c", dev->dev_addr[i],
+			       (i < (ETHER_ADDR_LEN-1) ? ':' : ' '));
+
+		printk("\n");
+	}
+
+	ret = register_netdev(dev);
+	if (ret)
+		goto out_irq;
+
+	return 0;
+
+ out_irq:
+	/* cleanup irq */
+	free_irq(dev->irq, dev);
+ err_out:
+	return ret;
+}
+
+static int ax_remove(struct platform_device *_dev)
+{
+	struct net_device *dev = platform_get_drvdata(_dev);
+	struct ax_device  *ax;
+
+	ax = to_ax_dev(dev);
+
+	unregister_netdev(dev);
+	free_irq(dev->irq, dev);
+
+	iounmap(ei_status.mem);
+	release_resource(ax->mem);
+	kfree(ax->mem);
+
+	if (ax->map2) {
+		iounmap(ax->map2);
+		release_resource(ax->mem2);
+		kfree(ax->mem2);
+	}
+
+	free_netdev(dev);
+
+	return 0;
+}
+
+/* ax_probe
+ *
+ * This is the entry point when the platform device system uses to
+ * notify us of a new device to attach to. Allocate memory, find
+ * the resources and information passed, and map the necessary registers.
+*/
+
+static int ax_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct ax_device  *ax;
+	struct resource   *res;
+	size_t size;
+	int ret;
+
+	dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
+	if (dev == NULL)
+		return -ENOMEM;
+
+	/* ok, let's setup our device */
+	ax = to_ax_dev(dev);
+
+	memset(ax, 0, sizeof(struct ax_device));
+
+	spin_lock_init(&ax->mii_lock);
+
+	ax->dev = pdev;
+	ax->plat = pdev->dev.platform_data;
+	platform_set_drvdata(pdev, dev);
+
+	ei_status.rxcr_base  = ax->plat->rcr_val;
+
+	/* find the platform resources */
+
+	dev->irq  = platform_get_irq(pdev, 0);
+	if (dev->irq < 0) {
+		dev_err(&pdev->dev, "no IRQ specified\n");
+		ret = -ENXIO;
+		goto exit_mem;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no MEM specified\n");
+		ret = -ENXIO;
+		goto exit_mem;
+	}
+
+	size = (res->end - res->start) + 1;
+
+	/* setup the register offsets from either the platform data
+	 * or by using the size of the resource provided */
+
+	if (ax->plat->reg_offsets)
+		ei_status.reg_offset = ax->plat->reg_offsets;
+	else {
+		ei_status.reg_offset = ax->reg_offsets;
+		for (ret = 0; ret < 0x18; ret++)
+			ax->reg_offsets[ret] = (size / 0x18) * ret;
+	}
+
+	ax->mem = request_mem_region(res->start, size, pdev->name);
+	if (ax->mem == NULL) {
+		dev_err(&pdev->dev, "cannot reserve registers\n");
+ 		ret = -ENXIO;
+		goto exit_mem;
+	}
+
+	ei_status.mem = ioremap(res->start, size);
+	dev->base_addr = (long)ei_status.mem;
+
+	if (ei_status.mem == NULL) {
+		dev_err(&pdev->dev, "Cannot ioremap area (%08zx,%08zx)\n",
+			res->start, res->end);
+
+ 		ret = -ENXIO;
+		goto exit_req;
+	}
+
+	/* look for reset area */
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res == NULL) {
+		if (!ax->plat->reg_offsets) {
+			for (ret = 0; ret < 0x20; ret++)
+				ax->reg_offsets[ret] = (size / 0x20) * ret;
+		}
+
+		ax->map2 = NULL;
+	} else {
+ 		size = (res->end - res->start) + 1;
+
+		ax->mem2 = request_mem_region(res->start, size, pdev->name);
+		if (ax->mem == NULL) {
+			dev_err(&pdev->dev, "cannot reserve registers\n");
+			ret = -ENXIO;
+			goto exit_mem1;
+		}
+
+		ax->map2 = ioremap(res->start, size);
+		if (ax->map2 == NULL) {
+			dev_err(&pdev->dev, "cannot map reset register");
+			ret = -ENXIO;
+			goto exit_mem2;
+		}
+
+		ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem;
+	}
+
+	/* got resources, now initialise and register device */
+
+	ret = ax_init_dev(dev, 1);
+	if (!ret)
+		return 0;
+
+	if (ax->map2 == NULL)
+		goto exit_mem1;
+
+	iounmap(ax->map2);
+
+ exit_mem2:
+	release_resource(ax->mem2);
+	kfree(ax->mem2);
+
+ exit_mem1:
+	iounmap(ei_status.mem);
+
+ exit_req:
+	release_resource(ax->mem);
+	kfree(ax->mem);
+
+ exit_mem:
+	free_netdev(dev);
+
+	return ret;
+}
+
+/* suspend and resume */
+
+#ifdef CONFIG_PM
+static int ax_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct net_device *ndev = platform_get_drvdata(dev);
+	struct ax_device  *ax = to_ax_dev(ndev);
+
+	ax->resume_open = ax->running;
+
+	netif_device_detach(ndev);
+	ax_close(ndev);
+
+	return 0;
+}
+
+static int ax_resume(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct ax_device  *ax = to_ax_dev(ndev);
+
+	ax_initial_setup(ndev, netdev_priv(ndev));
+	ax_NS8390_init(ndev, ax->resume_open);
+	netif_device_attach(ndev);
+
+	if (ax->resume_open)
+		ax_open(ndev);
+
+	return 0;
+}
+
+#else
+#define ax_suspend NULL
+#define ax_resume  NULL
+#endif
+
+static struct platform_driver axdrv = {
+	.driver	= {
+		.name		= "ax88796",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= ax_probe,
+	.remove		= ax_remove,
+	.suspend	= ax_suspend,
+	.resume		= ax_resume,
+};
+
+static int __init axdrv_init(void)
+{
+	return platform_driver_register(&axdrv);
+}
+
+static void __exit axdrv_exit(void)
+{
+	platform_driver_unregister(&axdrv);
+}
+
+module_init(axdrv_init);
+module_exit(axdrv_exit);
+
+MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 879a2ff..96fb0ec 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -15,6 +15,7 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/if_ether.h>
+#include <linux/if_vlan.h>
 #include <linux/etherdevice.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -68,8 +69,8 @@
 	  (BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
 #define NEXT_TX(N)		(((N) + 1) & (B44_TX_RING_SIZE - 1))
 
-#define RX_PKT_BUF_SZ		(1536 + bp->rx_offset + 64)
-#define TX_PKT_BUF_SZ		(B44_MAX_MTU + ETH_HLEN + 8)
+#define RX_PKT_OFFSET		30
+#define RX_PKT_BUF_SZ		(1536 + RX_PKT_OFFSET + 64)
 
 /* minimum number of free TX descriptors required to wake up TX process */
 #define B44_TX_WAKEUP_THRESH		(B44_TX_RING_SIZE / 4)
@@ -599,8 +600,7 @@
 
 	spin_unlock_irq(&bp->lock);
 
-	bp->timer.expires = jiffies + HZ;
-	add_timer(&bp->timer);
+	mod_timer(&bp->timer, round_jiffies(jiffies + HZ));
 }
 
 static void b44_tx(struct b44 *bp)
@@ -653,7 +653,7 @@
 		src_map = &bp->rx_buffers[src_idx];
 	dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1);
 	map = &bp->rx_buffers[dest_idx];
-	skb = dev_alloc_skb(RX_PKT_BUF_SZ);
+	skb = netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ);
 	if (skb == NULL)
 		return -ENOMEM;
 
@@ -669,7 +669,7 @@
 		if (!dma_mapping_error(mapping))
 			pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
 		dev_kfree_skb_any(skb);
-		skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
+		skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
 		if (skb == NULL)
 			return -ENOMEM;
 		mapping = pci_map_single(bp->pdev, skb->data,
@@ -684,11 +684,9 @@
 		}
 	}
 
-	skb->dev = bp->dev;
-	skb_reserve(skb, bp->rx_offset);
+	rh = (struct rx_header *) skb->data;
+	skb_reserve(skb, RX_PKT_OFFSET);
 
-	rh = (struct rx_header *)
-		(skb->data - bp->rx_offset);
 	rh->len = 0;
 	rh->flags = 0;
 
@@ -698,13 +696,13 @@
 	if (src_map != NULL)
 		src_map->skb = NULL;
 
-	ctrl  = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - bp->rx_offset));
+	ctrl  = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET));
 	if (dest_idx == (B44_RX_RING_SIZE - 1))
 		ctrl |= DESC_CTRL_EOT;
 
 	dp = &bp->rx_ring[dest_idx];
 	dp->ctrl = cpu_to_le32(ctrl);
-	dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
+	dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset);
 
 	if (bp->flags & B44_FLAG_RX_RING_HACK)
 		b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
@@ -783,7 +781,7 @@
 					    PCI_DMA_FROMDEVICE);
 		rh = (struct rx_header *) skb->data;
 		len = le16_to_cpu(rh->len);
-		if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) ||
+		if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
 		    (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
 		drop_it:
 			b44_recycle_rx(bp, cons, bp->rx_prod);
@@ -815,8 +813,8 @@
 			pci_unmap_single(bp->pdev, map,
 					 skb_size, PCI_DMA_FROMDEVICE);
 			/* Leave out rx_header */
-                	skb_put(skb, len+bp->rx_offset);
-            	        skb_pull(skb,bp->rx_offset);
+                	skb_put(skb, len + RX_PKT_OFFSET);
+            	        skb_pull(skb, RX_PKT_OFFSET);
 		} else {
 			struct sk_buff *copy_skb;
 
@@ -828,7 +826,7 @@
 			skb_reserve(copy_skb, 2);
 			skb_put(copy_skb, len);
 			/* DMA sync done above, copy just the actual packet */
-			skb_copy_from_linear_data_offset(skb, bp->rx_offset,
+			skb_copy_from_linear_data_offset(skb, RX_PKT_OFFSET,
 							 copy_skb->data, len);
 			skb = copy_skb;
 		}
@@ -969,7 +967,6 @@
 static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct b44 *bp = netdev_priv(dev);
-	struct sk_buff *bounce_skb;
 	int rc = NETDEV_TX_OK;
 	dma_addr_t mapping;
 	u32 len, entry, ctrl;
@@ -987,12 +984,13 @@
 
 	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
 	if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
+		struct sk_buff *bounce_skb;
+
 		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
 		if (!dma_mapping_error(mapping))
 			pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
 
-		bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
-					     GFP_ATOMIC|GFP_DMA);
+		bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA);
 		if (!bounce_skb)
 			goto err_out;
 
@@ -1001,13 +999,12 @@
 		if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
 			if (!dma_mapping_error(mapping))
 				pci_unmap_single(bp->pdev, mapping,
-					 len, PCI_DMA_TODEVICE);
+						 len, PCI_DMA_TODEVICE);
 			dev_kfree_skb_any(bounce_skb);
 			goto err_out;
 		}
 
-		skb_copy_from_linear_data(skb, skb_put(bounce_skb, len),
-					  skb->len);
+		skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
 		dev_kfree_skb_any(skb);
 		skb = bounce_skb;
 	}
@@ -1396,12 +1393,12 @@
 	bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
 	if (reset_kind == B44_PARTIAL_RESET) {
 		bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-				      (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+				      (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
 	} else {
 		bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
 		bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
 		bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-				      (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+				      (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
 		bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
 
 		bw32(bp, B44_DMARX_PTR, bp->rx_pending);
@@ -2093,11 +2090,6 @@
 
 	bp->phy_addr = eeprom[90] & 0x1f;
 
-	/* With this, plus the rx_header prepended to the data by the
-	 * hardware, we'll land the ethernet header on a 2-byte boundary.
-	 */
-	bp->rx_offset = 30;
-
 	bp->imask = IMASK_DEF;
 
 	bp->core_unit = ssb_core_unit(bp);
@@ -2348,11 +2340,11 @@
 	netif_device_attach(bp->dev);
 	spin_unlock_irq(&bp->lock);
 
-	bp->timer.expires = jiffies + HZ;
-	add_timer(&bp->timer);
-
 	b44_enable_ints(bp);
 	netif_wake_queue(dev);
+
+	mod_timer(&bp->timer, jiffies + 1);
+
 	return 0;
 }
 
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 18fc133..e537e63 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -443,8 +443,6 @@
 #define B44_FLAG_TX_RING_HACK	0x40000000
 #define B44_FLAG_WOL_ENABLE	0x80000000
 
-	u32			rx_offset;
-
 	u32			msg_enable;
 
 	struct timer_list	timer;
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index ce3ed67..d681903 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -40,7 +40,6 @@
 #define BCM_VLAN 1
 #endif
 #include <net/ip.h>
-#include <net/tcp.h>
 #include <net/checksum.h>
 #include <linux/workqueue.h>
 #include <linux/crc32.h>
@@ -54,8 +53,8 @@
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.5.11"
-#define DRV_MODULE_RELDATE	"June 4, 2007"
+#define DRV_MODULE_VERSION	"1.6.2"
+#define DRV_MODULE_RELDATE	"July 6, 2007"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -550,6 +549,9 @@
 {
 	u32 fw_link_status = 0;
 
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		return;
+
 	if (bp->link_up) {
 		u32 bmsr;
 
@@ -601,12 +603,21 @@
 	REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status);
 }
 
+static char *
+bnx2_xceiver_str(struct bnx2 *bp)
+{
+	return ((bp->phy_port == PORT_FIBRE) ? "SerDes" :
+		((bp->phy_flags & PHY_SERDES_FLAG) ? "Remote Copper" :
+		 "Copper"));
+}
+
 static void
 bnx2_report_link(struct bnx2 *bp)
 {
 	if (bp->link_up) {
 		netif_carrier_on(bp->dev);
-		printk(KERN_INFO PFX "%s NIC Link is Up, ", bp->dev->name);
+		printk(KERN_INFO PFX "%s NIC %s Link is Up, ", bp->dev->name,
+		       bnx2_xceiver_str(bp));
 
 		printk("%d Mbps ", bp->line_speed);
 
@@ -630,7 +641,8 @@
 	}
 	else {
 		netif_carrier_off(bp->dev);
-		printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name);
+		printk(KERN_ERR PFX "%s NIC %s Link is Down\n", bp->dev->name,
+		       bnx2_xceiver_str(bp));
 	}
 
 	bnx2_report_fw_link(bp);
@@ -1100,6 +1112,9 @@
 		return 0;
 	}
 
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		return 0;
+
 	link_up = bp->link_up;
 
 	bnx2_enable_bmsr1(bp);
@@ -1210,12 +1225,74 @@
 	return adv;
 }
 
+static int bnx2_fw_sync(struct bnx2 *, u32, int);
+
 static int
-bnx2_setup_serdes_phy(struct bnx2 *bp)
+bnx2_setup_remote_phy(struct bnx2 *bp, u8 port)
+{
+	u32 speed_arg = 0, pause_adv;
+
+	pause_adv = bnx2_phy_get_pause_adv(bp);
+
+	if (bp->autoneg & AUTONEG_SPEED) {
+		speed_arg |= BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG;
+		if (bp->advertising & ADVERTISED_10baseT_Half)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10HALF;
+		if (bp->advertising & ADVERTISED_10baseT_Full)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10FULL;
+		if (bp->advertising & ADVERTISED_100baseT_Half)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100HALF;
+		if (bp->advertising & ADVERTISED_100baseT_Full)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100FULL;
+		if (bp->advertising & ADVERTISED_1000baseT_Full)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_1GFULL;
+		if (bp->advertising & ADVERTISED_2500baseX_Full)
+			speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_2G5FULL;
+	} else {
+		if (bp->req_line_speed == SPEED_2500)
+			speed_arg = BNX2_NETLINK_SET_LINK_SPEED_2G5FULL;
+		else if (bp->req_line_speed == SPEED_1000)
+			speed_arg = BNX2_NETLINK_SET_LINK_SPEED_1GFULL;
+		else if (bp->req_line_speed == SPEED_100) {
+			if (bp->req_duplex == DUPLEX_FULL)
+				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100FULL;
+			else
+				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100HALF;
+		} else if (bp->req_line_speed == SPEED_10) {
+			if (bp->req_duplex == DUPLEX_FULL)
+				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10FULL;
+			else
+				speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10HALF;
+		}
+	}
+
+	if (pause_adv & (ADVERTISE_1000XPAUSE | ADVERTISE_PAUSE_CAP))
+		speed_arg |= BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE;
+	if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_1000XPSE_ASYM))
+		speed_arg |= BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE;
+
+	if (port == PORT_TP)
+		speed_arg |= BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE |
+			     BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED;
+
+	REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB_ARG0, speed_arg);
+
+	spin_unlock_bh(&bp->phy_lock);
+	bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 0);
+	spin_lock_bh(&bp->phy_lock);
+
+	return 0;
+}
+
+static int
+bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port)
 {
 	u32 adv, bmcr;
 	u32 new_adv = 0;
 
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		return (bnx2_setup_remote_phy(bp, port));
+
 	if (!(bp->autoneg & AUTONEG_SPEED)) {
 		u32 new_bmcr;
 		int force_link_down = 0;
@@ -1323,7 +1400,9 @@
 }
 
 #define ETHTOOL_ALL_FIBRE_SPEED						\
-	(ADVERTISED_1000baseT_Full)
+	(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) ?			\
+		(ADVERTISED_2500baseX_Full | ADVERTISED_1000baseT_Full) :\
+		(ADVERTISED_1000baseT_Full)
 
 #define ETHTOOL_ALL_COPPER_SPEED					\
 	(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |		\
@@ -1335,6 +1414,188 @@
 
 #define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL)
 
+static void
+bnx2_set_default_remote_link(struct bnx2 *bp)
+{
+	u32 link;
+
+	if (bp->phy_port == PORT_TP)
+		link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_COPPER_LINK);
+	else
+		link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_SERDES_LINK);
+
+	if (link & BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG) {
+		bp->req_line_speed = 0;
+		bp->autoneg |= AUTONEG_SPEED;
+		bp->advertising = ADVERTISED_Autoneg;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF)
+			bp->advertising |= ADVERTISED_10baseT_Half;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_10FULL)
+			bp->advertising |= ADVERTISED_10baseT_Full;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF)
+			bp->advertising |= ADVERTISED_100baseT_Half;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_100FULL)
+			bp->advertising |= ADVERTISED_100baseT_Full;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL)
+			bp->advertising |= ADVERTISED_1000baseT_Full;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL)
+			bp->advertising |= ADVERTISED_2500baseX_Full;
+	} else {
+		bp->autoneg = 0;
+		bp->advertising = 0;
+		bp->req_duplex = DUPLEX_FULL;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_10) {
+			bp->req_line_speed = SPEED_10;
+			if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF)
+				bp->req_duplex = DUPLEX_HALF;
+		}
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_100) {
+			bp->req_line_speed = SPEED_100;
+			if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF)
+				bp->req_duplex = DUPLEX_HALF;
+		}
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL)
+			bp->req_line_speed = SPEED_1000;
+		if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL)
+			bp->req_line_speed = SPEED_2500;
+	}
+}
+
+static void
+bnx2_set_default_link(struct bnx2 *bp)
+{
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		return bnx2_set_default_remote_link(bp);
+
+	bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
+	bp->req_line_speed = 0;
+	if (bp->phy_flags & PHY_SERDES_FLAG) {
+		u32 reg;
+
+		bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
+
+		reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG);
+		reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
+		if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
+			bp->autoneg = 0;
+			bp->req_line_speed = bp->line_speed = SPEED_1000;
+			bp->req_duplex = DUPLEX_FULL;
+		}
+	} else
+		bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
+}
+
+static void
+bnx2_send_heart_beat(struct bnx2 *bp)
+{
+	u32 msg;
+	u32 addr;
+
+	spin_lock(&bp->indirect_lock);
+	msg = (u32) (++bp->fw_drv_pulse_wr_seq & BNX2_DRV_PULSE_SEQ_MASK);
+	addr = bp->shmem_base + BNX2_DRV_PULSE_MB;
+	REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr);
+	REG_WR(bp, BNX2_PCICFG_REG_WINDOW, msg);
+	spin_unlock(&bp->indirect_lock);
+}
+
+static void
+bnx2_remote_phy_event(struct bnx2 *bp)
+{
+	u32 msg;
+	u8 link_up = bp->link_up;
+	u8 old_port;
+
+	msg = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS);
+
+	if (msg & BNX2_LINK_STATUS_HEART_BEAT_EXPIRED)
+		bnx2_send_heart_beat(bp);
+
+	msg &= ~BNX2_LINK_STATUS_HEART_BEAT_EXPIRED;
+
+	if ((msg & BNX2_LINK_STATUS_LINK_UP) == BNX2_LINK_STATUS_LINK_DOWN)
+		bp->link_up = 0;
+	else {
+		u32 speed;
+
+		bp->link_up = 1;
+		speed = msg & BNX2_LINK_STATUS_SPEED_MASK;
+		bp->duplex = DUPLEX_FULL;
+		switch (speed) {
+			case BNX2_LINK_STATUS_10HALF:
+				bp->duplex = DUPLEX_HALF;
+			case BNX2_LINK_STATUS_10FULL:
+				bp->line_speed = SPEED_10;
+				break;
+			case BNX2_LINK_STATUS_100HALF:
+				bp->duplex = DUPLEX_HALF;
+			case BNX2_LINK_STATUS_100BASE_T4:
+			case BNX2_LINK_STATUS_100FULL:
+				bp->line_speed = SPEED_100;
+				break;
+			case BNX2_LINK_STATUS_1000HALF:
+				bp->duplex = DUPLEX_HALF;
+			case BNX2_LINK_STATUS_1000FULL:
+				bp->line_speed = SPEED_1000;
+				break;
+			case BNX2_LINK_STATUS_2500HALF:
+				bp->duplex = DUPLEX_HALF;
+			case BNX2_LINK_STATUS_2500FULL:
+				bp->line_speed = SPEED_2500;
+				break;
+			default:
+				bp->line_speed = 0;
+				break;
+		}
+
+		spin_lock(&bp->phy_lock);
+		bp->flow_ctrl = 0;
+		if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) !=
+		    (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) {
+			if (bp->duplex == DUPLEX_FULL)
+				bp->flow_ctrl = bp->req_flow_ctrl;
+		} else {
+			if (msg & BNX2_LINK_STATUS_TX_FC_ENABLED)
+				bp->flow_ctrl |= FLOW_CTRL_TX;
+			if (msg & BNX2_LINK_STATUS_RX_FC_ENABLED)
+				bp->flow_ctrl |= FLOW_CTRL_RX;
+		}
+
+		old_port = bp->phy_port;
+		if (msg & BNX2_LINK_STATUS_SERDES_LINK)
+			bp->phy_port = PORT_FIBRE;
+		else
+			bp->phy_port = PORT_TP;
+
+		if (old_port != bp->phy_port)
+			bnx2_set_default_link(bp);
+
+		spin_unlock(&bp->phy_lock);
+	}
+	if (bp->link_up != link_up)
+		bnx2_report_link(bp);
+
+	bnx2_set_mac_link(bp);
+}
+
+static int
+bnx2_set_remote_link(struct bnx2 *bp)
+{
+	u32 evt_code;
+
+	evt_code = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_EVT_CODE_MB);
+	switch (evt_code) {
+		case BNX2_FW_EVT_CODE_LINK_EVENT:
+			bnx2_remote_phy_event(bp);
+			break;
+		case BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT:
+		default:
+			bnx2_send_heart_beat(bp);
+			break;
+	}
+	return 0;
+}
+
 static int
 bnx2_setup_copper_phy(struct bnx2 *bp)
 {
@@ -1433,13 +1694,13 @@
 }
 
 static int
-bnx2_setup_phy(struct bnx2 *bp)
+bnx2_setup_phy(struct bnx2 *bp, u8 port)
 {
 	if (bp->loopback == MAC_LOOPBACK)
 		return 0;
 
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
-		return (bnx2_setup_serdes_phy(bp));
+		return (bnx2_setup_serdes_phy(bp, port));
 	}
 	else {
 		return (bnx2_setup_copper_phy(bp));
@@ -1659,6 +1920,9 @@
 
         REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
 
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		goto setup_phy;
+
 	bnx2_read_phy(bp, MII_PHYSID1, &val);
 	bp->phy_id = val << 16;
 	bnx2_read_phy(bp, MII_PHYSID2, &val);
@@ -1676,7 +1940,9 @@
 		rc = bnx2_init_copper_phy(bp);
 	}
 
-	bnx2_setup_phy(bp);
+setup_phy:
+	if (!rc)
+		rc = bnx2_setup_phy(bp, bp->phy_port);
 
 	return rc;
 }
@@ -1984,6 +2250,9 @@
 		bnx2_set_link(bp);
 		spin_unlock(&bp->phy_lock);
 	}
+	if (bnx2_phy_event_is_set(bp, STATUS_ATTN_BITS_TIMER_ABORT))
+		bnx2_set_remote_link(bp);
+
 }
 
 static void
@@ -2297,6 +2566,7 @@
 {
 	struct net_device *dev = dev_instance;
 	struct bnx2 *bp = netdev_priv(dev);
+	struct status_block *sblk = bp->status_blk;
 
 	/* When using INTx, it is possible for the interrupt to arrive
 	 * at the CPU before the status block posted prior to the
@@ -2304,7 +2574,7 @@
 	 * When using MSI, the MSI message will always complete after
 	 * the status block write.
 	 */
-	if ((bp->status_blk->status_idx == bp->last_status_idx) &&
+	if ((sblk->status_idx == bp->last_status_idx) &&
 	    (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
 	     BNX2_PCICFG_MISC_STATUS_INTA_VALUE))
 		return IRQ_NONE;
@@ -2313,16 +2583,25 @@
 		BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
 		BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
 
+	/* Read back to deassert IRQ immediately to avoid too many
+	 * spurious interrupts.
+	 */
+	REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
+
 	/* Return here if interrupt is shared and is disabled. */
 	if (unlikely(atomic_read(&bp->intr_sem) != 0))
 		return IRQ_HANDLED;
 
-	netif_rx_schedule(dev);
+	if (netif_rx_schedule_prep(dev)) {
+		bp->last_status_idx = sblk->status_idx;
+		__netif_rx_schedule(dev);
+	}
 
 	return IRQ_HANDLED;
 }
 
-#define STATUS_ATTN_EVENTS	STATUS_ATTN_BITS_LINK_STATE
+#define STATUS_ATTN_EVENTS	(STATUS_ATTN_BITS_LINK_STATE | \
+				 STATUS_ATTN_BITS_TIMER_ABORT)
 
 static inline int
 bnx2_has_work(struct bnx2 *bp)
@@ -3562,6 +3841,36 @@
 	return rc;
 }
 
+static void
+bnx2_init_remote_phy(struct bnx2 *bp)
+{
+	u32 val;
+
+	bp->phy_flags &= ~REMOTE_PHY_CAP_FLAG;
+	if (!(bp->phy_flags & PHY_SERDES_FLAG))
+		return;
+
+	val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_CAP_MB);
+	if ((val & BNX2_FW_CAP_SIGNATURE_MASK) != BNX2_FW_CAP_SIGNATURE)
+		return;
+
+	if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) {
+		if (netif_running(bp->dev)) {
+			val = BNX2_DRV_ACK_CAP_SIGNATURE |
+			      BNX2_FW_CAP_REMOTE_PHY_CAPABLE;
+			REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB,
+				   val);
+		}
+		bp->phy_flags |= REMOTE_PHY_CAP_FLAG;
+
+		val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS);
+		if (val & BNX2_LINK_STATUS_SERDES_LINK)
+			bp->phy_port = PORT_FIBRE;
+		else
+			bp->phy_port = PORT_TP;
+	}
+}
+
 static int
 bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
 {
@@ -3642,6 +3951,12 @@
 	if (rc)
 		return rc;
 
+	spin_lock_bh(&bp->phy_lock);
+	bnx2_init_remote_phy(bp);
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		bnx2_set_default_remote_link(bp);
+	spin_unlock_bh(&bp->phy_lock);
+
 	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
 		/* Adjust the voltage regular to two steps lower.  The default
 		 * of this register is 0x0000000e. */
@@ -3826,7 +4141,7 @@
 	rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
 			  0);
 
-	REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff);
+	REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT);
 	REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
 
 	udelay(20);
@@ -4069,8 +4384,8 @@
 
 	spin_lock_bh(&bp->phy_lock);
 	bnx2_init_phy(bp);
-	spin_unlock_bh(&bp->phy_lock);
 	bnx2_set_link(bp);
+	spin_unlock_bh(&bp->phy_lock);
 	return 0;
 }
 
@@ -4600,6 +4915,9 @@
 static void
 bnx2_5708_serdes_timer(struct bnx2 *bp)
 {
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+		return;
+
 	if ((bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) == 0) {
 		bp->serdes_an_pending = 0;
 		return;
@@ -4631,7 +4949,6 @@
 bnx2_timer(unsigned long data)
 {
 	struct bnx2 *bp = (struct bnx2 *) data;
-	u32 msg;
 
 	if (!netif_running(bp->dev))
 		return;
@@ -4639,8 +4956,7 @@
 	if (atomic_read(&bp->intr_sem) != 0)
 		goto bnx2_restart_timer;
 
-	msg = (u32) ++bp->fw_drv_pulse_wr_seq;
-	REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg);
+	bnx2_send_heart_beat(bp);
 
 	bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
 
@@ -5083,17 +5399,25 @@
 bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct bnx2 *bp = netdev_priv(dev);
+	int support_serdes = 0, support_copper = 0;
 
 	cmd->supported = SUPPORTED_Autoneg;
-	if (bp->phy_flags & PHY_SERDES_FLAG) {
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) {
+		support_serdes = 1;
+		support_copper = 1;
+	} else if (bp->phy_port == PORT_FIBRE)
+		support_serdes = 1;
+	else
+		support_copper = 1;
+
+	if (support_serdes) {
 		cmd->supported |= SUPPORTED_1000baseT_Full |
 			SUPPORTED_FIBRE;
 		if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)
 			cmd->supported |= SUPPORTED_2500baseX_Full;
 
-		cmd->port = PORT_FIBRE;
 	}
-	else {
+	if (support_copper) {
 		cmd->supported |= SUPPORTED_10baseT_Half |
 			SUPPORTED_10baseT_Full |
 			SUPPORTED_100baseT_Half |
@@ -5101,9 +5425,10 @@
 			SUPPORTED_1000baseT_Full |
 			SUPPORTED_TP;
 
-		cmd->port = PORT_TP;
 	}
 
+	spin_lock_bh(&bp->phy_lock);
+	cmd->port = bp->phy_port;
 	cmd->advertising = bp->advertising;
 
 	if (bp->autoneg & AUTONEG_SPEED) {
@@ -5121,6 +5446,7 @@
 		cmd->speed = -1;
 		cmd->duplex = -1;
 	}
+	spin_unlock_bh(&bp->phy_lock);
 
 	cmd->transceiver = XCVR_INTERNAL;
 	cmd->phy_address = bp->phy_addr;
@@ -5136,6 +5462,15 @@
 	u8 req_duplex = bp->req_duplex;
 	u16 req_line_speed = bp->req_line_speed;
 	u32 advertising = bp->advertising;
+	int err = -EINVAL;
+
+	spin_lock_bh(&bp->phy_lock);
+
+	if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE)
+		goto err_out_unlock;
+
+	if (cmd->port != bp->phy_port && !(bp->phy_flags & REMOTE_PHY_CAP_FLAG))
+		goto err_out_unlock;
 
 	if (cmd->autoneg == AUTONEG_ENABLE) {
 		autoneg |= AUTONEG_SPEED;
@@ -5148,44 +5483,41 @@
 			(cmd->advertising == ADVERTISED_100baseT_Half) ||
 			(cmd->advertising == ADVERTISED_100baseT_Full)) {
 
-			if (bp->phy_flags & PHY_SERDES_FLAG)
-				return -EINVAL;
+			if (cmd->port == PORT_FIBRE)
+				goto err_out_unlock;
 
 			advertising = cmd->advertising;
 
 		} else if (cmd->advertising == ADVERTISED_2500baseX_Full) {
-			if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
-				return -EINVAL;
-		} else if (cmd->advertising == ADVERTISED_1000baseT_Full) {
+			if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) ||
+			    (cmd->port == PORT_TP))
+				goto err_out_unlock;
+		} else if (cmd->advertising == ADVERTISED_1000baseT_Full)
 			advertising = cmd->advertising;
-		}
-		else if (cmd->advertising == ADVERTISED_1000baseT_Half) {
-			return -EINVAL;
-		}
+		else if (cmd->advertising == ADVERTISED_1000baseT_Half)
+			goto err_out_unlock;
 		else {
-			if (bp->phy_flags & PHY_SERDES_FLAG) {
+			if (cmd->port == PORT_FIBRE)
 				advertising = ETHTOOL_ALL_FIBRE_SPEED;
-			}
-			else {
+			else
 				advertising = ETHTOOL_ALL_COPPER_SPEED;
-			}
 		}
 		advertising |= ADVERTISED_Autoneg;
 	}
 	else {
-		if (bp->phy_flags & PHY_SERDES_FLAG) {
+		if (cmd->port == PORT_FIBRE) {
 			if ((cmd->speed != SPEED_1000 &&
 			     cmd->speed != SPEED_2500) ||
 			    (cmd->duplex != DUPLEX_FULL))
-				return -EINVAL;
+				goto err_out_unlock;
 
 			if (cmd->speed == SPEED_2500 &&
 			    !(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
-				return -EINVAL;
+				goto err_out_unlock;
 		}
-		else if (cmd->speed == SPEED_1000) {
-			return -EINVAL;
-		}
+		else if (cmd->speed == SPEED_1000 || cmd->speed == SPEED_2500)
+			goto err_out_unlock;
+
 		autoneg &= ~AUTONEG_SPEED;
 		req_line_speed = cmd->speed;
 		req_duplex = cmd->duplex;
@@ -5197,13 +5529,12 @@
 	bp->req_line_speed = req_line_speed;
 	bp->req_duplex = req_duplex;
 
-	spin_lock_bh(&bp->phy_lock);
+	err = bnx2_setup_phy(bp, cmd->port);
 
-	bnx2_setup_phy(bp);
-
+err_out_unlock:
 	spin_unlock_bh(&bp->phy_lock);
 
-	return 0;
+	return err;
 }
 
 static void
@@ -5214,11 +5545,7 @@
 	strcpy(info->driver, DRV_MODULE_NAME);
 	strcpy(info->version, DRV_MODULE_VERSION);
 	strcpy(info->bus_info, pci_name(bp->pdev));
-	info->fw_version[0] = ((bp->fw_ver & 0xff000000) >> 24) + '0';
-	info->fw_version[2] = ((bp->fw_ver & 0xff0000) >> 16) + '0';
-	info->fw_version[4] = ((bp->fw_ver & 0xff00) >> 8) + '0';
-	info->fw_version[1] = info->fw_version[3] = '.';
-	info->fw_version[5] = 0;
+	strcpy(info->fw_version, bp->fw_version);
 }
 
 #define BNX2_REGDUMP_LEN		(32 * 1024)
@@ -5330,6 +5657,14 @@
 
 	spin_lock_bh(&bp->phy_lock);
 
+	if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) {
+		int rc;
+
+		rc = bnx2_setup_remote_phy(bp, bp->phy_port);
+		spin_unlock_bh(&bp->phy_lock);
+		return rc;
+	}
+
 	/* Force a link down visible on the other side */
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
 		bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
@@ -5543,7 +5878,7 @@
 
 	spin_lock_bh(&bp->phy_lock);
 
-	bnx2_setup_phy(bp);
+	bnx2_setup_phy(bp, bp->phy_port);
 
 	spin_unlock_bh(&bp->phy_lock);
 
@@ -5939,6 +6274,9 @@
 	case SIOCGMIIREG: {
 		u32 mii_regval;
 
+		if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+			return -EOPNOTSUPP;
+
 		if (!netif_running(dev))
 			return -EAGAIN;
 
@@ -5955,6 +6293,9 @@
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 
+		if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+			return -EOPNOTSUPP;
+
 		if (!netif_running(dev))
 			return -EAGAIN;
 
@@ -6116,7 +6457,7 @@
 {
 	struct bnx2 *bp;
 	unsigned long mem_len;
-	int rc;
+	int rc, i, j;
 	u32 reg;
 	u64 dma_mask, persist_dma_mask;
 
@@ -6273,7 +6614,35 @@
 		goto err_out_unmap;
 	}
 
-	bp->fw_ver = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV);
+	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV);
+	for (i = 0, j = 0; i < 3; i++) {
+		u8 num, k, skip0;
+
+		num = (u8) (reg >> (24 - (i * 8)));
+		for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) {
+			if (num >= k || !skip0 || k == 1) {
+				bp->fw_version[j++] = (num / k) + '0';
+				skip0 = 0;
+			}
+		}
+		if (i != 2)
+			bp->fw_version[j++] = '.';
+	}
+	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_BC_STATE_CONDITION);
+	reg &= BNX2_CONDITION_MFW_RUN_MASK;
+	if (reg != BNX2_CONDITION_MFW_RUN_UNKNOWN &&
+	    reg != BNX2_CONDITION_MFW_RUN_NONE) {
+		int i;
+		u32 addr = REG_RD_IND(bp, bp->shmem_base + BNX2_MFW_VER_PTR);
+
+		bp->fw_version[j++] = ' ';
+		for (i = 0; i < 3; i++) {
+			reg = REG_RD_IND(bp, addr + i * 4);
+			reg = swab32(reg);
+			memcpy(&bp->fw_version[j], &reg, 4);
+			j += 4;
+		}
+	}
 
 	reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER);
 	bp->mac_addr[0] = (u8) (reg >> 8);
@@ -6315,7 +6684,9 @@
 	else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
 		bp->phy_flags |= PHY_SERDES_FLAG;
 
+	bp->phy_port = PORT_TP;
 	if (bp->phy_flags & PHY_SERDES_FLAG) {
+		bp->phy_port = PORT_FIBRE;
 		bp->flags |= NO_WOL_FLAG;
 		if (CHIP_NUM(bp) != CHIP_NUM_5706) {
 			bp->phy_addr = 2;
@@ -6324,6 +6695,8 @@
 			if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
 				bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG;
 		}
+		bnx2_init_remote_phy(bp);
+
 	} else if (CHIP_NUM(bp) == CHIP_NUM_5706 ||
 		   CHIP_NUM(bp) == CHIP_NUM_5708)
 		bp->phy_flags |= PHY_CRC_FIX_FLAG;
@@ -6374,23 +6747,7 @@
 		}
 	}
 
-	bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
-	bp->req_line_speed = 0;
-	if (bp->phy_flags & PHY_SERDES_FLAG) {
-		bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
-
-		reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG);
-		reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
-		if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
-			bp->autoneg = 0;
-			bp->req_line_speed = bp->line_speed = SPEED_1000;
-			bp->req_duplex = DUPLEX_FULL;
-		}
-	}
-	else {
-		bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
-	}
-
+	bnx2_set_default_link(bp);
 	bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
 
 	init_timer(&bp->timer);
@@ -6490,10 +6847,10 @@
 	memcpy(dev->perm_addr, bp->mac_addr, 6);
 	bp->name = board_info[ent->driver_data].name;
 
+	dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 	if (CHIP_NUM(bp) == CHIP_NUM_5709)
-		dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
-	else
-		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+		dev->features |= NETIF_F_IPV6_CSUM;
+
 #ifdef BCM_VLAN
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 #endif
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 49a5de2..d8cd1af 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6338,6 +6338,8 @@
 
 #define RX_COPY_THRESH			92
 
+#define BNX2_MISC_ENABLE_DEFAULT	0x7ffffff
+
 #define DMA_READ_CHANS	5
 #define DMA_WRITE_CHANS	3
 
@@ -6537,6 +6539,7 @@
 #define PHY_INT_MODE_AUTO_POLLING_FLAG	0x100
 #define PHY_INT_MODE_LINK_READY_FLAG	0x200
 #define PHY_DIS_EARLY_DAC_FLAG		0x400
+#define REMOTE_PHY_CAP_FLAG		0x800
 
 	u32			mii_bmcr;
 	u32			mii_bmsr;
@@ -6625,6 +6628,7 @@
 	u16			req_line_speed;
 	u8			req_duplex;
 
+	u8			phy_port;
 	u8			link_up;
 
 	u16			line_speed;
@@ -6656,7 +6660,7 @@
 
 	u32			shmem_base;
 
-	u32			fw_ver;
+	char			fw_version[32];
 
 	int			pm_cap;
 	int			pcix_cap;
@@ -6770,7 +6774,7 @@
  * the firmware has timed out, the driver will assume there is no firmware
  * running and there won't be any firmware-driver synchronization during a
  * driver reset. */
-#define FW_ACK_TIME_OUT_MS                  100
+#define FW_ACK_TIME_OUT_MS                  1000
 
 
 #define BNX2_DRV_RESET_SIGNATURE		0x00000000
@@ -6788,6 +6792,7 @@
 #define BNX2_DRV_MSG_CODE_DIAG			 0x07000000
 #define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL	 0x09000000
 #define BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN		 0x0b000000
+#define BNX2_DRV_MSG_CODE_CMD_SET_LINK		 0x10000000
 
 #define BNX2_DRV_MSG_DATA			 0x00ff0000
 #define BNX2_DRV_MSG_DATA_WAIT0			 0x00010000
@@ -6836,6 +6841,7 @@
 #define BNX2_LINK_STATUS_SERDES_LINK		 (1<<20)
 #define BNX2_LINK_STATUS_PARTNER_AD_2500FULL	 (1<<21)
 #define BNX2_LINK_STATUS_PARTNER_AD_2500HALF	 (1<<22)
+#define BNX2_LINK_STATUS_HEART_BEAT_EXPIRED	 (1<<31)
 
 #define BNX2_DRV_PULSE_MB			0x00000010
 #define BNX2_DRV_PULSE_SEQ_MASK			 0x00007fff
@@ -6845,6 +6851,30 @@
  * This is used for debugging. */
 #define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE	 0x00080000
 
+#define BNX2_DRV_MB_ARG0			0x00000014
+#define BNX2_NETLINK_SET_LINK_SPEED_10HALF	 (1<<0)
+#define BNX2_NETLINK_SET_LINK_SPEED_10FULL	 (1<<1)
+#define BNX2_NETLINK_SET_LINK_SPEED_10		 \
+	(BNX2_NETLINK_SET_LINK_SPEED_10HALF |	 \
+	 BNX2_NETLINK_SET_LINK_SPEED_10FULL)
+#define BNX2_NETLINK_SET_LINK_SPEED_100HALF	 (1<<2)
+#define BNX2_NETLINK_SET_LINK_SPEED_100FULL	 (1<<3)
+#define BNX2_NETLINK_SET_LINK_SPEED_100		 \
+	(BNX2_NETLINK_SET_LINK_SPEED_100HALF |	 \
+	 BNX2_NETLINK_SET_LINK_SPEED_100FULL)
+#define BNX2_NETLINK_SET_LINK_SPEED_1GHALF	 (1<<4)
+#define BNX2_NETLINK_SET_LINK_SPEED_1GFULL	 (1<<5)
+#define BNX2_NETLINK_SET_LINK_SPEED_2G5HALF	 (1<<6)
+#define BNX2_NETLINK_SET_LINK_SPEED_2G5FULL	 (1<<7)
+#define BNX2_NETLINK_SET_LINK_SPEED_10GHALF	 (1<<8)
+#define BNX2_NETLINK_SET_LINK_SPEED_10GFULL	 (1<<9)
+#define BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG	 (1<<10)
+#define BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE	 (1<<11)
+#define BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE	 (1<<12)
+#define BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE	 (1<<13)
+#define BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED	 (1<<14)
+#define BNX2_NETLINK_SET_LINK_PHY_RESET		 (1<<15)
+
 #define BNX2_DEV_INFO_SIGNATURE			0x00000020
 #define BNX2_DEV_INFO_SIGNATURE_MAGIC		 0x44564900
 #define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK	 0xffffff00
@@ -7006,6 +7036,8 @@
 #define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK	 0xffff
 #define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE	 0x10000
 
+#define BNX2_MFW_VER_PTR			0x00000014c
+
 #define BNX2_BC_STATE_RESET_TYPE		0x000001c0
 #define BNX2_BC_STATE_RESET_TYPE_SIG		 0x00005254
 #define BNX2_BC_STATE_RESET_TYPE_SIG_MASK	 0x0000ffff
@@ -7059,12 +7091,42 @@
 #define BNX2_BC_STATE_ERR_NO_RXP		 (BNX2_BC_STATE_SIGN | 0x0600)
 #define BNX2_BC_STATE_ERR_TOO_MANY_RBUF		 (BNX2_BC_STATE_SIGN | 0x0700)
 
+#define BNX2_BC_STATE_CONDITION			0x000001c8
+#define BNX2_CONDITION_MFW_RUN_UNKNOWN		 0x00000000
+#define BNX2_CONDITION_MFW_RUN_IPMI		 0x00002000
+#define BNX2_CONDITION_MFW_RUN_UMP		 0x00004000
+#define BNX2_CONDITION_MFW_RUN_NCSI		 0x00006000
+#define BNX2_CONDITION_MFW_RUN_NONE		 0x0000e000
+#define BNX2_CONDITION_MFW_RUN_MASK		 0x0000e000
+
 #define BNX2_BC_STATE_DEBUG_CMD			0x1dc
 #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE	 0x42440000
 #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK	 0xffff0000
 #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK	 0xffff
 #define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE	 0xffff
 
+#define BNX2_FW_EVT_CODE_MB			0x354
+#define BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT 0x00000000
+#define BNX2_FW_EVT_CODE_LINK_EVENT		 0x00000001
+
+#define BNX2_DRV_ACK_CAP_MB			0x364
+#define BNX2_DRV_ACK_CAP_SIGNATURE		 0x35450000
+#define BNX2_CAPABILITY_SIGNATURE_MASK		 0xFFFF0000
+
+#define BNX2_FW_CAP_MB				0x368
+#define BNX2_FW_CAP_SIGNATURE			 0xaa550000
+#define BNX2_FW_ACK_DRV_SIGNATURE		 0x52500000
+#define BNX2_FW_CAP_SIGNATURE_MASK		 0xffff0000
+#define BNX2_FW_CAP_REMOTE_PHY_CAPABLE		 0x00000001
+#define BNX2_FW_CAP_REMOTE_PHY_PRESENT		 0x00000002
+
+#define BNX2_RPHY_SIGNATURE			0x36c
+#define BNX2_RPHY_LOAD_SIGNATURE		 0x5a5a5a5a
+
+#define BNX2_RPHY_FLAGS				0x370
+#define BNX2_RPHY_SERDES_LINK			0x374
+#define BNX2_RPHY_COPPER_LINK			0x378
+
 #define HOST_VIEW_SHMEM_BASE			0x167c00
 
 #endif
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 6287ffb..cb9cb30 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -187,7 +187,7 @@
 
 /*---------------------------- General routines -----------------------------*/
 
-const char *bond_mode_name(int mode)
+static const char *bond_mode_name(int mode)
 {
 	switch (mode) {
 	case BOND_MODE_ROUNDROBIN :
@@ -1224,7 +1224,8 @@
 
 /*---------------------------------- IOCTL ----------------------------------*/
 
-int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
+static int bond_sethwaddr(struct net_device *bond_dev,
+			  struct net_device *slave_dev)
 {
 	dprintk("bond_dev=%p\n", bond_dev);
 	dprintk("slave_dev=%p\n", slave_dev);
@@ -1390,6 +1391,11 @@
 		goto err_free;
 	}
 
+	res = netdev_set_master(slave_dev, bond_dev);
+	if (res) {
+		dprintk("Error %d calling netdev_set_master\n", res);
+		goto err_close;
+	}
 	/* open the slave since the application closed it */
 	res = dev_open(slave_dev);
 	if (res) {
@@ -1397,12 +1403,6 @@
 		goto err_restore_mac;
 	}
 
-	res = netdev_set_master(slave_dev, bond_dev);
-	if (res) {
-		dprintk("Error %d calling netdev_set_master\n", res);
-		goto err_close;
-	}
-
 	new_slave->dev = slave_dev;
 	slave_dev->priv_flags |= IFF_BONDING;
 
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index a891021..6dcbd25 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -301,13 +301,11 @@
 void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
 int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
 int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
-int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
 void bond_mii_monitor(struct net_device *bond_dev);
 void bond_loadbalance_arp_mon(struct net_device *bond_dev);
 void bond_activebackup_arp_mon(struct net_device *bond_dev);
 void bond_set_mode_ops(struct bonding *bond, int mode);
 int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
-const char *bond_mode_name(int mode);
 void bond_select_active_slave(struct bonding *bond);
 void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
 void bond_register_arp(struct bonding *);
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 80c3d8f..ab72563 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -71,27 +71,29 @@
 	QUEUES_BOUND = (1 << 3),
 };
 
+struct fl_pg_chunk {
+	struct page *page;
+	void *va;
+	unsigned int offset;
+};
+
 struct rx_desc;
 struct rx_sw_desc;
 
-struct sge_fl_page {
-	struct skb_frag_struct frag;
-	unsigned char *va;
-};
-
-struct sge_fl {			/* SGE per free-buffer list state */
-	unsigned int buf_size;	/* size of each Rx buffer */
-	unsigned int credits;	/* # of available Rx buffers */
-	unsigned int size;	/* capacity of free list */
-	unsigned int cidx;	/* consumer index */
-	unsigned int pidx;	/* producer index */
-	unsigned int gen;	/* free list generation */
-	unsigned int cntxt_id;	/* SGE context id for the free list */
-	struct sge_fl_page page;
-	struct rx_desc *desc;	/* address of HW Rx descriptor ring */
-	struct rx_sw_desc *sdesc;	/* address of SW Rx descriptor ring */
-	dma_addr_t phys_addr;	/* physical address of HW ring start */
-	unsigned long empty;	/* # of times queue ran out of buffers */
+struct sge_fl {                     /* SGE per free-buffer list state */
+	unsigned int buf_size;      /* size of each Rx buffer */
+	unsigned int credits;       /* # of available Rx buffers */
+	unsigned int size;          /* capacity of free list */
+	unsigned int cidx;          /* consumer index */
+	unsigned int pidx;          /* producer index */
+	unsigned int gen;           /* free list generation */
+	struct fl_pg_chunk pg_chunk;/* page chunk cache */
+	unsigned int use_pages;     /* whether FL uses pages or sk_buffs */
+	struct rx_desc *desc;       /* address of HW Rx descriptor ring */
+	struct rx_sw_desc *sdesc;   /* address of SW Rx descriptor ring */
+	dma_addr_t   phys_addr;     /* physical address of HW ring start */
+	unsigned int cntxt_id;      /* SGE context id for the free list */
+	unsigned long empty;        /* # of times queue ran out of buffers */
 	unsigned long alloc_failed; /* # of times buffer allocation failed */
 };
 
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 8d13796..1637800 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -101,6 +101,7 @@
 	TCB_SIZE = 128,		/* TCB size */
 	NMTUS = 16,		/* size of MTU table */
 	NCCTRL_WIN = 32,	/* # of congestion control windows */
+	PROTO_SRAM_LINES = 128, /* size of TP sram */
 };
 
 #define MAX_RX_COALESCING_LEN 16224U
@@ -124,6 +125,30 @@
 };
 
 enum {
+	TP_VERSION_MAJOR	= 1,
+	TP_VERSION_MINOR	= 0,
+	TP_VERSION_MICRO	= 44
+};
+
+#define S_TP_VERSION_MAJOR		16
+#define M_TP_VERSION_MAJOR		0xFF
+#define V_TP_VERSION_MAJOR(x)		((x) << S_TP_VERSION_MAJOR)
+#define G_TP_VERSION_MAJOR(x)		\
+	    (((x) >> S_TP_VERSION_MAJOR) & M_TP_VERSION_MAJOR)
+
+#define S_TP_VERSION_MINOR		8
+#define M_TP_VERSION_MINOR		0xFF
+#define V_TP_VERSION_MINOR(x)		((x) << S_TP_VERSION_MINOR)
+#define G_TP_VERSION_MINOR(x)		\
+	    (((x) >> S_TP_VERSION_MINOR) & M_TP_VERSION_MINOR)
+
+#define S_TP_VERSION_MICRO		0
+#define M_TP_VERSION_MICRO		0xFF
+#define V_TP_VERSION_MICRO(x)		((x) << S_TP_VERSION_MICRO)
+#define G_TP_VERSION_MICRO(x)		\
+	    (((x) >> S_TP_VERSION_MICRO) & M_TP_VERSION_MICRO)
+
+enum {
 	SGE_QSETS = 8,		/* # of SGE Tx/Rx/RspQ sets */
 	SGE_RXQ_PER_SET = 2,	/* # of Rx queues per set */
 	SGE_TXQ_PER_SET = 3	/* # of Tx queues per set */
@@ -654,6 +679,9 @@
 int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data);
 int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data);
 int t3_seeprom_wp(struct adapter *adapter, int enable);
+int t3_check_tpsram_version(struct adapter *adapter);
+int t3_check_tpsram(struct adapter *adapter, u8 *tp_ram, unsigned int size);
+int t3_set_proto_sram(struct adapter *adap, u8 *data);
 int t3_read_flash(struct adapter *adapter, unsigned int addr,
 		  unsigned int nwords, u32 *data, int byte_oriented);
 int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size);
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index d8a1f54..6fd1e52 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -43,6 +43,7 @@
 #include <linux/proc_fs.h>
 #include <linux/rtnetlink.h>
 #include <linux/firmware.h>
+#include <linux/log2.h>
 #include <asm/uaccess.h>
 
 #include "common.h"
@@ -1818,8 +1819,8 @@
 			return -EBUSY;
 		if (copy_from_user(&m, useraddr, sizeof(m)))
 			return -EFAULT;
-		if (!m.rx_pg_sz || (m.rx_pg_sz & (m.rx_pg_sz - 1)) ||
-			!m.tx_pg_sz || (m.tx_pg_sz & (m.tx_pg_sz - 1)))
+		if (!is_power_of_2(m.rx_pg_sz) ||
+			!is_power_of_2(m.tx_pg_sz))
 			return -EINVAL;	/* not power of 2 */
 		if (!(m.rx_pg_sz & 0x14000))
 			return -EINVAL;	/* not 16KB or 64KB */
@@ -2088,6 +2089,42 @@
 }
 #endif
 
+#define TPSRAM_NAME "t3%c_protocol_sram-%d.%d.%d.bin"
+int update_tpsram(struct adapter *adap)
+{
+	const struct firmware *tpsram;
+	char buf[64];
+	struct device *dev = &adap->pdev->dev;
+	int ret;
+	char rev;
+	
+	rev = adap->params.rev == T3_REV_B2 ? 'b' : 'a';
+
+	snprintf(buf, sizeof(buf), TPSRAM_NAME, rev,
+		 TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
+
+	ret = request_firmware(&tpsram, buf, dev);
+	if (ret < 0) {
+		dev_err(dev, "could not load TP SRAM: unable to load %s\n",
+			buf);
+		return ret;
+	}
+	
+	ret = t3_check_tpsram(adap, tpsram->data, tpsram->size);
+	if (ret)
+		goto release_tpsram;	
+
+	ret = t3_set_proto_sram(adap, tpsram->data);
+	if (ret)
+		dev_err(dev, "loading protocol SRAM failed\n");
+
+release_tpsram:
+	release_firmware(tpsram);
+	
+	return ret;
+}
+
+
 /*
  * Periodic accumulation of MAC statistics.
  */
@@ -2437,6 +2474,13 @@
 		goto out_free_dev;
 	}
 
+	err = t3_check_tpsram_version(adapter);
+	if (err == -EINVAL)
+		err = update_tpsram(adapter);
+
+	if (err)
+		goto out_free_dev;
+		
 	/*
 	 * The card is now ready to go.  If any errors occur during device
 	 * registration we do not fail the whole card but rather proceed only
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index 020859c..aa80313 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -1160,6 +1160,8 @@
 
 #define A_TP_MOD_CHANNEL_WEIGHT 0x434
 
+#define A_TP_MOD_RATE_LIMIT 0x438
+
 #define A_TP_PIO_ADDR 0x440
 
 #define A_TP_PIO_DATA 0x444
@@ -1214,6 +1216,15 @@
 #define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \
 			       M_TXDROPCNTCH0RCVD)
 
+#define A_TP_PROXY_FLOW_CNTL 0x4b0
+
+#define A_TP_EMBED_OP_FIELD0 0x4e8
+#define A_TP_EMBED_OP_FIELD1 0x4ec
+#define A_TP_EMBED_OP_FIELD2 0x4f0
+#define A_TP_EMBED_OP_FIELD3 0x4f4
+#define A_TP_EMBED_OP_FIELD4 0x4f8
+#define A_TP_EMBED_OP_FIELD5 0x4fc
+
 #define A_ULPRX_CTL 0x500
 
 #define S_ROUND_ROBIN    4
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index a60ec4d..a2cfd68 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -46,23 +46,16 @@
 
 #define SGE_RX_SM_BUF_SIZE 1536
 
-/*
- * If USE_RX_PAGE is defined, the small freelist populated with (partial)
- * pages instead of skbs. Pages are carved up into RX_PAGE_SIZE chunks (must
- * be a multiple of the host page size).
- */
-#define USE_RX_PAGE
-#define RX_PAGE_SIZE 2048
-
-/*
- * skb freelist packets are copied into a new skb (and the freelist one is 
- * reused) if their len is <= 
- */
 #define SGE_RX_COPY_THRES  256
+#define SGE_RX_PULL_LEN    128
 
 /*
- * Minimum number of freelist entries before we start dropping TUNNEL frames.
+ * Page chunk size for FL0 buffers if FL0 is to be populated with page chunks.
+ * It must be a divisor of PAGE_SIZE.  If set to 0 FL0 will use sk_buffs
+ * directly.
  */
+#define FL0_PG_CHUNK_SIZE  2048
+
 #define SGE_RX_DROP_THRES 16
 
 /*
@@ -100,12 +93,12 @@
 	struct sk_buff *skb;
 };
 
-struct rx_sw_desc {		/* SW state per Rx descriptor */
+struct rx_sw_desc {                /* SW state per Rx descriptor */
 	union {
 		struct sk_buff *skb;
-		struct sge_fl_page page;
-	} t;
-	 DECLARE_PCI_UNMAP_ADDR(dma_addr);
+		struct fl_pg_chunk pg_chunk;
+	};
+	DECLARE_PCI_UNMAP_ADDR(dma_addr);
 };
 
 struct rsp_desc {		/* response queue descriptor */
@@ -351,27 +344,26 @@
 
 		pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr),
 				 q->buf_size, PCI_DMA_FROMDEVICE);
-
-		if (q->buf_size != RX_PAGE_SIZE) {
-			kfree_skb(d->t.skb);
-			d->t.skb = NULL;
+		if (q->use_pages) {
+			put_page(d->pg_chunk.page);
+			d->pg_chunk.page = NULL;
 		} else {
-			if (d->t.page.frag.page)
-				put_page(d->t.page.frag.page);
-			d->t.page.frag.page = NULL;
+			kfree_skb(d->skb);
+			d->skb = NULL;
 		}
 		if (++cidx == q->size)
 			cidx = 0;
 	}
 
-	if (q->page.frag.page)
-		put_page(q->page.frag.page);
-	q->page.frag.page = NULL;
+	if (q->pg_chunk.page) {
+		__free_page(q->pg_chunk.page);
+		q->pg_chunk.page = NULL;
+	}
 }
 
 /**
  *	add_one_rx_buf - add a packet buffer to a free-buffer list
- *	@va: va of the buffer to add
+ *	@va:  buffer start VA
  *	@len: the buffer length
  *	@d: the HW Rx descriptor to write
  *	@sd: the SW Rx descriptor to write
@@ -381,7 +373,7 @@
  *	Add a buffer of the given length to the supplied HW and SW Rx
  *	descriptors.
  */
-static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
+static inline void add_one_rx_buf(void *va, unsigned int len,
 				  struct rx_desc *d, struct rx_sw_desc *sd,
 				  unsigned int gen, struct pci_dev *pdev)
 {
@@ -397,6 +389,27 @@
 	d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
 }
 
+static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp)
+{
+	if (!q->pg_chunk.page) {
+		q->pg_chunk.page = alloc_page(gfp);
+		if (unlikely(!q->pg_chunk.page))
+			return -ENOMEM;
+		q->pg_chunk.va = page_address(q->pg_chunk.page);
+		q->pg_chunk.offset = 0;
+	}
+	sd->pg_chunk = q->pg_chunk;
+
+	q->pg_chunk.offset += q->buf_size;
+	if (q->pg_chunk.offset == PAGE_SIZE)
+		q->pg_chunk.page = NULL;
+	else {
+		q->pg_chunk.va += q->buf_size;
+		get_page(q->pg_chunk.page);
+	}
+	return 0;
+}
+
 /**
  *	refill_fl - refill an SGE free-buffer list
  *	@adapter: the adapter
@@ -410,49 +423,29 @@
  */
 static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
 {
+	void *buf_start;
 	struct rx_sw_desc *sd = &q->sdesc[q->pidx];
 	struct rx_desc *d = &q->desc[q->pidx];
-	struct sge_fl_page *p = &q->page;
 
 	while (n--) {
-		unsigned char *va;
-
-		if (unlikely(q->buf_size != RX_PAGE_SIZE)) {
-			struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
-
-			if (!skb) {
-				q->alloc_failed++;
+		if (q->use_pages) {
+			if (unlikely(alloc_pg_chunk(q, sd, gfp))) {
+nomem:				q->alloc_failed++;
 				break;
 			}
-			va = skb->data;
-			sd->t.skb = skb;
+			buf_start = sd->pg_chunk.va;
 		} else {
-			if (!p->frag.page) {
-				p->frag.page = alloc_pages(gfp, 0);
-				if (unlikely(!p->frag.page)) {
-					q->alloc_failed++;
-					break;
-				} else {
-					p->frag.size = RX_PAGE_SIZE;
-					p->frag.page_offset = 0;
-					p->va = page_address(p->frag.page);
-				}
-			}
+			struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
 
-			memcpy(&sd->t, p, sizeof(*p));
-			va = p->va;
+			if (!skb)
+				goto nomem;
 
-			p->frag.page_offset += RX_PAGE_SIZE;
-			BUG_ON(p->frag.page_offset > PAGE_SIZE);
-			p->va += RX_PAGE_SIZE;
-			if (p->frag.page_offset == PAGE_SIZE)
-				p->frag.page = NULL;
-			else
-				get_page(p->frag.page);
+			sd->skb = skb;
+			buf_start = skb->data;
 		}
 
-		add_one_rx_buf(va, q->buf_size, d, sd, q->gen, adap->pdev);
-
+		add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen,
+			       adap->pdev);
 		d++;
 		sd++;
 		if (++q->pidx == q->size) {
@@ -487,7 +480,7 @@
 	struct rx_desc *from = &q->desc[idx];
 	struct rx_desc *to = &q->desc[q->pidx];
 
-	memcpy(&q->sdesc[q->pidx], &q->sdesc[idx], sizeof(struct rx_sw_desc));
+	q->sdesc[q->pidx] = q->sdesc[idx];
 	to->addr_lo = from->addr_lo;	/* already big endian */
 	to->addr_hi = from->addr_hi;	/* likewise */
 	wmb();
@@ -650,6 +643,132 @@
 }
 
 /**
+ *	get_packet - return the next ingress packet buffer from a free list
+ *	@adap: the adapter that received the packet
+ *	@fl: the SGE free list holding the packet
+ *	@len: the packet length including any SGE padding
+ *	@drop_thres: # of remaining buffers before we start dropping packets
+ *
+ *	Get the next packet from a free list and complete setup of the
+ *	sk_buff.  If the packet is small we make a copy and recycle the
+ *	original buffer, otherwise we use the original buffer itself.  If a
+ *	positive drop threshold is supplied packets are dropped and their
+ *	buffers recycled if (a) the number of remaining buffers is under the
+ *	threshold and the packet is too big to copy, or (b) the packet should
+ *	be copied but there is no memory for the copy.
+ */
+static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
+				  unsigned int len, unsigned int drop_thres)
+{
+	struct sk_buff *skb = NULL;
+	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+
+	prefetch(sd->skb->data);
+	fl->credits--;
+
+	if (len <= SGE_RX_COPY_THRES) {
+		skb = alloc_skb(len, GFP_ATOMIC);
+		if (likely(skb != NULL)) {
+			__skb_put(skb, len);
+			pci_dma_sync_single_for_cpu(adap->pdev,
+					    pci_unmap_addr(sd, dma_addr), len,
+					    PCI_DMA_FROMDEVICE);
+			memcpy(skb->data, sd->skb->data, len);
+			pci_dma_sync_single_for_device(adap->pdev,
+					    pci_unmap_addr(sd, dma_addr), len,
+					    PCI_DMA_FROMDEVICE);
+		} else if (!drop_thres)
+			goto use_orig_buf;
+recycle:
+		recycle_rx_buf(adap, fl, fl->cidx);
+		return skb;
+	}
+
+	if (unlikely(fl->credits < drop_thres))
+		goto recycle;
+
+use_orig_buf:
+	pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
+			 fl->buf_size, PCI_DMA_FROMDEVICE);
+	skb = sd->skb;
+	skb_put(skb, len);
+	__refill_fl(adap, fl);
+	return skb;
+}
+
+/**
+ *	get_packet_pg - return the next ingress packet buffer from a free list
+ *	@adap: the adapter that received the packet
+ *	@fl: the SGE free list holding the packet
+ *	@len: the packet length including any SGE padding
+ *	@drop_thres: # of remaining buffers before we start dropping packets
+ *
+ *	Get the next packet from a free list populated with page chunks.
+ *	If the packet is small we make a copy and recycle the original buffer,
+ *	otherwise we attach the original buffer as a page fragment to a fresh
+ *	sk_buff.  If a positive drop threshold is supplied packets are dropped
+ *	and their buffers recycled if (a) the number of remaining buffers is
+ *	under the threshold and the packet is too big to copy, or (b) there's
+ *	no system memory.
+ *
+ * 	Note: this function is similar to @get_packet but deals with Rx buffers
+ * 	that are page chunks rather than sk_buffs.
+ */
+static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl,
+				     unsigned int len, unsigned int drop_thres)
+{
+	struct sk_buff *skb = NULL;
+	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+
+	if (len <= SGE_RX_COPY_THRES) {
+		skb = alloc_skb(len, GFP_ATOMIC);
+		if (likely(skb != NULL)) {
+			__skb_put(skb, len);
+			pci_dma_sync_single_for_cpu(adap->pdev,
+					    pci_unmap_addr(sd, dma_addr), len,
+					    PCI_DMA_FROMDEVICE);
+			memcpy(skb->data, sd->pg_chunk.va, len);
+			pci_dma_sync_single_for_device(adap->pdev,
+					    pci_unmap_addr(sd, dma_addr), len,
+					    PCI_DMA_FROMDEVICE);
+		} else if (!drop_thres)
+			return NULL;
+recycle:
+		fl->credits--;
+		recycle_rx_buf(adap, fl, fl->cidx);
+		return skb;
+	}
+
+	if (unlikely(fl->credits <= drop_thres))
+		goto recycle;
+
+	skb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC);
+	if (unlikely(!skb)) {
+		if (!drop_thres)
+			return NULL;
+		goto recycle;
+	}
+
+	pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
+			 fl->buf_size, PCI_DMA_FROMDEVICE);
+	__skb_put(skb, SGE_RX_PULL_LEN);
+	memcpy(skb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN);
+	skb_fill_page_desc(skb, 0, sd->pg_chunk.page,
+			   sd->pg_chunk.offset + SGE_RX_PULL_LEN,
+			   len - SGE_RX_PULL_LEN);
+	skb->len = len;
+	skb->data_len = len - SGE_RX_PULL_LEN;
+	skb->truesize += skb->data_len;
+
+	fl->credits--;
+	/*
+	 * We do not refill FLs here, we let the caller do it to overlap a
+	 * prefetch.
+	 */
+	return skb;
+}
+
+/**
  *	get_imm_packet - return the next ingress packet buffer from a response
  *	@resp: the response descriptor containing the packet data
  *
@@ -1715,85 +1834,6 @@
 		netif_rx(skb);
 }
 
-#define SKB_DATA_SIZE 128
-
-static void skb_data_init(struct sk_buff *skb, struct sge_fl_page *p,
-			  unsigned int len)
-{
-	skb->len = len;
-	if (len <= SKB_DATA_SIZE) {
-		skb_copy_to_linear_data(skb, p->va, len);
-		skb->tail += len;
-		put_page(p->frag.page);
-	} else {
-		skb_copy_to_linear_data(skb, p->va, SKB_DATA_SIZE);
-		skb_shinfo(skb)->frags[0].page = p->frag.page;
-		skb_shinfo(skb)->frags[0].page_offset =
-		    p->frag.page_offset + SKB_DATA_SIZE;
-		skb_shinfo(skb)->frags[0].size = len - SKB_DATA_SIZE;
-		skb_shinfo(skb)->nr_frags = 1;
-		skb->data_len = len - SKB_DATA_SIZE;
-		skb->tail += SKB_DATA_SIZE;
-		skb->truesize += skb->data_len;
-	}
-}
-
-/**
-*      get_packet - return the next ingress packet buffer from a free list
-*      @adap: the adapter that received the packet
-*      @fl: the SGE free list holding the packet
-*      @len: the packet length including any SGE padding
-*      @drop_thres: # of remaining buffers before we start dropping packets
-*
-*      Get the next packet from a free list and complete setup of the
-*      sk_buff.  If the packet is small we make a copy and recycle the
-*      original buffer, otherwise we use the original buffer itself.  If a
-*      positive drop threshold is supplied packets are dropped and their
-*      buffers recycled if (a) the number of remaining buffers is under the
-*      threshold and the packet is too big to copy, or (b) the packet should
-*      be copied but there is no memory for the copy.
-*/
-static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
-				  unsigned int len, unsigned int drop_thres)
-{
-	struct sk_buff *skb = NULL;
-	struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
-
-	prefetch(sd->t.skb->data);
-
-	if (len <= SGE_RX_COPY_THRES) {
-		skb = alloc_skb(len, GFP_ATOMIC);
-		if (likely(skb != NULL)) {
-			struct rx_desc *d = &fl->desc[fl->cidx];
-			dma_addr_t mapping =
-			    (dma_addr_t)((u64) be32_to_cpu(d->addr_hi) << 32 |
-					 be32_to_cpu(d->addr_lo));
-
-			__skb_put(skb, len);
-			pci_dma_sync_single_for_cpu(adap->pdev, mapping, len,
-						    PCI_DMA_FROMDEVICE);
-			skb_copy_from_linear_data(sd->t.skb, skb->data, len);
-			pci_dma_sync_single_for_device(adap->pdev, mapping, len,
-						       PCI_DMA_FROMDEVICE);
-		} else if (!drop_thres)
-			goto use_orig_buf;
-recycle:
-		recycle_rx_buf(adap, fl, fl->cidx);
-		return skb;
-	}
-
-	if (unlikely(fl->credits < drop_thres))
-		goto recycle;
-
-use_orig_buf:
-	pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
-			 fl->buf_size, PCI_DMA_FROMDEVICE);
-	skb = sd->t.skb;
-	skb_put(skb, len);
-	__refill_fl(adap, fl);
-	return skb;
-}
-
 /**
  *	handle_rsp_cntrl_info - handles control information in a response
  *	@qs: the queue set corresponding to the response
@@ -1935,7 +1975,7 @@
 		} else if (flags & F_RSPD_IMM_DATA_VALID) {
 			skb = get_imm_packet(r);
 			if (unlikely(!skb)) {
-			      no_mem:
+no_mem:
 				q->next_holdoff = NOMEM_INTR_DELAY;
 				q->nomem++;
 				/* consume one credit since we tried */
@@ -1945,53 +1985,29 @@
 			q->imm_data++;
 			ethpad = 0;
 		} else if ((len = ntohl(r->len_cq)) != 0) {
-			struct sge_fl *fl =
-			    (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
+			struct sge_fl *fl;
 
-			if (fl->buf_size == RX_PAGE_SIZE) {
-				struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
-				struct sge_fl_page *p = &sd->t.page;
+			fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
+			if (fl->use_pages) {
+				void *addr = fl->sdesc[fl->cidx].pg_chunk.va;
 
-				prefetch(p->va);
-				prefetch(p->va + L1_CACHE_BYTES);
-
+				prefetch(addr);
+#if L1_CACHE_BYTES < 128
+				prefetch(addr + L1_CACHE_BYTES);
+#endif
 				__refill_fl(adap, fl);
 
-				pci_unmap_single(adap->pdev,
-						 pci_unmap_addr(sd, dma_addr),
-						 fl->buf_size,
-						 PCI_DMA_FROMDEVICE);
-
-				if (eth) {
-					if (unlikely(fl->credits <
-						     SGE_RX_DROP_THRES))
-						goto eth_recycle;
-
-					skb = alloc_skb(SKB_DATA_SIZE,
-							GFP_ATOMIC);
-					if (unlikely(!skb)) {
-eth_recycle:
-						q->rx_drops++;
-						recycle_rx_buf(adap, fl,
-							       fl->cidx);
-						goto eth_done;
-					}
-				} else {
-					skb = alloc_skb(SKB_DATA_SIZE,
-							GFP_ATOMIC);
-					if (unlikely(!skb))
-						goto no_mem;
-				}
-
-				skb_data_init(skb, p, G_RSPD_LEN(len));
-eth_done:
-				fl->credits--;
-				q->eth_pkts++;
-			} else {
-				fl->credits--;
+				skb = get_packet_pg(adap, fl, G_RSPD_LEN(len),
+						 eth ? SGE_RX_DROP_THRES : 0);
+			} else
 				skb = get_packet(adap, fl, G_RSPD_LEN(len),
 						 eth ? SGE_RX_DROP_THRES : 0);
-			}
+			if (unlikely(!skb)) {
+				if (!eth)
+					goto no_mem;
+				q->rx_drops++;
+			} else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT))
+				__skb_pull(skb, 2);
 
 			if (++fl->cidx == fl->size)
 				fl->cidx = 0;
@@ -2016,20 +2032,15 @@
 			q->credits = 0;
 		}
 
-		if (skb) {
-			/* Preserve the RSS info in csum & priority */
-			skb->csum = rss_hi;
-			skb->priority = rss_lo;
-
+		if (likely(skb != NULL)) {
 			if (eth)
 				rx_eth(adap, q, skb, ethpad);
 			else {
-				if (unlikely(r->rss_hdr.opcode ==
-					     CPL_TRACE_PKT))
-					__skb_pull(skb, ethpad);
-
-				ngathered = rx_offload(&adap->tdev, q,
-						       skb, offload_skbs,
+				/* Preserve the RSS info in csum & priority */
+				skb->csum = rss_hi;
+				skb->priority = rss_lo;
+				ngathered = rx_offload(&adap->tdev, q, skb,
+						       offload_skbs,
 						       ngathered);
 			}
 		}
@@ -2635,25 +2646,15 @@
 	q->txq[TXQ_ETH].stop_thres = nports *
 	    flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3);
 
-	if (!is_offload(adapter)) {
-#ifdef USE_RX_PAGE
-		q->fl[0].buf_size = RX_PAGE_SIZE;
+#if FL0_PG_CHUNK_SIZE > 0
+	q->fl[0].buf_size = FL0_PG_CHUNK_SIZE;
 #else
-		q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + 2 +
-		    sizeof(struct cpl_rx_pkt);
+	q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data);
 #endif
-		q->fl[1].buf_size = MAX_FRAME_SIZE + 2 +
-		    sizeof(struct cpl_rx_pkt);
-	} else {
-#ifdef USE_RX_PAGE
-		q->fl[0].buf_size = RX_PAGE_SIZE;
-#else
-		q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE +
-		    sizeof(struct cpl_rx_data);
-#endif
-		q->fl[1].buf_size = (16 * 1024) -
-		    SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
-	}
+	q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0;
+	q->fl[1].buf_size = is_offload(adapter) ?
+		(16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
+		MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt);
 
 	spin_lock(&adapter->sge.reg_lock);
 
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index fb485d0..dd3149d 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -847,6 +847,64 @@
 	return 0;
 }
 
+/**
+ *	t3_check_tpsram_version - read the tp sram version
+ *	@adapter: the adapter
+ *
+ *	Reads the protocol sram version from serial eeprom.
+ */
+int t3_check_tpsram_version(struct adapter *adapter)
+{
+	int ret;
+	u32 vers;
+	unsigned int major, minor;
+
+	/* Get version loaded in SRAM */
+	t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0);
+	ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0,
+			      1, 1, 5, 1);
+	if (ret)
+		return ret;
+	
+	vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
+
+	major = G_TP_VERSION_MAJOR(vers);
+	minor = G_TP_VERSION_MINOR(vers);
+
+	if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR) 
+		return 0;
+
+	return -EINVAL;
+}
+
+/**
+ *	t3_check_tpsram - check if provided protocol SRAM 
+ *			  is compatible with this driver
+ *	@adapter: the adapter
+ *	@tp_sram: the firmware image to write
+ *	@size: image size
+ *
+ *	Checks if an adapter's tp sram is compatible with the driver.
+ *	Returns 0 if the versions are compatible, a negative error otherwise.
+ */
+int t3_check_tpsram(struct adapter *adapter, u8 *tp_sram, unsigned int size)
+{
+	u32 csum;
+	unsigned int i;
+	const u32 *p = (const u32 *)tp_sram;
+
+	/* Verify checksum */
+	for (csum = 0, i = 0; i < size / sizeof(csum); i++)
+		csum += ntohl(p[i]);
+	if (csum != 0xffffffff) {
+		CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n",
+		       csum);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 enum fw_version_type {
 	FW_VERSION_N3,
 	FW_VERSION_T3
@@ -921,7 +979,7 @@
 /*
  *	t3_load_fw - download firmware
  *	@adapter: the adapter
- *	@fw_data: the firrware image to write
+ *	@fw_data: the firmware image to write
  *	@size: image size
  *
  *	Write the supplied firmware image to the card's serial flash.
@@ -2362,7 +2420,7 @@
 		     F_TCPCHECKSUMOFFLOAD | V_IPTTL(64));
 	t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) |
 		     F_MTUENABLE | V_WINDOWSCALEMODE(1) |
-		     V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1));
+		     V_TIMESTAMPSMODE(0) | V_SACKMODE(1) | V_SACKRX(1));
 	t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) |
 		     V_AUTOSTATE2(1) | V_AUTOSTATE1(0) |
 		     V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) |
@@ -2371,16 +2429,18 @@
 			 F_IPV6ENABLE | F_NICMODE);
 	t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814);
 	t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105);
-	t3_set_reg_field(adap, A_TP_PARA_REG6,
-			 adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND,
-			 0);
+	t3_set_reg_field(adap, A_TP_PARA_REG6, 0,
+			 adap->params.rev > 0 ? F_ENABLEESND :
+			 F_T3A_ENABLEESND);
 
 	t3_set_reg_field(adap, A_TP_PC_CONFIG,
-			 F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL,
-			 F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE |
-			 F_RXCONGESTIONMODE);
+			 F_ENABLEEPCMDAFULL,
+			 F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK |
+			 F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
 	t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0);
-
+	t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080);
+	t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000);
+	
 	if (adap->params.rev > 0) {
 		tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
 		t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO,
@@ -2390,9 +2450,10 @@
 	} else
 		t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
 
-	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0x12121212);
-	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0x12121212);
-	t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0x1212);
+	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
+	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
+	t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
+	t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000);
 }
 
 /* Desired TP timer resolution in usec */
@@ -2468,6 +2529,7 @@
 		val |= F_RXCOALESCEENABLE;
 		if (psh)
 			val |= F_RXCOALESCEPSHEN;
+		size = min(MAX_RX_COALESCING_LEN, size);
 		t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) |
 			     V_MAXRXDATA(MAX_RX_COALESCING_LEN));
 	}
@@ -2496,11 +2558,11 @@
 	 * it can accomodate max size TCP/IP headers when SACK and timestamps
 	 * are enabled and still have at least 8 bytes of payload.
 	 */
-	mtus[0] = 88;
-	mtus[1] = 256;
-	mtus[2] = 512;
-	mtus[3] = 576;
-	mtus[4] = 808;
+	mtus[1] = 88;
+	mtus[1] = 88;
+	mtus[2] = 256;
+	mtus[3] = 512;
+	mtus[4] = 576;
 	mtus[5] = 1024;
 	mtus[6] = 1280;
 	mtus[7] = 1492;
@@ -2682,6 +2744,34 @@
 	t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff);
 }
 
+/**
+ *	t3_set_proto_sram - set the contents of the protocol sram
+ *	@adapter: the adapter
+ *	@data: the protocol image
+ *
+ *	Write the contents of the protocol SRAM.
+ */
+int t3_set_proto_sram(struct adapter *adap, u8 *data)
+{
+	int i;
+	u32 *buf = (u32 *)data;
+
+	for (i = 0; i < PROTO_SRAM_LINES; i++) {
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, cpu_to_be32(*buf++));
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, cpu_to_be32(*buf++));
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, cpu_to_be32(*buf++));
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, cpu_to_be32(*buf++));
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, cpu_to_be32(*buf++));
+		
+		t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31);
+		if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1))
+			return -EIO;
+	}
+	t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0);
+
+	return 0;
+}
+
 void t3_config_trace_filter(struct adapter *adapter,
 			    const struct trace_params *tp, int filter_index,
 			    int invert, int enable)
@@ -2802,7 +2892,7 @@
 		t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0);
 		t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN |
 			     F_PORT0ACTIVE | F_ENFORCEPKT);
-		t3_write_reg(adap, A_PM1_TX_CFG, 0xc000c000);
+		t3_write_reg(adap, A_PM1_TX_CFG, 0xffffffff);
 	} else {
 		t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN);
 		t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB);
@@ -3097,7 +3187,7 @@
 	else
 		t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN);
 
-	t3_write_reg(adapter, A_PM1_RX_CFG, 0xf000f000);
+	t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff);
 	init_hw_for_avail_ports(adapter, adapter->params.nports);
 	t3_sge_init(adapter, &adapter->params.sge);
 
diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h
index b112317..8eddd23 100644
--- a/drivers/net/cxgb3/version.h
+++ b/drivers/net/cxgb3/version.h
@@ -39,6 +39,6 @@
 
 /* Firmware version */
 #define FW_VERSION_MAJOR 4
-#define FW_VERSION_MINOR 0
+#define FW_VERSION_MINOR 1
 #define FW_VERSION_MICRO 0
 #endif				/* __CHELSIO_VERSION_H */
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 74ec64a..a4ace07 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -866,9 +866,9 @@
 							    PCI_DMA_FROMDEVICE);
 				/* 16 byte align the IP header */
 				skb_reserve (skb, 2);
-				eth_copy_and_sum (skb,
+				skb_copy_to_linear_data (skb,
 						  np->rx_skbuff[entry]->data,
-						  pkt_len, 0);
+						  pkt_len);
 				skb_put (skb, pkt_len);
 				pci_dma_sync_single_for_device(np->pdev,
 				  			       desc->fraginfo &
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 60673bc..91126b9 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -34,11 +34,17 @@
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/moduleparam.h>
+#include <linux/rtnetlink.h>
+#include <net/rtnetlink.h>
+
+struct dummy_priv {
+	struct net_device *dev;
+	struct list_head list;
+};
 
 static int numdummies = 1;
 
 static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
-static struct net_device_stats *dummy_get_stats(struct net_device *dev);
 
 static int dummy_set_address(struct net_device *dev, void *p)
 {
@@ -56,13 +62,13 @@
 {
 }
 
-static void __init dummy_setup(struct net_device *dev)
+static void dummy_setup(struct net_device *dev)
 {
 	/* Initialize the device structure. */
-	dev->get_stats = dummy_get_stats;
 	dev->hard_start_xmit = dummy_xmit;
 	dev->set_multicast_list = set_multicast_list;
 	dev->set_mac_address = dummy_set_address;
+	dev->destructor = free_netdev;
 
 	/* Fill in device structure with ethernet-generic values. */
 	ether_setup(dev);
@@ -76,77 +82,114 @@
 
 static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct net_device_stats *stats = netdev_priv(dev);
-
-	stats->tx_packets++;
-	stats->tx_bytes+=skb->len;
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
 
 	dev_kfree_skb(skb);
 	return 0;
 }
 
-static struct net_device_stats *dummy_get_stats(struct net_device *dev)
+static LIST_HEAD(dummies);
+
+static int dummy_newlink(struct net_device *dev,
+			 struct nlattr *tb[], struct nlattr *data[])
 {
-	return netdev_priv(dev);
+	struct dummy_priv *priv = netdev_priv(dev);
+	int err;
+
+	err = register_netdevice(dev);
+	if (err < 0)
+		return err;
+
+	priv->dev = dev;
+	list_add_tail(&priv->list, &dummies);
+	return 0;
 }
 
-static struct net_device **dummies;
+static void dummy_dellink(struct net_device *dev)
+{
+	struct dummy_priv *priv = netdev_priv(dev);
+
+	list_del(&priv->list);
+	unregister_netdevice(dev);
+}
+
+static struct rtnl_link_ops dummy_link_ops __read_mostly = {
+	.kind		= "dummy",
+	.priv_size	= sizeof(struct dummy_priv),
+	.setup		= dummy_setup,
+	.newlink	= dummy_newlink,
+	.dellink	= dummy_dellink,
+};
 
 /* Number of dummy devices to be set up by this module. */
 module_param(numdummies, int, 0);
 MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
 
-static int __init dummy_init_one(int index)
+static int __init dummy_init_one(void)
 {
 	struct net_device *dev_dummy;
+	struct dummy_priv *priv;
 	int err;
 
-	dev_dummy = alloc_netdev(sizeof(struct net_device_stats),
-				 "dummy%d", dummy_setup);
+	dev_dummy = alloc_netdev(sizeof(struct dummy_priv), "dummy%d",
+				 dummy_setup);
 
 	if (!dev_dummy)
 		return -ENOMEM;
 
-	if ((err = register_netdev(dev_dummy))) {
-		free_netdev(dev_dummy);
-		dev_dummy = NULL;
-	} else {
-		dummies[index] = dev_dummy;
-	}
+	err = dev_alloc_name(dev_dummy, dev_dummy->name);
+	if (err < 0)
+		goto err;
 
+	dev_dummy->rtnl_link_ops = &dummy_link_ops;
+	err = register_netdevice(dev_dummy);
+	if (err < 0)
+		goto err;
+
+	priv = netdev_priv(dev_dummy);
+	priv->dev = dev_dummy;
+	list_add_tail(&priv->list, &dummies);
+	return 0;
+
+err:
+	free_netdev(dev_dummy);
 	return err;
 }
 
-static void dummy_free_one(int index)
-{
-	unregister_netdev(dummies[index]);
-	free_netdev(dummies[index]);
-}
-
 static int __init dummy_init_module(void)
 {
+	struct dummy_priv *priv, *next;
 	int i, err = 0;
-	dummies = kmalloc(numdummies * sizeof(void *), GFP_KERNEL);
-	if (!dummies)
-		return -ENOMEM;
+
+	rtnl_lock();
+	err = __rtnl_link_register(&dummy_link_ops);
+
 	for (i = 0; i < numdummies && !err; i++)
-		err = dummy_init_one(i);
-	if (err) {
-		i--;
-		while (--i >= 0)
-			dummy_free_one(i);
+		err = dummy_init_one();
+	if (err < 0) {
+		list_for_each_entry_safe(priv, next, &dummies, list)
+			dummy_dellink(priv->dev);
+		__rtnl_link_unregister(&dummy_link_ops);
 	}
+	rtnl_unlock();
+
 	return err;
 }
 
 static void __exit dummy_cleanup_module(void)
 {
-	int i;
-	for (i = 0; i < numdummies; i++)
-		dummy_free_one(i);
-	kfree(dummies);
+	struct dummy_priv *priv, *next;
+
+	rtnl_lock();
+	list_for_each_entry_safe(priv, next, &dummies, list)
+		dummy_dellink(priv->dev);
+
+	__rtnl_link_unregister(&dummy_link_ops);
+	rtnl_unlock();
 }
 
 module_init(dummy_init_module);
 module_exit(dummy_cleanup_module);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_RTNL_LINK("dummy");
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 763810c..74ea637 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -159,7 +159,7 @@
 
 #define DRV_NAME		"e100"
 #define DRV_EXT			"-NAPI"
-#define DRV_VERSION		"3.5.17-k4"DRV_EXT
+#define DRV_VERSION		"3.5.23-k4"DRV_EXT
 #define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
 #define DRV_COPYRIGHT		"Copyright(c) 1999-2006 Intel Corporation"
 #define PFX			DRV_NAME ": "
@@ -1024,10 +1024,16 @@
 		config->mwi_enable = 0x1;	/* 1=enable, 0=disable */
 		config->standard_tcb = 0x0;	/* 1=standard, 0=extended */
 		config->rx_long_ok = 0x1;	/* 1=VLANs ok, 0=standard */
-		if(nic->mac >= mac_82559_D101M)
+		if (nic->mac >= mac_82559_D101M) {
 			config->tno_intr = 0x1;		/* TCO stats enable */
-		else
+			/* Enable TCO in extended config */
+			if (nic->mac >= mac_82551_10) {
+				config->byte_count = 0x20; /* extended bytes */
+				config->rx_d102_mode = 0x1; /* GMRC for TCO */
+			}
+		} else {
 			config->standard_stat_counter = 0x0;
+		}
 	}
 
 	DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 98003419..9afa47e 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -1801,7 +1801,7 @@
 
 #if 1 || USE_IP_CSUM
 				/* Packet is in one chunk -- we can copy + cksum. */
-				eth_copy_and_sum(skb, sp->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb, sp->rx_skbuff[entry]->data, pkt_len);
 				skb_put(skb, pkt_len);
 #else
 				skb_copy_from_linear_data(sp->rx_skbuff[entry],
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index c0f81b5..f03f070 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,7 +39,13 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"ehea"
-#define DRV_VERSION	"EHEA_0064"
+#define DRV_VERSION	"EHEA_0067"
+
+/* EHEA capability flags */
+#define DLPAR_PORT_ADD_REM 1
+#define DLPAR_MEM_ADD 2
+#define DLPAR_MEM_REM 4
+#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM)
 
 #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
 	| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@@ -136,10 +142,10 @@
 	(0xffffffffffffffffULL >> ((64 - (mask)) & 0xffff))
 
 #define EHEA_BMASK_SET(mask, value) \
-        ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
+	((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
 
 #define EHEA_BMASK_GET(mask, value) \
-        (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
+	(EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
 
 /*
  * Generic ehea page
@@ -190,7 +196,7 @@
  * Queue attributes passed to ehea_create_qp()
  */
 struct ehea_qp_init_attr {
-        /* input parameter */
+	/* input parameter */
 	u32 qp_token;           /* queue token */
 	u8 low_lat_rq1;
 	u8 signalingtype;       /* cqe generation flag */
@@ -212,7 +218,7 @@
 	u64 recv_cq_handle;
 	u64 aff_eq_handle;
 
-        /* output parameter */
+	/* output parameter */
 	u32 qp_nr;
 	u16 act_nr_send_wqes;
 	u16 act_nr_rwqes_rq1;
@@ -279,12 +285,12 @@
  * Completion Queue attributes
  */
 struct ehea_cq_attr {
-        /* input parameter */
+	/* input parameter */
 	u32 max_nr_of_cqes;
 	u32 cq_token;
 	u64 eq_handle;
 
-        /* output parameter */
+	/* output parameter */
 	u32 act_nr_of_cqes;
 	u32 nr_pages;
 };
diff --git a/drivers/net/ehea/ehea_hw.h b/drivers/net/ehea/ehea_hw.h
index 1246757..1af7ca4 100644
--- a/drivers/net/ehea/ehea_hw.h
+++ b/drivers/net/ehea/ehea_hw.h
@@ -211,34 +211,34 @@
 }
 
 #define epa_store_eq(epa, offset, value)\
-        epa_store(epa, EQTEMM_OFFSET(offset), value)
+	epa_store(epa, EQTEMM_OFFSET(offset), value)
 #define epa_load_eq(epa, offset)\
-        epa_load(epa, EQTEMM_OFFSET(offset))
+	epa_load(epa, EQTEMM_OFFSET(offset))
 
 #define epa_store_cq(epa, offset, value)\
-        epa_store(epa, CQTEMM_OFFSET(offset), value)
+	epa_store(epa, CQTEMM_OFFSET(offset), value)
 #define epa_load_cq(epa, offset)\
-        epa_load(epa, CQTEMM_OFFSET(offset))
+	epa_load(epa, CQTEMM_OFFSET(offset))
 
 #define epa_store_qp(epa, offset, value)\
-        epa_store(epa, QPTEMM_OFFSET(offset), value)
+	epa_store(epa, QPTEMM_OFFSET(offset), value)
 #define epa_load_qp(epa, offset)\
-        epa_load(epa, QPTEMM_OFFSET(offset))
+	epa_load(epa, QPTEMM_OFFSET(offset))
 
 #define epa_store_qped(epa, offset, value)\
-        epa_store(epa, QPEDMM_OFFSET(offset), value)
+	epa_store(epa, QPEDMM_OFFSET(offset), value)
 #define epa_load_qped(epa, offset)\
-        epa_load(epa, QPEDMM_OFFSET(offset))
+	epa_load(epa, QPEDMM_OFFSET(offset))
 
 #define epa_store_mrmw(epa, offset, value)\
-        epa_store(epa, MRMWMM_OFFSET(offset), value)
+	epa_store(epa, MRMWMM_OFFSET(offset), value)
 #define epa_load_mrmw(epa, offset)\
-        epa_load(epa, MRMWMM_OFFSET(offset))
+	epa_load(epa, MRMWMM_OFFSET(offset))
 
 #define epa_store_base(epa, offset, value)\
-        epa_store(epa, HCAGR_OFFSET(offset), value)
+	epa_store(epa, HCAGR_OFFSET(offset), value)
 #define epa_load_base(epa, offset)\
-        epa_load(epa, HCAGR_OFFSET(offset))
+	epa_load(epa, HCAGR_OFFSET(offset))
 
 static inline void ehea_update_sqa(struct ehea_qp *qp, u16 nr_wqes)
 {
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 9e13433..383144d 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -81,7 +81,7 @@
 static int port_name_cnt = 0;
 
 static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
-                                        const struct of_device_id *id);
+					const struct of_device_id *id);
 
 static int __devexit ehea_remove(struct ibmebus_dev *dev);
 
@@ -236,7 +236,7 @@
 
 		rwqe = ehea_get_next_rwqe(qp, rq_nr);
 		rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
-		            | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
+			    | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
 		rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
 		rwqe->sg_list[0].vaddr = (u64)skb->data;
 		rwqe->sg_list[0].len = packet_size;
@@ -427,7 +427,7 @@
 						break;
 				}
 				skb_copy_to_linear_data(skb, ((char*)cqe) + 64,
-					       cqe->num_bytes_transfered - 4);
+						 cqe->num_bytes_transfered - 4);
 				ehea_fill_skb(port->netdev, skb, cqe);
 			} else if (rq == 2) {  /* RQ2 */
 				skb = get_skb_by_index(skb_arr_rq2,
@@ -618,7 +618,7 @@
 
 	for (i = 0; i < EHEA_MAX_PORTS; i++)
 		if (adapter->port[i])
-	                if (adapter->port[i]->logical_port_id == logical_port)
+			if (adapter->port[i]->logical_port_id == logical_port)
 				return adapter->port[i];
 	return NULL;
 }
@@ -1695,6 +1695,7 @@
 {
 	if (skb->protocol == htons(ETH_P_IP)) {
 		const struct iphdr *iph = ip_hdr(skb);
+
 		/* IPv4 */
 		swqe->tx_control |= EHEA_SWQE_CRC
 				 | EHEA_SWQE_IP_CHECKSUM
@@ -1705,13 +1706,12 @@
 		write_ip_start_end(swqe, skb);
 
 		if (iph->protocol == IPPROTO_UDP) {
-			if ((iph->frag_off & IP_MF) ||
-			    (iph->frag_off & IP_OFFSET))
+			if ((iph->frag_off & IP_MF)
+			    || (iph->frag_off & IP_OFFSET))
 				/* IP fragment, so don't change cs */
 				swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
 			else
 				write_udp_offset_end(swqe, skb);
-
 		} else if (iph->protocol == IPPROTO_TCP) {
 			write_tcp_offset_end(swqe, skb);
 		}
@@ -1739,6 +1739,7 @@
 
 	if (skb->protocol == htons(ETH_P_IP)) {
 		const struct iphdr *iph = ip_hdr(skb);
+
 		/* IPv4 */
 		write_ip_start_end(swqe, skb);
 
@@ -1751,8 +1752,8 @@
 			write_tcp_offset_end(swqe, skb);
 
 		} else if (iph->protocol == IPPROTO_UDP) {
-			if ((iph->frag_off & IP_MF) ||
-			    (iph->frag_off & IP_OFFSET))
+			if ((iph->frag_off & IP_MF)
+			    || (iph->frag_off & IP_OFFSET))
 				/* IP fragment, so don't change cs */
 				swqe->tx_control |= EHEA_SWQE_CRC
 						 | EHEA_SWQE_IMM_DATA_PRESENT;
@@ -2407,7 +2408,7 @@
 }
 
 static int ehea_driver_sysfs_add(struct device *dev,
-                                 struct device_driver *driver)
+				 struct device_driver *driver)
 {
 	int ret;
 
@@ -2424,7 +2425,7 @@
 }
 
 static void ehea_driver_sysfs_remove(struct device *dev,
-                                     struct device_driver *driver)
+				     struct device_driver *driver)
 {
 	struct device_driver *drv = driver;
 
@@ -2453,7 +2454,7 @@
 	}
 
 	ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id);
-        if (ret) {
+	if (ret) {
 		ehea_error("failed to register attributes, ret=%d", ret);
 		goto out_unreg_of_dev;
 	}
@@ -2601,6 +2602,7 @@
 {
 	struct device_node *lhea_dn;
 	struct device_node *eth_dn = NULL;
+
 	const u32 *dn_log_port_id;
 	int i = 0;
 
@@ -2608,7 +2610,7 @@
 	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
 
 		dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
-						    NULL);
+						 NULL);
 		if (!dn_log_port_id) {
 			ehea_error("bad device node: eth_dn name=%s",
 				   eth_dn->full_name);
@@ -2648,7 +2650,7 @@
 	while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
 
 		dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
-						    NULL);
+						 NULL);
 		if (dn_log_port_id)
 			if (*dn_log_port_id == logical_port_id)
 				return eth_dn;
@@ -2789,7 +2791,7 @@
 	adapter->ebus_dev = dev;
 
 	adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
-					    NULL);
+					 NULL);
 	if (adapter_handle)
 		adapter->handle = *adapter_handle;
 
@@ -2921,6 +2923,15 @@
 	return ret;
 }
 
+static ssize_t ehea_show_capabilities(struct device_driver *drv,
+				      char *buf)
+{
+	return sprintf(buf, "%d", EHEA_CAPABILITIES);
+}
+
+static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH,
+		   ehea_show_capabilities, NULL);
+
 int __init ehea_module_init(void)
 {
 	int ret;
@@ -2932,8 +2943,19 @@
 	if (ret)
 		goto out;
 	ret = ibmebus_register_driver(&ehea_driver);
-	if (ret)
+	if (ret) {
 		ehea_error("failed registering eHEA device driver on ebus");
+		goto out;
+	}
+
+	ret = driver_create_file(&ehea_driver.driver,
+				 &driver_attr_capabilities);
+	if (ret) {
+		ehea_error("failed to register capabilities attribute, ret=%d",
+			   ret);
+		ibmebus_unregister_driver(&ehea_driver);
+		goto out;
+	}
 
 out:
 	return ret;
@@ -2941,6 +2963,7 @@
 
 static void __exit ehea_module_exit(void)
 {
+	driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
 	ibmebus_unregister_driver(&ehea_driver);
 }
 
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index f24a886..29eaa46 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -211,7 +211,7 @@
 	u64 hret;
 	u64 adapter_handle = cq->adapter->handle;
 
-        /* deregister all previous registered pages */
+	/* deregister all previous registered pages */
 	hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force);
 	if (hret != H_SUCCESS)
 		return hret;
@@ -362,7 +362,7 @@
 	if (hret != H_SUCCESS) {
 		ehea_error("destroy EQ failed");
 		return -EIO;
-        }
+	}
 
 	return 0;
 }
@@ -507,44 +507,44 @@
 
 u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
 {
-        u64 hret;
-        struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
+	u64 hret;
+	struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
 
 
-        ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
-        hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
-        if (hret != H_SUCCESS)
-                return hret;
+	ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
+	hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
+	if (hret != H_SUCCESS)
+		return hret;
 
-        hw_queue_dtor(&qp->hw_squeue);
-        hw_queue_dtor(&qp->hw_rqueue1);
+	hw_queue_dtor(&qp->hw_squeue);
+	hw_queue_dtor(&qp->hw_rqueue1);
 
-        if (qp_attr->rq_count > 1)
-                hw_queue_dtor(&qp->hw_rqueue2);
-        if (qp_attr->rq_count > 2)
-                hw_queue_dtor(&qp->hw_rqueue3);
-        kfree(qp);
+	if (qp_attr->rq_count > 1)
+		hw_queue_dtor(&qp->hw_rqueue2);
+	if (qp_attr->rq_count > 2)
+		hw_queue_dtor(&qp->hw_rqueue3);
+	kfree(qp);
 
-        return hret;
+	return hret;
 }
 
 int ehea_destroy_qp(struct ehea_qp *qp)
 {
-        u64 hret;
-        if (!qp)
-                return 0;
+	u64 hret;
+	if (!qp)
+		return 0;
 
-        if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
-                ehea_error_data(qp->adapter, qp->fw_handle);
-                hret = ehea_destroy_qp_res(qp, FORCE_FREE);
-        }
+	if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
+		ehea_error_data(qp->adapter, qp->fw_handle);
+		hret = ehea_destroy_qp_res(qp, FORCE_FREE);
+	}
 
-        if (hret != H_SUCCESS) {
-                ehea_error("destroy QP failed");
-                return -EIO;
-        }
+	if (hret != H_SUCCESS) {
+		ehea_error("destroy QP failed");
+		return -EIO;
+	}
 
-        return 0;
+	return 0;
 }
 
 int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 5e51794..1197784 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -1201,7 +1201,7 @@
 							    ep->rx_ring[entry].bufaddr,
 							    ep->rx_buf_sz,
 							    PCI_DMA_FROMDEVICE);
-				eth_copy_and_sum(skb, ep->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb, ep->rx_skbuff[entry]->data, pkt_len);
 				skb_put(skb, pkt_len);
 				pci_dma_sync_single_for_device(ep->pci_dev,
 							       ep->rx_ring[entry].bufaddr,
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index abe9b08..ff9f177 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -1727,8 +1727,8 @@
 				/* Call copy + cksum if available. */
 
 #if ! defined(__alpha__)
-				eth_copy_and_sum(skb,
-					np->cur_rx->skbuff->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb,
+					np->cur_rx->skbuff->data, pkt_len);
 				skb_put(skb, pkt_len);
 #else
 				memcpy(skb_put(skb, pkt_len),
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 255b091..03023dd 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -648,7 +648,7 @@
 		fep->stats.rx_dropped++;
 	} else {
 		skb_put(skb,pkt_len-4);	/* Make room */
-		eth_copy_and_sum(skb, data, pkt_len-4, 0);
+		skb_copy_to_linear_data(skb, data, pkt_len-4);
 		skb->protocol=eth_type_trans(skb,dev);
 		netif_rx(skb);
 	}
diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig
index a84c232..afb34de 100644
--- a/drivers/net/fec_8xx/Kconfig
+++ b/drivers/net/fec_8xx/Kconfig
@@ -1,6 +1,6 @@
 config FEC_8XX
 	tristate "Motorola 8xx FEC driver"
-	depends on NET_ETHERNET && 8xx
+	depends on 8XX
 	select MII
 
 config FEC_8XX_GENERIC_PHY
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index 6aaee67..e27ee21 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -1,6 +1,6 @@
 config FS_ENET
        tristate "Freescale Ethernet Driver"
-       depends on NET_ETHERNET && (CPM1 || CPM2)
+       depends on CPM1 || CPM2
        select MII
 
 config FS_ENET_HAS_SCC
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 1b854bf..d7a1a58 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -130,6 +130,9 @@
 static void free_skb_resources(struct gfar_private *priv);
 static void gfar_set_multi(struct net_device *dev);
 static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
+static void gfar_configure_serdes(struct net_device *dev);
+extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value);
+extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum);
 #ifdef CONFIG_GFAR_NAPI
 static int gfar_poll(struct net_device *dev, int *budget);
 #endif
@@ -451,6 +454,9 @@
 
 	phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface);
 
+	if (interface == PHY_INTERFACE_MODE_SGMII)
+		gfar_configure_serdes(dev);
+
 	if (IS_ERR(phydev)) {
 		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
 		return PTR_ERR(phydev);
@@ -465,6 +471,27 @@
 	return 0;
 }
 
+static void gfar_configure_serdes(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar_mii __iomem *regs =
+			(void __iomem *)&priv->regs->gfar_mii_regs;
+
+	/* Initialise TBI i/f to communicate with serdes (lynx phy) */
+
+	/* Single clk mode, mii mode off(for aerdes communication) */
+	gfar_local_mdio_write(regs, TBIPA_VALUE, MII_TBICON, TBICON_CLK_SELECT);
+
+	/* Supported pause and full-duplex, no half-duplex */
+	gfar_local_mdio_write(regs, TBIPA_VALUE, MII_ADVERTISE,
+			ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
+			ADVERTISE_1000XPSE_ASYM);
+
+	/* ANEG enable, restart ANEG, full duplex mode, speed[1] set */
+	gfar_local_mdio_write(regs, TBIPA_VALUE, MII_BMCR, BMCR_ANENABLE |
+			BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
+}
+
 static void init_registers(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 39e9e32..d8e779c 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -136,6 +136,12 @@
 #define MIIMCFG_RESET           0x80000000
 #define MIIMIND_BUSY            0x00000001
 
+/* TBI register addresses */
+#define MII_TBICON		0x11
+
+/* TBICON register bit fields */
+#define TBICON_CLK_SELECT	0x0020
+
 /* MAC register bits */
 #define MACCFG1_SOFT_RESET	0x80000000
 #define MACCFG1_RESET_RX_MC	0x00080000
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index bcc6b82..5dd34a1 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -43,13 +43,18 @@
 #include "gianfar.h"
 #include "gianfar_mii.h"
 
-/* Write value to the PHY at mii_id at register regnum,
- * on the bus, waiting until the write is done before returning.
- * All PHY configuration is done through the TSEC1 MIIM regs */
-int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+/*
+ * Write value to the PHY at mii_id at register regnum,
+ * on the bus attached to the local interface, which may be different from the
+ * generic mdio bus (tied to a single interface), waiting until the write is
+ * done before returning. This is helpful in programming interfaces like
+ * the TBI which control interfaces like onchip SERDES and are always tied to
+ * the local mdio pins, which may not be the same as system mdio bus, used for
+ * controlling the external PHYs, for example.
+ */
+int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id,
+			  int regnum, u16 value)
 {
-	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
-
 	/* Set the PHY address and the register address we want to write */
 	gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
 
@@ -63,12 +68,19 @@
 	return 0;
 }
 
-/* Read the bus for PHY at addr mii_id, register regnum, and
- * return the value.  Clears miimcom first.  All PHY
- * configuration has to be done through the TSEC1 MIIM regs */
-int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+/*
+ * Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value.  Clears miimcom first.  All PHY operation
+ * done on the bus attached to the local interface,
+ * which may be different from the generic mdio bus
+ * This is helpful in programming interfaces like
+ * the TBI which, inturn, control interfaces like onchip SERDES
+ * and are always tied to the local mdio pins, which may not be the
+ * same as system mdio bus, used for controlling the external PHYs, for eg.
+ */
+int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum)
+
 {
-	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
 	u16 value;
 
 	/* Set the PHY address and the register address we want to read */
@@ -88,6 +100,27 @@
 	return value;
 }
 
+/* Write value to the PHY at mii_id at register regnum,
+ * on the bus, waiting until the write is done before returning.
+ * All PHY configuration is done through the TSEC1 MIIM regs */
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+
+	/* Write to the local MII regs */
+	return(gfar_local_mdio_write(regs, mii_id, regnum, value));
+}
+
+/* Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value.  Clears miimcom first.  All PHY
+ * configuration has to be done through the TSEC1 MIIM regs */
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+
+	/* Read the local MII regs */
+	return(gfar_local_mdio_read(regs, mii_id, regnum));
+}
 
 /* Reset the MIIM registers, and wait for the bus to free */
 int gfar_mdio_reset(struct mii_bus *bus)
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 2521b11..15254dc 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -1575,8 +1575,8 @@
 							    PCI_DMA_FROMDEVICE);
 				/* Call copy + cksum if available. */
 #if 1 || USE_IP_COPYSUM
-				eth_copy_and_sum(skb,
-					hmp->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb,
+					hmp->rx_skbuff[entry]->data, pkt_len);
 				skb_put(skb, pkt_len);
 #else
 				memcpy(skb_put(skb, pkt_len), hmp->rx_ring_dma
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 07b4c0d..669ee1a 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -33,12 +33,15 @@
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/moduleparam.h>
+#include <linux/list.h>
 #include <net/pkt_sched.h>
 
 #define TX_TIMEOUT  (2*HZ)
 
 #define TX_Q_LIMIT    32
 struct ifb_private {
+	struct list_head	list;
+	struct net_device	*dev;
 	struct net_device_stats stats;
 	struct tasklet_struct   ifb_tasklet;
 	int     tasklet_pending;
@@ -136,13 +139,14 @@
 
 }
 
-static void __init ifb_setup(struct net_device *dev)
+static void ifb_setup(struct net_device *dev)
 {
 	/* Initialize the device structure. */
 	dev->get_stats = ifb_get_stats;
 	dev->hard_start_xmit = ifb_xmit;
 	dev->open = &ifb_open;
 	dev->stop = &ifb_close;
+	dev->destructor = free_netdev;
 
 	/* Fill in device structure with ethernet-generic values. */
 	ether_setup(dev);
@@ -197,7 +201,7 @@
 	return stats;
 }
 
-static struct net_device **ifbs;
+static LIST_HEAD(ifbs);
 
 /* Number of ifb devices to be set up by this module. */
 module_param(numifbs, int, 0);
@@ -226,9 +230,41 @@
 	return 0;
 }
 
+static int ifb_newlink(struct net_device *dev,
+		       struct nlattr *tb[], struct nlattr *data[])
+{
+	struct ifb_private *priv = netdev_priv(dev);
+	int err;
+
+	err = register_netdevice(dev);
+	if (err < 0)
+		return err;
+
+	priv->dev = dev;
+	list_add_tail(&priv->list, &ifbs);
+	return 0;
+}
+
+static void ifb_dellink(struct net_device *dev)
+{
+	struct ifb_private *priv = netdev_priv(dev);
+
+	list_del(&priv->list);
+	unregister_netdevice(dev);
+}
+
+static struct rtnl_link_ops ifb_link_ops __read_mostly = {
+	.kind		= "ifb",
+	.priv_size	= sizeof(struct ifb_private),
+	.setup		= ifb_setup,
+	.newlink	= ifb_newlink,
+	.dellink	= ifb_dellink,
+};
+
 static int __init ifb_init_one(int index)
 {
 	struct net_device *dev_ifb;
+	struct ifb_private *priv;
 	int err;
 
 	dev_ifb = alloc_netdev(sizeof(struct ifb_private),
@@ -237,49 +273,59 @@
 	if (!dev_ifb)
 		return -ENOMEM;
 
-	if ((err = register_netdev(dev_ifb))) {
-		free_netdev(dev_ifb);
-		dev_ifb = NULL;
-	} else {
-		ifbs[index] = dev_ifb;
-	}
+	err = dev_alloc_name(dev_ifb, dev_ifb->name);
+	if (err < 0)
+		goto err;
 
+	dev_ifb->rtnl_link_ops = &ifb_link_ops;
+	err = register_netdevice(dev_ifb);
+	if (err < 0)
+		goto err;
+
+	priv = netdev_priv(dev_ifb);
+	priv->dev = dev_ifb;
+	list_add_tail(&priv->list, &ifbs);
+	return 0;
+
+err:
+	free_netdev(dev_ifb);
 	return err;
 }
 
-static void ifb_free_one(int index)
-{
-	unregister_netdev(ifbs[index]);
-	free_netdev(ifbs[index]);
-}
-
 static int __init ifb_init_module(void)
 {
-	int i, err = 0;
-	ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL);
-	if (!ifbs)
-		return -ENOMEM;
+	struct ifb_private *priv, *next;
+	int i, err;
+
+	rtnl_lock();
+	err = __rtnl_link_register(&ifb_link_ops);
+
 	for (i = 0; i < numifbs && !err; i++)
 		err = ifb_init_one(i);
 	if (err) {
-		i--;
-		while (--i >= 0)
-			ifb_free_one(i);
+		list_for_each_entry_safe(priv, next, &ifbs, list)
+			ifb_dellink(priv->dev);
+		__rtnl_link_unregister(&ifb_link_ops);
 	}
+	rtnl_unlock();
 
 	return err;
 }
 
 static void __exit ifb_cleanup_module(void)
 {
-	int i;
+	struct ifb_private *priv, *next;
 
-	for (i = 0; i < numifbs; i++)
-		ifb_free_one(i);
-	kfree(ifbs);
+	rtnl_lock();
+	list_for_each_entry_safe(priv, next, &ifbs, list)
+		ifb_dellink(priv->dev);
+
+	__rtnl_link_unregister(&ifb_link_ops);
+	rtnl_unlock();
 }
 
 module_init(ifb_init_module);
 module_exit(ifb_cleanup_module);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jamal Hadi Salim");
+MODULE_ALIAS_RTNL_LINK("ifb");
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index f749e07..3ca1e8e 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -352,13 +352,12 @@
 
 static int nic_init(struct ioc3 *ioc3)
 {
-	const char *type;
+	const char *unknown = "unknown";
+	const char *type = unknown;
 	u8 crc;
 	u8 serial[6];
 	int save = 0, i;
 
-	type = "unknown";
-
 	while (1) {
 		u64 reg;
 		reg = nic_find(ioc3, &save);
@@ -392,7 +391,7 @@
 	}
 
 	printk("Found %s NIC", type);
-	if (type != "unknown") {
+	if (type != unknown) {
 		printk (" registration number %02x:%02x:%02x:%02x:%02x:%02x,"
 			" CRC %02x", serial[0], serial[1], serial[2],
 			serial[3], serial[4], serial[5], crc);
@@ -1103,20 +1102,28 @@
  * MiniDINs; all other subdevices are left swinging in the wind, leave
  * them disabled.
  */
-static inline int ioc3_is_menet(struct pci_dev *pdev)
-{
-	struct pci_dev *dev;
 
-	return pdev->bus->parent == NULL
-	       && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(0, 0)))
-	       && dev->vendor == PCI_VENDOR_ID_SGI
-	       && dev->device == PCI_DEVICE_ID_SGI_IOC3
-	       && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(1, 0)))
-	       && dev->vendor == PCI_VENDOR_ID_SGI
-	       && dev->device == PCI_DEVICE_ID_SGI_IOC3
-	       && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(2, 0)))
-	       && dev->vendor == PCI_VENDOR_ID_SGI
-	       && dev->device == PCI_DEVICE_ID_SGI_IOC3;
+static int ioc3_adjacent_is_ioc3(struct pci_dev *pdev, int slot)
+{
+	struct pci_dev *dev = pci_get_slot(pdev->bus, PCI_DEVFN(slot, 0));
+	int ret = 0;
+
+	if (dev) {
+		if (dev->vendor == PCI_VENDOR_ID_SGI &&
+			dev->device == PCI_DEVICE_ID_SGI_IOC3)
+			ret = 1;
+		pci_dev_put(dev);
+	}
+
+	return ret;
+}
+
+static int ioc3_is_menet(struct pci_dev *pdev)
+{
+	return pdev->bus->parent == NULL &&
+	       ioc3_adjacent_is_ioc3(pdev, 0) &&
+	       ioc3_adjacent_is_ioc3(pdev, 1) &&
+	       ioc3_adjacent_is_ioc3(pdev, 2);
 }
 
 #ifdef CONFIG_SERIAL_8250
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
index 2174291..bdd5c97 100644
--- a/drivers/net/irda/kingsun-sir.c
+++ b/drivers/net/irda/kingsun-sir.c
@@ -4,7 +4,7 @@
 * Version:       0.1.1
 * Description:   Irda KingSun/DonShine USB Dongle
 * Status:        Experimental
-* Author:        Alex Villac�s Lasso <a_villacis@palosanto.com>
+* Author:        Alex Villacís Lasso <a_villacis@palosanto.com>
 *
 *  	Based on stir4200 and mcs7780 drivers, with (strange?) differences
 *
@@ -652,6 +652,6 @@
 }
 module_exit(kingsun_cleanup);
 
-MODULE_AUTHOR("Alex Villac�s Lasso <a_villacis@palosanto.com>");
+MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
 MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine");
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index bf78ef1..0538ca9 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -44,6 +44,7 @@
 #include <linux/time.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
@@ -1660,8 +1661,8 @@
 	idev = ndev->priv;
 
 	spin_lock_init(&idev->lock);
-	init_MUTEX(&idev->sem);
-	down(&idev->sem);
+	mutex_init(&idev->mtx);
+	mutex_lock(&idev->mtx);
 	idev->pdev = pdev;
 
 	if (vlsi_irda_init(ndev) < 0)
@@ -1689,12 +1690,12 @@
 	IRDA_MESSAGE("%s: registered device %s\n", drivername, ndev->name);
 
 	pci_set_drvdata(pdev, ndev);
-	up(&idev->sem);
+	mutex_unlock(&idev->mtx);
 
 	return 0;
 
 out_freedev:
-	up(&idev->sem);
+	mutex_unlock(&idev->mtx);
 	free_netdev(ndev);
 out_disable:
 	pci_disable_device(pdev);
@@ -1716,12 +1717,12 @@
 	unregister_netdev(ndev);
 
 	idev = ndev->priv;
-	down(&idev->sem);
+	mutex_lock(&idev->mtx);
 	if (idev->proc_entry) {
 		remove_proc_entry(ndev->name, vlsi_proc_root);
 		idev->proc_entry = NULL;
 	}
-	up(&idev->sem);
+	mutex_unlock(&idev->mtx);
 
 	free_netdev(ndev);
 
@@ -1751,7 +1752,7 @@
 		return 0;
 	}
 	idev = ndev->priv;	
-	down(&idev->sem);
+	mutex_lock(&idev->mtx);
 	if (pdev->current_state != 0) {			/* already suspended */
 		if (state.event > pdev->current_state) {	/* simply go deeper */
 			pci_set_power_state(pdev, pci_choose_state(pdev, state));
@@ -1759,7 +1760,7 @@
 		}
 		else
 			IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, pci_name(pdev), pdev->current_state, state.event);
-		up(&idev->sem);
+		mutex_unlock(&idev->mtx);
 		return 0;
 	}
 
@@ -1775,7 +1776,7 @@
 	pci_set_power_state(pdev, pci_choose_state(pdev, state));
 	pdev->current_state = state.event;
 	idev->resume_ok = 1;
-	up(&idev->sem);
+	mutex_unlock(&idev->mtx);
 	return 0;
 }
 
@@ -1790,9 +1791,9 @@
 		return 0;
 	}
 	idev = ndev->priv;	
-	down(&idev->sem);
+	mutex_lock(&idev->mtx);
 	if (pdev->current_state == 0) {
-		up(&idev->sem);
+		mutex_unlock(&idev->mtx);
 		IRDA_WARNING("%s - %s: already resumed\n",
 			     __FUNCTION__, pci_name(pdev));
 		return 0;
@@ -1814,7 +1815,7 @@
 		 * device and independently resume_ok should catch any garbage config.
 		 */
 		IRDA_WARNING("%s - hm, nothing to resume?\n", __FUNCTION__);
-		up(&idev->sem);
+		mutex_unlock(&idev->mtx);
 		return 0;
 	}
 
@@ -1824,7 +1825,7 @@
 		netif_device_attach(ndev);
 	}
 	idev->resume_ok = 0;
-	up(&idev->sem);
+	mutex_unlock(&idev->mtx);
 	return 0;
 }
 
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index 2d3b773..ca12a60 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -728,7 +728,7 @@
 	struct timeval		last_rx;
 
 	spinlock_t		lock;
-	struct semaphore	sem;
+	struct mutex		mtx;
 
 	u8			resume_ok;	
 	struct proc_dir_entry	*proc_entry;
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index d5f694f..d9ce1ae 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -111,7 +111,7 @@
 		skb = dev_alloc_skb(desc->pkt_length + 2);
 		if (likely(skb != NULL)) {
 			skb_reserve(skb, 2);
-			eth_copy_and_sum(skb, buf, desc->pkt_length, 0);
+			skb_copy_to_linear_data(skb, buf, desc->pkt_length);
 			skb_put(skb, desc->pkt_length);
 			skb->protocol = eth_type_trans(skb, nds[desc->channel]);
 
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 0fe96c8..a2f37e5 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -1186,9 +1186,9 @@
 				}
 				skb_reserve(skb,2);	/* 16 byte align */
 				skb_put(skb,pkt_len);	/* Make room */
-				eth_copy_and_sum(skb,
+				skb_copy_to_linear_data(skb,
 					(unsigned char *)isa_bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)),
-					pkt_len,0);
+					pkt_len);
 				skb->protocol=eth_type_trans(skb,dev);
 				netif_rx(skb);
 				dev->last_rx = jiffies;
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 741780e..efbae4b 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -86,93 +86,36 @@
 #include <linux/dma-mapping.h>
 
 #include <asm/io.h>
-#include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/pdc.h>
-#include <asm/cache.h>
 #include <asm/parisc-device.h>
 
 #define LASI_82596_DRIVER_VERSION "LASI 82596 driver - Revision: 1.30"
 
-/* DEBUG flags
- */
-
-#define DEB_INIT	0x0001
-#define DEB_PROBE	0x0002
-#define DEB_SERIOUS	0x0004
-#define DEB_ERRORS	0x0008
-#define DEB_MULTI	0x0010
-#define DEB_TDR		0x0020
-#define DEB_OPEN	0x0040
-#define DEB_RESET	0x0080
-#define DEB_ADDCMD	0x0100
-#define DEB_STATUS	0x0200
-#define DEB_STARTTX	0x0400
-#define DEB_RXADDR	0x0800
-#define DEB_TXADDR	0x1000
-#define DEB_RXFRAME	0x2000
-#define DEB_INTS	0x4000
-#define DEB_STRUCT	0x8000
-#define DEB_ANY		0xffff
-
-
-#define DEB(x,y)	if (i596_debug & (x)) { y; }
-
-
-#define  CHECK_WBACK(priv, addr,len) \
-	do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_TO_DEVICE); } while (0)
-
-#define  CHECK_INV(priv, addr,len) \
-	do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_FROM_DEVICE); } while(0)
-
-#define  CHECK_WBACK_INV(priv, addr,len) \
-	do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
-
-
 #define PA_I82596_RESET		0	/* Offsets relative to LASI-LAN-Addr.*/
 #define PA_CPU_PORT_L_ACCESS	4
 #define PA_CHANNEL_ATTENTION	8
 
+#define OPT_SWAP_PORT	0x0001	/* Need to wordswp on the MPU port */
 
-/*
- * Define various macros for Channel Attention, word swapping etc., dependent
- * on architecture.  MVME and BVME are 680x0 based, otherwise it is Intel.
- */
+#define DMA_ALLOC                        dma_alloc_noncoherent
+#define DMA_FREE                         dma_free_noncoherent
+#define DMA_WBACK(ndev, addr, len) \
+	do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_TO_DEVICE); } while (0)
 
-#ifdef __BIG_ENDIAN
-#define WSWAPrfd(x)  (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPrbd(x)  (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPiscp(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPscb(x)  (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPcmd(x)  (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPtbd(x)  (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPchar(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define ISCP_BUSY	0x00010000
-#define MACH_IS_APRICOT	0
-#else
-#define WSWAPrfd(x)     ((struct i596_rfd *)(x))
-#define WSWAPrbd(x)     ((struct i596_rbd *)(x))
-#define WSWAPiscp(x)    ((struct i596_iscp *)(x))
-#define WSWAPscb(x)     ((struct i596_scb *)(x))
-#define WSWAPcmd(x)     ((struct i596_cmd *)(x))
-#define WSWAPtbd(x)     ((struct i596_tbd *)(x))
-#define WSWAPchar(x)    ((char *)(x))
-#define ISCP_BUSY	0x0001
-#define MACH_IS_APRICOT	1
-#endif
+#define DMA_INV(ndev, addr, len) \
+	do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_FROM_DEVICE); } while (0)
 
-/*
- * The MPU_PORT command allows direct access to the 82596. With PORT access
- * the following commands are available (p5-18). The 32-bit port command
- * must be word-swapped with the most significant word written first.
- * This only applies to VME boards.
- */
-#define PORT_RESET		0x00	/* reset 82596 */
-#define PORT_SELFTEST		0x01	/* selftest */
-#define PORT_ALTSCP		0x02	/* alternate SCB address */
-#define PORT_ALTDUMP		0x03	/* Alternate DUMP address */
+#define DMA_WBACK_INV(ndev, addr, len) \
+	do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
 
-static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+#define SYSBUS      0x0000006c;
+
+/* big endian CPU, 82596 "big" endian mode */
+#define SWAP32(x)   (((u32)(x)<<16) | ((((u32)(x)))>>16))
+#define SWAP16(x)   (x)
+
+#include "lib82596.c"
 
 MODULE_AUTHOR("Richard Hirst");
 MODULE_DESCRIPTION("i82596 driver");
@@ -180,255 +123,15 @@
 module_param(i596_debug, int, 0);
 MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask");
 
-/* Copy frames shorter than rx_copybreak, otherwise pass on up in
- * a full sized sk_buff.  Value of 100 stolen from tulip.c (!alpha).
- */
-static int rx_copybreak = 100;
-
-#define MAX_DRIVERS	4	/* max count of drivers */
-
-#define PKT_BUF_SZ	1536
-#define MAX_MC_CNT	64
-
-#define I596_NULL ((u32)0xffffffff)
-
-#define CMD_EOL		0x8000	/* The last command of the list, stop. */
-#define CMD_SUSP	0x4000	/* Suspend after doing cmd. */
-#define CMD_INTR	0x2000	/* Interrupt after doing cmd. */
-
-#define CMD_FLEX	0x0008	/* Enable flexible memory model */
-
-enum commands {
-	CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
-	CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
-};
-
-#define STAT_C		0x8000	/* Set to 0 after execution */
-#define STAT_B		0x4000	/* Command being executed */
-#define STAT_OK		0x2000	/* Command executed ok */
-#define STAT_A		0x1000	/* Command aborted */
-
-#define	 CUC_START	0x0100
-#define	 CUC_RESUME	0x0200
-#define	 CUC_SUSPEND    0x0300
-#define	 CUC_ABORT	0x0400
-#define	 RX_START	0x0010
-#define	 RX_RESUME	0x0020
-#define	 RX_SUSPEND	0x0030
-#define	 RX_ABORT	0x0040
-
-#define TX_TIMEOUT	5
-
-#define OPT_SWAP_PORT	0x0001	/* Need to wordswp on the MPU port */
-
-
-struct i596_reg {
-	unsigned short porthi;
-	unsigned short portlo;
-	u32            ca;
-};
-
-#define EOF		0x8000
-#define SIZE_MASK	0x3fff
-
-struct i596_tbd {
-	unsigned short size;
-	unsigned short pad;
-	dma_addr_t     next;
-	dma_addr_t     data;
-	u32 cache_pad[5];		/* Total 32 bytes... */
-};
-
-/* The command structure has two 'next' pointers; v_next is the address of
- * the next command as seen by the CPU, b_next is the address of the next
- * command as seen by the 82596.  The b_next pointer, as used by the 82596
- * always references the status field of the next command, rather than the
- * v_next field, because the 82596 is unaware of v_next.  It may seem more
- * logical to put v_next at the end of the structure, but we cannot do that
- * because the 82596 expects other fields to be there, depending on command
- * type.
- */
-
-struct i596_cmd {
-	struct i596_cmd *v_next;	/* Address from CPUs viewpoint */
-	unsigned short status;
-	unsigned short command;
-	dma_addr_t     b_next;	/* Address from i596 viewpoint */
-};
-
-struct tx_cmd {
-	struct i596_cmd cmd;
-	dma_addr_t     tbd;
-	unsigned short size;
-	unsigned short pad;
-	struct sk_buff *skb;		/* So we can free it after tx */
-	dma_addr_t dma_addr;
-#ifdef __LP64__
-	u32 cache_pad[6];		/* Total 64 bytes... */
-#else
-	u32 cache_pad[1];		/* Total 32 bytes... */
-#endif
-};
-
-struct tdr_cmd {
-	struct i596_cmd cmd;
-	unsigned short status;
-	unsigned short pad;
-};
-
-struct mc_cmd {
-	struct i596_cmd cmd;
-	short mc_cnt;
-	char mc_addrs[MAX_MC_CNT*6];
-};
-
-struct sa_cmd {
-	struct i596_cmd cmd;
-	char eth_addr[8];
-};
-
-struct cf_cmd {
-	struct i596_cmd cmd;
-	char i596_config[16];
-};
-
-struct i596_rfd {
-	unsigned short stat;
-	unsigned short cmd;
-	dma_addr_t     b_next;	/* Address from i596 viewpoint */
-	dma_addr_t     rbd;
-	unsigned short count;
-	unsigned short size;
-	struct i596_rfd *v_next;	/* Address from CPUs viewpoint */
-	struct i596_rfd *v_prev;
-#ifndef __LP64__
-	u32 cache_pad[2];		/* Total 32 bytes... */
-#endif
-};
-
-struct i596_rbd {
-    /* hardware data */
-    unsigned short count;
-    unsigned short zero1;
-    dma_addr_t     b_next;
-    dma_addr_t     b_data;		/* Address from i596 viewpoint */
-    unsigned short size;
-    unsigned short zero2;
-    /* driver data */
-    struct sk_buff *skb;
-    struct i596_rbd *v_next;
-    dma_addr_t     b_addr;		/* This rbd addr from i596 view */
-    unsigned char *v_data;		/* Address from CPUs viewpoint */
-					/* Total 32 bytes... */
-#ifdef __LP64__
-    u32 cache_pad[4];
-#endif
-};
-
-/* These values as chosen so struct i596_private fits in one page... */
-
-#define TX_RING_SIZE 32
-#define RX_RING_SIZE 16
-
-struct i596_scb {
-	unsigned short status;
-	unsigned short command;
-	dma_addr_t    cmd;
-	dma_addr_t    rfd;
-	u32           crc_err;
-	u32           align_err;
-	u32           resource_err;
-	u32           over_err;
-	u32           rcvdt_err;
-	u32           short_err;
-	unsigned short t_on;
-	unsigned short t_off;
-};
-
-struct i596_iscp {
-	u32           stat;
-	dma_addr_t    scb;
-};
-
-struct i596_scp {
-	u32           sysbus;
-	u32            pad;
-	dma_addr_t    iscp;
-};
-
-struct i596_private {
-	volatile struct i596_scp scp		__attribute__((aligned(32)));
-	volatile struct i596_iscp iscp		__attribute__((aligned(32)));
-	volatile struct i596_scb scb		__attribute__((aligned(32)));
-	struct sa_cmd sa_cmd			__attribute__((aligned(32)));
-	struct cf_cmd cf_cmd			__attribute__((aligned(32)));
-	struct tdr_cmd tdr_cmd			__attribute__((aligned(32)));
-	struct mc_cmd mc_cmd			__attribute__((aligned(32)));
-	struct i596_rfd rfds[RX_RING_SIZE]	__attribute__((aligned(32)));
-	struct i596_rbd rbds[RX_RING_SIZE]	__attribute__((aligned(32)));
-	struct tx_cmd tx_cmds[TX_RING_SIZE]	__attribute__((aligned(32)));
-	struct i596_tbd tbds[TX_RING_SIZE]	__attribute__((aligned(32)));
-	u32    stat;
-	int last_restart;
-	struct i596_rfd *rfd_head;
-	struct i596_rbd *rbd_head;
-	struct i596_cmd *cmd_tail;
-	struct i596_cmd *cmd_head;
-	int cmd_backlog;
-	u32    last_cmd;
-	struct net_device_stats stats;
-	int next_tx_cmd;
-	int options;
-	spinlock_t lock;
-	dma_addr_t dma_addr;
-	struct device *dev;
-};
-
-static const char init_setup[] =
-{
-	0x8E,			/* length, prefetch on */
-	0xC8,			/* fifo to 8, monitor off */
-	0x80,			/* don't save bad frames */
-	0x2E,			/* No source address insertion, 8 byte preamble */
-	0x00,			/* priority and backoff defaults */
-	0x60,			/* interframe spacing */
-	0x00,			/* slot time LSB */
-	0xf2,			/* slot time and retries */
-	0x00,			/* promiscuous mode */
-	0x00,			/* collision detect */
-	0x40,			/* minimum frame length */
-	0xff,
-	0x00,
-	0x7f /*  *multi IA */ };
-
-static int i596_open(struct net_device *dev);
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t i596_interrupt(int irq, void *dev_id);
-static int i596_close(struct net_device *dev);
-static struct net_device_stats *i596_get_stats(struct net_device *dev);
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
-static void i596_tx_timeout (struct net_device *dev);
-static void print_eth(unsigned char *buf, char *str);
-static void set_multicast_list(struct net_device *dev);
-
-static int rx_ring_size = RX_RING_SIZE;
-static int ticks_limit = 100;
-static int max_cmd_backlog = TX_RING_SIZE-1;
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void i596_poll_controller(struct net_device *dev);
-#endif
-
-
-static inline void CA(struct net_device *dev)
+static inline void ca(struct net_device *dev)
 {
 	gsc_writel(0, dev->base_addr + PA_CHANNEL_ATTENTION);
 }
 
 
-static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x)
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
 {
-	struct i596_private *lp = dev->priv;
+	struct i596_private *lp = netdev_priv(dev);
 
 	u32 v = (u32) (c) | (u32) (x);
 	u16 a, b;
@@ -446,1078 +149,15 @@
 	gsc_writel(b, dev->base_addr + PA_CPU_PORT_L_ACCESS);
 }
 
-
-static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
-	CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
-	while (--delcnt && lp->iscp.stat) {
-		udelay(10);
-		CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
-	}
-	if (!delcnt) {
-		printk("%s: %s, iscp.stat %04x, didn't clear\n",
-		     dev->name, str, lp->iscp.stat);
-		return -1;
-	}
-	else
-		return 0;
-}
-
-
-static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
-	CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
-	while (--delcnt && lp->scb.command) {
-		udelay(10);
-		CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
-	}
-	if (!delcnt) {
-		printk("%s: %s, status %4.4x, cmd %4.4x.\n",
-		     dev->name, str, lp->scb.status, lp->scb.command);
-		return -1;
-	}
-	else
-		return 0;
-}
-
-
-static void i596_display_data(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	struct i596_cmd *cmd;
-	struct i596_rfd *rfd;
-	struct i596_rbd *rbd;
-
-	printk("lp and scp at %p, .sysbus = %08x, .iscp = %08x\n",
-	       &lp->scp, lp->scp.sysbus, lp->scp.iscp);
-	printk("iscp at %p, iscp.stat = %08x, .scb = %08x\n",
-	       &lp->iscp, lp->iscp.stat, lp->iscp.scb);
-	printk("scb at %p, scb.status = %04x, .command = %04x,"
-		" .cmd = %08x, .rfd = %08x\n",
-	       &lp->scb, lp->scb.status, lp->scb.command,
-		lp->scb.cmd, lp->scb.rfd);
-	printk("   errors: crc %x, align %x, resource %x,"
-               " over %x, rcvdt %x, short %x\n",
-		lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err,
-		lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err);
-	cmd = lp->cmd_head;
-	while (cmd != NULL) {
-		printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %08x\n",
-		  cmd, cmd->status, cmd->command, cmd->b_next);
-		cmd = cmd->v_next;
-	}
-	rfd = lp->rfd_head;
-	printk("rfd_head = %p\n", rfd);
-	do {
-		printk("   %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x,"
-                        " count %04x\n",
-			rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd,
-			rfd->count);
-		rfd = rfd->v_next;
-	} while (rfd != lp->rfd_head);
-	rbd = lp->rbd_head;
-	printk("rbd_head = %p\n", rbd);
-	do {
-		printk("   %p .count %04x, b_next %08x, b_data %08x, size %04x\n",
-			rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size);
-		rbd = rbd->v_next;
-	} while (rbd != lp->rbd_head);
-	CHECK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-
-#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
-static void i596_error(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
-
-	pcc2[0x28] = 1;
-	pcc2[0x2b] = 0x1d;
-	printk("%s: Error interrupt\n", dev->name);
-	i596_display_data(dev);
-}
-#endif
-
-#define virt_to_dma(lp,v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)(lp)))
-
-static inline void init_rx_bufs(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	int i;
-	struct i596_rfd *rfd;
-	struct i596_rbd *rbd;
-
-	/* First build the Receive Buffer Descriptor List */
-
-	for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
-		dma_addr_t dma_addr;
-		struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ + 4);
-
-		if (skb == NULL)
-			panic("%s: alloc_skb() failed", __FILE__);
-		skb_reserve(skb, 2);
-		dma_addr = dma_map_single(lp->dev, skb->data,PKT_BUF_SZ,
-					  DMA_FROM_DEVICE);
-		skb->dev = dev;
-		rbd->v_next = rbd+1;
-		rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1));
-		rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd));
-		rbd->skb = skb;
-		rbd->v_data = skb->data;
-		rbd->b_data = WSWAPchar(dma_addr);
-		rbd->size = PKT_BUF_SZ;
-	}
-	lp->rbd_head = lp->rbds;
-	rbd = lp->rbds + rx_ring_size - 1;
-	rbd->v_next = lp->rbds;
-	rbd->b_next = WSWAPrbd(virt_to_dma(lp,lp->rbds));
-
-	/* Now build the Receive Frame Descriptor List */
-
-	for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) {
-		rfd->rbd = I596_NULL;
-		rfd->v_next = rfd+1;
-		rfd->v_prev = rfd-1;
-		rfd->b_next = WSWAPrfd(virt_to_dma(lp,rfd+1));
-		rfd->cmd = CMD_FLEX;
-	}
-	lp->rfd_head = lp->rfds;
-	lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
-	rfd = lp->rfds;
-	rfd->rbd = WSWAPrbd(virt_to_dma(lp,lp->rbd_head));
-	rfd->v_prev = lp->rfds + rx_ring_size - 1;
-	rfd = lp->rfds + rx_ring_size - 1;
-	rfd->v_next = lp->rfds;
-	rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds));
-	rfd->cmd = CMD_EOL|CMD_FLEX;
-
-	CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-static inline void remove_rx_bufs(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	struct i596_rbd *rbd;
-	int i;
-
-	for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
-		if (rbd->skb == NULL)
-			break;
-		dma_unmap_single(lp->dev,
-				 (dma_addr_t)WSWAPchar(rbd->b_data),
-				 PKT_BUF_SZ, DMA_FROM_DEVICE);
-		dev_kfree_skb(rbd->skb);
-	}
-}
-
-
-static void rebuild_rx_bufs(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	int i;
-
-	/* Ensure rx frame/buffer descriptors are tidy */
-
-	for (i = 0; i < rx_ring_size; i++) {
-		lp->rfds[i].rbd = I596_NULL;
-		lp->rfds[i].cmd = CMD_FLEX;
-	}
-	lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;
-	lp->rfd_head = lp->rfds;
-	lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
-	lp->rbd_head = lp->rbds;
-	lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds));
-
-	CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-
-static int init_i596_mem(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	unsigned long flags;
-
-	disable_irq(dev->irq);	/* disable IRQs from LAN */
-	DEB(DEB_INIT,
-		printk("RESET 82596 port: %lx (with IRQ %d disabled)\n",
-		       (dev->base_addr + PA_I82596_RESET),
-		       dev->irq));
-
-	gsc_writel(0, (dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
-	udelay(100);			/* Wait 100us - seems to help */
-
-	/* change the scp address */
-
-	lp->last_cmd = jiffies;
-
-
-	lp->scp.sysbus = 0x0000006c;
-	lp->scp.iscp = WSWAPiscp(virt_to_dma(lp,&(lp->iscp)));
-	lp->iscp.scb = WSWAPscb(virt_to_dma(lp,&(lp->scb)));
-	lp->iscp.stat = ISCP_BUSY;
-	lp->cmd_backlog = 0;
-
-	lp->cmd_head = NULL;
-        lp->scb.cmd = I596_NULL;
-
-	DEB(DEB_INIT, printk("%s: starting i82596.\n", dev->name));
-
-	CHECK_WBACK(lp, &(lp->scp), sizeof(struct i596_scp));
-	CHECK_WBACK(lp, &(lp->iscp), sizeof(struct i596_iscp));
-
-	MPU_PORT(dev, PORT_ALTSCP, virt_to_dma(lp,&lp->scp));
-
-	CA(dev);
-
-	if (wait_istat(dev, lp, 1000, "initialization timed out"))
-		goto failed;
-	DEB(DEB_INIT, printk("%s: i82596 initialization successful\n", dev->name));
-
-	/* Ensure rx frame/buffer descriptors are tidy */
-	rebuild_rx_bufs(dev);
-
-	lp->scb.command = 0;
-	CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-
-	enable_irq(dev->irq);	/* enable IRQs from LAN */
-
-	DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name));
-	memcpy(lp->cf_cmd.i596_config, init_setup, sizeof(init_setup));
-	lp->cf_cmd.cmd.command = CmdConfigure;
-	CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd));
-	i596_add_cmd(dev, &lp->cf_cmd.cmd);
-
-	DEB(DEB_INIT, printk("%s: queuing CmdSASetup\n", dev->name));
-	memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6);
-	lp->sa_cmd.cmd.command = CmdSASetup;
-	CHECK_WBACK(lp, &(lp->sa_cmd), sizeof(struct sa_cmd));
-	i596_add_cmd(dev, &lp->sa_cmd.cmd);
-
-	DEB(DEB_INIT, printk("%s: queuing CmdTDR\n", dev->name));
-	lp->tdr_cmd.cmd.command = CmdTDR;
-	CHECK_WBACK(lp, &(lp->tdr_cmd), sizeof(struct tdr_cmd));
-	i596_add_cmd(dev, &lp->tdr_cmd.cmd);
-
-	spin_lock_irqsave (&lp->lock, flags);
-
-	if (wait_cmd(dev, lp, 1000, "timed out waiting to issue RX_START")) {
-		spin_unlock_irqrestore (&lp->lock, flags);
-		goto failed;
-	}
-	DEB(DEB_INIT, printk("%s: Issuing RX_START\n", dev->name));
-	lp->scb.command = RX_START;
-	lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
-	CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-
-	CA(dev);
-
-	spin_unlock_irqrestore (&lp->lock, flags);
-
-	if (wait_cmd(dev, lp, 1000, "RX_START not processed"))
-		goto failed;
-	DEB(DEB_INIT, printk("%s: Receive unit started OK\n", dev->name));
-
-	return 0;
-
-failed:
-	printk("%s: Failed to initialise 82596\n", dev->name);
-	MPU_PORT(dev, PORT_RESET, 0);
-	return -1;
-}
-
-
-static inline int i596_rx(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	struct i596_rfd *rfd;
-	struct i596_rbd *rbd;
-	int frames = 0;
-
-	DEB(DEB_RXFRAME, printk("i596_rx(), rfd_head %p, rbd_head %p\n",
-			lp->rfd_head, lp->rbd_head));
-
-
-	rfd = lp->rfd_head;		/* Ref next frame to check */
-
-	CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
-	while ((rfd->stat) & STAT_C) {	/* Loop while complete frames */
-		if (rfd->rbd == I596_NULL)
-			rbd = NULL;
-		else if (rfd->rbd == lp->rbd_head->b_addr) {
-			rbd = lp->rbd_head;
-			CHECK_INV(lp, rbd, sizeof(struct i596_rbd));
-		}
-		else {
-			printk("%s: rbd chain broken!\n", dev->name);
-			/* XXX Now what? */
-			rbd = NULL;
-		}
-		DEB(DEB_RXFRAME, printk("  rfd %p, rfd.rbd %08x, rfd.stat %04x\n",
-			rfd, rfd->rbd, rfd->stat));
-
-		if (rbd != NULL && ((rfd->stat) & STAT_OK)) {
-			/* a good frame */
-			int pkt_len = rbd->count & 0x3fff;
-			struct sk_buff *skb = rbd->skb;
-			int rx_in_place = 0;
-
-			DEB(DEB_RXADDR,print_eth(rbd->v_data, "received"));
-			frames++;
-
-			/* Check if the packet is long enough to just accept
-			 * without copying to a properly sized skbuff.
-			 */
-
-			if (pkt_len > rx_copybreak) {
-				struct sk_buff *newskb;
-				dma_addr_t dma_addr;
-
-				dma_unmap_single(lp->dev,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
-				/* Get fresh skbuff to replace filled one. */
-				newskb = dev_alloc_skb(PKT_BUF_SZ + 4);
-				if (newskb == NULL) {
-					skb = NULL;	/* drop pkt */
-					goto memory_squeeze;
-				}
-				skb_reserve(newskb, 2);
-
-				/* Pass up the skb already on the Rx ring. */
-				skb_put(skb, pkt_len);
-				rx_in_place = 1;
-				rbd->skb = newskb;
-				newskb->dev = dev;
-				dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE);
-				rbd->v_data = newskb->data;
-				rbd->b_data = WSWAPchar(dma_addr);
-				CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
-			}
-			else
-				skb = dev_alloc_skb(pkt_len + 2);
-memory_squeeze:
-			if (skb == NULL) {
-				/* XXX tulip.c can defer packets here!! */
-				printk("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
-				lp->stats.rx_dropped++;
-			}
-			else {
-				if (!rx_in_place) {
-					/* 16 byte align the data fields */
-					dma_sync_single_for_cpu(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
-					skb_reserve(skb, 2);
-					memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len);
-					dma_sync_single_for_device(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
-				}
-				skb->len = pkt_len;
-				skb->protocol=eth_type_trans(skb,dev);
-				netif_rx(skb);
-				dev->last_rx = jiffies;
-				lp->stats.rx_packets++;
-				lp->stats.rx_bytes+=pkt_len;
-			}
-		}
-		else {
-			DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n",
-					dev->name, rfd->stat));
-			lp->stats.rx_errors++;
-			if ((rfd->stat) & 0x0001)
-				lp->stats.collisions++;
-			if ((rfd->stat) & 0x0080)
-				lp->stats.rx_length_errors++;
-			if ((rfd->stat) & 0x0100)
-				lp->stats.rx_over_errors++;
-			if ((rfd->stat) & 0x0200)
-				lp->stats.rx_fifo_errors++;
-			if ((rfd->stat) & 0x0400)
-				lp->stats.rx_frame_errors++;
-			if ((rfd->stat) & 0x0800)
-				lp->stats.rx_crc_errors++;
-			if ((rfd->stat) & 0x1000)
-				lp->stats.rx_length_errors++;
-		}
-
-		/* Clear the buffer descriptor count and EOF + F flags */
-
-		if (rbd != NULL && (rbd->count & 0x4000)) {
-			rbd->count = 0;
-			lp->rbd_head = rbd->v_next;
-			CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
-		}
-
-		/* Tidy the frame descriptor, marking it as end of list */
-
-		rfd->rbd = I596_NULL;
-		rfd->stat = 0;
-		rfd->cmd = CMD_EOL|CMD_FLEX;
-		rfd->count = 0;
-
-		/* Remove end-of-list from old end descriptor */
-
-		rfd->v_prev->cmd = CMD_FLEX;
-
-		/* Update record of next frame descriptor to process */
-
-		lp->scb.rfd = rfd->b_next;
-		lp->rfd_head = rfd->v_next;
-		CHECK_WBACK_INV(lp, rfd->v_prev, sizeof(struct i596_rfd));
-		CHECK_WBACK_INV(lp, rfd, sizeof(struct i596_rfd));
-		rfd = lp->rfd_head;
-		CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
-	}
-
-	DEB(DEB_RXFRAME, printk("frames %d\n", frames));
-
-	return 0;
-}
-
-
-static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
-{
-	struct i596_cmd *ptr;
-
-	while (lp->cmd_head != NULL) {
-		ptr = lp->cmd_head;
-		lp->cmd_head = ptr->v_next;
-		lp->cmd_backlog--;
-
-		switch ((ptr->command) & 0x7) {
-		case CmdTx:
-			{
-				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
-				struct sk_buff *skb = tx_cmd->skb;
-				dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE);
-
-				dev_kfree_skb(skb);
-
-				lp->stats.tx_errors++;
-				lp->stats.tx_aborted_errors++;
-
-				ptr->v_next = NULL;
-				ptr->b_next = I596_NULL;
-				tx_cmd->cmd.command = 0;  /* Mark as free */
-				break;
-			}
-		default:
-			ptr->v_next = NULL;
-			ptr->b_next = I596_NULL;
-		}
-		CHECK_WBACK_INV(lp, ptr, sizeof(struct i596_cmd));
-	}
-
-	wait_cmd(dev, lp, 100, "i596_cleanup_cmd timed out");
-	lp->scb.cmd = I596_NULL;
-	CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-}
-
-
-static inline void i596_reset(struct net_device *dev, struct i596_private *lp)
-{
-	unsigned long flags;
-
-	DEB(DEB_RESET, printk("i596_reset\n"));
-
-	spin_lock_irqsave (&lp->lock, flags);
-
-	wait_cmd(dev, lp, 100, "i596_reset timed out");
-
-	netif_stop_queue(dev);
-
-	/* FIXME: this command might cause an lpmc */
-	lp->scb.command = CUC_ABORT | RX_ABORT;
-	CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-	CA(dev);
-
-	/* wait for shutdown */
-	wait_cmd(dev, lp, 1000, "i596_reset 2 timed out");
-	spin_unlock_irqrestore (&lp->lock, flags);
-
-	i596_cleanup_cmd(dev,lp);
-	i596_rx(dev);
-
-	netif_start_queue(dev);
-	init_i596_mem(dev);
-}
-
-
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
-{
-	struct i596_private *lp = dev->priv;
-	unsigned long flags;
-
-	DEB(DEB_ADDCMD, printk("i596_add_cmd cmd_head %p\n", lp->cmd_head));
-
-	cmd->status = 0;
-	cmd->command |= (CMD_EOL | CMD_INTR);
-	cmd->v_next = NULL;
-	cmd->b_next = I596_NULL;
-	CHECK_WBACK(lp, cmd, sizeof(struct i596_cmd));
-
-	spin_lock_irqsave (&lp->lock, flags);
-
-	if (lp->cmd_head != NULL) {
-		lp->cmd_tail->v_next = cmd;
-		lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status));
-		CHECK_WBACK(lp, lp->cmd_tail, sizeof(struct i596_cmd));
-	} else {
-		lp->cmd_head = cmd;
-		wait_cmd(dev, lp, 100, "i596_add_cmd timed out");
-		lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status));
-		lp->scb.command = CUC_START;
-		CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-		CA(dev);
-	}
-	lp->cmd_tail = cmd;
-	lp->cmd_backlog++;
-
-	spin_unlock_irqrestore (&lp->lock, flags);
-
-	if (lp->cmd_backlog > max_cmd_backlog) {
-		unsigned long tickssofar = jiffies - lp->last_cmd;
-
-		if (tickssofar < ticks_limit)
-			return;
-
-		printk("%s: command unit timed out, status resetting.\n", dev->name);
-#if 1
-		i596_reset(dev, lp);
-#endif
-	}
-}
-
-#if 0
-/* this function makes a perfectly adequate probe...  but we have a
-   device list */
-static int i596_test(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	volatile int *tint;
-	u32 data;
-
-	tint = (volatile int *)(&(lp->scp));
-	data = virt_to_dma(lp,tint);
-
-	tint[1] = -1;
-	CHECK_WBACK(lp, tint, PAGE_SIZE);
-
-	MPU_PORT(dev, 1, data);
-
-	for(data = 1000000; data; data--) {
-		CHECK_INV(lp, tint, PAGE_SIZE);
-		if(tint[1] != -1)
-			break;
-
-	}
-
-	printk("i596_test result %d\n", tint[1]);
-
-}
-#endif
-
-
-static int i596_open(struct net_device *dev)
-{
-	DEB(DEB_OPEN, printk("%s: i596_open() irq %d.\n", dev->name, dev->irq));
-
-	if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
-		printk("%s: IRQ %d not free\n", dev->name, dev->irq);
-		goto out;
-	}
-
-	init_rx_bufs(dev);
-
-	if (init_i596_mem(dev)) {
-		printk("%s: Failed to init memory\n", dev->name);
-		goto out_remove_rx_bufs;
-	}
-
-	netif_start_queue(dev);
-
-	return 0;
-
-out_remove_rx_bufs:
-	remove_rx_bufs(dev);
-	free_irq(dev->irq, dev);
-out:
-	return -EAGAIN;
-}
-
-static void i596_tx_timeout (struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-
-	/* Transmitter timeout, serious problems. */
-	DEB(DEB_ERRORS, printk("%s: transmit timed out, status resetting.\n",
-			dev->name));
-
-	lp->stats.tx_errors++;
-
-	/* Try to restart the adaptor */
-	if (lp->last_restart == lp->stats.tx_packets) {
-		DEB(DEB_ERRORS, printk("Resetting board.\n"));
-		/* Shutdown and restart */
-		i596_reset (dev, lp);
-	} else {
-		/* Issue a channel attention signal */
-		DEB(DEB_ERRORS, printk("Kicking board.\n"));
-		lp->scb.command = CUC_START | RX_START;
-		CHECK_WBACK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
-		CA (dev);
-		lp->last_restart = lp->stats.tx_packets;
-	}
-
-	dev->trans_start = jiffies;
-	netif_wake_queue (dev);
-}
-
-
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	struct tx_cmd *tx_cmd;
-	struct i596_tbd *tbd;
-	short length = skb->len;
-	dev->trans_start = jiffies;
-
-	DEB(DEB_STARTTX, printk("%s: i596_start_xmit(%x,%p) called\n", dev->name,
-				skb->len, skb->data));
-
-	if (length < ETH_ZLEN) {
-		if (skb_padto(skb, ETH_ZLEN))
-			return 0;
-		length = ETH_ZLEN;
-	}
-
-	netif_stop_queue(dev);
-
-	tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
-	tbd = lp->tbds + lp->next_tx_cmd;
-
-	if (tx_cmd->cmd.command) {
-		DEB(DEB_ERRORS, printk("%s: xmit ring full, dropping packet.\n",
-				dev->name));
-		lp->stats.tx_dropped++;
-
-		dev_kfree_skb(skb);
-	} else {
-		if (++lp->next_tx_cmd == TX_RING_SIZE)
-			lp->next_tx_cmd = 0;
-		tx_cmd->tbd = WSWAPtbd(virt_to_dma(lp,tbd));
-		tbd->next = I596_NULL;
-
-		tx_cmd->cmd.command = CMD_FLEX | CmdTx;
-		tx_cmd->skb = skb;
-
-		tx_cmd->pad = 0;
-		tx_cmd->size = 0;
-		tbd->pad = 0;
-		tbd->size = EOF | length;
-
-		tx_cmd->dma_addr = dma_map_single(lp->dev, skb->data, skb->len,
-				DMA_TO_DEVICE);
-		tbd->data = WSWAPchar(tx_cmd->dma_addr);
-
-		DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued"));
-		CHECK_WBACK_INV(lp, tx_cmd, sizeof(struct tx_cmd));
-		CHECK_WBACK_INV(lp, tbd, sizeof(struct i596_tbd));
-		i596_add_cmd(dev, &tx_cmd->cmd);
-
-		lp->stats.tx_packets++;
-		lp->stats.tx_bytes += length;
-	}
-
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-static void print_eth(unsigned char *add, char *str)
-{
-	int i;
-
-	printk("i596 0x%p, ", add);
-	for (i = 0; i < 6; i++)
-		printk(" %02X", add[i + 6]);
-	printk(" -->");
-	for (i = 0; i < 6; i++)
-		printk(" %02X", add[i]);
-	printk(" %02X%02X, %s\n", add[12], add[13], str);
-}
-
-
 #define LAN_PROM_ADDR	0xF0810000
 
-static int __devinit i82596_probe(struct net_device *dev,
-				  struct device *gen_dev)
-{
-	int i;
-	struct i596_private *lp;
-	char eth_addr[6];
-	dma_addr_t dma_addr;
-
-	/* This lot is ensure things have been cache line aligned. */
-	BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
-	BUILD_BUG_ON(sizeof(struct i596_rbd) &  31);
-	BUILD_BUG_ON(sizeof(struct tx_cmd)   &  31);
-	BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
-#ifndef __LP64__
-	BUILD_BUG_ON(sizeof(struct i596_private) > 4096);
-#endif
-
-	if (!dev->base_addr || !dev->irq)
-		return -ENODEV;
-
-	if (pdc_lan_station_id(eth_addr, dev->base_addr)) {
-		for (i=0; i < 6; i++) {
-			eth_addr[i] = gsc_readb(LAN_PROM_ADDR + i);
-		}
-		printk(KERN_INFO "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__);
-	}
-
-	dev->mem_start = (unsigned long) dma_alloc_noncoherent(gen_dev,
-		sizeof(struct i596_private), &dma_addr, GFP_KERNEL);
-	if (!dev->mem_start) {
-		printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = eth_addr[i];
-
-	/* The 82596-specific entries in the device structure. */
-	dev->open = i596_open;
-	dev->stop = i596_close;
-	dev->hard_start_xmit = i596_start_xmit;
-	dev->get_stats = i596_get_stats;
-	dev->set_multicast_list = set_multicast_list;
-	dev->tx_timeout = i596_tx_timeout;
-	dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = i596_poll_controller;
-#endif
-
-	dev->priv = (void *)(dev->mem_start);
-
-	lp = dev->priv;
-	memset(lp, 0, sizeof(struct i596_private));
-
-	lp->scb.command = 0;
-	lp->scb.cmd = I596_NULL;
-	lp->scb.rfd = I596_NULL;
-	spin_lock_init(&lp->lock);
-	lp->dma_addr = dma_addr;
-	lp->dev = gen_dev;
-
-	CHECK_WBACK_INV(lp, dev->mem_start, sizeof(struct i596_private));
-
-	i = register_netdev(dev);
-	if (i) {
-		lp = dev->priv;
-		dma_free_noncoherent(lp->dev, sizeof(struct i596_private),
-				    (void *)dev->mem_start, lp->dma_addr);
-		return i;
-	};
-
-	DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,", dev->name, dev->base_addr));
-	for (i = 0; i < 6; i++)
-		DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i]));
-	DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq));
-	DEB(DEB_INIT, printk(KERN_INFO "%s: lp at 0x%p (%d bytes), lp->scb at 0x%p\n",
-		dev->name, lp, (int)sizeof(struct i596_private), &lp->scb));
-
-	return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void i596_poll_controller(struct net_device *dev)
-{
-	disable_irq(dev->irq);
-	i596_interrupt(dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-static irqreturn_t i596_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct i596_private *lp;
-	unsigned short status, ack_cmd = 0;
-
-	if (dev == NULL) {
-		printk("%s: irq %d for unknown device.\n", __FUNCTION__, irq);
-		return IRQ_NONE;
-	}
-
-	lp = dev->priv;
-
-	spin_lock (&lp->lock);
-
-	wait_cmd(dev, lp, 100, "i596 interrupt, timeout");
-	status = lp->scb.status;
-
-	DEB(DEB_INTS, printk("%s: i596 interrupt, IRQ %d, status %4.4x.\n",
-			dev->name, irq, status));
-
-	ack_cmd = status & 0xf000;
-
-	if (!ack_cmd) {
-		DEB(DEB_ERRORS, printk("%s: interrupt with no events\n", dev->name));
-		spin_unlock (&lp->lock);
-		return IRQ_NONE;
-	}
-
-	if ((status & 0x8000) || (status & 0x2000)) {
-		struct i596_cmd *ptr;
-
-		if ((status & 0x8000))
-			DEB(DEB_INTS, printk("%s: i596 interrupt completed command.\n", dev->name));
-		if ((status & 0x2000))
-			DEB(DEB_INTS, printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700));
-
-		while (lp->cmd_head != NULL) {
-			CHECK_INV(lp, lp->cmd_head, sizeof(struct i596_cmd));
-			if (!(lp->cmd_head->status & STAT_C))
-				break;
-
-			ptr = lp->cmd_head;
-
-			DEB(DEB_STATUS, printk("cmd_head->status = %04x, ->command = %04x\n",
-				       lp->cmd_head->status, lp->cmd_head->command));
-			lp->cmd_head = ptr->v_next;
-			lp->cmd_backlog--;
-
-			switch ((ptr->command) & 0x7) {
-			case CmdTx:
-			    {
-				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
-				struct sk_buff *skb = tx_cmd->skb;
-
-				if ((ptr->status) & STAT_OK) {
-					DEB(DEB_TXADDR, print_eth(skb->data, "tx-done"));
-				} else {
-					lp->stats.tx_errors++;
-					if ((ptr->status) & 0x0020)
-						lp->stats.collisions++;
-					if (!((ptr->status) & 0x0040))
-						lp->stats.tx_heartbeat_errors++;
-					if ((ptr->status) & 0x0400)
-						lp->stats.tx_carrier_errors++;
-					if ((ptr->status) & 0x0800)
-						lp->stats.collisions++;
-					if ((ptr->status) & 0x1000)
-						lp->stats.tx_aborted_errors++;
-				}
-				dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE);
-				dev_kfree_skb_irq(skb);
-
-				tx_cmd->cmd.command = 0; /* Mark free */
-				break;
-			    }
-			case CmdTDR:
-			    {
-				unsigned short status = ((struct tdr_cmd *)ptr)->status;
-
-				if (status & 0x8000) {
-					DEB(DEB_ANY, printk("%s: link ok.\n", dev->name));
-				} else {
-					if (status & 0x4000)
-						printk("%s: Transceiver problem.\n", dev->name);
-					if (status & 0x2000)
-						printk("%s: Termination problem.\n", dev->name);
-					if (status & 0x1000)
-						printk("%s: Short circuit.\n", dev->name);
-
-					DEB(DEB_TDR, printk("%s: Time %d.\n", dev->name, status & 0x07ff));
-				}
-				break;
-			    }
-			case CmdConfigure:
-				/* Zap command so set_multicast_list() knows it is free */
-				ptr->command = 0;
-				break;
-			}
-			ptr->v_next = NULL;
-		        ptr->b_next = I596_NULL;
-			CHECK_WBACK(lp, ptr, sizeof(struct i596_cmd));
-			lp->last_cmd = jiffies;
-		}
-
-		/* This mess is arranging that only the last of any outstanding
-		 * commands has the interrupt bit set.  Should probably really
-		 * only add to the cmd queue when the CU is stopped.
-		 */
-		ptr = lp->cmd_head;
-		while ((ptr != NULL) && (ptr != lp->cmd_tail)) {
-			struct i596_cmd *prev = ptr;
-
-			ptr->command &= 0x1fff;
-			ptr = ptr->v_next;
-			CHECK_WBACK_INV(lp, prev, sizeof(struct i596_cmd));
-		}
-
-		if ((lp->cmd_head != NULL))
-			ack_cmd |= CUC_START;
-		lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status));
-		CHECK_WBACK_INV(lp, &lp->scb, sizeof(struct i596_scb));
-	}
-	if ((status & 0x1000) || (status & 0x4000)) {
-		if ((status & 0x4000))
-			DEB(DEB_INTS, printk("%s: i596 interrupt received a frame.\n", dev->name));
-		i596_rx(dev);
-		/* Only RX_START if stopped - RGH 07-07-96 */
-		if (status & 0x1000) {
-			if (netif_running(dev)) {
-				DEB(DEB_ERRORS, printk("%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status));
-				ack_cmd |= RX_START;
-				lp->stats.rx_errors++;
-				lp->stats.rx_fifo_errors++;
-				rebuild_rx_bufs(dev);
-			}
-		}
-	}
-	wait_cmd(dev, lp, 100, "i596 interrupt, timeout");
-	lp->scb.command = ack_cmd;
-	CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
-
-	/* DANGER: I suspect that some kind of interrupt
-	 acknowledgement aside from acking the 82596 might be needed
-	 here...  but it's running acceptably without */
-
-	CA(dev);
-
-	wait_cmd(dev, lp, 100, "i596 interrupt, exit timeout");
-	DEB(DEB_INTS, printk("%s: exiting interrupt.\n", dev->name));
-
-	spin_unlock (&lp->lock);
-	return IRQ_HANDLED;
-}
-
-static int i596_close(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	unsigned long flags;
-
-	netif_stop_queue(dev);
-
-	DEB(DEB_INIT, printk("%s: Shutting down ethercard, status was %4.4x.\n",
-		       dev->name, lp->scb.status));
-
-	spin_lock_irqsave(&lp->lock, flags);
-
-	wait_cmd(dev, lp, 100, "close1 timed out");
-	lp->scb.command = CUC_ABORT | RX_ABORT;
-	CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
-
-	CA(dev);
-
-	wait_cmd(dev, lp, 100, "close2 timed out");
-	spin_unlock_irqrestore(&lp->lock, flags);
-	DEB(DEB_STRUCT,i596_display_data(dev));
-	i596_cleanup_cmd(dev,lp);
-
-	disable_irq(dev->irq);
-
-	free_irq(dev->irq, dev);
-	remove_rx_bufs(dev);
-
-	return 0;
-}
-
-static struct net_device_stats *
- i596_get_stats(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-
-	return &lp->stats;
-}
-
-/*
- *    Set or clear the multicast filter for this adaptor.
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
-	struct i596_private *lp = dev->priv;
-	int config = 0, cnt;
-
-	DEB(DEB_MULTI, printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
-		dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF",
-		dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
-
-	if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) {
-		lp->cf_cmd.i596_config[8] |= 0x01;
-		config = 1;
-	}
-	if (!(dev->flags & IFF_PROMISC) && (lp->cf_cmd.i596_config[8] & 0x01)) {
-		lp->cf_cmd.i596_config[8] &= ~0x01;
-		config = 1;
-	}
-	if ((dev->flags & IFF_ALLMULTI) && (lp->cf_cmd.i596_config[11] & 0x20)) {
-		lp->cf_cmd.i596_config[11] &= ~0x20;
-		config = 1;
-	}
-	if (!(dev->flags & IFF_ALLMULTI) && !(lp->cf_cmd.i596_config[11] & 0x20)) {
-		lp->cf_cmd.i596_config[11] |= 0x20;
-		config = 1;
-	}
-	if (config) {
-		if (lp->cf_cmd.cmd.command)
-			printk("%s: config change request already queued\n",
-			       dev->name);
-		else {
-			lp->cf_cmd.cmd.command = CmdConfigure;
-			CHECK_WBACK_INV(lp, &lp->cf_cmd, sizeof(struct cf_cmd));
-			i596_add_cmd(dev, &lp->cf_cmd.cmd);
-		}
-	}
-
-	cnt = dev->mc_count;
-	if (cnt > MAX_MC_CNT)
-	{
-		cnt = MAX_MC_CNT;
-		printk("%s: Only %d multicast addresses supported",
-			dev->name, cnt);
-	}
-
-	if (dev->mc_count > 0) {
-		struct dev_mc_list *dmi;
-		unsigned char *cp;
-		struct mc_cmd *cmd;
-
-		cmd = &lp->mc_cmd;
-		cmd->cmd.command = CmdMulticastList;
-		cmd->mc_cnt = dev->mc_count * 6;
-		cp = cmd->mc_addrs;
-		for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) {
-			memcpy(cp, dmi->dmi_addr, 6);
-			if (i596_debug > 1)
-				DEB(DEB_MULTI, printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
-						dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5]));
-		}
-		CHECK_WBACK_INV(lp, &lp->mc_cmd, sizeof(struct mc_cmd));
-		i596_add_cmd(dev, &cmd->cmd);
-	}
-}
-
-static int debug = -1;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "lasi_82596 debug mask");
-
-static int num_drivers;
-static struct net_device *netdevs[MAX_DRIVERS];
-
 static int __devinit
 lan_init_chip(struct parisc_device *dev)
 {
 	struct	net_device *netdevice;
+	struct i596_private *lp;
 	int	retval;
-
-	if (num_drivers >= MAX_DRIVERS) {
-		/* max count of possible i82596 drivers reached */
-		return -ENOMEM;
-	}
-
-	if (num_drivers == 0)
-		printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
+	int i;
 
 	if (!dev->irq) {
 		printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
@@ -1528,28 +168,45 @@
 	printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start,
 			dev->irq);
 
-	netdevice = alloc_etherdev(0);
+	netdevice = alloc_etherdev(sizeof(struct i596_private));
 	if (!netdevice)
 		return -ENOMEM;
+	SET_NETDEV_DEV(netdevice, &dev->dev);
+	parisc_set_drvdata (dev, netdevice);
 
 	netdevice->base_addr = dev->hpa.start;
 	netdevice->irq = dev->irq;
 
-	retval = i82596_probe(netdevice, &dev->dev);
+	if (pdc_lan_station_id(netdevice->dev_addr, netdevice->base_addr)) {
+		for (i = 0; i < 6; i++) {
+			netdevice->dev_addr[i] = gsc_readb(LAN_PROM_ADDR + i);
+		}
+		printk(KERN_INFO
+		       "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__);
+	}
+
+	lp = netdev_priv(netdevice);
+	lp->options = dev->id.sversion == 0x72 ? OPT_SWAP_PORT : 0;
+
+	retval = i82596_probe(netdevice);
 	if (retval) {
 		free_netdev(netdevice);
 		return -ENODEV;
 	}
-
-	if (dev->id.sversion == 0x72) {
-		((struct i596_private *)netdevice->priv)->options = OPT_SWAP_PORT;
-	}
-
-	netdevs[num_drivers++] = netdevice;
-
 	return retval;
 }
 
+static int __devexit lan_remove_chip (struct parisc_device *pdev)
+{
+	struct net_device *dev = parisc_get_drvdata(pdev);
+	struct i596_private *lp = netdev_priv(dev);
+
+	unregister_netdev (dev);
+	DMA_FREE(&pdev->dev, sizeof(struct i596_private),
+		 (void *)lp->dma, lp->dma_addr);
+	free_netdev (dev);
+	return 0;
+}
 
 static struct parisc_device_id lan_tbl[] = {
 	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008a },
@@ -1563,12 +220,12 @@
 	.name		= "lasi_82596",
 	.id_table	= lan_tbl,
 	.probe		= lan_init_chip,
+	.remove         = __devexit_p(lan_remove_chip),
 };
 
 static int __devinit lasi_82596_init(void)
 {
-	if (debug >= 0)
-		i596_debug = debug;
+	printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
 	return register_parisc_driver(&lan_driver);
 }
 
@@ -1576,25 +233,6 @@
 
 static void __exit lasi_82596_exit(void)
 {
-	int i;
-
-	for (i=0; i<MAX_DRIVERS; i++) {
-		struct i596_private *lp;
-		struct net_device *netdevice;
-
-		netdevice = netdevs[i];
-		if (!netdevice)
-			continue;
-
-		unregister_netdev(netdevice);
-
-		lp = netdevice->priv;
-		dma_free_noncoherent(lp->dev, sizeof(struct i596_private),
-				       (void *)netdevice->mem_start, lp->dma_addr);
-		free_netdev(netdevice);
-	}
-	num_drivers = 0;
-
 	unregister_parisc_driver(&lan_driver);
 }
 
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
new file mode 100644
index 0000000..5884f5b
--- /dev/null
+++ b/drivers/net/lib82596.c
@@ -0,0 +1,1434 @@
+/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as
+   munged into HPPA boxen .
+
+   This driver is based upon 82596.c, original credits are below...
+   but there were too many hoops which HP wants jumped through to
+   keep this code in there in a sane manner.
+
+   3 primary sources of the mess --
+   1) hppa needs *lots* of cacheline flushing to keep this kind of
+   MMIO running.
+
+   2) The 82596 needs to see all of its pointers as their physical
+   address.  Thus virt_to_bus/bus_to_virt are *everywhere*.
+
+   3) The implementation HP is using seems to be significantly pickier
+   about when and how the command and RX units are started.  some
+   command ordering was changed.
+
+   Examination of the mach driver leads one to believe that there
+   might be a saner way to pull this off...  anyone who feels like a
+   full rewrite can be my guest.
+
+   Split 02/13/2000 Sam Creasey (sammy@oh.verio.com)
+
+   02/01/2000  Initial modifications for parisc by Helge Deller (deller@gmx.de)
+   03/02/2000  changes for better/correct(?) cache-flushing (deller)
+*/
+
+/* 82596.c: A generic 82596 ethernet driver for linux. */
+/*
+   Based on Apricot.c
+   Written 1994 by Mark Evans.
+   This driver is for the Apricot 82596 bus-master interface
+
+   Modularised 12/94 Mark Evans
+
+
+   Modified to support the 82596 ethernet chips on 680x0 VME boards.
+   by Richard Hirst <richard@sleepie.demon.co.uk>
+   Renamed to be 82596.c
+
+   980825:  Changed to receive directly in to sk_buffs which are
+   allocated at open() time.  Eliminates copy on incoming frames
+   (small ones are still copied).  Shared data now held in a
+   non-cached page, so we can run on 68060 in copyback mode.
+
+   TBD:
+   * look at deferring rx frames rather than discarding (as per tulip)
+   * handle tx ring full as per tulip
+   * performace test to tune rx_copybreak
+
+   Most of my modifications relate to the braindead big-endian
+   implementation by Intel.  When the i596 is operating in
+   'big-endian' mode, it thinks a 32 bit value of 0x12345678
+   should be stored as 0x56781234.  This is a real pain, when
+   you have linked lists which are shared by the 680x0 and the
+   i596.
+
+   Driver skeleton
+   Written 1993 by Donald Becker.
+   Copyright 1993 United States Government as represented by the Director,
+   National Security Agency. This software may only be used and distributed
+   according to the terms of the GNU General Public License as modified by SRC,
+   incorporated herein by reference.
+
+   The author may be reached as becker@scyld.com, or C/O
+   Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
+
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+/* DEBUG flags
+ */
+
+#define DEB_INIT	0x0001
+#define DEB_PROBE	0x0002
+#define DEB_SERIOUS	0x0004
+#define DEB_ERRORS	0x0008
+#define DEB_MULTI	0x0010
+#define DEB_TDR		0x0020
+#define DEB_OPEN	0x0040
+#define DEB_RESET	0x0080
+#define DEB_ADDCMD	0x0100
+#define DEB_STATUS	0x0200
+#define DEB_STARTTX	0x0400
+#define DEB_RXADDR	0x0800
+#define DEB_TXADDR	0x1000
+#define DEB_RXFRAME	0x2000
+#define DEB_INTS	0x4000
+#define DEB_STRUCT	0x8000
+#define DEB_ANY		0xffff
+
+
+#define DEB(x, y)	if (i596_debug & (x)) { y; }
+
+
+/*
+ * The MPU_PORT command allows direct access to the 82596. With PORT access
+ * the following commands are available (p5-18). The 32-bit port command
+ * must be word-swapped with the most significant word written first.
+ * This only applies to VME boards.
+ */
+#define PORT_RESET		0x00	/* reset 82596 */
+#define PORT_SELFTEST		0x01	/* selftest */
+#define PORT_ALTSCP		0x02	/* alternate SCB address */
+#define PORT_ALTDUMP		0x03	/* Alternate DUMP address */
+
+static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+
+/* Copy frames shorter than rx_copybreak, otherwise pass on up in
+ * a full sized sk_buff.  Value of 100 stolen from tulip.c (!alpha).
+ */
+static int rx_copybreak = 100;
+
+#define PKT_BUF_SZ	1536
+#define MAX_MC_CNT	64
+
+#define ISCP_BUSY	0x0001
+
+#define I596_NULL ((u32)0xffffffff)
+
+#define CMD_EOL		0x8000	/* The last command of the list, stop. */
+#define CMD_SUSP	0x4000	/* Suspend after doing cmd. */
+#define CMD_INTR	0x2000	/* Interrupt after doing cmd. */
+
+#define CMD_FLEX	0x0008	/* Enable flexible memory model */
+
+enum commands {
+	CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
+	CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
+};
+
+#define STAT_C		0x8000	/* Set to 0 after execution */
+#define STAT_B		0x4000	/* Command being executed */
+#define STAT_OK		0x2000	/* Command executed ok */
+#define STAT_A		0x1000	/* Command aborted */
+
+#define	 CUC_START	0x0100
+#define	 CUC_RESUME	0x0200
+#define	 CUC_SUSPEND    0x0300
+#define	 CUC_ABORT	0x0400
+#define	 RX_START	0x0010
+#define	 RX_RESUME	0x0020
+#define	 RX_SUSPEND	0x0030
+#define	 RX_ABORT	0x0040
+
+#define TX_TIMEOUT	5
+
+
+struct i596_reg {
+	unsigned short porthi;
+	unsigned short portlo;
+	u32            ca;
+};
+
+#define EOF		0x8000
+#define SIZE_MASK	0x3fff
+
+struct i596_tbd {
+	unsigned short size;
+	unsigned short pad;
+	dma_addr_t     next;
+	dma_addr_t     data;
+	u32 cache_pad[5];		/* Total 32 bytes... */
+};
+
+/* The command structure has two 'next' pointers; v_next is the address of
+ * the next command as seen by the CPU, b_next is the address of the next
+ * command as seen by the 82596.  The b_next pointer, as used by the 82596
+ * always references the status field of the next command, rather than the
+ * v_next field, because the 82596 is unaware of v_next.  It may seem more
+ * logical to put v_next at the end of the structure, but we cannot do that
+ * because the 82596 expects other fields to be there, depending on command
+ * type.
+ */
+
+struct i596_cmd {
+	struct i596_cmd *v_next;	/* Address from CPUs viewpoint */
+	unsigned short status;
+	unsigned short command;
+	dma_addr_t     b_next;	/* Address from i596 viewpoint */
+};
+
+struct tx_cmd {
+	struct i596_cmd cmd;
+	dma_addr_t     tbd;
+	unsigned short size;
+	unsigned short pad;
+	struct sk_buff *skb;		/* So we can free it after tx */
+	dma_addr_t dma_addr;
+#ifdef __LP64__
+	u32 cache_pad[6];		/* Total 64 bytes... */
+#else
+	u32 cache_pad[1];		/* Total 32 bytes... */
+#endif
+};
+
+struct tdr_cmd {
+	struct i596_cmd cmd;
+	unsigned short status;
+	unsigned short pad;
+};
+
+struct mc_cmd {
+	struct i596_cmd cmd;
+	short mc_cnt;
+	char mc_addrs[MAX_MC_CNT*6];
+};
+
+struct sa_cmd {
+	struct i596_cmd cmd;
+	char eth_addr[8];
+};
+
+struct cf_cmd {
+	struct i596_cmd cmd;
+	char i596_config[16];
+};
+
+struct i596_rfd {
+	unsigned short stat;
+	unsigned short cmd;
+	dma_addr_t     b_next;	/* Address from i596 viewpoint */
+	dma_addr_t     rbd;
+	unsigned short count;
+	unsigned short size;
+	struct i596_rfd *v_next;	/* Address from CPUs viewpoint */
+	struct i596_rfd *v_prev;
+#ifndef __LP64__
+	u32 cache_pad[2];		/* Total 32 bytes... */
+#endif
+};
+
+struct i596_rbd {
+    /* hardware data */
+    unsigned short count;
+    unsigned short zero1;
+    dma_addr_t     b_next;
+    dma_addr_t     b_data;		/* Address from i596 viewpoint */
+    unsigned short size;
+    unsigned short zero2;
+    /* driver data */
+    struct sk_buff *skb;
+    struct i596_rbd *v_next;
+    dma_addr_t     b_addr;		/* This rbd addr from i596 view */
+    unsigned char *v_data;		/* Address from CPUs viewpoint */
+					/* Total 32 bytes... */
+#ifdef __LP64__
+    u32 cache_pad[4];
+#endif
+};
+
+/* These values as chosen so struct i596_dma fits in one page... */
+
+#define TX_RING_SIZE 32
+#define RX_RING_SIZE 16
+
+struct i596_scb {
+	unsigned short status;
+	unsigned short command;
+	dma_addr_t    cmd;
+	dma_addr_t    rfd;
+	u32           crc_err;
+	u32           align_err;
+	u32           resource_err;
+	u32           over_err;
+	u32           rcvdt_err;
+	u32           short_err;
+	unsigned short t_on;
+	unsigned short t_off;
+};
+
+struct i596_iscp {
+	u32           stat;
+	dma_addr_t    scb;
+};
+
+struct i596_scp {
+	u32           sysbus;
+	u32           pad;
+	dma_addr_t    iscp;
+};
+
+struct i596_dma {
+	struct i596_scp scp		        __attribute__((aligned(32)));
+	volatile struct i596_iscp iscp		__attribute__((aligned(32)));
+	volatile struct i596_scb scb		__attribute__((aligned(32)));
+	struct sa_cmd sa_cmd			__attribute__((aligned(32)));
+	struct cf_cmd cf_cmd			__attribute__((aligned(32)));
+	struct tdr_cmd tdr_cmd			__attribute__((aligned(32)));
+	struct mc_cmd mc_cmd			__attribute__((aligned(32)));
+	struct i596_rfd rfds[RX_RING_SIZE]	__attribute__((aligned(32)));
+	struct i596_rbd rbds[RX_RING_SIZE]	__attribute__((aligned(32)));
+	struct tx_cmd tx_cmds[TX_RING_SIZE]	__attribute__((aligned(32)));
+	struct i596_tbd tbds[TX_RING_SIZE]	__attribute__((aligned(32)));
+};
+
+struct i596_private {
+	struct i596_dma *dma;
+	u32    stat;
+	int last_restart;
+	struct i596_rfd *rfd_head;
+	struct i596_rbd *rbd_head;
+	struct i596_cmd *cmd_tail;
+	struct i596_cmd *cmd_head;
+	int cmd_backlog;
+	u32    last_cmd;
+	struct net_device_stats stats;
+	int next_tx_cmd;
+	int options;
+	spinlock_t lock;       /* serialize access to chip */
+	dma_addr_t dma_addr;
+	void __iomem *mpu_port;
+	void __iomem *ca;
+};
+
+static const char init_setup[] =
+{
+	0x8E,		/* length, prefetch on */
+	0xC8,		/* fifo to 8, monitor off */
+	0x80,		/* don't save bad frames */
+	0x2E,		/* No source address insertion, 8 byte preamble */
+	0x00,		/* priority and backoff defaults */
+	0x60,		/* interframe spacing */
+	0x00,		/* slot time LSB */
+	0xf2,		/* slot time and retries */
+	0x00,		/* promiscuous mode */
+	0x00,		/* collision detect */
+	0x40,		/* minimum frame length */
+	0xff,
+	0x00,
+	0x7f /*  *multi IA */ };
+
+static int i596_open(struct net_device *dev);
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static irqreturn_t i596_interrupt(int irq, void *dev_id);
+static int i596_close(struct net_device *dev);
+static struct net_device_stats *i596_get_stats(struct net_device *dev);
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
+static void i596_tx_timeout (struct net_device *dev);
+static void print_eth(unsigned char *buf, char *str);
+static void set_multicast_list(struct net_device *dev);
+static inline void ca(struct net_device *dev);
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x);
+
+static int rx_ring_size = RX_RING_SIZE;
+static int ticks_limit = 100;
+static int max_cmd_backlog = TX_RING_SIZE-1;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev);
+#endif
+
+
+static inline int wait_istat(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str)
+{
+	DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp));
+	while (--delcnt && dma->iscp.stat) {
+		udelay(10);
+		DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp));
+	}
+	if (!delcnt) {
+		printk(KERN_ERR "%s: %s, iscp.stat %04x, didn't clear\n",
+		     dev->name, str, SWAP16(dma->iscp.stat));
+		return -1;
+	} else
+		return 0;
+}
+
+
+static inline int wait_cmd(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str)
+{
+	DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb));
+	while (--delcnt && dma->scb.command) {
+		udelay(10);
+		DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb));
+	}
+	if (!delcnt) {
+		printk(KERN_ERR "%s: %s, status %4.4x, cmd %4.4x.\n",
+		       dev->name, str,
+		       SWAP16(dma->scb.status),
+		       SWAP16(dma->scb.command));
+		return -1;
+	} else
+		return 0;
+}
+
+
+static void i596_display_data(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	struct i596_cmd *cmd;
+	struct i596_rfd *rfd;
+	struct i596_rbd *rbd;
+
+	printk(KERN_DEBUG "lp and scp at %p, .sysbus = %08x, .iscp = %08x\n",
+	       &dma->scp, dma->scp.sysbus, SWAP32(dma->scp.iscp));
+	printk(KERN_DEBUG "iscp at %p, iscp.stat = %08x, .scb = %08x\n",
+	       &dma->iscp, SWAP32(dma->iscp.stat), SWAP32(dma->iscp.scb));
+	printk(KERN_DEBUG "scb at %p, scb.status = %04x, .command = %04x,"
+		" .cmd = %08x, .rfd = %08x\n",
+	       &dma->scb, SWAP16(dma->scb.status), SWAP16(dma->scb.command),
+		SWAP16(dma->scb.cmd), SWAP32(dma->scb.rfd));
+	printk(KERN_DEBUG "   errors: crc %x, align %x, resource %x,"
+	       " over %x, rcvdt %x, short %x\n",
+	       SWAP32(dma->scb.crc_err), SWAP32(dma->scb.align_err),
+	       SWAP32(dma->scb.resource_err), SWAP32(dma->scb.over_err),
+	       SWAP32(dma->scb.rcvdt_err), SWAP32(dma->scb.short_err));
+	cmd = lp->cmd_head;
+	while (cmd != NULL) {
+		printk(KERN_DEBUG
+		       "cmd at %p, .status = %04x, .command = %04x,"
+		       " .b_next = %08x\n",
+		       cmd, SWAP16(cmd->status), SWAP16(cmd->command),
+		       SWAP32(cmd->b_next));
+		cmd = cmd->v_next;
+	}
+	rfd = lp->rfd_head;
+	printk(KERN_DEBUG "rfd_head = %p\n", rfd);
+	do {
+		printk(KERN_DEBUG
+		       "   %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x,"
+		       " count %04x\n",
+		       rfd, SWAP16(rfd->stat), SWAP16(rfd->cmd),
+		       SWAP32(rfd->b_next), SWAP32(rfd->rbd),
+		       SWAP16(rfd->count));
+		rfd = rfd->v_next;
+	} while (rfd != lp->rfd_head);
+	rbd = lp->rbd_head;
+	printk(KERN_DEBUG "rbd_head = %p\n", rbd);
+	do {
+		printk(KERN_DEBUG
+		       "   %p .count %04x, b_next %08x, b_data %08x,"
+		       " size %04x\n",
+			rbd, SWAP16(rbd->count), SWAP32(rbd->b_next),
+		       SWAP32(rbd->b_data), SWAP16(rbd->size));
+		rbd = rbd->v_next;
+	} while (rbd != lp->rbd_head);
+	DMA_INV(dev, dma, sizeof(struct i596_dma));
+}
+
+
+#define virt_to_dma(lp, v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)((lp)->dma)))
+
+static inline int init_rx_bufs(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	int i;
+	struct i596_rfd *rfd;
+	struct i596_rbd *rbd;
+
+	/* First build the Receive Buffer Descriptor List */
+
+	for (i = 0, rbd = dma->rbds; i < rx_ring_size; i++, rbd++) {
+		dma_addr_t dma_addr;
+		struct sk_buff *skb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4);
+
+		if (skb == NULL)
+			return -1;
+		skb_reserve(skb, 2);
+		dma_addr = dma_map_single(dev->dev.parent, skb->data,
+					  PKT_BUF_SZ, DMA_FROM_DEVICE);
+		rbd->v_next = rbd+1;
+		rbd->b_next = SWAP32(virt_to_dma(lp, rbd+1));
+		rbd->b_addr = SWAP32(virt_to_dma(lp, rbd));
+		rbd->skb = skb;
+		rbd->v_data = skb->data;
+		rbd->b_data = SWAP32(dma_addr);
+		rbd->size = SWAP16(PKT_BUF_SZ);
+	}
+	lp->rbd_head = dma->rbds;
+	rbd = dma->rbds + rx_ring_size - 1;
+	rbd->v_next = dma->rbds;
+	rbd->b_next = SWAP32(virt_to_dma(lp, dma->rbds));
+
+	/* Now build the Receive Frame Descriptor List */
+
+	for (i = 0, rfd = dma->rfds; i < rx_ring_size; i++, rfd++) {
+		rfd->rbd = I596_NULL;
+		rfd->v_next = rfd+1;
+		rfd->v_prev = rfd-1;
+		rfd->b_next = SWAP32(virt_to_dma(lp, rfd+1));
+		rfd->cmd = SWAP16(CMD_FLEX);
+	}
+	lp->rfd_head = dma->rfds;
+	dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+	rfd = dma->rfds;
+	rfd->rbd = SWAP32(virt_to_dma(lp, lp->rbd_head));
+	rfd->v_prev = dma->rfds + rx_ring_size - 1;
+	rfd = dma->rfds + rx_ring_size - 1;
+	rfd->v_next = dma->rfds;
+	rfd->b_next = SWAP32(virt_to_dma(lp, dma->rfds));
+	rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX);
+
+	DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+	return 0;
+}
+
+static inline void remove_rx_bufs(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_rbd *rbd;
+	int i;
+
+	for (i = 0, rbd = lp->dma->rbds; i < rx_ring_size; i++, rbd++) {
+		if (rbd->skb == NULL)
+			break;
+		dma_unmap_single(dev->dev.parent,
+				 (dma_addr_t)SWAP32(rbd->b_data),
+				 PKT_BUF_SZ, DMA_FROM_DEVICE);
+		dev_kfree_skb(rbd->skb);
+	}
+}
+
+
+static void rebuild_rx_bufs(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	int i;
+
+	/* Ensure rx frame/buffer descriptors are tidy */
+
+	for (i = 0; i < rx_ring_size; i++) {
+		dma->rfds[i].rbd = I596_NULL;
+		dma->rfds[i].cmd = SWAP16(CMD_FLEX);
+	}
+	dma->rfds[rx_ring_size-1].cmd = SWAP16(CMD_EOL|CMD_FLEX);
+	lp->rfd_head = dma->rfds;
+	dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+	lp->rbd_head = dma->rbds;
+	dma->rfds[0].rbd = SWAP32(virt_to_dma(lp, dma->rbds));
+
+	DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+}
+
+
+static int init_i596_mem(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	unsigned long flags;
+
+	mpu_port(dev, PORT_RESET, 0);
+	udelay(100);			/* Wait 100us - seems to help */
+
+	/* change the scp address */
+
+	lp->last_cmd = jiffies;
+
+	dma->scp.sysbus = SYSBUS;
+	dma->scp.iscp = SWAP32(virt_to_dma(lp, &(dma->iscp)));
+	dma->iscp.scb = SWAP32(virt_to_dma(lp, &(dma->scb)));
+	dma->iscp.stat = SWAP32(ISCP_BUSY);
+	lp->cmd_backlog = 0;
+
+	lp->cmd_head = NULL;
+	dma->scb.cmd = I596_NULL;
+
+	DEB(DEB_INIT, printk(KERN_DEBUG "%s: starting i82596.\n", dev->name));
+
+	DMA_WBACK(dev, &(dma->scp), sizeof(struct i596_scp));
+	DMA_WBACK(dev, &(dma->iscp), sizeof(struct i596_iscp));
+	DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+	mpu_port(dev, PORT_ALTSCP, virt_to_dma(lp, &dma->scp));
+	ca(dev);
+	if (wait_istat(dev, dma, 1000, "initialization timed out"))
+		goto failed;
+	DEB(DEB_INIT, printk(KERN_DEBUG
+			     "%s: i82596 initialization successful\n",
+			     dev->name));
+
+	if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
+		printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq);
+		goto failed;
+	}
+
+	/* Ensure rx frame/buffer descriptors are tidy */
+	rebuild_rx_bufs(dev);
+
+	dma->scb.command = 0;
+	DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+	DEB(DEB_INIT, printk(KERN_DEBUG
+			     "%s: queuing CmdConfigure\n", dev->name));
+	memcpy(dma->cf_cmd.i596_config, init_setup, 14);
+	dma->cf_cmd.cmd.command = SWAP16(CmdConfigure);
+	DMA_WBACK(dev, &(dma->cf_cmd), sizeof(struct cf_cmd));
+	i596_add_cmd(dev, &dma->cf_cmd.cmd);
+
+	DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdSASetup\n", dev->name));
+	memcpy(dma->sa_cmd.eth_addr, dev->dev_addr, 6);
+	dma->sa_cmd.cmd.command = SWAP16(CmdSASetup);
+	DMA_WBACK(dev, &(dma->sa_cmd), sizeof(struct sa_cmd));
+	i596_add_cmd(dev, &dma->sa_cmd.cmd);
+
+	DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdTDR\n", dev->name));
+	dma->tdr_cmd.cmd.command = SWAP16(CmdTDR);
+	DMA_WBACK(dev, &(dma->tdr_cmd), sizeof(struct tdr_cmd));
+	i596_add_cmd(dev, &dma->tdr_cmd.cmd);
+
+	spin_lock_irqsave (&lp->lock, flags);
+
+	if (wait_cmd(dev, dma, 1000, "timed out waiting to issue RX_START")) {
+		spin_unlock_irqrestore (&lp->lock, flags);
+		goto failed_free_irq;
+	}
+	DEB(DEB_INIT, printk(KERN_DEBUG "%s: Issuing RX_START\n", dev->name));
+	dma->scb.command = SWAP16(RX_START);
+	dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+	DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+	ca(dev);
+
+	spin_unlock_irqrestore (&lp->lock, flags);
+	if (wait_cmd(dev, dma, 1000, "RX_START not processed"))
+		goto failed_free_irq;
+	DEB(DEB_INIT, printk(KERN_DEBUG
+			     "%s: Receive unit started OK\n", dev->name));
+	return 0;
+
+failed_free_irq:
+	free_irq(dev->irq, dev);
+failed:
+	printk(KERN_ERR "%s: Failed to initialise 82596\n", dev->name);
+	mpu_port(dev, PORT_RESET, 0);
+	return -1;
+}
+
+
+static inline int i596_rx(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_rfd *rfd;
+	struct i596_rbd *rbd;
+	int frames = 0;
+
+	DEB(DEB_RXFRAME, printk(KERN_DEBUG
+				"i596_rx(), rfd_head %p, rbd_head %p\n",
+				lp->rfd_head, lp->rbd_head));
+
+
+	rfd = lp->rfd_head;		/* Ref next frame to check */
+
+	DMA_INV(dev, rfd, sizeof(struct i596_rfd));
+	while (rfd->stat & SWAP16(STAT_C)) {	/* Loop while complete frames */
+		if (rfd->rbd == I596_NULL)
+			rbd = NULL;
+		else if (rfd->rbd == lp->rbd_head->b_addr) {
+			rbd = lp->rbd_head;
+			DMA_INV(dev, rbd, sizeof(struct i596_rbd));
+		} else {
+			printk(KERN_ERR "%s: rbd chain broken!\n", dev->name);
+			/* XXX Now what? */
+			rbd = NULL;
+		}
+		DEB(DEB_RXFRAME, printk(KERN_DEBUG
+				      "  rfd %p, rfd.rbd %08x, rfd.stat %04x\n",
+				      rfd, rfd->rbd, rfd->stat));
+
+		if (rbd != NULL && (rfd->stat & SWAP16(STAT_OK))) {
+			/* a good frame */
+			int pkt_len = SWAP16(rbd->count) & 0x3fff;
+			struct sk_buff *skb = rbd->skb;
+			int rx_in_place = 0;
+
+			DEB(DEB_RXADDR, print_eth(rbd->v_data, "received"));
+			frames++;
+
+			/* Check if the packet is long enough to just accept
+			 * without copying to a properly sized skbuff.
+			 */
+
+			if (pkt_len > rx_copybreak) {
+				struct sk_buff *newskb;
+				dma_addr_t dma_addr;
+
+				dma_unmap_single(dev->dev.parent,
+						 (dma_addr_t)SWAP32(rbd->b_data),
+						 PKT_BUF_SZ, DMA_FROM_DEVICE);
+				/* Get fresh skbuff to replace filled one. */
+				newskb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4);
+				if (newskb == NULL) {
+					skb = NULL;	/* drop pkt */
+					goto memory_squeeze;
+				}
+				skb_reserve(newskb, 2);
+
+				/* Pass up the skb already on the Rx ring. */
+				skb_put(skb, pkt_len);
+				rx_in_place = 1;
+				rbd->skb = newskb;
+				dma_addr = dma_map_single(dev->dev.parent,
+							  newskb->data,
+							  PKT_BUF_SZ,
+							  DMA_FROM_DEVICE);
+				rbd->v_data = newskb->data;
+				rbd->b_data = SWAP32(dma_addr);
+				DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd));
+			} else
+				skb = netdev_alloc_skb(dev, pkt_len + 2);
+memory_squeeze:
+			if (skb == NULL) {
+				/* XXX tulip.c can defer packets here!! */
+				printk(KERN_ERR
+				       "%s: i596_rx Memory squeeze, dropping packet.\n",
+				       dev->name);
+				lp->stats.rx_dropped++;
+			} else {
+				if (!rx_in_place) {
+					/* 16 byte align the data fields */
+					dma_sync_single_for_cpu(dev->dev.parent,
+								(dma_addr_t)SWAP32(rbd->b_data),
+								PKT_BUF_SZ, DMA_FROM_DEVICE);
+					skb_reserve(skb, 2);
+					memcpy(skb_put(skb, pkt_len), rbd->v_data, pkt_len);
+					dma_sync_single_for_device(dev->dev.parent,
+								   (dma_addr_t)SWAP32(rbd->b_data),
+								   PKT_BUF_SZ, DMA_FROM_DEVICE);
+				}
+				skb->len = pkt_len;
+				skb->protocol = eth_type_trans(skb, dev);
+				netif_rx(skb);
+				dev->last_rx = jiffies;
+				lp->stats.rx_packets++;
+				lp->stats.rx_bytes += pkt_len;
+			}
+		} else {
+			DEB(DEB_ERRORS, printk(KERN_DEBUG
+					       "%s: Error, rfd.stat = 0x%04x\n",
+					       dev->name, rfd->stat));
+			lp->stats.rx_errors++;
+			if (rfd->stat & SWAP16(0x0100))
+				lp->stats.collisions++;
+			if (rfd->stat & SWAP16(0x8000))
+				lp->stats.rx_length_errors++;
+			if (rfd->stat & SWAP16(0x0001))
+				lp->stats.rx_over_errors++;
+			if (rfd->stat & SWAP16(0x0002))
+				lp->stats.rx_fifo_errors++;
+			if (rfd->stat & SWAP16(0x0004))
+				lp->stats.rx_frame_errors++;
+			if (rfd->stat & SWAP16(0x0008))
+				lp->stats.rx_crc_errors++;
+			if (rfd->stat & SWAP16(0x0010))
+				lp->stats.rx_length_errors++;
+		}
+
+		/* Clear the buffer descriptor count and EOF + F flags */
+
+		if (rbd != NULL && (rbd->count & SWAP16(0x4000))) {
+			rbd->count = 0;
+			lp->rbd_head = rbd->v_next;
+			DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd));
+		}
+
+		/* Tidy the frame descriptor, marking it as end of list */
+
+		rfd->rbd = I596_NULL;
+		rfd->stat = 0;
+		rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX);
+		rfd->count = 0;
+
+		/* Update record of next frame descriptor to process */
+
+		lp->dma->scb.rfd = rfd->b_next;
+		lp->rfd_head = rfd->v_next;
+		DMA_WBACK_INV(dev, rfd, sizeof(struct i596_rfd));
+
+		/* Remove end-of-list from old end descriptor */
+
+		rfd->v_prev->cmd = SWAP16(CMD_FLEX);
+		DMA_WBACK_INV(dev, rfd->v_prev, sizeof(struct i596_rfd));
+		rfd = lp->rfd_head;
+		DMA_INV(dev, rfd, sizeof(struct i596_rfd));
+	}
+
+	DEB(DEB_RXFRAME, printk(KERN_DEBUG "frames %d\n", frames));
+
+	return 0;
+}
+
+
+static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
+{
+	struct i596_cmd *ptr;
+
+	while (lp->cmd_head != NULL) {
+		ptr = lp->cmd_head;
+		lp->cmd_head = ptr->v_next;
+		lp->cmd_backlog--;
+
+		switch (SWAP16(ptr->command) & 0x7) {
+		case CmdTx:
+			{
+				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+				struct sk_buff *skb = tx_cmd->skb;
+				dma_unmap_single(dev->dev.parent,
+						 tx_cmd->dma_addr,
+						 skb->len, DMA_TO_DEVICE);
+
+				dev_kfree_skb(skb);
+
+				lp->stats.tx_errors++;
+				lp->stats.tx_aborted_errors++;
+
+				ptr->v_next = NULL;
+				ptr->b_next = I596_NULL;
+				tx_cmd->cmd.command = 0;  /* Mark as free */
+				break;
+			}
+		default:
+			ptr->v_next = NULL;
+			ptr->b_next = I596_NULL;
+		}
+		DMA_WBACK_INV(dev, ptr, sizeof(struct i596_cmd));
+	}
+
+	wait_cmd(dev, lp->dma, 100, "i596_cleanup_cmd timed out");
+	lp->dma->scb.cmd = I596_NULL;
+	DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+}
+
+
+static inline void i596_reset(struct net_device *dev, struct i596_private *lp)
+{
+	unsigned long flags;
+
+	DEB(DEB_RESET, printk(KERN_DEBUG "i596_reset\n"));
+
+	spin_lock_irqsave (&lp->lock, flags);
+
+	wait_cmd(dev, lp->dma, 100, "i596_reset timed out");
+
+	netif_stop_queue(dev);
+
+	/* FIXME: this command might cause an lpmc */
+	lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT);
+	DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+	ca(dev);
+
+	/* wait for shutdown */
+	wait_cmd(dev, lp->dma, 1000, "i596_reset 2 timed out");
+	spin_unlock_irqrestore (&lp->lock, flags);
+
+	i596_cleanup_cmd(dev, lp);
+	i596_rx(dev);
+
+	netif_start_queue(dev);
+	init_i596_mem(dev);
+}
+
+
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	unsigned long flags;
+
+	DEB(DEB_ADDCMD, printk(KERN_DEBUG "i596_add_cmd cmd_head %p\n",
+			       lp->cmd_head));
+
+	cmd->status = 0;
+	cmd->command |= SWAP16(CMD_EOL | CMD_INTR);
+	cmd->v_next = NULL;
+	cmd->b_next = I596_NULL;
+	DMA_WBACK(dev, cmd, sizeof(struct i596_cmd));
+
+	spin_lock_irqsave (&lp->lock, flags);
+
+	if (lp->cmd_head != NULL) {
+		lp->cmd_tail->v_next = cmd;
+		lp->cmd_tail->b_next = SWAP32(virt_to_dma(lp, &cmd->status));
+		DMA_WBACK(dev, lp->cmd_tail, sizeof(struct i596_cmd));
+	} else {
+		lp->cmd_head = cmd;
+		wait_cmd(dev, dma, 100, "i596_add_cmd timed out");
+		dma->scb.cmd = SWAP32(virt_to_dma(lp, &cmd->status));
+		dma->scb.command = SWAP16(CUC_START);
+		DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+		ca(dev);
+	}
+	lp->cmd_tail = cmd;
+	lp->cmd_backlog++;
+
+	spin_unlock_irqrestore (&lp->lock, flags);
+
+	if (lp->cmd_backlog > max_cmd_backlog) {
+		unsigned long tickssofar = jiffies - lp->last_cmd;
+
+		if (tickssofar < ticks_limit)
+			return;
+
+		printk(KERN_ERR
+		       "%s: command unit timed out, status resetting.\n",
+		       dev->name);
+#if 1
+		i596_reset(dev, lp);
+#endif
+	}
+}
+
+static int i596_open(struct net_device *dev)
+{
+	DEB(DEB_OPEN, printk(KERN_DEBUG
+			     "%s: i596_open() irq %d.\n", dev->name, dev->irq));
+
+	if (init_rx_bufs(dev)) {
+		printk(KERN_ERR "%s: Failed to init rx bufs\n", dev->name);
+		return -EAGAIN;
+	}
+	if (init_i596_mem(dev)) {
+		printk(KERN_ERR "%s: Failed to init memory\n", dev->name);
+		goto out_remove_rx_bufs;
+	}
+	netif_start_queue(dev);
+
+	return 0;
+
+out_remove_rx_bufs:
+	remove_rx_bufs(dev);
+	return -EAGAIN;
+}
+
+static void i596_tx_timeout (struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+
+	/* Transmitter timeout, serious problems. */
+	DEB(DEB_ERRORS, printk(KERN_DEBUG
+			       "%s: transmit timed out, status resetting.\n",
+			       dev->name));
+
+	lp->stats.tx_errors++;
+
+	/* Try to restart the adaptor */
+	if (lp->last_restart == lp->stats.tx_packets) {
+		DEB(DEB_ERRORS, printk(KERN_DEBUG "Resetting board.\n"));
+		/* Shutdown and restart */
+		i596_reset (dev, lp);
+	} else {
+		/* Issue a channel attention signal */
+		DEB(DEB_ERRORS, printk(KERN_DEBUG "Kicking board.\n"));
+		lp->dma->scb.command = SWAP16(CUC_START | RX_START);
+		DMA_WBACK_INV(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+		ca (dev);
+		lp->last_restart = lp->stats.tx_packets;
+	}
+
+	dev->trans_start = jiffies;
+	netif_wake_queue (dev);
+}
+
+
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct tx_cmd *tx_cmd;
+	struct i596_tbd *tbd;
+	short length = skb->len;
+	dev->trans_start = jiffies;
+
+	DEB(DEB_STARTTX, printk(KERN_DEBUG
+				"%s: i596_start_xmit(%x,%p) called\n",
+				dev->name, skb->len, skb->data));
+
+	if (length < ETH_ZLEN) {
+		if (skb_padto(skb, ETH_ZLEN))
+			return 0;
+		length = ETH_ZLEN;
+	}
+
+	netif_stop_queue(dev);
+
+	tx_cmd = lp->dma->tx_cmds + lp->next_tx_cmd;
+	tbd = lp->dma->tbds + lp->next_tx_cmd;
+
+	if (tx_cmd->cmd.command) {
+		DEB(DEB_ERRORS, printk(KERN_DEBUG
+				       "%s: xmit ring full, dropping packet.\n",
+				       dev->name));
+		lp->stats.tx_dropped++;
+
+		dev_kfree_skb(skb);
+	} else {
+		if (++lp->next_tx_cmd == TX_RING_SIZE)
+			lp->next_tx_cmd = 0;
+		tx_cmd->tbd = SWAP32(virt_to_dma(lp, tbd));
+		tbd->next = I596_NULL;
+
+		tx_cmd->cmd.command = SWAP16(CMD_FLEX | CmdTx);
+		tx_cmd->skb = skb;
+
+		tx_cmd->pad = 0;
+		tx_cmd->size = 0;
+		tbd->pad = 0;
+		tbd->size = SWAP16(EOF | length);
+
+		tx_cmd->dma_addr = dma_map_single(dev->dev.parent, skb->data,
+						  skb->len, DMA_TO_DEVICE);
+		tbd->data = SWAP32(tx_cmd->dma_addr);
+
+		DEB(DEB_TXADDR, print_eth(skb->data, "tx-queued"));
+		DMA_WBACK_INV(dev, tx_cmd, sizeof(struct tx_cmd));
+		DMA_WBACK_INV(dev, tbd, sizeof(struct i596_tbd));
+		i596_add_cmd(dev, &tx_cmd->cmd);
+
+		lp->stats.tx_packets++;
+		lp->stats.tx_bytes += length;
+	}
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static void print_eth(unsigned char *add, char *str)
+{
+	int i;
+
+	printk(KERN_DEBUG "i596 0x%p, ", add);
+	for (i = 0; i < 6; i++)
+		printk(" %02X", add[i + 6]);
+	printk(" -->");
+	for (i = 0; i < 6; i++)
+		printk(" %02X", add[i]);
+	printk(" %02X%02X, %s\n", add[12], add[13], str);
+}
+
+static int __devinit i82596_probe(struct net_device *dev)
+{
+	int i;
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma;
+
+	/* This lot is ensure things have been cache line aligned. */
+	BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
+	BUILD_BUG_ON(sizeof(struct i596_rbd) &  31);
+	BUILD_BUG_ON(sizeof(struct tx_cmd)   &  31);
+	BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
+#ifndef __LP64__
+	BUILD_BUG_ON(sizeof(struct i596_dma) > 4096);
+#endif
+
+	if (!dev->base_addr || !dev->irq)
+		return -ENODEV;
+
+	dma = (struct i596_dma *) DMA_ALLOC(dev->dev.parent,
+		sizeof(struct i596_dma), &lp->dma_addr, GFP_KERNEL);
+	if (!dma) {
+		printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
+		return -ENOMEM;
+	}
+
+	/* The 82596-specific entries in the device structure. */
+	dev->open = i596_open;
+	dev->stop = i596_close;
+	dev->hard_start_xmit = i596_start_xmit;
+	dev->get_stats = i596_get_stats;
+	dev->set_multicast_list = set_multicast_list;
+	dev->tx_timeout = i596_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = i596_poll_controller;
+#endif
+
+	memset(dma, 0, sizeof(struct i596_dma));
+	lp->dma = dma;
+
+	dma->scb.command = 0;
+	dma->scb.cmd = I596_NULL;
+	dma->scb.rfd = I596_NULL;
+	spin_lock_init(&lp->lock);
+
+	DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+
+	i = register_netdev(dev);
+	if (i) {
+		DMA_FREE(dev->dev.parent, sizeof(struct i596_dma),
+				    (void *)dma, lp->dma_addr);
+		return i;
+	};
+
+	DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,",
+			      dev->name, dev->base_addr));
+	for (i = 0; i < 6; i++)
+		DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i]));
+	DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq));
+	DEB(DEB_INIT, printk(KERN_INFO
+			     "%s: dma at 0x%p (%d bytes), lp->scb at 0x%p\n",
+			     dev->name, dma, (int)sizeof(struct i596_dma),
+			     &dma->scb));
+
+	return 0;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	i596_interrupt(dev->irq, dev);
+	enable_irq(dev->irq);
+}
+#endif
+
+static irqreturn_t i596_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct i596_private *lp;
+	struct i596_dma *dma;
+	unsigned short status, ack_cmd = 0;
+
+	if (dev == NULL) {
+		printk(KERN_WARNING "%s: irq %d for unknown device.\n",
+		       __FUNCTION__, irq);
+		return IRQ_NONE;
+	}
+
+	lp = netdev_priv(dev);
+	dma = lp->dma;
+
+	spin_lock (&lp->lock);
+
+	wait_cmd(dev, dma, 100, "i596 interrupt, timeout");
+	status = SWAP16(dma->scb.status);
+
+	DEB(DEB_INTS, printk(KERN_DEBUG
+			     "%s: i596 interrupt, IRQ %d, status %4.4x.\n",
+			dev->name, irq, status));
+
+	ack_cmd = status & 0xf000;
+
+	if (!ack_cmd) {
+		DEB(DEB_ERRORS, printk(KERN_DEBUG
+				       "%s: interrupt with no events\n",
+				       dev->name));
+		spin_unlock (&lp->lock);
+		return IRQ_NONE;
+	}
+
+	if ((status & 0x8000) || (status & 0x2000)) {
+		struct i596_cmd *ptr;
+
+		if ((status & 0x8000))
+			DEB(DEB_INTS,
+			    printk(KERN_DEBUG
+				   "%s: i596 interrupt completed command.\n",
+				   dev->name));
+		if ((status & 0x2000))
+			DEB(DEB_INTS,
+			    printk(KERN_DEBUG
+				   "%s: i596 interrupt command unit inactive %x.\n",
+				   dev->name, status & 0x0700));
+
+		while (lp->cmd_head != NULL) {
+			DMA_INV(dev, lp->cmd_head, sizeof(struct i596_cmd));
+			if (!(lp->cmd_head->status & SWAP16(STAT_C)))
+				break;
+
+			ptr = lp->cmd_head;
+
+			DEB(DEB_STATUS,
+			    printk(KERN_DEBUG
+				   "cmd_head->status = %04x, ->command = %04x\n",
+				   SWAP16(lp->cmd_head->status),
+				   SWAP16(lp->cmd_head->command)));
+			lp->cmd_head = ptr->v_next;
+			lp->cmd_backlog--;
+
+			switch (SWAP16(ptr->command) & 0x7) {
+			case CmdTx:
+			    {
+				struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+				struct sk_buff *skb = tx_cmd->skb;
+
+				if (ptr->status & SWAP16(STAT_OK)) {
+					DEB(DEB_TXADDR,
+					    print_eth(skb->data, "tx-done"));
+				} else {
+					lp->stats.tx_errors++;
+					if (ptr->status & SWAP16(0x0020))
+						lp->stats.collisions++;
+					if (!(ptr->status & SWAP16(0x0040)))
+						lp->stats.tx_heartbeat_errors++;
+					if (ptr->status & SWAP16(0x0400))
+						lp->stats.tx_carrier_errors++;
+					if (ptr->status & SWAP16(0x0800))
+						lp->stats.collisions++;
+					if (ptr->status & SWAP16(0x1000))
+						lp->stats.tx_aborted_errors++;
+				}
+				dma_unmap_single(dev->dev.parent,
+						 tx_cmd->dma_addr,
+						 skb->len, DMA_TO_DEVICE);
+				dev_kfree_skb_irq(skb);
+
+				tx_cmd->cmd.command = 0; /* Mark free */
+				break;
+			    }
+			case CmdTDR:
+			    {
+				unsigned short status = SWAP16(((struct tdr_cmd *)ptr)->status);
+
+				if (status & 0x8000) {
+					DEB(DEB_ANY,
+					    printk(KERN_DEBUG "%s: link ok.\n",
+						   dev->name));
+				} else {
+					if (status & 0x4000)
+						printk(KERN_ERR
+						       "%s: Transceiver problem.\n",
+						       dev->name);
+					if (status & 0x2000)
+						printk(KERN_ERR
+						       "%s: Termination problem.\n",
+						       dev->name);
+					if (status & 0x1000)
+						printk(KERN_ERR
+						       "%s: Short circuit.\n",
+						       dev->name);
+
+					DEB(DEB_TDR,
+					    printk(KERN_DEBUG "%s: Time %d.\n",
+						   dev->name, status & 0x07ff));
+				}
+				break;
+			    }
+			case CmdConfigure:
+				/*
+				 * Zap command so set_multicast_list() know
+				 * it is free
+				 */
+				ptr->command = 0;
+				break;
+			}
+			ptr->v_next = NULL;
+			ptr->b_next = I596_NULL;
+			DMA_WBACK(dev, ptr, sizeof(struct i596_cmd));
+			lp->last_cmd = jiffies;
+		}
+
+		/* This mess is arranging that only the last of any outstanding
+		 * commands has the interrupt bit set.  Should probably really
+		 * only add to the cmd queue when the CU is stopped.
+		 */
+		ptr = lp->cmd_head;
+		while ((ptr != NULL) && (ptr != lp->cmd_tail)) {
+			struct i596_cmd *prev = ptr;
+
+			ptr->command &= SWAP16(0x1fff);
+			ptr = ptr->v_next;
+			DMA_WBACK_INV(dev, prev, sizeof(struct i596_cmd));
+		}
+
+		if (lp->cmd_head != NULL)
+			ack_cmd |= CUC_START;
+		dma->scb.cmd = SWAP32(virt_to_dma(lp, &lp->cmd_head->status));
+		DMA_WBACK_INV(dev, &dma->scb, sizeof(struct i596_scb));
+	}
+	if ((status & 0x1000) || (status & 0x4000)) {
+		if ((status & 0x4000))
+			DEB(DEB_INTS,
+			    printk(KERN_DEBUG
+				   "%s: i596 interrupt received a frame.\n",
+				   dev->name));
+		i596_rx(dev);
+		/* Only RX_START if stopped - RGH 07-07-96 */
+		if (status & 0x1000) {
+			if (netif_running(dev)) {
+				DEB(DEB_ERRORS,
+				    printk(KERN_DEBUG
+					   "%s: i596 interrupt receive unit inactive, status 0x%x\n",
+					   dev->name, status));
+				ack_cmd |= RX_START;
+				lp->stats.rx_errors++;
+				lp->stats.rx_fifo_errors++;
+				rebuild_rx_bufs(dev);
+			}
+		}
+	}
+	wait_cmd(dev, dma, 100, "i596 interrupt, timeout");
+	dma->scb.command = SWAP16(ack_cmd);
+	DMA_WBACK(dev, &dma->scb, sizeof(struct i596_scb));
+
+	/* DANGER: I suspect that some kind of interrupt
+	 acknowledgement aside from acking the 82596 might be needed
+	 here...  but it's running acceptably without */
+
+	ca(dev);
+
+	wait_cmd(dev, dma, 100, "i596 interrupt, exit timeout");
+	DEB(DEB_INTS, printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name));
+
+	spin_unlock (&lp->lock);
+	return IRQ_HANDLED;
+}
+
+static int i596_close(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	unsigned long flags;
+
+	netif_stop_queue(dev);
+
+	DEB(DEB_INIT,
+	    printk(KERN_DEBUG
+		   "%s: Shutting down ethercard, status was %4.4x.\n",
+		   dev->name, SWAP16(lp->dma->scb.status)));
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	wait_cmd(dev, lp->dma, 100, "close1 timed out");
+	lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT);
+	DMA_WBACK(dev, &lp->dma->scb, sizeof(struct i596_scb));
+
+	ca(dev);
+
+	wait_cmd(dev, lp->dma, 100, "close2 timed out");
+	spin_unlock_irqrestore(&lp->lock, flags);
+	DEB(DEB_STRUCT, i596_display_data(dev));
+	i596_cleanup_cmd(dev, lp);
+
+	free_irq(dev->irq, dev);
+	remove_rx_bufs(dev);
+
+	return 0;
+}
+
+static struct net_device_stats *i596_get_stats(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+
+	return &lp->stats;
+}
+
+/*
+ *    Set or clear the multicast filter for this adaptor.
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+	struct i596_dma *dma = lp->dma;
+	int config = 0, cnt;
+
+	DEB(DEB_MULTI,
+	    printk(KERN_DEBUG
+		   "%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
+		   dev->name, dev->mc_count,
+		   dev->flags & IFF_PROMISC ? "ON" : "OFF",
+		   dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
+
+	if ((dev->flags & IFF_PROMISC) &&
+	    !(dma->cf_cmd.i596_config[8] & 0x01)) {
+		dma->cf_cmd.i596_config[8] |= 0x01;
+		config = 1;
+	}
+	if (!(dev->flags & IFF_PROMISC) &&
+	    (dma->cf_cmd.i596_config[8] & 0x01)) {
+		dma->cf_cmd.i596_config[8] &= ~0x01;
+		config = 1;
+	}
+	if ((dev->flags & IFF_ALLMULTI) &&
+	    (dma->cf_cmd.i596_config[11] & 0x20)) {
+		dma->cf_cmd.i596_config[11] &= ~0x20;
+		config = 1;
+	}
+	if (!(dev->flags & IFF_ALLMULTI) &&
+	    !(dma->cf_cmd.i596_config[11] & 0x20)) {
+		dma->cf_cmd.i596_config[11] |= 0x20;
+		config = 1;
+	}
+	if (config) {
+		if (dma->cf_cmd.cmd.command)
+			printk(KERN_INFO
+			       "%s: config change request already queued\n",
+			       dev->name);
+		else {
+			dma->cf_cmd.cmd.command = SWAP16(CmdConfigure);
+			DMA_WBACK_INV(dev, &dma->cf_cmd, sizeof(struct cf_cmd));
+			i596_add_cmd(dev, &dma->cf_cmd.cmd);
+		}
+	}
+
+	cnt = dev->mc_count;
+	if (cnt > MAX_MC_CNT) {
+		cnt = MAX_MC_CNT;
+		printk(KERN_NOTICE "%s: Only %d multicast addresses supported",
+			dev->name, cnt);
+	}
+
+	if (dev->mc_count > 0) {
+		struct dev_mc_list *dmi;
+		unsigned char *cp;
+		struct mc_cmd *cmd;
+
+		cmd = &dma->mc_cmd;
+		cmd->cmd.command = SWAP16(CmdMulticastList);
+		cmd->mc_cnt = SWAP16(dev->mc_count * 6);
+		cp = cmd->mc_addrs;
+		for (dmi = dev->mc_list;
+		     cnt && dmi != NULL;
+		     dmi = dmi->next, cnt--, cp += 6) {
+			memcpy(cp, dmi->dmi_addr, 6);
+			if (i596_debug > 1)
+				DEB(DEB_MULTI,
+				    printk(KERN_DEBUG
+					   "%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
+					   dev->name, cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]));
+		}
+		DMA_WBACK_INV(dev, &dma->mc_cmd, sizeof(struct mc_cmd));
+		i596_add_cmd(dev, &cmd->cmd);
+	}
+}
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index fef3193..9a343b96 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -577,7 +577,7 @@
 	struct mace_data *mp = netdev_priv(dev);
 	volatile struct mace *mb = mp->mace;
 	int intr, fs;
-	unsigned int flags;
+	unsigned long flags;
 
 	/* don't want the dma interrupt handler to fire */
 	local_irq_save(flags);
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index 7f8b7d5..492cfaa 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -113,8 +113,7 @@
 	struct mlx4_cmd_mailbox *mailbox;
 	int ret = 0;
 
-	if (cur_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
-	    new_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
+	if (cur_state >= MLX4_QP_NUM_STATE || cur_state >= MLX4_QP_NUM_STATE ||
 	    !op[cur_state][new_state])
 		return -EINVAL;
 
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index d0cc122..e1732c1 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -60,6 +60,7 @@
 #include <linux/crc32.h>
 #include <linux/moduleparam.h>
 #include <linux/io.h>
+#include <linux/log2.h>
 #include <net/checksum.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -1804,7 +1805,7 @@
 	 */
 	big_pow2 = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
 	if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) {
-		while ((big_pow2 & (big_pow2 - 1)) != 0)
+		while (!is_power_of_2(big_pow2))
 			big_pow2++;
 		mgp->big_bytes = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
 	} else {
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 460a0871..3450051 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -2357,8 +2357,8 @@
 					np->rx_dma[entry],
 					buflen,
 					PCI_DMA_FROMDEVICE);
-				eth_copy_and_sum(skb,
-					np->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb,
+					np->rx_skbuff[entry]->data, pkt_len);
 				skb_put(skb, pkt_len);
 				pci_dma_sync_single_for_device(np->pci_dev,
 					np->rx_dma[entry],
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 6195037..325269d 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -1097,109 +1097,6 @@
 int netxen_nic_set_mac(struct net_device *netdev, void *p);
 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
 
-static inline void netxen_nic_disable_int(struct netxen_adapter *adapter)
-{
-	uint32_t	mask = 0x7ff;
-	int retries = 32;
-
-	DPRINTK(1, INFO, "Entered ISR Disable \n");
-
-	switch (adapter->portnum) {
-	case 0:
-		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
-		break;
-	case 1:
-		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
-		break;
-	case 2:
-		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
-		break;
-	case 3:
-		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
-		break;
-	}
-
-	if (adapter->intr_scheme != -1 &&
-		adapter->intr_scheme != INTR_SCHEME_PERPORT) {
-		writel(mask,
-			(void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)));
-	}
-
-	/* Window = 0 or 1 */
-	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
-		do {
-			writel(0xffffffff, (void *)
-				(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS)));
-			mask = readl((void *)
-					(pci_base_offset(adapter, ISR_INT_VECTOR)));
-			if (!(mask & 0x80))
-				break;
-			udelay(10);
-		} while (--retries);
-
-		if (!retries) {
-			printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n",
-					netxen_nic_driver_name);
-		}
-	}
-
-	DPRINTK(1, INFO, "Done with Disable Int\n");
-
-	return;
-}
-
-static inline void netxen_nic_enable_int(struct netxen_adapter *adapter)
-{
-	u32 mask;
-
-	DPRINTK(1, INFO, "Entered ISR Enable \n");
-
-	if (adapter->intr_scheme != -1 &&
-		adapter->intr_scheme != INTR_SCHEME_PERPORT) {
-		switch (adapter->ahw.board_type) {
-		case NETXEN_NIC_GBE:
-			mask  =  0x77b;
-			break;
-		case NETXEN_NIC_XGBE:
-			mask  =  0x77f;
-			break;
-		default:
-			mask  =  0x7ff;
-			break;
-		}
-
-		writel(mask,
-			(void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)));
-	}
-	switch (adapter->portnum) {
-	case 0:
-		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
-		break;
-	case 1:
-		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
-		break;
-	case 2:
-		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
-		break;
-	case 3:
-		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
-		break;
-	}
-
-	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
-		mask = 0xbff;
-		if (adapter->intr_scheme != -1 &&
-			adapter->intr_scheme != INTR_SCHEME_PERPORT) {
-			writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
-		}
-		writel(mask,
-			(void *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK)));
-	}
-
-	DPRINTK(1, INFO, "Done with enable Int\n");
-
-	return;
-}
 
 /*
  * NetXen Board information
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index a66ff58..56f8197 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -156,6 +156,103 @@
 #define	ADAPTER_LIST_SIZE 12
 int netxen_cards_found;
 
+static void netxen_nic_disable_int(struct netxen_adapter *adapter)
+{
+	uint32_t	mask = 0x7ff;
+	int retries = 32;
+
+	DPRINTK(1, INFO, "Entered ISR Disable \n");
+
+	switch (adapter->portnum) {
+	case 0:
+		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
+		break;
+	case 1:
+		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
+		break;
+	case 2:
+		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
+		break;
+	case 3:
+		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
+		break;
+	}
+
+	if (adapter->intr_scheme != -1 &&
+	    adapter->intr_scheme != INTR_SCHEME_PERPORT)
+		writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+
+	/* Window = 0 or 1 */
+	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+		do {
+			writel(0xffffffff,
+			       PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS));
+			mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
+			if (!(mask & 0x80))
+				break;
+			udelay(10);
+		} while (--retries);
+
+		if (!retries) {
+			printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n",
+					netxen_nic_driver_name);
+		}
+	}
+
+	DPRINTK(1, INFO, "Done with Disable Int\n");
+}
+
+static void netxen_nic_enable_int(struct netxen_adapter *adapter)
+{
+	u32 mask;
+
+	DPRINTK(1, INFO, "Entered ISR Enable \n");
+
+	if (adapter->intr_scheme != -1 &&
+		adapter->intr_scheme != INTR_SCHEME_PERPORT) {
+		switch (adapter->ahw.board_type) {
+		case NETXEN_NIC_GBE:
+			mask  =  0x77b;
+			break;
+		case NETXEN_NIC_XGBE:
+			mask  =  0x77f;
+			break;
+		default:
+			mask  =  0x7ff;
+			break;
+		}
+
+		writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+	}
+
+	switch (adapter->portnum) {
+	case 0:
+		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
+		break;
+	case 1:
+		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
+		break;
+	case 2:
+		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
+		break;
+	case 3:
+		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
+		break;
+	}
+
+	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+		mask = 0xbff;
+		if (adapter->intr_scheme != -1 &&
+			adapter->intr_scheme != INTR_SCHEME_PERPORT) {
+			writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+		}
+		writel(mask,
+		       PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK));
+	}
+
+	DPRINTK(1, INFO, "Done with enable Int\n");
+}
+
 /*
  * netxen_nic_probe()
  *
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index 75102d3..05e0577 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -724,7 +724,7 @@
 	__u32 mac_cfg0;
 	u32 port = physical_port[adapter->portnum];
 
-	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+	if (port > NETXEN_NIU_MAX_GBE_PORTS)
 		return -EINVAL;
 	mac_cfg0 = 0;
 	netxen_gb_soft_reset(mac_cfg0);
@@ -757,7 +757,7 @@
 	__u32 reg;
 	u32 port = physical_port[adapter->portnum];
 
-	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+	if (port > NETXEN_NIU_MAX_GBE_PORTS)
 		return -EINVAL;
 
 	/* save previous contents */
@@ -894,7 +894,7 @@
 	__u32 reg;
 	u32 port = physical_port[adapter->portnum];
 
-	if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
+	if (port > NETXEN_NIU_MAX_XG_PORTS)
 		return -EINVAL;
 
 	if (netxen_nic_hw_read_wx(adapter,
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index 8dbd6d1..5e7999d 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -936,7 +936,7 @@
 					{
 						skb_reserve(skb,2);
 						skb_put(skb,totlen);
-						eth_copy_and_sum(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen,0);
+						skb_copy_to_linear_data(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen);
 						skb->protocol=eth_type_trans(skb,dev);
 						netif_rx(skb);
 						dev->last_rx = jiffies;
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index 3818edf..4ef5fe3 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -1096,7 +1096,7 @@
 #ifdef RCV_VIA_SKB
 				if( (unsigned long) (skb->data + R_BUF_SIZE) > 0x1000000) {
 					skb_put(skb,len);
-					eth_copy_and_sum(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len,0);
+					skb_copy_to_linear_data(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len);
 				}
 				else {
 					struct sk_buff *skb1 = p->recv_skb[p->rmdnum];
@@ -1108,7 +1108,7 @@
 				}
 #else
 				skb_put(skb,len);
-				eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0);
+				skb_copy_to_linear_data(skb, (unsigned char *) p->recvbounce[p->rmdnum],len);
 #endif
 				p->stats.rx_packets++;
 				p->stats.rx_bytes += len;
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 8d38425..0b3066a 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -755,7 +755,7 @@
 	flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
 
 	pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
-			       PAS_IOB_DMA_RXCH_CFG_CNTTH(1));
+			       PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
 
 	pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
 			       PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index df8998b..3cdbe118 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -1567,7 +1567,7 @@
 		if (skb) {
 			skb_reserve (skb, 2);	/* 16 byte align the IP fields. */
 
-			eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+			skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size);
 			skb_put (skb, pkt_size);
 
 			skb->protocol = eth_type_trans (skb, dev);
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 808fae1..50dff1b 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -521,6 +521,7 @@
 
 static int axnet_open(struct net_device *dev)
 {
+    int ret;
     axnet_dev_t *info = PRIV(dev);
     struct pcmcia_device *link = info->p_dev;
     
@@ -529,9 +530,11 @@
     if (!pcmcia_dev_present(link))
 	return -ENODEV;
 
-    link->open++;
+    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+    if (ret)
+	    return ret;
 
-    request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+    link->open++;
 
     info->link_status = 0x00;
     init_timer(&info->watchdog);
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 3f93d49..85d5f2c 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -109,7 +109,7 @@
     card type
  */
 typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, 
-	       XXX10304
+	       XXX10304, NEC, KME
 } cardtype_t;
 
 /*
@@ -374,6 +374,18 @@
 		link->io.NumPorts2 = 8;
 	    }
 	    break;
+	case MANFID_NEC:
+	    cardtype = NEC; /* MultiFunction Card */
+	    link->conf.ConfigBase = 0x800;
+	    link->conf.ConfigIndex = 0x47;
+	    link->io.NumPorts2 = 8;
+	    break;
+	case MANFID_KME:
+	    cardtype = KME; /* MultiFunction Card */
+	    link->conf.ConfigBase = 0x800;
+	    link->conf.ConfigIndex = 0x47;
+	    link->io.NumPorts2 = 8;
+	    break;
 	case MANFID_CONTEC:
 	    cardtype = CONTEC;
 	    break;
@@ -450,6 +462,8 @@
     case TDK:
     case LA501:
     case CONTEC:
+    case NEC:
+    case KME:
 	tuple.DesiredTuple = CISTPL_FUNCE;
 	tuple.TupleOffset = 0;
 	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
@@ -469,6 +483,10 @@
 		card_name = "TDK LAK-CD021";
 	    } else if( cardtype == LA501 ) {
 		card_name = "LA501";
+	    } else if( cardtype == NEC ) {
+		card_name = "PK-UG-J001";
+	    } else if( cardtype == KME ) {
+		card_name = "Panasonic";
 	    } else {
 		card_name = "C-NET(PC)C";
 	    }
@@ -678,8 +696,11 @@
 	PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
 	PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
+	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
 	PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index d88e9b2..63de89e 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -960,6 +960,7 @@
 
 static int pcnet_open(struct net_device *dev)
 {
+    int ret;
     pcnet_dev_t *info = PRIV(dev);
     struct pcmcia_device *link = info->p_dev;
 
@@ -968,10 +969,12 @@
     if (!pcmcia_dev_present(link))
 	return -ENODEV;
 
-    link->open++;
-
     set_misc_reg(dev);
-    request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
+    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
+    if (ret)
+	    return ret;
+
+    link->open++;
 
     info->phy_id = info->eth_phy;
     info->link_status = 0x00;
@@ -1552,6 +1555,7 @@
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
+	PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
 	PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card       ", 0xb569a6e5, 0x5bd4ff2c),
@@ -1577,6 +1581,7 @@
 	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103),
 	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121),
 	PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941),
+	PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e),
 	PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b),
 	PCMCIA_DEVICE_PROD_ID123("CNet  ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b),
 	PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e),
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 9c171a7..465485a 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1235,9 +1235,9 @@
 					    lp->rx_dma_addr[entry],
 					    pkt_len,
 					    PCI_DMA_FROMDEVICE);
-		eth_copy_and_sum(skb,
+		skb_copy_to_linear_data(skb,
 				 (unsigned char *)(lp->rx_skbuff[entry]->data),
-				 pkt_len, 0);
+				 pkt_len);
 		pci_dma_sync_single_for_device(lp->pci_dev,
 					       lp->rx_dma_addr[entry],
 					       pkt_len,
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 09b6f25..dd09011 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -55,6 +55,11 @@
 	---help---
 	  Currently supports the BCM5411, BCM5421 and BCM5461 PHYs.
 
+config ICPLUS_PHY
+	tristate "Drivers for ICPlus PHYs"
+	---help---
+	  Currently supports the IP175C PHY.
+
 config FIXED_PHY
 	tristate "Drivers for PHY emulation on fixed speed/link"
 	---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index bcd1efb..8885650 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -11,4 +11,5 @@
 obj-$(CONFIG_SMSC_PHY)		+= smsc.o
 obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o
 obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o
+obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
 obj-$(CONFIG_FIXED_PHY)		+= fixed.o
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
new file mode 100644
index 0000000..af3f1f2
--- /dev/null
+++ b/drivers/net/phy/icplus.c
@@ -0,0 +1,134 @@
+/*
+ * Driver for ICPlus PHYs
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+MODULE_DESCRIPTION("ICPlus IP175C PHY driver");
+MODULE_AUTHOR("Michael Barkowski");
+MODULE_LICENSE("GPL");
+
+static int ip175c_config_init(struct phy_device *phydev)
+{
+	int err, i;
+	static int full_reset_performed = 0;
+
+	if (full_reset_performed == 0) {
+
+		/* master reset */
+		err = phydev->bus->write(phydev->bus, 30, 0, 0x175c);
+		if (err < 0)
+			return err;
+
+		/* ensure no bus delays overlap reset period */
+		err = phydev->bus->read(phydev->bus, 30, 0);
+
+		/* data sheet specifies reset period is 2 msec */
+		mdelay(2);
+
+		/* enable IP175C mode */
+		err = phydev->bus->write(phydev->bus, 29, 31, 0x175c);
+		if (err < 0)
+			return err;
+
+		/* Set MII0 speed and duplex (in PHY mode) */
+		err = phydev->bus->write(phydev->bus, 29, 22, 0x420);
+		if (err < 0)
+			return err;
+
+		/* reset switch ports */
+		for (i = 0; i < 5; i++) {
+			err = phydev->bus->write(phydev->bus, i,
+						 MII_BMCR, BMCR_RESET);
+			if (err < 0)
+				return err;
+		}
+
+		for (i = 0; i < 5; i++)
+			err = phydev->bus->read(phydev->bus, i, MII_BMCR);
+
+		mdelay(2);
+
+		full_reset_performed = 1;
+	}
+
+	if (phydev->addr != 4) {
+		phydev->state = PHY_RUNNING;
+		phydev->speed = SPEED_100;
+		phydev->duplex = DUPLEX_FULL;
+		phydev->link = 1;
+		netif_carrier_on(phydev->attached_dev);
+	}
+
+	return 0;
+}
+
+static int ip175c_read_status(struct phy_device *phydev)
+{
+	if (phydev->addr == 4) /* WAN port */
+		genphy_read_status(phydev);
+	else
+		/* Don't need to read status for switch ports */
+		phydev->irq = PHY_IGNORE_INTERRUPT;
+
+	return 0;
+}
+
+static int ip175c_config_aneg(struct phy_device *phydev)
+{
+	if (phydev->addr == 4) /* WAN port */
+		genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static struct phy_driver ip175c_driver = {
+	.phy_id		= 0x02430d80,
+	.name		= "ICPlus IP175C",
+	.phy_id_mask	= 0x0ffffff0,
+	.features	= PHY_BASIC_FEATURES,
+	.config_init	= &ip175c_config_init,
+	.config_aneg	= &ip175c_config_aneg,
+	.read_status	= &ip175c_read_status,
+	.driver		= { .owner = THIS_MODULE,},
+};
+
+static int __init ip175c_init(void)
+{
+	return phy_driver_register(&ip175c_driver);
+}
+
+static void __exit ip175c_exit(void)
+{
+	phy_driver_unregister(&ip175c_driver);
+}
+
+module_init(ip175c_init);
+module_exit(ip175c_exit);
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index b87f8d2..d2ede5f 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -60,6 +60,7 @@
 #define MII_M1111_PHY_EXT_SR		0x1b
 #define MII_M1111_HWCFG_MODE_MASK	0xf
 #define MII_M1111_HWCFG_MODE_RGMII	0xb
+#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK	0x4
 
 MODULE_DESCRIPTION("Marvell PHY driver");
 MODULE_AUTHOR("Andy Fleming");
@@ -169,6 +170,21 @@
 			return err;
 	}
 
+	if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
+		int temp;
+
+		temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
+		if (temp < 0)
+			return temp;
+
+		temp &= ~(MII_M1111_HWCFG_MODE_MASK);
+		temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK;
+
+		err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
+		if (err < 0)
+			return err;
+	}
+
 	err = phy_write(phydev, MII_BMCR, BMCR_RESET);
 	if (err < 0)
 		return err;
@@ -238,77 +254,84 @@
 	return 0;
 }
 
-static struct phy_driver m88e1101_driver = {
-	.phy_id = 0x01410c60,
-	.phy_id_mask = 0xfffffff0,
-	.name = "Marvell 88E1101",
-	.features = PHY_GBIT_FEATURES,
-	.flags = PHY_HAS_INTERRUPT,
-	.config_aneg = &marvell_config_aneg,
-	.read_status = &genphy_read_status,
-	.ack_interrupt = &marvell_ack_interrupt,
-	.config_intr = &marvell_config_intr,
-	.driver = {.owner = THIS_MODULE,},
-};
-
-static struct phy_driver m88e1111_driver = {
-	.phy_id = 0x01410cc0,
-	.phy_id_mask = 0xfffffff0,
-	.name = "Marvell 88E1111",
-	.features = PHY_GBIT_FEATURES,
-	.flags = PHY_HAS_INTERRUPT,
-	.config_aneg = &marvell_config_aneg,
-	.read_status = &genphy_read_status,
-	.ack_interrupt = &marvell_ack_interrupt,
-	.config_intr = &marvell_config_intr,
-	.config_init = &m88e1111_config_init,
-	.driver = {.owner = THIS_MODULE,},
-};
-
-static struct phy_driver m88e1145_driver = {
-	.phy_id = 0x01410cd0,
-	.phy_id_mask = 0xfffffff0,
-	.name = "Marvell 88E1145",
-	.features = PHY_GBIT_FEATURES,
-	.flags = PHY_HAS_INTERRUPT,
-	.config_init = &m88e1145_config_init,
-	.config_aneg = &marvell_config_aneg,
-	.read_status = &genphy_read_status,
-	.ack_interrupt = &marvell_ack_interrupt,
-	.config_intr = &marvell_config_intr,
-	.driver = {.owner = THIS_MODULE,},
+static struct phy_driver marvell_drivers[] = {
+	{
+		.phy_id = 0x01410c60,
+		.phy_id_mask = 0xfffffff0,
+		.name = "Marvell 88E1101",
+		.features = PHY_GBIT_FEATURES,
+		.flags = PHY_HAS_INTERRUPT,
+		.config_aneg = &marvell_config_aneg,
+		.read_status = &genphy_read_status,
+		.ack_interrupt = &marvell_ack_interrupt,
+		.config_intr = &marvell_config_intr,
+		.driver = {.owner = THIS_MODULE,},
+	},
+	{
+		.phy_id = 0x01410c90,
+		.phy_id_mask = 0xfffffff0,
+		.name = "Marvell 88E1112",
+		.features = PHY_GBIT_FEATURES,
+		.flags = PHY_HAS_INTERRUPT,
+		.config_init = &m88e1111_config_init,
+		.config_aneg = &marvell_config_aneg,
+		.read_status = &genphy_read_status,
+		.ack_interrupt = &marvell_ack_interrupt,
+		.config_intr = &marvell_config_intr,
+		.driver = {.owner = THIS_MODULE,},
+	},
+	{
+		.phy_id = 0x01410cc0,
+		.phy_id_mask = 0xfffffff0,
+		.name = "Marvell 88E1111",
+		.features = PHY_GBIT_FEATURES,
+		.flags = PHY_HAS_INTERRUPT,
+		.config_init = &m88e1111_config_init,
+		.config_aneg = &marvell_config_aneg,
+		.read_status = &genphy_read_status,
+		.ack_interrupt = &marvell_ack_interrupt,
+		.config_intr = &marvell_config_intr,
+		.driver = {.owner = THIS_MODULE,},
+	},
+	{
+		.phy_id = 0x01410cd0,
+		.phy_id_mask = 0xfffffff0,
+		.name = "Marvell 88E1145",
+		.features = PHY_GBIT_FEATURES,
+		.flags = PHY_HAS_INTERRUPT,
+		.config_init = &m88e1145_config_init,
+		.config_aneg = &marvell_config_aneg,
+		.read_status = &genphy_read_status,
+		.ack_interrupt = &marvell_ack_interrupt,
+		.config_intr = &marvell_config_intr,
+		.driver = {.owner = THIS_MODULE,},
+	}
 };
 
 static int __init marvell_init(void)
 {
 	int ret;
+	int i;
 
-	ret = phy_driver_register(&m88e1101_driver);
-	if (ret)
-		return ret;
+	for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) {
+		ret = phy_driver_register(&marvell_drivers[i]);
 
-	ret = phy_driver_register(&m88e1111_driver);
-	if (ret)
-		goto err1111;
-
-	ret = phy_driver_register(&m88e1145_driver);
-	if (ret)
-		goto err1145;
+		if (ret) {
+			while (i-- > 0)
+				phy_driver_unregister(&marvell_drivers[i]);
+			return ret;
+		}
+	}
 
 	return 0;
-
-err1145:
-	phy_driver_unregister(&m88e1111_driver);
-err1111:
-	phy_driver_unregister(&m88e1101_driver);
-	return ret;
 }
 
 static void __exit marvell_exit(void)
 {
-	phy_driver_unregister(&m88e1101_driver);
-	phy_driver_unregister(&m88e1111_driver);
-	phy_driver_unregister(&m88e1145_driver);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++)
+		phy_driver_unregister(&marvell_drivers[i]);
 }
 
 module_init(marvell_init);
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
new file mode 100644
index 0000000..5891a0f
--- /dev/null
+++ b/drivers/net/pppol2tp.c
@@ -0,0 +1,2486 @@
+/*****************************************************************************
+ * Linux PPP over L2TP (PPPoX/PPPoL2TP) Sockets
+ *
+ * PPPoX    --- Generic PPP encapsulation socket family
+ * PPPoL2TP --- PPP over L2TP (RFC 2661)
+ *
+ * Version:	1.0.0
+ *
+ * Authors:	Martijn van Oosterhout <kleptog@svana.org>
+ *		James Chapman (jchapman@katalix.com)
+ * Contributors:
+ *		Michal Ostrowski <mostrows@speakeasy.net>
+ *		Arnaldo Carvalho de Melo <acme@xconectiva.com.br>
+ *		David S. Miller (davem@redhat.com)
+ *
+ * License:
+ *		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 driver handles only L2TP data frames; control frames are handled by a
+ * userspace application.
+ *
+ * To send data in an L2TP session, userspace opens a PPPoL2TP socket and
+ * attaches it to a bound UDP socket with local tunnel_id / session_id and
+ * peer tunnel_id / session_id set. Data can then be sent or received using
+ * regular socket sendmsg() / recvmsg() calls. Kernel parameters of the socket
+ * can be read or modified using ioctl() or [gs]etsockopt() calls.
+ *
+ * When a PPPoL2TP socket is connected with local and peer session_id values
+ * zero, the socket is treated as a special tunnel management socket.
+ *
+ * Here's example userspace code to create a socket for sending/receiving data
+ * over an L2TP session:-
+ *
+ *	struct sockaddr_pppol2tp sax;
+ *	int fd;
+ *	int session_fd;
+ *
+ *	fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
+ *
+ *	sax.sa_family = AF_PPPOX;
+ *	sax.sa_protocol = PX_PROTO_OL2TP;
+ *	sax.pppol2tp.fd = tunnel_fd;	// bound UDP socket
+ *	sax.pppol2tp.addr.sin_addr.s_addr = addr->sin_addr.s_addr;
+ *	sax.pppol2tp.addr.sin_port = addr->sin_port;
+ *	sax.pppol2tp.addr.sin_family = AF_INET;
+ *	sax.pppol2tp.s_tunnel  = tunnel_id;
+ *	sax.pppol2tp.s_session = session_id;
+ *	sax.pppol2tp.d_tunnel  = peer_tunnel_id;
+ *	sax.pppol2tp.d_session = peer_session_id;
+ *
+ *	session_fd = connect(fd, (struct sockaddr *)&sax, sizeof(sax));
+ *
+ * A pppd plugin that allows PPP traffic to be carried over L2TP using
+ * this driver is available from the OpenL2TP project at
+ * http://openl2tp.sourceforge.net.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/jiffies.h>
+
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/inetdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/if_pppox.h>
+#include <linux/if_pppol2tp.h>
+#include <net/sock.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/file.h>
+#include <linux/hash.h>
+#include <linux/sort.h>
+#include <linux/proc_fs.h>
+#include <net/dst.h>
+#include <net/ip.h>
+#include <net/udp.h>
+#include <net/xfrm.h>
+
+#include <asm/byteorder.h>
+#include <asm/atomic.h>
+
+
+#define PPPOL2TP_DRV_VERSION	"V1.0"
+
+/* L2TP header constants */
+#define L2TP_HDRFLAG_T	   0x8000
+#define L2TP_HDRFLAG_L	   0x4000
+#define L2TP_HDRFLAG_S	   0x0800
+#define L2TP_HDRFLAG_O	   0x0200
+#define L2TP_HDRFLAG_P	   0x0100
+
+#define L2TP_HDR_VER_MASK  0x000F
+#define L2TP_HDR_VER	   0x0002
+
+/* Space for UDP, L2TP and PPP headers */
+#define PPPOL2TP_HEADER_OVERHEAD	40
+
+/* Just some random numbers */
+#define L2TP_TUNNEL_MAGIC	0x42114DDA
+#define L2TP_SESSION_MAGIC	0x0C04EB7D
+
+#define PPPOL2TP_HASH_BITS	4
+#define PPPOL2TP_HASH_SIZE	(1 << PPPOL2TP_HASH_BITS)
+
+/* Default trace flags */
+#define PPPOL2TP_DEFAULT_DEBUG_FLAGS	0
+
+#define PRINTK(_mask, _type, _lvl, _fmt, args...)			\
+	do {								\
+		if ((_mask) & (_type))					\
+			printk(_lvl "PPPOL2TP: " _fmt, ##args);		\
+	} while(0)
+
+/* Number of bytes to build transmit L2TP headers.
+ * Unfortunately the size is different depending on whether sequence numbers
+ * are enabled.
+ */
+#define PPPOL2TP_L2TP_HDR_SIZE_SEQ		10
+#define PPPOL2TP_L2TP_HDR_SIZE_NOSEQ		6
+
+struct pppol2tp_tunnel;
+
+/* Describes a session. It is the sk_user_data field in the PPPoL2TP
+ * socket. Contains information to determine incoming packets and transmit
+ * outgoing ones.
+ */
+struct pppol2tp_session
+{
+	int			magic;		/* should be
+						 * L2TP_SESSION_MAGIC */
+	int			owner;		/* pid that opened the socket */
+
+	struct sock		*sock;		/* Pointer to the session
+						 * PPPoX socket */
+	struct sock		*tunnel_sock;	/* Pointer to the tunnel UDP
+						 * socket */
+
+	struct pppol2tp_addr	tunnel_addr;	/* Description of tunnel */
+
+	struct pppol2tp_tunnel	*tunnel;	/* back pointer to tunnel
+						 * context */
+
+	char			name[20];	/* "sess xxxxx/yyyyy", where
+						 * x=tunnel_id, y=session_id */
+	int			mtu;
+	int			mru;
+	int			flags;		/* accessed by PPPIOCGFLAGS.
+						 * Unused. */
+	unsigned		recv_seq:1;	/* expect receive packets with
+						 * sequence numbers? */
+	unsigned		send_seq:1;	/* send packets with sequence
+						 * numbers? */
+	unsigned		lns_mode:1;	/* behave as LNS? LAC enables
+						 * sequence numbers under
+						 * control of LNS. */
+	int			debug;		/* bitmask of debug message
+						 * categories */
+	int			reorder_timeout; /* configured reorder timeout
+						  * (in jiffies) */
+	u16			nr;		/* session NR state (receive) */
+	u16			ns;		/* session NR state (send) */
+	struct sk_buff_head	reorder_q;	/* receive reorder queue */
+	struct pppol2tp_ioc_stats stats;
+	struct hlist_node	hlist;		/* Hash list node */
+};
+
+/* The sk_user_data field of the tunnel's UDP socket. It contains info to track
+ * all the associated sessions so incoming packets can be sorted out
+ */
+struct pppol2tp_tunnel
+{
+	int			magic;		/* Should be L2TP_TUNNEL_MAGIC */
+	rwlock_t		hlist_lock;	/* protect session_hlist */
+	struct hlist_head	session_hlist[PPPOL2TP_HASH_SIZE];
+						/* hashed list of sessions,
+						 * hashed by id */
+	int			debug;		/* bitmask of debug message
+						 * categories */
+	char			name[12];	/* "tunl xxxxx" */
+	struct pppol2tp_ioc_stats stats;
+
+	void (*old_sk_destruct)(struct sock *);
+
+	struct sock		*sock;		/* Parent socket */
+	struct list_head	list;		/* Keep a list of all open
+						 * prepared sockets */
+
+	atomic_t		ref_count;
+};
+
+/* Private data stored for received packets in the skb.
+ */
+struct pppol2tp_skb_cb {
+	u16			ns;
+	u16			nr;
+	u16			has_seq;
+	u16			length;
+	unsigned long		expires;
+};
+
+#define PPPOL2TP_SKB_CB(skb)	((struct pppol2tp_skb_cb *) &skb->cb[sizeof(struct inet_skb_parm)])
+
+static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb);
+static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel);
+
+static atomic_t pppol2tp_tunnel_count;
+static atomic_t pppol2tp_session_count;
+static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL };
+static struct proto_ops pppol2tp_ops;
+static LIST_HEAD(pppol2tp_tunnel_list);
+static DEFINE_RWLOCK(pppol2tp_tunnel_list_lock);
+
+/* Helpers to obtain tunnel/session contexts from sockets.
+ */
+static inline struct pppol2tp_session *pppol2tp_sock_to_session(struct sock *sk)
+{
+	struct pppol2tp_session *session;
+
+	if (sk == NULL)
+		return NULL;
+
+	session = (struct pppol2tp_session *)(sk->sk_user_data);
+	if (session == NULL)
+		return NULL;
+
+	BUG_ON(session->magic != L2TP_SESSION_MAGIC);
+
+	return session;
+}
+
+static inline struct pppol2tp_tunnel *pppol2tp_sock_to_tunnel(struct sock *sk)
+{
+	struct pppol2tp_tunnel *tunnel;
+
+	if (sk == NULL)
+		return NULL;
+
+	tunnel = (struct pppol2tp_tunnel *)(sk->sk_user_data);
+	if (tunnel == NULL)
+		return NULL;
+
+	BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
+
+	return tunnel;
+}
+
+/* Tunnel reference counts. Incremented per session that is added to
+ * the tunnel.
+ */
+static inline void pppol2tp_tunnel_inc_refcount(struct pppol2tp_tunnel *tunnel)
+{
+	atomic_inc(&tunnel->ref_count);
+}
+
+static inline void pppol2tp_tunnel_dec_refcount(struct pppol2tp_tunnel *tunnel)
+{
+	if (atomic_dec_and_test(&tunnel->ref_count))
+		pppol2tp_tunnel_free(tunnel);
+}
+
+/* Session hash list.
+ * The session_id SHOULD be random according to RFC2661, but several
+ * L2TP implementations (Cisco and Microsoft) use incrementing
+ * session_ids.  So we do a real hash on the session_id, rather than a
+ * simple bitmask.
+ */
+static inline struct hlist_head *
+pppol2tp_session_id_hash(struct pppol2tp_tunnel *tunnel, u16 session_id)
+{
+	unsigned long hash_val = (unsigned long) session_id;
+	return &tunnel->session_hlist[hash_long(hash_val, PPPOL2TP_HASH_BITS)];
+}
+
+/* Lookup a session by id
+ */
+static struct pppol2tp_session *
+pppol2tp_session_find(struct pppol2tp_tunnel *tunnel, u16 session_id)
+{
+	struct hlist_head *session_list =
+		pppol2tp_session_id_hash(tunnel, session_id);
+	struct pppol2tp_session *session;
+	struct hlist_node *walk;
+
+	read_lock(&tunnel->hlist_lock);
+	hlist_for_each_entry(session, walk, session_list, hlist) {
+		if (session->tunnel_addr.s_session == session_id) {
+			read_unlock(&tunnel->hlist_lock);
+			return session;
+		}
+	}
+	read_unlock(&tunnel->hlist_lock);
+
+	return NULL;
+}
+
+/* Lookup a tunnel by id
+ */
+static struct pppol2tp_tunnel *pppol2tp_tunnel_find(u16 tunnel_id)
+{
+	struct pppol2tp_tunnel *tunnel = NULL;
+
+	read_lock(&pppol2tp_tunnel_list_lock);
+	list_for_each_entry(tunnel, &pppol2tp_tunnel_list, list) {
+		if (tunnel->stats.tunnel_id == tunnel_id) {
+			read_unlock(&pppol2tp_tunnel_list_lock);
+			return tunnel;
+		}
+	}
+	read_unlock(&pppol2tp_tunnel_list_lock);
+
+	return NULL;
+}
+
+/*****************************************************************************
+ * Receive data handling
+ *****************************************************************************/
+
+/* Queue a skb in order. We come here only if the skb has an L2TP sequence
+ * number.
+ */
+static void pppol2tp_recv_queue_skb(struct pppol2tp_session *session, struct sk_buff *skb)
+{
+	struct sk_buff *skbp;
+	u16 ns = PPPOL2TP_SKB_CB(skb)->ns;
+
+	spin_lock(&session->reorder_q.lock);
+	skb_queue_walk(&session->reorder_q, skbp) {
+		if (PPPOL2TP_SKB_CB(skbp)->ns > ns) {
+			__skb_insert(skb, skbp->prev, skbp, &session->reorder_q);
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+			       "%s: pkt %hu, inserted before %hu, reorder_q len=%d\n",
+			       session->name, ns, PPPOL2TP_SKB_CB(skbp)->ns,
+			       skb_queue_len(&session->reorder_q));
+			session->stats.rx_oos_packets++;
+			goto out;
+		}
+	}
+
+	__skb_queue_tail(&session->reorder_q, skb);
+
+out:
+	spin_unlock(&session->reorder_q.lock);
+}
+
+/* Dequeue a single skb.
+ */
+static void pppol2tp_recv_dequeue_skb(struct pppol2tp_session *session, struct sk_buff *skb)
+{
+	struct pppol2tp_tunnel *tunnel = session->tunnel;
+	int length = PPPOL2TP_SKB_CB(skb)->length;
+	struct sock *session_sock = NULL;
+
+	/* We're about to requeue the skb, so unlink it and return resources
+	 * to its current owner (a socket receive buffer).
+	 */
+	skb_unlink(skb, &session->reorder_q);
+	skb_orphan(skb);
+
+	tunnel->stats.rx_packets++;
+	tunnel->stats.rx_bytes += length;
+	session->stats.rx_packets++;
+	session->stats.rx_bytes += length;
+
+	if (PPPOL2TP_SKB_CB(skb)->has_seq) {
+		/* Bump our Nr */
+		session->nr++;
+		PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+		       "%s: updated nr to %hu\n", session->name, session->nr);
+	}
+
+	/* If the socket is bound, send it in to PPP's input queue. Otherwise
+	 * queue it on the session socket.
+	 */
+	session_sock = session->sock;
+	if (session_sock->sk_state & PPPOX_BOUND) {
+		struct pppox_sock *po;
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: recv %d byte data frame, passing to ppp\n",
+		       session->name, length);
+
+		/* We need to forget all info related to the L2TP packet
+		 * gathered in the skb as we are going to reuse the same
+		 * skb for the inner packet.
+		 * Namely we need to:
+		 * - reset xfrm (IPSec) information as it applies to
+		 *   the outer L2TP packet and not to the inner one
+		 * - release the dst to force a route lookup on the inner
+		 *   IP packet since skb->dst currently points to the dst
+		 *   of the UDP tunnel
+		 * - reset netfilter information as it doesn't apply
+		 *   to the inner packet either
+		 */
+		secpath_reset(skb);
+		dst_release(skb->dst);
+		skb->dst = NULL;
+		nf_reset(skb);
+
+		po = pppox_sk(session_sock);
+		ppp_input(&po->chan, skb);
+	} else {
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+		       "%s: socket not bound\n", session->name);
+
+		/* Not bound. Nothing we can do, so discard. */
+		session->stats.rx_errors++;
+		kfree_skb(skb);
+	}
+
+	sock_put(session->sock);
+}
+
+/* Dequeue skbs from the session's reorder_q, subject to packet order.
+ * Skbs that have been in the queue for too long are simply discarded.
+ */
+static void pppol2tp_recv_dequeue(struct pppol2tp_session *session)
+{
+	struct sk_buff *skb;
+	struct sk_buff *tmp;
+
+	/* If the pkt at the head of the queue has the nr that we
+	 * expect to send up next, dequeue it and any other
+	 * in-sequence packets behind it.
+	 */
+	spin_lock(&session->reorder_q.lock);
+	skb_queue_walk_safe(&session->reorder_q, skb, tmp) {
+		if (time_after(jiffies, PPPOL2TP_SKB_CB(skb)->expires)) {
+			session->stats.rx_seq_discards++;
+			session->stats.rx_errors++;
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+			       "%s: oos pkt %hu len %d discarded (too old), "
+			       "waiting for %hu, reorder_q_len=%d\n",
+			       session->name, PPPOL2TP_SKB_CB(skb)->ns,
+			       PPPOL2TP_SKB_CB(skb)->length, session->nr,
+			       skb_queue_len(&session->reorder_q));
+			__skb_unlink(skb, &session->reorder_q);
+			kfree_skb(skb);
+			continue;
+		}
+
+		if (PPPOL2TP_SKB_CB(skb)->has_seq) {
+			if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) {
+				PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+				       "%s: holding oos pkt %hu len %d, "
+				       "waiting for %hu, reorder_q_len=%d\n",
+				       session->name, PPPOL2TP_SKB_CB(skb)->ns,
+				       PPPOL2TP_SKB_CB(skb)->length, session->nr,
+				       skb_queue_len(&session->reorder_q));
+				goto out;
+			}
+		}
+		spin_unlock(&session->reorder_q.lock);
+		pppol2tp_recv_dequeue_skb(session, skb);
+		spin_lock(&session->reorder_q.lock);
+	}
+
+out:
+	spin_unlock(&session->reorder_q.lock);
+}
+
+/* Internal receive frame. Do the real work of receiving an L2TP data frame
+ * here. The skb is not on a list when we get here.
+ * Returns 0 if the packet was a data packet and was successfully passed on.
+ * Returns 1 if the packet was not a good data packet and could not be
+ * forwarded.  All such packets are passed up to userspace to deal with.
+ */
+static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
+{
+	struct pppol2tp_session *session = NULL;
+	struct pppol2tp_tunnel *tunnel;
+	unsigned char *ptr;
+	u16 hdrflags;
+	u16 tunnel_id, session_id;
+	int length;
+	struct udphdr *uh;
+
+	tunnel = pppol2tp_sock_to_tunnel(sock);
+	if (tunnel == NULL)
+		goto error;
+
+	/* Short packet? */
+	if (skb->len < sizeof(struct udphdr)) {
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+		       "%s: recv short packet (len=%d)\n", tunnel->name, skb->len);
+		goto error;
+	}
+
+	/* Point to L2TP header */
+	ptr = skb->data + sizeof(struct udphdr);
+
+	/* Get L2TP header flags */
+	hdrflags = ntohs(*(__be16*)ptr);
+
+	/* Trace packet contents, if enabled */
+	if (tunnel->debug & PPPOL2TP_MSG_DATA) {
+		printk(KERN_DEBUG "%s: recv: ", tunnel->name);
+
+		for (length = 0; length < 16; length++)
+			printk(" %02X", ptr[length]);
+		printk("\n");
+	}
+
+	/* Get length of L2TP packet */
+	uh = (struct udphdr *) skb_transport_header(skb);
+	length = ntohs(uh->len) - sizeof(struct udphdr);
+
+	/* Too short? */
+	if (length < 12) {
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+		       "%s: recv short L2TP packet (len=%d)\n", tunnel->name, length);
+		goto error;
+	}
+
+	/* If type is control packet, it is handled by userspace. */
+	if (hdrflags & L2TP_HDRFLAG_T) {
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: recv control packet, len=%d\n", tunnel->name, length);
+		goto error;
+	}
+
+	/* Skip flags */
+	ptr += 2;
+
+	/* If length is present, skip it */
+	if (hdrflags & L2TP_HDRFLAG_L)
+		ptr += 2;
+
+	/* Extract tunnel and session ID */
+	tunnel_id = ntohs(*(__be16 *) ptr);
+	ptr += 2;
+	session_id = ntohs(*(__be16 *) ptr);
+	ptr += 2;
+
+	/* Find the session context */
+	session = pppol2tp_session_find(tunnel, session_id);
+	if (!session) {
+		/* Not found? Pass to userspace to deal with */
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+		       "%s: no socket found (%hu/%hu). Passing up.\n",
+		       tunnel->name, tunnel_id, session_id);
+		goto error;
+	}
+	sock_hold(session->sock);
+
+	/* The ref count on the socket was increased by the above call since
+	 * we now hold a pointer to the session. Take care to do sock_put()
+	 * when exiting this function from now on...
+	 */
+
+	/* Handle the optional sequence numbers.  If we are the LAC,
+	 * enable/disable sequence numbers under the control of the LNS.  If
+	 * no sequence numbers present but we were expecting them, discard
+	 * frame.
+	 */
+	if (hdrflags & L2TP_HDRFLAG_S) {
+		u16 ns, nr;
+		ns = ntohs(*(__be16 *) ptr);
+		ptr += 2;
+		nr = ntohs(*(__be16 *) ptr);
+		ptr += 2;
+
+		/* Received a packet with sequence numbers. If we're the LNS,
+		 * check if we sre sending sequence numbers and if not,
+		 * configure it so.
+		 */
+		if ((!session->lns_mode) && (!session->send_seq)) {
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_INFO,
+			       "%s: requested to enable seq numbers by LNS\n",
+			       session->name);
+			session->send_seq = -1;
+		}
+
+		/* Store L2TP info in the skb */
+		PPPOL2TP_SKB_CB(skb)->ns = ns;
+		PPPOL2TP_SKB_CB(skb)->nr = nr;
+		PPPOL2TP_SKB_CB(skb)->has_seq = 1;
+
+		PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+		       "%s: recv data ns=%hu, nr=%hu, session nr=%hu\n",
+		       session->name, ns, nr, session->nr);
+	} else {
+		/* No sequence numbers.
+		 * If user has configured mandatory sequence numbers, discard.
+		 */
+		if (session->recv_seq) {
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_WARNING,
+			       "%s: recv data has no seq numbers when required. "
+			       "Discarding\n", session->name);
+			session->stats.rx_seq_discards++;
+			session->stats.rx_errors++;
+			goto discard;
+		}
+
+		/* If we're the LAC and we're sending sequence numbers, the
+		 * LNS has requested that we no longer send sequence numbers.
+		 * If we're the LNS and we're sending sequence numbers, the
+		 * LAC is broken. Discard the frame.
+		 */
+		if ((!session->lns_mode) && (session->send_seq)) {
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_INFO,
+			       "%s: requested to disable seq numbers by LNS\n",
+			       session->name);
+			session->send_seq = 0;
+		} else if (session->send_seq) {
+			PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_WARNING,
+			       "%s: recv data has no seq numbers when required. "
+			       "Discarding\n", session->name);
+			session->stats.rx_seq_discards++;
+			session->stats.rx_errors++;
+			goto discard;
+		}
+
+		/* Store L2TP info in the skb */
+		PPPOL2TP_SKB_CB(skb)->has_seq = 0;
+	}
+
+	/* If offset bit set, skip it. */
+	if (hdrflags & L2TP_HDRFLAG_O)
+		ptr += 2 + ntohs(*(__be16 *) ptr);
+
+	skb_pull(skb, ptr - skb->data);
+
+	/* Skip PPP header, if present.	 In testing, Microsoft L2TP clients
+	 * don't send the PPP header (PPP header compression enabled), but
+	 * other clients can include the header. So we cope with both cases
+	 * here. The PPP header is always FF03 when using L2TP.
+	 *
+	 * Note that skb->data[] isn't dereferenced from a u16 ptr here since
+	 * the field may be unaligned.
+	 */
+	if ((skb->data[0] == 0xff) && (skb->data[1] == 0x03))
+		skb_pull(skb, 2);
+
+	/* Prepare skb for adding to the session's reorder_q.  Hold
+	 * packets for max reorder_timeout or 1 second if not
+	 * reordering.
+	 */
+	PPPOL2TP_SKB_CB(skb)->length = length;
+	PPPOL2TP_SKB_CB(skb)->expires = jiffies +
+		(session->reorder_timeout ? session->reorder_timeout : HZ);
+
+	/* Add packet to the session's receive queue. Reordering is done here, if
+	 * enabled. Saved L2TP protocol info is stored in skb->sb[].
+	 */
+	if (PPPOL2TP_SKB_CB(skb)->has_seq) {
+		if (session->reorder_timeout != 0) {
+			/* Packet reordering enabled. Add skb to session's
+			 * reorder queue, in order of ns.
+			 */
+			pppol2tp_recv_queue_skb(session, skb);
+		} else {
+			/* Packet reordering disabled. Discard out-of-sequence
+			 * packets
+			 */
+			if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) {
+				session->stats.rx_seq_discards++;
+				session->stats.rx_errors++;
+				PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+				       "%s: oos pkt %hu len %d discarded, "
+				       "waiting for %hu, reorder_q_len=%d\n",
+				       session->name, PPPOL2TP_SKB_CB(skb)->ns,
+				       PPPOL2TP_SKB_CB(skb)->length, session->nr,
+				       skb_queue_len(&session->reorder_q));
+				goto discard;
+			}
+			skb_queue_tail(&session->reorder_q, skb);
+		}
+	} else {
+		/* No sequence numbers. Add the skb to the tail of the
+		 * reorder queue. This ensures that it will be
+		 * delivered after all previous sequenced skbs.
+		 */
+		skb_queue_tail(&session->reorder_q, skb);
+	}
+
+	/* Try to dequeue as many skbs from reorder_q as we can. */
+	pppol2tp_recv_dequeue(session);
+
+	return 0;
+
+discard:
+	kfree_skb(skb);
+	sock_put(session->sock);
+
+	return 0;
+
+error:
+	return 1;
+}
+
+/* UDP encapsulation receive handler. See net/ipv4/udp.c.
+ * Return codes:
+ * 0 : success.
+ * <0: error
+ * >0: skb should be passed up to userspace as UDP.
+ */
+static int pppol2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
+{
+	struct pppol2tp_tunnel *tunnel;
+
+	tunnel = pppol2tp_sock_to_tunnel(sk);
+	if (tunnel == NULL)
+		goto pass_up;
+
+	PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+	       "%s: received %d bytes\n", tunnel->name, skb->len);
+
+	if (pppol2tp_recv_core(sk, skb))
+		goto pass_up;
+
+	return 0;
+
+pass_up:
+	return 1;
+}
+
+/* Receive message. This is the recvmsg for the PPPoL2TP socket.
+ */
+static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock,
+			    struct msghdr *msg, size_t len,
+			    int flags)
+{
+	int err;
+	struct sk_buff *skb;
+	struct sock *sk = sock->sk;
+
+	err = -EIO;
+	if (sk->sk_state & PPPOX_BOUND)
+		goto end;
+
+	msg->msg_namelen = 0;
+
+	err = 0;
+	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+				flags & MSG_DONTWAIT, &err);
+	if (skb) {
+		err = memcpy_toiovec(msg->msg_iov, (unsigned char *) skb->data,
+				     skb->len);
+		if (err < 0)
+			goto do_skb_free;
+		err = skb->len;
+	}
+do_skb_free:
+	kfree_skb(skb);
+end:
+	return err;
+}
+
+/************************************************************************
+ * Transmit handling
+ ***********************************************************************/
+
+/* Tell how big L2TP headers are for a particular session. This
+ * depends on whether sequence numbers are being used.
+ */
+static inline int pppol2tp_l2tp_header_len(struct pppol2tp_session *session)
+{
+	if (session->send_seq)
+		return PPPOL2TP_L2TP_HDR_SIZE_SEQ;
+
+	return PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
+}
+
+/* Build an L2TP header for the session into the buffer provided.
+ */
+static void pppol2tp_build_l2tp_header(struct pppol2tp_session *session,
+				       void *buf)
+{
+	__be16 *bufp = buf;
+	u16 flags = L2TP_HDR_VER;
+
+	if (session->send_seq)
+		flags |= L2TP_HDRFLAG_S;
+
+	/* Setup L2TP header.
+	 * FIXME: Can this ever be unaligned? Is direct dereferencing of
+	 * 16-bit header fields safe here for all architectures?
+	 */
+	*bufp++ = htons(flags);
+	*bufp++ = htons(session->tunnel_addr.d_tunnel);
+	*bufp++ = htons(session->tunnel_addr.d_session);
+	if (session->send_seq) {
+		*bufp++ = htons(session->ns);
+		*bufp++ = 0;
+		session->ns++;
+		PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+		       "%s: updated ns to %hu\n", session->name, session->ns);
+	}
+}
+
+/* This is the sendmsg for the PPPoL2TP pppol2tp_session socket.  We come here
+ * when a user application does a sendmsg() on the session socket. L2TP and
+ * PPP headers must be inserted into the user's data.
+ */
+static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
+			    size_t total_len)
+{
+	static const unsigned char ppph[2] = { 0xff, 0x03 };
+	struct sock *sk = sock->sk;
+	struct inet_sock *inet;
+	__wsum csum = 0;
+	struct sk_buff *skb;
+	int error;
+	int hdr_len;
+	struct pppol2tp_session *session;
+	struct pppol2tp_tunnel *tunnel;
+	struct udphdr *uh;
+
+	error = -ENOTCONN;
+	if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
+		goto error;
+
+	/* Get session and tunnel contexts */
+	error = -EBADF;
+	session = pppol2tp_sock_to_session(sk);
+	if (session == NULL)
+		goto error;
+
+	tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+	if (tunnel == NULL)
+		goto error;
+
+	/* What header length is configured for this session? */
+	hdr_len = pppol2tp_l2tp_header_len(session);
+
+	/* Allocate a socket buffer */
+	error = -ENOMEM;
+	skb = sock_wmalloc(sk, NET_SKB_PAD + sizeof(struct iphdr) +
+			   sizeof(struct udphdr) + hdr_len +
+			   sizeof(ppph) + total_len,
+			   0, GFP_KERNEL);
+	if (!skb)
+		goto error;
+
+	/* Reserve space for headers. */
+	skb_reserve(skb, NET_SKB_PAD);
+	skb_reset_network_header(skb);
+	skb_reserve(skb, sizeof(struct iphdr));
+	skb_reset_transport_header(skb);
+
+	/* Build UDP header */
+	inet = inet_sk(session->tunnel_sock);
+	uh = (struct udphdr *) skb->data;
+	uh->source = inet->sport;
+	uh->dest = inet->dport;
+	uh->len = htons(hdr_len + sizeof(ppph) + total_len);
+	uh->check = 0;
+	skb_put(skb, sizeof(struct udphdr));
+
+	/* Build L2TP header */
+	pppol2tp_build_l2tp_header(session, skb->data);
+	skb_put(skb, hdr_len);
+
+	/* Add PPP header */
+	skb->data[0] = ppph[0];
+	skb->data[1] = ppph[1];
+	skb_put(skb, 2);
+
+	/* Copy user data into skb */
+	error = memcpy_fromiovec(skb->data, m->msg_iov, total_len);
+	if (error < 0) {
+		kfree_skb(skb);
+		goto error;
+	}
+	skb_put(skb, total_len);
+
+	/* Calculate UDP checksum if configured to do so */
+	if (session->tunnel_sock->sk_no_check != UDP_CSUM_NOXMIT)
+		csum = udp_csum_outgoing(sk, skb);
+
+	/* Debug */
+	if (session->send_seq)
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: send %Zd bytes, ns=%hu\n", session->name,
+		       total_len, session->ns - 1);
+	else
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: send %Zd bytes\n", session->name, total_len);
+
+	if (session->debug & PPPOL2TP_MSG_DATA) {
+		int i;
+		unsigned char *datap = skb->data;
+
+		printk(KERN_DEBUG "%s: xmit:", session->name);
+		for (i = 0; i < total_len; i++) {
+			printk(" %02X", *datap++);
+			if (i == 15) {
+				printk(" ...");
+				break;
+			}
+		}
+		printk("\n");
+	}
+
+	/* Queue the packet to IP for output */
+	error = ip_queue_xmit(skb, 1);
+
+	/* Update stats */
+	if (error >= 0) {
+		tunnel->stats.tx_packets++;
+		tunnel->stats.tx_bytes += skb->len;
+		session->stats.tx_packets++;
+		session->stats.tx_bytes += skb->len;
+	} else {
+		tunnel->stats.tx_errors++;
+		session->stats.tx_errors++;
+	}
+
+error:
+	return error;
+}
+
+/* Transmit function called by generic PPP driver.  Sends PPP frame
+ * over PPPoL2TP socket.
+ *
+ * This is almost the same as pppol2tp_sendmsg(), but rather than
+ * being called with a msghdr from userspace, it is called with a skb
+ * from the kernel.
+ *
+ * The supplied skb from ppp doesn't have enough headroom for the
+ * insertion of L2TP, UDP and IP headers so we need to allocate more
+ * headroom in the skb. This will create a cloned skb. But we must be
+ * careful in the error case because the caller will expect to free
+ * the skb it supplied, not our cloned skb. So we take care to always
+ * leave the original skb unfreed if we return an error.
+ */
+static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+{
+	static const u8 ppph[2] = { 0xff, 0x03 };
+	struct sock *sk = (struct sock *) chan->private;
+	struct sock *sk_tun;
+	int hdr_len;
+	struct pppol2tp_session *session;
+	struct pppol2tp_tunnel *tunnel;
+	int rc;
+	int headroom;
+	int data_len = skb->len;
+	struct inet_sock *inet;
+	__wsum csum = 0;
+	struct sk_buff *skb2 = NULL;
+	struct udphdr *uh;
+
+	if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
+		goto abort;
+
+	/* Get session and tunnel contexts from the socket */
+	session = pppol2tp_sock_to_session(sk);
+	if (session == NULL)
+		goto abort;
+
+	sk_tun = session->tunnel_sock;
+	if (sk_tun == NULL)
+		goto abort;
+	tunnel = pppol2tp_sock_to_tunnel(sk_tun);
+	if (tunnel == NULL)
+		goto abort;
+
+	/* What header length is configured for this session? */
+	hdr_len = pppol2tp_l2tp_header_len(session);
+
+	/* Check that there's enough headroom in the skb to insert IP,
+	 * UDP and L2TP and PPP headers. If not enough, expand it to
+	 * make room. Note that a new skb (or a clone) is
+	 * allocated. If we return an error from this point on, make
+	 * sure we free the new skb but do not free the original skb
+	 * since that is done by the caller for the error case.
+	 */
+	headroom = NET_SKB_PAD + sizeof(struct iphdr) +
+		sizeof(struct udphdr) + hdr_len + sizeof(ppph);
+	if (skb_headroom(skb) < headroom) {
+		skb2 = skb_realloc_headroom(skb, headroom);
+		if (skb2 == NULL)
+			goto abort;
+	} else
+		skb2 = skb;
+
+	/* Check that the socket has room */
+	if (atomic_read(&sk_tun->sk_wmem_alloc) < sk_tun->sk_sndbuf)
+		skb_set_owner_w(skb2, sk_tun);
+	else
+		goto discard;
+
+	/* Setup PPP header */
+	skb_push(skb2, sizeof(ppph));
+	skb2->data[0] = ppph[0];
+	skb2->data[1] = ppph[1];
+
+	/* Setup L2TP header */
+	skb_push(skb2, hdr_len);
+	pppol2tp_build_l2tp_header(session, skb2->data);
+
+	/* Setup UDP header */
+	inet = inet_sk(sk_tun);
+	skb_push(skb2, sizeof(struct udphdr));
+	skb_reset_transport_header(skb2);
+	uh = (struct udphdr *) skb2->data;
+	uh->source = inet->sport;
+	uh->dest = inet->dport;
+	uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len);
+	uh->check = 0;
+
+	/* Calculate UDP checksum if configured to do so */
+	if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT)
+		csum = udp_csum_outgoing(sk_tun, skb2);
+
+	/* Debug */
+	if (session->send_seq)
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: send %d bytes, ns=%hu\n", session->name,
+		       data_len, session->ns - 1);
+	else
+		PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+		       "%s: send %d bytes\n", session->name, data_len);
+
+	if (session->debug & PPPOL2TP_MSG_DATA) {
+		int i;
+		unsigned char *datap = skb2->data;
+
+		printk(KERN_DEBUG "%s: xmit:", session->name);
+		for (i = 0; i < data_len; i++) {
+			printk(" %02X", *datap++);
+			if (i == 31) {
+				printk(" ...");
+				break;
+			}
+		}
+		printk("\n");
+	}
+
+	/* Get routing info from the tunnel socket */
+	skb2->dst = sk_dst_get(sk_tun);
+
+	/* Queue the packet to IP for output */
+	rc = ip_queue_xmit(skb2, 1);
+
+	/* Update stats */
+	if (rc >= 0) {
+		tunnel->stats.tx_packets++;
+		tunnel->stats.tx_bytes += skb2->len;
+		session->stats.tx_packets++;
+		session->stats.tx_bytes += skb2->len;
+	} else {
+		tunnel->stats.tx_errors++;
+		session->stats.tx_errors++;
+	}
+
+	/* Free the original skb */
+	kfree_skb(skb);
+
+	return 1;
+
+discard:
+	/* Free the new skb. Caller will free original skb. */
+	if (skb2 != skb)
+		kfree_skb(skb2);
+abort:
+	return 0;
+}
+
+/*****************************************************************************
+ * Session (and tunnel control) socket create/destroy.
+ *****************************************************************************/
+
+/* When the tunnel UDP socket is closed, all the attached sockets need to go
+ * too.
+ */
+static void pppol2tp_tunnel_closeall(struct pppol2tp_tunnel *tunnel)
+{
+	int hash;
+	struct hlist_node *walk;
+	struct hlist_node *tmp;
+	struct pppol2tp_session *session;
+	struct sock *sk;
+
+	if (tunnel == NULL)
+		BUG();
+
+	PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+	       "%s: closing all sessions...\n", tunnel->name);
+
+	write_lock(&tunnel->hlist_lock);
+	for (hash = 0; hash < PPPOL2TP_HASH_SIZE; hash++) {
+again:
+		hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) {
+			session = hlist_entry(walk, struct pppol2tp_session, hlist);
+
+			sk = session->sock;
+
+			PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+			       "%s: closing session\n", session->name);
+
+			hlist_del_init(&session->hlist);
+
+			/* Since we should hold the sock lock while
+			 * doing any unbinding, we need to release the
+			 * lock we're holding before taking that lock.
+			 * Hold a reference to the sock so it doesn't
+			 * disappear as we're jumping between locks.
+			 */
+			sock_hold(sk);
+			write_unlock(&tunnel->hlist_lock);
+			lock_sock(sk);
+
+			if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+				pppox_unbind_sock(sk);
+				sk->sk_state = PPPOX_DEAD;
+				sk->sk_state_change(sk);
+			}
+
+			/* Purge any queued data */
+			skb_queue_purge(&sk->sk_receive_queue);
+			skb_queue_purge(&sk->sk_write_queue);
+			skb_queue_purge(&session->reorder_q);
+
+			release_sock(sk);
+			sock_put(sk);
+
+			/* Now restart from the beginning of this hash
+			 * chain.  We always remove a session from the
+			 * list so we are guaranteed to make forward
+			 * progress.
+			 */
+			write_lock(&tunnel->hlist_lock);
+			goto again;
+		}
+	}
+	write_unlock(&tunnel->hlist_lock);
+}
+
+/* Really kill the tunnel.
+ * Come here only when all sessions have been cleared from the tunnel.
+ */
+static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel)
+{
+	/* Remove from socket list */
+	write_lock(&pppol2tp_tunnel_list_lock);
+	list_del_init(&tunnel->list);
+	write_unlock(&pppol2tp_tunnel_list_lock);
+
+	atomic_dec(&pppol2tp_tunnel_count);
+	kfree(tunnel);
+}
+
+/* Tunnel UDP socket destruct hook.
+ * The tunnel context is deleted only when all session sockets have been
+ * closed.
+ */
+static void pppol2tp_tunnel_destruct(struct sock *sk)
+{
+	struct pppol2tp_tunnel *tunnel;
+
+	tunnel = pppol2tp_sock_to_tunnel(sk);
+	if (tunnel == NULL)
+		goto end;
+
+	PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+	       "%s: closing...\n", tunnel->name);
+
+	/* Close all sessions */
+	pppol2tp_tunnel_closeall(tunnel);
+
+	/* No longer an encapsulation socket. See net/ipv4/udp.c */
+	(udp_sk(sk))->encap_type = 0;
+	(udp_sk(sk))->encap_rcv = NULL;
+
+	/* Remove hooks into tunnel socket */
+	tunnel->sock = NULL;
+	sk->sk_destruct = tunnel->old_sk_destruct;
+	sk->sk_user_data = NULL;
+
+	/* Call original (UDP) socket descructor */
+	if (sk->sk_destruct != NULL)
+		(*sk->sk_destruct)(sk);
+
+	pppol2tp_tunnel_dec_refcount(tunnel);
+
+end:
+	return;
+}
+
+/* Really kill the session socket. (Called from sock_put() if
+ * refcnt == 0.)
+ */
+static void pppol2tp_session_destruct(struct sock *sk)
+{
+	struct pppol2tp_session *session = NULL;
+
+	if (sk->sk_user_data != NULL) {
+		struct pppol2tp_tunnel *tunnel;
+
+		session = pppol2tp_sock_to_session(sk);
+		if (session == NULL)
+			goto out;
+
+		/* Don't use pppol2tp_sock_to_tunnel() here to
+		 * get the tunnel context because the tunnel
+		 * socket might have already been closed (its
+		 * sk->sk_user_data will be NULL) so use the
+		 * session's private tunnel ptr instead.
+		 */
+		tunnel = session->tunnel;
+		if (tunnel != NULL) {
+			BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
+
+			/* If session_id is zero, this is a null
+			 * session context, which was created for a
+			 * socket that is being used only to manage
+			 * tunnels.
+			 */
+			if (session->tunnel_addr.s_session != 0) {
+				/* Delete the session socket from the
+				 * hash
+				 */
+				write_lock(&tunnel->hlist_lock);
+				hlist_del_init(&session->hlist);
+				write_unlock(&tunnel->hlist_lock);
+
+				atomic_dec(&pppol2tp_session_count);
+			}
+
+			/* This will delete the tunnel context if this
+			 * is the last session on the tunnel.
+			 */
+			session->tunnel = NULL;
+			session->tunnel_sock = NULL;
+			pppol2tp_tunnel_dec_refcount(tunnel);
+		}
+	}
+
+	kfree(session);
+out:
+	return;
+}
+
+/* Called when the PPPoX socket (session) is closed.
+ */
+static int pppol2tp_release(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+	int error;
+
+	if (!sk)
+		return 0;
+
+	error = -EBADF;
+	lock_sock(sk);
+	if (sock_flag(sk, SOCK_DEAD) != 0)
+		goto error;
+
+	pppox_unbind_sock(sk);
+
+	/* Signal the death of the socket. */
+	sk->sk_state = PPPOX_DEAD;
+	sock_orphan(sk);
+	sock->sk = NULL;
+
+	/* Purge any queued data */
+	skb_queue_purge(&sk->sk_receive_queue);
+	skb_queue_purge(&sk->sk_write_queue);
+
+	release_sock(sk);
+
+	/* This will delete the session context via
+	 * pppol2tp_session_destruct() if the socket's refcnt drops to
+	 * zero.
+	 */
+	sock_put(sk);
+
+	return 0;
+
+error:
+	release_sock(sk);
+	return error;
+}
+
+/* Internal function to prepare a tunnel (UDP) socket to have PPPoX
+ * sockets attached to it.
+ */
+static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id,
+						   int *error)
+{
+	int err;
+	struct socket *sock = NULL;
+	struct sock *sk;
+	struct pppol2tp_tunnel *tunnel;
+	struct sock *ret = NULL;
+
+	/* Get the tunnel UDP socket from the fd, which was opened by
+	 * the userspace L2TP daemon.
+	 */
+	err = -EBADF;
+	sock = sockfd_lookup(fd, &err);
+	if (!sock) {
+		PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR,
+		       "tunl %hu: sockfd_lookup(fd=%d) returned %d\n",
+		       tunnel_id, fd, err);
+		goto err;
+	}
+
+	/* Quick sanity checks */
+	err = -ESOCKTNOSUPPORT;
+	if (sock->type != SOCK_DGRAM) {
+		PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR,
+		       "tunl %hu: fd %d wrong type, got %d, expected %d\n",
+		       tunnel_id, fd, sock->type, SOCK_DGRAM);
+		goto err;
+	}
+	err = -EAFNOSUPPORT;
+	if (sock->ops->family != AF_INET) {
+		PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR,
+		       "tunl %hu: fd %d wrong family, got %d, expected %d\n",
+		       tunnel_id, fd, sock->ops->family, AF_INET);
+		goto err;
+	}
+
+	err = -ENOTCONN;
+	sk = sock->sk;
+
+	/* Check if this socket has already been prepped */
+	tunnel = (struct pppol2tp_tunnel *)sk->sk_user_data;
+	if (tunnel != NULL) {
+		/* User-data field already set */
+		err = -EBUSY;
+		BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
+
+		/* This socket has already been prepped */
+		ret = tunnel->sock;
+		goto out;
+	}
+
+	/* This socket is available and needs prepping. Create a new tunnel
+	 * context and init it.
+	 */
+	sk->sk_user_data = tunnel = kzalloc(sizeof(struct pppol2tp_tunnel), GFP_KERNEL);
+	if (sk->sk_user_data == NULL) {
+		err = -ENOMEM;
+		goto err;
+	}
+
+	tunnel->magic = L2TP_TUNNEL_MAGIC;
+	sprintf(&tunnel->name[0], "tunl %hu", tunnel_id);
+
+	tunnel->stats.tunnel_id = tunnel_id;
+	tunnel->debug = PPPOL2TP_DEFAULT_DEBUG_FLAGS;
+
+	/* Hook on the tunnel socket destructor so that we can cleanup
+	 * if the tunnel socket goes away.
+	 */
+	tunnel->old_sk_destruct = sk->sk_destruct;
+	sk->sk_destruct = &pppol2tp_tunnel_destruct;
+
+	tunnel->sock = sk;
+	sk->sk_allocation = GFP_ATOMIC;
+
+	/* Misc init */
+	rwlock_init(&tunnel->hlist_lock);
+
+	/* Add tunnel to our list */
+	INIT_LIST_HEAD(&tunnel->list);
+	write_lock(&pppol2tp_tunnel_list_lock);
+	list_add(&tunnel->list, &pppol2tp_tunnel_list);
+	write_unlock(&pppol2tp_tunnel_list_lock);
+	atomic_inc(&pppol2tp_tunnel_count);
+
+	/* Bump the reference count. The tunnel context is deleted
+	 * only when this drops to zero.
+	 */
+	pppol2tp_tunnel_inc_refcount(tunnel);
+
+	/* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
+	(udp_sk(sk))->encap_type = UDP_ENCAP_L2TPINUDP;
+	(udp_sk(sk))->encap_rcv = pppol2tp_udp_encap_recv;
+
+	ret = tunnel->sock;
+
+	*error = 0;
+out:
+	if (sock)
+		sockfd_put(sock);
+
+	return ret;
+
+err:
+	*error = err;
+	goto out;
+}
+
+static struct proto pppol2tp_sk_proto = {
+	.name	  = "PPPOL2TP",
+	.owner	  = THIS_MODULE,
+	.obj_size = sizeof(struct pppox_sock),
+};
+
+/* socket() handler. Initialize a new struct sock.
+ */
+static int pppol2tp_create(struct socket *sock)
+{
+	int error = -ENOMEM;
+	struct sock *sk;
+
+	sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto, 1);
+	if (!sk)
+		goto out;
+
+	sock_init_data(sock, sk);
+
+	sock->state  = SS_UNCONNECTED;
+	sock->ops    = &pppol2tp_ops;
+
+	sk->sk_backlog_rcv = pppol2tp_recv_core;
+	sk->sk_protocol	   = PX_PROTO_OL2TP;
+	sk->sk_family	   = PF_PPPOX;
+	sk->sk_state	   = PPPOX_NONE;
+	sk->sk_type	   = SOCK_STREAM;
+	sk->sk_destruct	   = pppol2tp_session_destruct;
+
+	error = 0;
+
+out:
+	return error;
+}
+
+/* connect() handler. Attach a PPPoX socket to a tunnel UDP socket
+ */
+static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
+			    int sockaddr_len, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr;
+	struct pppox_sock *po = pppox_sk(sk);
+	struct sock *tunnel_sock = NULL;
+	struct pppol2tp_session *session = NULL;
+	struct pppol2tp_tunnel *tunnel;
+	struct dst_entry *dst;
+	int error = 0;
+
+	lock_sock(sk);
+
+	error = -EINVAL;
+	if (sp->sa_protocol != PX_PROTO_OL2TP)
+		goto end;
+
+	/* Check for already bound sockets */
+	error = -EBUSY;
+	if (sk->sk_state & PPPOX_CONNECTED)
+		goto end;
+
+	/* We don't supporting rebinding anyway */
+	error = -EALREADY;
+	if (sk->sk_user_data)
+		goto end; /* socket is already attached */
+
+	/* Don't bind if s_tunnel is 0 */
+	error = -EINVAL;
+	if (sp->pppol2tp.s_tunnel == 0)
+		goto end;
+
+	/* Special case: prepare tunnel socket if s_session and
+	 * d_session is 0. Otherwise look up tunnel using supplied
+	 * tunnel id.
+	 */
+	if ((sp->pppol2tp.s_session == 0) && (sp->pppol2tp.d_session == 0)) {
+		tunnel_sock = pppol2tp_prepare_tunnel_socket(sp->pppol2tp.fd,
+							     sp->pppol2tp.s_tunnel,
+							     &error);
+		if (tunnel_sock == NULL)
+			goto end;
+
+		tunnel = tunnel_sock->sk_user_data;
+	} else {
+		tunnel = pppol2tp_tunnel_find(sp->pppol2tp.s_tunnel);
+
+		/* Error if we can't find the tunnel */
+		error = -ENOENT;
+		if (tunnel == NULL)
+			goto end;
+
+		tunnel_sock = tunnel->sock;
+	}
+
+	/* Check that this session doesn't already exist */
+	error = -EEXIST;
+	session = pppol2tp_session_find(tunnel, sp->pppol2tp.s_session);
+	if (session != NULL)
+		goto end;
+
+	/* Allocate and initialize a new session context. */
+	session = kzalloc(sizeof(struct pppol2tp_session), GFP_KERNEL);
+	if (session == NULL) {
+		error = -ENOMEM;
+		goto end;
+	}
+
+	skb_queue_head_init(&session->reorder_q);
+
+	session->magic	     = L2TP_SESSION_MAGIC;
+	session->owner	     = current->pid;
+	session->sock	     = sk;
+	session->tunnel	     = tunnel;
+	session->tunnel_sock = tunnel_sock;
+	session->tunnel_addr = sp->pppol2tp;
+	sprintf(&session->name[0], "sess %hu/%hu",
+		session->tunnel_addr.s_tunnel,
+		session->tunnel_addr.s_session);
+
+	session->stats.tunnel_id  = session->tunnel_addr.s_tunnel;
+	session->stats.session_id = session->tunnel_addr.s_session;
+
+	INIT_HLIST_NODE(&session->hlist);
+
+	/* Inherit debug options from tunnel */
+	session->debug = tunnel->debug;
+
+	/* Default MTU must allow space for UDP/L2TP/PPP
+	 * headers.
+	 */
+	session->mtu = session->mru = 1500 - PPPOL2TP_HEADER_OVERHEAD;
+
+	/* If PMTU discovery was enabled, use the MTU that was discovered */
+	dst = sk_dst_get(sk);
+	if (dst != NULL) {
+		u32 pmtu = dst_mtu(__sk_dst_get(sk));
+		if (pmtu != 0)
+			session->mtu = session->mru = pmtu -
+				PPPOL2TP_HEADER_OVERHEAD;
+		dst_release(dst);
+	}
+
+	/* Special case: if source & dest session_id == 0x0000, this socket is
+	 * being created to manage the tunnel. Don't add the session to the
+	 * session hash list, just set up the internal context for use by
+	 * ioctl() and sockopt() handlers.
+	 */
+	if ((session->tunnel_addr.s_session == 0) &&
+	    (session->tunnel_addr.d_session == 0)) {
+		error = 0;
+		sk->sk_user_data = session;
+		goto out_no_ppp;
+	}
+
+	/* Get tunnel context from the tunnel socket */
+	tunnel = pppol2tp_sock_to_tunnel(tunnel_sock);
+	if (tunnel == NULL) {
+		error = -EBADF;
+		goto end;
+	}
+
+	/* Right now, because we don't have a way to push the incoming skb's
+	 * straight through the UDP layer, the only header we need to worry
+	 * about is the L2TP header. This size is different depending on
+	 * whether sequence numbers are enabled for the data channel.
+	 */
+	po->chan.hdrlen = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
+
+	po->chan.private = sk;
+	po->chan.ops	 = &pppol2tp_chan_ops;
+	po->chan.mtu	 = session->mtu;
+
+	error = ppp_register_channel(&po->chan);
+	if (error)
+		goto end;
+
+	/* This is how we get the session context from the socket. */
+	sk->sk_user_data = session;
+
+	/* Add session to the tunnel's hash list */
+	write_lock(&tunnel->hlist_lock);
+	hlist_add_head(&session->hlist,
+		       pppol2tp_session_id_hash(tunnel,
+						session->tunnel_addr.s_session));
+	write_unlock(&tunnel->hlist_lock);
+
+	atomic_inc(&pppol2tp_session_count);
+
+out_no_ppp:
+	pppol2tp_tunnel_inc_refcount(tunnel);
+	sk->sk_state = PPPOX_CONNECTED;
+	PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+	       "%s: created\n", session->name);
+
+end:
+	release_sock(sk);
+
+	if (error != 0)
+		PRINTK(session ? session->debug : -1, PPPOL2TP_MSG_CONTROL, KERN_WARNING,
+		       "%s: connect failed: %d\n", session->name, error);
+
+	return error;
+}
+
+/* getname() support.
+ */
+static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr,
+			    int *usockaddr_len, int peer)
+{
+	int len = sizeof(struct sockaddr_pppol2tp);
+	struct sockaddr_pppol2tp sp;
+	int error = 0;
+	struct pppol2tp_session *session;
+
+	error = -ENOTCONN;
+	if (sock->sk->sk_state != PPPOX_CONNECTED)
+		goto end;
+
+	session = pppol2tp_sock_to_session(sock->sk);
+	if (session == NULL) {
+		error = -EBADF;
+		goto end;
+	}
+
+	sp.sa_family	= AF_PPPOX;
+	sp.sa_protocol	= PX_PROTO_OL2TP;
+	memcpy(&sp.pppol2tp, &session->tunnel_addr,
+	       sizeof(struct pppol2tp_addr));
+
+	memcpy(uaddr, &sp, len);
+
+	*usockaddr_len = len;
+
+	error = 0;
+
+end:
+	return error;
+}
+
+/****************************************************************************
+ * ioctl() handlers.
+ *
+ * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP
+ * sockets. However, in order to control kernel tunnel features, we allow
+ * userspace to create a special "tunnel" PPPoX socket which is used for
+ * control only.  Tunnel PPPoX sockets have session_id == 0 and simply allow
+ * the user application to issue L2TP setsockopt(), getsockopt() and ioctl()
+ * calls.
+ ****************************************************************************/
+
+/* Session ioctl helper.
+ */
+static int pppol2tp_session_ioctl(struct pppol2tp_session *session,
+				  unsigned int cmd, unsigned long arg)
+{
+	struct ifreq ifr;
+	int err = 0;
+	struct sock *sk = session->sock;
+	int val = (int) arg;
+
+	PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG,
+	       "%s: pppol2tp_session_ioctl(cmd=%#x, arg=%#lx)\n",
+	       session->name, cmd, arg);
+
+	sock_hold(sk);
+
+	switch (cmd) {
+	case SIOCGIFMTU:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		err = -EFAULT;
+		if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq)))
+			break;
+		ifr.ifr_mtu = session->mtu;
+		if (copy_to_user((void __user *) arg, &ifr, sizeof(struct ifreq)))
+			break;
+
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get mtu=%d\n", session->name, session->mtu);
+		err = 0;
+		break;
+
+	case SIOCSIFMTU:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		err = -EFAULT;
+		if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq)))
+			break;
+
+		session->mtu = ifr.ifr_mtu;
+
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set mtu=%d\n", session->name, session->mtu);
+		err = 0;
+		break;
+
+	case PPPIOCGMRU:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		err = -EFAULT;
+		if (put_user(session->mru, (int __user *) arg))
+			break;
+
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get mru=%d\n", session->name, session->mru);
+		err = 0;
+		break;
+
+	case PPPIOCSMRU:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		err = -EFAULT;
+		if (get_user(val,(int __user *) arg))
+			break;
+
+		session->mru = val;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set mru=%d\n", session->name, session->mru);
+		err = 0;
+		break;
+
+	case PPPIOCGFLAGS:
+		err = -EFAULT;
+		if (put_user(session->flags, (int __user *) arg))
+			break;
+
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get flags=%d\n", session->name, session->flags);
+		err = 0;
+		break;
+
+	case PPPIOCSFLAGS:
+		err = -EFAULT;
+		if (get_user(val, (int __user *) arg))
+			break;
+		session->flags = val;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set flags=%d\n", session->name, session->flags);
+		err = 0;
+		break;
+
+	case PPPIOCGL2TPSTATS:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		if (copy_to_user((void __user *) arg, &session->stats,
+				 sizeof(session->stats)))
+			break;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get L2TP stats\n", session->name);
+		err = 0;
+		break;
+
+	default:
+		err = -ENOSYS;
+		break;
+	}
+
+	sock_put(sk);
+
+	return err;
+}
+
+/* Tunnel ioctl helper.
+ *
+ * Note the special handling for PPPIOCGL2TPSTATS below. If the ioctl data
+ * specifies a session_id, the session ioctl handler is called. This allows an
+ * application to retrieve session stats via a tunnel socket.
+ */
+static int pppol2tp_tunnel_ioctl(struct pppol2tp_tunnel *tunnel,
+				 unsigned int cmd, unsigned long arg)
+{
+	int err = 0;
+	struct sock *sk = tunnel->sock;
+	struct pppol2tp_ioc_stats stats_req;
+
+	PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG,
+	       "%s: pppol2tp_tunnel_ioctl(cmd=%#x, arg=%#lx)\n", tunnel->name,
+	       cmd, arg);
+
+	sock_hold(sk);
+
+	switch (cmd) {
+	case PPPIOCGL2TPSTATS:
+		err = -ENXIO;
+		if (!(sk->sk_state & PPPOX_CONNECTED))
+			break;
+
+		if (copy_from_user(&stats_req, (void __user *) arg,
+				   sizeof(stats_req))) {
+			err = -EFAULT;
+			break;
+		}
+		if (stats_req.session_id != 0) {
+			/* resend to session ioctl handler */
+			struct pppol2tp_session *session =
+				pppol2tp_session_find(tunnel, stats_req.session_id);
+			if (session != NULL)
+				err = pppol2tp_session_ioctl(session, cmd, arg);
+			else
+				err = -EBADR;
+			break;
+		}
+#ifdef CONFIG_XFRM
+		tunnel->stats.using_ipsec = (sk->sk_policy[0] || sk->sk_policy[1]) ? 1 : 0;
+#endif
+		if (copy_to_user((void __user *) arg, &tunnel->stats,
+				 sizeof(tunnel->stats))) {
+			err = -EFAULT;
+			break;
+		}
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get L2TP stats\n", tunnel->name);
+		err = 0;
+		break;
+
+	default:
+		err = -ENOSYS;
+		break;
+	}
+
+	sock_put(sk);
+
+	return err;
+}
+
+/* Main ioctl() handler.
+ * Dispatch to tunnel or session helpers depending on the socket.
+ */
+static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd,
+			  unsigned long arg)
+{
+	struct sock *sk = sock->sk;
+	struct pppol2tp_session *session;
+	struct pppol2tp_tunnel *tunnel;
+	int err;
+
+	if (!sk)
+		return 0;
+
+	err = -EBADF;
+	if (sock_flag(sk, SOCK_DEAD) != 0)
+		goto end;
+
+	err = -ENOTCONN;
+	if ((sk->sk_user_data == NULL) ||
+	    (!(sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND))))
+		goto end;
+
+	/* Get session context from the socket */
+	err = -EBADF;
+	session = pppol2tp_sock_to_session(sk);
+	if (session == NULL)
+		goto end;
+
+	/* Special case: if session's session_id is zero, treat ioctl as a
+	 * tunnel ioctl
+	 */
+	if ((session->tunnel_addr.s_session == 0) &&
+	    (session->tunnel_addr.d_session == 0)) {
+		err = -EBADF;
+		tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+		if (tunnel == NULL)
+			goto end;
+
+		err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg);
+		goto end;
+	}
+
+	err = pppol2tp_session_ioctl(session, cmd, arg);
+
+end:
+	return err;
+}
+
+/*****************************************************************************
+ * setsockopt() / getsockopt() support.
+ *
+ * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP
+ * sockets. In order to control kernel tunnel features, we allow userspace to
+ * create a special "tunnel" PPPoX socket which is used for control only.
+ * Tunnel PPPoX sockets have session_id == 0 and simply allow the user
+ * application to issue L2TP setsockopt(), getsockopt() and ioctl() calls.
+ *****************************************************************************/
+
+/* Tunnel setsockopt() helper.
+ */
+static int pppol2tp_tunnel_setsockopt(struct sock *sk,
+				      struct pppol2tp_tunnel *tunnel,
+				      int optname, int val)
+{
+	int err = 0;
+
+	switch (optname) {
+	case PPPOL2TP_SO_DEBUG:
+		tunnel->debug = val;
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set debug=%x\n", tunnel->name, tunnel->debug);
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	return err;
+}
+
+/* Session setsockopt helper.
+ */
+static int pppol2tp_session_setsockopt(struct sock *sk,
+				       struct pppol2tp_session *session,
+				       int optname, int val)
+{
+	int err = 0;
+
+	switch (optname) {
+	case PPPOL2TP_SO_RECVSEQ:
+		if ((val != 0) && (val != 1)) {
+			err = -EINVAL;
+			break;
+		}
+		session->recv_seq = val ? -1 : 0;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set recv_seq=%d\n", session->name,
+		       session->recv_seq);
+		break;
+
+	case PPPOL2TP_SO_SENDSEQ:
+		if ((val != 0) && (val != 1)) {
+			err = -EINVAL;
+			break;
+		}
+		session->send_seq = val ? -1 : 0;
+		{
+			struct sock *ssk      = session->sock;
+			struct pppox_sock *po = pppox_sk(ssk);
+			po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ :
+				PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
+		}
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set send_seq=%d\n", session->name, session->send_seq);
+		break;
+
+	case PPPOL2TP_SO_LNSMODE:
+		if ((val != 0) && (val != 1)) {
+			err = -EINVAL;
+			break;
+		}
+		session->lns_mode = val ? -1 : 0;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set lns_mode=%d\n", session->name,
+		       session->lns_mode);
+		break;
+
+	case PPPOL2TP_SO_DEBUG:
+		session->debug = val;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set debug=%x\n", session->name, session->debug);
+		break;
+
+	case PPPOL2TP_SO_REORDERTO:
+		session->reorder_timeout = msecs_to_jiffies(val);
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: set reorder_timeout=%d\n", session->name,
+		       session->reorder_timeout);
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	return err;
+}
+
+/* Main setsockopt() entry point.
+ * Does API checks, then calls either the tunnel or session setsockopt
+ * handler, according to whether the PPPoL2TP socket is a for a regular
+ * session or the special tunnel type.
+ */
+static int pppol2tp_setsockopt(struct socket *sock, int level, int optname,
+			       char __user *optval, int optlen)
+{
+	struct sock *sk = sock->sk;
+	struct pppol2tp_session *session = sk->sk_user_data;
+	struct pppol2tp_tunnel *tunnel;
+	int val;
+	int err;
+
+	if (level != SOL_PPPOL2TP)
+		return udp_prot.setsockopt(sk, level, optname, optval, optlen);
+
+	if (optlen < sizeof(int))
+		return -EINVAL;
+
+	if (get_user(val, (int __user *)optval))
+		return -EFAULT;
+
+	err = -ENOTCONN;
+	if (sk->sk_user_data == NULL)
+		goto end;
+
+	/* Get session context from the socket */
+	err = -EBADF;
+	session = pppol2tp_sock_to_session(sk);
+	if (session == NULL)
+		goto end;
+
+	/* Special case: if session_id == 0x0000, treat as operation on tunnel
+	 */
+	if ((session->tunnel_addr.s_session == 0) &&
+	    (session->tunnel_addr.d_session == 0)) {
+		err = -EBADF;
+		tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+		if (tunnel == NULL)
+			goto end;
+
+		err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val);
+	} else
+		err = pppol2tp_session_setsockopt(sk, session, optname, val);
+
+	err = 0;
+
+end:
+	return err;
+}
+
+/* Tunnel getsockopt helper. Called with sock locked.
+ */
+static int pppol2tp_tunnel_getsockopt(struct sock *sk,
+				      struct pppol2tp_tunnel *tunnel,
+				      int optname, int __user *val)
+{
+	int err = 0;
+
+	switch (optname) {
+	case PPPOL2TP_SO_DEBUG:
+		*val = tunnel->debug;
+		PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get debug=%x\n", tunnel->name, tunnel->debug);
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	return err;
+}
+
+/* Session getsockopt helper. Called with sock locked.
+ */
+static int pppol2tp_session_getsockopt(struct sock *sk,
+				       struct pppol2tp_session *session,
+				       int optname, int __user *val)
+{
+	int err = 0;
+
+	switch (optname) {
+	case PPPOL2TP_SO_RECVSEQ:
+		*val = session->recv_seq;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get recv_seq=%d\n", session->name, *val);
+		break;
+
+	case PPPOL2TP_SO_SENDSEQ:
+		*val = session->send_seq;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get send_seq=%d\n", session->name, *val);
+		break;
+
+	case PPPOL2TP_SO_LNSMODE:
+		*val = session->lns_mode;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get lns_mode=%d\n", session->name, *val);
+		break;
+
+	case PPPOL2TP_SO_DEBUG:
+		*val = session->debug;
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get debug=%d\n", session->name, *val);
+		break;
+
+	case PPPOL2TP_SO_REORDERTO:
+		*val = (int) jiffies_to_msecs(session->reorder_timeout);
+		PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+		       "%s: get reorder_timeout=%d\n", session->name, *val);
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+	}
+
+	return err;
+}
+
+/* Main getsockopt() entry point.
+ * Does API checks, then calls either the tunnel or session getsockopt
+ * handler, according to whether the PPPoX socket is a for a regular session
+ * or the special tunnel type.
+ */
+static int pppol2tp_getsockopt(struct socket *sock, int level,
+			       int optname, char __user *optval, int __user *optlen)
+{
+	struct sock *sk = sock->sk;
+	struct pppol2tp_session *session = sk->sk_user_data;
+	struct pppol2tp_tunnel *tunnel;
+	int val, len;
+	int err;
+
+	if (level != SOL_PPPOL2TP)
+		return udp_prot.getsockopt(sk, level, optname, optval, optlen);
+
+	if (get_user(len, (int __user *) optlen))
+		return -EFAULT;
+
+	len = min_t(unsigned int, len, sizeof(int));
+
+	if (len < 0)
+		return -EINVAL;
+
+	err = -ENOTCONN;
+	if (sk->sk_user_data == NULL)
+		goto end;
+
+	/* Get the session context */
+	err = -EBADF;
+	session = pppol2tp_sock_to_session(sk);
+	if (session == NULL)
+		goto end;
+
+	/* Special case: if session_id == 0x0000, treat as operation on tunnel */
+	if ((session->tunnel_addr.s_session == 0) &&
+	    (session->tunnel_addr.d_session == 0)) {
+		err = -EBADF;
+		tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+		if (tunnel == NULL)
+			goto end;
+
+		err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val);
+	} else
+		err = pppol2tp_session_getsockopt(sk, session, optname, &val);
+
+	err = -EFAULT;
+	if (put_user(len, (int __user *) optlen))
+		goto end;
+
+	if (copy_to_user((void __user *) optval, &val, len))
+		goto end;
+
+	err = 0;
+end:
+	return err;
+}
+
+/*****************************************************************************
+ * /proc filesystem for debug
+ *****************************************************************************/
+
+#ifdef CONFIG_PROC_FS
+
+#include <linux/seq_file.h>
+
+struct pppol2tp_seq_data {
+	struct pppol2tp_tunnel *tunnel; /* current tunnel */
+	struct pppol2tp_session *session; /* NULL means get first session in tunnel */
+};
+
+static struct pppol2tp_session *next_session(struct pppol2tp_tunnel *tunnel, struct pppol2tp_session *curr)
+{
+	struct pppol2tp_session *session = NULL;
+	struct hlist_node *walk;
+	int found = 0;
+	int next = 0;
+	int i;
+
+	read_lock(&tunnel->hlist_lock);
+	for (i = 0; i < PPPOL2TP_HASH_SIZE; i++) {
+		hlist_for_each_entry(session, walk, &tunnel->session_hlist[i], hlist) {
+			if (curr == NULL) {
+				found = 1;
+				goto out;
+			}
+			if (session == curr) {
+				next = 1;
+				continue;
+			}
+			if (next) {
+				found = 1;
+				goto out;
+			}
+		}
+	}
+out:
+	read_unlock(&tunnel->hlist_lock);
+	if (!found)
+		session = NULL;
+
+	return session;
+}
+
+static struct pppol2tp_tunnel *next_tunnel(struct pppol2tp_tunnel *curr)
+{
+	struct pppol2tp_tunnel *tunnel = NULL;
+
+	read_lock(&pppol2tp_tunnel_list_lock);
+	if (list_is_last(&curr->list, &pppol2tp_tunnel_list)) {
+		goto out;
+	}
+	tunnel = list_entry(curr->list.next, struct pppol2tp_tunnel, list);
+out:
+	read_unlock(&pppol2tp_tunnel_list_lock);
+
+	return tunnel;
+}
+
+static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs)
+{
+	struct pppol2tp_seq_data *pd = SEQ_START_TOKEN;
+	loff_t pos = *offs;
+
+	if (!pos)
+		goto out;
+
+	BUG_ON(m->private == NULL);
+	pd = m->private;
+
+	if (pd->tunnel == NULL) {
+		if (!list_empty(&pppol2tp_tunnel_list))
+			pd->tunnel = list_entry(pppol2tp_tunnel_list.next, struct pppol2tp_tunnel, list);
+	} else {
+		pd->session = next_session(pd->tunnel, pd->session);
+		if (pd->session == NULL) {
+			pd->tunnel = next_tunnel(pd->tunnel);
+		}
+	}
+
+	/* NULL tunnel and session indicates end of list */
+	if ((pd->tunnel == NULL) && (pd->session == NULL))
+		pd = NULL;
+
+out:
+	return pd;
+}
+
+static void *pppol2tp_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return NULL;
+}
+
+static void pppol2tp_seq_stop(struct seq_file *p, void *v)
+{
+	/* nothing to do */
+}
+
+static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v)
+{
+	struct pppol2tp_tunnel *tunnel = v;
+
+	seq_printf(m, "\nTUNNEL '%s', %c %d\n",
+		   tunnel->name,
+		   (tunnel == tunnel->sock->sk_user_data) ? 'Y':'N',
+		   atomic_read(&tunnel->ref_count) - 1);
+	seq_printf(m, " %08x %llu/%llu/%llu %llu/%llu/%llu\n",
+		   tunnel->debug,
+		   tunnel->stats.tx_packets, tunnel->stats.tx_bytes,
+		   tunnel->stats.tx_errors,
+		   tunnel->stats.rx_packets, tunnel->stats.rx_bytes,
+		   tunnel->stats.rx_errors);
+}
+
+static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
+{
+	struct pppol2tp_session *session = v;
+
+	seq_printf(m, "  SESSION '%s' %08X/%d %04X/%04X -> "
+		   "%04X/%04X %d %c\n",
+		   session->name,
+		   ntohl(session->tunnel_addr.addr.sin_addr.s_addr),
+		   ntohs(session->tunnel_addr.addr.sin_port),
+		   session->tunnel_addr.s_tunnel,
+		   session->tunnel_addr.s_session,
+		   session->tunnel_addr.d_tunnel,
+		   session->tunnel_addr.d_session,
+		   session->sock->sk_state,
+		   (session == session->sock->sk_user_data) ?
+		   'Y' : 'N');
+	seq_printf(m, "   %d/%d/%c/%c/%s %08x %u\n",
+		   session->mtu, session->mru,
+		   session->recv_seq ? 'R' : '-',
+		   session->send_seq ? 'S' : '-',
+		   session->lns_mode ? "LNS" : "LAC",
+		   session->debug,
+		   jiffies_to_msecs(session->reorder_timeout));
+	seq_printf(m, "   %hu/%hu %llu/%llu/%llu %llu/%llu/%llu\n",
+		   session->nr, session->ns,
+		   session->stats.tx_packets,
+		   session->stats.tx_bytes,
+		   session->stats.tx_errors,
+		   session->stats.rx_packets,
+		   session->stats.rx_bytes,
+		   session->stats.rx_errors);
+}
+
+static int pppol2tp_seq_show(struct seq_file *m, void *v)
+{
+	struct pppol2tp_seq_data *pd = v;
+
+	/* display header on line 1 */
+	if (v == SEQ_START_TOKEN) {
+		seq_puts(m, "PPPoL2TP driver info, " PPPOL2TP_DRV_VERSION "\n");
+		seq_puts(m, "TUNNEL name, user-data-ok session-count\n");
+		seq_puts(m, " debug tx-pkts/bytes/errs rx-pkts/bytes/errs\n");
+		seq_puts(m, "  SESSION name, addr/port src-tid/sid "
+			 "dest-tid/sid state user-data-ok\n");
+		seq_puts(m, "   mtu/mru/rcvseq/sendseq/lns debug reorderto\n");
+		seq_puts(m, "   nr/ns tx-pkts/bytes/errs rx-pkts/bytes/errs\n");
+		goto out;
+	}
+
+	/* Show the tunnel or session context.
+	 */
+	if (pd->session == NULL)
+		pppol2tp_seq_tunnel_show(m, pd->tunnel);
+	else
+		pppol2tp_seq_session_show(m, pd->session);
+
+out:
+	return 0;
+}
+
+static struct seq_operations pppol2tp_seq_ops = {
+	.start		= pppol2tp_seq_start,
+	.next		= pppol2tp_seq_next,
+	.stop		= pppol2tp_seq_stop,
+	.show		= pppol2tp_seq_show,
+};
+
+/* Called when our /proc file is opened. We allocate data for use when
+ * iterating our tunnel / session contexts and store it in the private
+ * data of the seq_file.
+ */
+static int pppol2tp_proc_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *m;
+	struct pppol2tp_seq_data *pd;
+	int ret = 0;
+
+	ret = seq_open(file, &pppol2tp_seq_ops);
+	if (ret < 0)
+		goto out;
+
+	m = file->private_data;
+
+	/* Allocate and fill our proc_data for access later */
+	ret = -ENOMEM;
+	m->private = kzalloc(sizeof(struct pppol2tp_seq_data), GFP_KERNEL);
+	if (m->private == NULL)
+		goto out;
+
+	pd = m->private;
+	ret = 0;
+
+out:
+	return ret;
+}
+
+/* Called when /proc file access completes.
+ */
+static int pppol2tp_proc_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *m = (struct seq_file *)file->private_data;
+
+	kfree(m->private);
+	m->private = NULL;
+
+	return seq_release(inode, file);
+}
+
+static struct file_operations pppol2tp_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pppol2tp_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= pppol2tp_proc_release,
+};
+
+static struct proc_dir_entry *pppol2tp_proc;
+
+#endif /* CONFIG_PROC_FS */
+
+/*****************************************************************************
+ * Init and cleanup
+ *****************************************************************************/
+
+static struct proto_ops pppol2tp_ops = {
+	.family		= AF_PPPOX,
+	.owner		= THIS_MODULE,
+	.release	= pppol2tp_release,
+	.bind		= sock_no_bind,
+	.connect	= pppol2tp_connect,
+	.socketpair	= sock_no_socketpair,
+	.accept		= sock_no_accept,
+	.getname	= pppol2tp_getname,
+	.poll		= datagram_poll,
+	.listen		= sock_no_listen,
+	.shutdown	= sock_no_shutdown,
+	.setsockopt	= pppol2tp_setsockopt,
+	.getsockopt	= pppol2tp_getsockopt,
+	.sendmsg	= pppol2tp_sendmsg,
+	.recvmsg	= pppol2tp_recvmsg,
+	.mmap		= sock_no_mmap,
+	.ioctl		= pppox_ioctl,
+};
+
+static struct pppox_proto pppol2tp_proto = {
+	.create		= pppol2tp_create,
+	.ioctl		= pppol2tp_ioctl
+};
+
+static int __init pppol2tp_init(void)
+{
+	int err;
+
+	err = proto_register(&pppol2tp_sk_proto, 0);
+	if (err)
+		goto out;
+	err = register_pppox_proto(PX_PROTO_OL2TP, &pppol2tp_proto);
+	if (err)
+		goto out_unregister_pppol2tp_proto;
+
+#ifdef CONFIG_PROC_FS
+	pppol2tp_proc = create_proc_entry("pppol2tp", 0, proc_net);
+	if (!pppol2tp_proc) {
+		err = -ENOMEM;
+		goto out_unregister_pppox_proto;
+	}
+	pppol2tp_proc->proc_fops = &pppol2tp_proc_fops;
+#endif /* CONFIG_PROC_FS */
+	printk(KERN_INFO "PPPoL2TP kernel driver, %s\n",
+	       PPPOL2TP_DRV_VERSION);
+
+out:
+	return err;
+
+out_unregister_pppox_proto:
+	unregister_pppox_proto(PX_PROTO_OL2TP);
+out_unregister_pppol2tp_proto:
+	proto_unregister(&pppol2tp_sk_proto);
+	goto out;
+}
+
+static void __exit pppol2tp_exit(void)
+{
+	unregister_pppox_proto(PX_PROTO_OL2TP);
+
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("pppol2tp", proc_net);
+#endif
+	proto_unregister(&pppol2tp_sk_proto);
+}
+
+module_init(pppol2tp_init);
+module_exit(pppol2tp_exit);
+
+MODULE_AUTHOR("Martijn van Oosterhout <kleptog@svana.org>,"
+	      "James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("PPP over L2TP over UDP");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PPPOL2TP_DRV_VERSION);
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
new file mode 100644
index 0000000..08d2506
--- /dev/null
+++ b/drivers/net/ps3_gelic_net.c
@@ -0,0 +1,1576 @@
+/*
+ *  PS3 gelic network driver.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ *
+ * This file is based on: spider_net.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ *           Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+#include <linux/dma-mapping.h>
+#include <net/checksum.h>
+#include <asm/firmware.h>
+#include <asm/ps3.h>
+#include <asm/lv1call.h>
+
+#include "ps3_gelic_net.h"
+
+#define DRV_NAME "Gelic Network Driver"
+#define DRV_VERSION "1.0"
+
+MODULE_AUTHOR("SCE Inc.");
+MODULE_DESCRIPTION("Gelic Network driver");
+MODULE_LICENSE("GPL");
+
+static inline struct device *ctodev(struct gelic_net_card *card)
+{
+	return &card->dev->core;
+}
+static inline unsigned int bus_id(struct gelic_net_card *card)
+{
+	return card->dev->bus_id;
+}
+static inline unsigned int dev_id(struct gelic_net_card *card)
+{
+	return card->dev->dev_id;
+}
+
+/* set irq_mask */
+static int gelic_net_set_irq_mask(struct gelic_net_card *card, u64 mask)
+{
+	int status;
+
+	status = lv1_net_set_interrupt_mask(bus_id(card), dev_id(card),
+					    mask, 0);
+	if (status)
+		dev_info(ctodev(card),
+			 "lv1_net_set_interrupt_mask failed %d\n", status);
+	return status;
+}
+static inline void gelic_net_rx_irq_on(struct gelic_net_card *card)
+{
+	gelic_net_set_irq_mask(card, card->ghiintmask | GELIC_NET_RXINT);
+}
+static inline void gelic_net_rx_irq_off(struct gelic_net_card *card)
+{
+	gelic_net_set_irq_mask(card, card->ghiintmask & ~GELIC_NET_RXINT);
+}
+/**
+ * gelic_net_get_descr_status -- returns the status of a descriptor
+ * @descr: descriptor to look at
+ *
+ * returns the status as in the dmac_cmd_status field of the descriptor
+ */
+static enum gelic_net_descr_status
+gelic_net_get_descr_status(struct gelic_net_descr *descr)
+{
+	u32 cmd_status;
+
+	cmd_status = descr->dmac_cmd_status;
+	cmd_status >>= GELIC_NET_DESCR_IND_PROC_SHIFT;
+	return cmd_status;
+}
+
+/**
+ * gelic_net_set_descr_status -- sets the status of a descriptor
+ * @descr: descriptor to change
+ * @status: status to set in the descriptor
+ *
+ * changes the status to the specified value. Doesn't change other bits
+ * in the status
+ */
+static void gelic_net_set_descr_status(struct gelic_net_descr *descr,
+				       enum gelic_net_descr_status status)
+{
+	u32 cmd_status;
+
+	/* read the status */
+	cmd_status = descr->dmac_cmd_status;
+	/* clean the upper 4 bits */
+	cmd_status &= GELIC_NET_DESCR_IND_PROC_MASKO;
+	/* add the status to it */
+	cmd_status |= ((u32)status) << GELIC_NET_DESCR_IND_PROC_SHIFT;
+	/* and write it back */
+	descr->dmac_cmd_status = cmd_status;
+	/*
+	 * dma_cmd_status field is used to indicate whether the descriptor
+	 * is valid or not.
+	 * Usually caller of this function wants to inform that to the
+	 * hardware, so we assure here the hardware sees the change.
+	 */
+	wmb();
+}
+
+/**
+ * gelic_net_free_chain - free descriptor chain
+ * @card: card structure
+ * @descr_in: address of desc
+ */
+static void gelic_net_free_chain(struct gelic_net_card *card,
+				 struct gelic_net_descr *descr_in)
+{
+	struct gelic_net_descr *descr;
+
+	for (descr = descr_in; descr && descr->bus_addr; descr = descr->next) {
+		dma_unmap_single(ctodev(card), descr->bus_addr,
+				 GELIC_NET_DESCR_SIZE, DMA_BIDIRECTIONAL);
+		descr->bus_addr = 0;
+	}
+}
+
+/**
+ * gelic_net_init_chain - links descriptor chain
+ * @card: card structure
+ * @chain: address of chain
+ * @start_descr: address of descriptor array
+ * @no: number of descriptors
+ *
+ * we manage a circular list that mirrors the hardware structure,
+ * except that the hardware uses bus addresses.
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_init_chain(struct gelic_net_card *card,
+				struct gelic_net_descr_chain *chain,
+				struct gelic_net_descr *start_descr, int no)
+{
+	int i;
+	struct gelic_net_descr *descr;
+
+	descr = start_descr;
+	memset(descr, 0, sizeof(*descr) * no);
+
+	/* set up the hardware pointers in each descriptor */
+	for (i = 0; i < no; i++, descr++) {
+		gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+		descr->bus_addr =
+			dma_map_single(ctodev(card), descr,
+				       GELIC_NET_DESCR_SIZE,
+				       DMA_BIDIRECTIONAL);
+
+		if (!descr->bus_addr)
+			goto iommu_error;
+
+		descr->next = descr + 1;
+		descr->prev = descr - 1;
+	}
+	/* make them as ring */
+	(descr - 1)->next = start_descr;
+	start_descr->prev = (descr - 1);
+
+	/* chain bus addr of hw descriptor */
+	descr = start_descr;
+	for (i = 0; i < no; i++, descr++) {
+		descr->next_descr_addr = descr->next->bus_addr;
+	}
+
+	chain->head = start_descr;
+	chain->tail = start_descr;
+
+	/* do not chain last hw descriptor */
+	(descr - 1)->next_descr_addr = 0;
+
+	return 0;
+
+iommu_error:
+	for (i--, descr--; 0 <= i; i--, descr--)
+		if (descr->bus_addr)
+			dma_unmap_single(ctodev(card), descr->bus_addr,
+					 GELIC_NET_DESCR_SIZE,
+					 DMA_BIDIRECTIONAL);
+	return -ENOMEM;
+}
+
+/**
+ * gelic_net_prepare_rx_descr - reinitializes a rx descriptor
+ * @card: card structure
+ * @descr: descriptor to re-init
+ *
+ * return 0 on succes, <0 on failure
+ *
+ * allocates a new rx skb, iommu-maps it and attaches it to the descriptor.
+ * Activate the descriptor state-wise
+ */
+static int gelic_net_prepare_rx_descr(struct gelic_net_card *card,
+				      struct gelic_net_descr *descr)
+{
+	int offset;
+	unsigned int bufsize;
+
+	if (gelic_net_get_descr_status(descr) !=  GELIC_NET_DESCR_NOT_IN_USE) {
+		dev_info(ctodev(card), "%s: ERROR status \n", __func__);
+	}
+	/* we need to round up the buffer size to a multiple of 128 */
+	bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN);
+
+	/* and we need to have it 128 byte aligned, therefore we allocate a
+	 * bit more */
+	descr->skb = netdev_alloc_skb(card->netdev,
+		bufsize + GELIC_NET_RXBUF_ALIGN - 1);
+	if (!descr->skb) {
+		descr->buf_addr = 0; /* tell DMAC don't touch memory */
+		dev_info(ctodev(card),
+			 "%s:allocate skb failed !!\n", __func__);
+		return -ENOMEM;
+	}
+	descr->buf_size = bufsize;
+	descr->dmac_cmd_status = 0;
+	descr->result_size = 0;
+	descr->valid_size = 0;
+	descr->data_error = 0;
+
+	offset = ((unsigned long)descr->skb->data) &
+		(GELIC_NET_RXBUF_ALIGN - 1);
+	if (offset)
+		skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset);
+	/* io-mmu-map the skb */
+	descr->buf_addr = dma_map_single(ctodev(card), descr->skb->data,
+					 GELIC_NET_MAX_MTU,
+					 DMA_FROM_DEVICE);
+	if (!descr->buf_addr) {
+		dev_kfree_skb_any(descr->skb);
+		descr->skb = NULL;
+		dev_info(ctodev(card),
+			 "%s:Could not iommu-map rx buffer\n", __func__);
+		gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+		return -ENOMEM;
+	} else {
+		gelic_net_set_descr_status(descr, GELIC_NET_DESCR_CARDOWNED);
+		return 0;
+	}
+}
+
+/**
+ * gelic_net_release_rx_chain - free all skb of rx descr
+ * @card: card structure
+ *
+ */
+static void gelic_net_release_rx_chain(struct gelic_net_card *card)
+{
+	struct gelic_net_descr *descr = card->rx_chain.head;
+
+	do {
+		if (descr->skb) {
+			dma_unmap_single(ctodev(card),
+					 descr->buf_addr,
+					 descr->skb->len,
+					 DMA_FROM_DEVICE);
+			descr->buf_addr = 0;
+			dev_kfree_skb_any(descr->skb);
+			descr->skb = NULL;
+			descr->dmac_cmd_status = GELIC_NET_DESCR_NOT_IN_USE;
+		}
+		descr = descr->next;
+	} while (descr != card->rx_chain.head);
+}
+
+/**
+ * gelic_net_fill_rx_chain - fills descriptors/skbs in the rx chains
+ * @card: card structure
+ *
+ * fills all descriptors in the rx chain: allocates skbs
+ * and iommu-maps them.
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_fill_rx_chain(struct gelic_net_card *card)
+{
+	struct gelic_net_descr *descr = card->rx_chain.head;
+	int ret;
+
+	do {
+		if (!descr->skb) {
+			ret = gelic_net_prepare_rx_descr(card, descr);
+			if (ret)
+				goto rewind;
+		}
+		descr = descr->next;
+	} while (descr != card->rx_chain.head);
+
+	return 0;
+rewind:
+	gelic_net_release_rx_chain(card);
+	return ret;
+}
+
+/**
+ * gelic_net_alloc_rx_skbs - allocates rx skbs in rx descriptor chains
+ * @card: card structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_alloc_rx_skbs(struct gelic_net_card *card)
+{
+	struct gelic_net_descr_chain *chain;
+	int ret;
+	chain = &card->rx_chain;
+	ret = gelic_net_fill_rx_chain(card);
+	chain->head = card->rx_top->prev; /* point to the last */
+	return ret;
+}
+
+/**
+ * gelic_net_release_tx_descr - processes a used tx descriptor
+ * @card: card structure
+ * @descr: descriptor to release
+ *
+ * releases a used tx descriptor (unmapping, freeing of skb)
+ */
+static void gelic_net_release_tx_descr(struct gelic_net_card *card,
+			    struct gelic_net_descr *descr)
+{
+	struct sk_buff *skb;
+
+
+	if (descr->data_status & (1 << GELIC_NET_TXDESC_TAIL)) {
+		/* 2nd descriptor */
+		skb = descr->skb;
+		dma_unmap_single(ctodev(card), descr->buf_addr, skb->len,
+				 DMA_TO_DEVICE);
+		dev_kfree_skb_any(skb);
+	} else {
+		dma_unmap_single(ctodev(card), descr->buf_addr,
+				 descr->buf_size, DMA_TO_DEVICE);
+	}
+
+	descr->buf_addr = 0;
+	descr->buf_size = 0;
+	descr->next_descr_addr = 0;
+	descr->result_size = 0;
+	descr->valid_size = 0;
+	descr->data_status = 0;
+	descr->data_error = 0;
+	descr->skb = NULL;
+
+	/* set descr status */
+	descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE;
+}
+
+/**
+ * gelic_net_release_tx_chain - processes sent tx descriptors
+ * @card: adapter structure
+ * @stop: net_stop sequence
+ *
+ * releases the tx descriptors that gelic has finished with
+ */
+static void gelic_net_release_tx_chain(struct gelic_net_card *card, int stop)
+{
+	struct gelic_net_descr_chain *tx_chain;
+	enum gelic_net_descr_status status;
+	int release = 0;
+
+	for (tx_chain = &card->tx_chain;
+	     tx_chain->head != tx_chain->tail && tx_chain->tail;
+	     tx_chain->tail = tx_chain->tail->next) {
+		status = gelic_net_get_descr_status(tx_chain->tail);
+		switch (status) {
+		case GELIC_NET_DESCR_RESPONSE_ERROR:
+		case GELIC_NET_DESCR_PROTECTION_ERROR:
+		case GELIC_NET_DESCR_FORCE_END:
+			if (printk_ratelimit())
+				dev_info(ctodev(card),
+					 "%s: forcing end of tx descriptor " \
+					 "with status %x\n",
+					 __func__, status);
+			card->netdev_stats.tx_dropped++;
+			break;
+
+		case GELIC_NET_DESCR_COMPLETE:
+			card->netdev_stats.tx_packets++;
+			card->netdev_stats.tx_bytes +=
+				tx_chain->tail->skb->len;
+			break;
+
+		case GELIC_NET_DESCR_CARDOWNED:
+			/* pending tx request */
+		default:
+			/* any other value (== GELIC_NET_DESCR_NOT_IN_USE) */
+			goto out;
+		}
+		gelic_net_release_tx_descr(card, tx_chain->tail);
+		release = 1;
+	}
+out:
+	if (!stop && release)
+		netif_wake_queue(card->netdev);
+}
+
+/**
+ * gelic_net_set_multi - sets multicast addresses and promisc flags
+ * @netdev: interface device structure
+ *
+ * gelic_net_set_multi configures multicast addresses as needed for the
+ * netdev interface. It also sets up multicast, allmulti and promisc
+ * flags appropriately
+ */
+static void gelic_net_set_multi(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+	struct dev_mc_list *mc;
+	unsigned int i;
+	uint8_t *p;
+	u64 addr;
+	int status;
+
+	/* clear all multicast address */
+	status = lv1_net_remove_multicast_address(bus_id(card), dev_id(card),
+						  0, 1);
+	if (status)
+		dev_err(ctodev(card),
+			"lv1_net_remove_multicast_address failed %d\n",
+			status);
+	/* set broadcast address */
+	status = lv1_net_add_multicast_address(bus_id(card), dev_id(card),
+					       GELIC_NET_BROADCAST_ADDR, 0);
+	if (status)
+		dev_err(ctodev(card),
+			"lv1_net_add_multicast_address failed, %d\n",
+			status);
+
+	if (netdev->flags & IFF_ALLMULTI
+		|| netdev->mc_count > GELIC_NET_MC_COUNT_MAX) { /* list max */
+		status = lv1_net_add_multicast_address(bus_id(card),
+						       dev_id(card),
+						       0, 1);
+		if (status)
+			dev_err(ctodev(card),
+				"lv1_net_add_multicast_address failed, %d\n",
+				status);
+		return;
+	}
+
+	/* set multicast address */
+	for (mc = netdev->mc_list; mc; mc = mc->next) {
+		addr = 0;
+		p = mc->dmi_addr;
+		for (i = 0; i < ETH_ALEN; i++) {
+			addr <<= 8;
+			addr |= *p++;
+		}
+		status = lv1_net_add_multicast_address(bus_id(card),
+						       dev_id(card),
+						       addr, 0);
+		if (status)
+			dev_err(ctodev(card),
+				"lv1_net_add_multicast_address failed, %d\n",
+				status);
+	}
+}
+
+/**
+ * gelic_net_enable_rxdmac - enables the receive DMA controller
+ * @card: card structure
+ *
+ * gelic_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
+ * in the GDADMACCNTR register
+ */
+static inline void gelic_net_enable_rxdmac(struct gelic_net_card *card)
+{
+	int status;
+
+	status = lv1_net_start_rx_dma(bus_id(card), dev_id(card),
+				card->rx_chain.tail->bus_addr, 0);
+	if (status)
+		dev_info(ctodev(card),
+			 "lv1_net_start_rx_dma failed, status=%d\n", status);
+}
+
+/**
+ * gelic_net_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * gelic_net_disable_rxdmac terminates processing on the DMA controller by
+ * turing off DMA and issueing a force end
+ */
+static inline void gelic_net_disable_rxdmac(struct gelic_net_card *card)
+{
+	int status;
+
+	/* this hvc blocks until the DMA in progress really stopped */
+	status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card), 0);
+	if (status)
+		dev_err(ctodev(card),
+			"lv1_net_stop_rx_dma faild, %d\n", status);
+}
+
+/**
+ * gelic_net_disable_txdmac - disables the transmit DMA controller
+ * @card: card structure
+ *
+ * gelic_net_disable_txdmac terminates processing on the DMA controller by
+ * turing off DMA and issueing a force end
+ */
+static inline void gelic_net_disable_txdmac(struct gelic_net_card *card)
+{
+	int status;
+
+	/* this hvc blocks until the DMA in progress really stopped */
+	status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card), 0);
+	if (status)
+		dev_err(ctodev(card),
+			"lv1_net_stop_tx_dma faild, status=%d\n", status);
+}
+
+/**
+ * gelic_net_stop - called upon ifconfig down
+ * @netdev: interface device structure
+ *
+ * always returns 0
+ */
+static int gelic_net_stop(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	netif_poll_disable(netdev);
+	netif_stop_queue(netdev);
+
+	/* turn off DMA, force end */
+	gelic_net_disable_rxdmac(card);
+	gelic_net_disable_txdmac(card);
+
+	gelic_net_set_irq_mask(card, 0);
+
+	/* disconnect event port */
+	free_irq(card->netdev->irq, card->netdev);
+	ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq);
+	card->netdev->irq = NO_IRQ;
+
+	netif_carrier_off(netdev);
+
+	/* release chains */
+	gelic_net_release_tx_chain(card, 1);
+	gelic_net_release_rx_chain(card);
+
+	gelic_net_free_chain(card, card->tx_top);
+	gelic_net_free_chain(card, card->rx_top);
+
+	return 0;
+}
+
+/**
+ * gelic_net_get_next_tx_descr - returns the next available tx descriptor
+ * @card: device structure to get descriptor from
+ *
+ * returns the address of the next descriptor, or NULL if not available.
+ */
+static struct gelic_net_descr *
+gelic_net_get_next_tx_descr(struct gelic_net_card *card)
+{
+	if (!card->tx_chain.head)
+		return NULL;
+	/*  see if we can two consecutive free descrs */
+	if (card->tx_chain.tail != card->tx_chain.head->next &&
+	    gelic_net_get_descr_status(card->tx_chain.head) ==
+	    GELIC_NET_DESCR_NOT_IN_USE &&
+	    card->tx_chain.tail != card->tx_chain.head->next->next &&
+	    gelic_net_get_descr_status(card->tx_chain.head->next) ==
+	     GELIC_NET_DESCR_NOT_IN_USE )
+		return card->tx_chain.head;
+	else
+		return NULL;
+
+}
+
+/**
+ * gelic_net_set_txdescr_cmdstat - sets the tx descriptor command field
+ * @descr: descriptor structure to fill out
+ * @skb: packet to consider
+ * @middle: middle of frame
+ *
+ * fills out the command and status field of the descriptor structure,
+ * depending on hardware checksum settings. This function assumes a wmb()
+ * has executed before.
+ */
+static void gelic_net_set_txdescr_cmdstat(struct gelic_net_descr *descr,
+					  struct sk_buff *skb, int middle)
+{
+	u32 eofr;
+
+	if (middle)
+		eofr = 0;
+	else
+		eofr = GELIC_NET_DMAC_CMDSTAT_END_FRAME;
+
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+		descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOCS | eofr;
+	else {
+		/* is packet ip?
+		 * if yes: tcp? udp? */
+		if (skb->protocol == htons(ETH_P_IP)) {
+			if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+				descr->dmac_cmd_status =
+					GELIC_NET_DMAC_CMDSTAT_TCPCS | eofr;
+			else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+				descr->dmac_cmd_status =
+					GELIC_NET_DMAC_CMDSTAT_UDPCS | eofr;
+			else	/*
+				 * the stack should checksum non-tcp and non-udp
+				 * packets on his own: NETIF_F_IP_CSUM
+				 */
+				descr->dmac_cmd_status =
+					GELIC_NET_DMAC_CMDSTAT_NOCS | eofr;
+		}
+	}
+}
+
+/**
+ * gelic_net_prepare_tx_descr_v - get dma address of skb_data
+ * @card: card structure
+ * @descr: descriptor structure
+ * @skb: packet to use
+ *
+ * returns 0 on success, <0 on failure.
+ *
+ */
+static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card,
+					struct gelic_net_descr *descr,
+					struct sk_buff *skb)
+{
+	dma_addr_t buf[2];
+	unsigned int vlan_len;
+
+	if (skb->len < GELIC_NET_VLAN_POS)
+		return -EINVAL;
+
+	memcpy(&descr->vlan, skb->data, GELIC_NET_VLAN_POS);
+	if (card->vlan_index != -1) {
+		descr->vlan.h_vlan_proto = htons(ETH_P_8021Q); /* vlan 0x8100*/
+		descr->vlan.h_vlan_TCI = htons(card->vlan_id[card->vlan_index]);
+		vlan_len = GELIC_NET_VLAN_POS + VLAN_HLEN; /* VLAN_HLEN=4 */
+	} else
+		vlan_len = GELIC_NET_VLAN_POS; /* no vlan tag */
+
+	/* first descr */
+	buf[0] = dma_map_single(ctodev(card), &descr->vlan,
+			     vlan_len, DMA_TO_DEVICE);
+
+	if (!buf[0]) {
+		dev_err(ctodev(card),
+			"dma map 1 failed (%p, %i). Dropping packet\n",
+			skb->data, vlan_len);
+		return -ENOMEM;
+	}
+
+	descr->buf_addr = buf[0];
+	descr->buf_size = vlan_len;
+	descr->skb = skb; /* not used */
+	descr->data_status = 0;
+	gelic_net_set_txdescr_cmdstat(descr, skb, 1); /* not the frame end */
+
+	/* second descr */
+	card->tx_chain.head = card->tx_chain.head->next;
+	descr->next_descr_addr = descr->next->bus_addr;
+	descr = descr->next;
+	if (gelic_net_get_descr_status(descr) != GELIC_NET_DESCR_NOT_IN_USE)
+		/* XXX will be removed */
+		dev_err(ctodev(card), "descr is not free!\n");
+
+	buf[1] = dma_map_single(ctodev(card), skb->data + GELIC_NET_VLAN_POS,
+			     skb->len - GELIC_NET_VLAN_POS,
+			     DMA_TO_DEVICE);
+
+	if (!buf[1]) {
+		dev_err(ctodev(card),
+			"dma map 2 failed (%p, %i). Dropping packet\n",
+			skb->data + GELIC_NET_VLAN_POS,
+			skb->len - GELIC_NET_VLAN_POS);
+		dma_unmap_single(ctodev(card), buf[0], vlan_len,
+				 DMA_TO_DEVICE);
+		return -ENOMEM;
+	}
+
+	descr->buf_addr = buf[1];
+	descr->buf_size = skb->len - GELIC_NET_VLAN_POS;
+	descr->skb = skb;
+	descr->data_status = 0;
+	descr->next_descr_addr = 0; /* terminate hw descr */
+	gelic_net_set_txdescr_cmdstat(descr, skb, 0);
+
+	return 0;
+}
+
+/**
+ * gelic_net_kick_txdma - enables TX DMA processing
+ * @card: card structure
+ * @descr: descriptor address to enable TX processing at
+ *
+ */
+static int gelic_net_kick_txdma(struct gelic_net_card *card,
+				struct gelic_net_descr *descr)
+{
+	int status = -ENXIO;
+	int count = 10;
+
+	if (card->tx_dma_progress)
+		return 0;
+
+	if (gelic_net_get_descr_status(descr) == GELIC_NET_DESCR_CARDOWNED) {
+		card->tx_dma_progress = 1;
+		/* sometimes we need retry here */
+		while (count--) {
+			status = lv1_net_start_tx_dma(bus_id(card),
+						      dev_id(card),
+						      descr->bus_addr, 0);
+			if (!status)
+				break;
+		}
+		if (!count)
+			dev_info(ctodev(card), "lv1_net_start_txdma failed," \
+				"status=%d %#lx\n",
+				 status, card->irq_status);
+	}
+	return status;
+}
+
+/**
+ * gelic_net_xmit - transmits a frame over the device
+ * @skb: packet to send out
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+	struct gelic_net_descr *descr = NULL;
+	int result;
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->tx_dma_lock, flags);
+
+	gelic_net_release_tx_chain(card, 0);
+	if (!skb)
+		goto kick;
+	descr = gelic_net_get_next_tx_descr(card);
+	if (!descr) {
+		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+		return NETDEV_TX_BUSY;
+	}
+	result = gelic_net_prepare_tx_descr_v(card, descr, skb);
+
+	if (result)
+		goto error;
+
+	card->tx_chain.head = card->tx_chain.head->next;
+
+	if (descr->prev)
+		descr->prev->next_descr_addr = descr->bus_addr;
+kick:
+	/*
+	 * as hardware descriptor is modified in the above lines,
+	 * ensure that the hardware sees it
+	 */
+	wmb();
+	if (gelic_net_kick_txdma(card, card->tx_chain.tail))
+		goto error;
+
+	netdev->trans_start = jiffies;
+	spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+	return NETDEV_TX_OK;
+
+error:
+	card->netdev_stats.tx_dropped++;
+	spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+	return NETDEV_TX_LOCKED;
+}
+
+/**
+ * gelic_net_pass_skb_up - takes an skb from a descriptor and passes it on
+ * @descr: descriptor to process
+ * @card: card structure
+ *
+ * iommu-unmaps the skb, fills out skb structure and passes the data to the
+ * stack. The descriptor state is not changed.
+ */
+static void gelic_net_pass_skb_up(struct gelic_net_descr *descr,
+				 struct gelic_net_card *card)
+{
+	struct sk_buff *skb;
+	struct net_device *netdev;
+	u32 data_status, data_error;
+
+	data_status = descr->data_status;
+	data_error = descr->data_error;
+	netdev = card->netdev;
+	/* unmap skb buffer */
+	skb = descr->skb;
+	dma_unmap_single(ctodev(card), descr->buf_addr, GELIC_NET_MAX_MTU,
+			 DMA_FROM_DEVICE);
+
+	skb_put(skb, descr->valid_size? descr->valid_size : descr->result_size);
+	if (!descr->valid_size)
+		dev_info(ctodev(card), "buffer full %x %x %x\n",
+			 descr->result_size, descr->buf_size,
+			 descr->dmac_cmd_status);
+
+	descr->skb = NULL;
+	/*
+	 * the card put 2 bytes vlan tag in front
+	 * of the ethernet frame
+	 */
+	skb_pull(skb, 2);
+	skb->protocol = eth_type_trans(skb, netdev);
+
+	/* checksum offload */
+	if (card->rx_csum) {
+		if ((data_status & GELIC_NET_DATA_STATUS_CHK_MASK) &&
+		    (!(data_error & GELIC_NET_DATA_ERROR_CHK_MASK)))
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+		else
+			skb->ip_summed = CHECKSUM_NONE;
+	} else
+		skb->ip_summed = CHECKSUM_NONE;
+
+	/* update netdevice statistics */
+	card->netdev_stats.rx_packets++;
+	card->netdev_stats.rx_bytes += skb->len;
+
+	/* pass skb up to stack */
+	netif_receive_skb(skb);
+}
+
+/**
+ * gelic_net_decode_one_descr - processes an rx descriptor
+ * @card: card structure
+ *
+ * returns 1 if a packet has been sent to the stack, otherwise 0
+ *
+ * processes an rx descriptor by iommu-unmapping the data buffer and passing
+ * the packet up to the stack
+ */
+static int gelic_net_decode_one_descr(struct gelic_net_card *card)
+{
+	enum gelic_net_descr_status status;
+	struct gelic_net_descr_chain *chain = &card->rx_chain;
+	struct gelic_net_descr *descr = chain->tail;
+	int dmac_chain_ended;
+
+	status = gelic_net_get_descr_status(descr);
+	/* is this descriptor terminated with next_descr == NULL? */
+	dmac_chain_ended =
+		descr->dmac_cmd_status & GELIC_NET_DMAC_CMDSTAT_RXDCEIS;
+
+	if (status == GELIC_NET_DESCR_CARDOWNED)
+		return 0;
+
+	if (status == GELIC_NET_DESCR_NOT_IN_USE) {
+		dev_dbg(ctodev(card), "dormant descr? %p\n", descr);
+		return 0;
+	}
+
+	if ((status == GELIC_NET_DESCR_RESPONSE_ERROR) ||
+	    (status == GELIC_NET_DESCR_PROTECTION_ERROR) ||
+	    (status == GELIC_NET_DESCR_FORCE_END)) {
+		dev_info(ctodev(card), "dropping RX descriptor with state %x\n",
+			 status);
+		card->netdev_stats.rx_dropped++;
+		goto refill;
+	}
+
+	if ((status != GELIC_NET_DESCR_COMPLETE) &&
+	    (status != GELIC_NET_DESCR_FRAME_END)) {
+		dev_dbg(ctodev(card), "RX descriptor with state %x\n",
+			status);
+		goto refill;
+	}
+
+	/* ok, we've got a packet in descr */
+	gelic_net_pass_skb_up(descr, card); /* 1: skb_up sccess */
+
+refill:
+	descr->next_descr_addr = 0; /* unlink the descr */
+
+	/* change the descriptor state: */
+	gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+
+	/* refill one desc
+	 * FIXME: this can fail, but for now, just leave this
+	 * descriptor without skb
+	 */
+	gelic_net_prepare_rx_descr(card, descr);
+	chain->head = descr;
+	chain->tail = descr->next;
+	descr->prev->next_descr_addr = descr->bus_addr;
+
+	if (dmac_chain_ended) {
+		gelic_net_enable_rxdmac(card);
+		dev_dbg(ctodev(card), "reenable rx dma\n");
+	}
+
+	return 1;
+}
+
+/**
+ * gelic_net_poll - NAPI poll function called by the stack to return packets
+ * @netdev: interface device structure
+ * @budget: number of packets we can pass to the stack at most
+ *
+ * returns 0 if no more packets available to the driver/stack. Returns 1,
+ * if the quota is exceeded, but the driver has still packets.
+ *
+ */
+static int gelic_net_poll(struct net_device *netdev, int *budget)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+	int packets_to_do, packets_done = 0;
+	int no_more_packets = 0;
+
+	packets_to_do = min(*budget, netdev->quota);
+
+	while (packets_to_do) {
+		if (gelic_net_decode_one_descr(card)) {
+			packets_done++;
+			packets_to_do--;
+		} else {
+			/* no more packets for the stack */
+			no_more_packets = 1;
+			break;
+		}
+	}
+	netdev->quota -= packets_done;
+	*budget -= packets_done;
+	if (no_more_packets) {
+		netif_rx_complete(netdev);
+		gelic_net_rx_irq_on(card);
+		return 0;
+	} else
+		return 1;
+}
+
+/**
+ * gelic_net_get_stats - get interface statistics
+ * @netdev: interface device structure
+ *
+ * returns the interface statistics residing in the gelic_net_card struct
+ */
+static struct net_device_stats *gelic_net_get_stats(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	return &card->netdev_stats;
+}
+
+/**
+ * gelic_net_change_mtu - changes the MTU of an interface
+ * @netdev: interface device structure
+ * @new_mtu: new MTU value
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	/* no need to re-alloc skbs or so -- the max mtu is about 2.3k
+	 * and mtu is outbound only anyway */
+	if ((new_mtu < GELIC_NET_MIN_MTU) ||
+	    (new_mtu > GELIC_NET_MAX_MTU)) {
+		return -EINVAL;
+	}
+	netdev->mtu = new_mtu;
+	return 0;
+}
+
+/**
+ * gelic_net_interrupt - event handler for gelic_net
+ */
+static irqreturn_t gelic_net_interrupt(int irq, void *ptr)
+{
+	unsigned long flags;
+	struct net_device *netdev = ptr;
+	struct gelic_net_card *card = netdev_priv(netdev);
+	u64 status;
+
+	status = card->irq_status;
+
+	if (!status)
+		return IRQ_NONE;
+
+	if (status & GELIC_NET_RXINT) {
+		gelic_net_rx_irq_off(card);
+		netif_rx_schedule(netdev);
+	}
+
+	if (status & GELIC_NET_TXINT) {
+		spin_lock_irqsave(&card->tx_dma_lock, flags);
+		card->tx_dma_progress = 0;
+		spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+		/* start pending DMA */
+		gelic_net_xmit(NULL, netdev);
+	}
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * gelic_net_poll_controller - artificial interrupt for netconsole etc.
+ * @netdev: interface device structure
+ *
+ * see Documentation/networking/netconsole.txt
+ */
+static void gelic_net_poll_controller(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	gelic_net_set_irq_mask(card, 0);
+	gelic_net_interrupt(netdev->irq, netdev);
+	gelic_net_set_irq_mask(card, card->ghiintmask);
+}
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+
+/**
+ * gelic_net_open_device - open device and map dma region
+ * @card: card structure
+ */
+static int gelic_net_open_device(struct gelic_net_card *card)
+{
+	int result;
+
+	result = ps3_sb_event_receive_port_setup(card->dev, PS3_BINDING_CPU_ANY,
+		&card->netdev->irq);
+
+	if (result) {
+		dev_info(ctodev(card),
+			 "%s:%d: gelic_net_open_device failed (%d)\n",
+			 __func__, __LINE__, result);
+		result = -EPERM;
+		goto fail_alloc_irq;
+	}
+
+	result = request_irq(card->netdev->irq, gelic_net_interrupt,
+			     IRQF_DISABLED, "gelic network", card->netdev);
+
+	if (result) {
+		dev_info(ctodev(card), "%s:%d: request_irq failed (%d)\n",
+			__func__, __LINE__, result);
+		goto fail_request_irq;
+	}
+
+	return 0;
+
+fail_request_irq:
+	ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq);
+	card->netdev->irq = NO_IRQ;
+fail_alloc_irq:
+	return result;
+}
+
+
+/**
+ * gelic_net_open - called upon ifonfig up
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * gelic_net_open allocates all the descriptors and memory needed for
+ * operation, sets up multicast list and enables interrupts
+ */
+static int gelic_net_open(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	dev_dbg(ctodev(card), " -> %s:%d\n", __func__, __LINE__);
+
+	gelic_net_open_device(card);
+
+	if (gelic_net_init_chain(card, &card->tx_chain,
+			card->descr, GELIC_NET_TX_DESCRIPTORS))
+		goto alloc_tx_failed;
+	if (gelic_net_init_chain(card, &card->rx_chain,
+				 card->descr + GELIC_NET_RX_DESCRIPTORS,
+				 GELIC_NET_RX_DESCRIPTORS))
+		goto alloc_rx_failed;
+
+	/* head of chain */
+	card->tx_top = card->tx_chain.head;
+	card->rx_top = card->rx_chain.head;
+	dev_dbg(ctodev(card), "descr rx %p, tx %p, size %#lx, num %#x\n",
+		card->rx_top, card->tx_top, sizeof(struct gelic_net_descr),
+		GELIC_NET_RX_DESCRIPTORS);
+	/* allocate rx skbs */
+	if (gelic_net_alloc_rx_skbs(card))
+		goto alloc_skbs_failed;
+
+	card->tx_dma_progress = 0;
+	card->ghiintmask = GELIC_NET_RXINT | GELIC_NET_TXINT;
+
+	gelic_net_set_irq_mask(card, card->ghiintmask);
+	gelic_net_enable_rxdmac(card);
+
+	netif_start_queue(netdev);
+	netif_carrier_on(netdev);
+	netif_poll_enable(netdev);
+
+	return 0;
+
+alloc_skbs_failed:
+	gelic_net_free_chain(card, card->rx_top);
+alloc_rx_failed:
+	gelic_net_free_chain(card, card->tx_top);
+alloc_tx_failed:
+	return -ENOMEM;
+}
+
+#ifdef GELIC_NET_ETHTOOL
+static void gelic_net_get_drvinfo (struct net_device *netdev,
+				   struct ethtool_drvinfo *info)
+{
+	strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1);
+	strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1);
+}
+
+static int gelic_net_get_settings(struct net_device *netdev,
+				  struct ethtool_cmd *cmd)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+	int status;
+	u64 v1, v2;
+	int speed, duplex;
+
+	speed = duplex = -1;
+	status = lv1_net_control(bus_id(card), dev_id(card),
+			GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0,
+			&v1, &v2);
+	if (status) {
+		/* link down */
+	} else {
+		if (v1 & GELIC_NET_FULL_DUPLEX) {
+			duplex = DUPLEX_FULL;
+		} else {
+			duplex = DUPLEX_HALF;
+		}
+
+		if (v1 & GELIC_NET_SPEED_10 ) {
+			speed = SPEED_10;
+		} else if (v1 & GELIC_NET_SPEED_100) {
+			speed = SPEED_100;
+		} else if (v1 & GELIC_NET_SPEED_1000) {
+			speed = SPEED_1000;
+		}
+	}
+	cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg |
+			SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+			SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+			SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
+	cmd->advertising = cmd->supported;
+	cmd->speed = speed;
+	cmd->duplex = duplex;
+	cmd->autoneg = AUTONEG_ENABLE; /* always enabled */
+	cmd->port = PORT_TP;
+
+	return 0;
+}
+
+static u32 gelic_net_get_link(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+	int status;
+	u64 v1, v2;
+	int link;
+
+	status = lv1_net_control(bus_id(card), dev_id(card),
+			GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0,
+			&v1, &v2);
+	if (status)
+		return 0; /* link down */
+
+	if (v1 & GELIC_NET_LINK_UP)
+		link = 1;
+	else
+		link = 0;
+
+	return link;
+}
+
+static int gelic_net_nway_reset(struct net_device *netdev)
+{
+	if (netif_running(netdev)) {
+		gelic_net_stop(netdev);
+		gelic_net_open(netdev);
+	}
+	return 0;
+}
+
+static u32 gelic_net_get_tx_csum(struct net_device *netdev)
+{
+	return (netdev->features & NETIF_F_IP_CSUM) != 0;
+}
+
+static int gelic_net_set_tx_csum(struct net_device *netdev, u32 data)
+{
+	if (data)
+		netdev->features |= NETIF_F_IP_CSUM;
+	else
+		netdev->features &= ~NETIF_F_IP_CSUM;
+
+	return 0;
+}
+
+static u32 gelic_net_get_rx_csum(struct net_device *netdev)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	return card->rx_csum;
+}
+
+static int gelic_net_set_rx_csum(struct net_device *netdev, u32 data)
+{
+	struct gelic_net_card *card = netdev_priv(netdev);
+
+	card->rx_csum = data;
+	return 0;
+}
+
+static struct ethtool_ops gelic_net_ethtool_ops = {
+	.get_drvinfo	= gelic_net_get_drvinfo,
+	.get_settings	= gelic_net_get_settings,
+	.get_link	= gelic_net_get_link,
+	.nway_reset	= gelic_net_nway_reset,
+	.get_tx_csum	= gelic_net_get_tx_csum,
+	.set_tx_csum	= gelic_net_set_tx_csum,
+	.get_rx_csum	= gelic_net_get_rx_csum,
+	.set_rx_csum	= gelic_net_set_rx_csum,
+};
+#endif
+
+/**
+ * gelic_net_tx_timeout_task - task scheduled by the watchdog timeout
+ * function (to be called not under interrupt status)
+ * @work: work is context of tx timout task
+ *
+ * called as task when tx hangs, resets interface (if interface is up)
+ */
+static void gelic_net_tx_timeout_task(struct work_struct *work)
+{
+	struct gelic_net_card *card =
+		container_of(work, struct gelic_net_card, tx_timeout_task);
+	struct net_device *netdev = card->netdev;
+
+	dev_info(ctodev(card), "%s:Timed out. Restarting... \n", __func__);
+
+	if (!(netdev->flags & IFF_UP))
+		goto out;
+
+	netif_device_detach(netdev);
+	gelic_net_stop(netdev);
+
+	gelic_net_open(netdev);
+	netif_device_attach(netdev);
+
+out:
+	atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * gelic_net_tx_timeout - called when the tx timeout watchdog kicks in.
+ * @netdev: interface device structure
+ *
+ * called, if tx hangs. Schedules a task that resets the interface
+ */
+static void gelic_net_tx_timeout(struct net_device *netdev)
+{
+	struct gelic_net_card *card;
+
+	card = netdev_priv(netdev);
+	atomic_inc(&card->tx_timeout_task_counter);
+	if (netdev->flags & IFF_UP)
+		schedule_work(&card->tx_timeout_task);
+	else
+		atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * gelic_net_setup_netdev_ops - initialization of net_device operations
+ * @netdev: net_device structure
+ *
+ * fills out function pointers in the net_device structure
+ */
+static void gelic_net_setup_netdev_ops(struct net_device *netdev)
+{
+	netdev->open = &gelic_net_open;
+	netdev->stop = &gelic_net_stop;
+	netdev->hard_start_xmit = &gelic_net_xmit;
+	netdev->get_stats = &gelic_net_get_stats;
+	netdev->set_multicast_list = &gelic_net_set_multi;
+	netdev->change_mtu = &gelic_net_change_mtu;
+	/* tx watchdog */
+	netdev->tx_timeout = &gelic_net_tx_timeout;
+	netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
+	/* NAPI */
+	netdev->poll = &gelic_net_poll;
+	netdev->weight = GELIC_NET_NAPI_WEIGHT;
+#ifdef GELIC_NET_ETHTOOL
+	netdev->ethtool_ops = &gelic_net_ethtool_ops;
+#endif
+}
+
+/**
+ * gelic_net_setup_netdev - initialization of net_device
+ * @card: card structure
+ *
+ * Returns 0 on success or <0 on failure
+ *
+ * gelic_net_setup_netdev initializes the net_device structure
+ **/
+static int gelic_net_setup_netdev(struct gelic_net_card *card)
+{
+	struct net_device *netdev = card->netdev;
+	struct sockaddr addr;
+	unsigned int i;
+	int status;
+	u64 v1, v2;
+
+	SET_MODULE_OWNER(netdev);
+	SET_NETDEV_DEV(netdev, &card->dev->core);
+	spin_lock_init(&card->tx_dma_lock);
+
+	card->rx_csum = GELIC_NET_RX_CSUM_DEFAULT;
+
+	gelic_net_setup_netdev_ops(netdev);
+
+	netdev->features = NETIF_F_IP_CSUM;
+
+	status = lv1_net_control(bus_id(card), dev_id(card),
+				 GELIC_NET_GET_MAC_ADDRESS,
+				 0, 0, 0, &v1, &v2);
+	if (status || !is_valid_ether_addr((u8 *)&v1)) {
+		dev_info(ctodev(card),
+			 "%s:lv1_net_control GET_MAC_ADDR failed %d\n",
+			 __func__, status);
+		return -EINVAL;
+	}
+	v1 <<= 16;
+	memcpy(addr.sa_data, &v1, ETH_ALEN);
+	memcpy(netdev->dev_addr, addr.sa_data, ETH_ALEN);
+	dev_info(ctodev(card), "MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+		 netdev->dev_addr[0], netdev->dev_addr[1],
+		 netdev->dev_addr[2], netdev->dev_addr[3],
+		 netdev->dev_addr[4], netdev->dev_addr[5]);
+
+	card->vlan_index = -1;	/* no vlan */
+	for (i = 0; i < GELIC_NET_VLAN_MAX; i++) {
+		status = lv1_net_control(bus_id(card), dev_id(card),
+					GELIC_NET_GET_VLAN_ID,
+					i + 1, /* index; one based */
+					0, 0, &v1, &v2);
+		if (status == GELIC_NET_VLAN_NO_ENTRY) {
+			dev_dbg(ctodev(card),
+				"GELIC_VLAN_ID no entry:%d, VLAN disabled\n",
+				status);
+			card->vlan_id[i] = 0;
+		} else if (status) {
+			dev_dbg(ctodev(card),
+				"%s:GELIC_NET_VLAN_ID faild, status=%d\n",
+				__func__, status);
+			card->vlan_id[i] = 0;
+		} else {
+			card->vlan_id[i] = (u32)v1;
+			dev_dbg(ctodev(card), "vlan_id:%d, %lx\n", i, v1);
+		}
+	}
+	if (card->vlan_id[GELIC_NET_VLAN_WIRED - 1])
+		card->vlan_index = GELIC_NET_VLAN_WIRED - 1;
+
+	status = register_netdev(netdev);
+	if (status) {
+		dev_err(ctodev(card), "%s:Couldn't register net_device: %d\n",
+			__func__, status);
+		return status;
+	}
+
+	return 0;
+}
+
+/**
+ * gelic_net_alloc_card - allocates net_device and card structure
+ *
+ * returns the card structure or NULL in case of errors
+ *
+ * the card and net_device structures are linked to each other
+ */
+static struct gelic_net_card *gelic_net_alloc_card(void)
+{
+	struct net_device *netdev;
+	struct gelic_net_card *card;
+	size_t alloc_size;
+
+	alloc_size = sizeof (*card) +
+		sizeof (struct gelic_net_descr) * GELIC_NET_RX_DESCRIPTORS +
+		sizeof (struct gelic_net_descr) * GELIC_NET_TX_DESCRIPTORS;
+	/*
+	 * we assume private data is allocated 32 bytes (or more) aligned
+	 * so that gelic_net_descr should be 32 bytes aligned.
+	 * Current alloc_etherdev() does do it because NETDEV_ALIGN
+	 * is 32.
+	 * check this assumption here.
+	 */
+	BUILD_BUG_ON(NETDEV_ALIGN < 32);
+	BUILD_BUG_ON(offsetof(struct gelic_net_card, irq_status) % 8);
+	BUILD_BUG_ON(offsetof(struct gelic_net_card, descr) % 32);
+
+	netdev = alloc_etherdev(alloc_size);
+	if (!netdev)
+		return NULL;
+
+	card = netdev_priv(netdev);
+	card->netdev = netdev;
+	INIT_WORK(&card->tx_timeout_task, gelic_net_tx_timeout_task);
+	init_waitqueue_head(&card->waitq);
+	atomic_set(&card->tx_timeout_task_counter, 0);
+
+	return card;
+}
+
+/**
+ * ps3_gelic_driver_probe - add a device to the control of this driver
+ */
+static int ps3_gelic_driver_probe (struct ps3_system_bus_device *dev)
+{
+	struct gelic_net_card *card = gelic_net_alloc_card();
+	int result;
+
+	if (!card) {
+		dev_info(&dev->core, "gelic_net_alloc_card failed\n");
+		result = -ENOMEM;
+		goto fail_alloc_card;
+	}
+
+	ps3_system_bus_set_driver_data(dev, card);
+	card->dev = dev;
+
+	result = ps3_open_hv_device(dev);
+
+	if (result) {
+		dev_dbg(&dev->core, "ps3_open_hv_device failed\n");
+		goto fail_open;
+	}
+
+	result = ps3_dma_region_create(dev->d_region);
+
+	if (result) {
+		dev_dbg(&dev->core, "ps3_dma_region_create failed(%d)\n",
+			result);
+		BUG_ON("check region type");
+		goto fail_dma_region;
+	}
+
+	result = lv1_net_set_interrupt_status_indicator(bus_id(card),
+							dev_id(card),
+		ps3_mm_phys_to_lpar(__pa(&card->irq_status)),
+		0);
+
+	if (result) {
+		dev_dbg(&dev->core,
+			"lv1_net_set_interrupt_status_indicator failed: %s\n",
+			ps3_result(result));
+		result = -EIO;
+		goto fail_status_indicator;
+	}
+
+	result = gelic_net_setup_netdev(card);
+
+	if (result) {
+		dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
+			"(%d)\n", __func__, __LINE__, result);
+		goto fail_setup_netdev;
+	}
+
+	return 0;
+
+fail_setup_netdev:
+	lv1_net_set_interrupt_status_indicator(bus_id(card),
+					       bus_id(card),
+					       0 , 0);
+fail_status_indicator:
+	ps3_dma_region_free(dev->d_region);
+fail_dma_region:
+	ps3_close_hv_device(dev);
+fail_open:
+	ps3_system_bus_set_driver_data(dev, NULL);
+	free_netdev(card->netdev);
+fail_alloc_card:
+	return result;
+}
+
+/**
+ * ps3_gelic_driver_remove - remove a device from the control of this driver
+ */
+
+static int ps3_gelic_driver_remove (struct ps3_system_bus_device *dev)
+{
+	struct gelic_net_card *card = ps3_system_bus_get_driver_data(dev);
+
+	wait_event(card->waitq,
+		   atomic_read(&card->tx_timeout_task_counter) == 0);
+
+	lv1_net_set_interrupt_status_indicator(bus_id(card), dev_id(card),
+					       0 , 0);
+
+	unregister_netdev(card->netdev);
+	free_netdev(card->netdev);
+
+	ps3_system_bus_set_driver_data(dev, NULL);
+
+	ps3_dma_region_free(dev->d_region);
+
+	ps3_close_hv_device(dev);
+
+	return 0;
+}
+
+static struct ps3_system_bus_driver ps3_gelic_driver = {
+	.match_id = PS3_MATCH_ID_GELIC,
+	.probe = ps3_gelic_driver_probe,
+	.remove = ps3_gelic_driver_remove,
+	.shutdown = ps3_gelic_driver_remove,
+	.core.name = "ps3_gelic_driver",
+	.core.owner = THIS_MODULE,
+};
+
+static int __init ps3_gelic_driver_init (void)
+{
+	return firmware_has_feature(FW_FEATURE_PS3_LV1)
+		? ps3_system_bus_driver_register(&ps3_gelic_driver)
+		: -ENODEV;
+}
+
+static void __exit ps3_gelic_driver_exit (void)
+{
+	ps3_system_bus_driver_unregister(&ps3_gelic_driver);
+}
+
+module_init (ps3_gelic_driver_init);
+module_exit (ps3_gelic_driver_exit);
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_GELIC);
+
diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h
new file mode 100644
index 0000000..5e1c286
--- /dev/null
+++ b/drivers/net/ps3_gelic_net.h
@@ -0,0 +1,239 @@
+/*
+ *  PS3 Platfom gelic network driver.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation.
+ *
+ * This file is based on: spider_net.h
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ *           Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _GELIC_NET_H
+#define _GELIC_NET_H
+
+#define GELIC_NET_DRV_NAME "Gelic Network Driver"
+#define GELIC_NET_DRV_VERSION "1.0"
+
+#define GELIC_NET_ETHTOOL               /* use ethtool */
+
+/* ioctl */
+#define GELIC_NET_GET_MODE              (SIOCDEVPRIVATE + 0)
+#define GELIC_NET_SET_MODE              (SIOCDEVPRIVATE + 1)
+
+/* descriptors */
+#define GELIC_NET_RX_DESCRIPTORS        128 /* num of descriptors */
+#define GELIC_NET_TX_DESCRIPTORS        128 /* num of descriptors */
+
+#define GELIC_NET_MAX_MTU               2308
+#define GELIC_NET_MIN_MTU               64
+#define GELIC_NET_RXBUF_ALIGN           128
+#define GELIC_NET_RX_CSUM_DEFAULT       1 /* hw chksum */
+#define GELIC_NET_WATCHDOG_TIMEOUT      5*HZ
+#define GELIC_NET_NAPI_WEIGHT           (GELIC_NET_RX_DESCRIPTORS)
+#define GELIC_NET_BROADCAST_ADDR        0xffffffffffffL
+#define GELIC_NET_VLAN_POS              (VLAN_ETH_ALEN * 2)
+#define GELIC_NET_VLAN_MAX              4
+#define GELIC_NET_MC_COUNT_MAX          32 /* multicast address list */
+
+enum gelic_net_int0_status {
+	GELIC_NET_GDTDCEINT  = 24,
+	GELIC_NET_GRFANMINT  = 28,
+};
+
+/* GHIINT1STS bits */
+enum gelic_net_int1_status {
+	GELIC_NET_GDADCEINT = 14,
+};
+
+/* interrupt mask */
+#define GELIC_NET_TXINT                   (1L << (GELIC_NET_GDTDCEINT + 32))
+
+#define GELIC_NET_RXINT0                  (1L << (GELIC_NET_GRFANMINT + 32))
+#define GELIC_NET_RXINT1                  (1L << GELIC_NET_GDADCEINT)
+#define GELIC_NET_RXINT                   (GELIC_NET_RXINT0 | GELIC_NET_RXINT1)
+
+ /* RX descriptor data_status bits */
+#define GELIC_NET_RXDMADU	0x80000000 /* destination MAC addr unknown */
+#define GELIC_NET_RXLSTFBF	0x40000000 /* last frame buffer            */
+#define GELIC_NET_RXIPCHK	0x20000000 /* IP checksum performed        */
+#define GELIC_NET_RXTCPCHK	0x10000000 /* TCP/UDP checksup performed   */
+#define GELIC_NET_RXIPSPKT	0x08000000 /* IPsec packet   */
+#define GELIC_NET_RXIPSAHPRT	0x04000000 /* IPsec AH protocol performed */
+#define GELIC_NET_RXIPSESPPRT	0x02000000 /* IPsec ESP protocol performed */
+#define GELIC_NET_RXSESPAH	0x01000000 /*
+					    * IPsec ESP protocol auth
+					    * performed
+					    */
+
+#define GELIC_NET_RXWTPKT	0x00C00000 /*
+					    * wakeup trigger packet
+					    * 01: Magic Packet (TM)
+					    * 10: ARP packet
+					    * 11: Multicast MAC addr
+					    */
+#define GELIC_NET_RXVLNPKT	0x00200000 /* VLAN packet */
+/* bit 20..16 reserved */
+#define GELIC_NET_RXRECNUM	0x0000ff00 /* reception receipt number */
+/* bit 7..0 reserved */
+
+#define GELIC_NET_TXDESC_TAIL		0
+#define GELIC_NET_DATA_STATUS_CHK_MASK	(GELIC_NET_RXIPCHK | GELIC_NET_RXTCPCHK)
+
+/* RX descriptor data_error bits */
+/* bit 31 reserved */
+#define GELIC_NET_RXALNERR	0x40000000 /* alignement error 10/100M */
+#define GELIC_NET_RXOVERERR	0x20000000 /* oversize error */
+#define GELIC_NET_RXRNTERR	0x10000000 /* Runt error */
+#define GELIC_NET_RXIPCHKERR	0x08000000 /* IP checksum  error */
+#define GELIC_NET_RXTCPCHKERR	0x04000000 /* TCP/UDP checksum  error */
+#define GELIC_NET_RXUMCHSP	0x02000000 /* unmatched sp on sp */
+#define GELIC_NET_RXUMCHSPI	0x01000000 /* unmatched SPI on SAD */
+#define GELIC_NET_RXUMCHSAD	0x00800000 /* unmatched SAD */
+#define GELIC_NET_RXIPSAHERR	0x00400000 /* auth error on AH protocol
+					    * processing */
+#define GELIC_NET_RXIPSESPAHERR	0x00200000 /* auth error on ESP protocol
+					    * processing */
+#define GELIC_NET_RXDRPPKT	0x00100000 /* drop packet */
+#define GELIC_NET_RXIPFMTERR	0x00080000 /* IP packet format error */
+/* bit 18 reserved */
+#define GELIC_NET_RXDATAERR	0x00020000 /* IP packet format error */
+#define GELIC_NET_RXCALERR	0x00010000 /* cariier extension length
+					    * error */
+#define GELIC_NET_RXCREXERR	0x00008000 /* carrier extention error */
+#define GELIC_NET_RXMLTCST	0x00004000 /* multicast address frame */
+/* bit 13..0 reserved */
+#define GELIC_NET_DATA_ERROR_CHK_MASK		\
+	(GELIC_NET_RXIPCHKERR | GELIC_NET_RXTCPCHKERR)
+
+
+/* tx descriptor command and status */
+#define GELIC_NET_DMAC_CMDSTAT_NOCS       0xa0080000 /* middle of frame */
+#define GELIC_NET_DMAC_CMDSTAT_TCPCS      0xa00a0000
+#define GELIC_NET_DMAC_CMDSTAT_UDPCS      0xa00b0000
+#define GELIC_NET_DMAC_CMDSTAT_END_FRAME  0x00040000 /* end of frame */
+
+#define GELIC_NET_DMAC_CMDSTAT_RXDCEIS	  0x00000002 /* descriptor chain end
+						      * interrupt status */
+
+#define GELIC_NET_DMAC_CMDSTAT_CHAIN_END  0x00000002 /* RXDCEIS:DMA stopped */
+#define GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE 0xb0000000
+#define GELIC_NET_DESCR_IND_PROC_SHIFT    28
+#define GELIC_NET_DESCR_IND_PROC_MASKO    0x0fffffff
+
+
+enum gelic_net_descr_status {
+	GELIC_NET_DESCR_COMPLETE            = 0x00, /* used in rx and tx */
+	GELIC_NET_DESCR_RESPONSE_ERROR      = 0x01, /* used in rx and tx */
+	GELIC_NET_DESCR_PROTECTION_ERROR    = 0x02, /* used in rx and tx */
+	GELIC_NET_DESCR_FRAME_END           = 0x04, /* used in rx */
+	GELIC_NET_DESCR_FORCE_END           = 0x05, /* used in rx and tx */
+	GELIC_NET_DESCR_CARDOWNED           = 0x0a, /* used in rx and tx */
+	GELIC_NET_DESCR_NOT_IN_USE                  /* any other value */
+};
+/* for lv1_net_control */
+#define GELIC_NET_GET_MAC_ADDRESS               0x0000000000000001
+#define GELIC_NET_GET_ETH_PORT_STATUS           0x0000000000000002
+#define GELIC_NET_SET_NEGOTIATION_MODE          0x0000000000000003
+#define GELIC_NET_GET_VLAN_ID                   0x0000000000000004
+
+#define GELIC_NET_LINK_UP                       0x0000000000000001
+#define GELIC_NET_FULL_DUPLEX                   0x0000000000000002
+#define GELIC_NET_AUTO_NEG                      0x0000000000000004
+#define GELIC_NET_SPEED_10                      0x0000000000000010
+#define GELIC_NET_SPEED_100                     0x0000000000000020
+#define GELIC_NET_SPEED_1000                    0x0000000000000040
+
+#define GELIC_NET_VLAN_ALL                      0x0000000000000001
+#define GELIC_NET_VLAN_WIRED                    0x0000000000000002
+#define GELIC_NET_VLAN_WIRELESS                 0x0000000000000003
+#define GELIC_NET_VLAN_PSP                      0x0000000000000004
+#define GELIC_NET_VLAN_PORT0                    0x0000000000000010
+#define GELIC_NET_VLAN_PORT1                    0x0000000000000011
+#define GELIC_NET_VLAN_PORT2                    0x0000000000000012
+#define GELIC_NET_VLAN_DAEMON_CLIENT_BSS        0x0000000000000013
+#define GELIC_NET_VLAN_LIBERO_CLIENT_BSS        0x0000000000000014
+#define GELIC_NET_VLAN_NO_ENTRY                 -6
+
+#define GELIC_NET_PORT                          2 /* for port status */
+
+/* size of hardware part of gelic descriptor */
+#define GELIC_NET_DESCR_SIZE	(32)
+struct gelic_net_descr {
+	/* as defined by the hardware */
+	u32 buf_addr;
+	u32 buf_size;
+	u32 next_descr_addr;
+	u32 dmac_cmd_status;
+	u32 result_size;
+	u32 valid_size;	/* all zeroes for tx */
+	u32 data_status;
+	u32 data_error;	/* all zeroes for tx */
+
+	/* used in the driver */
+	struct sk_buff *skb;
+	dma_addr_t bus_addr;
+	struct gelic_net_descr *next;
+	struct gelic_net_descr *prev;
+	struct vlan_ethhdr vlan;
+} __attribute__((aligned(32)));
+
+struct gelic_net_descr_chain {
+	/* we walk from tail to head */
+	struct gelic_net_descr *head;
+	struct gelic_net_descr *tail;
+};
+
+struct gelic_net_card {
+	struct net_device *netdev;
+	/*
+	 * hypervisor requires irq_status should be
+	 * 8 bytes aligned, but u64 member is
+	 * always disposed in that manner
+	 */
+	u64 irq_status;
+	u64 ghiintmask;
+
+	struct ps3_system_bus_device *dev;
+	u32 vlan_id[GELIC_NET_VLAN_MAX];
+	int vlan_index;
+
+	struct gelic_net_descr_chain tx_chain;
+	struct gelic_net_descr_chain rx_chain;
+	/* gurad dmac descriptor chain*/
+	spinlock_t chain_lock;
+
+	struct net_device_stats netdev_stats;
+	int rx_csum;
+	/* guard tx_dma_progress */
+	spinlock_t tx_dma_lock;
+	int tx_dma_progress;
+
+	struct work_struct tx_timeout_task;
+	atomic_t tx_timeout_task_counter;
+	wait_queue_head_t waitq;
+
+	struct gelic_net_descr *tx_top, *rx_top;
+	struct gelic_net_descr descr[0];
+};
+
+
+extern unsigned long p_to_lp(long pa);
+
+#endif /* _GELIC_NET_H */
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 585be04..8be8be4 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2433,37 +2433,22 @@
 	return -1;
 }
 
-static void ql_hw_csum_setup(struct sk_buff *skb,
+static void ql_hw_csum_setup(const struct sk_buff *skb,
 			     struct ob_mac_iocb_req *mac_iocb_ptr)
 {
-	struct ethhdr *eth;
-	struct iphdr *ip = NULL;
-	u8 offset = ETH_HLEN;
+	const struct iphdr *ip = ip_hdr(skb);
 
-	eth = (struct ethhdr *)(skb->data);
+	mac_iocb_ptr->ip_hdr_off = skb_network_offset(skb);
+	mac_iocb_ptr->ip_hdr_len = ip->ihl;
 
-	if (eth->h_proto == __constant_htons(ETH_P_IP)) {
-		ip = (struct iphdr *)&skb->data[ETH_HLEN];
-	} else if (eth->h_proto == htons(ETH_P_8021Q) &&
-		   ((struct vlan_ethhdr *)skb->data)->
-		   h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP)) {
-		ip = (struct iphdr *)&skb->data[VLAN_ETH_HLEN];
-		offset = VLAN_ETH_HLEN;
+	if (ip->protocol == IPPROTO_TCP) {
+		mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
+			OB_3032MAC_IOCB_REQ_IC;
+	} else {
+		mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
+			OB_3032MAC_IOCB_REQ_IC;
 	}
 
-	if (ip) {
-		if (ip->protocol == IPPROTO_TCP) {
-			mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC | 
-			OB_3032MAC_IOCB_REQ_IC;
-			mac_iocb_ptr->ip_hdr_off = offset;
-			mac_iocb_ptr->ip_hdr_len = ip->ihl;
-		} else if (ip->protocol == IPPROTO_UDP) {
-			mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC | 
-			OB_3032MAC_IOCB_REQ_IC;
-			mac_iocb_ptr->ip_hdr_off = offset;
-			mac_iocb_ptr->ip_hdr_len = ip->ihl;
-		}
-	}
 }
 
 /*
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 5ec7752c..982a901 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1,53 +1,11 @@
 /*
-=========================================================================
- r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver for Linux kernel 2.4.x.
- --------------------------------------------------------------------
-
- History:
- Feb  4 2002	- created initially by ShuChen <shuchen@realtek.com.tw>.
- May 20 2002	- Add link status force-mode and TBI mode support.
-	2004	- Massive updates. See kernel SCM system for details.
-=========================================================================
-  1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.
-	 Command: 'insmod r8169 media = SET_MEDIA'
-	 Ex:	  'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex.
-
-	 SET_MEDIA can be:
- 		_10_Half	= 0x01
- 		_10_Full	= 0x02
- 		_100_Half	= 0x04
- 		_100_Full	= 0x08
- 		_1000_Full	= 0x10
-
-  2. Support TBI mode.
-=========================================================================
-VERSION 1.1	<2002/10/4>
-
-	The bit4:0 of MII register 4 is called "selector field", and have to be
-	00001b to indicate support of IEEE std 802.3 during NWay process of
-	exchanging Link Code Word (FLP).
-
-VERSION 1.2	<2002/11/30>
-
-	- Large style cleanup
-	- Use ether_crc in stock kernel (linux/crc32.h)
-	- Copy mc_filter setup code from 8139cp
-	  (includes an optimization, and avoids set_bit use)
-
-VERSION 1.6LK	<2004/04/14>
-
-	- Merge of Realtek's version 1.6
-	- Conversion to DMA API
-	- Suspend/resume
-	- Endianness
-	- Misc Rx/Tx bugs
-
-VERSION 2.2LK	<2005/01/25>
-
-	- RX csum, TX csum/SG, TSO
-	- VLAN
-	- baby (< 7200) Jumbo frames support
-	- Merge of Realtek's version 2.2 (new phy)
+ * r8169.c: RealTek 8169/8168/8101 ethernet driver.
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ * See MAINTAINERS file for support contact information.
  */
 
 #include <linux/module.h>
@@ -108,11 +66,6 @@
 #define rtl8169_rx_quota(count, quota)	count
 #endif
 
-/* media options */
-#define MAX_UNITS 8
-static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-static int num_media = 0;
-
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static const int max_interrupt_work = 20;
 
@@ -126,7 +79,7 @@
 #define RX_FIFO_THRESH	7	/* 7 means NO threshold, Rx buffer level before first PCI xfer. */
 #define RX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
 #define TX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
-#define EarlyTxThld 	0x3F	/* 0x3F means NO early transmit */
+#define EarlyTxThld	0x3F	/* 0x3F means NO early transmit */
 #define RxPacketMaxSize	0x3FE8	/* 16K - 1 - ETH_HLEN - VLAN - CRC... */
 #define SafeMtu		0x1c20	/* ... actually life sucks beyond ~7k */
 #define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
@@ -151,16 +104,17 @@
 #define RTL_R32(reg)		((unsigned long) readl (ioaddr + (reg)))
 
 enum mac_version {
-	RTL_GIGA_MAC_VER_01 = 0x00,
-	RTL_GIGA_MAC_VER_02 = 0x01,
-	RTL_GIGA_MAC_VER_03 = 0x02,
-	RTL_GIGA_MAC_VER_04 = 0x03,
-	RTL_GIGA_MAC_VER_05 = 0x04,
-	RTL_GIGA_MAC_VER_11 = 0x0b,
-	RTL_GIGA_MAC_VER_12 = 0x0c,
-	RTL_GIGA_MAC_VER_13 = 0x0d,
-	RTL_GIGA_MAC_VER_14 = 0x0e,
-	RTL_GIGA_MAC_VER_15 = 0x0f
+	RTL_GIGA_MAC_VER_01 = 0x01, // 8169
+	RTL_GIGA_MAC_VER_02 = 0x02, // 8169S
+	RTL_GIGA_MAC_VER_03 = 0x03, // 8110S
+	RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB
+	RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd
+	RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe
+	RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb
+	RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be 8168Bf
+	RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb 8101Ec
+	RTL_GIGA_MAC_VER_14 = 0x0e, // 8101
+	RTL_GIGA_MAC_VER_15 = 0x0f  // 8101
 };
 
 enum phy_version {
@@ -180,11 +134,12 @@
 	u8 mac_version;
 	u32 RxConfigMask;	/* Clears the bits supported by this chip */
 } rtl_chip_info[] = {
-	_R("RTL8169",		RTL_GIGA_MAC_VER_01, 0xff7e1880),
-	_R("RTL8169s/8110s",	RTL_GIGA_MAC_VER_02, 0xff7e1880),
-	_R("RTL8169s/8110s",	RTL_GIGA_MAC_VER_03, 0xff7e1880),
-	_R("RTL8169sb/8110sb",	RTL_GIGA_MAC_VER_04, 0xff7e1880),
-	_R("RTL8169sc/8110sc",	RTL_GIGA_MAC_VER_05, 0xff7e1880),
+	_R("RTL8169",		RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169
+	_R("RTL8169s",		RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S
+	_R("RTL8110s",		RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S
+	_R("RTL8169sb/8110sb",	RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB
+	_R("RTL8169sc/8110sc",	RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd
+	_R("RTL8169sc/8110sc",	RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe
 	_R("RTL8168b/8111b",	RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E
 	_R("RTL8168b/8111b",	RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
 	_R("RTL8101e",		RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
@@ -199,20 +154,15 @@
 	RTL_CFG_2
 };
 
-static const struct {
-	unsigned int region;
-	unsigned int align;
-} rtl_cfg_info[] = {
-	[RTL_CFG_0] = { 1, NET_IP_ALIGN },
-	[RTL_CFG_1] = { 2, NET_IP_ALIGN },
-	[RTL_CFG_2] = { 2, 8 }
-};
+static void rtl_hw_start_8169(struct net_device *);
+static void rtl_hw_start_8168(struct net_device *);
+static void rtl_hw_start_8101(struct net_device *);
 
 static struct pci_device_id rtl8169_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8129), 0, 0, RTL_CFG_0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8136), 0, 0, RTL_CFG_2 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8167), 0, 0, RTL_CFG_0 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8168), 0, 0, RTL_CFG_2 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8168), 0, 0, RTL_CFG_1 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8169), 0, 0, RTL_CFG_0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK,	0x4300), 0, 0, RTL_CFG_0 },
 	{ PCI_DEVICE(0x1259,			0xc107), 0, 0, RTL_CFG_0 },
@@ -230,62 +180,63 @@
 	u32 msg_enable;
 } debug = { -1 };
 
-enum RTL8169_registers {
-	MAC0 = 0,		/* Ethernet hardware address. */
-	MAR0 = 8,		/* Multicast filter. */
-	CounterAddrLow = 0x10,
-	CounterAddrHigh = 0x14,
-	TxDescStartAddrLow = 0x20,
-	TxDescStartAddrHigh = 0x24,
-	TxHDescStartAddrLow = 0x28,
-	TxHDescStartAddrHigh = 0x2c,
-	FLASH = 0x30,
-	ERSR = 0x36,
-	ChipCmd = 0x37,
-	TxPoll = 0x38,
-	IntrMask = 0x3C,
-	IntrStatus = 0x3E,
-	TxConfig = 0x40,
-	RxConfig = 0x44,
-	RxMissed = 0x4C,
-	Cfg9346 = 0x50,
-	Config0 = 0x51,
-	Config1 = 0x52,
-	Config2 = 0x53,
-	Config3 = 0x54,
-	Config4 = 0x55,
-	Config5 = 0x56,
-	MultiIntr = 0x5C,
-	PHYAR = 0x60,
-	TBICSR = 0x64,
-	TBI_ANAR = 0x68,
-	TBI_LPAR = 0x6A,
-	PHYstatus = 0x6C,
-	RxMaxSize = 0xDA,
-	CPlusCmd = 0xE0,
-	IntrMitigate = 0xE2,
-	RxDescAddrLow = 0xE4,
-	RxDescAddrHigh = 0xE8,
-	EarlyTxThres = 0xEC,
-	FuncEvent = 0xF0,
-	FuncEventMask = 0xF4,
-	FuncPresetState = 0xF8,
-	FuncForceEvent = 0xFC,
+enum rtl_registers {
+	MAC0		= 0,	/* Ethernet hardware address. */
+	MAC4		= 4,
+	MAR0		= 8,	/* Multicast filter. */
+	CounterAddrLow		= 0x10,
+	CounterAddrHigh		= 0x14,
+	TxDescStartAddrLow	= 0x20,
+	TxDescStartAddrHigh	= 0x24,
+	TxHDescStartAddrLow	= 0x28,
+	TxHDescStartAddrHigh	= 0x2c,
+	FLASH		= 0x30,
+	ERSR		= 0x36,
+	ChipCmd		= 0x37,
+	TxPoll		= 0x38,
+	IntrMask	= 0x3c,
+	IntrStatus	= 0x3e,
+	TxConfig	= 0x40,
+	RxConfig	= 0x44,
+	RxMissed	= 0x4c,
+	Cfg9346		= 0x50,
+	Config0		= 0x51,
+	Config1		= 0x52,
+	Config2		= 0x53,
+	Config3		= 0x54,
+	Config4		= 0x55,
+	Config5		= 0x56,
+	MultiIntr	= 0x5c,
+	PHYAR		= 0x60,
+	TBICSR		= 0x64,
+	TBI_ANAR	= 0x68,
+	TBI_LPAR	= 0x6a,
+	PHYstatus	= 0x6c,
+	RxMaxSize	= 0xda,
+	CPlusCmd	= 0xe0,
+	IntrMitigate	= 0xe2,
+	RxDescAddrLow	= 0xe4,
+	RxDescAddrHigh	= 0xe8,
+	EarlyTxThres	= 0xec,
+	FuncEvent	= 0xf0,
+	FuncEventMask	= 0xf4,
+	FuncPresetState	= 0xf8,
+	FuncForceEvent	= 0xfc,
 };
 
-enum RTL8169_register_content {
+enum rtl_register_content {
 	/* InterruptStatusBits */
-	SYSErr = 0x8000,
-	PCSTimeout = 0x4000,
-	SWInt = 0x0100,
-	TxDescUnavail = 0x80,
-	RxFIFOOver = 0x40,
-	LinkChg = 0x20,
-	RxOverflow = 0x10,
-	TxErr = 0x08,
-	TxOK = 0x04,
-	RxErr = 0x02,
-	RxOK = 0x01,
+	SYSErr		= 0x8000,
+	PCSTimeout	= 0x4000,
+	SWInt		= 0x0100,
+	TxDescUnavail	= 0x0080,
+	RxFIFOOver	= 0x0040,
+	LinkChg		= 0x0020,
+	RxOverflow	= 0x0010,
+	TxErr		= 0x0008,
+	TxOK		= 0x0004,
+	RxErr		= 0x0002,
+	RxOK		= 0x0001,
 
 	/* RxStatusDesc */
 	RxFOVF	= (1 << 23),
@@ -295,26 +246,31 @@
 	RxCRC	= (1 << 19),
 
 	/* ChipCmdBits */
-	CmdReset = 0x10,
-	CmdRxEnb = 0x08,
-	CmdTxEnb = 0x04,
-	RxBufEmpty = 0x01,
+	CmdReset	= 0x10,
+	CmdRxEnb	= 0x08,
+	CmdTxEnb	= 0x04,
+	RxBufEmpty	= 0x01,
+
+	/* TXPoll register p.5 */
+	HPQ		= 0x80,		/* Poll cmd on the high prio queue */
+	NPQ		= 0x40,		/* Poll cmd on the low prio queue */
+	FSWInt		= 0x01,		/* Forced software interrupt */
 
 	/* Cfg9346Bits */
-	Cfg9346_Lock = 0x00,
-	Cfg9346_Unlock = 0xC0,
+	Cfg9346_Lock	= 0x00,
+	Cfg9346_Unlock	= 0xc0,
 
 	/* rx_mode_bits */
-	AcceptErr = 0x20,
-	AcceptRunt = 0x10,
-	AcceptBroadcast = 0x08,
-	AcceptMulticast = 0x04,
-	AcceptMyPhys = 0x02,
-	AcceptAllPhys = 0x01,
+	AcceptErr	= 0x20,
+	AcceptRunt	= 0x10,
+	AcceptBroadcast	= 0x08,
+	AcceptMulticast	= 0x04,
+	AcceptMyPhys	= 0x02,
+	AcceptAllPhys	= 0x01,
 
 	/* RxConfigBits */
-	RxCfgFIFOShift = 13,
-	RxCfgDMAShift = 8,
+	RxCfgFIFOShift	= 13,
+	RxCfgDMAShift	=  8,
 
 	/* TxConfigBits */
 	TxInterFrameGapShift = 24,
@@ -323,6 +279,10 @@
 	/* Config1 register p.24 */
 	PMEnable	= (1 << 0),	/* Power Management Enable */
 
+	/* Config2 register p. 25 */
+	PCI_Clock_66MHz = 0x01,
+	PCI_Clock_33MHz = 0x00,
+
 	/* Config3 register p.25 */
 	MagicPacket	= (1 << 5),	/* Wake up when receives a Magic Packet */
 	LinkUp		= (1 << 4),	/* Wake up when the cable connection is re-established */
@@ -343,36 +303,34 @@
 	TBINwComplete	= 0x01000000,
 
 	/* CPlusCmd p.31 */
+	PktCntrDisable	= (1 << 7),	// 8168
 	RxVlan		= (1 << 6),
 	RxChkSum	= (1 << 5),
 	PCIDAC		= (1 << 4),
 	PCIMulRW	= (1 << 3),
+	INTT_0		= 0x0000,	// 8168
+	INTT_1		= 0x0001,	// 8168
+	INTT_2		= 0x0002,	// 8168
+	INTT_3		= 0x0003,	// 8168
 
 	/* rtl8169_PHYstatus */
-	TBI_Enable = 0x80,
-	TxFlowCtrl = 0x40,
-	RxFlowCtrl = 0x20,
-	_1000bpsF = 0x10,
-	_100bps = 0x08,
-	_10bps = 0x04,
-	LinkStatus = 0x02,
-	FullDup = 0x01,
-
-	/* _MediaType */
-	_10_Half = 0x01,
-	_10_Full = 0x02,
-	_100_Half = 0x04,
-	_100_Full = 0x08,
-	_1000_Full = 0x10,
+	TBI_Enable	= 0x80,
+	TxFlowCtrl	= 0x40,
+	RxFlowCtrl	= 0x20,
+	_1000bpsF	= 0x10,
+	_100bps		= 0x08,
+	_10bps		= 0x04,
+	LinkStatus	= 0x02,
+	FullDup		= 0x01,
 
 	/* _TBICSRBit */
-	TBILinkOK = 0x02000000,
+	TBILinkOK	= 0x02000000,
 
 	/* DumpCounterCommand */
-	CounterDump = 0x8,
+	CounterDump	= 0x8,
 };
 
-enum _DescStatusBit {
+enum desc_status_bit {
 	DescOwn		= (1 << 31), /* Descriptor is owned by NIC */
 	RingEnd		= (1 << 30), /* End of descriptor ring */
 	FirstFrag	= (1 << 29), /* First segment of a packet */
@@ -405,15 +363,15 @@
 #define RsvdMask	0x3fffc000
 
 struct TxDesc {
-	u32 opts1;
-	u32 opts2;
-	u64 addr;
+	__le32 opts1;
+	__le32 opts2;
+	__le64 addr;
 };
 
 struct RxDesc {
-	u32 opts1;
-	u32 opts2;
-	u64 addr;
+	__le32 opts1;
+	__le32 opts2;
+	__le64 addr;
 };
 
 struct ring_info {
@@ -446,6 +404,8 @@
 	unsigned rx_buf_sz;
 	struct timer_list timer;
 	u16 cp_cmd;
+	u16 intr_event;
+	u16 napi_event;
 	u16 intr_mask;
 	int phy_auto_nego_reg;
 	int phy_1000_ctrl_reg;
@@ -455,6 +415,7 @@
 	int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
 	void (*get_settings)(struct net_device *, struct ethtool_cmd *);
 	void (*phy_reset_enable)(void __iomem *);
+	void (*hw_start)(struct net_device *);
 	unsigned int (*phy_reset_pending)(void __iomem *);
 	unsigned int (*link_ok)(void __iomem *);
 	struct delayed_work task;
@@ -463,8 +424,6 @@
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
 MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
-module_param_array(media, int, &num_media, 0);
-MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8).");
 module_param(rx_copybreak, int, 0);
 MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
 module_param(use_dac, int, 0);
@@ -478,9 +437,9 @@
 static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance);
 static int rtl8169_init_ring(struct net_device *dev);
-static void rtl8169_hw_start(struct net_device *dev);
+static void rtl_hw_start(struct net_device *dev);
 static int rtl8169_close(struct net_device *dev);
-static void rtl8169_set_rx_mode(struct net_device *dev);
+static void rtl_set_rx_mode(struct net_device *dev);
 static void rtl8169_tx_timeout(struct net_device *dev);
 static struct net_device_stats *rtl8169_get_stats(struct net_device *dev);
 static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
@@ -493,35 +452,37 @@
 static int rtl8169_poll(struct net_device *dev, int *budget);
 #endif
 
-static const u16 rtl8169_intr_mask =
-	SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
-static const u16 rtl8169_napi_event =
-	RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr;
 static const unsigned int rtl8169_rx_config =
 	(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
 
-static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
+static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
 {
 	int i;
 
-	RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
+	RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value);
 
 	for (i = 20; i > 0; i--) {
-		/* Check if the RTL8169 has completed writing to the specified MII register */
+		/*
+		 * Check if the RTL8169 has completed writing to the specified
+		 * MII register.
+		 */
 		if (!(RTL_R32(PHYAR) & 0x80000000))
 			break;
 		udelay(25);
 	}
 }
 
-static int mdio_read(void __iomem *ioaddr, int RegAddr)
+static int mdio_read(void __iomem *ioaddr, int reg_addr)
 {
 	int i, value = -1;
 
-	RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
+	RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16);
 
 	for (i = 20; i > 0; i--) {
-		/* Check if the RTL8169 has completed retrieving data from the specified MII register */
+		/*
+		 * Check if the RTL8169 has completed retrieving data from
+		 * the specified MII register.
+		 */
 		if (RTL_R32(PHYAR) & 0x80000000) {
 			value = (int) (RTL_R32(PHYAR) & 0xFFFF);
 			break;
@@ -579,7 +540,8 @@
 }
 
 static void rtl8169_check_link_status(struct net_device *dev,
-				      struct rtl8169_private *tp, void __iomem *ioaddr)
+				      struct rtl8169_private *tp,
+				      void __iomem *ioaddr)
 {
 	unsigned long flags;
 
@@ -596,38 +558,6 @@
 	spin_unlock_irqrestore(&tp->lock, flags);
 }
 
-static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
-{
-	struct {
-		u16 speed;
-		u8 duplex;
-		u8 autoneg;
-		u8 media;
-	} link_settings[] = {
-		{ SPEED_10,	DUPLEX_HALF, AUTONEG_DISABLE,	_10_Half },
-		{ SPEED_10,	DUPLEX_FULL, AUTONEG_DISABLE,	_10_Full },
-		{ SPEED_100,	DUPLEX_HALF, AUTONEG_DISABLE,	_100_Half },
-		{ SPEED_100,	DUPLEX_FULL, AUTONEG_DISABLE,	_100_Full },
-		{ SPEED_1000,	DUPLEX_FULL, AUTONEG_DISABLE,	_1000_Full },
-		/* Make TBI happy */
-		{ SPEED_1000,	DUPLEX_FULL, AUTONEG_ENABLE,	0xff }
-	}, *p;
-	unsigned char option;
-
-	option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
-
-	if ((option != 0xff) && !idx && netif_msg_drv(&debug))
-		printk(KERN_WARNING PFX "media option is deprecated.\n");
-
-	for (p = link_settings; p->media != 0xff; p++) {
-		if (p->media == option)
-			break;
-	}
-	*autoneg = p->autoneg;
-	*speed = p->speed;
-	*duplex = p->duplex;
-}
-
 static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -667,7 +597,7 @@
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
-	int i;
+	unsigned int i;
 	static struct {
 		u32 opt;
 		u16 reg;
@@ -893,8 +823,7 @@
 	int ret;
 
 	if (tp->vlgrp && (opts2 & RxVlanTag)) {
-		rtl8169_rx_hwaccel_skb(skb, tp->vlgrp,
-				       swab16(opts2 & 0xffff));
+		rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, swab16(opts2 & 0xffff));
 		ret = 0;
 	} else
 		ret = -1;
@@ -1115,7 +1044,6 @@
 	}
 }
 
-
 static const struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_drvinfo		= rtl8169_get_drvinfo,
 	.get_regs_len		= rtl8169_get_regs_len,
@@ -1141,8 +1069,8 @@
 	.get_perm_addr		= ethtool_op_get_perm_addr,
 };
 
-static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
-				       int bitval)
+static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg,
+				       int bitnum, int bitval)
 {
 	int val;
 
@@ -1152,8 +1080,20 @@
 	mdio_write(ioaddr, reg, val & 0xffff);
 }
 
-static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_mac_version(struct rtl8169_private *tp,
+				    void __iomem *ioaddr)
 {
+	/*
+	 * The driver currently handles the 8168Bf and the 8168Be identically
+	 * but they can be identified more specifically through the test below
+	 * if needed:
+	 *
+	 * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
+	 *
+	 * Same thing for the 8101Eb and the 8101Ec:
+	 *
+	 * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
+	 */
 	const struct {
 		u32 mask;
 		int mac_version;
@@ -1163,6 +1103,7 @@
 		{ 0x34000000,	RTL_GIGA_MAC_VER_13 },
 		{ 0x30800000,	RTL_GIGA_MAC_VER_14 },
 		{ 0x30000000,	RTL_GIGA_MAC_VER_11 },
+		{ 0x98000000,	RTL_GIGA_MAC_VER_06 },
 		{ 0x18000000,	RTL_GIGA_MAC_VER_05 },
 		{ 0x10000000,	RTL_GIGA_MAC_VER_04 },
 		{ 0x04000000,	RTL_GIGA_MAC_VER_03 },
@@ -1171,7 +1112,7 @@
 	}, *p = mac_info;
 	u32 reg;
 
-	reg = RTL_R32(TxConfig) & 0x7c800000;
+	reg = RTL_R32(TxConfig) & 0xfc800000;
 	while ((reg & p->mask) != p->mask)
 		p++;
 	tp->mac_version = p->mac_version;
@@ -1182,7 +1123,8 @@
 	dprintk("mac_version = 0x%02x\n", tp->mac_version);
 }
 
-static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_phy_version(struct rtl8169_private *tp,
+				    void __iomem *ioaddr)
 {
 	const struct {
 		u16 mask;
@@ -1259,7 +1201,7 @@
 		  0xbf00 }	//w 0 15 0 bf00
 		}
 	}, *p = phy_magic;
-	int i;
+	unsigned int i;
 
 	rtl8169_print_mac_version(tp);
 	rtl8169_print_phy_version(tp);
@@ -1393,7 +1335,7 @@
 			      struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
-	int i;
+	unsigned int i;
 
 	tp->phy_reset_enable(ioaddr);
 	for (i = 0; i < 100; i++) {
@@ -1408,21 +1350,16 @@
 static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
-	static int board_idx = -1;
-	u8 autoneg, duplex;
-	u16 speed;
-
-	board_idx++;
 
 	rtl8169_hw_phy_config(dev);
 
 	dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
 	RTL_W8(0x82, 0x01);
 
-	if (tp->mac_version < RTL_GIGA_MAC_VER_03) {
-		dprintk("Set PCI Latency=0x40\n");
-		pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
-	}
+	pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
+
+	if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
+		pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
 
 	if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
 		dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
@@ -1431,16 +1368,52 @@
 		mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
 	}
 
-	rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
-
 	rtl8169_phy_reset(dev, tp);
 
-	rtl8169_set_speed(dev, autoneg, speed, duplex);
+	/*
+	 * rtl8169_set_speed_xmii takes good care of the Fast Ethernet
+	 * only 8101. Don't panic.
+	 */
+	rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL);
 
 	if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
 		printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
 }
 
+static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	u32 high;
+	u32 low;
+
+	low  = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
+	high = addr[4] | (addr[5] << 8);
+
+	spin_lock_irq(&tp->lock);
+
+	RTL_W8(Cfg9346, Cfg9346_Unlock);
+	RTL_W32(MAC0, low);
+	RTL_W32(MAC4, high);
+	RTL_W8(Cfg9346, Cfg9346_Lock);
+
+	spin_unlock_irq(&tp->lock);
+}
+
+static int rtl_set_mac_address(struct net_device *dev, void *p)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	rtl_rar_set(tp, dev->dev_addr);
+
+	return 0;
+}
+
 static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -1467,15 +1440,49 @@
 	return -EOPNOTSUPP;
 }
 
+static const struct rtl_cfg_info {
+	void (*hw_start)(struct net_device *);
+	unsigned int region;
+	unsigned int align;
+	u16 intr_event;
+	u16 napi_event;
+} rtl_cfg_infos [] = {
+	[RTL_CFG_0] = {
+		.hw_start	= rtl_hw_start_8169,
+		.region		= 1,
+		.align		= 0,
+		.intr_event	= SYSErr | LinkChg | RxOverflow |
+				  RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+		.napi_event	= RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+	},
+	[RTL_CFG_1] = {
+		.hw_start	= rtl_hw_start_8168,
+		.region		= 2,
+		.align		= 8,
+		.intr_event	= SYSErr | LinkChg | RxOverflow |
+				  TxErr | TxOK | RxOK | RxErr,
+		.napi_event	= TxErr | TxOK | RxOK | RxOverflow
+	},
+	[RTL_CFG_2] = {
+		.hw_start	= rtl_hw_start_8101,
+		.region		= 2,
+		.align		= 8,
+		.intr_event	= SYSErr | LinkChg | RxOverflow | PCSTimeout |
+				  RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+		.napi_event	= RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+	}
+};
+
 static int __devinit
 rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	const unsigned int region = rtl_cfg_info[ent->driver_data].region;
+	const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
+	const unsigned int region = cfg->region;
 	struct rtl8169_private *tp;
 	struct net_device *dev;
 	void __iomem *ioaddr;
-	unsigned int pm_cap;
-	int i, rc;
+	unsigned int i;
+	int rc;
 
 	if (netif_msg_drv(&debug)) {
 		printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
@@ -1508,20 +1515,6 @@
 	if (rc < 0)
 		goto err_out_disable_2;
 
-	/* save power state before pci_enable_device overwrites it */
-	pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
-	if (pm_cap) {
-		u16 pwr_command, acpi_idle_state;
-
-		pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
-		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
-	} else {
-		if (netif_msg_probe(tp)) {
-			dev_err(&pdev->dev,
-				"PowerManagement capability not found.\n");
-		}
-	}
-
 	/* make sure PCI base addr 1 is MMIO */
 	if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
 		if (netif_msg_probe(tp)) {
@@ -1585,7 +1578,7 @@
 	RTL_W8(ChipCmd, CmdReset);
 
 	/* Check that the chip has finished the reset. */
-	for (i = 100; i > 0; i--) {
+	for (i = 0; i < 100; i++) {
 		if ((RTL_R8(ChipCmd) & CmdReset) == 0)
 			break;
 		msleep_interruptible(1);
@@ -1647,11 +1640,12 @@
 	SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
 	dev->stop = rtl8169_close;
 	dev->tx_timeout = rtl8169_tx_timeout;
-	dev->set_multicast_list = rtl8169_set_rx_mode;
+	dev->set_multicast_list = rtl_set_rx_mode;
 	dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
 	dev->irq = pdev->irq;
 	dev->base_addr = (unsigned long) ioaddr;
 	dev->change_mtu = rtl8169_change_mtu;
+	dev->set_mac_address = rtl_set_mac_address;
 
 #ifdef CONFIG_R8169_NAPI
 	dev->poll = rtl8169_poll;
@@ -1670,7 +1664,10 @@
 	tp->intr_mask = 0xffff;
 	tp->pci_dev = pdev;
 	tp->mmio_addr = ioaddr;
-	tp->align = rtl_cfg_info[ent->driver_data].align;
+	tp->align = cfg->align;
+	tp->hw_start = cfg->hw_start;
+	tp->intr_event = cfg->intr_event;
+	tp->napi_event = cfg->napi_event;
 
 	init_timer(&tp->timer);
 	tp->timer.data = (unsigned long) dev;
@@ -1685,15 +1682,17 @@
 	pci_set_drvdata(pdev, dev);
 
 	if (netif_msg_probe(tp)) {
+		u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff;
+
 		printk(KERN_INFO "%s: %s at 0x%lx, "
 		       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
-		       "IRQ %d\n",
+		       "XID %08x IRQ %d\n",
 		       dev->name,
 		       rtl_chip_info[tp->chipset].name,
 		       dev->base_addr,
 		       dev->dev_addr[0], dev->dev_addr[1],
 		       dev->dev_addr[2], dev->dev_addr[3],
-		       dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+		       dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq);
 	}
 
 	rtl8169_init_phy(dev, tp);
@@ -1714,15 +1713,11 @@
 	goto out;
 }
 
-static void __devexit
-rtl8169_remove_one(struct pci_dev *pdev)
+static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct rtl8169_private *tp = netdev_priv(dev);
 
-	assert(dev != NULL);
-	assert(tp != NULL);
-
 	flush_scheduled_work();
 
 	unregister_netdev(dev);
@@ -1774,7 +1769,7 @@
 	if (retval < 0)
 		goto err_release_ring_2;
 
-	rtl8169_hw_start(dev);
+	rtl_hw_start(dev);
 
 	rtl8169_request_timer(dev);
 
@@ -1805,7 +1800,7 @@
 	RTL_R8(ChipCmd);
 }
 
-static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp)
+static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
 {
 	void __iomem *ioaddr = tp->mmio_addr;
 	u32 cfg = rtl8169_rx_config;
@@ -1818,47 +1813,92 @@
 		(InterFrameGap << TxInterFrameGapShift));
 }
 
-static void rtl8169_hw_start(struct net_device *dev)
+static void rtl_hw_start(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
-	struct pci_dev *pdev = tp->pci_dev;
-	u16 cmd;
-	u32 i;
+	unsigned int i;
 
 	/* Soft reset the chip. */
 	RTL_W8(ChipCmd, CmdReset);
 
 	/* Check that the chip has finished the reset. */
-	for (i = 100; i > 0; i--) {
+	for (i = 0; i < 100; i++) {
 		if ((RTL_R8(ChipCmd) & CmdReset) == 0)
 			break;
 		msleep_interruptible(1);
 	}
 
+	tp->hw_start(dev);
+
+	netif_start_queue(dev);
+}
+
+
+static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
+					 void __iomem *ioaddr)
+{
+	/*
+	 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
+	 * register to be written before TxDescAddrLow to work.
+	 * Switching from MMIO to I/O access fixes the issue as well.
+	 */
+	RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
+	RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK);
+	RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
+	RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK);
+}
+
+static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
+{
+	u16 cmd;
+
+	cmd = RTL_R16(CPlusCmd);
+	RTL_W16(CPlusCmd, cmd);
+	return cmd;
+}
+
+static void rtl_set_rx_max_size(void __iomem *ioaddr)
+{
+	/* Low hurts. Let's disable the filtering. */
+	RTL_W16(RxMaxSize, 16383);
+}
+
+static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
+{
+	struct {
+		u32 mac_version;
+		u32 clk;
+		u32 val;
+	} cfg2_info [] = {
+		{ RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
+		{ RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
+		{ RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
+		{ RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
+	}, *p = cfg2_info;
+	unsigned int i;
+	u32 clk;
+
+	clk = RTL_R8(Config2) & PCI_Clock_66MHz;
+	for (i = 0; i < ARRAY_SIZE(cfg2_info); i++) {
+		if ((p->mac_version == mac_version) && (p->clk == clk)) {
+			RTL_W32(0x7c, p->val);
+			break;
+		}
+	}
+}
+
+static void rtl_hw_start_8169(struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+
 	if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
 		RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
 		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
 	}
 
-	if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
-		pci_write_config_word(pdev, 0x68, 0x00);
-		pci_write_config_word(pdev, 0x69, 0x08);
-	}
-
-	/* Undocumented stuff. */
-	if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
-		/* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */
-		if ((RTL_R8(Config2) & 0x07) & 0x01)
-			RTL_W32(0x7c, 0x0007ffff);
-
-		RTL_W32(0x7c, 0x0007ff00);
-
-		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-		cmd = cmd & 0xef;
-		pci_write_config_word(pdev, PCI_COMMAND, cmd);
-	}
-
 	RTL_W8(Cfg9346, Cfg9346_Unlock);
 	if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
 	    (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
@@ -1868,19 +1908,11 @@
 
 	RTL_W8(EarlyTxThres, EarlyTxThld);
 
-	/* Low hurts. Let's disable the filtering. */
-	RTL_W16(RxMaxSize, 16383);
+	rtl_set_rx_max_size(ioaddr);
 
-	if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_03) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_04))
-		rtl8169_set_rx_tx_config_registers(tp);
+	rtl_set_rx_tx_config_registers(tp);
 
-	cmd = RTL_R16(CPlusCmd);
-	RTL_W16(CPlusCmd, cmd);
-
-	tp->cp_cmd |= cmd | PCIMulRW;
+	tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
 
 	if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
 	    (tp->mac_version == RTL_GIGA_MAC_VER_03)) {
@@ -1891,29 +1923,15 @@
 
 	RTL_W16(CPlusCmd, tp->cp_cmd);
 
+	rtl8169_set_magic_reg(ioaddr, tp->mac_version);
+
 	/*
 	 * Undocumented corner. Supposedly:
 	 * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
 	 */
 	RTL_W16(IntrMitigate, 0x0000);
 
-	/*
-	 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
-	 * register to be written before TxDescAddrLow to work.
-	 * Switching from MMIO to I/O access fixes the issue as well.
-	 */
-	RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));
-	RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
-	RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32));
-	RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
-
-	if ((tp->mac_version != RTL_GIGA_MAC_VER_01) &&
-	    (tp->mac_version != RTL_GIGA_MAC_VER_02) &&
-	    (tp->mac_version != RTL_GIGA_MAC_VER_03) &&
-	    (tp->mac_version != RTL_GIGA_MAC_VER_04)) {
-		RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
-		rtl8169_set_rx_tx_config_registers(tp);
-	}
+	rtl_set_rx_tx_desc_registers(tp, ioaddr);
 
 	RTL_W8(Cfg9346, Cfg9346_Lock);
 
@@ -1922,15 +1940,107 @@
 
 	RTL_W32(RxMissed, 0);
 
-	rtl8169_set_rx_mode(dev);
+	rtl_set_rx_mode(dev);
 
 	/* no early-rx interrupts */
 	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
 
 	/* Enable all known interrupts by setting the interrupt mask. */
-	RTL_W16(IntrMask, rtl8169_intr_mask);
+	RTL_W16(IntrMask, tp->intr_event);
 
-	netif_start_queue(dev);
+	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+}
+
+static void rtl_hw_start_8168(struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+	u8 ctl;
+
+	RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+	RTL_W8(EarlyTxThres, EarlyTxThld);
+
+	rtl_set_rx_max_size(ioaddr);
+
+	rtl_set_rx_tx_config_registers(tp);
+
+	tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
+
+	RTL_W16(CPlusCmd, tp->cp_cmd);
+
+	/* Tx performance tweak. */
+	pci_read_config_byte(pdev, 0x69, &ctl);
+	ctl = (ctl & ~0x70) | 0x50;
+	pci_write_config_byte(pdev, 0x69, ctl);
+
+	RTL_W16(IntrMitigate, 0x5151);
+
+	/* Work around for RxFIFO overflow. */
+	if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
+		tp->intr_event |= RxFIFOOver | PCSTimeout;
+		tp->intr_event &= ~RxOverflow;
+	}
+
+	rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+	RTL_W8(Cfg9346, Cfg9346_Lock);
+
+	RTL_R8(IntrMask);
+
+	RTL_W32(RxMissed, 0);
+
+	rtl_set_rx_mode(dev);
+
+	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
+
+	RTL_W16(IntrMask, tp->intr_event);
+}
+
+static void rtl_hw_start_8101(struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct pci_dev *pdev = tp->pci_dev;
+
+	if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
+		pci_write_config_word(pdev, 0x68, 0x00);
+		pci_write_config_word(pdev, 0x69, 0x08);
+	}
+
+	RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+	RTL_W8(EarlyTxThres, EarlyTxThld);
+
+	rtl_set_rx_max_size(ioaddr);
+
+	tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
+
+	RTL_W16(CPlusCmd, tp->cp_cmd);
+
+	RTL_W16(IntrMitigate, 0x0000);
+
+	rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+	rtl_set_rx_tx_config_registers(tp);
+
+	RTL_W8(Cfg9346, Cfg9346_Lock);
+
+	RTL_R8(IntrMask);
+
+	RTL_W32(RxMissed, 0);
+
+	rtl_set_rx_mode(dev);
+
+	RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+	RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
+
+	RTL_W16(IntrMask, tp->intr_event);
 }
 
 static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
@@ -1956,7 +2066,7 @@
 
 	netif_poll_enable(dev);
 
-	rtl8169_hw_start(dev);
+	rtl_hw_start(dev);
 
 	rtl8169_request_timer(dev);
 
@@ -1997,38 +2107,38 @@
 	rtl8169_mark_to_asic(desc, rx_buf_sz);
 }
 
-static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
-				struct RxDesc *desc, int rx_buf_sz,
-				unsigned int align)
+static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
+					    struct net_device *dev,
+					    struct RxDesc *desc, int rx_buf_sz,
+					    unsigned int align)
 {
 	struct sk_buff *skb;
 	dma_addr_t mapping;
-	int ret = 0;
+	unsigned int pad;
 
-	skb = dev_alloc_skb(rx_buf_sz + align);
+	pad = align ? align : NET_IP_ALIGN;
+
+	skb = netdev_alloc_skb(dev, rx_buf_sz + pad);
 	if (!skb)
 		goto err_out;
 
-	skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
-	*sk_buff = skb;
+	skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad);
 
 	mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
 				 PCI_DMA_FROMDEVICE);
 
 	rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
-
 out:
-	return ret;
+	return skb;
 
 err_out:
-	ret = -ENOMEM;
 	rtl8169_make_unusable_by_asic(desc);
 	goto out;
 }
 
 static void rtl8169_rx_clear(struct rtl8169_private *tp)
 {
-	int i;
+	unsigned int i;
 
 	for (i = 0; i < NUM_RX_DESC; i++) {
 		if (tp->Rx_skbuff[i]) {
@@ -2043,16 +2153,22 @@
 {
 	u32 cur;
 
-	for (cur = start; end - cur > 0; cur++) {
-		int ret, i = cur % NUM_RX_DESC;
+	for (cur = start; end - cur != 0; cur++) {
+		struct sk_buff *skb;
+		unsigned int i = cur % NUM_RX_DESC;
+
+		WARN_ON((s32)(end - cur) < 0);
 
 		if (tp->Rx_skbuff[i])
 			continue;
 
-		ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
-			tp->RxDescArray + i, tp->rx_buf_sz, tp->align);
-		if (ret < 0)
+		skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev,
+					   tp->RxDescArray + i,
+					   tp->rx_buf_sz, tp->align);
+		if (!skb)
 			break;
+
+		tp->Rx_skbuff[i] = skb;
 	}
 	return cur - start;
 }
@@ -2164,14 +2280,9 @@
 
 	ret = rtl8169_open(dev);
 	if (unlikely(ret < 0)) {
-		if (net_ratelimit()) {
-			struct rtl8169_private *tp = netdev_priv(dev);
-
-			if (netif_msg_drv(tp)) {
-				printk(PFX KERN_ERR
-				       "%s: reinit failure (status = %d)."
-				       " Rescheduling.\n", dev->name, ret);
-			}
+		if (net_ratelimit() && netif_msg_drv(tp)) {
+			printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
+			       " Rescheduling.\n", dev->name, ret);
 		}
 		rtl8169_schedule_work(dev, rtl8169_reinit_task);
 	}
@@ -2198,16 +2309,12 @@
 
 	if (tp->dirty_rx == tp->cur_rx) {
 		rtl8169_init_ring_indexes(tp);
-		rtl8169_hw_start(dev);
+		rtl_hw_start(dev);
 		netif_wake_queue(dev);
 	} else {
-		if (net_ratelimit()) {
-			struct rtl8169_private *tp = netdev_priv(dev);
-
-			if (netif_msg_intr(tp)) {
-				printk(PFX KERN_EMERG
-				       "%s: Rx buffers shortage\n", dev->name);
-			}
+		if (net_ratelimit() && netif_msg_intr(tp)) {
+			printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
+			       dev->name);
 		}
 		rtl8169_schedule_work(dev, rtl8169_reset_task);
 	}
@@ -2344,7 +2451,7 @@
 
 	smp_wmb();
 
-	RTL_W8(TxPoll, 0x40);	/* set polling bit */
+	RTL_W8(TxPoll, NPQ);	/* set polling bit */
 
 	if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) {
 		netif_stop_queue(dev);
@@ -2414,16 +2521,12 @@
 	rtl8169_schedule_work(dev, rtl8169_reinit_task);
 }
 
-static void
-rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
-		     void __iomem *ioaddr)
+static void rtl8169_tx_interrupt(struct net_device *dev,
+				 struct rtl8169_private *tp,
+				 void __iomem *ioaddr)
 {
 	unsigned int dirty_tx, tx_left;
 
-	assert(dev != NULL);
-	assert(tp != NULL);
-	assert(ioaddr != NULL);
-
 	dirty_tx = tp->dirty_tx;
 	smp_rmb();
 	tx_left = tp->cur_tx - dirty_tx;
@@ -2480,38 +2583,37 @@
 		skb->ip_summed = CHECKSUM_NONE;
 }
 
-static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
-				      struct RxDesc *desc, int rx_buf_sz,
-				      unsigned int align)
+static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff,
+				       struct rtl8169_private *tp, int pkt_size,
+				       dma_addr_t addr)
 {
-	int ret = -1;
+	struct sk_buff *skb;
+	bool done = false;
 
-	if (pkt_size < rx_copybreak) {
-		struct sk_buff *skb;
+	if (pkt_size >= rx_copybreak)
+		goto out;
 
-		skb = dev_alloc_skb(pkt_size + align);
-		if (skb) {
-			skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
-			eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
-			*sk_buff = skb;
-			rtl8169_mark_to_asic(desc, rx_buf_sz);
-			ret = 0;
-		}
-	}
-	return ret;
+	skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN);
+	if (!skb)
+		goto out;
+
+	pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size,
+				    PCI_DMA_FROMDEVICE);
+	skb_reserve(skb, NET_IP_ALIGN);
+	skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size);
+	*sk_buff = skb;
+	done = true;
+out:
+	return done;
 }
 
-static int
-rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
-		     void __iomem *ioaddr)
+static int rtl8169_rx_interrupt(struct net_device *dev,
+				struct rtl8169_private *tp,
+				void __iomem *ioaddr)
 {
 	unsigned int cur_rx, rx_left;
 	unsigned int delta, count;
 
-	assert(dev != NULL);
-	assert(tp != NULL);
-	assert(ioaddr != NULL);
-
 	cur_rx = tp->cur_rx;
 	rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
 	rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
@@ -2544,9 +2646,9 @@
 			rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
 		} else {
 			struct sk_buff *skb = tp->Rx_skbuff[entry];
+			dma_addr_t addr = le64_to_cpu(desc->addr);
 			int pkt_size = (status & 0x00001FFF) - 4;
-			void (*pci_action)(struct pci_dev *, dma_addr_t,
-				size_t, int) = pci_dma_sync_single_for_device;
+			struct pci_dev *pdev = tp->pci_dev;
 
 			/*
 			 * The driver does not support incoming fragmented
@@ -2562,19 +2664,16 @@
 
 			rtl8169_rx_csum(skb, desc);
 
-			pci_dma_sync_single_for_cpu(tp->pci_dev,
-				le64_to_cpu(desc->addr), tp->rx_buf_sz,
-				PCI_DMA_FROMDEVICE);
-
-			if (rtl8169_try_rx_copy(&skb, pkt_size, desc,
-						tp->rx_buf_sz, tp->align)) {
-				pci_action = pci_unmap_single;
+			if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) {
+				pci_dma_sync_single_for_device(pdev, addr,
+					pkt_size, PCI_DMA_FROMDEVICE);
+				rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+			} else {
+				pci_unmap_single(pdev, addr, pkt_size,
+						 PCI_DMA_FROMDEVICE);
 				tp->Rx_skbuff[entry] = NULL;
 			}
 
-			pci_action(tp->pci_dev, le64_to_cpu(desc->addr),
-				   tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-
 			skb_put(skb, pkt_size);
 			skb->protocol = eth_type_trans(skb, dev);
 
@@ -2585,6 +2684,13 @@
 			tp->stats.rx_bytes += pkt_size;
 			tp->stats.rx_packets++;
 		}
+
+		/* Work around for AMD plateform. */
+		if ((desc->opts2 & 0xfffe000) &&
+		    (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
+			desc->opts2 = 0;
+			cur_rx++;
+		}
 	}
 
 	count = cur_rx - tp->cur_rx;
@@ -2608,11 +2714,9 @@
 	return count;
 }
 
-/* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
-static irqreturn_t
-rtl8169_interrupt(int irq, void *dev_instance)
+static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
 {
-	struct net_device *dev = (struct net_device *) dev_instance;
+	struct net_device *dev = dev_instance;
 	struct rtl8169_private *tp = netdev_priv(dev);
 	int boguscnt = max_interrupt_work;
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -2637,9 +2741,17 @@
 		RTL_W16(IntrStatus,
 			(status & RxFIFOOver) ? (status | RxOverflow) : status);
 
-		if (!(status & rtl8169_intr_mask))
+		if (!(status & tp->intr_event))
 			break;
 
+                /* Work around for rx fifo overflow */
+                if (unlikely(status & RxFIFOOver) &&
+		    (tp->mac_version == RTL_GIGA_MAC_VER_11)) {
+			netif_stop_queue(dev);
+			rtl8169_tx_timeout(dev);
+			break;
+		}
+
 		if (unlikely(status & SYSErr)) {
 			rtl8169_pcierr_interrupt(dev);
 			break;
@@ -2649,8 +2761,8 @@
 			rtl8169_check_link_status(dev, tp, ioaddr);
 
 #ifdef CONFIG_R8169_NAPI
-		RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event);
-		tp->intr_mask = ~rtl8169_napi_event;
+		RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event);
+		tp->intr_mask = ~tp->napi_event;
 
 		if (likely(netif_rx_schedule_prep(dev)))
 			__netif_rx_schedule(dev);
@@ -2661,9 +2773,9 @@
 		break;
 #else
 		/* Rx interrupt */
-		if (status & (RxOK | RxOverflow | RxFIFOOver)) {
+		if (status & (RxOK | RxOverflow | RxFIFOOver))
 			rtl8169_rx_interrupt(dev, tp, ioaddr);
-		}
+
 		/* Tx interrupt */
 		if (status & (TxOK | TxErr))
 			rtl8169_tx_interrupt(dev, tp, ioaddr);
@@ -2707,7 +2819,7 @@
 		 * write is safe - FR
 		 */
 		smp_wmb();
-		RTL_W16(IntrMask, rtl8169_intr_mask);
+		RTL_W16(IntrMask, tp->intr_event);
 	}
 
 	return (work_done >= work_to_do);
@@ -2789,14 +2901,13 @@
 	return 0;
 }
 
-static void
-rtl8169_set_rx_mode(struct net_device *dev)
+static void rtl_set_rx_mode(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 	u32 mc_filter[2];	/* Multicast hash filter */
-	int i, rx_mode;
+	int rx_mode;
 	u32 tmp = 0;
 
 	if (dev->flags & IFF_PROMISC) {
@@ -2816,6 +2927,8 @@
 		mc_filter[1] = mc_filter[0] = 0xffffffff;
 	} else {
 		struct dev_mc_list *mclist;
+		unsigned int i;
+
 		rx_mode = AcceptBroadcast | AcceptMyPhys;
 		mc_filter[1] = mc_filter[0] = 0;
 		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
@@ -2840,10 +2953,11 @@
 		mc_filter[1] = 0xffffffff;
 	}
 
-	RTL_W32(RxConfig, tmp);
 	RTL_W32(MAR0 + 0, mc_filter[0]);
 	RTL_W32(MAR0 + 4, mc_filter[1]);
 
+	RTL_W32(RxConfig, tmp);
+
 	spin_unlock_irqrestore(&tp->lock, flags);
 }
 
@@ -2931,14 +3045,12 @@
 #endif
 };
 
-static int __init
-rtl8169_init_module(void)
+static int __init rtl8169_init_module(void)
 {
 	return pci_register_driver(&rtl8169_pci_driver);
 }
 
-static void __exit
-rtl8169_cleanup_module(void)
+static void __exit rtl8169_cleanup_module(void)
 {
 	pci_unregister_driver(&rtl8169_pci_driver);
 }
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 25c73d4..5c2e41f 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -516,7 +516,7 @@
 }
 
 
-static int __init rr_init(struct net_device *dev)
+static int __devinit rr_init(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
 	struct rr_regs __iomem *regs;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 09078ff..fa29a40 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -469,11 +469,18 @@
 
 MODULE_DEVICE_TABLE(pci, s2io_tbl);
 
+static struct pci_error_handlers s2io_err_handler = {
+	.error_detected = s2io_io_error_detected,
+	.slot_reset = s2io_io_slot_reset,
+	.resume = s2io_io_resume,
+};
+
 static struct pci_driver s2io_driver = {
       .name = "S2IO",
       .id_table = s2io_tbl,
       .probe = s2io_init_nic,
       .remove = __devexit_p(s2io_rem_nic),
+      .err_handler = &s2io_err_handler,
 };
 
 /* A simplifier macro used both by init and free shared_mem Fns(). */
@@ -2689,6 +2696,9 @@
 	u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
 	int i;
 
+	if (pci_channel_offline(nic->pdev))
+		return;
+
 	disable_irq(dev->irq);
 
 	atomic_inc(&nic->isr_cnt);
@@ -3215,6 +3225,8 @@
 	int i;
 	if (atomic_read(&nic->card_state) == CARD_DOWN)
 		return;
+	if (pci_channel_offline(nic->pdev))
+		return;
 	nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
 	/* Handling the XPAK counters update */
 	if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
@@ -3958,7 +3970,6 @@
 	/* Reset card, kill tasklet and free Tx and Rx buffers. */
 	s2io_card_down(sp);
 
-	sp->device_close_flag = TRUE;	/* Device is shut down. */
 	return 0;
 }
 
@@ -4314,6 +4325,10 @@
 	struct mac_info *mac_control;
 	struct config_param *config;
 
+	/* Pretend we handled any irq's from a disconnected card */
+	if (pci_channel_offline(sp->pdev))
+		return IRQ_NONE;
+
 	atomic_inc(&sp->isr_cnt);
 	mac_control = &sp->mac_control;
 	config = &sp->config;
@@ -6569,7 +6584,7 @@
 	} while(cnt < 5);
 }
 
-static void s2io_card_down(struct s2io_nic * sp)
+static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
 {
 	int cnt = 0;
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -6584,7 +6599,8 @@
 	atomic_set(&sp->card_state, CARD_DOWN);
 
 	/* disable Tx and Rx traffic on the NIC */
-	stop_nic(sp);
+	if (do_io)
+		stop_nic(sp);
 
 	s2io_rem_isr(sp);
 
@@ -6592,7 +6608,7 @@
 	tasklet_kill(&sp->task);
 
 	/* Check if the device is Quiescent and then Reset the NIC */
-	do {
+	while(do_io) {
 		/* As per the HW requirement we need to replenish the
 		 * receive buffer to avoid the ring bump. Since there is
 		 * no intention of processing the Rx frame at this pointwe are
@@ -6617,8 +6633,9 @@
 				  (unsigned long long) val64);
 			break;
 		}
-	} while (1);
-	s2io_reset(sp);
+	}
+	if (do_io)
+		s2io_reset(sp);
 
 	spin_lock_irqsave(&sp->tx_lock, flags);
 	/* Free all Tx buffers */
@@ -6633,6 +6650,11 @@
 	clear_bit(0, &(sp->link_state));
 }
 
+static void s2io_card_down(struct s2io_nic * sp)
+{
+	do_s2io_card_down(sp, 1);
+}
+
 static int s2io_card_up(struct s2io_nic * sp)
 {
 	int i, ret = 0;
@@ -8010,3 +8032,85 @@
 	sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++;
 	return;
 }
+
+/**
+ * s2io_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
+                                               pci_channel_state_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct s2io_nic *sp = netdev->priv;
+
+	netif_device_detach(netdev);
+
+	if (netif_running(netdev)) {
+		/* Bring down the card, while avoiding PCI I/O */
+		do_s2io_card_down(sp, 0);
+	}
+	pci_disable_device(pdev);
+
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * s2io_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot.
+ * At this point, the card has exprienced a hard reset,
+ * followed by fixups by BIOS, and has its config space
+ * set up identically to what it was at cold boot.
+ */
+static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct s2io_nic *sp = netdev->priv;
+
+	if (pci_enable_device(pdev)) {
+		printk(KERN_ERR "s2io: "
+		       "Cannot re-enable PCI device after reset.\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+
+	pci_set_master(pdev);
+	s2io_reset(sp);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * s2io_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells
+ * us that its OK to resume normal operation.
+ */
+static void s2io_io_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct s2io_nic *sp = netdev->priv;
+
+	if (netif_running(netdev)) {
+		if (s2io_card_up(sp)) {
+			printk(KERN_ERR "s2io: "
+			       "Can't bring device back up after reset.\n");
+			return;
+		}
+
+		if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) {
+			s2io_card_down(sp);
+			printk(KERN_ERR "s2io: "
+			       "Can't resetore mac addr after reset.\n");
+			return;
+		}
+	}
+
+	netif_device_attach(netdev);
+	netif_wake_queue(netdev);
+}
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 54baa0b..5859278 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -794,7 +794,6 @@
 
 	struct net_device_stats stats;
 	int high_dma_flag;
-	int device_close_flag;
 	int device_enabled_once;
 
 	char name[60];
@@ -1052,6 +1051,11 @@
 			   struct sk_buff *skb, u32 tcp_len);
 static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring);
 
+static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
+			                      pci_channel_state_t state);
+static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev);
+static void s2io_io_resume(struct pci_dev *pdev);
+
 #define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size
 #define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size
 #define s2io_offload_type(skb) skb_shinfo(skb)->gso_type
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
index ad94358..451486b 100644
--- a/drivers/net/saa9730.c
+++ b/drivers/net/saa9730.c
@@ -690,9 +690,9 @@
 				lp->stats.rx_packets++;
 				skb_reserve(skb, 2);	/* 16 byte align */
 				skb_put(skb, len);	/* make room */
-				eth_copy_and_sum(skb,
+				skb_copy_to_linear_data(skb,
 						 (unsigned char *) pData,
-						 len, 0);
+						 len);
 				skb->protocol = eth_type_trans(skb, dev);
 				netif_rx(skb);
 				dev->last_rx = jiffies;
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 2106bec..384b468 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -320,7 +320,7 @@
 				skb_put(skb, len);
 
 				/* Copy out of kseg1 to avoid silly cache flush. */
-				eth_copy_and_sum(skb, pkt_pointer + 2, len, 0);
+				skb_copy_to_linear_data(skb, pkt_pointer + 2, len);
 				skb->protocol = eth_type_trans(skb, dev);
 
 				/* We don't want to receive our own packets */
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index bc8de48..ec2ad9f 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -548,7 +548,7 @@
 		skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
 		if (skb) {
 			skb_reserve(skb, NET_IP_ALIGN);
-			eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
+			skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
 			*sk_buff = skb;
 			sis190_give_to_asic(desc, rx_buf_sz);
 			ret = 0;
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 2cb2e15..7c6e480 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -573,7 +573,7 @@
  *	return error if it failed to found.
  */
 
-static int __init sis900_mii_probe(struct net_device * net_dev)
+static int __devinit sis900_mii_probe(struct net_device * net_dev)
 {
 	struct sis900_private * sis_priv = net_dev->priv;
 	const char *dev_name = pci_name(sis_priv->pci_dev);
diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
deleted file mode 100644
index afd900d..0000000
--- a/drivers/net/sk98lin/Makefile
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# Makefile for the SysKonnect SK-98xx device driver.
-#
-
-
-#
-# Standalone driver params
-# SKPARAM += -DSK_KERNEL_24
-# SKPARAM += -DSK_KERNEL_24_26
-# SKPARAM += -DSK_KERNEL_26
-# SKPARAM += -DSK_KERNEL_22_24
-
-obj-$(CONFIG_SK98LIN) += sk98lin.o
-sk98lin-objs    :=	\
-		skge.o		\
-		skethtool.o	\
-		skdim.o		\
-		skaddr.o	\
-		skgehwt.o	\
-		skgeinit.o	\
-		skgepnmi.o	\
-		skgesirq.o	\
-		ski2c.o		\
-		sklm80.o	\
-		skqueue.o	\
-		skrlmt.o	\
-		sktimer.o	\
-		skvpd.o		\
-		skxmac2.o
-
-# DBGDEF =  \
-# -DDEBUG
-
-ifdef DEBUG
-DBGDEF +=  \
--DSK_DEBUG_CHKMOD=0x00000000L \
--DSK_DEBUG_CHKCAT=0x00000000L
-endif
-
-
-# **** possible debug modules for SK_DEBUG_CHKMOD *****************
-# SK_DBGMOD_MERR        0x00000001L     /* general module error indication */
-# SK_DBGMOD_HWM         0x00000002L     /* Hardware init module */
-# SK_DBGMOD_RLMT        0x00000004L     /* RLMT module */
-# SK_DBGMOD_VPD         0x00000008L     /* VPD module */
-# SK_DBGMOD_I2C         0x00000010L     /* I2C module */
-# SK_DBGMOD_PNMI        0x00000020L     /* PNMI module */
-# SK_DBGMOD_CSUM        0x00000040L     /* CSUM module */
-# SK_DBGMOD_ADDR        0x00000080L     /* ADDR module */
-# SK_DBGMOD_DRV         0x00010000L     /* DRV module */
-
-# **** possible debug categories for SK_DEBUG_CHKCAT **************
-# *** common modules ***
-# SK_DBGCAT_INIT        0x00000001L     module/driver initialization
-# SK_DBGCAT_CTRL        0x00000002L     controlling: add/rmv MCA/MAC and other controls (IOCTL)
-# SK_DBGCAT_ERR         0x00000004L     error handling paths
-# SK_DBGCAT_TX          0x00000008L     transmit path
-# SK_DBGCAT_RX          0x00000010L     receive path
-# SK_DBGCAT_IRQ         0x00000020L     general IRQ handling
-# SK_DBGCAT_QUEUE       0x00000040L     any queue management
-# SK_DBGCAT_DUMP        0x00000080L     large data output e.g. hex dump
-# SK_DBGCAT_FATAL       0x00000100L     large data output e.g. hex dump
-
-# *** driver (file skge.c) ***
-# SK_DBGCAT_DRV_ENTRY           0x00010000      entry points
-# SK_DBGCAT_DRV_???             0x00020000      not used
-# SK_DBGCAT_DRV_MCA             0x00040000      multicast
-# SK_DBGCAT_DRV_TX_PROGRESS     0x00080000      tx path
-# SK_DBGCAT_DRV_RX_PROGRESS     0x00100000      rx path
-# SK_DBGCAT_DRV_PROGRESS        0x00200000      general runtime
-# SK_DBGCAT_DRV_???             0x00400000      not used
-# SK_DBGCAT_DRV_PROM            0x00800000      promiscuous mode
-# SK_DBGCAT_DRV_TX_FRAME        0x01000000      display tx frames
-# SK_DBGCAT_DRV_ERROR           0x02000000      error conditions
-# SK_DBGCAT_DRV_INT_SRC         0x04000000      interrupts sources
-# SK_DBGCAT_DRV_EVENT           0x08000000      driver events
-
-EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
-
-clean:
-	rm -f core *.o *.a *.s
-
-
-
-
-
-
diff --git a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h
deleted file mode 100644
index 4e2dbbf..0000000
--- a/drivers/net/sk98lin/h/lm80.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/******************************************************************************
- *
- * Name:	lm80.h	
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.6 $
- * Date:	$Date: 2003/05/13 17:26:52 $
- * Purpose:	Contains all defines for the LM80 Chip
- *		(National Semiconductor).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_LM80_H
-#define __INC_LM80_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-/*
- * LM80 register definition
- *
- * All registers are 8 bit wide
- */
-#define LM80_CFG			0x00	/* Configuration Register */
-#define LM80_ISRC_1			0x01	/* Interrupt Status Register 1 */
-#define LM80_ISRC_2			0x02	/* Interrupt Status Register 2 */
-#define LM80_IMSK_1			0x03	/* Interrupt Mask Register 1 */
-#define LM80_IMSK_2			0x04	/* Interrupt Mask Register 2 */
-#define LM80_FAN_CTRL		0x05	/* Fan Devisor/RST#/OS# Register */
-#define LM80_TEMP_CTRL		0x06	/* OS# Config, Temp Res. Reg */
-	/* 0x07 - 0x1f reserved	*/
-	/* current values */
-#define LM80_VT0_IN			0x20	/* current Voltage 0 value */
-#define LM80_VT1_IN			0x21	/* current Voltage 1 value */
-#define LM80_VT2_IN			0x22	/* current Voltage 2 value */
-#define LM80_VT3_IN			0x23	/* current Voltage 3 value */
-#define LM80_VT4_IN			0x24	/* current Voltage 4 value */
-#define LM80_VT5_IN			0x25	/* current Voltage 5 value */
-#define LM80_VT6_IN			0x26	/* current Voltage 6 value */
-#define LM80_TEMP_IN		0x27	/* current Temperature value */
-#define LM80_FAN1_IN		0x28	/* current Fan 1 count */
-#define LM80_FAN2_IN		0x29	/* current Fan 2 count */
-	/* limit values */
-#define LM80_VT0_HIGH_LIM	0x2a	/* high limit val for Voltage 0 */
-#define LM80_VT0_LOW_LIM	0x2b	/* low limit val for Voltage 0 */
-#define LM80_VT1_HIGH_LIM	0x2c	/* high limit val for Voltage 1 */
-#define LM80_VT1_LOW_LIM	0x2d	/* low limit val for Voltage 1 */
-#define LM80_VT2_HIGH_LIM	0x2e	/* high limit val for Voltage 2 */
-#define LM80_VT2_LOW_LIM	0x2f	/* low limit val for Voltage 2 */
-#define LM80_VT3_HIGH_LIM	0x30	/* high limit val for Voltage 3 */
-#define LM80_VT3_LOW_LIM	0x31	/* low limit val for Voltage 3 */
-#define LM80_VT4_HIGH_LIM	0x32	/* high limit val for Voltage 4 */
-#define LM80_VT4_LOW_LIM	0x33	/* low limit val for Voltage 4 */
-#define LM80_VT5_HIGH_LIM	0x34	/* high limit val for Voltage 5 */
-#define LM80_VT5_LOW_LIM	0x35	/* low limit val for Voltage 5 */
-#define LM80_VT6_HIGH_LIM	0x36	/* high limit val for Voltage 6 */
-#define LM80_VT6_LOW_LIM	0x37	/* low limit val for Voltage 6 */
-#define LM80_THOT_LIM_UP	0x38	/* hot temperature limit (high) */
-#define LM80_THOT_LIM_LO	0x39	/* hot temperature limit (low) */
-#define LM80_TOS_LIM_UP		0x3a	/* OS temperature limit (high) */
-#define LM80_TOS_LIM_LO		0x3b	/* OS temperature limit (low) */
-#define LM80_FAN1_COUNT_LIM	0x3c	/* Fan 1 count limit (high) */
-#define LM80_FAN2_COUNT_LIM	0x3d	/* Fan 2 count limit (low) */
-	/* 0x3e - 0x3f reserved	*/
-
-/*
- * LM80 bit definitions
- */
-
-/*	LM80_CFG		Configuration Register */
-#define LM80_CFG_START		(1<<0)	/* start monitoring operation */
-#define LM80_CFG_INT_ENA	(1<<1)	/* enables the INT# Interrupt output */
-#define LM80_CFG_INT_POL	(1<<2)	/* INT# pol: 0 act low, 1 act high */
-#define LM80_CFG_INT_CLR	(1<<3)	/* disables INT#/RST_OUT#/OS# outputs */
-#define LM80_CFG_RESET		(1<<4)	/* signals a reset */
-#define LM80_CFG_CHASS_CLR	(1<<5)	/* clears Chassis Intrusion (CI) pin */
-#define LM80_CFG_GPO		(1<<6)	/* drives the GPO# pin */
-#define LM80_CFG_INIT		(1<<7)	/* restore power on defaults */
-
-/*	LM80_ISRC_1		Interrupt Status Register 1 */
-/*	LM80_IMSK_1		Interrupt Mask Register 1 */
-#define LM80_IS_VT0			(1<<0)	/* limit exceeded for Voltage 0 */
-#define LM80_IS_VT1			(1<<1)	/* limit exceeded for Voltage 1 */
-#define LM80_IS_VT2			(1<<2)	/* limit exceeded for Voltage 2 */
-#define LM80_IS_VT3			(1<<3)	/* limit exceeded for Voltage 3 */
-#define LM80_IS_VT4			(1<<4)	/* limit exceeded for Voltage 4 */
-#define LM80_IS_VT5			(1<<5)	/* limit exceeded for Voltage 5 */
-#define LM80_IS_VT6			(1<<6)	/* limit exceeded for Voltage 6 */
-#define LM80_IS_INT_IN		(1<<7)	/* state of INT_IN# */
-
-/*	LM80_ISRC_2		Interrupt Status Register 2 */
-/*	LM80_IMSK_2		Interrupt Mask Register 2 */
-#define LM80_IS_TEMP		(1<<0)	/* HOT temperature limit exceeded */
-#define LM80_IS_BTI			(1<<1)	/* state of BTI# pin */
-#define LM80_IS_FAN1		(1<<2)	/* count limit exceeded for Fan 1 */
-#define LM80_IS_FAN2		(1<<3)	/* count limit exceeded for Fan 2 */
-#define LM80_IS_CI			(1<<4)	/* Chassis Intrusion occured */
-#define LM80_IS_OS			(1<<5)	/* OS temperature limit exceeded */
-	/* bit 6 and 7 are reserved in LM80_ISRC_2 */
-#define LM80_IS_HT_IRQ_MD	(1<<6)	/* Hot temperature interrupt mode */
-#define LM80_IS_OT_IRQ_MD	(1<<7)	/* OS temperature interrupt mode */
-
-/*	LM80_FAN_CTRL		Fan Devisor/RST#/OS# Register */
-#define LM80_FAN1_MD_SEL	(1<<0)	/* Fan 1 mode select */
-#define LM80_FAN2_MD_SEL	(1<<1)	/* Fan 2 mode select */
-#define LM80_FAN1_PRM_CTL	(3<<2)	/* Fan 1 speed control */
-#define LM80_FAN2_PRM_CTL	(3<<4)	/* Fan 2 speed control */
-#define LM80_FAN_OS_ENA		(1<<6)	/* enable OS mode on RST_OUT#/OS# pins*/
-#define LM80_FAN_RST_ENA	(1<<7)	/* sets RST_OUT#/OS# pins in RST mode */
-
-/*	LM80_TEMP_CTRL		OS# Config, Temp Res. Reg */
-#define LM80_TEMP_OS_STAT	(1<<0)	/* mirrors the state of RST_OUT#/OS# */
-#define LM80_TEMP_OS_POL	(1<<1)	/* select OS# polarity */
-#define LM80_TEMP_OS_MODE	(1<<2)	/* selects Interrupt mode */
-#define LM80_TEMP_RES		(1<<3)	/* selects 9 or 11 bit temp resulution*/
-#define LM80_TEMP_LSB		(0xf<<4)/* 4 LSBs of 11 bit temp data */
-#define LM80_TEMP_LSB_9		(1<<7)	/* LSB of 9 bit temperature data */
-
-	/* 0x07 - 0x1f reserved	*/
-/*	LM80_VT0_IN		current Voltage 0 value */
-/*	LM80_VT1_IN		current Voltage 1 value */
-/*	LM80_VT2_IN		current Voltage 2 value */
-/*	LM80_VT3_IN		current Voltage 3 value */
-/*	LM80_VT4_IN		current Voltage 4 value */
-/*	LM80_VT5_IN		current Voltage 5 value */
-/*	LM80_VT6_IN		current Voltage 6 value */
-/*	LM80_TEMP_IN		current temperature value */
-/*	LM80_FAN1_IN		current Fan 1 count */
-/*	LM80_FAN2_IN		current Fan 2 count */
-/*	LM80_VT0_HIGH_LIM	high limit val for Voltage 0 */
-/*	LM80_VT0_LOW_LIM	low limit val for Voltage 0 */
-/*	LM80_VT1_HIGH_LIM	high limit val for Voltage 1 */
-/*	LM80_VT1_LOW_LIM	low limit val for Voltage 1 */
-/*	LM80_VT2_HIGH_LIM	high limit val for Voltage 2 */
-/*	LM80_VT2_LOW_LIM	low limit val for Voltage 2 */
-/*	LM80_VT3_HIGH_LIM	high limit val for Voltage 3 */
-/*	LM80_VT3_LOW_LIM	low limit val for Voltage 3 */
-/*	LM80_VT4_HIGH_LIM	high limit val for Voltage 4 */
-/*	LM80_VT4_LOW_LIM	low limit val for Voltage 4 */
-/*	LM80_VT5_HIGH_LIM	high limit val for Voltage 5 */
-/*	LM80_VT5_LOW_LIM	low limit val for Voltage 5 */
-/*	LM80_VT6_HIGH_LIM	high limit val for Voltage 6 */
-/*	LM80_VT6_LOW_LIM	low limit val for Voltage 6 */
-/*	LM80_THOT_LIM_UP	hot temperature limit (high) */
-/*	LM80_THOT_LIM_LO	hot temperature limit (low) */
-/*	LM80_TOS_LIM_UP		OS temperature limit (high) */
-/*	LM80_TOS_LIM_LO		OS temperature limit (low) */
-/*	LM80_FAN1_COUNT_LIM	Fan 1 count limit (high) */
-/*	LM80_FAN2_COUNT_LIM	Fan 2 count limit (low) */
-	/* 0x3e - 0x3f reserved	*/
-
-#define LM80_ADDR		0x28	/* LM80 default addr */
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_LM80_H */
diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h
deleted file mode 100644
index 423ad06..0000000
--- a/drivers/net/sk98lin/h/skaddr.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/******************************************************************************
- *
- * Name:	skaddr.h
- * Project:	Gigabit Ethernet Adapters, ADDR-Modul
- * Version:	$Revision: 1.29 $
- * Date:	$Date: 2003/05/13 16:57:24 $
- * Purpose:	Header file for Address Management (MC, UC, Prom).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage multicast addresses and promiscuous mode
- * on GEnesis adapters.
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	...
- *	"sktypes.h"
- *	"skqueue.h"
- *	"skaddr.h"
- *	...
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKADDR_H
-#define __INC_SKADDR_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_MAC_ADDR_LEN				6	/* Length of MAC address. */
-#define	SK_MAX_ADDRS				14	/* #Addrs for exact match. */
-
-/* ----- Common return values ----- */
-
-#define SK_ADDR_SUCCESS				0	/* Function returned successfully. */
-#define SK_ADDR_ILLEGAL_PORT			100	/* Port number too high. */
-#define SK_ADDR_TOO_EARLY			101	/* Function called too early. */
-
-/* ----- Clear/Add flag bits ----- */
-
-#define SK_ADDR_PERMANENT			1	/* RLMT Address */
-
-/* ----- Additional Clear flag bits ----- */
-
-#define SK_MC_SW_ONLY				2	/* Do not update HW when clearing. */
-
-/* ----- Override flag bits ----- */
-
-#define SK_ADDR_LOGICAL_ADDRESS		0
-#define SK_ADDR_VIRTUAL_ADDRESS		(SK_ADDR_LOGICAL_ADDRESS)	/* old */
-#define SK_ADDR_PHYSICAL_ADDRESS	1
-#define SK_ADDR_CLEAR_LOGICAL		2
-#define SK_ADDR_SET_LOGICAL			4
-
-/* ----- Override return values ----- */
-
-#define SK_ADDR_OVERRIDE_SUCCESS	(SK_ADDR_SUCCESS)
-#define SK_ADDR_DUPLICATE_ADDRESS	1
-#define SK_ADDR_MULTICAST_ADDRESS	2
-
-/* ----- Partitioning of excact match table ----- */
-
-#define SK_ADDR_EXACT_MATCHES		16	/* #Exact match entries. */
-
-#define SK_ADDR_FIRST_MATCH_RLMT	1
-#define SK_ADDR_LAST_MATCH_RLMT		2
-#define SK_ADDR_FIRST_MATCH_DRV		3
-#define SK_ADDR_LAST_MATCH_DRV		(SK_ADDR_EXACT_MATCHES - 1)
-
-/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */
-
-#define SK_MC_FILTERING_EXACT		0	/* Exact filtering. */
-#define SK_MC_FILTERING_INEXACT		1	/* Inexact filtering. */
-
-/* ----- Additional SkAddrMcAdd return values ----- */
-
-#define SK_MC_ILLEGAL_ADDRESS		2	/* Illegal address. */
-#define SK_MC_ILLEGAL_PORT			3	/* Illegal port (not the active one). */
-#define SK_MC_RLMT_OVERFLOW			4	/* Too many RLMT mc addresses. */
-
-/* Promiscuous mode bits ----- */
-
-#define SK_PROM_MODE_NONE			0	/* Normal receive. */
-#define SK_PROM_MODE_LLC			1	/* Receive all LLC frames. */
-#define SK_PROM_MODE_ALL_MC			2	/* Receive all multicast frames. */
-/* #define SK_PROM_MODE_NON_LLC		4 */	/* Receive all non-LLC frames. */
-
-/* Macros */
-
-#ifdef OLD_STUFF
-#ifndef SK_ADDR_EQUAL
-/*
- * "&" instead of "&&" allows better optimization on IA-64.
- * The replacement is safe here, as all bytes exist.
- */
-#ifndef SK_ADDR_DWORD_COMPARE
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \
-	(((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \
-	(((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \
-	(((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \
-	(((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \
-	(((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0]))
-#else	/* SK_ADDR_DWORD_COMPARE */
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \
-	(*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0])))
-#endif	/* SK_ADDR_DWORD_COMPARE */
-#endif	/* SK_ADDR_EQUAL */
-#endif /* 0 */
-
-#ifndef SK_ADDR_EQUAL
-#ifndef SK_ADDR_DWORD_COMPARE
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \
-	(((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \
-	(((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \
-	(((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \
-	(((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \
-	(((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0]))
-#else	/* SK_ADDR_DWORD_COMPARE */
-#define SK_ADDR_EQUAL(A1,A2)	( \
-	(*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \
-	*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \
-	(*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \
-	*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0])))
-#endif	/* SK_ADDR_DWORD_COMPARE */
-#endif	/* SK_ADDR_EQUAL */
-
-/* typedefs *******************************************************************/
-
-typedef struct s_MacAddr {
-	SK_U8	a[SK_MAC_ADDR_LEN];
-} SK_MAC_ADDR;
-
-
-/* SK_FILTER is used to ensure alignment of the filter. */
-typedef union s_InexactFilter {
-	SK_U8	Bytes[8];
-	SK_U64	Val;	/* Dummy entry for alignment only. */
-} SK_FILTER64;
-
-
-typedef struct s_AddrNet SK_ADDR_NET;
-
-
-typedef struct s_AddrPort {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_MAC_ADDR	CurrentMacAddress;	/* Current physical MAC Address. */
-	SK_MAC_ADDR	PermanentMacAddress;	/* Permanent physical MAC Address. */
-	int		PromMode;		/* Promiscuous Mode. */
-
-/* ----- Private part ----- */
-
-	SK_MAC_ADDR	PreviousMacAddress;	/* Prev. phys. MAC Address. */
-	SK_BOOL		CurrentMacAddressSet;	/* CurrentMacAddress is set. */
-	SK_U8		Align01;
-
-	SK_U32		FirstExactMatchRlmt;
-	SK_U32		NextExactMatchRlmt;
-	SK_U32		FirstExactMatchDrv;
-	SK_U32		NextExactMatchDrv;
-	SK_MAC_ADDR	Exact[SK_ADDR_EXACT_MATCHES];
-	SK_FILTER64	InexactFilter;			/* For 64-bit hash register. */
-	SK_FILTER64	InexactRlmtFilter;		/* For 64-bit hash register. */
-	SK_FILTER64	InexactDrvFilter;		/* For 64-bit hash register. */
-} SK_ADDR_PORT;
-
-
-struct s_AddrNet {
-/* ----- Public part (read-only) ----- */
-
-	SK_MAC_ADDR		CurrentMacAddress;	/* Logical MAC Address. */
-	SK_MAC_ADDR		PermanentMacAddress;	/* Logical MAC Address. */
-
-/* ----- Private part ----- */
-
-	SK_U32			ActivePort;		/* View of module ADDR. */
-	SK_BOOL			CurrentMacAddressSet;	/* CurrentMacAddress is set. */
-	SK_U8			Align01;
-	SK_U16			Align02;
-};
-
-
-typedef struct s_Addr {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_ADDR_NET		Net[SK_MAX_NETS];
-	SK_ADDR_PORT	Port[SK_MAX_MACS];
-
-/* ----- Private part ----- */
-} SK_ADDR;
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_KR_PROTO
-
-/* Functions provided by SkAddr */
-
-/* ANSI/C++ compliant function prototypes */
-
-extern	int	SkAddrInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int	Level);
-
-extern	int	SkAddrMcClear(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	PortNumber,
-	int	Flags);
-
-extern	int	SkAddrMcAdd(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_U32		PortNumber,
-	SK_MAC_ADDR	*pMc,
-	int		Flags);
-
-extern	int	SkAddrMcUpdate(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	PortNumber);
-
-extern	int	SkAddrOverride(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_U32		PortNumber,
-	SK_MAC_ADDR	SK_FAR *pNewAddr,
-	int		Flags);
-
-extern	int	SkAddrPromiscuousChange(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	PortNumber,
-	int	NewPromMode);
-
-#ifndef SK_SLIM
-extern	int	SkAddrSwap(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	FromPortNumber,
-	SK_U32	ToPortNumber);
-#endif
-
-#else	/* defined(SK_KR_PROTO)) */
-
-/* Non-ANSI/C++ compliant function prototypes */
-
-#error KR-style prototypes are not yet provided.
-
-#endif	/* defined(SK_KR_PROTO)) */
-
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKADDR_H */
diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h
deleted file mode 100644
index 6e256bd..0000000
--- a/drivers/net/sk98lin/h/skcsum.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/******************************************************************************
- *
- * Name:	skcsum.h
- * Project:	GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx)
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/08/20 13:59:57 $
- * Purpose:	Store/verify Internet checksum in send/receive packets.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2001 SysKonnect GmbH.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * Public header file for the "GEnesis" common module "CSUM".
- *
- * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon"
- * and is the code name of this SysKonnect project.
- *
- * Compilation Options:
- *
- *	SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an
- *	empty module.
- *
- *	SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id
- *	definitions. In this case, all SKCS_PROTO_xxx definitions must be made
- *	external.
- *
- *	SKCS_OVERWRITE_STATUS - Define to overwrite the default return status
- *	definitions. In this case, all SKCS_STATUS_xxx definitions must be made
- *	external.
- *
- * Include File Hierarchy:
- *
- *	"h/skcsum.h"
- *	 "h/sktypes.h"
- *	 "h/skqueue.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKCSUM_H
-#define __INC_SKCSUM_H
-
-#include "h/sktypes.h"
-#include "h/skqueue.h"
-
-/* defines ********************************************************************/
-
-/*
- * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags'  if no user
- * overwrite.
- */
-#ifndef SKCS_OVERWRITE_PROTO	/* User overwrite? */
-#define SKCS_PROTO_IP	0x1	/* IP (Internet Protocol version 4) */
-#define SKCS_PROTO_TCP	0x2	/* TCP (Transmission Control Protocol) */
-#define SKCS_PROTO_UDP	0x4	/* UDP (User Datagram Protocol) */
-
-/* Indices for protocol statistics. */
-#define SKCS_PROTO_STATS_IP	0
-#define SKCS_PROTO_STATS_UDP	1
-#define SKCS_PROTO_STATS_TCP	2
-#define SKCS_NUM_PROTOCOLS	3	/* Number of supported protocols. */
-#endif	/* !SKCS_OVERWRITE_PROTO */
-
-/*
- * Define the default SKCS_STATUS type and values if no user overwrite.
- *
- *	SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
- *	SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
- *	SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
- *	SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
- *	SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
- *	SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
- *	SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
- *	SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
- *	SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
- *	SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
- *	SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. 
- */
-#ifndef SKCS_OVERWRITE_STATUS	/* User overwrite? */
-#define SKCS_STATUS	int	/* Define status type. */
-
-#define SKCS_STATUS_UNKNOWN_IP_VERSION	1
-#define SKCS_STATUS_IP_CSUM_ERROR		2
-#define SKCS_STATUS_IP_FRAGMENT			3
-#define SKCS_STATUS_IP_CSUM_OK			4
-#define SKCS_STATUS_TCP_CSUM_ERROR		5
-#define SKCS_STATUS_UDP_CSUM_ERROR		6
-#define SKCS_STATUS_TCP_CSUM_OK			7
-#define SKCS_STATUS_UDP_CSUM_OK			8
-/* needed for Microsoft */
-#define SKCS_STATUS_IP_CSUM_ERROR_UDP	9
-#define SKCS_STATUS_IP_CSUM_ERROR_TCP	10
-/* UDP checksum may be omitted */
-#define SKCS_STATUS_IP_CSUM_OK_NO_UDP	11
-#endif	/* !SKCS_OVERWRITE_STATUS */
-
-/* Clear protocol statistics event. */
-#define SK_CSUM_EVENT_CLEAR_PROTO_STATS	1
-
-/*
- * Add two values in one's complement.
- *
- * Note: One of the two input values may be "longer" than 16-bit, but then the
- * resulting sum may be 17 bits long. In this case, add zero to the result using
- * SKCS_OC_ADD() again.
- *
- *	Result = Value1 + Value2
- */
-#define SKCS_OC_ADD(Result, Value1, Value2) {				\
-	unsigned long Sum;						\
-									\
-	Sum = (unsigned long) (Value1) + (unsigned long) (Value2);	\
-	/* Add-in any carry. */						\
-	(Result) = (Sum & 0xffff) + (Sum >> 16);			\
-}
-
-/*
- * Subtract two values in one's complement.
- *
- *	Result = Value1 - Value2
- */
-#define SKCS_OC_SUB(Result, Value1, Value2)	\
-	SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff)
-
-/* typedefs *******************************************************************/
-
-/*
- * SKCS_PROTO_STATS - The CSUM protocol statistics structure.
- *
- * There is one instance of this structure for each protocol supported.
- */
-typedef struct s_CsProtocolStatistics {
-	SK_U64 RxOkCts;		/* Receive checksum ok. */
-	SK_U64 RxUnableCts;	/* Unable to verify receive checksum. */
-	SK_U64 RxErrCts;	/* Receive checksum error. */
-	SK_U64 TxOkCts;		/* Transmit checksum ok. */
-	SK_U64 TxUnableCts;	/* Unable to calculate checksum in hw. */
-} SKCS_PROTO_STATS;
-
-/*
- * s_Csum - The CSUM module context structure.
- */
-typedef struct s_Csum {
-	/* Enabled receive SK_PROTO_XXX bit flags. */
-	unsigned ReceiveFlags[SK_MAX_NETS];
-#ifdef TX_CSUM
-	unsigned TransmitFlags[SK_MAX_NETS];
-#endif /* TX_CSUM */
-
-	/* The protocol statistics structure; one per supported protocol. */
-	SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS];
-} SK_CSUM;
-
-/*
- * SKCS_PACKET_INFO - The packet information structure.
- */
-typedef struct s_CsPacketInfo {
-	/* Bit field specifiying the desired/found protocols. */
-	unsigned ProtocolFlags;
-
-	/* Length of complete IP header, including any option fields. */
-	unsigned IpHeaderLength;
-
-	/* IP header checksum. */
-	unsigned IpHeaderChecksum;
-
-	/* TCP/UDP pseudo header checksum. */
-	unsigned PseudoHeaderChecksum;
-} SKCS_PACKET_INFO;
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_CS_CALCULATE_CHECKSUM
-extern unsigned SkCsCalculateChecksum(
-	void		*pData,
-	unsigned	Length);
-#endif /* SK_CS_CALCULATE_CHECKSUM */
-
-extern int SkCsEvent(
-	SK_AC		*pAc,
-	SK_IOC		Ioc,
-	SK_U32		Event,
-	SK_EVPARA	Param);
-
-extern SKCS_STATUS SkCsGetReceiveInfo(
-	SK_AC		*pAc,
-	void		*pIpHeader,
-	unsigned	Checksum1,
-	unsigned	Checksum2,
-	int			NetNumber);
-
-extern void SkCsSetReceiveFlags(
-	SK_AC		*pAc,
-	unsigned	ReceiveFlags,
-	unsigned	*pChecksum1Offset,
-	unsigned	*pChecksum2Offset,
-	int			NetNumber);
-
-#endif	/* __INC_SKCSUM_H */
diff --git a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h
deleted file mode 100644
index 3cba171..0000000
--- a/drivers/net/sk98lin/h/skdebug.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdebug.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.14 $
- * Date:	$Date: 2003/05/13 17:26:00 $
- * Purpose:	SK specific DEBUG support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDEBUG_H
-#define __INC_SKDEBUG_H
-
-#ifdef	DEBUG
-#ifndef SK_DBG_MSG
-#define SK_DBG_MSG(pAC,comp,cat,arg) \
-		if ( ((comp) & SK_DBG_CHKMOD(pAC)) && 	\
-		      ((cat) & SK_DBG_CHKCAT(pAC)) ) { 	\
-			SK_DBG_PRINTF arg ;		\
-		}
-#endif
-#else
-#define SK_DBG_MSG(pAC,comp,lev,arg)
-#endif
-
-/* PLS NOTE:
- * =========
- * Due to any restrictions of kernel printf routines do not use other
- * format identifiers as: %x %d %c %s .
- * Never use any combined format identifiers such as: %lx %ld in your
- * printf - argument (arg) because some OS specific kernel printfs may
- * only support some basic identifiers.
- */
-
-/* Debug modules */
-
-#define SK_DBGMOD_MERR	0x00000001L	/* general module error indication */
-#define SK_DBGMOD_HWM	0x00000002L	/* Hardware init module */
-#define SK_DBGMOD_RLMT	0x00000004L	/* RLMT module */
-#define SK_DBGMOD_VPD	0x00000008L	/* VPD module */
-#define SK_DBGMOD_I2C	0x00000010L	/* I2C module */
-#define SK_DBGMOD_PNMI	0x00000020L	/* PNMI module */
-#define SK_DBGMOD_CSUM	0x00000040L	/* CSUM module */
-#define SK_DBGMOD_ADDR	0x00000080L	/* ADDR module */
-#define SK_DBGMOD_PECP	0x00000100L	/* PECP module */
-#define SK_DBGMOD_POWM	0x00000200L	/* Power Management module */
-
-/* Debug events */
-
-#define SK_DBGCAT_INIT	0x00000001L	/* module/driver initialization */
-#define SK_DBGCAT_CTRL	0x00000002L	/* controlling devices */
-#define SK_DBGCAT_ERR	0x00000004L	/* error handling paths */
-#define SK_DBGCAT_TX	0x00000008L	/* transmit path */
-#define SK_DBGCAT_RX	0x00000010L	/* receive path */
-#define SK_DBGCAT_IRQ	0x00000020L	/* general IRQ handling */
-#define SK_DBGCAT_QUEUE	0x00000040L	/* any queue management */
-#define SK_DBGCAT_DUMP	0x00000080L	/* large data output e.g. hex dump */
-#define SK_DBGCAT_FATAL	0x00000100L	/* fatal error */
-
-#endif	/* __INC_SKDEBUG_H */
diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
deleted file mode 100644
index 91b8d4f..0000000
--- a/drivers/net/sk98lin/h/skdrv1st.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdrv1st.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.4 $
- * Date:	$Date: 2003/11/12 14:28:14 $
- * Purpose:	First header file for driver and all other modules
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the first include file of the driver, which includes all
- * neccessary system header files and some of the GEnesis header files.
- * It also defines some basic items.
- *
- * Include File Hierarchy:
- *
- *	see skge.c
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDRV1ST_H
-#define __INC_SKDRV1ST_H
-
-typedef struct s_AC	SK_AC;
-
-/* Set card versions */
-#define SK_FAR
-
-/* override some default functions with optimized linux functions */
-
-#define SK_PNMI_STORE_U16(p,v)		memcpy((char*)(p),(char*)&(v),2)
-#define SK_PNMI_STORE_U32(p,v)		memcpy((char*)(p),(char*)&(v),4)
-#define SK_PNMI_STORE_U64(p,v)		memcpy((char*)(p),(char*)&(v),8)
-#define SK_PNMI_READ_U16(p,v)		memcpy((char*)&(v),(char*)(p),2)
-#define SK_PNMI_READ_U32(p,v)		memcpy((char*)&(v),(char*)(p),4)
-#define SK_PNMI_READ_U64(p,v)		memcpy((char*)&(v),(char*)(p),8)
-
-#define SK_ADDR_EQUAL(a1,a2)		(!memcmp(a1,a2,6))
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <net/checksum.h>
-
-#define SK_CS_CALCULATE_CHECKSUM
-#ifndef CONFIG_X86_64
-#define SkCsCalculateChecksum(p,l)	((~ip_compute_csum(p, l)) & 0xffff)
-#else
-#define SkCsCalculateChecksum(p,l)	((~ip_fast_csum(p, l)) & 0xffff)
-#endif
-
-#include	"h/sktypes.h"
-#include	"h/skerror.h"
-#include	"h/skdebug.h"
-#include	"h/lm80.h"
-#include	"h/xmac_ii.h"
-
-#ifdef __LITTLE_ENDIAN
-#define SK_LITTLE_ENDIAN
-#else
-#define SK_BIG_ENDIAN
-#endif
-
-#define SK_NET_DEVICE	net_device
-
-
-/* we use gethrtime(), return unit: nanoseconds */
-#define SK_TICKS_PER_SEC	100
-
-#define	SK_MEM_MAPPED_IO
-
-// #define SK_RLMT_SLOW_LOOKAHEAD
-
-#define SK_MAX_MACS		2
-#define SK_MAX_NETS		2
-
-#define SK_IOC			char __iomem *
-
-typedef struct s_DrvRlmtMbuf SK_MBUF;
-
-#define	SK_CONST64	INT64_C
-#define	SK_CONSTU64	UINT64_C
-
-#define SK_MEMCPY(dest,src,size)	memcpy(dest,src,size)
-#define SK_MEMCMP(s1,s2,size)		memcmp(s1,s2,size)
-#define SK_MEMSET(dest,val,size)	memset(dest,val,size)
-#define SK_STRLEN(pStr)			strlen((char*)(pStr))
-#define SK_STRNCPY(pDest,pSrc,size)	strncpy((char*)(pDest),(char*)(pSrc),size)
-#define SK_STRCMP(pStr1,pStr2)		strcmp((char*)(pStr1),(char*)(pStr2))
-
-/* macros to access the adapter */
-#define SK_OUT8(b,a,v)		writeb((v), ((b)+(a)))	
-#define SK_OUT16(b,a,v)		writew((v), ((b)+(a)))	
-#define SK_OUT32(b,a,v)		writel((v), ((b)+(a)))	
-#define SK_IN8(b,a,pv)		(*(pv) = readb((b)+(a)))
-#define SK_IN16(b,a,pv)		(*(pv) = readw((b)+(a)))
-#define SK_IN32(b,a,pv)		(*(pv) = readl((b)+(a)))
-
-#define int8_t		char
-#define int16_t		short
-#define int32_t		long
-#define int64_t		long long
-#define uint8_t		u_char
-#define uint16_t	u_short
-#define uint32_t	u_long
-#define uint64_t	unsigned long long
-#define t_scalar_t	int
-#define t_uscalar_t	unsigned int
-#define uintptr_t	unsigned long
-
-#define __CONCAT__(A,B) A##B
-
-#define INT32_C(a)		__CONCAT__(a,L)
-#define INT64_C(a)		__CONCAT__(a,LL)
-#define UINT32_C(a)		__CONCAT__(a,UL)
-#define UINT64_C(a)		__CONCAT__(a,ULL)
-
-#ifdef DEBUG
-#define SK_DBG_PRINTF		printk
-#ifndef SK_DEBUG_CHKMOD
-#define SK_DEBUG_CHKMOD		0
-#endif
-#ifndef SK_DEBUG_CHKCAT
-#define SK_DEBUG_CHKCAT		0
-#endif
-/* those come from the makefile */
-#define SK_DBG_CHKMOD(pAC)	(SK_DEBUG_CHKMOD)
-#define SK_DBG_CHKCAT(pAC)	(SK_DEBUG_CHKCAT)
-
-extern void SkDbgPrintf(const char *format,...);
-
-#define SK_DBGMOD_DRV			0x00010000
-
-/**** possible driver debug categories ********************************/
-#define SK_DBGCAT_DRV_ENTRY		0x00010000
-#define SK_DBGCAT_DRV_SAP		0x00020000
-#define SK_DBGCAT_DRV_MCA		0x00040000
-#define SK_DBGCAT_DRV_TX_PROGRESS	0x00080000
-#define SK_DBGCAT_DRV_RX_PROGRESS	0x00100000
-#define SK_DBGCAT_DRV_PROGRESS		0x00200000
-#define SK_DBGCAT_DRV_MSG		0x00400000
-#define SK_DBGCAT_DRV_PROM		0x00800000
-#define SK_DBGCAT_DRV_TX_FRAME		0x01000000
-#define SK_DBGCAT_DRV_ERROR		0x02000000
-#define SK_DBGCAT_DRV_INT_SRC		0x04000000
-#define SK_DBGCAT_DRV_EVENT		0x08000000
-
-#endif
-
-#define SK_ERR_LOG		SkErrorLog
-
-extern void SkErrorLog(SK_AC*, int, int, char*);
-
-#endif
-
diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
deleted file mode 100644
index 3fa6717..0000000
--- a/drivers/net/sk98lin/h/skdrv2nd.h
+++ /dev/null
@@ -1,447 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdrv2nd.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/12/11 16:04:45 $
- * Purpose:	Second header file for driver and all other modules
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the second include file of the driver, which includes all other
- * neccessary files and defines all structures and constants used by the
- * driver and the common modules.
- *
- * Include File Hierarchy:
- *
- *	see skge.c
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDRV2ND_H
-#define __INC_SKDRV2ND_H
-
-#include "h/skqueue.h"
-#include "h/skgehwt.h"
-#include "h/sktimer.h"
-#include "h/ski2c.h"
-#include "h/skgepnmi.h"
-#include "h/skvpd.h"
-#include "h/skgehw.h"
-#include "h/skgeinit.h"
-#include "h/skaddr.h"
-#include "h/skgesirq.h"
-#include "h/skcsum.h"
-#include "h/skrlmt.h"
-#include "h/skgedrv.h"
-
-
-extern SK_MBUF		*SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
-extern void		SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
-extern SK_U64		SkOsGetTime(SK_AC*);
-extern int		SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
-extern int		SkPciReadCfgWord(SK_AC*, int, SK_U16*);
-extern int		SkPciReadCfgByte(SK_AC*, int, SK_U8*);
-extern int		SkPciWriteCfgWord(SK_AC*, int, SK_U16);
-extern int		SkPciWriteCfgByte(SK_AC*, int, SK_U8);
-extern int		SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
-
-#ifdef SK_DIAG_SUPPORT
-extern int		SkDrvEnterDiagMode(SK_AC *pAc);
-extern int		SkDrvLeaveDiagMode(SK_AC *pAc);
-#endif
-
-struct s_DrvRlmtMbuf {
-	SK_MBUF		*pNext;		/* Pointer to next RLMT Mbuf. */
-	SK_U8		*pData;		/* Data buffer (virtually contig.). */
-	unsigned	Size;		/* Data buffer size. */
-	unsigned	Length;		/* Length of packet (<= Size). */
-	SK_U32		PortIdx;	/* Receiving/transmitting port. */
-#ifdef SK_RLMT_MBUF_PRIVATE
-	SK_RLMT_MBUF	Rlmt;		/* Private part for RLMT. */
-#endif  /* SK_RLMT_MBUF_PRIVATE */
-	struct sk_buff	*pOs;		/* Pointer to message block */
-};
-
-
-/*
- * Time macros
- */
-#if SK_TICKS_PER_SEC == 100
-#define SK_PNMI_HUNDREDS_SEC(t)	(t)
-#else
-#define SK_PNMI_HUNDREDS_SEC(t)	((((unsigned long)t) * 100) / \
-										(SK_TICKS_PER_SEC))
-#endif
-
-/*
- * New SkOsGetTime
- */
-#define SkOsGetTimeCurrent(pAC, pUsec) {\
-	struct timeval t;\
-	do_gettimeofday(&t);\
-	*pUsec = ((((t.tv_sec) * 1000000L)+t.tv_usec)/10000);\
-}
-
-
-/*
- * ioctl definitions
- */
-#define		SK_IOCTL_BASE		(SIOCDEVPRIVATE)
-#define		SK_IOCTL_GETMIB		(SK_IOCTL_BASE + 0)
-#define		SK_IOCTL_SETMIB		(SK_IOCTL_BASE + 1)
-#define		SK_IOCTL_PRESETMIB	(SK_IOCTL_BASE + 2)
-#define		SK_IOCTL_GEN		(SK_IOCTL_BASE + 3)
-#define		SK_IOCTL_DIAG		(SK_IOCTL_BASE + 4)
-
-typedef struct s_IOCTL	SK_GE_IOCTL;
-
-struct s_IOCTL {
-	char __user *	pData;
-	unsigned int	Len;
-};
-
-
-/*
- * define sizes of descriptor rings in bytes
- */
-
-#define		TX_RING_SIZE	(8*1024)
-#define		RX_RING_SIZE	(24*1024)
-
-/*
- * Buffer size for ethernet packets
- */
-#define	ETH_BUF_SIZE	1540
-#define	ETH_MAX_MTU	1514
-#define ETH_MIN_MTU	60
-#define ETH_MULTICAST_BIT	0x01
-#define SK_JUMBO_MTU	9000
-
-/*
- * transmit priority selects the queue: LOW=asynchron, HIGH=synchron
- */
-#define TX_PRIO_LOW	0
-#define TX_PRIO_HIGH	1
-
-/*
- * alignment of rx/tx descriptors
- */
-#define DESCR_ALIGN	64
-
-/*
- * definitions for pnmi. TODO
- */
-#define SK_DRIVER_RESET(pAC, IoC)	0
-#define SK_DRIVER_SENDEVENT(pAC, IoC)	0
-#define SK_DRIVER_SELFTEST(pAC, IoC)	0
-/* For get mtu you must add an own function */
-#define SK_DRIVER_GET_MTU(pAc,IoC,i)	0
-#define SK_DRIVER_SET_MTU(pAc,IoC,i,v)	0
-#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v)	0
-
-/*
-** Interim definition of SK_DRV_TIMER placed in this file until 
-** common modules have been finalized
-*/
-#define SK_DRV_TIMER			11 
-#define	SK_DRV_MODERATION_TIMER		1
-#define SK_DRV_MODERATION_TIMER_LENGTH  1000000  /* 1 second */
-#define SK_DRV_RX_CLEANUP_TIMER		2
-#define SK_DRV_RX_CLEANUP_TIMER_LENGTH	1000000	 /* 100 millisecs */
-
-/*
-** Definitions regarding transmitting frames 
-** any calculating any checksum.
-*/
-#define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6
-#define C_LEN_ETHERMAC_HEADER_SRC_ADDR  6
-#define C_LEN_ETHERMAC_HEADER_LENTYPE   2
-#define C_LEN_ETHERMAC_HEADER           ( (C_LEN_ETHERMAC_HEADER_DEST_ADDR) + \
-                                          (C_LEN_ETHERMAC_HEADER_SRC_ADDR)  + \
-                                          (C_LEN_ETHERMAC_HEADER_LENTYPE) )
-
-#define C_LEN_ETHERMTU_MINSIZE          46
-#define C_LEN_ETHERMTU_MAXSIZE_STD      1500
-#define C_LEN_ETHERMTU_MAXSIZE_JUMBO    9000
-
-#define C_LEN_ETHERNET_MINSIZE          ( (C_LEN_ETHERMAC_HEADER) + \
-                                          (C_LEN_ETHERMTU_MINSIZE) )
-
-#define C_OFFSET_IPHEADER               C_LEN_ETHERMAC_HEADER
-#define C_OFFSET_IPHEADER_IPPROTO       9
-#define C_OFFSET_TCPHEADER_TCPCS        16
-#define C_OFFSET_UDPHEADER_UDPCS        6
-
-#define C_OFFSET_IPPROTO                ( (C_LEN_ETHERMAC_HEADER) + \
-                                          (C_OFFSET_IPHEADER_IPPROTO) )
-
-#define C_PROTO_ID_UDP                  17       /* refer to RFC 790 or Stevens'   */
-#define C_PROTO_ID_TCP                  6        /* TCP/IP illustrated for details */
-
-/* TX and RX descriptors *****************************************************/
-
-typedef struct s_RxD RXD; /* the receive descriptor */
-
-struct s_RxD {
-	volatile SK_U32	RBControl;	/* Receive Buffer Control */
-	SK_U32		VNextRxd;	/* Next receive descriptor,low dword */
-	SK_U32		VDataLow;	/* Receive buffer Addr, low dword */
-	SK_U32		VDataHigh;	/* Receive buffer Addr, high dword */
-	SK_U32		FrameStat;	/* Receive Frame Status word */
-	SK_U32		TimeStamp;	/* Time stamp from XMAC */
-	SK_U32		TcpSums;	/* TCP Sum 2 / TCP Sum 1 */
-	SK_U32		TcpSumStarts;	/* TCP Sum Start 2 / TCP Sum Start 1 */
-	RXD		*pNextRxd;	/* Pointer to next Rxd */
-	struct sk_buff	*pMBuf;		/* Pointer to Linux' socket buffer */
-};
-
-typedef struct s_TxD TXD; /* the transmit descriptor */
-
-struct s_TxD {
-	volatile SK_U32	TBControl;	/* Transmit Buffer Control */
-	SK_U32		VNextTxd;	/* Next transmit descriptor,low dword */
-	SK_U32		VDataLow;	/* Transmit Buffer Addr, low dword */
-	SK_U32		VDataHigh;	/* Transmit Buffer Addr, high dword */
-	SK_U32		FrameStat;	/* Transmit Frame Status Word */
-	SK_U32		TcpSumOfs;	/* Reserved / TCP Sum Offset */
-	SK_U16		TcpSumSt;	/* TCP Sum Start */
-	SK_U16		TcpSumWr;	/* TCP Sum Write */
-	SK_U32		TcpReserved;	/* not used */
-	TXD		*pNextTxd;	/* Pointer to next Txd */
-	struct sk_buff	*pMBuf;		/* Pointer to Linux' socket buffer */
-};
-
-/* Used interrupt bits in the interrupts source register *********************/
-
-#define DRIVER_IRQS	((IS_IRQ_SW)   | \
-			(IS_R1_F)      |(IS_R2_F)  | \
-			(IS_XS1_F)     |(IS_XA1_F) | \
-			(IS_XS2_F)     |(IS_XA2_F))
-
-#define SPECIAL_IRQS	((IS_HW_ERR)   |(IS_I2C_READY)  | \
-			(IS_EXT_REG)   |(IS_TIMINT)     | \
-			(IS_PA_TO_RX1) |(IS_PA_TO_RX2)  | \
-			(IS_PA_TO_TX1) |(IS_PA_TO_TX2)  | \
-			(IS_MAC1)      |(IS_LNK_SYNC_M1)| \
-			(IS_MAC2)      |(IS_LNK_SYNC_M2)| \
-			(IS_R1_C)      |(IS_R2_C)       | \
-			(IS_XS1_C)     |(IS_XA1_C)      | \
-			(IS_XS2_C)     |(IS_XA2_C))
-
-#define IRQ_MASK	((IS_IRQ_SW)   | \
-			(IS_R1_B)      |(IS_R1_F)     |(IS_R2_B) |(IS_R2_F) | \
-			(IS_XS1_B)     |(IS_XS1_F)    |(IS_XA1_B)|(IS_XA1_F)| \
-			(IS_XS2_B)     |(IS_XS2_F)    |(IS_XA2_B)|(IS_XA2_F)| \
-			(IS_HW_ERR)    |(IS_I2C_READY)| \
-			(IS_EXT_REG)   |(IS_TIMINT)   | \
-			(IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \
-			(IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \
-			(IS_MAC1)      |(IS_MAC2)     | \
-			(IS_R1_C)      |(IS_R2_C)     | \
-			(IS_XS1_C)     |(IS_XA1_C)    | \
-			(IS_XS2_C)     |(IS_XA2_C))
-
-#define IRQ_HWE_MASK	(IS_ERR_MSK) /* enable all HW irqs */
-
-typedef struct s_DevNet DEV_NET;
-
-struct s_DevNet {
-	int             PortNr;
-	int             NetNr;
-	SK_AC   *pAC;
-};  
-
-typedef struct s_TxPort		TX_PORT;
-
-struct s_TxPort {
-	/* the transmit descriptor rings */
-	caddr_t		pTxDescrRing;	/* descriptor area memory */
-	SK_U64		VTxDescrRing;	/* descr. area bus virt. addr. */
-	TXD		*pTxdRingHead;	/* Head of Tx rings */
-	TXD		*pTxdRingTail;	/* Tail of Tx rings */
-	TXD		*pTxdRingPrev;	/* descriptor sent previously */
-	int		TxdRingFree;	/* # of free entrys */
-	spinlock_t	TxDesRingLock;	/* serialize descriptor accesses */
-	SK_IOC		HwAddr;		/* bmu registers address */
-	int		PortIndex;	/* index number of port (0 or 1) */
-};
-
-typedef struct s_RxPort		RX_PORT;
-
-struct s_RxPort {
-	/* the receive descriptor rings */
-	caddr_t		pRxDescrRing;	/* descriptor area memory */
-	SK_U64		VRxDescrRing;   /* descr. area bus virt. addr. */
-	RXD		*pRxdRingHead;	/* Head of Rx rings */
-	RXD		*pRxdRingTail;	/* Tail of Rx rings */
-	RXD		*pRxdRingPrev;	/* descriptor given to BMU previously */
-	int		RxdRingFree;	/* # of free entrys */
-	int		RxCsum;		/* use receive checksum hardware */
-	spinlock_t	RxDesRingLock;	/* serialize descriptor accesses */
-	int		RxFillLimit;	/* limit for buffers in ring */
-	SK_IOC		HwAddr;		/* bmu registers address */
-	int		PortIndex;	/* index number of port (0 or 1) */
-};
-
-/* Definitions needed for interrupt moderation *******************************/
-
-#define IRQ_EOF_AS_TX     ((IS_XA1_F)     | (IS_XA2_F))
-#define IRQ_EOF_SY_TX     ((IS_XS1_F)     | (IS_XS2_F))
-#define IRQ_MASK_TX_ONLY  ((IRQ_EOF_AS_TX)| (IRQ_EOF_SY_TX))
-#define IRQ_MASK_RX_ONLY  ((IS_R1_F)      | (IS_R2_F))
-#define IRQ_MASK_SP_ONLY  (SPECIAL_IRQS)
-#define IRQ_MASK_TX_RX    ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY))
-#define IRQ_MASK_SP_RX    ((SPECIAL_IRQS)    | (IRQ_MASK_RX_ONLY))
-#define IRQ_MASK_SP_TX    ((SPECIAL_IRQS)    | (IRQ_MASK_TX_ONLY))
-#define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS)    | (IRQ_MASK_TX_RX))
-
-#define C_INT_MOD_NONE                 1
-#define C_INT_MOD_STATIC               2
-#define C_INT_MOD_DYNAMIC              4
-
-#define C_CLK_FREQ_GENESIS      53215000 /* shorter: 53.125 MHz  */
-#define C_CLK_FREQ_YUKON        78215000 /* shorter: 78.125 MHz  */
-
-#define C_INTS_PER_SEC_DEFAULT      2000 
-#define C_INT_MOD_ENABLE_PERCENTAGE   50 /* if higher 50% enable */
-#define C_INT_MOD_DISABLE_PERCENTAGE  50 /* if lower 50% disable */
-#define C_INT_MOD_IPS_LOWER_RANGE     30
-#define C_INT_MOD_IPS_UPPER_RANGE     40000
-
-
-typedef struct s_DynIrqModInfo  DIM_INFO;
-struct s_DynIrqModInfo {
-	unsigned long   PrevTimeVal;
-	unsigned int    PrevSysLoad;
-	unsigned int    PrevUsedTime;
-	unsigned int    PrevTotalTime;
-	int             PrevUsedDescrRatio;
-	int             NbrProcessedDescr;
-        SK_U64          PrevPort0RxIntrCts;
-        SK_U64          PrevPort1RxIntrCts;
-        SK_U64          PrevPort0TxIntrCts;
-        SK_U64          PrevPort1TxIntrCts;
-	SK_BOOL         ModJustEnabled;     /* Moderation just enabled yes/no */
-
-	int             MaxModIntsPerSec;            /* Moderation Threshold */
-	int             MaxModIntsPerSecUpperLimit;  /* Upper limit for DIM  */
-	int             MaxModIntsPerSecLowerLimit;  /* Lower limit for DIM  */
-
-	long            MaskIrqModeration;   /* ModIrqType (eg. 'TxRx')      */
-	SK_BOOL         DisplayStats;        /* Stats yes/no                 */
-	SK_BOOL         AutoSizing;          /* Resize DIM-timer on/off      */
-	int             IntModTypeSelect;    /* EnableIntMod (eg. 'dynamic') */
-
-	SK_TIMER        ModTimer; /* just some timer */
-};
-
-typedef struct s_PerStrm	PER_STRM;
-
-#define SK_ALLOC_IRQ	0x00000001
-
-#ifdef SK_DIAG_SUPPORT
-#define	DIAG_ACTIVE		1
-#define	DIAG_NOTACTIVE		0
-#endif
-
-/****************************************************************************
- * Per board structure / Adapter Context structure:
- *	Allocated within attach(9e) and freed within detach(9e).
- *	Contains all 'per device' necessary handles, flags, locks etc.:
- */
-struct s_AC  {
-	SK_GEINIT	GIni;		/* GE init struct */
-	SK_PNMI		Pnmi;		/* PNMI data struct */
-	SK_VPD		vpd;		/* vpd data struct */
-	SK_QUEUE	Event;		/* Event queue */
-	SK_HWT		Hwt;		/* Hardware Timer control struct */
-	SK_TIMCTRL	Tim;		/* Software Timer control struct */
-	SK_I2C		I2c;		/* I2C relevant data structure */
-	SK_ADDR		Addr;		/* for Address module */
-	SK_CSUM		Csum;		/* for checksum module */
-	SK_RLMT		Rlmt;		/* for rlmt module */
-	spinlock_t	SlowPathLock;	/* Normal IRQ lock */
-	struct timer_list BlinkTimer;	/* for LED blinking */
-	int		LedsOn;
-	SK_PNMI_STRUCT_DATA PnmiStruct;	/* structure to get all Pnmi-Data */
-	int			RlmtMode;	/* link check mode to set */
-	int			RlmtNets;	/* Number of nets */
-	
-	SK_IOC		IoBase;		/* register set of adapter */
-	int		BoardLevel;	/* level of active hw init (0-2) */
-
-	SK_U32		AllocFlag;	/* flag allocation of resources */
-	struct pci_dev	*PciDev;	/* for access to pci config space */
-	struct SK_NET_DEVICE	*dev[2];	/* pointer to device struct */
-
-	int		RxBufSize;	/* length of receive buffers */
-        struct net_device_stats stats;	/* linux 'netstat -i' statistics */
-	int		Index;		/* internal board index number */
-
-	/* adapter RAM sizes for queues of active port */
-	int		RxQueueSize;	/* memory used for receive queue */
-	int		TxSQueueSize;	/* memory used for sync. tx queue */
-	int		TxAQueueSize;	/* memory used for async. tx queue */
-
-	int		PromiscCount;	/* promiscuous mode counter  */
-	int		AllMultiCount;  /* allmulticast mode counter */
-	int		MulticCount;	/* number of different MC    */
-					/*  addresses for this board */
-					/*  (may be more than HW can)*/
-
-	int		HWRevision;	/* Hardware revision */
-	int		ActivePort;	/* the active XMAC port */
-	int		MaxPorts;		/* number of activated ports */
-	int		TxDescrPerRing;	/* # of descriptors per tx ring */
-	int		RxDescrPerRing;	/* # of descriptors per rx ring */
-
-	caddr_t		pDescrMem;	/* Pointer to the descriptor area */
-	dma_addr_t	pDescrMemDMA;	/* PCI DMA address of area */
-
-	/* the port structures with descriptor rings */
-	TX_PORT		TxPort[SK_MAX_MACS][2];
-	RX_PORT		RxPort[SK_MAX_MACS];
-
-	SK_BOOL		CheckQueue;	/* check event queue soon */
-	SK_TIMER        DrvCleanupTimer;/* to check for pending descriptors */
-	DIM_INFO        DynIrqModInfo;  /* all data related to DIM */
-
-	/* Only for tests */
-	int		PortDown;
-	int		ChipsetType;	/*  Chipset family type 
-					 *  0 == Genesis family support
-					 *  1 == Yukon family support
-					 */
-#ifdef SK_DIAG_SUPPORT
-	SK_U32		DiagModeActive;		/* is diag active?	*/
-	SK_BOOL		DiagFlowCtrl;		/* for control purposes	*/
-	SK_PNMI_STRUCT_DATA PnmiBackup;		/* backup structure for all Pnmi-Data */
-	SK_BOOL         WasIfUp[SK_MAX_MACS];   /* for OpenClose while 
-						 * DIAG is busy with NIC 
-						 */
-#endif
-
-};
-
-
-#endif /* __INC_SKDRV2ND_H */
-
diff --git a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h
deleted file mode 100644
index da062f7..0000000
--- a/drivers/net/sk98lin/h/skerror.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/******************************************************************************
- *
- * Name:	skerror.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.7 $
- * Date:	$Date: 2003/05/13 17:25:13 $
- * Purpose:	SK specific Error log support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _INC_SKERROR_H_
-#define _INC_SKERROR_H_
-
-/*
- * Define Error Classes
- */
-#define	SK_ERRCL_OTHER		(0)		/* Other error */
-#define	SK_ERRCL_CONFIG		(1L<<0)	/* Configuration error */
-#define	SK_ERRCL_INIT		(1L<<1)	/* Initialization error */
-#define	SK_ERRCL_NORES		(1L<<2)	/* Out of Resources error */
-#define	SK_ERRCL_SW			(1L<<3)	/* Internal Software error */
-#define	SK_ERRCL_HW			(1L<<4)	/* Hardware Failure */
-#define	SK_ERRCL_COMM		(1L<<5)	/* Communication error */
-
-
-/*
- * Define Error Code Bases
- */
-#define	SK_ERRBASE_RLMT		 100	/* Base Error number for RLMT */
-#define	SK_ERRBASE_HWINIT	 200	/* Base Error number for HWInit */
-#define	SK_ERRBASE_VPD		 300	/* Base Error number for VPD */
-#define	SK_ERRBASE_PNMI		 400	/* Base Error number for PNMI */
-#define	SK_ERRBASE_CSUM		 500	/* Base Error number for Checksum */
-#define	SK_ERRBASE_SIRQ		 600	/* Base Error number for Special IRQ */
-#define	SK_ERRBASE_I2C		 700	/* Base Error number for I2C module */
-#define	SK_ERRBASE_QUEUE	 800	/* Base Error number for Scheduler */
-#define	SK_ERRBASE_ADDR		 900	/* Base Error number for Address module */
-#define SK_ERRBASE_PECP		1000    /* Base Error number for PECP */
-#define	SK_ERRBASE_DRV		1100	/* Base Error number for Driver */
-
-#endif	/* _INC_SKERROR_H_ */
diff --git a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h
deleted file mode 100644
index 44fd4c3..0000000
--- a/drivers/net/sk98lin/h/skgedrv.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgedrv.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.10 $
- * Date:	$Date: 2003/07/04 12:25:01 $
- * Purpose:	Interface with the driver
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEDRV_H_
-#define __INC_SKGEDRV_H_
-
-/* defines ********************************************************************/
-
-/*
- * Define the driver events.
- * Usually the events are defined by the destination module.
- * In case of the driver we put the definition of the events here.
- */
-#define SK_DRV_PORT_RESET		 1	/* The port needs to be reset */
-#define SK_DRV_NET_UP   		 2	/* The net is operational */
-#define SK_DRV_NET_DOWN			 3	/* The net is down */
-#define SK_DRV_SWITCH_SOFT		 4	/* Ports switch with both links connected */
-#define SK_DRV_SWITCH_HARD		 5	/* Port switch due to link failure */
-#define SK_DRV_RLMT_SEND		 6	/* Send a RLMT packet */
-#define SK_DRV_ADAP_FAIL		 7	/* The whole adapter fails */
-#define SK_DRV_PORT_FAIL		 8	/* One port fails */
-#define SK_DRV_SWITCH_INTERN	 9	/* Port switch by the driver itself */
-#define SK_DRV_POWER_DOWN		10	/* Power down mode */
-#define SK_DRV_TIMER			11	/* Timer for free use */
-#ifdef SK_NO_RLMT
-#define SK_DRV_LINK_UP  		12	/* Link Up event for driver */
-#define SK_DRV_LINK_DOWN		13	/* Link Down event for driver */
-#endif
-#define SK_DRV_DOWNSHIFT_DET	14	/* Downshift 4-Pair / 2-Pair (YUKON only) */
-#endif /* __INC_SKGEDRV_H_ */
diff --git a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h
deleted file mode 100644
index f6282b7..0000000
--- a/drivers/net/sk98lin/h/skgehw.h
+++ /dev/null
@@ -1,2126 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgehw.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.56 $
- * Date:	$Date: 2003/09/23 09:01:00 $
- * Purpose:	Defines and Macros for the Gigabit Ethernet Adapter Product Family
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEHW_H
-#define __INC_SKGEHW_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-#define BIT_31		(1UL << 31)
-#define BIT_30		(1L << 30)
-#define BIT_29		(1L << 29)
-#define BIT_28		(1L << 28)
-#define BIT_27		(1L << 27)
-#define BIT_26		(1L << 26)
-#define BIT_25		(1L << 25)
-#define BIT_24		(1L << 24)
-#define BIT_23		(1L << 23)
-#define BIT_22		(1L << 22)
-#define BIT_21		(1L << 21)
-#define BIT_20		(1L << 20)
-#define BIT_19		(1L << 19)
-#define BIT_18		(1L << 18)
-#define BIT_17		(1L << 17)
-#define BIT_16		(1L << 16)
-#define BIT_15		(1L << 15)
-#define BIT_14		(1L << 14)
-#define BIT_13		(1L << 13)
-#define BIT_12		(1L << 12)
-#define BIT_11		(1L << 11)
-#define BIT_10		(1L << 10)
-#define BIT_9		(1L << 9)
-#define BIT_8		(1L << 8)
-#define BIT_7		(1L << 7)
-#define BIT_6		(1L << 6)
-#define BIT_5		(1L << 5)
-#define BIT_4		(1L << 4)
-#define BIT_3		(1L << 3)
-#define BIT_2		(1L << 2)
-#define BIT_1		(1L << 1)
-#define BIT_0		1L
-
-#define BIT_15S		(1U << 15)
-#define BIT_14S		(1 << 14)
-#define BIT_13S		(1 << 13)
-#define BIT_12S		(1 << 12)
-#define BIT_11S		(1 << 11)
-#define BIT_10S		(1 << 10)
-#define BIT_9S		(1 << 9)
-#define BIT_8S		(1 << 8)
-#define BIT_7S 		(1 << 7)
-#define BIT_6S		(1 << 6)
-#define BIT_5S		(1 << 5)
-#define BIT_4S		(1 << 4)
-#define BIT_3S		(1 << 3)
-#define BIT_2S		(1 << 2)
-#define BIT_1S		(1 << 1)
-#define BIT_0S		1
-
-#define SHIFT31(x)	((x) << 31)
-#define SHIFT30(x)	((x) << 30)
-#define SHIFT29(x)	((x) << 29)
-#define SHIFT28(x)	((x) << 28)
-#define SHIFT27(x)	((x) << 27)
-#define SHIFT26(x)	((x) << 26)
-#define SHIFT25(x)	((x) << 25)
-#define SHIFT24(x)	((x) << 24)
-#define SHIFT23(x)	((x) << 23)
-#define SHIFT22(x)	((x) << 22)
-#define SHIFT21(x)	((x) << 21)
-#define SHIFT20(x)	((x) << 20)
-#define SHIFT19(x)	((x) << 19)
-#define SHIFT18(x)	((x) << 18)
-#define SHIFT17(x)	((x) << 17)
-#define SHIFT16(x)	((x) << 16)
-#define SHIFT15(x)	((x) << 15)
-#define SHIFT14(x)	((x) << 14)
-#define SHIFT13(x)	((x) << 13)
-#define SHIFT12(x)	((x) << 12)
-#define SHIFT11(x)	((x) << 11)
-#define SHIFT10(x)	((x) << 10)
-#define SHIFT9(x)	((x) << 9)
-#define SHIFT8(x)	((x) << 8)
-#define SHIFT7(x)	((x) << 7)
-#define SHIFT6(x)	((x) << 6)
-#define SHIFT5(x)	((x) << 5)
-#define SHIFT4(x)	((x) << 4)
-#define SHIFT3(x)	((x) << 3)
-#define SHIFT2(x)	((x) << 2)
-#define SHIFT1(x)	((x) << 1)
-#define SHIFT0(x)	((x) << 0)
-
-/*
- * Configuration Space header
- * Since this module is used for different OS', those may be
- * duplicate on some of them (e.g. Linux). But to keep the
- * common source, we have to live with this...
- */
-#define PCI_VENDOR_ID	0x00	/* 16 bit	Vendor ID */
-#define PCI_DEVICE_ID	0x02	/* 16 bit	Device ID */
-#define PCI_COMMAND		0x04	/* 16 bit	Command */
-#define PCI_STATUS		0x06	/* 16 bit	Status */
-#define PCI_REV_ID		0x08	/*  8 bit	Revision ID */
-#define PCI_CLASS_CODE	0x09	/* 24 bit	Class Code */
-#define PCI_CACHE_LSZ	0x0c	/*  8 bit	Cache Line Size */
-#define PCI_LAT_TIM		0x0d	/*  8 bit	Latency Timer */
-#define PCI_HEADER_T	0x0e	/*  8 bit	Header Type */
-#define PCI_BIST		0x0f	/*  8 bit	Built-in selftest */
-#define PCI_BASE_1ST	0x10	/* 32 bit	1st Base address */
-#define PCI_BASE_2ND	0x14	/* 32 bit	2nd Base address */
-	/* Byte 0x18..0x2b:	reserved */
-#define PCI_SUB_VID		0x2c	/* 16 bit	Subsystem Vendor ID */
-#define PCI_SUB_ID		0x2e	/* 16 bit	Subsystem ID */
-#define PCI_BASE_ROM	0x30	/* 32 bit	Expansion ROM Base Address */
-#define PCI_CAP_PTR		0x34	/*  8 bit 	Capabilities Ptr */
-	/* Byte 0x35..0x3b:	reserved */
-#define PCI_IRQ_LINE	0x3c	/*  8 bit	Interrupt Line */
-#define PCI_IRQ_PIN		0x3d	/*  8 bit	Interrupt Pin */
-#define PCI_MIN_GNT		0x3e	/*  8 bit	Min_Gnt */
-#define PCI_MAX_LAT		0x3f	/*  8 bit	Max_Lat */
-	/* Device Dependent Region */
-#define PCI_OUR_REG_1	0x40	/* 32 bit 	Our Register 1 */
-#define PCI_OUR_REG_2	0x44	/* 32 bit 	Our Register 2 */
-	/* Power Management Region */
-#define PCI_PM_CAP_ID	0x48	/*  8 bit 	Power Management Cap. ID */
-#define PCI_PM_NITEM	0x49	/*  8 bit 	Next Item Ptr */
-#define PCI_PM_CAP_REG	0x4a	/* 16 bit 	Power Management Capabilities */
-#define PCI_PM_CTL_STS	0x4c	/* 16 bit 	Power Manag. Control/Status */
-	/* Byte 0x4e:	reserved */
-#define PCI_PM_DAT_REG	0x4f	/*  8 bit 	Power Manag. Data Register */
-	/* VPD Region */
-#define PCI_VPD_CAP_ID	0x50	/*  8 bit 	VPD Cap. ID */
-#define PCI_VPD_NITEM	0x51	/*  8 bit 	Next Item Ptr */
-#define PCI_VPD_ADR_REG	0x52	/* 16 bit 	VPD Address Register */
-#define PCI_VPD_DAT_REG	0x54	/* 32 bit 	VPD Data Register */
-	/* Byte 0x58..0x59:	reserved */
-#define PCI_SER_LD_CTRL	0x5a	/* 16 bit 	SEEPROM Loader Ctrl (YUKON only) */
-	/* Byte 0x5c..0xff:	reserved */
-
-/*
- * I2C Address (PCI Config)
- *
- * Note: The temperature and voltage sensors are relocated on a different
- *	 I2C bus.
- */
-#define I2C_ADDR_VPD	0xa0	/* I2C address for the VPD EEPROM */
-
-/*
- * Define Bits and Values of the registers
- */
-/*	PCI_COMMAND	16 bit	Command */
-								/* Bit 15..11:	reserved */
-#define PCI_INT_DIS		BIT_10S		/* Interrupt INTx# disable (PCI 2.3) */
-#define PCI_FBTEN		BIT_9S		/* Fast Back-To-Back enable */
-#define PCI_SERREN		BIT_8S		/* SERR enable */
-#define PCI_ADSTEP		BIT_7S		/* Address Stepping */
-#define PCI_PERREN		BIT_6S		/* Parity Report Response enable */
-#define PCI_VGA_SNOOP	BIT_5S		/* VGA palette snoop */
-#define PCI_MWIEN		BIT_4S		/* Memory write an inv cycl ena */
-#define PCI_SCYCEN		BIT_3S		/* Special Cycle enable */
-#define PCI_BMEN		BIT_2S		/* Bus Master enable */
-#define PCI_MEMEN		BIT_1S		/* Memory Space Access enable */
-#define PCI_IOEN		BIT_0S		/* I/O Space Access enable */
-
-#define PCI_COMMAND_VAL	(PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\
-						 PCI_BMEN | PCI_MEMEN | PCI_IOEN)
-
-/*	PCI_STATUS	16 bit	Status */
-#define PCI_PERR		BIT_15S		/* Parity Error */
-#define PCI_SERR		BIT_14S		/* Signaled SERR */
-#define PCI_RMABORT		BIT_13S		/* Received Master Abort */
-#define PCI_RTABORT		BIT_12S		/* Received Target Abort */
-								/* Bit 11:	reserved */
-#define PCI_DEVSEL		(3<<9)		/* Bit 10.. 9:	DEVSEL Timing */
-#define PCI_DEV_FAST	(0<<9)		/*		fast */
-#define PCI_DEV_MEDIUM	(1<<9)		/*		medium */
-#define PCI_DEV_SLOW	(2<<9)		/*		slow */
-#define PCI_DATAPERR	BIT_8S		/* DATA Parity error detected */
-#define PCI_FB2BCAP		BIT_7S		/* Fast Back-to-Back Capability */
-#define PCI_UDF			BIT_6S		/* User Defined Features */
-#define PCI_66MHZCAP	BIT_5S		/* 66 MHz PCI bus clock capable */
-#define PCI_NEWCAP		BIT_4S		/* New cap. list implemented */
-#define PCI_INT_STAT	BIT_3S		/* Interrupt INTx# Status (PCI 2.3) */
-								/* Bit  2.. 0:	reserved */
-
-#define PCI_ERRBITS	(PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\
-			PCI_DATAPERR)
-
-/*	PCI_CLASS_CODE	24 bit	Class Code */
-/*	Byte 2:		Base Class		(02) */
-/*	Byte 1:		SubClass		(00) */
-/*	Byte 0:		Programming Interface	(00) */
-
-/*	PCI_CACHE_LSZ	8 bit	Cache Line Size */
-/*	Possible values: 0,2,4,8,16,32,64,128	*/
-
-/*	PCI_HEADER_T	8 bit	Header Type */
-#define PCI_HD_MF_DEV	BIT_7S	/* 0= single, 1= multi-func dev */
-#define PCI_HD_TYPE		0x7f	/* Bit 6..0:	Header Layout 0= normal */
-
-/*	PCI_BIST	8 bit	Built-in selftest */
-/*	Built-in Self test not supported (optional) */
-
-/*	PCI_BASE_1ST	32 bit	1st Base address */
-#define PCI_MEMSIZE		0x4000L		/* use 16 kB Memory Base */
-#define PCI_MEMBASE_MSK 0xffffc000L	/* Bit 31..14:	Memory Base Address */
-#define PCI_MEMSIZE_MSK 0x00003ff0L	/* Bit 13.. 4:	Memory Size Req. */
-#define PCI_PREFEN		BIT_3		/* Prefetchable */
-#define PCI_MEM_TYP		(3L<<2)		/* Bit	2.. 1:	Memory Type */
-#define PCI_MEM32BIT	(0L<<1)		/* Base addr anywhere in 32 Bit range */
-#define PCI_MEM1M		(1L<<1)		/* Base addr below 1 MegaByte */
-#define PCI_MEM64BIT	(2L<<1)		/* Base addr anywhere in 64 Bit range */
-#define PCI_MEMSPACE	BIT_0		/* Memory Space Indicator */
-
-/*	PCI_BASE_2ND	32 bit	2nd Base address */
-#define PCI_IOBASE		0xffffff00L	/* Bit 31.. 8:	I/O Base address */
-#define PCI_IOSIZE		0x000000fcL	/* Bit	7.. 2:	I/O Size Requirements */
-									/* Bit	1:	reserved */
-#define PCI_IOSPACE		BIT_0		/* I/O Space Indicator */
-
-/*	PCI_BASE_ROM	32 bit	Expansion ROM Base Address */
-#define PCI_ROMBASE_MSK	0xfffe0000L	/* Bit 31..17:	ROM Base address */
-#define PCI_ROMBASE_SIZ	(0x1cL<<14)	/* Bit 16..14:	Treat as Base or Size */
-#define PCI_ROMSIZE		(0x38L<<11)	/* Bit 13..11:	ROM Size Requirements */
-									/* Bit 10.. 1:	reserved */
-#define PCI_ROMEN		BIT_0		/* Address Decode enable */
-
-/* Device Dependent Region */
-/*	PCI_OUR_REG_1		32 bit	Our Register 1 */
-									/* Bit 31..29:	reserved */
-#define PCI_PHY_COMA	BIT_28		/* Set PHY to Coma Mode (YUKON only) */
-#define PCI_TEST_CAL	BIT_27		/* Test PCI buffer calib. (YUKON only) */
-#define PCI_EN_CAL		BIT_26		/* Enable PCI buffer calib. (YUKON only) */
-#define PCI_VIO			BIT_25		/* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */
-#define PCI_DIS_BOOT	BIT_24		/* Disable BOOT via ROM */
-#define PCI_EN_IO		BIT_23		/* Mapping to I/O space */
-#define PCI_EN_FPROM	BIT_22		/* Enable FLASH mapping to memory */
-									/*		1 = Map Flash to memory */
-									/*		0 = Disable addr. dec */
-#define PCI_PAGESIZE	(3L<<20)	/* Bit 21..20:	FLASH Page Size	*/
-#define PCI_PAGE_16		(0L<<20)	/*		16 k pages	*/
-#define PCI_PAGE_32K	(1L<<20)	/*		32 k pages	*/
-#define PCI_PAGE_64K	(2L<<20)	/*		64 k pages	*/
-#define PCI_PAGE_128K	(3L<<20)	/*		128 k pages	*/
-									/* Bit 19:	reserved	*/
-#define PCI_PAGEREG		(7L<<16)	/* Bit 18..16:	Page Register	*/
-#define PCI_NOTAR		BIT_15		/* No turnaround cycle */
-#define PCI_FORCE_BE	BIT_14		/* Assert all BEs on MR */
-#define PCI_DIS_MRL		BIT_13		/* Disable Mem Read Line */
-#define PCI_DIS_MRM		BIT_12		/* Disable Mem Read Multiple */
-#define PCI_DIS_MWI		BIT_11		/* Disable Mem Write & Invalidate */
-#define PCI_DISC_CLS	BIT_10		/* Disc: cacheLsz bound */
-#define PCI_BURST_DIS	BIT_9		/* Burst Disable */
-#define PCI_DIS_PCI_CLK	BIT_8		/* Disable PCI clock driving */
-#define PCI_SKEW_DAS	(0xfL<<4)	/* Bit	7.. 4:	Skew Ctrl, DAS Ext */
-#define PCI_SKEW_BASE	0xfL		/* Bit	3.. 0:	Skew Ctrl, Base	*/
-
-
-/*	PCI_OUR_REG_2		32 bit	Our Register 2 */
-#define PCI_VPD_WR_THR	(0xffL<<24)	/* Bit 31..24:	VPD Write Threshold */
-#define PCI_DEV_SEL		(0x7fL<<17)	/* Bit 23..17:	EEPROM Device Select */
-#define PCI_VPD_ROM_SZ	(7L<<14)	/* Bit 16..14:	VPD ROM Size	*/
-									/* Bit 13..12:	reserved	*/
-#define PCI_PATCH_DIR	(0xfL<<8)	/* Bit 11.. 8:	Ext Patches dir 3..0 */
-#define PCI_PATCH_DIR_3	BIT_11
-#define PCI_PATCH_DIR_2	BIT_10
-#define PCI_PATCH_DIR_1	BIT_9
-#define PCI_PATCH_DIR_0	BIT_8
-#define PCI_EXT_PATCHS	(0xfL<<4)	/* Bit	7.. 4:	Extended Patches 3..0 */
-#define PCI_EXT_PATCH_3	BIT_7
-#define PCI_EXT_PATCH_2	BIT_6
-#define PCI_EXT_PATCH_1	BIT_5
-#define PCI_EXT_PATCH_0	BIT_4
-#define PCI_EN_DUMMY_RD	BIT_3		/* Enable Dummy Read */
-#define PCI_REV_DESC	BIT_2		/* Reverse Desc. Bytes */
-									/* Bit	1:	reserved */
-#define PCI_USEDATA64	BIT_0		/* Use 64Bit Data bus ext */
-
-
-/* Power Management Region */
-/*	PCI_PM_CAP_REG		16 bit	Power Management Capabilities */
-#define PCI_PME_SUP_MSK	(0x1f<<11)	/* Bit 15..11:	PM Event Support Mask */
-#define PCI_PME_D3C_SUP	BIT_15S		/* PME from D3cold Support (if Vaux) */
-#define PCI_PME_D3H_SUP	BIT_14S		/* PME from D3hot Support */
-#define PCI_PME_D2_SUP	BIT_13S		/* PME from D2 Support */
-#define PCI_PME_D1_SUP	BIT_12S		/* PME from D1 Support */
-#define PCI_PME_D0_SUP	BIT_11S		/* PME from D0 Support */
-#define PCI_PM_D2_SUP	BIT_10S		/* D2 Support in 33 MHz mode */
-#define PCI_PM_D1_SUP	BIT_9S		/* D1 Support */
-									/* Bit	8.. 6:	reserved */
-#define PCI_PM_DSI		BIT_5S		/* Device Specific Initialization */
-#define PCI_PM_APS		BIT_4S		/* Auxialiary Power Source */
-#define PCI_PME_CLOCK	BIT_3S		/* PM Event Clock */
-#define PCI_PM_VER_MSK		7		/* Bit	2.. 0:	PM PCI Spec. version */
-
-/*	PCI_PM_CTL_STS		16 bit	Power Management Control/Status */
-#define PCI_PME_STATUS	BIT_15S		/* PME Status (YUKON only) */
-#define PCI_PM_DAT_SCL	(3<<13)		/* Bit 14..13:	Data Reg. scaling factor */
-#define PCI_PM_DAT_SEL	(0xf<<9)	/* Bit 12.. 9:	PM data selector field */
-#define PCI_PME_EN		BIT_8S		/* Enable PME# generation (YUKON only) */
-									/* Bit	7.. 2:	reserved */
-#define PCI_PM_STATE_MSK	3		/* Bit	1.. 0:	Power Management State */
-
-#define PCI_PM_STATE_D0		0		/* D0:	Operational (default) */
-#define PCI_PM_STATE_D1		1		/* D1:	(YUKON only) */
-#define PCI_PM_STATE_D2		2		/* D2:	(YUKON only) */
-#define PCI_PM_STATE_D3 	3		/* D3:	HOT, Power Down and Reset */
-
-/* VPD Region */
-/*	PCI_VPD_ADR_REG		16 bit	VPD Address Register */
-#define PCI_VPD_FLAG	BIT_15S		/* starts VPD rd/wr cycle */
-#define PCI_VPD_ADR_MSK	0x7fffL		/* Bit 14.. 0:	VPD address mask */
-
-/*	Control Register File (Address Map) */
-
-/*
- *	Bank 0
- */
-#define B0_RAP			0x0000	/*  8 bit	Register Address Port */
-	/* 0x0001 - 0x0003:	reserved */
-#define B0_CTST			0x0004	/* 16 bit	Control/Status register */
-#define B0_LED			0x0006	/*  8 Bit	LED register */
-#define B0_POWER_CTRL	0x0007	/*  8 Bit	Power Control reg (YUKON only) */
-#define B0_ISRC			0x0008	/* 32 bit	Interrupt Source Register */
-#define B0_IMSK			0x000c	/* 32 bit	Interrupt Mask Register */
-#define B0_HWE_ISRC		0x0010	/* 32 bit	HW Error Interrupt Src Reg */
-#define B0_HWE_IMSK		0x0014	/* 32 bit	HW Error Interrupt Mask Reg */
-#define B0_SP_ISRC		0x0018	/* 32 bit	Special Interrupt Source Reg */
-	/* 0x001c:		reserved */
-
-/* B0 XMAC 1 registers (GENESIS only) */
-#define B0_XM1_IMSK		0x0020	/* 16 bit r/w	XMAC 1 Interrupt Mask Register*/
-	/* 0x0022 - 0x0027:	reserved */
-#define B0_XM1_ISRC		0x0028	/* 16 bit ro	XMAC 1 Interrupt Status Reg */
-	/* 0x002a - 0x002f:	reserved */
-#define B0_XM1_PHY_ADDR 0x0030	/* 16 bit r/w	XMAC 1 PHY Address Register */
-	/* 0x0032 - 0x0033:	reserved */
-#define B0_XM1_PHY_DATA 0x0034	/* 16 bit r/w	XMAC 1 PHY Data Register */
-	/* 0x0036 - 0x003f:	reserved */
-
-/* B0 XMAC 2 registers (GENESIS only) */
-#define B0_XM2_IMSK		0x0040	/* 16 bit r/w	XMAC 2 Interrupt Mask Register*/
-	/* 0x0042 - 0x0047:	reserved */
-#define B0_XM2_ISRC		0x0048	/* 16 bit ro	XMAC 2 Interrupt Status Reg */
-	/* 0x004a - 0x004f:	reserved */
-#define B0_XM2_PHY_ADDR 0x0050	/* 16 bit r/w	XMAC 2 PHY Address Register */
-	/* 0x0052 - 0x0053:	reserved */
-#define B0_XM2_PHY_DATA 0x0054	/* 16 bit r/w	XMAC 2 PHY Data Register */
-	/* 0x0056 - 0x005f:	reserved */
-
-/* BMU Control Status Registers */
-#define B0_R1_CSR		0x0060	/* 32 bit	BMU Ctrl/Stat Rx Queue 1 */
-#define B0_R2_CSR		0x0064	/* 32 bit	BMU Ctrl/Stat Rx Queue 2 */
-#define B0_XS1_CSR		0x0068	/* 32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
-#define B0_XA1_CSR		0x006c	/* 32 bit	BMU Ctrl/Stat Async Tx Queue 1*/
-#define B0_XS2_CSR		0x0070	/* 32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
-#define B0_XA2_CSR		0x0074	/* 32 bit	BMU Ctrl/Stat Async Tx Queue 2*/
-	/* 0x0078 - 0x007f:	reserved */
-
-/*
- *	Bank 1
- *	- completely empty (this is the RAP Block window)
- *	Note: if RAP = 1 this page is reserved
- */
-
-/*
- *	Bank 2
- */
-/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */
-#define B2_MAC_1		0x0100	/* NA reg	 MAC Address 1 */
-	/* 0x0106 - 0x0107:	reserved */
-#define B2_MAC_2		0x0108	/* NA reg	 MAC Address 2 */
-	/* 0x010e - 0x010f:	reserved */
-#define B2_MAC_3		0x0110	/* NA reg	 MAC Address 3 */
-	/* 0x0116 - 0x0117:	reserved */
-#define B2_CONN_TYP		0x0118	/*  8 bit	Connector type */
-#define B2_PMD_TYP		0x0119	/*  8 bit	PMD type */
-#define B2_MAC_CFG		0x011a	/*  8 bit	MAC Configuration / Chip Revision */
-#define B2_CHIP_ID		0x011b	/*  8 bit 	Chip Identification Number */
-	/* Eprom registers are currently of no use */
-#define B2_E_0			0x011c	/*  8 bit	EPROM Byte 0 (ext. SRAM size */
-#define B2_E_1			0x011d	/*  8 bit	EPROM Byte 1 (PHY type) */
-#define B2_E_2			0x011e	/*  8 bit	EPROM Byte 2 */
-#define B2_E_3			0x011f	/*  8 bit	EPROM Byte 3 */
-#define B2_FAR			0x0120	/* 32 bit	Flash-Prom Addr Reg/Cnt */
-#define B2_FDP			0x0124	/*  8 bit	Flash-Prom Data Port */
-	/* 0x0125 - 0x0127:	reserved */
-#define B2_LD_CTRL		0x0128	/*  8 bit	EPROM loader control register */
-#define B2_LD_TEST		0x0129	/*  8 bit	EPROM loader test register */
-	/* 0x012a - 0x012f:	reserved */
-#define B2_TI_INI		0x0130	/* 32 bit	Timer Init Value */
-#define B2_TI_VAL		0x0134	/* 32 bit	Timer Value */
-#define B2_TI_CTRL		0x0138	/*  8 bit	Timer Control */
-#define B2_TI_TEST		0x0139	/*  8 Bit	Timer Test */
-	/* 0x013a - 0x013f:	reserved */
-#define B2_IRQM_INI		0x0140	/* 32 bit	IRQ Moderation Timer Init Reg.*/
-#define B2_IRQM_VAL		0x0144	/* 32 bit	IRQ Moderation Timer Value */
-#define B2_IRQM_CTRL	0x0148	/*  8 bit	IRQ Moderation Timer Control */
-#define B2_IRQM_TEST	0x0149	/*  8 bit	IRQ Moderation Timer Test */
-#define B2_IRQM_MSK 	0x014c	/* 32 bit	IRQ Moderation Mask */
-#define B2_IRQM_HWE_MSK 0x0150	/* 32 bit	IRQ Moderation HW Error Mask */
-	/* 0x0154 - 0x0157:	reserved */
-#define B2_TST_CTRL1	0x0158	/*  8 bit	Test Control Register 1 */
-#define B2_TST_CTRL2	0x0159	/*  8 bit	Test Control Register 2 */
-	/* 0x015a - 0x015b:	reserved */
-#define B2_GP_IO		0x015c	/* 32 bit	General Purpose I/O Register */
-#define B2_I2C_CTRL		0x0160	/* 32 bit	I2C HW Control Register */
-#define B2_I2C_DATA		0x0164	/* 32 bit	I2C HW Data Register */
-#define B2_I2C_IRQ		0x0168	/* 32 bit	I2C HW IRQ Register */
-#define B2_I2C_SW		0x016c	/* 32 bit	I2C SW Port Register */
-
-/* Blink Source Counter (GENESIS only) */
-#define B2_BSC_INI		0x0170	/* 32 bit	Blink Source Counter Init Val */
-#define B2_BSC_VAL		0x0174	/* 32 bit	Blink Source Counter Value */
-#define B2_BSC_CTRL		0x0178	/*  8 bit	Blink Source Counter Control */
-#define B2_BSC_STAT		0x0179	/*  8 bit	Blink Source Counter Status */
-#define B2_BSC_TST		0x017a	/* 16 bit	Blink Source Counter Test Reg */
-	/* 0x017c - 0x017f:	reserved */
-
-/*
- *	Bank 3
- */
-/* RAM Random Registers */
-#define B3_RAM_ADDR		0x0180	/* 32 bit	RAM Address, to read or write */
-#define B3_RAM_DATA_LO	0x0184	/* 32 bit	RAM Data Word (low dWord) */
-#define B3_RAM_DATA_HI	0x0188	/* 32 bit	RAM Data Word (high dWord) */
-	/* 0x018c - 0x018f:	reserved */
-
-/* RAM Interface Registers */
-/*
- * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
- * not usable in SW. Please notice these are NOT real timeouts, these are
- * the number of qWords transferred continuously.
- */
-#define B3_RI_WTO_R1	0x0190	/*  8 bit	WR Timeout Queue R1		(TO0) */
-#define B3_RI_WTO_XA1	0x0191	/*  8 bit	WR Timeout Queue XA1	(TO1) */
-#define B3_RI_WTO_XS1	0x0192	/*  8 bit	WR Timeout Queue XS1	(TO2) */
-#define B3_RI_RTO_R1	0x0193	/*  8 bit	RD Timeout Queue R1		(TO3) */
-#define B3_RI_RTO_XA1	0x0194	/*  8 bit	RD Timeout Queue XA1	(TO4) */
-#define B3_RI_RTO_XS1	0x0195	/*  8 bit	RD Timeout Queue XS1	(TO5) */
-#define B3_RI_WTO_R2	0x0196	/*  8 bit	WR Timeout Queue R2		(TO6) */
-#define B3_RI_WTO_XA2	0x0197	/*  8 bit	WR Timeout Queue XA2	(TO7) */
-#define B3_RI_WTO_XS2	0x0198	/*  8 bit	WR Timeout Queue XS2	(TO8) */
-#define B3_RI_RTO_R2	0x0199	/*  8 bit	RD Timeout Queue R2		(TO9) */
-#define B3_RI_RTO_XA2	0x019a	/*  8 bit	RD Timeout Queue XA2	(TO10)*/
-#define B3_RI_RTO_XS2	0x019b	/*  8 bit	RD Timeout Queue XS2	(TO11)*/
-#define B3_RI_TO_VAL	0x019c	/*  8 bit	Current Timeout Count Val */
-	/* 0x019d - 0x019f:	reserved */
-#define B3_RI_CTRL		0x01a0	/* 16 bit	RAM Interface Control Register */
-#define B3_RI_TEST		0x01a2	/*  8 bit	RAM Interface Test Register */
-	/* 0x01a3 - 0x01af:	reserved */
-
-/* MAC Arbiter Registers (GENESIS only) */
-/* these are the no. of qWord transferred continuously and NOT real timeouts */
-#define B3_MA_TOINI_RX1	0x01b0	/*  8 bit	Timeout Init Val Rx Path MAC 1 */
-#define B3_MA_TOINI_RX2	0x01b1	/*  8 bit	Timeout Init Val Rx Path MAC 2 */
-#define B3_MA_TOINI_TX1	0x01b2	/*  8 bit	Timeout Init Val Tx Path MAC 1 */
-#define B3_MA_TOINI_TX2	0x01b3	/*  8 bit	Timeout Init Val Tx Path MAC 2 */
-#define B3_MA_TOVAL_RX1	0x01b4	/*  8 bit	Timeout Value Rx Path MAC 1 */
-#define B3_MA_TOVAL_RX2	0x01b5	/*  8 bit	Timeout Value Rx Path MAC 1 */
-#define B3_MA_TOVAL_TX1	0x01b6	/*  8 bit	Timeout Value Tx Path MAC 2 */
-#define B3_MA_TOVAL_TX2	0x01b7	/*  8 bit	Timeout Value Tx Path MAC 2 */
-#define B3_MA_TO_CTRL	0x01b8	/* 16 bit	MAC Arbiter Timeout Ctrl Reg */
-#define B3_MA_TO_TEST	0x01ba	/* 16 bit	MAC Arbiter Timeout Test Reg */
-	/* 0x01bc - 0x01bf:	reserved */
-#define B3_MA_RCINI_RX1	0x01c0	/*  8 bit	Recovery Init Val Rx Path MAC 1 */
-#define B3_MA_RCINI_RX2	0x01c1	/*  8 bit	Recovery Init Val Rx Path MAC 2 */
-#define B3_MA_RCINI_TX1	0x01c2	/*  8 bit	Recovery Init Val Tx Path MAC 1 */
-#define B3_MA_RCINI_TX2	0x01c3	/*  8 bit	Recovery Init Val Tx Path MAC 2 */
-#define B3_MA_RCVAL_RX1	0x01c4	/*  8 bit	Recovery Value Rx Path MAC 1 */
-#define B3_MA_RCVAL_RX2	0x01c5	/*  8 bit	Recovery Value Rx Path MAC 1 */
-#define B3_MA_RCVAL_TX1	0x01c6	/*  8 bit	Recovery Value Tx Path MAC 2 */
-#define B3_MA_RCVAL_TX2	0x01c7	/*  8 bit	Recovery Value Tx Path MAC 2 */
-#define B3_MA_RC_CTRL	0x01c8	/* 16 bit	MAC Arbiter Recovery Ctrl Reg */
-#define B3_MA_RC_TEST	0x01ca	/* 16 bit	MAC Arbiter Recovery Test Reg */
-	/* 0x01cc - 0x01cf:	reserved */
-
-/* Packet Arbiter Registers (GENESIS only) */
-/* these are real timeouts */
-#define B3_PA_TOINI_RX1	0x01d0	/* 16 bit	Timeout Init Val Rx Path MAC 1 */
-	/* 0x01d2 - 0x01d3:	reserved */
-#define B3_PA_TOINI_RX2	0x01d4	/* 16 bit	Timeout Init Val Rx Path MAC 2 */
-	/* 0x01d6 - 0x01d7:	reserved */
-#define B3_PA_TOINI_TX1	0x01d8	/* 16 bit	Timeout Init Val Tx Path MAC 1 */
-	/* 0x01da - 0x01db:	reserved */
-#define B3_PA_TOINI_TX2	0x01dc	/* 16 bit	Timeout Init Val Tx Path MAC 2 */
-	/* 0x01de - 0x01df:	reserved */
-#define B3_PA_TOVAL_RX1	0x01e0	/* 16 bit	Timeout Val Rx Path MAC 1 */
-	/* 0x01e2 - 0x01e3:	reserved */
-#define B3_PA_TOVAL_RX2	0x01e4	/* 16 bit	Timeout Val Rx Path MAC 2 */
-	/* 0x01e6 - 0x01e7:	reserved */
-#define B3_PA_TOVAL_TX1	0x01e8	/* 16 bit	Timeout Val Tx Path MAC 1 */
-	/* 0x01ea - 0x01eb:	reserved */
-#define B3_PA_TOVAL_TX2	0x01ec	/* 16 bit	Timeout Val Tx Path MAC 2 */
-	/* 0x01ee - 0x01ef:	reserved */
-#define B3_PA_CTRL	0x01f0	/* 16 bit	Packet Arbiter Ctrl Register */
-#define B3_PA_TEST	0x01f2	/* 16 bit	Packet Arbiter Test Register */
-	/* 0x01f4 - 0x01ff:	reserved */
-
-/*
- *	Bank 4 - 5
- */
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
-#define TXA_ITI_INI		0x0200	/* 32 bit	Tx Arb Interval Timer Init Val*/
-#define TXA_ITI_VAL		0x0204	/* 32 bit	Tx Arb Interval Timer Value */
-#define TXA_LIM_INI		0x0208	/* 32 bit	Tx Arb Limit Counter Init Val */
-#define TXA_LIM_VAL		0x020c	/* 32 bit	Tx Arb Limit Counter Value */
-#define TXA_CTRL		0x0210	/*  8 bit	Tx Arbiter Control Register */
-#define TXA_TEST		0x0211	/*  8 bit	Tx Arbiter Test Register */
-#define TXA_STAT		0x0212	/*  8 bit	Tx Arbiter Status Register */
-	/* 0x0213 - 0x027f:	reserved */
-	/* 0x0280 - 0x0292:	MAC 2 */
-	/* 0x0213 - 0x027f:	reserved */
-
-/*
- *	Bank 6
- */
-/* External registers (GENESIS only) */
-#define B6_EXT_REG		0x0300
-
-/*
- *	Bank 7
- */
-/* This is a copy of the Configuration register file (lower half) */
-#define B7_CFG_SPC		0x0380
-
-/*
- *	Bank 8 - 15
- */
-/* Receive and Transmit Queue Registers, use Q_ADDR() to access */
-#define B8_Q_REGS		0x0400
-
-/* Queue Register Offsets, use Q_ADDR() to access */
-#define Q_D		0x00	/* 8*32	bit	Current Descriptor */
-#define Q_DA_L	0x20	/* 32 bit	Current Descriptor Address Low dWord */
-#define Q_DA_H	0x24	/* 32 bit	Current Descriptor Address High dWord */
-#define Q_AC_L	0x28	/* 32 bit	Current Address Counter Low dWord */
-#define Q_AC_H	0x2c	/* 32 bit	Current Address Counter High dWord */
-#define Q_BC	0x30	/* 32 bit	Current Byte Counter */
-#define Q_CSR	0x34	/* 32 bit	BMU Control/Status Register */
-#define Q_F		0x38	/* 32 bit	Flag Register */
-#define Q_T1	0x3c	/* 32 bit	Test Register 1 */
-#define Q_T1_TR	0x3c	/*  8 bit	Test Register 1 Transfer SM */
-#define Q_T1_WR	0x3d	/*  8 bit	Test Register 1 Write Descriptor SM */
-#define Q_T1_RD	0x3e	/*  8 bit	Test Register 1 Read Descriptor SM */
-#define Q_T1_SV	0x3f	/*  8 bit	Test Register 1 Supervisor SM */
-#define Q_T2	0x40	/* 32 bit	Test Register 2	*/
-#define Q_T3	0x44	/* 32 bit	Test Register 3	*/
-	/* 0x48 - 0x7f:	reserved */
-
-/*
- *	Bank 16 - 23
- */
-/* RAM Buffer Registers */
-#define B16_RAM_REGS	0x0800
-
-/* RAM Buffer Register Offsets, use RB_ADDR() to access */
-#define RB_START		0x00	/* 32 bit	RAM Buffer Start Address */
-#define RB_END			0x04	/* 32 bit	RAM Buffer End Address */
-#define RB_WP			0x08	/* 32 bit	RAM Buffer Write Pointer */
-#define RB_RP			0x0c	/* 32 bit	RAM Buffer Read Pointer */
-#define RB_RX_UTPP		0x10	/* 32 bit	Rx Upper Threshold, Pause Pack */
-#define RB_RX_LTPP		0x14	/* 32 bit	Rx Lower Threshold, Pause Pack */
-#define RB_RX_UTHP		0x18	/* 32 bit	Rx Upper Threshold, High Prio */
-#define RB_RX_LTHP		0x1c	/* 32 bit	Rx Lower Threshold, High Prio */
-	/* 0x10 - 0x1f:	reserved at Tx RAM Buffer Registers */
-#define RB_PC			0x20	/* 32 bit	RAM Buffer Packet Counter */
-#define RB_LEV			0x24	/* 32 bit	RAM Buffer Level Register */
-#define RB_CTRL			0x28	/*  8 bit	RAM Buffer Control Register */
-#define RB_TST1			0x29	/*  8 bit	RAM Buffer Test Register 1 */
-#define RB_TST2			0x2A	/*  8 bit	RAM Buffer Test Register 2 */
-	/* 0x2c - 0x7f:	reserved */
-
-/*
- *	Bank 24
- */
-/*
- * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only)
- * use MR_ADDR() to access
- */
-#define RX_MFF_EA		0x0c00	/* 32 bit	Receive MAC FIFO End Address */
-#define RX_MFF_WP		0x0c04	/* 32 bit 	Receive MAC FIFO Write Pointer */
-	/* 0x0c08 - 0x0c0b:	reserved */
-#define RX_MFF_RP		0x0c0c	/* 32 bit	Receive MAC FIFO Read Pointer */
-#define RX_MFF_PC		0x0c10	/* 32 bit	Receive MAC FIFO Packet Cnt */
-#define RX_MFF_LEV		0x0c14	/* 32 bit	Receive MAC FIFO Level */
-#define RX_MFF_CTRL1	0x0c18	/* 16 bit	Receive MAC FIFO Control Reg 1*/
-#define RX_MFF_STAT_TO	0x0c1a	/*  8 bit	Receive MAC Status Timeout */
-#define RX_MFF_TIST_TO	0x0c1b	/*  8 bit	Receive MAC Time Stamp Timeout */
-#define RX_MFF_CTRL2	0x0c1c	/*  8 bit	Receive MAC FIFO Control Reg 2*/
-#define RX_MFF_TST1		0x0c1d	/*  8 bit	Receive MAC FIFO Test Reg 1 */
-#define RX_MFF_TST2		0x0c1e	/*  8 bit	Receive MAC FIFO Test Reg 2 */
-	/* 0x0c1f:	reserved */
-#define RX_LED_INI		0x0c20	/* 32 bit	Receive LED Cnt Init Value */
-#define RX_LED_VAL		0x0c24	/* 32 bit	Receive LED Cnt Current Value */
-#define RX_LED_CTRL		0x0c28	/*  8 bit	Receive LED Cnt Control Reg */
-#define RX_LED_TST		0x0c29	/*  8 bit	Receive LED Cnt Test Register */
-	/* 0x0c2a - 0x0c2f:	reserved */
-#define LNK_SYNC_INI	0x0c30	/* 32 bit	Link Sync Cnt Init Value */
-#define LNK_SYNC_VAL	0x0c34	/* 32 bit	Link Sync Cnt Current Value */
-#define LNK_SYNC_CTRL	0x0c38	/*  8 bit	Link Sync Cnt Control Register */
-#define LNK_SYNC_TST	0x0c39	/*  8 bit	Link Sync Cnt Test Register */
-	/* 0x0c3a - 0x0c3b:	reserved */
-#define LNK_LED_REG		0x0c3c	/*  8 bit	Link LED Register */
-	/* 0x0c3d - 0x0c3f:	reserved */
-
-/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */
-#define RX_GMF_EA		0x0c40	/* 32 bit	Rx GMAC FIFO End Address */
-#define RX_GMF_AF_THR	0x0c44	/* 32 bit	Rx GMAC FIFO Almost Full Thresh. */
-#define RX_GMF_CTRL_T	0x0c48	/* 32 bit	Rx GMAC FIFO Control/Test */
-#define RX_GMF_FL_MSK	0x0c4c	/* 32 bit	Rx GMAC FIFO Flush Mask */
-#define RX_GMF_FL_THR	0x0c50	/* 32 bit	Rx GMAC FIFO Flush Threshold */
-	/* 0x0c54 - 0x0c5f:	reserved */
-#define RX_GMF_WP		0x0c60	/* 32 bit 	Rx GMAC FIFO Write Pointer */
-	/* 0x0c64 - 0x0c67:	reserved */
-#define RX_GMF_WLEV		0x0c68	/* 32 bit 	Rx GMAC FIFO Write Level */
-	/* 0x0c6c - 0x0c6f:	reserved */
-#define RX_GMF_RP		0x0c70	/* 32 bit 	Rx GMAC FIFO Read Pointer */
-	/* 0x0c74 - 0x0c77:	reserved */
-#define RX_GMF_RLEV		0x0c78	/* 32 bit 	Rx GMAC FIFO Read Level */
-	/* 0x0c7c - 0x0c7f:	reserved */
-
-/*
- *	Bank 25
- */
-	/* 0x0c80 - 0x0cbf:	MAC 2 */
-	/* 0x0cc0 - 0x0cff:	reserved */
-
-/*
- *	Bank 26
- */
-/*
- * Transmit MAC FIFO and Transmit LED Registers (GENESIS only),
- * use MR_ADDR() to access
- */
-#define TX_MFF_EA		0x0d00	/* 32 bit	Transmit MAC FIFO End Address */
-#define TX_MFF_WP		0x0d04	/* 32 bit 	Transmit MAC FIFO WR Pointer */
-#define TX_MFF_WSP		0x0d08	/* 32 bit	Transmit MAC FIFO WR Shadow Ptr */
-#define TX_MFF_RP		0x0d0c	/* 32 bit	Transmit MAC FIFO RD Pointer */
-#define TX_MFF_PC		0x0d10	/* 32 bit	Transmit MAC FIFO Packet Cnt */
-#define TX_MFF_LEV		0x0d14	/* 32 bit	Transmit MAC FIFO Level */
-#define TX_MFF_CTRL1	0x0d18	/* 16 bit	Transmit MAC FIFO Ctrl Reg 1 */
-#define TX_MFF_WAF		0x0d1a	/*  8 bit	Transmit MAC Wait after flush */
-	/* 0x0c1b:	reserved */
-#define TX_MFF_CTRL2	0x0d1c	/*  8 bit	Transmit MAC FIFO Ctrl Reg 2 */
-#define TX_MFF_TST1		0x0d1d	/*  8 bit	Transmit MAC FIFO Test Reg 1 */
-#define TX_MFF_TST2		0x0d1e	/*  8 bit	Transmit MAC FIFO Test Reg 2 */
-	/* 0x0d1f:	reserved */
-#define TX_LED_INI		0x0d20	/* 32 bit	Transmit LED Cnt Init Value */
-#define TX_LED_VAL		0x0d24	/* 32 bit	Transmit LED Cnt Current Val */
-#define TX_LED_CTRL		0x0d28	/*  8 bit	Transmit LED Cnt Control Reg */
-#define TX_LED_TST		0x0d29	/*  8 bit	Transmit LED Cnt Test Reg */
-	/* 0x0d2a - 0x0d3f:	reserved */
-
-/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */
-#define TX_GMF_EA		0x0d40	/* 32 bit	Tx GMAC FIFO End Address */
-#define TX_GMF_AE_THR	0x0d44	/* 32 bit	Tx GMAC FIFO Almost Empty Thresh.*/
-#define TX_GMF_CTRL_T	0x0d48	/* 32 bit	Tx GMAC FIFO Control/Test */
-	/* 0x0d4c - 0x0d5f:	reserved */
-#define TX_GMF_WP		0x0d60	/* 32 bit 	Tx GMAC FIFO Write Pointer */
-#define TX_GMF_WSP		0x0d64	/* 32 bit 	Tx GMAC FIFO Write Shadow Ptr. */
-#define TX_GMF_WLEV		0x0d68	/* 32 bit 	Tx GMAC FIFO Write Level */
-	/* 0x0d6c - 0x0d6f:	reserved */
-#define TX_GMF_RP		0x0d70	/* 32 bit 	Tx GMAC FIFO Read Pointer */
-#define TX_GMF_RSTP		0x0d74	/* 32 bit 	Tx GMAC FIFO Restart Pointer */
-#define TX_GMF_RLEV		0x0d78	/* 32 bit 	Tx GMAC FIFO Read Level */
-	/* 0x0d7c - 0x0d7f:	reserved */
-
-/*
- *	Bank 27
- */
-	/* 0x0d80 - 0x0dbf:	MAC 2 */
-	/* 0x0daa - 0x0dff:	reserved */
-
-/*
- *	Bank 28
- */
-/* Descriptor Poll Timer Registers */
-#define B28_DPT_INI		0x0e00	/* 24 bit	Descriptor Poll Timer Init Val */
-#define B28_DPT_VAL		0x0e04	/* 24 bit	Descriptor Poll Timer Curr Val */
-#define B28_DPT_CTRL	0x0e08	/*  8 bit	Descriptor Poll Timer Ctrl Reg */
-	/* 0x0e09:	reserved */
-#define B28_DPT_TST		0x0e0a	/*  8 bit	Descriptor Poll Timer Test Reg */
-	/* 0x0e0b:	reserved */
-
-/* Time Stamp Timer Registers (YUKON only) */
-	/* 0x0e10:	reserved */
-#define GMAC_TI_ST_VAL	0x0e14	/* 32 bit	Time Stamp Timer Curr Val */
-#define GMAC_TI_ST_CTRL	0x0e18	/*  8 bit	Time Stamp Timer Ctrl Reg */
-	/* 0x0e19:	reserved */
-#define GMAC_TI_ST_TST	0x0e1a	/*  8 bit	Time Stamp Timer Test Reg */
-	/* 0x0e1b - 0x0e7f:	reserved */
-
-/*
- *	Bank 29
- */
-	/* 0x0e80 - 0x0efc:	reserved */
-
-/*
- *	Bank 30
- */
-/* GMAC and GPHY Control Registers (YUKON only) */
-#define GMAC_CTRL		0x0f00	/* 32 bit	GMAC Control Reg */
-#define GPHY_CTRL		0x0f04	/* 32 bit	GPHY Control Reg */
-#define GMAC_IRQ_SRC	0x0f08	/*  8 bit	GMAC Interrupt Source Reg */
-	/* 0x0f09 - 0x0f0b:	reserved */
-#define GMAC_IRQ_MSK	0x0f0c	/*  8 bit	GMAC Interrupt Mask Reg */
-	/* 0x0f0d - 0x0f0f:	reserved */
-#define GMAC_LINK_CTRL	0x0f10	/* 16 bit	Link Control Reg */
-	/* 0x0f14 - 0x0f1f:	reserved */
-
-/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
-
-#define WOL_REG_OFFS	0x20	/* HW-Bug: Address is + 0x20 against spec. */
-
-#define WOL_CTRL_STAT	0x0f20	/* 16 bit	WOL Control/Status Reg */
-#define WOL_MATCH_CTL	0x0f22	/*  8 bit	WOL Match Control Reg */
-#define WOL_MATCH_RES	0x0f23	/*  8 bit	WOL Match Result Reg */
-#define WOL_MAC_ADDR_LO	0x0f24	/* 32 bit	WOL MAC Address Low */
-#define WOL_MAC_ADDR_HI	0x0f28	/* 16 bit	WOL MAC Address High */
-#define WOL_PATT_RPTR	0x0f2c	/*  8 bit	WOL Pattern Read Ptr */
-
-/* use this macro to access above registers */
-#define WOL_REG(Reg)	((Reg) + (pAC->GIni.GIWolOffs))
-
-
-/* WOL Pattern Length Registers (YUKON only) */
-
-#define WOL_PATT_LEN_LO	0x0f30		/* 32 bit	WOL Pattern Length 3..0 */
-#define WOL_PATT_LEN_HI	0x0f34		/* 24 bit	WOL Pattern Length 6..4 */
-
-/* WOL Pattern Counter Registers (YUKON only) */
-
-#define WOL_PATT_CNT_0	0x0f38		/* 32 bit	WOL Pattern Counter 3..0 */
-#define WOL_PATT_CNT_4	0x0f3c		/* 24 bit	WOL Pattern Counter 6..4 */
-	/* 0x0f40 - 0x0f7f:	reserved */
-
-/*
- *	Bank 31
- */
-/* 0x0f80 - 0x0fff:	reserved */
-
-/*
- *	Bank 32	- 33
- */
-#define WOL_PATT_RAM_1	0x1000	/*  WOL Pattern RAM Link 1 */
-
-/*
- *	Bank 0x22 - 0x3f
- */
-/* 0x1100 - 0x1fff:	reserved */
-
-/*
- *	Bank 0x40 - 0x4f
- */
-#define BASE_XMAC_1		0x2000	/* XMAC 1 registers */
-
-/*
- *	Bank 0x50 - 0x5f
- */
-
-#define BASE_GMAC_1		0x2800	/* GMAC 1 registers */
-
-/*
- *	Bank 0x60 - 0x6f
- */
-#define BASE_XMAC_2		0x3000	/* XMAC 2 registers */
-
-/*
- *	Bank 0x70 - 0x7f
- */
-#define BASE_GMAC_2		0x3800	/* GMAC 2 registers */
-
-/*
- *	Control Register Bit Definitions:
- */
-/*	B0_RAP		8 bit	Register Address Port */
-								/* Bit 7:	reserved */
-#define RAP_RAP			0x3f	/* Bit 6..0:	0 = block 0,..,6f = block 6f */
-
-/*	B0_CTST			16 bit	Control/Status register */
-								/* Bit 15..14:	reserved */
-#define CS_CLK_RUN_HOT	BIT_13S		/* CLK_RUN hot m. (YUKON-Lite only) */
-#define CS_CLK_RUN_RST	BIT_12S		/* CLK_RUN reset  (YUKON-Lite only) */
-#define CS_CLK_RUN_ENA	BIT_11S		/* CLK_RUN enable (YUKON-Lite only) */
-#define CS_VAUX_AVAIL	BIT_10S		/* VAUX available (YUKON only) */
-#define CS_BUS_CLOCK	BIT_9S		/* Bus Clock 0/1 = 33/66 MHz */
-#define CS_BUS_SLOT_SZ	BIT_8S		/* Slot Size 0/1 = 32/64 bit slot */
-#define CS_ST_SW_IRQ	BIT_7S		/* Set IRQ SW Request */
-#define CS_CL_SW_IRQ	BIT_6S		/* Clear IRQ SW Request */
-#define CS_STOP_DONE	BIT_5S		/* Stop Master is finished */
-#define CS_STOP_MAST	BIT_4S		/* Command Bit to stop the master */
-#define CS_MRST_CLR		BIT_3S		/* Clear Master reset	*/
-#define CS_MRST_SET		BIT_2S		/* Set Master reset	*/
-#define CS_RST_CLR		BIT_1S		/* Clear Software reset	*/
-#define CS_RST_SET		BIT_0S		/* Set   Software reset	*/
-
-/*	B0_LED			 8 Bit	LED register */
-								/* Bit  7.. 2:	reserved */
-#define LED_STAT_ON		BIT_1S		/* Status LED on	*/
-#define LED_STAT_OFF	BIT_0S		/* Status LED off	*/
-
-/*	B0_POWER_CTRL	 8 Bit	Power Control reg (YUKON only) */
-#define PC_VAUX_ENA		BIT_7		/* Switch VAUX Enable  */
-#define PC_VAUX_DIS		BIT_6       /* Switch VAUX Disable */
-#define PC_VCC_ENA		BIT_5       /* Switch VCC Enable  */
-#define PC_VCC_DIS		BIT_4       /* Switch VCC Disable */
-#define PC_VAUX_ON		BIT_3       /* Switch VAUX On  */
-#define PC_VAUX_OFF		BIT_2       /* Switch VAUX Off */
-#define PC_VCC_ON		BIT_1       /* Switch VCC On  */
-#define PC_VCC_OFF		BIT_0       /* Switch VCC Off */
-
-/*	B0_ISRC			32 bit	Interrupt Source Register */
-/*	B0_IMSK			32 bit	Interrupt Mask Register */
-/*	B0_SP_ISRC		32 bit	Special Interrupt Source Reg */
-/*	B2_IRQM_MSK 	32 bit	IRQ Moderation Mask */
-#define IS_ALL_MSK		0xbfffffffUL	/* All Interrupt bits */
-#define IS_HW_ERR		BIT_31		/* Interrupt HW Error */
-								/* Bit 30:	reserved */
-#define IS_PA_TO_RX1	BIT_29		/* Packet Arb Timeout Rx1 */
-#define IS_PA_TO_RX2	BIT_28		/* Packet Arb Timeout Rx2 */
-#define IS_PA_TO_TX1	BIT_27		/* Packet Arb Timeout Tx1 */
-#define IS_PA_TO_TX2	BIT_26		/* Packet Arb Timeout Tx2 */
-#define IS_I2C_READY	BIT_25		/* IRQ on end of I2C Tx */
-#define IS_IRQ_SW		BIT_24		/* SW forced IRQ	*/
-#define IS_EXT_REG		BIT_23		/* IRQ from LM80 or PHY (GENESIS only) */
-									/* IRQ from PHY (YUKON only) */
-#define IS_TIMINT		BIT_22		/* IRQ from Timer	*/
-#define IS_MAC1			BIT_21		/* IRQ from MAC 1	*/
-#define IS_LNK_SYNC_M1	BIT_20		/* Link Sync Cnt wrap MAC 1 */
-#define IS_MAC2			BIT_19		/* IRQ from MAC 2	*/
-#define IS_LNK_SYNC_M2	BIT_18		/* Link Sync Cnt wrap MAC 2 */
-/* Receive Queue 1 */
-#define IS_R1_B			BIT_17		/* Q_R1 End of Buffer */
-#define IS_R1_F			BIT_16		/* Q_R1 End of Frame */
-#define IS_R1_C			BIT_15		/* Q_R1 Encoding Error */
-/* Receive Queue 2 */
-#define IS_R2_B			BIT_14		/* Q_R2 End of Buffer */
-#define IS_R2_F			BIT_13		/* Q_R2 End of Frame */
-#define IS_R2_C			BIT_12		/* Q_R2 Encoding Error */
-/* Synchronous Transmit Queue 1 */
-#define IS_XS1_B		BIT_11		/* Q_XS1 End of Buffer */
-#define IS_XS1_F		BIT_10		/* Q_XS1 End of Frame */
-#define IS_XS1_C		BIT_9		/* Q_XS1 Encoding Error */
-/* Asynchronous Transmit Queue 1 */
-#define IS_XA1_B		BIT_8		/* Q_XA1 End of Buffer */
-#define IS_XA1_F		BIT_7		/* Q_XA1 End of Frame */
-#define IS_XA1_C		BIT_6		/* Q_XA1 Encoding Error */
-/* Synchronous Transmit Queue 2 */
-#define IS_XS2_B		BIT_5		/* Q_XS2 End of Buffer */
-#define IS_XS2_F		BIT_4		/* Q_XS2 End of Frame */
-#define IS_XS2_C		BIT_3		/* Q_XS2 Encoding Error */
-/* Asynchronous Transmit Queue 2 */
-#define IS_XA2_B		BIT_2		/* Q_XA2 End of Buffer */
-#define IS_XA2_F		BIT_1		/* Q_XA2 End of Frame */
-#define IS_XA2_C		BIT_0		/* Q_XA2 Encoding Error */
-
-
-/*	B0_HWE_ISRC		32 bit	HW Error Interrupt Src Reg */
-/*	B0_HWE_IMSK		32 bit	HW Error Interrupt Mask Reg */
-/*	B2_IRQM_HWE_MSK	32 bit	IRQ Moderation HW Error Mask */
-#define IS_ERR_MSK		0x00000fffL	/* 		All Error bits */
-								/* Bit 31..14:	reserved */
-#define IS_IRQ_TIST_OV	BIT_13	/* Time Stamp Timer Overflow (YUKON only) */
-#define IS_IRQ_SENSOR	BIT_12	/* IRQ from Sensor (YUKON only) */
-#define IS_IRQ_MST_ERR	BIT_11	/* IRQ master error detected */
-#define IS_IRQ_STAT		BIT_10	/* IRQ status exception */
-#define IS_NO_STAT_M1	BIT_9	/* No Rx Status from MAC 1 */
-#define IS_NO_STAT_M2	BIT_8	/* No Rx Status from MAC 2 */
-#define IS_NO_TIST_M1	BIT_7	/* No Time Stamp from MAC 1 */
-#define IS_NO_TIST_M2	BIT_6	/* No Time Stamp from MAC 2 */
-#define IS_RAM_RD_PAR	BIT_5	/* RAM Read  Parity Error */
-#define IS_RAM_WR_PAR	BIT_4	/* RAM Write Parity Error */
-#define IS_M1_PAR_ERR	BIT_3	/* MAC 1 Parity Error */
-#define IS_M2_PAR_ERR	BIT_2	/* MAC 2 Parity Error */
-#define IS_R1_PAR_ERR	BIT_1	/* Queue R1 Parity Error */
-#define IS_R2_PAR_ERR	BIT_0	/* Queue R2 Parity Error */
-
-/*	B2_CONN_TYP		 8 bit	Connector type */
-/*	B2_PMD_TYP		 8 bit	PMD type */
-/*	Values of connector and PMD type comply to SysKonnect internal std */
-
-/*	B2_MAC_CFG		 8 bit	MAC Configuration / Chip Revision */
-#define CFG_CHIP_R_MSK	(0xf<<4)	/* Bit 7.. 4: Chip Revision */
-									/* Bit 3.. 2:	reserved */
-#define CFG_DIS_M2_CLK	BIT_1S		/* Disable Clock for 2nd MAC */
-#define CFG_SNG_MAC		BIT_0S		/* MAC Config: 0=2 MACs / 1=1 MAC*/
-
-/*	B2_CHIP_ID		 8 bit 	Chip Identification Number */
-#define CHIP_ID_GENESIS		0x0a	/* Chip ID for GENESIS */
-#define CHIP_ID_YUKON		0xb0	/* Chip ID for YUKON */
-#define CHIP_ID_YUKON_LITE	0xb1	/* Chip ID for YUKON-Lite (Rev. A1-A3) */
-#define CHIP_ID_YUKON_LP	0xb2	/* Chip ID for YUKON-LP */
-
-#define CHIP_REV_YU_LITE_A1	3		/* Chip Rev. for YUKON-Lite A1,A2 */
-#define CHIP_REV_YU_LITE_A3	7		/* Chip Rev. for YUKON-Lite A3 */
-
-/*	B2_FAR			32 bit	Flash-Prom Addr Reg/Cnt */
-#define FAR_ADDR		0x1ffffL	/* Bit 16.. 0:	FPROM Address mask */
-
-/*	B2_LD_CTRL		 8 bit	EPROM loader control register */
-/*	Bits are currently reserved */
-
-/*	B2_LD_TEST		 8 bit	EPROM loader test register */
-								/* Bit 7.. 4:	reserved */
-#define LD_T_ON			BIT_3S	/* Loader Test mode on */
-#define LD_T_OFF		BIT_2S	/* Loader Test mode off */
-#define LD_T_STEP		BIT_1S	/* Decrement FPROM addr. Counter */
-#define LD_START		BIT_0S	/* Start loading FPROM */
-
-/*
- *	Timer Section
- */
-/*	B2_TI_CTRL		 8 bit	Timer control */
-/*	B2_IRQM_CTRL	 8 bit	IRQ Moderation Timer Control */
-								/* Bit 7.. 3:	reserved */
-#define TIM_START		BIT_2S	/* Start Timer */
-#define TIM_STOP		BIT_1S	/* Stop  Timer */
-#define TIM_CLR_IRQ		BIT_0S	/* Clear Timer IRQ (!IRQM) */
-
-/*	B2_TI_TEST		 8 Bit	Timer Test */
-/*	B2_IRQM_TEST	 8 bit	IRQ Moderation Timer Test */
-/*	B28_DPT_TST		 8 bit	Descriptor Poll Timer Test Reg */
-								/* Bit 7.. 3:	reserved */
-#define TIM_T_ON		BIT_2S	/* Test mode on */
-#define TIM_T_OFF		BIT_1S	/* Test mode off */
-#define TIM_T_STEP		BIT_0S	/* Test step */
-
-/*	B28_DPT_INI	32 bit	Descriptor Poll Timer Init Val */
-/*	B28_DPT_VAL	32 bit	Descriptor Poll Timer Curr Val */
-								/* Bit 31..24:	reserved */
-#define DPT_MSK		0x00ffffffL	/* Bit 23.. 0:	Desc Poll Timer Bits */
-
-/*	B28_DPT_CTRL	 8 bit	Descriptor Poll Timer Ctrl Reg */
-								/* Bit  7.. 2:	reserved */
-#define DPT_START		BIT_1S	/* Start Descriptor Poll Timer */
-#define DPT_STOP		BIT_0S	/* Stop  Descriptor Poll Timer */
-
-/*	B2_E_3			 8 bit 	lower 4 bits used for HW self test result */
-#define B2_E3_RES_MASK	0x0f
-
-/*	B2_TST_CTRL1	 8 bit	Test Control Register 1 */
-#define TST_FRC_DPERR_MR	BIT_7S	/* force DATAPERR on MST RD */
-#define TST_FRC_DPERR_MW	BIT_6S	/* force DATAPERR on MST WR */
-#define TST_FRC_DPERR_TR	BIT_5S	/* force DATAPERR on TRG RD */
-#define TST_FRC_DPERR_TW	BIT_4S	/* force DATAPERR on TRG WR */
-#define TST_FRC_APERR_M		BIT_3S	/* force ADDRPERR on MST */
-#define TST_FRC_APERR_T		BIT_2S	/* force ADDRPERR on TRG */
-#define TST_CFG_WRITE_ON	BIT_1S	/* Enable  Config Reg WR */
-#define TST_CFG_WRITE_OFF	BIT_0S	/* Disable Config Reg WR */
-
-/*	B2_TST_CTRL2	 8 bit	Test Control Register 2 */
-									/* Bit 7.. 4:	reserved */
-			/* force the following error on the next master read/write	*/
-#define TST_FRC_DPERR_MR64	BIT_3S	/* DataPERR RD 64	*/
-#define TST_FRC_DPERR_MW64	BIT_2S	/* DataPERR WR 64	*/
-#define TST_FRC_APERR_1M64	BIT_1S	/* AddrPERR on 1. phase */
-#define TST_FRC_APERR_2M64	BIT_0S	/* AddrPERR on 2. phase */
-
-/*	B2_GP_IO		32 bit	General Purpose I/O Register */
-							/* Bit 31..26:	reserved */
-#define GP_DIR_9	BIT_25	/* IO_9 direct, 0=In/1=Out */
-#define GP_DIR_8	BIT_24	/* IO_8 direct, 0=In/1=Out */
-#define GP_DIR_7	BIT_23	/* IO_7 direct, 0=In/1=Out */
-#define GP_DIR_6	BIT_22	/* IO_6 direct, 0=In/1=Out */
-#define GP_DIR_5	BIT_21	/* IO_5 direct, 0=In/1=Out */
-#define GP_DIR_4	BIT_20	/* IO_4 direct, 0=In/1=Out */
-#define GP_DIR_3	BIT_19	/* IO_3 direct, 0=In/1=Out */
-#define GP_DIR_2	BIT_18	/* IO_2 direct, 0=In/1=Out */
-#define GP_DIR_1	BIT_17	/* IO_1 direct, 0=In/1=Out */
-#define GP_DIR_0	BIT_16	/* IO_0 direct, 0=In/1=Out */
-						/* Bit 15..10:	reserved */
-#define GP_IO_9		BIT_9	/* IO_9 pin */
-#define GP_IO_8		BIT_8	/* IO_8 pin */
-#define GP_IO_7		BIT_7	/* IO_7 pin */
-#define GP_IO_6		BIT_6	/* IO_6 pin */
-#define GP_IO_5		BIT_5	/* IO_5 pin */
-#define GP_IO_4		BIT_4	/* IO_4 pin */
-#define GP_IO_3		BIT_3	/* IO_3 pin */
-#define GP_IO_2		BIT_2	/* IO_2 pin */
-#define GP_IO_1		BIT_1	/* IO_1 pin */
-#define GP_IO_0		BIT_0	/* IO_0 pin */
-
-/*	B2_I2C_CTRL		32 bit	I2C HW Control Register */
-#define I2C_FLAG		BIT_31		/* Start read/write if WR */
-#define I2C_ADDR		(0x7fffL<<16)	/* Bit 30..16:	Addr to be RD/WR */
-#define I2C_DEV_SEL		(0x7fL<<9)		/* Bit 15.. 9:	I2C Device Select */
-								/* Bit	8.. 5:	reserved	*/
-#define I2C_BURST_LEN	BIT_4		/* Burst Len, 1/4 bytes */
-#define I2C_DEV_SIZE	(7<<1)		/* Bit	3.. 1:	I2C Device Size	*/
-#define I2C_025K_DEV	(0<<1)		/*		0: 256 Bytes or smal. */
-#define I2C_05K_DEV		(1<<1)		/* 		1: 512	Bytes	*/
-#define I2C_1K_DEV		(2<<1)		/*		2: 1024 Bytes	*/
-#define I2C_2K_DEV		(3<<1)		/*		3: 2048	Bytes	*/
-#define I2C_4K_DEV		(4<<1)		/*		4: 4096 Bytes	*/
-#define I2C_8K_DEV		(5<<1)		/*		5: 8192 Bytes	*/
-#define I2C_16K_DEV		(6<<1)		/*		6: 16384 Bytes	*/
-#define I2C_32K_DEV		(7<<1)		/*		7: 32768 Bytes	*/
-#define I2C_STOP		BIT_0		/* Interrupt I2C transfer */
-
-/*	B2_I2C_IRQ		32 bit	I2C HW IRQ Register */
-								/* Bit 31.. 1	reserved */
-#define I2C_CLR_IRQ		BIT_0	/* Clear I2C IRQ */
-
-/*	B2_I2C_SW		32 bit (8 bit access)	I2C HW SW Port Register */
-								/* Bit  7.. 3:	reserved */
-#define I2C_DATA_DIR	BIT_2S		/* direction of I2C_DATA */
-#define I2C_DATA		BIT_1S		/* I2C Data Port	*/
-#define I2C_CLK			BIT_0S		/* I2C Clock Port	*/
-
-/*
- * I2C Address
- */
-#define I2C_SENS_ADDR	LM80_ADDR	/* I2C Sensor Address, (Volt and Temp)*/
-
-
-/*	B2_BSC_CTRL		 8 bit	Blink Source Counter Control */
-							/* Bit  7.. 2:	reserved */
-#define BSC_START	BIT_1S		/* Start Blink Source Counter */
-#define BSC_STOP	BIT_0S		/* Stop  Blink Source Counter */
-
-/*	B2_BSC_STAT		 8 bit	Blink Source Counter Status */
-							/* Bit  7.. 1:	reserved */
-#define BSC_SRC		BIT_0S		/* Blink Source, 0=Off / 1=On */
-
-/*	B2_BSC_TST		16 bit	Blink Source Counter Test Reg */
-#define BSC_T_ON	BIT_2S		/* Test mode on */
-#define BSC_T_OFF	BIT_1S		/* Test mode off */
-#define BSC_T_STEP	BIT_0S		/* Test step */
-
-
-/*	B3_RAM_ADDR		32 bit	RAM Address, to read or write */
-					/* Bit 31..19:	reserved */
-#define RAM_ADR_RAN	0x0007ffffL	/* Bit 18.. 0:	RAM Address Range */
-
-/* RAM Interface Registers */
-/*	B3_RI_CTRL		16 bit	RAM Iface Control Register */
-								/* Bit 15..10:	reserved */
-#define RI_CLR_RD_PERR	BIT_9S	/* Clear IRQ RAM Read Parity Err */
-#define RI_CLR_WR_PERR	BIT_8S	/* Clear IRQ RAM Write Parity Err*/
-								/* Bit	7.. 2:	reserved */
-#define RI_RST_CLR		BIT_1S	/* Clear RAM Interface Reset */
-#define RI_RST_SET		BIT_0S	/* Set   RAM Interface Reset */
-
-/*	B3_RI_TEST		 8 bit	RAM Iface Test Register */
-								/* Bit 15.. 4:	reserved */
-#define RI_T_EV			BIT_3S	/* Timeout Event occured */
-#define RI_T_ON			BIT_2S	/* Timeout Timer Test On */
-#define RI_T_OFF		BIT_1S	/* Timeout Timer Test Off */
-#define RI_T_STEP		BIT_0S	/* Timeout Timer Step */
-
-/* MAC Arbiter Registers */
-/*	B3_MA_TO_CTRL	16 bit	MAC Arbiter Timeout Ctrl Reg */
-								/* Bit 15.. 4:	reserved */
-#define MA_FOE_ON		BIT_3S	/* XMAC Fast Output Enable ON */
-#define MA_FOE_OFF		BIT_2S	/* XMAC Fast Output Enable OFF */
-#define MA_RST_CLR		BIT_1S	/* Clear MAC Arbiter Reset */
-#define MA_RST_SET		BIT_0S	/* Set   MAC Arbiter Reset */
-
-/*	B3_MA_RC_CTRL	16 bit	MAC Arbiter Recovery Ctrl Reg */
-								/* Bit 15.. 8:	reserved */
-#define MA_ENA_REC_TX2	BIT_7S	/* Enable  Recovery Timer TX2 */
-#define MA_DIS_REC_TX2	BIT_6S	/* Disable Recovery Timer TX2 */
-#define MA_ENA_REC_TX1	BIT_5S	/* Enable  Recovery Timer TX1 */
-#define MA_DIS_REC_TX1	BIT_4S	/* Disable Recovery Timer TX1 */
-#define MA_ENA_REC_RX2	BIT_3S	/* Enable  Recovery Timer RX2 */
-#define MA_DIS_REC_RX2	BIT_2S	/* Disable Recovery Timer RX2 */
-#define MA_ENA_REC_RX1	BIT_1S	/* Enable  Recovery Timer RX1 */
-#define MA_DIS_REC_RX1	BIT_0S	/* Disable Recovery Timer RX1 */
-
-/* Packet Arbiter Registers */
-/*	B3_PA_CTRL		16 bit	Packet Arbiter Ctrl Register */
-								/* Bit 15..14:	reserved */
-#define PA_CLR_TO_TX2	BIT_13S	/* Clear IRQ Packet Timeout TX2 */
-#define PA_CLR_TO_TX1	BIT_12S	/* Clear IRQ Packet Timeout TX1 */
-#define PA_CLR_TO_RX2	BIT_11S	/* Clear IRQ Packet Timeout RX2 */
-#define PA_CLR_TO_RX1	BIT_10S	/* Clear IRQ Packet Timeout RX1 */
-#define PA_ENA_TO_TX2	BIT_9S	/* Enable  Timeout Timer TX2 */
-#define PA_DIS_TO_TX2	BIT_8S	/* Disable Timeout Timer TX2 */
-#define PA_ENA_TO_TX1	BIT_7S	/* Enable  Timeout Timer TX1 */
-#define PA_DIS_TO_TX1	BIT_6S	/* Disable Timeout Timer TX1 */
-#define PA_ENA_TO_RX2	BIT_5S	/* Enable  Timeout Timer RX2 */
-#define PA_DIS_TO_RX2	BIT_4S	/* Disable Timeout Timer RX2 */
-#define PA_ENA_TO_RX1	BIT_3S	/* Enable  Timeout Timer RX1 */
-#define PA_DIS_TO_RX1	BIT_2S	/* Disable Timeout Timer RX1 */
-#define PA_RST_CLR		BIT_1S	/* Clear MAC Arbiter Reset */
-#define PA_RST_SET		BIT_0S	/* Set   MAC Arbiter Reset */
-
-#define PA_ENA_TO_ALL	(PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\
-						PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
-
-/* Rx/Tx Path related Arbiter Test Registers */
-/*	B3_MA_TO_TEST	16 bit	MAC Arbiter Timeout Test Reg */
-/*	B3_MA_RC_TEST	16 bit	MAC Arbiter Recovery Test Reg */
-/*	B3_PA_TEST		16 bit	Packet Arbiter Test Register */
-/*			Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */
-#define TX2_T_EV	BIT_15S		/* TX2 Timeout/Recv Event occured */
-#define TX2_T_ON	BIT_14S		/* TX2 Timeout/Recv Timer Test On */
-#define TX2_T_OFF	BIT_13S		/* TX2 Timeout/Recv Timer Tst Off */
-#define TX2_T_STEP	BIT_12S		/* TX2 Timeout/Recv Timer Step */
-#define TX1_T_EV	BIT_11S		/* TX1 Timeout/Recv Event occured */
-#define TX1_T_ON	BIT_10S		/* TX1 Timeout/Recv Timer Test On */
-#define TX1_T_OFF	BIT_9S		/* TX1 Timeout/Recv Timer Tst Off */
-#define TX1_T_STEP	BIT_8S		/* TX1 Timeout/Recv Timer Step */
-#define RX2_T_EV	BIT_7S		/* RX2 Timeout/Recv Event occured */
-#define RX2_T_ON	BIT_6S		/* RX2 Timeout/Recv Timer Test On */
-#define RX2_T_OFF	BIT_5S		/* RX2 Timeout/Recv Timer Tst Off */
-#define RX2_T_STEP	BIT_4S		/* RX2 Timeout/Recv Timer Step */
-#define RX1_T_EV	BIT_3S		/* RX1 Timeout/Recv Event occured */
-#define RX1_T_ON	BIT_2S		/* RX1 Timeout/Recv Timer Test On */
-#define RX1_T_OFF	BIT_1S		/* RX1 Timeout/Recv Timer Tst Off */
-#define RX1_T_STEP	BIT_0S		/* RX1 Timeout/Recv Timer Step */
-
-
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
-/*	TXA_ITI_INI		32 bit	Tx Arb Interval Timer Init Val */
-/*	TXA_ITI_VAL		32 bit	Tx Arb Interval Timer Value */
-/*	TXA_LIM_INI		32 bit	Tx Arb Limit Counter Init Val */
-/*	TXA_LIM_VAL		32 bit	Tx Arb Limit Counter Value */
-								/* Bit 31..24:	reserved */
-#define TXA_MAX_VAL	0x00ffffffUL/* Bit 23.. 0:	Max TXA Timer/Cnt Val */
-
-/*	TXA_CTRL		 8 bit	Tx Arbiter Control Register */
-#define TXA_ENA_FSYNC	BIT_7S	/* Enable  force of sync Tx queue */
-#define TXA_DIS_FSYNC	BIT_6S	/* Disable force of sync Tx queue */
-#define TXA_ENA_ALLOC	BIT_5S	/* Enable  alloc of free bandwidth */
-#define TXA_DIS_ALLOC	BIT_4S	/* Disable alloc of free bandwidth */
-#define TXA_START_RC	BIT_3S	/* Start sync Rate Control */
-#define TXA_STOP_RC		BIT_2S	/* Stop  sync Rate Control */
-#define TXA_ENA_ARB		BIT_1S	/* Enable  Tx Arbiter */
-#define TXA_DIS_ARB		BIT_0S	/* Disable Tx Arbiter */
-
-/*	TXA_TEST		 8 bit	Tx Arbiter Test Register */
-								/* Bit 7.. 6:	reserved */
-#define TXA_INT_T_ON	BIT_5S	/* Tx Arb Interval Timer Test On */
-#define TXA_INT_T_OFF	BIT_4S	/* Tx Arb Interval Timer Test Off */
-#define TXA_INT_T_STEP	BIT_3S	/* Tx Arb Interval Timer Step */
-#define TXA_LIM_T_ON	BIT_2S	/* Tx Arb Limit Timer Test On */
-#define TXA_LIM_T_OFF	BIT_1S	/* Tx Arb Limit Timer Test Off */
-#define TXA_LIM_T_STEP	BIT_0S	/* Tx Arb Limit Timer Step */
-
-/*	TXA_STAT		 8 bit	Tx Arbiter Status Register */
-								/* Bit 7.. 1:	reserved */
-#define TXA_PRIO_XS		BIT_0S	/* sync queue has prio to send */
-
-/*	Q_BC			32 bit	Current Byte Counter */
-								/* Bit 31..16:	reserved */
-#define BC_MAX			0xffff	/* Bit 15.. 0:	Byte counter */
-
-/* BMU Control Status Registers */
-/*	B0_R1_CSR		32 bit	BMU Ctrl/Stat Rx Queue 1 */
-/*	B0_R2_CSR		32 bit	BMU Ctrl/Stat Rx Queue 2 */
-/*	B0_XA1_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
-/*	B0_XS1_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 1 */
-/*	B0_XA2_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
-/*	B0_XS2_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 2 */
-/*	Q_CSR			32 bit	BMU Control/Status Register */
-								/* Bit 31..25:	reserved */
-#define CSR_SV_IDLE		BIT_24		/* BMU SM Idle */
-								/* Bit 23..22:	reserved */
-#define CSR_DESC_CLR	BIT_21		/* Clear Reset for Descr */
-#define CSR_DESC_SET	BIT_20		/* Set   Reset for Descr */
-#define CSR_FIFO_CLR	BIT_19		/* Clear Reset for FIFO */
-#define CSR_FIFO_SET	BIT_18		/* Set   Reset for FIFO */
-#define CSR_HPI_RUN		BIT_17		/* Release HPI SM */
-#define CSR_HPI_RST		BIT_16		/* Reset   HPI SM to Idle */
-#define CSR_SV_RUN		BIT_15		/* Release Supervisor SM */
-#define CSR_SV_RST		BIT_14		/* Reset   Supervisor SM */
-#define CSR_DREAD_RUN	BIT_13		/* Release Descr Read SM */
-#define CSR_DREAD_RST	BIT_12		/* Reset   Descr Read SM */
-#define CSR_DWRITE_RUN	BIT_11		/* Release Descr Write SM */
-#define CSR_DWRITE_RST	BIT_10		/* Reset   Descr Write SM */
-#define CSR_TRANS_RUN	BIT_9		/* Release Transfer SM */
-#define CSR_TRANS_RST	BIT_8		/* Reset   Transfer SM */
-#define CSR_ENA_POL		BIT_7		/* Enable  Descr Polling */
-#define CSR_DIS_POL		BIT_6		/* Disable Descr Polling */
-#define CSR_STOP		BIT_5		/* Stop  Rx/Tx Queue */
-#define CSR_START		BIT_4		/* Start Rx/Tx Queue */
-#define CSR_IRQ_CL_P	BIT_3		/* (Rx)	Clear Parity IRQ */
-#define CSR_IRQ_CL_B	BIT_2		/* Clear EOB IRQ */
-#define CSR_IRQ_CL_F	BIT_1		/* Clear EOF IRQ */
-#define CSR_IRQ_CL_C	BIT_0		/* Clear ERR IRQ */
-
-#define CSR_SET_RESET	(CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\
-						CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\
-						CSR_TRANS_RST)
-#define CSR_CLR_RESET	(CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\
-						CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
-						CSR_TRANS_RUN)
-
-/*	Q_F				32 bit	Flag Register */
-									/* Bit 31..28:	reserved */
-#define F_ALM_FULL		BIT_27		/* Rx FIFO: almost full */
-#define F_EMPTY			BIT_27		/* Tx FIFO: empty flag */
-#define F_FIFO_EOF		BIT_26		/* Tag (EOF Flag) bit in FIFO */
-#define F_WM_REACHED	BIT_25		/* Watermark reached */
-									/* reserved */
-#define F_FIFO_LEVEL	(0x1fL<<16)	/* Bit 23..16:	# of Qwords in FIFO */
-									/* Bit 15..11: 	reserved */
-#define F_WATER_MARK	0x0007ffL	/* Bit 10.. 0:	Watermark */
-
-/*	Q_T1			32 bit	Test Register 1 */
-/*		Holds four State Machine control Bytes */
-#define SM_CTRL_SV_MSK	(0xffL<<24)	/* Bit 31..24:	Control Supervisor SM */
-#define SM_CTRL_RD_MSK	(0xffL<<16)	/* Bit 23..16:	Control Read Desc SM */
-#define SM_CTRL_WR_MSK	(0xffL<<8)	/* Bit 15.. 8:	Control Write Desc SM */
-#define SM_CTRL_TR_MSK	0xffL		/* Bit	7.. 0:	Control Transfer SM */
-
-/*	Q_T1_TR			 8 bit	Test Register 1 Transfer SM */
-/*	Q_T1_WR			 8 bit	Test Register 1 Write Descriptor SM */
-/*	Q_T1_RD			 8 bit	Test Register 1 Read Descriptor SM */
-/*	Q_T1_SV			 8 bit	Test Register 1 Supervisor SM */
-
-/* The control status byte of each machine looks like ... */
-#define SM_STATE		0xf0	/* Bit 7.. 4:	State which shall be loaded */
-#define SM_LOAD			BIT_3S	/* Load the SM with SM_STATE */
-#define SM_TEST_ON		BIT_2S	/* Switch on SM Test Mode */
-#define SM_TEST_OFF		BIT_1S	/* Go off the Test Mode */
-#define SM_STEP			BIT_0S	/* Step the State Machine */
-/* The encoding of the states is not supported by the Diagnostics Tool */
-
-/*	Q_T2			32 bit	Test Register 2	*/
-								/* Bit 31.. 8:	reserved */
-#define T2_AC_T_ON		BIT_7	/* Address Counter Test Mode on */
-#define T2_AC_T_OFF		BIT_6	/* Address Counter Test Mode off */
-#define T2_BC_T_ON		BIT_5	/* Byte Counter Test Mode on */
-#define T2_BC_T_OFF		BIT_4	/* Byte Counter Test Mode off */
-#define T2_STEP04		BIT_3	/* Inc AC/Dec BC by 4 */
-#define T2_STEP03		BIT_2	/* Inc AC/Dec BC by 3 */
-#define T2_STEP02		BIT_1	/* Inc AC/Dec BC by 2 */
-#define T2_STEP01		BIT_0	/* Inc AC/Dec BC by 1 */
-
-/*	Q_T3			32 bit	Test Register 3	*/
-								/* Bit 31.. 7:	reserved */
-#define T3_MUX_MSK		(7<<4)	/* Bit  6.. 4:	Mux Position */
-								/* Bit  3:	reserved */
-#define T3_VRAM_MSK		7		/* Bit  2.. 0:	Virtual RAM Buffer Address */
-
-/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
-/*	RB_START		32 bit	RAM Buffer Start Address */
-/*	RB_END			32 bit	RAM Buffer End Address */
-/*	RB_WP			32 bit	RAM Buffer Write Pointer */
-/*	RB_RP			32 bit	RAM Buffer Read Pointer */
-/*	RB_RX_UTPP		32 bit	Rx Upper Threshold, Pause Pack */
-/*	RB_RX_LTPP		32 bit	Rx Lower Threshold, Pause Pack */
-/*	RB_RX_UTHP		32 bit	Rx Upper Threshold, High Prio */
-/*	RB_RX_LTHP		32 bit	Rx Lower Threshold, High Prio */
-/*	RB_PC			32 bit	RAM Buffer Packet Counter */
-/*	RB_LEV			32 bit	RAM Buffer Level Register */
-				/* Bit 31..19:	reserved */
-#define RB_MSK	0x0007ffff	/* Bit 18.. 0:	RAM Buffer Pointer Bits */
-
-/*	RB_TST2			 8 bit	RAM Buffer Test Register 2 */
-								/* Bit 7.. 4:	reserved */
-#define RB_PC_DEC		BIT_3S	/* Packet Counter Decrem */
-#define RB_PC_T_ON		BIT_2S	/* Packet Counter Test On */
-#define RB_PC_T_OFF		BIT_1S	/* Packet Counter Tst Off */
-#define RB_PC_INC		BIT_0S	/* Packet Counter Increm */
-
-/*	RB_TST1			 8 bit	RAM Buffer Test Register 1 */
-							/* Bit 7:	reserved */
-#define RB_WP_T_ON		BIT_6S	/* Write Pointer Test On */
-#define RB_WP_T_OFF		BIT_5S	/* Write Pointer Test Off */
-#define RB_WP_INC		BIT_4S	/* Write Pointer Increm */
-								/* Bit 3:	reserved */
-#define RB_RP_T_ON		BIT_2S	/* Read Pointer Test On */
-#define RB_RP_T_OFF		BIT_1S	/* Read Pointer Test Off */
-#define RB_RP_DEC		BIT_0S	/* Read Pointer Decrement */
-
-/*	RB_CTRL			 8 bit	RAM Buffer Control Register */
-								/* Bit 7.. 6:	reserved */
-#define RB_ENA_STFWD	BIT_5S	/* Enable  Store & Forward */
-#define RB_DIS_STFWD	BIT_4S	/* Disable Store & Forward */
-#define RB_ENA_OP_MD	BIT_3S	/* Enable  Operation Mode */
-#define RB_DIS_OP_MD	BIT_2S	/* Disable Operation Mode */
-#define RB_RST_CLR		BIT_1S	/* Clear RAM Buf STM Reset */
-#define RB_RST_SET		BIT_0S	/* Set   RAM Buf STM Reset */
-
-
-/* Receive and Transmit MAC FIFO Registers (GENESIS only) */
-
-/*	RX_MFF_EA		32 bit	Receive MAC FIFO End Address */
-/*	RX_MFF_WP		32 bit 	Receive MAC FIFO Write Pointer */
-/*	RX_MFF_RP		32 bit	Receive MAC FIFO Read Pointer */
-/*	RX_MFF_PC		32 bit	Receive MAC FIFO Packet Counter */
-/*	RX_MFF_LEV		32 bit	Receive MAC FIFO Level */
-/*	TX_MFF_EA		32 bit	Transmit MAC FIFO End Address */
-/*	TX_MFF_WP		32 bit 	Transmit MAC FIFO Write Pointer */
-/*	TX_MFF_WSP		32 bit	Transmit MAC FIFO WR Shadow Pointer */
-/*	TX_MFF_RP		32 bit	Transmit MAC FIFO Read Pointer */
-/*	TX_MFF_PC		32 bit	Transmit MAC FIFO Packet Cnt */
-/*	TX_MFF_LEV		32 bit	Transmit MAC FIFO Level */
-								/* Bit 31.. 6:	reserved */
-#define MFF_MSK			0x007fL	/* Bit	5.. 0:	MAC FIFO Address/Ptr Bits */
-
-/*	RX_MFF_CTRL1	16 bit	Receive MAC FIFO Control Reg 1 */
-								/* Bit 15..14:	reserved */
-#define MFF_ENA_RDY_PAT	BIT_13S		/* Enable  Ready Patch */
-#define MFF_DIS_RDY_PAT	BIT_12S		/* Disable Ready Patch */
-#define MFF_ENA_TIM_PAT	BIT_11S		/* Enable  Timing Patch */
-#define MFF_DIS_TIM_PAT	BIT_10S		/* Disable Timing Patch */
-#define MFF_ENA_ALM_FUL	BIT_9S		/* Enable  AlmostFull Sign */
-#define MFF_DIS_ALM_FUL	BIT_8S		/* Disable AlmostFull Sign */
-#define MFF_ENA_PAUSE	BIT_7S		/* Enable  Pause Signaling */
-#define MFF_DIS_PAUSE	BIT_6S		/* Disable Pause Signaling */
-#define MFF_ENA_FLUSH	BIT_5S		/* Enable  Frame Flushing */
-#define MFF_DIS_FLUSH	BIT_4S		/* Disable Frame Flushing */
-#define MFF_ENA_TIST	BIT_3S		/* Enable  Time Stamp Gener */
-#define MFF_DIS_TIST	BIT_2S		/* Disable Time Stamp Gener */
-#define MFF_CLR_INTIST	BIT_1S		/* Clear IRQ No Time Stamp */
-#define MFF_CLR_INSTAT	BIT_0S		/* Clear IRQ No Status */
-
-#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT
-
-/*	TX_MFF_CTRL1	16 bit	Transmit MAC FIFO Control Reg 1 */
-#define MFF_CLR_PERR	BIT_15S		/* Clear Parity Error IRQ */
-								/* Bit 14:	reserved */
-#define MFF_ENA_PKT_REC	BIT_13S		/* Enable  Packet Recovery */
-#define MFF_DIS_PKT_REC BIT_12S		/* Disable Packet Recovery */
-/*	MFF_ENA_TIM_PAT	 (see RX_MFF_CTRL1) Bit 11:	Enable  Timing Patch */
-/*	MFF_DIS_TIM_PAT	 (see RX_MFF_CTRL1) Bit 10:	Disable Timing Patch */
-/*	MFF_ENA_ALM_FUL	 (see RX_MFF_CTRL1) Bit	 9:	Enable  Almost Full Sign */
-/*	MFF_DIS_ALM_FUL	 (see RX_MFF_CTRL1) Bit	 8:	Disable Almost Full Sign */
-#define MFF_ENA_W4E		BIT_7S		/* Enable  Wait for Empty */
-#define MFF_DIS_W4E		BIT_6S		/* Disable Wait for Empty */
-/*	MFF_ENA_FLUSH	 (see RX_MFF_CTRL1) Bit	 5:	Enable  Frame Flushing */
-/*	MFF_DIS_FLUSH	 (see RX_MFF_CTRL1) Bit	 4:	Disable Frame Flushing */
-#define MFF_ENA_LOOPB	BIT_3S		/* Enable  Loopback */
-#define MFF_DIS_LOOPB	BIT_2S		/* Disable Loopback */
-#define MFF_CLR_MAC_RST	BIT_1S		/* Clear XMAC Reset */
-#define MFF_SET_MAC_RST	BIT_0S		/* Set   XMAC Reset */
-
-#define MFF_TX_CTRL_DEF	(MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH)
-
-/*	RX_MFF_TST2	 	 8 bit	Receive MAC FIFO Test Register 2 */
-/*	TX_MFF_TST2	 	 8 bit	Transmit MAC FIFO Test Register 2 */
-								/* Bit 7:	reserved */
-#define MFF_WSP_T_ON	BIT_6S	/* Tx: Write Shadow Ptr TestOn */
-#define MFF_WSP_T_OFF	BIT_5S	/* Tx: Write Shadow Ptr TstOff */
-#define MFF_WSP_INC		BIT_4S	/* Tx: Write Shadow Ptr Increment */
-#define MFF_PC_DEC		BIT_3S	/* Packet Counter Decrement */
-#define MFF_PC_T_ON		BIT_2S	/* Packet Counter Test On */
-#define MFF_PC_T_OFF	BIT_1S	/* Packet Counter Test Off */
-#define MFF_PC_INC		BIT_0S	/* Packet Counter Increment */
-
-/*	RX_MFF_TST1	 	 8 bit	Receive MAC FIFO Test Register 1 */
-/*	TX_MFF_TST1	 	 8 bit	Transmit MAC FIFO Test Register 1 */
-					/* Bit 7:	reserved */
-#define MFF_WP_T_ON		BIT_6S	/* Write Pointer Test On */
-#define MFF_WP_T_OFF	BIT_5S	/* Write Pointer Test Off */
-#define MFF_WP_INC		BIT_4S	/* Write Pointer Increm */
-							/* Bit 3:	reserved */
-#define MFF_RP_T_ON		BIT_2S	/* Read Pointer Test On */
-#define MFF_RP_T_OFF	BIT_1S	/* Read Pointer Test Off */
-#define MFF_RP_DEC		BIT_0S	/* Read Pointer Decrement */
-
-/*	RX_MFF_CTRL2	 8 bit	Receive MAC FIFO Control Reg 2 */
-/*	TX_MFF_CTRL2	 8 bit	Transmit MAC FIFO Control Reg 2 */
-								/* Bit 7..4:	reserved */
-#define MFF_ENA_OP_MD	BIT_3S	/* Enable  Operation Mode */
-#define MFF_DIS_OP_MD	BIT_2S	/* Disable Operation Mode */
-#define MFF_RST_CLR		BIT_1S	/* Clear MAC FIFO Reset */
-#define MFF_RST_SET		BIT_0S	/* Set   MAC FIFO Reset */
-
-
-/*	Link LED Counter Registers (GENESIS only) */
-
-/*	RX_LED_CTRL		 8 bit	Receive LED Cnt Control Reg */
-/*	TX_LED_CTRL		 8 bit	Transmit LED Cnt Control Reg */
-/*	LNK_SYNC_CTRL	 8 bit	Link Sync Cnt Control Register */
-							/* Bit 7.. 3:	reserved */
-#define LED_START		BIT_2S	/* Start Timer */
-#define LED_STOP		BIT_1S	/* Stop Timer */
-#define LED_STATE		BIT_0S	/* Rx/Tx: LED State, 1=LED on */
-#define LED_CLR_IRQ		BIT_0S	/* Lnk: 	Clear Link IRQ */
-
-/*	RX_LED_TST		 8 bit	Receive LED Cnt Test Register */
-/*	TX_LED_TST		 8 bit	Transmit LED Cnt Test Register */
-/*	LNK_SYNC_TST	 8 bit	Link Sync Cnt Test Register */
-							/* Bit 7.. 3:	reserved */
-#define LED_T_ON		BIT_2S	/* LED Counter Test mode On */
-#define LED_T_OFF		BIT_1S	/* LED Counter Test mode Off */
-#define LED_T_STEP		BIT_0S	/* LED Counter Step */
-
-/*	LNK_LED_REG	 	 8 bit	Link LED Register */
-								/* Bit 7.. 6:	reserved */
-#define LED_BLK_ON		BIT_5S	/* Link LED Blinking On */
-#define LED_BLK_OFF		BIT_4S	/* Link LED Blinking Off */
-#define LED_SYNC_ON		BIT_3S	/* Use Sync Wire to switch LED */
-#define LED_SYNC_OFF	BIT_2S	/* Disable Sync Wire Input */
-#define LED_ON			BIT_1S	/* switch LED on */
-#define LED_OFF			BIT_0S	/* switch LED off */
-
-/*	Receive and Transmit GMAC FIFO Registers (YUKON only) */
-
-/*	RX_GMF_EA		32 bit	Rx GMAC FIFO End Address */
-/*	RX_GMF_AF_THR	32 bit	Rx GMAC FIFO Almost Full Thresh. */
-/*	RX_GMF_WP		32 bit 	Rx GMAC FIFO Write Pointer */
-/*	RX_GMF_WLEV		32 bit 	Rx GMAC FIFO Write Level */
-/*	RX_GMF_RP		32 bit 	Rx GMAC FIFO Read Pointer */
-/*	RX_GMF_RLEV		32 bit 	Rx GMAC FIFO Read Level */
-/*	TX_GMF_EA		32 bit	Tx GMAC FIFO End Address */
-/*	TX_GMF_AE_THR	32 bit	Tx GMAC FIFO Almost Empty Thresh.*/
-/*	TX_GMF_WP		32 bit 	Tx GMAC FIFO Write Pointer */
-/*	TX_GMF_WSP		32 bit 	Tx GMAC FIFO Write Shadow Ptr. */
-/*	TX_GMF_WLEV		32 bit 	Tx GMAC FIFO Write Level */
-/*	TX_GMF_RP		32 bit 	Tx GMAC FIFO Read Pointer */
-/*	TX_GMF_RSTP		32 bit 	Tx GMAC FIFO Restart Pointer */
-/*	TX_GMF_RLEV		32 bit 	Tx GMAC FIFO Read Level */
-
-/*	RX_GMF_CTRL_T	32 bit	Rx GMAC FIFO Control/Test */
-						/* Bits 31..15:	reserved */
-#define GMF_WP_TST_ON	BIT_14		/* Write Pointer Test On */
-#define GMF_WP_TST_OFF	BIT_13		/* Write Pointer Test Off */
-#define GMF_WP_STEP		BIT_12		/* Write Pointer Step/Increment */
-						/* Bit 11:	reserved */
-#define GMF_RP_TST_ON	BIT_10		/* Read Pointer Test On */
-#define GMF_RP_TST_OFF	BIT_9		/* Read Pointer Test Off */
-#define GMF_RP_STEP		BIT_8		/* Read Pointer Step/Increment */
-#define GMF_RX_F_FL_ON	BIT_7		/* Rx FIFO Flush Mode On */
-#define GMF_RX_F_FL_OFF	BIT_6		/* Rx FIFO Flush Mode Off */
-#define GMF_CLI_RX_FO	BIT_5		/* Clear IRQ Rx FIFO Overrun */
-#define GMF_CLI_RX_FC	BIT_4		/* Clear IRQ Rx Frame Complete */
-#define GMF_OPER_ON		BIT_3		/* Operational Mode On */
-#define GMF_OPER_OFF	BIT_2		/* Operational Mode Off */
-#define GMF_RST_CLR		BIT_1		/* Clear GMAC FIFO Reset */
-#define GMF_RST_SET		BIT_0		/* Set   GMAC FIFO Reset */
-
-/*	TX_GMF_CTRL_T	32 bit	Tx GMAC FIFO Control/Test */
-						/* Bits 31..19:	reserved */
-#define GMF_WSP_TST_ON	BIT_18		/* Write Shadow Pointer Test On */
-#define GMF_WSP_TST_OFF	BIT_17		/* Write Shadow Pointer Test Off */
-#define GMF_WSP_STEP	BIT_16		/* Write Shadow Pointer Step/Increment */
-						/* Bits 15..7: same as for RX_GMF_CTRL_T */
-#define GMF_CLI_TX_FU	BIT_6		/* Clear IRQ Tx FIFO Underrun */
-#define GMF_CLI_TX_FC	BIT_5		/* Clear IRQ Tx Frame Complete */
-#define GMF_CLI_TX_PE	BIT_4		/* Clear IRQ Tx Parity Error */
-						/* Bits 3..0: same as for RX_GMF_CTRL_T */
-
-#define GMF_RX_CTRL_DEF		(GMF_OPER_ON | GMF_RX_F_FL_ON)
-#define GMF_TX_CTRL_DEF		GMF_OPER_ON
-
-#define RX_GMF_FL_THR_DEF	0x0a	/* Rx GMAC FIFO Flush Threshold default */
-
-/*	GMAC_TI_ST_CTRL	 8 bit	Time Stamp Timer Ctrl Reg (YUKON only) */
-								/* Bit 7.. 3:	reserved */
-#define GMT_ST_START	BIT_2S		/* Start Time Stamp Timer */
-#define GMT_ST_STOP		BIT_1S		/* Stop  Time Stamp Timer */
-#define GMT_ST_CLR_IRQ	BIT_0S		/* Clear Time Stamp Timer IRQ */
-
-/*	GMAC_CTRL		32 bit	GMAC Control Reg (YUKON only) */
-						/* Bits 31.. 8:	reserved */
-#define GMC_H_BURST_ON	BIT_7		/* Half Duplex Burst Mode On */
-#define GMC_H_BURST_OFF	BIT_6		/* Half Duplex Burst Mode Off */
-#define GMC_F_LOOPB_ON	BIT_5		/* FIFO Loopback On */
-#define GMC_F_LOOPB_OFF	BIT_4		/* FIFO Loopback Off */
-#define GMC_PAUSE_ON	BIT_3		/* Pause On */
-#define GMC_PAUSE_OFF	BIT_2		/* Pause Off */
-#define GMC_RST_CLR		BIT_1		/* Clear GMAC Reset */
-#define GMC_RST_SET		BIT_0		/* Set   GMAC Reset */
-
-/*	GPHY_CTRL		32 bit	GPHY Control Reg (YUKON only) */
-						/* Bits 31..29:	reserved */
-#define GPC_SEL_BDT		BIT_28	/* Select Bi-Dir. Transfer for MDC/MDIO */
-#define GPC_INT_POL_HI	BIT_27	/* IRQ Polarity is Active HIGH */
-#define GPC_75_OHM		BIT_26	/* Use 75 Ohm Termination instead of 50 */
-#define GPC_DIS_FC		BIT_25	/* Disable Automatic Fiber/Copper Detection */
-#define GPC_DIS_SLEEP	BIT_24	/* Disable Energy Detect */
-#define GPC_HWCFG_M_3	BIT_23	/* HWCFG_MODE[3] */
-#define GPC_HWCFG_M_2	BIT_22	/* HWCFG_MODE[2] */
-#define GPC_HWCFG_M_1	BIT_21	/* HWCFG_MODE[1] */
-#define GPC_HWCFG_M_0	BIT_20	/* HWCFG_MODE[0] */
-#define GPC_ANEG_0		BIT_19	/* ANEG[0] */
-#define GPC_ENA_XC		BIT_18	/* Enable MDI crossover */
-#define GPC_DIS_125		BIT_17	/* Disable 125 MHz clock */
-#define GPC_ANEG_3		BIT_16	/* ANEG[3] */
-#define GPC_ANEG_2		BIT_15	/* ANEG[2] */
-#define GPC_ANEG_1		BIT_14	/* ANEG[1] */
-#define GPC_ENA_PAUSE	BIT_13	/* Enable Pause (SYM_OR_REM) */
-#define GPC_PHYADDR_4	BIT_12	/* Bit 4 of Phy Addr */
-#define GPC_PHYADDR_3	BIT_11	/* Bit 3 of Phy Addr */
-#define GPC_PHYADDR_2	BIT_10	/* Bit 2 of Phy Addr */
-#define GPC_PHYADDR_1	BIT_9	/* Bit 1 of Phy Addr */
-#define GPC_PHYADDR_0	BIT_8	/* Bit 0 of Phy Addr */
-						/* Bits  7..2:	reserved */
-#define GPC_RST_CLR		BIT_1	/* Clear GPHY Reset */
-#define GPC_RST_SET		BIT_0	/* Set   GPHY Reset */
-
-#define GPC_HWCFG_GMII_COP	(GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \
-							 GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
-
-#define GPC_HWCFG_GMII_FIB	(				 GPC_HWCFG_M_2 | \
-							 GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
-
-#define GPC_ANEG_ADV_ALL_M	(GPC_ANEG_3 | GPC_ANEG_2 | \
-							 GPC_ANEG_1 | GPC_ANEG_0)
-
-/* forced speed and duplex mode (don't mix with other ANEG bits) */
-#define GPC_FRC10MBIT_HALF	0
-#define GPC_FRC10MBIT_FULL	GPC_ANEG_0
-#define GPC_FRC100MBIT_HALF	GPC_ANEG_1
-#define GPC_FRC100MBIT_FULL	(GPC_ANEG_0 | GPC_ANEG_1)
-
-/* auto-negotiation with limited advertised speeds */
-/* mix only with master/slave settings (for copper) */
-#define GPC_ADV_1000_HALF	GPC_ANEG_2
-#define GPC_ADV_1000_FULL	GPC_ANEG_3
-#define GPC_ADV_ALL			(GPC_ANEG_2 | GPC_ANEG_3)
-
-/* master/slave settings */
-/* only for copper with 1000 Mbps */
-#define GPC_FORCE_MASTER	0
-#define GPC_FORCE_SLAVE		GPC_ANEG_0
-#define GPC_PREF_MASTER		GPC_ANEG_1
-#define GPC_PREF_SLAVE		(GPC_ANEG_1 | GPC_ANEG_0)
-
-/*	GMAC_IRQ_SRC	 8 bit	GMAC Interrupt Source Reg (YUKON only) */
-/*	GMAC_IRQ_MSK	 8 bit	GMAC Interrupt Mask   Reg (YUKON only) */
-#define GM_IS_TX_CO_OV	BIT_5		/* Transmit Counter Overflow IRQ */
-#define GM_IS_RX_CO_OV	BIT_4		/* Receive Counter Overflow IRQ */
-#define GM_IS_TX_FF_UR	BIT_3		/* Transmit FIFO Underrun */
-#define GM_IS_TX_COMPL	BIT_2		/* Frame Transmission Complete */
-#define GM_IS_RX_FF_OR	BIT_1		/* Receive FIFO Overrun */
-#define GM_IS_RX_COMPL	BIT_0		/* Frame Reception Complete */
-
-#define GMAC_DEF_MSK	(GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \
-						GM_IS_TX_FF_UR)
-
-/*	GMAC_LINK_CTRL	16 bit	GMAC Link Control Reg (YUKON only) */
-						/* Bits 15.. 2:	reserved */
-#define GMLC_RST_CLR	BIT_1S		/* Clear GMAC Link Reset */
-#define GMLC_RST_SET	BIT_0S		/* Set   GMAC Link Reset */
-
-
-/*	WOL_CTRL_STAT	16 bit	WOL Control/Status Reg */
-#define WOL_CTL_LINK_CHG_OCC			BIT_15S
-#define WOL_CTL_MAGIC_PKT_OCC			BIT_14S
-#define WOL_CTL_PATTERN_OCC				BIT_13S
-
-#define WOL_CTL_CLEAR_RESULT			BIT_12S
-
-#define WOL_CTL_ENA_PME_ON_LINK_CHG		BIT_11S
-#define WOL_CTL_DIS_PME_ON_LINK_CHG		BIT_10S
-#define WOL_CTL_ENA_PME_ON_MAGIC_PKT	BIT_9S
-#define WOL_CTL_DIS_PME_ON_MAGIC_PKT	BIT_8S
-#define WOL_CTL_ENA_PME_ON_PATTERN		BIT_7S
-#define WOL_CTL_DIS_PME_ON_PATTERN		BIT_6S
-
-#define WOL_CTL_ENA_LINK_CHG_UNIT		BIT_5S
-#define WOL_CTL_DIS_LINK_CHG_UNIT		BIT_4S
-#define WOL_CTL_ENA_MAGIC_PKT_UNIT		BIT_3S
-#define WOL_CTL_DIS_MAGIC_PKT_UNIT		BIT_2S
-#define WOL_CTL_ENA_PATTERN_UNIT		BIT_1S
-#define WOL_CTL_DIS_PATTERN_UNIT		BIT_0S
-
-#define WOL_CTL_DEFAULT				\
-	(WOL_CTL_DIS_PME_ON_LINK_CHG |	\
-	WOL_CTL_DIS_PME_ON_PATTERN |	\
-	WOL_CTL_DIS_PME_ON_MAGIC_PKT |	\
-	WOL_CTL_DIS_LINK_CHG_UNIT |		\
-	WOL_CTL_DIS_PATTERN_UNIT |		\
-	WOL_CTL_DIS_MAGIC_PKT_UNIT)
-
-/*	WOL_MATCH_CTL	 8 bit	WOL Match Control Reg */
-#define WOL_CTL_PATT_ENA(x)				(BIT_0 << (x))
-
-#define SK_NUM_WOL_PATTERN		7
-#define SK_PATTERN_PER_WORD		4
-#define SK_BITMASK_PATTERN		7
-#define SK_POW_PATTERN_LENGTH	128
-
-#define WOL_LENGTH_MSK		0x7f
-#define WOL_LENGTH_SHIFT	8
-
-
-/* Receive and Transmit Descriptors ******************************************/
-
-/* Transmit Descriptor struct */
-typedef	struct s_HwTxd {
-	SK_U32 volatile	TxCtrl;	/* Transmit Buffer Control Field */
-	SK_U32	TxNext;			/* Physical Address Pointer to the next TxD */
-	SK_U32	TxAdrLo;		/* Physical Tx Buffer Address lower dword */
-	SK_U32	TxAdrHi;		/* Physical Tx Buffer Address upper dword */
-	SK_U32	TxStat;			/* Transmit Frame Status Word */
-#ifndef	SK_USE_REV_DESC
-	SK_U16	TxTcpOffs;		/* TCP Checksum Calculation Start Value */
-	SK_U16	TxRes1;			/* 16 bit reserved field */
-	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
-	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
-#else	/* SK_USE_REV_DESC */
-	SK_U16	TxRes1;			/* 16 bit reserved field */
-	SK_U16	TxTcpOffs;		/* TCP Checksum Calculation Start Value */
-	SK_U16	TxTcpSp;		/* TCP Checksum Calculation Start Position */
-	SK_U16	TxTcpWp;		/* TCP Checksum Write Position */
-#endif	/* SK_USE_REV_DESC */
-	SK_U32  TxRes2;			/* 32 bit reserved field */
-} SK_HWTXD;
-
-/* Receive Descriptor struct */
-typedef	struct s_HwRxd {
-	SK_U32 volatile RxCtrl;	/* Receive Buffer Control Field */
-	SK_U32	RxNext;			/* Physical Address Pointer to the next RxD */
-	SK_U32	RxAdrLo;		/* Physical Rx Buffer Address lower dword */
-	SK_U32	RxAdrHi;		/* Physical Rx Buffer Address upper dword */
-	SK_U32	RxStat;			/* Receive Frame Status Word */
-	SK_U32	RxTiSt;			/* Receive Time Stamp (from XMAC on GENESIS) */
-#ifndef	SK_USE_REV_DESC
-	SK_U16	RxTcpSum1;		/* TCP Checksum 1 */
-	SK_U16	RxTcpSum2;		/* TCP Checksum 2 */
-	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
-	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
-#else	/* SK_USE_REV_DESC */
-	SK_U16	RxTcpSum2;		/* TCP Checksum 2 */
-	SK_U16	RxTcpSum1;		/* TCP Checksum 1 */
-	SK_U16	RxTcpSp2;		/* TCP Checksum Calculation Start Position 2 */
-	SK_U16	RxTcpSp1;		/* TCP Checksum Calculation Start Position 1 */
-#endif	/* SK_USE_REV_DESC */
-} SK_HWRXD;
-
-/*
- * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2)
- * should set the define SK_USE_REV_DESC.
- * Structures are 'normaly' not endianess dependent. But in
- * this case the SK_U16 fields are bound to bit positions inside the
- * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord.
- * The bit positions inside a DWord are of course endianess dependent and
- * swaps if the DWord is swapped by the hardware.
- */
-
-
-/* Descriptor Bit Definition */
-/*	TxCtrl		Transmit Buffer Control Field */
-/*	RxCtrl		Receive  Buffer Control Field */
-#define BMU_OWN			BIT_31	/* OWN bit: 0=host/1=BMU */
-#define BMU_STF			BIT_30	/* Start of Frame */
-#define BMU_EOF			BIT_29	/* End of Frame */
-#define BMU_IRQ_EOB		BIT_28	/* Req "End of Buffer" IRQ */
-#define BMU_IRQ_EOF		BIT_27	/* Req "End of Frame" IRQ */
-/* TxCtrl specific bits */
-#define BMU_STFWD		BIT_26	/* (Tx)	Store & Forward Frame */
-#define BMU_NO_FCS		BIT_25	/* (Tx) Disable MAC FCS (CRC) generation */
-#define BMU_SW			BIT_24	/* (Tx)	1 bit res. for SW use */
-/* RxCtrl specific bits */
-#define BMU_DEV_0		BIT_26	/* (Rx)	Transfer data to Dev0 */
-#define BMU_STAT_VAL	BIT_25	/* (Rx)	Rx Status Valid */
-#define BMU_TIST_VAL	BIT_24	/* (Rx)	Rx TimeStamp Valid */
-								/* Bit 23..16:	BMU Check Opcodes */
-#define BMU_CHECK		(0x55L<<16)	/* Default BMU check */
-#define BMU_TCP_CHECK	(0x56L<<16)	/* Descr with TCP ext */
-#define BMU_UDP_CHECK	(0x57L<<16)	/* Descr with UDP ext (YUKON only) */
-#define BMU_BBC			0xffffL	/* Bit 15.. 0:	Buffer Byte Counter */
-
-/*	TxStat		Transmit Frame Status Word */
-/*	RxStat		Receive Frame Status Word */
-/*
- *Note: TxStat is reserved for ASIC loopback mode only
- *
- *	The Bits of the Status words are defined in xmac_ii.h
- *	(see XMR_FS bits)
- */
-
-/* macros ********************************************************************/
-
-/* Receive and Transmit Queues */
-#define Q_R1	0x0000		/* Receive Queue 1 */
-#define Q_R2	0x0080		/* Receive Queue 2 */
-#define Q_XS1	0x0200		/* Synchronous Transmit Queue 1 */
-#define Q_XA1	0x0280		/* Asynchronous Transmit Queue 1 */
-#define Q_XS2	0x0300		/* Synchronous Transmit Queue 2 */
-#define Q_XA2	0x0380		/* Asynchronous Transmit Queue 2 */
-
-/*
- *	Macro Q_ADDR()
- *
- *	Use this macro to access the Receive and Transmit Queue Registers.
- *
- * para:
- *	Queue	Queue to access.
- *				Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
- *	Offs	Queue register offset.
- *				Values: Q_D, Q_DA_L ... Q_T2, Q_T3
- *
- * usage	SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal)
- */
-#define Q_ADDR(Queue, Offs)	(B8_Q_REGS + (Queue) + (Offs))
-
-/*
- *	Macro RB_ADDR()
- *
- *	Use this macro to access the RAM Buffer Registers.
- *
- * para:
- *	Queue	Queue to access.
- *				Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
- *	Offs	Queue register offset.
- *				Values: RB_START, RB_END ... RB_LEV, RB_CTRL
- *
- * usage	SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal)
- */
-#define RB_ADDR(Queue, Offs)	(B16_RAM_REGS + (Queue) + (Offs))
-
-
-/* MAC Related Registers */
-#define MAC_1		0	/* belongs to the port near the slot */
-#define MAC_2		1	/* belongs to the port far away from the slot */
-
-/*
- *	Macro MR_ADDR()
- *
- *	Use this macro to access a MAC Related Registers inside the ASIC.
- *
- * para:
- *	Mac		MAC to access.
- *				Values: MAC_1, MAC_2
- *	Offs	MAC register offset.
- *				Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG,
- *						TX_MFF_EA, TX_MFF_WP ... TX_LED_TST
- *
- * usage	SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal)
- */
-#define MR_ADDR(Mac, Offs)	(((Mac) << 7) + (Offs))
-
-#ifdef	SK_LITTLE_ENDIAN
-#define XM_WORD_LO	0
-#define XM_WORD_HI	1
-#else	/* !SK_LITTLE_ENDIAN */
-#define XM_WORD_LO	1
-#define XM_WORD_HI	0
-#endif	/* !SK_LITTLE_ENDIAN */
-
-
-/*
- * macros to access the XMAC (GENESIS only)
- *
- * XM_IN16(),		to read a 16 bit register (e.g. XM_MMU_CMD)
- * XM_OUT16(),		to write a 16 bit register (e.g. XM_MMU_CMD)
- * XM_IN32(),		to read a 32 bit register (e.g. XM_TX_EV_CNT)
- * XM_OUT32(),		to write a 32 bit register (e.g. XM_TX_EV_CNT)
- * XM_INADDR(),		to read a network address register (e.g. XM_SRC_CHK)
- * XM_OUTADDR(),	to write a network address register (e.g. XM_SRC_CHK)
- * XM_INHASH(),		to read the XM_HSM_CHK register
- * XM_OUTHASH()		to write the XM_HSM_CHK register
- *
- * para:
- *	Mac		XMAC to access		values: MAC_1 or MAC_2
- *	IoC		I/O context needed for SK I/O macros
- *	Reg		XMAC Register to read or write
- *	(p)Val	Value or pointer to the value which should be read or written
- *
- * usage:	XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value);
- */
-
-#define XMA(Mac, Reg)									\
-	((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1))
-
-#define XM_IN16(IoC, Mac, Reg, pVal)					\
-	SK_IN16((IoC), XMA((Mac), (Reg)), (pVal))
-
-#define XM_OUT16(IoC, Mac, Reg, Val)					\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (Val))
-
-#define XM_IN32(IoC, Mac, Reg, pVal) {					\
-	SK_IN16((IoC), XMA((Mac), (Reg)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]);		\
-	SK_IN16((IoC), XMA((Mac), (Reg+2)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]);		\
-}
-
-#define XM_OUT32(IoC, Mac, Reg, Val) {										\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\
-}
-
-/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */
-
-#define XM_INADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_IN16((IoC), XMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define XM_OUTADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff) |				\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff) |				\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff) |				\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-}
-
-#define XM_INHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_IN16((IoC), XMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word);			\
-	pByte[6] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[7] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define XM_OUTHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff)|					\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff)|					\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff)|					\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16)		\
-		(((SK_U16)(pByte[6]) & 0x00ff)|					\
-		(((SK_U16)(pByte[7]) << 8) & 0xff00)));			\
-}
-
-/*
- * macros to access the GMAC (YUKON only)
- *
- * GM_IN16(),		to read  a 16 bit register (e.g. GM_GP_STAT)
- * GM_OUT16(),		to write a 16 bit register (e.g. GM_GP_CTRL)
- * GM_IN32(),		to read  a 32 bit register (e.g. GM_)
- * GM_OUT32(),		to write a 32 bit register (e.g. GM_)
- * GM_INADDR(),		to read  a network address register (e.g. GM_SRC_ADDR_1L)
- * GM_OUTADDR(),	to write a network address register (e.g. GM_SRC_ADDR_2L)
- * GM_INHASH(),		to read  the GM_MC_ADDR_H1 register
- * GM_OUTHASH()		to write the GM_MC_ADDR_H1 register
- *
- * para:
- *	Mac		GMAC to access		values: MAC_1 or MAC_2
- *	IoC		I/O context needed for SK I/O macros
- *	Reg		GMAC Register to read or write
- *	(p)Val	Value or pointer to the value which should be read or written
- *
- * usage:	GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value);
- */
-
-#define GMA(Mac, Reg)									\
-	((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg))
-
-#define GM_IN16(IoC, Mac, Reg, pVal)					\
-	SK_IN16((IoC), GMA((Mac), (Reg)), (pVal))
-
-#define GM_OUT16(IoC, Mac, Reg, Val)					\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (Val))
-
-#define GM_IN32(IoC, Mac, Reg, pVal) {					\
-	SK_IN16((IoC), GMA((Mac), (Reg)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]);		\
-	SK_IN16((IoC), GMA((Mac), (Reg+4)),					\
-		(SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]);		\
-}
-
-#define GM_OUT32(IoC, Mac, Reg, Val) {										\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\
-}
-
-#define GM_INADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_IN16((IoC), GMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define GM_OUTADDR(IoC, Mac, Reg, pVal) {				\
-	SK_U8	SK_FAR *pByte;								\
-	pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0];	\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff) |				\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff) |				\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff) |				\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-}
-
-#define GM_INHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U16	Word;										\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_IN16((IoC), GMA((Mac), (Reg)), &Word);			\
-	pByte[0] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[1] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word);			\
-	pByte[2] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[3] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word);			\
-	pByte[4] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[5] = (SK_U8)((Word >> 8) & 0x00ff);			\
-	SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word);		\
-	pByte[6] = (SK_U8)(Word  & 0x00ff);					\
-	pByte[7] = (SK_U8)((Word >> 8) & 0x00ff);			\
-}
-
-#define GM_OUTHASH(IoC, Mac, Reg, pVal) {				\
-	SK_U8	*pByte;										\
-	pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0];				\
-	SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)			\
-		(((SK_U16)(pByte[0]) & 0x00ff)|					\
-		(((SK_U16)(pByte[1]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)		\
-		(((SK_U16)(pByte[2]) & 0x00ff)|					\
-		(((SK_U16)(pByte[3]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16)		\
-		(((SK_U16)(pByte[4]) & 0x00ff)|					\
-		(((SK_U16)(pByte[5]) << 8) & 0xff00)));			\
-	SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16)		\
-		(((SK_U16)(pByte[6]) & 0x00ff)|					\
-		(((SK_U16)(pByte[7]) << 8) & 0xff00)));			\
-}
-
-/*
- * Different MAC Types
- */
-#define SK_MAC_XMAC		0	/* Xaqti XMAC II */
-#define SK_MAC_GMAC		1	/* Marvell GMAC */
-
-/*
- * Different PHY Types
- */
-#define SK_PHY_XMAC			0	/* integrated in XMAC II */
-#define SK_PHY_BCOM			1	/* Broadcom BCM5400 */
-#define SK_PHY_LONE			2	/* Level One LXT1000 */
-#define SK_PHY_NAT			3	/* National DP83891 */
-#define SK_PHY_MARV_COPPER	4	/* Marvell 88E1011S */
-#define SK_PHY_MARV_FIBER	5	/* Marvell 88E1011S working on fiber */
-
-/*
- * PHY addresses (bits 12..8 of PHY address reg)
- */
-#define PHY_ADDR_XMAC	(0<<8)
-#define PHY_ADDR_BCOM	(1<<8)
-#define PHY_ADDR_LONE	(3<<8)
-#define PHY_ADDR_NAT	(0<<8)
-
-/* GPHY address (bits 15..11 of SMI control reg) */
-#define PHY_ADDR_MARV	0
-
-/*
- * macros to access the PHY
- *
- * PHY_READ()		read a 16 bit value from the PHY
- * PHY_WRITE()		write a 16 bit value to the PHY
- *
- * para:
- * 	IoC		I/O context needed for SK I/O macros
- * 	pPort	Pointer to port struct for PhyAddr
- * 	Mac		XMAC to access		values: MAC_1 or MAC_2
- * 	PhyReg	PHY Register to read or write
- * 	(p)Val	Value or pointer to the value which should be read or
- *			written.
- *
- * usage:	PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value);
- * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never
- *          comes back. This is checked in DEBUG mode.
- */
-#ifndef DEBUG
-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) {						\
-	SK_U16 Mmu;  														\
-																		\
-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
-	XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));							\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);							\
-		XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));						\
-	}  																	\
-}
-#else
-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) {						\
-	SK_U16 Mmu;  														\
-	int __i = 0;														\
-																		\
-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
-	XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));							\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-			__i++;														\
-			if (__i > 100000) {											\
-				SK_DBG_PRINTF("*****************************\n");		\
-				SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n");		\
-				SK_DBG_PRINTF("*****************************\n");		\
-				break;													\
-			}															\
-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);							\
-		XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal));						\
-	}  																	\
-}
-#endif /* DEBUG */
-
-#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) {						\
-	SK_U16 Mmu;															\
-																		\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);							\
-	}  																	\
-	XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr);	\
-	XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val));							\
-	if ((pPort)->PhyType != SK_PHY_XMAC) {								\
-		do {  															\
-			XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu);					\
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);							\
-	}  																	\
-}
-
-/*
- *	Macro PCI_C()
- *
- *	Use this macro to access PCI config register from the I/O space.
- *
- * para:
- *	Addr	PCI configuration register to access.
- *			Values:	PCI_VENDOR_ID ... PCI_VPD_ADR_REG,
- *
- * usage	SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal);
- */
-#define PCI_C(Addr)	(B7_CFG_SPC + (Addr))	/* PCI Config Space */
-
-/*
- *	Macro SK_HW_ADDR(Base, Addr)
- *
- *	Calculates the effective HW address
- *
- * para:
- *	Base	I/O or memory base address
- *	Addr	Address offset
- *
- * usage:	May be used in SK_INxx and SK_OUTxx macros
- *		#define SK_IN8(pAC, Addr, pVal) ...\
- *			*pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr)))
- */
-#ifdef SK_MEM_MAPPED_IO
-#define SK_HW_ADDR(Base, Addr)	((Base) + (Addr))
-#else  /* SK_MEM_MAPPED_IO */
-#define SK_HW_ADDR(Base, Addr)	\
-			((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0)))
-#endif /* SK_MEM_MAPPED_IO */
-
-#define SZ_LONG	(sizeof(SK_U32))
-
-/*
- *	Macro SK_HWAC_LINK_LED()
- *
- *	Use this macro to set the link LED mode.
- * para:
- *	pAC		Pointer to adapter context struct
- *	IoC		I/O context needed for SK I/O macros
- *  Port	Port number
- *	Mode	Mode to set for this LED
- */
-#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \
-	SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode);
-
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKGEHW_H */
diff --git a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h
deleted file mode 100644
index e6b0016..0000000
--- a/drivers/net/sk98lin/h/skgehwt.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/******************************************************************************
- *
- * Name:	skhwt.h
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.7 $
- * Date:	$Date: 2003/09/16 12:55:08 $
- * Purpose:	Defines for the hardware timer functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKGEHWT.H	contains all defines and types for the timer functions
- */
-
-#ifndef	_SKGEHWT_H_
-#define _SKGEHWT_H_
-
-/*
- * SK Hardware Timer
- * - needed wherever the HWT module is used
- * - use in Adapters context name pAC->Hwt
- */
-typedef	struct s_Hwt {
-	SK_U32		TStart;	/* HWT start */
-	SK_U32		TStop;	/* HWT stop */
-	int		TActive;	/* HWT: flag : active/inactive */
-} SK_HWT;
-
-extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc);
-extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time);
-extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc);
-extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc);
-extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc);
-#endif	/* _SKGEHWT_H_ */
diff --git a/drivers/net/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h
deleted file mode 100644
index d9b6f6d..0000000
--- a/drivers/net/sk98lin/h/skgei2c.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgei2c.h
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.25 $
- * Date:	$Date: 2003/10/20 09:06:05 $
- * Purpose:	Special defines for TWSI
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKGEI2C.H	contains all SK-98xx specific defines for the TWSI handling
- */
-
-#ifndef _INC_SKGEI2C_H_
-#define _INC_SKGEI2C_H_
-
-/*
- * Macros to access the B2_I2C_CTRL
- */
-#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \
-	SK_OUT32(IoC, B2_I2C_CTRL,\
-		(flag ? 0x80000000UL : 0x0L) | \
-		(((SK_U32)reg << 16) & I2C_ADDR) | \
-		(((SK_U32)dev << 9) & I2C_DEV_SEL) | \
-		(dev_size & I2C_DEV_SIZE) | \
-		((burst << 4) & I2C_BURST_LEN))
-
-#define SK_I2C_STOP(IoC) {				\
-	SK_U32	I2cCtrl;				\
-	SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl);		\
-	SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP);	\
-}
-
-#define SK_I2C_GET_CTL(IoC, pI2cCtrl)	SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl)
-
-/*
- * Macros to access the TWSI SW Registers
- */
-#define SK_I2C_SET_BIT(IoC, SetBits) {			\
-	SK_U8	OrgBits;				\
-	SK_IN8(IoC, B2_I2C_SW, &OrgBits);		\
-	SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits));	\
-}
-
-#define SK_I2C_CLR_BIT(IoC, ClrBits) {			\
-	SK_U8	OrgBits;				\
-	SK_IN8(IoC, B2_I2C_SW, &OrgBits);		\
-	SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits)));	\
-}
-
-#define SK_I2C_GET_SW(IoC, pI2cSw)	SK_IN8(IoC, B2_I2C_SW, pI2cSw)
-
-/*
- * define the possible sensor states
- */
-#define	SK_SEN_IDLE		0	/* Idle: sensor not read */
-#define	SK_SEN_VALUE	1	/* Value Read cycle */
-#define	SK_SEN_VALEXT	2	/* Extended Value Read cycle */
-
-/*
- * Conversion factor to convert read Voltage sensor to milli Volt
- * Conversion factor to convert read Temperature sensor to 10th degree Celsius
- */
-#define	SK_LM80_VT_LSB		22	/* 22mV LSB resolution */
-#define	SK_LM80_TEMP_LSB	10	/* 1 degree LSB resolution */
-#define	SK_LM80_TEMPEXT_LSB	 5	/* 0.5 degree LSB resolution for ext. val. */
-
-/*
- * formula: counter = (22500*60)/(rpm * divisor * pulses/2)
- * assuming: 6500rpm, 4 pulses, divisor 1
- */
-#define SK_LM80_FAN_FAKTOR	((22500L*60)/(1*2))
-
-/*
- * Define sensor management data
- * Maximum is reached on Genesis copper dual port and Yukon-64
- * Board specific maximum is in pAC->I2c.MaxSens
- */
-#define	SK_MAX_SENSORS	8	/* maximal no. of installed sensors */
-#define	SK_MIN_SENSORS	5	/* minimal no. of installed sensors */
-
-/*
- * To watch the state machine (SM) use the timer in two ways
- * instead of one as hitherto
- */
-#define	SK_TIMER_WATCH_SM		0	/* Watch the SM to finish in a spec. time */
-#define	SK_TIMER_NEW_GAUGING	1	/* Start a new gauging when timer expires */
-
-/*
- * Defines for the individual thresholds
- */
-
-/* Temperature sensor */
-#define	SK_SEN_TEMP_HIGH_ERR	800	/* Temperature High Err  Threshold */
-#define	SK_SEN_TEMP_HIGH_WARN	700	/* Temperature High Warn Threshold */
-#define	SK_SEN_TEMP_LOW_WARN	100	/* Temperature Low  Warn Threshold */
-#define	SK_SEN_TEMP_LOW_ERR		  0	/* Temperature Low  Err  Threshold */
-
-/* VCC which should be 5 V */
-#define	SK_SEN_PCI_5V_HIGH_ERR		5588	/* Voltage PCI High Err  Threshold */
-#define	SK_SEN_PCI_5V_HIGH_WARN		5346	/* Voltage PCI High Warn Threshold */
-#define	SK_SEN_PCI_5V_LOW_WARN		4664	/* Voltage PCI Low  Warn Threshold */
-#define	SK_SEN_PCI_5V_LOW_ERR		4422	/* Voltage PCI Low  Err  Threshold */
-
-/*
- * VIO may be 5 V or 3.3 V. Initialization takes two parts:
- * 1. Initialize lowest lower limit and highest higher limit.
- * 2. After the first value is read correct the upper or the lower limit to
- *    the appropriate C constant.
- *
- * Warning limits are +-5% of the exepected voltage.
- * Error limits are +-10% of the expected voltage.
- */
-
-/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
-
-#define	SK_SEN_PCI_IO_5V_HIGH_ERR	5566	/* + 10% V PCI-IO High Err Threshold */
-#define	SK_SEN_PCI_IO_5V_HIGH_WARN	5324	/* +  5% V PCI-IO High Warn Threshold */
-					/*		5000	mVolt */
-#define	SK_SEN_PCI_IO_5V_LOW_WARN	4686	/* -  5% V PCI-IO Low Warn Threshold */
-#define	SK_SEN_PCI_IO_5V_LOW_ERR	4444	/* - 10% V PCI-IO Low Err Threshold */
-
-#define	SK_SEN_PCI_IO_RANGE_LIMITER	4000	/* 4000 mV range delimiter */
-
-/* correction values for the second pass */
-#define	SK_SEN_PCI_IO_3V3_HIGH_ERR	3850	/* + 15% V PCI-IO High Err Threshold */
-#define	SK_SEN_PCI_IO_3V3_HIGH_WARN	3674	/* + 10% V PCI-IO High Warn Threshold */
-					/*		3300	mVolt */
-#define	SK_SEN_PCI_IO_3V3_LOW_WARN	2926	/* - 10% V PCI-IO Low Warn Threshold */
-#define	SK_SEN_PCI_IO_3V3_LOW_ERR	2772	/* - 15% V PCI-IO Low Err  Threshold */
-
-/*
- * VDD voltage
- */
-#define	SK_SEN_VDD_HIGH_ERR		3630	/* Voltage ASIC High Err  Threshold */
-#define	SK_SEN_VDD_HIGH_WARN	3476	/* Voltage ASIC High Warn Threshold */
-#define	SK_SEN_VDD_LOW_WARN		3146	/* Voltage ASIC Low  Warn Threshold */
-#define	SK_SEN_VDD_LOW_ERR		2970	/* Voltage ASIC Low  Err  Threshold */
-
-/*
- * PHY PLL 3V3 voltage
- */
-#define	SK_SEN_PLL_3V3_HIGH_ERR		3630	/* Voltage PMA High Err  Threshold */
-#define	SK_SEN_PLL_3V3_HIGH_WARN	3476	/* Voltage PMA High Warn Threshold */
-#define	SK_SEN_PLL_3V3_LOW_WARN		3146	/* Voltage PMA Low  Warn Threshold */
-#define	SK_SEN_PLL_3V3_LOW_ERR		2970	/* Voltage PMA Low  Err  Threshold */
-
-/*
- * VAUX (YUKON only)
- */
-#define	SK_SEN_VAUX_3V3_HIGH_ERR	3630	/* Voltage VAUX High Err Threshold */
-#define	SK_SEN_VAUX_3V3_HIGH_WARN	3476	/* Voltage VAUX High Warn Threshold */
-#define	SK_SEN_VAUX_3V3_LOW_WARN	3146	/* Voltage VAUX Low Warn Threshold */
-#define	SK_SEN_VAUX_3V3_LOW_ERR		2970	/* Voltage VAUX Low Err Threshold */
-#define	SK_SEN_VAUX_0V_WARN_ERR		   0	/* if VAUX not present */
-#define	SK_SEN_VAUX_RANGE_LIMITER	1000	/* 1000 mV range delimiter */
-
-/*
- * PHY 2V5 voltage
- */
-#define	SK_SEN_PHY_2V5_HIGH_ERR		2750	/* Voltage PHY High Err Threshold */
-#define	SK_SEN_PHY_2V5_HIGH_WARN	2640	/* Voltage PHY High Warn Threshold */
-#define	SK_SEN_PHY_2V5_LOW_WARN		2376	/* Voltage PHY Low Warn Threshold */
-#define	SK_SEN_PHY_2V5_LOW_ERR		2222	/* Voltage PHY Low Err Threshold */
-
-/*
- * ASIC Core 1V5 voltage (YUKON only)
- */
-#define	SK_SEN_CORE_1V5_HIGH_ERR	1650	/* Voltage ASIC Core High Err Threshold */
-#define	SK_SEN_CORE_1V5_HIGH_WARN	1575	/* Voltage ASIC Core High Warn Threshold */
-#define	SK_SEN_CORE_1V5_LOW_WARN	1425	/* Voltage ASIC Core Low Warn Threshold */
-#define	SK_SEN_CORE_1V5_LOW_ERR 	1350	/* Voltage ASIC Core Low Err Threshold */
-
-/*
- * FAN 1 speed
- */
-/* assuming: 6500rpm +-15%, 4 pulses,
- * warning at:	80 %
- * error at:	70 %
- * no upper limit
- */
-#define	SK_SEN_FAN_HIGH_ERR		20000	/* FAN Speed High Err Threshold */
-#define	SK_SEN_FAN_HIGH_WARN	20000	/* FAN Speed High Warn Threshold */
-#define	SK_SEN_FAN_LOW_WARN		 5200	/* FAN Speed Low Warn Threshold */
-#define	SK_SEN_FAN_LOW_ERR		 4550	/* FAN Speed Low Err Threshold */
-
-/*
- * Some Voltages need dynamic thresholds
- */
-#define	SK_SEN_DYN_INIT_NONE		 0  /* No dynamic init of thresholds */
-#define	SK_SEN_DYN_INIT_PCI_IO		10  /* Init PCI-IO with new thresholds */
-#define	SK_SEN_DYN_INIT_VAUX		11  /* Init VAUX with new thresholds */
-
-extern	int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
-#endif	/* n_INC_SKGEI2C_H */
diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h
deleted file mode 100644
index 143e635..0000000
--- a/drivers/net/sk98lin/h/skgeinit.h
+++ /dev/null
@@ -1,797 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgeinit.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.83 $
- * Date:	$Date: 2003/09/16 14:07:37 $
- * Purpose:	Structures and prototypes for the GE Init Module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEINIT_H_
-#define __INC_SKGEINIT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_TEST_VAL		0x11335577UL
-
-/* modifying Link LED behaviour (used with SkGeLinkLED()) */
-#define SK_LNK_OFF		LED_OFF
-#define SK_LNK_ON		(LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
-#define SK_LNK_BLINK	(LED_ON | LED_BLK_ON  | LED_SYNC_ON)
-#define SK_LNK_PERM		(LED_ON | LED_BLK_OFF | LED_SYNC_ON)
-#define SK_LNK_TST		(LED_ON | LED_BLK_ON  | LED_SYNC_OFF)
-
-/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */
-#define SK_LED_OFF		LED_OFF
-#define SK_LED_ACTIVE	(LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
-#define SK_LED_STANDBY	(LED_ON | LED_BLK_ON  | LED_SYNC_OFF)
-
-/* addressing LED Registers in SkGeXmitLED() */
-#define XMIT_LED_INI	0
-#define XMIT_LED_CNT	(RX_LED_VAL - RX_LED_INI)
-#define XMIT_LED_CTRL	(RX_LED_CTRL- RX_LED_INI)
-#define XMIT_LED_TST	(RX_LED_TST - RX_LED_INI)
-
-/* parameter 'Mode' when calling SkGeXmitLED() */
-#define SK_LED_DIS	0
-#define SK_LED_ENA	1
-#define SK_LED_TST	2
-
-/* Counter and Timer constants, for a host clock of 62.5 MHz */
-#define SK_XMIT_DUR		0x002faf08UL	/*  50 ms */
-#define SK_BLK_DUR		0x01dcd650UL	/* 500 ms */
-
-#define SK_DPOLL_DEF	0x00ee6b28UL	/* 250 ms at 62.5 MHz */
-
-#define SK_DPOLL_MAX	0x00ffffffUL	/* 268 ms at 62.5 MHz */
-										/* 215 ms at 78.12 MHz */
-
-#define SK_FACT_62		100			/* is given in percent */
-#define SK_FACT_53		 85         /* on GENESIS:	53.12 MHz */
-#define SK_FACT_78		125			/* on YUKON:	78.12 MHz */
-
-/* Timeout values */
-#define SK_MAC_TO_53	72			/* MAC arbiter timeout */
-#define SK_PKT_TO_53	0x2000		/* Packet arbiter timeout */
-#define SK_PKT_TO_MAX	0xffff		/* Maximum value */
-#define SK_RI_TO_53		36			/* RAM interface timeout */
-
-#define SK_PHY_ACC_TO	600000		/* PHY access timeout */
-
-/* RAM Buffer High Pause Threshold values */
-#define SK_RB_ULPP		( 8 * 1024)	/* Upper Level in kB/8 */
-#define SK_RB_LLPP_S	(10 * 1024)	/* Lower Level for small Queues */
-#define SK_RB_LLPP_B	(16 * 1024)	/* Lower Level for big Queues */
-
-#ifndef SK_BMU_RX_WM
-#define SK_BMU_RX_WM	0x600		/* BMU Rx Watermark */
-#endif
-#ifndef SK_BMU_TX_WM
-#define SK_BMU_TX_WM	0x600		/* BMU Tx Watermark */
-#endif
-
-/* XMAC II Rx High Watermark */
-#define SK_XM_RX_HI_WM	0x05aa		/* 1450 */
-
-/* XMAC II Tx Threshold */
-#define SK_XM_THR_REDL	0x01fb		/* .. for redundant link usage */
-#define SK_XM_THR_SL	0x01fb		/* .. for single link adapters */
-#define SK_XM_THR_MULL	0x01fb		/* .. for multiple link usage */
-#define SK_XM_THR_JUMBO	0x03fc		/* .. for jumbo frame usage */
-
-/* values for GIPortUsage */
-#define SK_RED_LINK		1		/* redundant link usage */
-#define SK_MUL_LINK		2		/* multiple link usage */
-#define SK_JUMBO_LINK	3		/* driver uses jumbo frames */
-
-/* Minimum RAM Buffer Rx Queue Size */
-#define SK_MIN_RXQ_SIZE	16		/* 16 kB */
-
-/* Minimum RAM Buffer Tx Queue Size */
-#define SK_MIN_TXQ_SIZE	16		/* 16 kB */
-
-/* Queue Size units */
-#define QZ_UNITS		0x7
-#define QZ_STEP			8
-
-/* Percentage of queue size from whole memory */
-/* 80 % for receive */
-#define RAM_QUOTA_RX	80L
-/* 0% for sync transfer */
-#define	RAM_QUOTA_SYNC	0L
-/* the rest (20%) is taken for async transfer */
-
-/* Get the rounded queue size in Bytes in 8k steps */
-#define ROUND_QUEUE_SIZE(SizeInBytes)					\
-	((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) &	\
-	~(QZ_STEP-1))
-
-/* Get the rounded queue size in KBytes in 8k steps */
-#define ROUND_QUEUE_SIZE_KB(Kilobytes) \
-	ROUND_QUEUE_SIZE((Kilobytes) * 1024L)
-
-/* Types of RAM Buffer Queues */
-#define SK_RX_SRAM_Q	1	/* small receive queue */
-#define SK_RX_BRAM_Q	2	/* big receive queue */
-#define SK_TX_RAM_Q		3	/* small or big transmit queue */
-
-/* parameter 'Dir' when calling SkGeStopPort() */
-#define SK_STOP_TX	1	/* Stops the transmit path, resets the XMAC */
-#define SK_STOP_RX	2	/* Stops the receive path */
-#define SK_STOP_ALL	3	/* Stops Rx and Tx path, resets the XMAC */
-
-/* parameter 'RstMode' when calling SkGeStopPort() */
-#define SK_SOFT_RST	1	/* perform a software reset */
-#define SK_HARD_RST	2	/* perform a hardware reset */
-
-/* Init Levels */
-#define SK_INIT_DATA	0	/* Init level 0: init data structures */
-#define SK_INIT_IO		1	/* Init level 1: init with IOs */
-#define SK_INIT_RUN		2	/* Init level 2: init for run time */
-
-/* Link Mode Parameter */
-#define SK_LMODE_HALF		1	/* Half Duplex Mode */
-#define SK_LMODE_FULL		2	/* Full Duplex Mode */
-#define SK_LMODE_AUTOHALF	3	/* AutoHalf Duplex Mode */
-#define SK_LMODE_AUTOFULL	4	/* AutoFull Duplex Mode */
-#define SK_LMODE_AUTOBOTH	5	/* AutoBoth Duplex Mode */
-#define SK_LMODE_AUTOSENSE	6	/* configured mode auto sensing */
-#define SK_LMODE_INDETERMINATED	7	/* indeterminated */
-
-/* Auto-negotiation timeout in 100ms granularity */
-#define SK_AND_MAX_TO		6	/* Wait 600 msec before link comes up */
-
-/* Auto-negotiation error codes */
-#define SK_AND_OK			0	/* no error */
-#define SK_AND_OTHER		1	/* other error than below */
-#define SK_AND_DUP_CAP		2	/* Duplex capabilities error */
-
-
-/* Link Speed Capabilities */
-#define SK_LSPEED_CAP_AUTO			(1<<0)	/* Automatic resolution */
-#define SK_LSPEED_CAP_10MBPS		(1<<1)	/* 10 Mbps */
-#define SK_LSPEED_CAP_100MBPS		(1<<2)	/* 100 Mbps */
-#define SK_LSPEED_CAP_1000MBPS		(1<<3)	/* 1000 Mbps */
-#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */
-
-/* Link Speed Parameter */
-#define SK_LSPEED_AUTO				1	/* Automatic resolution */
-#define SK_LSPEED_10MBPS			2	/* 10 Mbps */
-#define SK_LSPEED_100MBPS			3	/* 100 Mbps */
-#define SK_LSPEED_1000MBPS			4	/* 1000 Mbps */
-#define SK_LSPEED_INDETERMINATED	5	/* indeterminated */
-
-/* Link Speed Current State */
-#define SK_LSPEED_STAT_UNKNOWN		1
-#define SK_LSPEED_STAT_10MBPS		2
-#define SK_LSPEED_STAT_100MBPS 		3
-#define SK_LSPEED_STAT_1000MBPS		4
-#define SK_LSPEED_STAT_INDETERMINATED 5
-
-
-/* Link Capability Parameter */
-#define SK_LMODE_CAP_HALF		(1<<0)	/* Half Duplex Mode */
-#define SK_LMODE_CAP_FULL		(1<<1)	/* Full Duplex Mode */
-#define SK_LMODE_CAP_AUTOHALF	(1<<2)	/* AutoHalf Duplex Mode */
-#define SK_LMODE_CAP_AUTOFULL	(1<<3)	/* AutoFull Duplex Mode */
-#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */
-
-/* Link Mode Current State */
-#define SK_LMODE_STAT_UNKNOWN	1	/* Unknown Duplex Mode */
-#define SK_LMODE_STAT_HALF		2	/* Half Duplex Mode */
-#define SK_LMODE_STAT_FULL		3	/* Full Duplex Mode */
-#define SK_LMODE_STAT_AUTOHALF	4	/* Half Duplex Mode obtained by Auto-Neg */
-#define SK_LMODE_STAT_AUTOFULL	5	/* Full Duplex Mode obtained by Auto-Neg */
-#define SK_LMODE_STAT_INDETERMINATED 6	/* indeterminated */
-
-/* Flow Control Mode Parameter (and capabilities) */
-#define SK_FLOW_MODE_NONE		1	/* No Flow-Control */
-#define SK_FLOW_MODE_LOC_SEND	2	/* Local station sends PAUSE */
-#define SK_FLOW_MODE_SYMMETRIC	3	/* Both stations may send PAUSE */
-#define SK_FLOW_MODE_SYM_OR_REM	4	/* Both stations may send PAUSE or
-					 * just the remote station may send PAUSE
-					 */
-#define SK_FLOW_MODE_INDETERMINATED 5	/* indeterminated */
-
-/* Flow Control Status Parameter */
-#define SK_FLOW_STAT_NONE		1	/* No Flow Control */
-#define SK_FLOW_STAT_REM_SEND	2	/* Remote Station sends PAUSE */
-#define SK_FLOW_STAT_LOC_SEND	3	/* Local station sends PAUSE */
-#define SK_FLOW_STAT_SYMMETRIC	4	/* Both station may send PAUSE */
-#define SK_FLOW_STAT_INDETERMINATED 5	/* indeterminated */
-
-/* Master/Slave Mode Capabilities */
-#define SK_MS_CAP_AUTO		(1<<0)	/* Automatic resolution */
-#define SK_MS_CAP_MASTER	(1<<1)	/* This station is master */
-#define SK_MS_CAP_SLAVE		(1<<2)	/* This station is slave */
-#define SK_MS_CAP_INDETERMINATED (1<<3)	/* indeterminated */
-
-/* Set Master/Slave Mode Parameter (and capabilities) */
-#define SK_MS_MODE_AUTO		1	/* Automatic resolution */
-#define SK_MS_MODE_MASTER	2	/* This station is master */
-#define SK_MS_MODE_SLAVE	3	/* This station is slave */
-#define SK_MS_MODE_INDETERMINATED 4	/* indeterminated */
-
-/* Master/Slave Status Parameter */
-#define SK_MS_STAT_UNSET	1	/* The M/S status is not set */
-#define SK_MS_STAT_MASTER	2	/* This station is master */
-#define SK_MS_STAT_SLAVE	3	/* This station is slave */
-#define SK_MS_STAT_FAULT	4	/* M/S resolution failed */
-#define SK_MS_STAT_INDETERMINATED 5	/* indeterminated */
-
-/* parameter 'Mode' when calling SkXmSetRxCmd() */
-#define SK_STRIP_FCS_ON		(1<<0)	/* Enable  FCS stripping of Rx frames */
-#define SK_STRIP_FCS_OFF	(1<<1)	/* Disable FCS stripping of Rx frames */
-#define SK_STRIP_PAD_ON		(1<<2)	/* Enable  pad byte stripping of Rx fr */
-#define SK_STRIP_PAD_OFF	(1<<3)	/* Disable pad byte stripping of Rx fr */
-#define SK_LENERR_OK_ON		(1<<4)	/* Don't chk fr for in range len error */
-#define SK_LENERR_OK_OFF	(1<<5)	/* Check frames for in range len error */
-#define SK_BIG_PK_OK_ON		(1<<6)	/* Don't set Rx Error bit for big frames */
-#define SK_BIG_PK_OK_OFF	(1<<7)	/* Set Rx Error bit for big frames */
-#define SK_SELF_RX_ON		(1<<8)	/* Enable  Rx of own packets */
-#define SK_SELF_RX_OFF		(1<<9)	/* Disable Rx of own packets */
-
-/* parameter 'Para' when calling SkMacSetRxTxEn() */
-#define SK_MAC_LOOPB_ON		(1<<0)	/* Enable  MAC Loopback Mode */
-#define SK_MAC_LOOPB_OFF	(1<<1)	/* Disable MAC Loopback Mode */
-#define SK_PHY_LOOPB_ON		(1<<2)	/* Enable  PHY Loopback Mode */
-#define SK_PHY_LOOPB_OFF	(1<<3)	/* Disable PHY Loopback Mode */
-#define SK_PHY_FULLD_ON		(1<<4)	/* Enable  GMII Full Duplex */
-#define SK_PHY_FULLD_OFF	(1<<5)	/* Disable GMII Full Duplex */
-
-/* States of PState */
-#define SK_PRT_RESET	0	/* the port is reset */
-#define SK_PRT_STOP		1	/* the port is stopped (similar to SW reset) */
-#define SK_PRT_INIT		2	/* the port is initialized */
-#define SK_PRT_RUN		3	/* the port has an active link */
-
-/* PHY power down modes */
-#define PHY_PM_OPERATIONAL_MODE		0	/* PHY operational mode */
-#define PHY_PM_DEEP_SLEEP			1	/* coma mode --> minimal power */
-#define PHY_PM_IEEE_POWER_DOWN		2	/* IEEE 22.2.4.1.5 compl. power down */
-#define PHY_PM_ENERGY_DETECT		3	/* energy detect */
-#define PHY_PM_ENERGY_DETECT_PLUS	4	/* energy detect plus */
-
-/* Default receive frame limit for Workaround of XMAC Errata */
-#define SK_DEF_RX_WA_LIM	SK_CONSTU64(100)
-
-/* values for GILedBlinkCtrl (LED Blink Control) */
-#define SK_ACT_LED_BLINK	(1<<0)	/* Active LED blinking */
-#define SK_DUP_LED_NORMAL	(1<<1)	/* Duplex LED normal */
-#define SK_LED_LINK100_ON	(1<<2)	/* Link 100M LED on */
-
-/* Link Partner Status */
-#define SK_LIPA_UNKNOWN	0	/* Link partner is in unknown state */
-#define SK_LIPA_MANUAL	1	/* Link partner is in detected manual state */
-#define SK_LIPA_AUTO	2	/* Link partner is in auto-negotiation state */
-
-/* Maximum Restarts before restart is ignored (3Com WA) */
-#define SK_MAX_LRESTART	3	/* Max. 3 times the link is restarted */
-
-/* Max. Auto-neg. timeouts before link detection in sense mode is reset */
-#define SK_MAX_ANEG_TO	10	/* Max. 10 times the sense mode is reset */
-
-/* structures *****************************************************************/
-
-/*
- * MAC specific functions
- */
-typedef struct s_GeMacFunc {
-	int  (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
-	int  (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
-							SK_U16 StatAddr, SK_U32 SK_FAR *pVal);
-	int  (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
-	int  (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
-						   SK_U16 IStatus, SK_U64 SK_FAR *pVal);
-} SK_GEMACFUNC;
-
-/*
- * Port Structure
- */
-typedef	struct s_GePort {
-#ifndef SK_DIAG
-	SK_TIMER	PWaTimer;	/* Workaround Timer */
-	SK_TIMER	HalfDupChkTimer;
-#endif /* SK_DIAG */
-	SK_U32	PPrevShorts;	/* Previous Short Counter checking */
-	SK_U32	PPrevFcs;		/* Previous FCS Error Counter checking */
-	SK_U64	PPrevRx;		/* Previous RxOk Counter checking */
-	SK_U64	PRxLim;			/* Previous RxOk Counter checking */
-	SK_U64	LastOctets;		/* For half duplex hang check */
-	int		PLinkResCt;		/* Link Restart Counter */
-	int		PAutoNegTimeOut;/* Auto-negotiation timeout current value */
-	int		PAutoNegTOCt;	/* Auto-negotiation Timeout Counter */
-	int		PRxQSize;		/* Port Rx Queue Size in kB */
-	int		PXSQSize;		/* Port Synchronous  Transmit Queue Size in kB */
-	int		PXAQSize;		/* Port Asynchronous Transmit Queue Size in kB */
-	SK_U32	PRxQRamStart;	/* Receive Queue RAM Buffer Start Address */
-	SK_U32	PRxQRamEnd;		/* Receive Queue RAM Buffer End Address */
-	SK_U32	PXsQRamStart;	/* Sync Tx Queue RAM Buffer Start Address */
-	SK_U32	PXsQRamEnd;		/* Sync Tx Queue RAM Buffer End Address */
-	SK_U32	PXaQRamStart;	/* Async Tx Queue RAM Buffer Start Address */
-	SK_U32	PXaQRamEnd;		/* Async Tx Queue RAM Buffer End Address */
-	SK_U32	PRxOverCnt;		/* Receive Overflow Counter */
-	int		PRxQOff;		/* Rx Queue Address Offset */
-	int		PXsQOff;		/* Synchronous Tx Queue Address Offset */
-	int		PXaQOff;		/* Asynchronous Tx Queue Address Offset */
-	int		PhyType;		/* PHY used on this port */
-	int		PState;			/* Port status (reset, stop, init, run) */
-	SK_U16	PhyId1;			/* PHY Id1 on this port */
-	SK_U16	PhyAddr;		/* MDIO/MDC PHY address */
-	SK_U16	PIsave;			/* Saved Interrupt status word */
-	SK_U16	PSsave;			/* Saved PHY status word */
-	SK_U16	PGmANegAdv;		/* Saved GPhy AutoNegAdvertisment register */
-	SK_BOOL	PHWLinkUp;		/* The hardware Link is up (wiring) */
-	SK_BOOL	PLinkBroken;	/* Is Link broken ? */
-	SK_BOOL	PCheckPar;		/* Do we check for parity errors ? */
-	SK_BOOL	HalfDupTimerActive;
-	SK_U8	PLinkCap;		/* Link Capabilities */
-	SK_U8	PLinkModeConf;	/* Link Mode configured */
-	SK_U8	PLinkMode;		/* Link Mode currently used */
-	SK_U8	PLinkModeStatus;/* Link Mode Status */
-	SK_U8	PLinkSpeedCap;	/* Link Speed Capabilities(10/100/1000 Mbps) */
-	SK_U8	PLinkSpeed;		/* configured Link Speed (10/100/1000 Mbps) */
-	SK_U8	PLinkSpeedUsed;	/* current Link Speed (10/100/1000 Mbps) */
-	SK_U8	PFlowCtrlCap;	/* Flow Control Capabilities */
-	SK_U8	PFlowCtrlMode;	/* Flow Control Mode */
-	SK_U8	PFlowCtrlStatus;/* Flow Control Status */
-	SK_U8	PMSCap;			/* Master/Slave Capabilities */
-	SK_U8	PMSMode;		/* Master/Slave Mode */
-	SK_U8	PMSStatus;		/* Master/Slave Status */
-	SK_BOOL	PAutoNegFail;	/* Auto-negotiation fail flag */
-	SK_U8	PLipaAutoNeg;	/* Auto-negotiation possible with Link Partner */
-	SK_U8	PCableLen;		/* Cable Length */
-	SK_U8	PMdiPairLen[4];	/* MDI[0..3] Pair Length */
-	SK_U8	PMdiPairSts[4];	/* MDI[0..3] Pair Diagnostic Status */
-	SK_U8	PPhyPowerState;	/* PHY current power state */
-	int		PMacColThres;	/* MAC Collision Threshold */
-	int		PMacJamLen;		/* MAC Jam length */
-	int		PMacJamIpgVal;	/* MAC Jam IPG */
-	int		PMacJamIpgData;	/* MAC IPG Jam to Data */
-	int		PMacIpgData;	/* MAC Data IPG */
-	SK_BOOL PMacLimit4;		/* reset collision counter and backoff algorithm */
-} SK_GEPORT;
-
-/*
- * Gigabit Ethernet Initialization Struct
- * (has to be included in the adapter context)
- */
-typedef	struct s_GeInit {
-	int			GIChipId;		/* Chip Identification Number */
-	int			GIChipRev;		/* Chip Revision Number */
-	SK_U8		GIPciHwRev;		/* PCI HW Revision Number */
-	SK_BOOL		GIGenesis;		/* Genesis adapter ? */
-	SK_BOOL		GIYukon;		/* YUKON-A1/Bx chip */
-	SK_BOOL		GIYukonLite;	/* YUKON-Lite chip */
-	SK_BOOL		GICopperType;	/* Copper Type adapter ? */
-	SK_BOOL		GIPciSlot64;	/* 64-bit PCI Slot */
-	SK_BOOL		GIPciClock66;	/* 66 MHz PCI Clock */
-	SK_BOOL		GIVauxAvail;	/* VAUX available (YUKON) */
-	SK_BOOL		GIYukon32Bit;	/* 32-Bit YUKON adapter */
-	SK_U16		GILedBlinkCtrl;	/* LED Blink Control */
-	int			GIMacsFound;	/* Number of MACs found on this adapter */
-	int			GIMacType;		/* MAC Type used on this adapter */
-	int			GIHstClkFact;	/* Host Clock Factor (62.5 / HstClk * 100) */
-	int			GIPortUsage;	/* Driver Port Usage */
-	int			GILevel;		/* Initialization Level completed */
-	int			GIRamSize;		/* The RAM size of the adapter in kB */
-	int			GIWolOffs;		/* WOL Register Offset (HW-Bug in Rev. A) */
-	SK_U32		GIRamOffs;		/* RAM Address Offset for addr calculation */
-	SK_U32		GIPollTimerVal;	/* Descr. Poll Timer Init Val (HstClk ticks) */
-	SK_U32		GIValIrqMask;	/* Value for Interrupt Mask */
-	SK_U32		GITimeStampCnt;	/* Time Stamp High Counter (YUKON only) */
-	SK_GEPORT	GP[SK_MAX_MACS];/* Port Dependent Information */
-	SK_GEMACFUNC GIFunc;		/* MAC depedent functions */
-} SK_GEINIT;
-
-/*
- * Error numbers and messages for skxmac2.c and skgeinit.c
- */
-#define SKERR_HWI_E001		(SK_ERRBASE_HWINIT)
-#define SKERR_HWI_E001MSG	"SkXmClrExactAddr() has got illegal parameters"
-#define SKERR_HWI_E002		(SKERR_HWI_E001+1)
-#define SKERR_HWI_E002MSG	"SkGeInit(): Level 1 call missing"
-#define SKERR_HWI_E003		(SKERR_HWI_E002+1)
-#define SKERR_HWI_E003MSG	"SkGeInit() called with illegal init Level"
-#define SKERR_HWI_E004		(SKERR_HWI_E003+1)
-#define SKERR_HWI_E004MSG	"SkGeInitPort(): Queue Size illegal configured"
-#define SKERR_HWI_E005		(SKERR_HWI_E004+1)
-#define SKERR_HWI_E005MSG	"SkGeInitPort(): cannot init running ports"
-#define SKERR_HWI_E006		(SKERR_HWI_E005+1)
-#define SKERR_HWI_E006MSG	"SkGeMacInit(): PState does not match HW state"
-#define SKERR_HWI_E007		(SKERR_HWI_E006+1)
-#define SKERR_HWI_E007MSG	"SkXmInitDupMd() called with invalid Dup Mode"
-#define SKERR_HWI_E008		(SKERR_HWI_E007+1)
-#define SKERR_HWI_E008MSG	"SkXmSetRxCmd() called with invalid Mode"
-#define SKERR_HWI_E009		(SKERR_HWI_E008+1)
-#define SKERR_HWI_E009MSG	"SkGeCfgSync() called although PXSQSize zero"
-#define SKERR_HWI_E010		(SKERR_HWI_E009+1)
-#define SKERR_HWI_E010MSG	"SkGeCfgSync() called with invalid parameters"
-#define SKERR_HWI_E011		(SKERR_HWI_E010+1)
-#define SKERR_HWI_E011MSG	"SkGeInitPort(): Receive Queue Size too small"
-#define SKERR_HWI_E012		(SKERR_HWI_E011+1)
-#define SKERR_HWI_E012MSG	"SkGeInitPort(): invalid Queue Size specified"
-#define SKERR_HWI_E013		(SKERR_HWI_E012+1)
-#define SKERR_HWI_E013MSG	"SkGeInitPort(): cfg changed for running queue"
-#define SKERR_HWI_E014		(SKERR_HWI_E013+1)
-#define SKERR_HWI_E014MSG	"SkGeInitPort(): unknown GIPortUsage specified"
-#define SKERR_HWI_E015		(SKERR_HWI_E014+1)
-#define SKERR_HWI_E015MSG	"Illegal Link mode parameter"
-#define SKERR_HWI_E016		(SKERR_HWI_E015+1)
-#define SKERR_HWI_E016MSG	"Illegal Flow control mode parameter"
-#define SKERR_HWI_E017		(SKERR_HWI_E016+1)
-#define SKERR_HWI_E017MSG	"Illegal value specified for GIPollTimerVal"
-#define SKERR_HWI_E018		(SKERR_HWI_E017+1)
-#define SKERR_HWI_E018MSG	"FATAL: SkGeStopPort() does not terminate (Tx)"
-#define SKERR_HWI_E019		(SKERR_HWI_E018+1)
-#define SKERR_HWI_E019MSG	"Illegal Speed parameter"
-#define SKERR_HWI_E020		(SKERR_HWI_E019+1)
-#define SKERR_HWI_E020MSG	"Illegal Master/Slave parameter"
-#define SKERR_HWI_E021		(SKERR_HWI_E020+1)
-#define	SKERR_HWI_E021MSG	"MacUpdateStats(): cannot update statistic counter"
-#define	SKERR_HWI_E022		(SKERR_HWI_E021+1)
-#define	SKERR_HWI_E022MSG	"MacStatistic(): illegal statistic base address"
-#define SKERR_HWI_E023		(SKERR_HWI_E022+1)
-#define SKERR_HWI_E023MSG	"SkGeInitPort(): Transmit Queue Size too small"
-#define SKERR_HWI_E024		(SKERR_HWI_E023+1)
-#define SKERR_HWI_E024MSG	"FATAL: SkGeStopPort() does not terminate (Rx)"
-#define SKERR_HWI_E025		(SKERR_HWI_E024+1)
-#define SKERR_HWI_E025MSG	""
-
-/* function prototypes ********************************************************/
-
-#ifndef	SK_KR_PROTO
-
-/*
- * public functions in skgeinit.c
- */
-extern void	SkGePollTxD(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL PollTxD);
-
-extern void	SkGeYellowLED(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		State);
-
-extern int	SkGeCfgSync(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U32	IntTime,
-	SK_U32	LimCount,
-	int		SyncMode);
-
-extern void	SkGeLoadLnkSyncCnt(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U32	CntVal);
-
-extern void	SkGeStopPort(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Dir,
-	int		RstMode);
-
-extern int	SkGeInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Level);
-
-extern void	SkGeDeInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC);
-
-extern int	SkGeInitPort(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkGeXmitLED(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Led,
-	int		Mode);
-
-extern int	SkGeInitAssignRamToQueues(
-	SK_AC	*pAC,
-	int		ActivePort,
-	SK_BOOL	DualNet);
-
-/*
- * public functions in skxmac2.c
- */
-extern void SkMacRxTxDisable(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacSoftRst(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacHardRst(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkXmInitMac(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkGmInitMac(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void SkMacInitPhy(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	DoLoop);
-
-extern void SkMacIrqDisable(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacFlushTxFifo(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacIrq(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern int	SkMacAutoNegDone(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacAutoNegLipaPhy(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U16	IStatus);
-
-extern int  SkMacRxTxEnable(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port);
-
-extern void	SkMacPromiscMode(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-
-extern void	SkMacHashing(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-
-extern void	SkXmPhyRead(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	SK_FAR *pVal);
-
-extern void	SkXmPhyWrite(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	Val);
-
-extern void	SkGmPhyRead(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	SK_FAR *pVal);
-
-extern void	SkGmPhyWrite(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	Val);
-
-extern void	SkXmClrExactAddr(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		StartNum,
-	int		StopNum);
-
-extern void	SkXmAutoNegLipaXmac(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_U16	IStatus);
-
-extern int SkXmUpdateStats(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkGmUpdateStats(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkXmMacStatistic(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16	StatAddr,
-	SK_U32	SK_FAR *pVal);
-
-extern int SkGmMacStatistic(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16	StatAddr,
-	SK_U32	SK_FAR *pVal);
-
-extern int SkXmResetCounter(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkGmResetCounter(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port);
-
-extern int SkXmOverflowStatus(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16  IStatus,
-	SK_U64	SK_FAR *pStatus);
-
-extern int SkGmOverflowStatus(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	unsigned int Port,
-	SK_U16	MacStatus,
-	SK_U64	SK_FAR *pStatus);
-
-extern int SkGmCableDiagStatus(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	StartTest);
-
-#ifdef SK_DIAG
-extern void	SkGePhyRead(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	*pVal);
-
-extern void	SkGePhyWrite(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Addr,
-	SK_U16	Val);
-
-extern void	SkMacSetRxCmd(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	int		Mode);
-extern void	SkMacCrcGener(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-extern void	SkMacTimeStamp(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-extern void	SkXmSendCont(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Port,
-	SK_BOOL	Enable);
-#endif /* SK_DIAG */
-
-#else	/* SK_KR_PROTO */
-
-/*
- * public functions in skgeinit.c
- */
-extern void	SkGePollTxD();
-extern void	SkGeYellowLED();
-extern int	SkGeCfgSync();
-extern void	SkGeLoadLnkSyncCnt();
-extern void	SkGeStopPort();
-extern int	SkGeInit();
-extern void	SkGeDeInit();
-extern int	SkGeInitPort();
-extern void	SkGeXmitLED();
-extern int	SkGeInitAssignRamToQueues();
-
-/*
- * public functions in skxmac2.c
- */
-extern void SkMacRxTxDisable();
-extern void	SkMacSoftRst();
-extern void	SkMacHardRst();
-extern void SkMacInitPhy();
-extern int  SkMacRxTxEnable();
-extern void SkMacPromiscMode();
-extern void SkMacHashing();
-extern void SkMacIrqDisable();
-extern void	SkMacFlushTxFifo();
-extern void	SkMacIrq();
-extern int	SkMacAutoNegDone();
-extern void	SkMacAutoNegLipaPhy();
-extern void	SkXmInitMac();
-extern void	SkXmPhyRead();
-extern void	SkXmPhyWrite();
-extern void	SkGmInitMac();
-extern void	SkGmPhyRead();
-extern void	SkGmPhyWrite();
-extern void	SkXmClrExactAddr();
-extern void	SkXmAutoNegLipaXmac();
-extern int	SkXmUpdateStats();
-extern int	SkGmUpdateStats();
-extern int	SkXmMacStatistic();
-extern int	SkGmMacStatistic();
-extern int	SkXmResetCounter();
-extern int	SkGmResetCounter();
-extern int	SkXmOverflowStatus();
-extern int	SkGmOverflowStatus();
-extern int	SkGmCableDiagStatus();
-
-#ifdef SK_DIAG
-extern void	SkGePhyRead();
-extern void	SkGePhyWrite();
-extern void	SkMacSetRxCmd();
-extern void	SkMacCrcGener();
-extern void	SkMacTimeStamp();
-extern void	SkXmSendCont();
-#endif /* SK_DIAG */
-
-#endif	/* SK_KR_PROTO */
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKGEINIT_H_ */
diff --git a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h
deleted file mode 100644
index ddd304f..0000000
--- a/drivers/net/sk98lin/h/skgepnm2.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgepnm2.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.36 $
- * Date:	$Date: 2003/05/23 12:45:13 $
- * Purpose:	Defines for Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _SKGEPNM2_H_
-#define _SKGEPNM2_H_
-
-/*
- * General definitions
- */
-#define SK_PNMI_CHIPSET_XMAC	1	/* XMAC11800FP */
-#define SK_PNMI_CHIPSET_YUKON	2	/* YUKON */
-
-#define	SK_PNMI_BUS_PCI		1	/* PCI bus*/
-
-/*
- * Actions
- */
-#define SK_PNMI_ACT_IDLE		1
-#define SK_PNMI_ACT_RESET		2
-#define SK_PNMI_ACT_SELFTEST	3
-#define SK_PNMI_ACT_RESETCNT	4
-
-/*
- * VPD releated defines
- */
-
-#define SK_PNMI_VPD_RW		1
-#define SK_PNMI_VPD_RO		2
-
-#define SK_PNMI_VPD_OK			0
-#define SK_PNMI_VPD_NOTFOUND	1
-#define SK_PNMI_VPD_CUT			2
-#define SK_PNMI_VPD_TIMEOUT		3
-#define SK_PNMI_VPD_FULL		4
-#define SK_PNMI_VPD_NOWRITE		5
-#define SK_PNMI_VPD_FATAL		6
-
-#define SK_PNMI_VPD_IGNORE	0
-#define SK_PNMI_VPD_CREATE	1
-#define SK_PNMI_VPD_DELETE	2
-
-
-/*
- * RLMT related defines
- */
-#define SK_PNMI_DEF_RLMT_CHG_THRES	240	/* 4 changes per minute */
-
-
-/*
- * VCT internal status values
- */
-#define SK_PNMI_VCT_PENDING	32
-#define SK_PNMI_VCT_TEST_DONE	64
-#define SK_PNMI_VCT_LINK	128
-
-/*
- * Internal table definitions
- */
-#define SK_PNMI_GET		0
-#define SK_PNMI_PRESET	1
-#define SK_PNMI_SET		2
-
-#define SK_PNMI_RO		0
-#define SK_PNMI_RW		1
-#define SK_PNMI_WO		2
-
-typedef struct s_OidTabEntry {
-	SK_U32			Id;
-	SK_U32			InstanceNo;
-	unsigned int	StructSize;
-	unsigned int	Offset;
-	int				Access;
-	int				(* Func)(SK_AC *pAc, SK_IOC pIo, int action,
-							 SK_U32 Id, char* pBuf, unsigned int* pLen,
-							 SK_U32 Instance, unsigned int TableIndex,
-							 SK_U32 NetNumber);
-	SK_U16			Param;
-} SK_PNMI_TAB_ENTRY;
-
-
-/*
- * Trap lengths
- */
-#define SK_PNMI_TRAP_SIMPLE_LEN			17
-#define SK_PNMI_TRAP_SENSOR_LEN_BASE	46
-#define SK_PNMI_TRAP_RLMT_CHANGE_LEN	23
-#define SK_PNMI_TRAP_RLMT_PORT_LEN		23
-
-/*
- * Number of MAC types supported
- */
-#define SK_PNMI_MAC_TYPES	(SK_MAC_GMAC + 1)
-
-/*
- * MAC statistic data list (overall set for MAC types used)
- */
-enum SK_MACSTATS {
-	SK_PNMI_HTX				= 0,
-	SK_PNMI_HTX_OCTET,
-	SK_PNMI_HTX_OCTETHIGH 	= SK_PNMI_HTX_OCTET,
-	SK_PNMI_HTX_OCTETLOW,
-	SK_PNMI_HTX_BROADCAST,
-	SK_PNMI_HTX_MULTICAST,
-	SK_PNMI_HTX_UNICAST,
-	SK_PNMI_HTX_BURST,
-	SK_PNMI_HTX_PMACC,
-	SK_PNMI_HTX_MACC,
-	SK_PNMI_HTX_COL,
-	SK_PNMI_HTX_SINGLE_COL,
-	SK_PNMI_HTX_MULTI_COL,
-	SK_PNMI_HTX_EXCESS_COL,
-	SK_PNMI_HTX_LATE_COL,
-	SK_PNMI_HTX_DEFFERAL,
-	SK_PNMI_HTX_EXCESS_DEF,
-	SK_PNMI_HTX_UNDERRUN,
-	SK_PNMI_HTX_CARRIER,
-	SK_PNMI_HTX_UTILUNDER,
-	SK_PNMI_HTX_UTILOVER,
-	SK_PNMI_HTX_64,
-	SK_PNMI_HTX_127,
-	SK_PNMI_HTX_255,
-	SK_PNMI_HTX_511,
-	SK_PNMI_HTX_1023,
-	SK_PNMI_HTX_MAX,
-	SK_PNMI_HTX_LONGFRAMES,
-	SK_PNMI_HTX_SYNC,
-	SK_PNMI_HTX_SYNC_OCTET,
-	SK_PNMI_HTX_RESERVED,
-	
-	SK_PNMI_HRX,
-	SK_PNMI_HRX_OCTET,
-	SK_PNMI_HRX_OCTETHIGH	= SK_PNMI_HRX_OCTET,
-	SK_PNMI_HRX_OCTETLOW,
-	SK_PNMI_HRX_BADOCTET,
-	SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET,
-	SK_PNMI_HRX_BADOCTETLOW,
-	SK_PNMI_HRX_BROADCAST,
-	SK_PNMI_HRX_MULTICAST,
-	SK_PNMI_HRX_UNICAST,
-	SK_PNMI_HRX_PMACC,
-	SK_PNMI_HRX_MACC,
-	SK_PNMI_HRX_PMACC_ERR,
-	SK_PNMI_HRX_MACC_UNKWN,
-	SK_PNMI_HRX_BURST,
-	SK_PNMI_HRX_MISSED,
-	SK_PNMI_HRX_FRAMING,
-	SK_PNMI_HRX_UNDERSIZE,
-	SK_PNMI_HRX_OVERFLOW,
-	SK_PNMI_HRX_JABBER,
-	SK_PNMI_HRX_CARRIER,
-	SK_PNMI_HRX_IRLENGTH,
-	SK_PNMI_HRX_SYMBOL,
-	SK_PNMI_HRX_SHORTS,
-	SK_PNMI_HRX_RUNT,
-	SK_PNMI_HRX_TOO_LONG,
-	SK_PNMI_HRX_FCS,
-	SK_PNMI_HRX_CEXT,
-	SK_PNMI_HRX_UTILUNDER,
-	SK_PNMI_HRX_UTILOVER,
-	SK_PNMI_HRX_64,
-	SK_PNMI_HRX_127,
-	SK_PNMI_HRX_255,
-	SK_PNMI_HRX_511,
-	SK_PNMI_HRX_1023,
-	SK_PNMI_HRX_MAX,
-	SK_PNMI_HRX_LONGFRAMES,
-	
-	SK_PNMI_HRX_RESERVED,
-	
-	SK_PNMI_MAX_IDX		/* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */
-};
-
-/*
- * MAC specific data
- */
-typedef struct s_PnmiStatAddr {
-	SK_U16		Reg;		/* MAC register containing the value */
-	SK_BOOL		GetOffset;	/* TRUE: Offset managed by PNMI (call GetStatVal())*/
-} SK_PNMI_STATADDR;
-
-
-/*
- * SK_PNMI_STRUCT_DATA copy offset evaluation macros
- */
-#define SK_PNMI_OFF(e)		((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
-#define SK_PNMI_MAI_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
-#define SK_PNMI_VPD_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e))
-#define SK_PNMI_SEN_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e))
-#define SK_PNMI_CHK_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e))
-#define SK_PNMI_STA_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e))
-#define SK_PNMI_CNF_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e))
-#define SK_PNMI_RLM_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e))
-#define SK_PNMI_MON_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e))
-#define SK_PNMI_TRP_OFF(e)	((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e))
-
-#define SK_PNMI_SET_STAT(b,s,o)	{SK_U32	Val32; char *pVal; \
-					Val32 = (s); \
-					pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
-						&(((SK_PNMI_STRUCT_DATA *)0)-> \
-						ReturnStatus.ErrorStatus)); \
-					SK_PNMI_STORE_U32(pVal, Val32); \
-					Val32 = (o); \
-					pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
-						&(((SK_PNMI_STRUCT_DATA *)0)-> \
-						ReturnStatus.ErrorOffset)); \
-					SK_PNMI_STORE_U32(pVal, Val32);}
-
-/*
- * Time macros
- */
-#ifndef SK_PNMI_HUNDREDS_SEC
-#if SK_TICKS_PER_SEC == 100
-#define SK_PNMI_HUNDREDS_SEC(t)	(t)
-#else
-#define SK_PNMI_HUNDREDS_SEC(t)	(((t) * 100) / (SK_TICKS_PER_SEC))
-#endif /* !SK_TICKS_PER_SEC */
-#endif /* !SK_PNMI_HUNDREDS_SEC */
-
-/*
- * Macros to work around alignment problems
- */
-#ifndef SK_PNMI_STORE_U16
-#define SK_PNMI_STORE_U16(p,v)	{*(char *)(p) = *((char *)&(v)); \
-					*((char *)(p) + 1) = \
-						*(((char *)&(v)) + 1);}
-#endif
-
-#ifndef SK_PNMI_STORE_U32
-#define SK_PNMI_STORE_U32(p,v)	{*(char *)(p) = *((char *)&(v)); \
-					*((char *)(p) + 1) = \
-						*(((char *)&(v)) + 1); \
-					*((char *)(p) + 2) = \
-						*(((char *)&(v)) + 2); \
-					*((char *)(p) + 3) = \
-						*(((char *)&(v)) + 3);}
-#endif
-
-#ifndef SK_PNMI_STORE_U64
-#define SK_PNMI_STORE_U64(p,v)	{*(char *)(p) = *((char *)&(v)); \
-					*((char *)(p) + 1) = \
-						*(((char *)&(v)) + 1); \
-					*((char *)(p) + 2) = \
-						*(((char *)&(v)) + 2); \
-					*((char *)(p) + 3) = \
-						*(((char *)&(v)) + 3); \
-					*((char *)(p) + 4) = \
-						*(((char *)&(v)) + 4); \
-					*((char *)(p) + 5) = \
-						*(((char *)&(v)) + 5); \
-					*((char *)(p) + 6) = \
-						*(((char *)&(v)) + 6); \
-					*((char *)(p) + 7) = \
-						*(((char *)&(v)) + 7);}
-#endif
-
-#ifndef SK_PNMI_READ_U16
-#define SK_PNMI_READ_U16(p,v)	{*((char *)&(v)) = *(char *)(p); \
-					*(((char *)&(v)) + 1) = \
-						*((char *)(p) + 1);}
-#endif
-
-#ifndef SK_PNMI_READ_U32
-#define SK_PNMI_READ_U32(p,v)	{*((char *)&(v)) = *(char *)(p); \
-					*(((char *)&(v)) + 1) = \
-						*((char *)(p) + 1); \
-					*(((char *)&(v)) + 2) = \
-						*((char *)(p) + 2); \
-					*(((char *)&(v)) + 3) = \
-						*((char *)(p) + 3);}
-#endif
-
-#ifndef SK_PNMI_READ_U64
-#define SK_PNMI_READ_U64(p,v)	{*((char *)&(v)) = *(char *)(p); \
-					*(((char *)&(v)) + 1) = \
-						*((char *)(p) + 1); \
-					*(((char *)&(v)) + 2) = \
-						*((char *)(p) + 2); \
-					*(((char *)&(v)) + 3) = \
-						*((char *)(p) + 3); \
-					*(((char *)&(v)) + 4) = \
-						*((char *)(p) + 4); \
-					*(((char *)&(v)) + 5) = \
-						*((char *)(p) + 5); \
-					*(((char *)&(v)) + 6) = \
-						*((char *)(p) + 6); \
-					*(((char *)&(v)) + 7) = \
-						*((char *)(p) + 7);}
-#endif
-
-/*
- * Macros for Debug
- */
-#ifdef DEBUG
-
-#define SK_PNMI_CHECKFLAGS(vSt)	{if (pAC->Pnmi.MacUpdatedFlag > 0 || \
-					pAC->Pnmi.RlmtUpdatedFlag > 0 || \
-					pAC->Pnmi.SirqUpdatedFlag > 0) { \
-						SK_DBG_MSG(pAC, \
-						SK_DBGMOD_PNMI, \
-						SK_DBGCAT_CTRL,	\
-						("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \
-						vSt, \
-						pAC->Pnmi.MacUpdatedFlag, \
-						pAC->Pnmi.RlmtUpdatedFlag, \
-						pAC->Pnmi.SirqUpdatedFlag))}}
-
-#else	/* !DEBUG */
-
-#define SK_PNMI_CHECKFLAGS(vSt)	/* Nothing */
-
-#endif	/* !DEBUG */
-
-#endif	/* _SKGEPNM2_H_ */
diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h
deleted file mode 100644
index 1ed214c..0000000
--- a/drivers/net/sk98lin/h/skgepnmi.h
+++ /dev/null
@@ -1,962 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgepnmi.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.62 $
- * Date:	$Date: 2003/08/15 12:31:52 $
- * Purpose:	Defines for Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _SKGEPNMI_H_
-#define _SKGEPNMI_H_
-
-/*
- * Include dependencies
- */
-#include "h/sktypes.h"
-#include "h/skerror.h"
-#include "h/sktimer.h"
-#include "h/ski2c.h"
-#include "h/skaddr.h"
-#include "h/skrlmt.h"
-#include "h/skvpd.h"
-
-/*
- * Management Database Version
- */
-#define SK_PNMI_MDB_VERSION		0x00030001	/* 3.1 */
-
-
-/*
- * Event definitions
- */
-#define SK_PNMI_EVT_SIRQ_OVERFLOW		1	/* Counter overflow */
-#define SK_PNMI_EVT_SEN_WAR_LOW			2	/* Lower war thres exceeded */
-#define SK_PNMI_EVT_SEN_WAR_UPP			3	/* Upper war thres exceeded */
-#define SK_PNMI_EVT_SEN_ERR_LOW			4	/* Lower err thres exceeded */
-#define SK_PNMI_EVT_SEN_ERR_UPP			5	/* Upper err thres exceeded */
-#define SK_PNMI_EVT_CHG_EST_TIMER		6	/* Timer event for RLMT Chg */
-#define SK_PNMI_EVT_UTILIZATION_TIMER	7	/* Timer event for Utiliza. */
-#define SK_PNMI_EVT_CLEAR_COUNTER		8	/* Clear statistic counters */
-#define SK_PNMI_EVT_XMAC_RESET			9	/* XMAC will be reset */
-
-#define SK_PNMI_EVT_RLMT_PORT_UP		10	/* Port came logically up */
-#define SK_PNMI_EVT_RLMT_PORT_DOWN		11	/* Port went logically down */
-#define SK_PNMI_EVT_RLMT_SEGMENTATION	13	/* Two SP root bridges found */
-#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN	14	/* Port went logically down */
-#define SK_PNMI_EVT_RLMT_ACTIVE_UP		15	/* Port came logically up */
-#define SK_PNMI_EVT_RLMT_SET_NETS		16	/* 1. Parameter is number of nets
-												1 = single net; 2 = dual net */
-#define SK_PNMI_EVT_VCT_RESET		17	/* VCT port reset timer event started with SET. */
-
-
-/*
- * Return values
- */
-#define SK_PNMI_ERR_OK				0
-#define SK_PNMI_ERR_GENERAL			1
-#define SK_PNMI_ERR_TOO_SHORT		2
-#define SK_PNMI_ERR_BAD_VALUE		3
-#define SK_PNMI_ERR_READ_ONLY		4
-#define SK_PNMI_ERR_UNKNOWN_OID		5
-#define SK_PNMI_ERR_UNKNOWN_INST	6
-#define SK_PNMI_ERR_UNKNOWN_NET 	7
-#define SK_PNMI_ERR_NOT_SUPPORTED	10
-
-
-/*
- * Return values of driver reset function SK_DRIVER_RESET() and
- * driver event function SK_DRIVER_EVENT()
- */
-#define SK_PNMI_ERR_OK			0
-#define SK_PNMI_ERR_FAIL		1
-
-
-/*
- * Return values of driver test function SK_DRIVER_SELFTEST()
- */
-#define SK_PNMI_TST_UNKNOWN		(1 << 0)
-#define SK_PNMI_TST_TRANCEIVER		(1 << 1)
-#define SK_PNMI_TST_ASIC		(1 << 2)
-#define SK_PNMI_TST_SENSOR		(1 << 3)
-#define SK_PNMI_TST_POWERMGMT		(1 << 4)
-#define SK_PNMI_TST_PCI			(1 << 5)
-#define SK_PNMI_TST_MAC			(1 << 6)
-
-
-/*
- * RLMT specific definitions
- */
-#define SK_PNMI_RLMT_STATUS_STANDBY	1
-#define SK_PNMI_RLMT_STATUS_ACTIVE	2
-#define SK_PNMI_RLMT_STATUS_ERROR	3
-
-#define SK_PNMI_RLMT_LSTAT_PHY_DOWN	1
-#define SK_PNMI_RLMT_LSTAT_AUTONEG	2
-#define SK_PNMI_RLMT_LSTAT_LOG_DOWN	3
-#define SK_PNMI_RLMT_LSTAT_LOG_UP	4
-#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5
-
-#define SK_PNMI_RLMT_MODE_CHK_LINK	(SK_RLMT_CHECK_LINK)
-#define SK_PNMI_RLMT_MODE_CHK_RX	(SK_RLMT_CHECK_LOC_LINK)
-#define SK_PNMI_RLMT_MODE_CHK_SPT	(SK_RLMT_CHECK_SEG)
-/* #define SK_PNMI_RLMT_MODE_CHK_EX */
-
-/*
- * OID definition
- */
-#ifndef _NDIS_	/* Check, whether NDIS already included OIDs */
-
-#define OID_GEN_XMIT_OK					0x00020101
-#define OID_GEN_RCV_OK					0x00020102
-#define OID_GEN_XMIT_ERROR				0x00020103
-#define OID_GEN_RCV_ERROR				0x00020104
-#define OID_GEN_RCV_NO_BUFFER			0x00020105
-
-/* #define OID_GEN_DIRECTED_BYTES_XMIT	0x00020201 */
-#define OID_GEN_DIRECTED_FRAMES_XMIT	0x00020202
-/* #define OID_GEN_MULTICAST_BYTES_XMIT	0x00020203 */
-#define OID_GEN_MULTICAST_FRAMES_XMIT	0x00020204
-/* #define OID_GEN_BROADCAST_BYTES_XMIT	0x00020205 */
-#define OID_GEN_BROADCAST_FRAMES_XMIT	0x00020206
-/* #define OID_GEN_DIRECTED_BYTES_RCV	0x00020207 */
-#define OID_GEN_DIRECTED_FRAMES_RCV		0x00020208
-/* #define OID_GEN_MULTICAST_BYTES_RCV	0x00020209 */
-#define OID_GEN_MULTICAST_FRAMES_RCV	0x0002020A
-/* #define OID_GEN_BROADCAST_BYTES_RCV	0x0002020B */
-#define OID_GEN_BROADCAST_FRAMES_RCV	0x0002020C
-#define OID_GEN_RCV_CRC_ERROR			0x0002020D
-#define OID_GEN_TRANSMIT_QUEUE_LENGTH	0x0002020E
-
-#define OID_802_3_PERMANENT_ADDRESS		0x01010101
-#define OID_802_3_CURRENT_ADDRESS		0x01010102
-/* #define OID_802_3_MULTICAST_LIST		0x01010103 */
-/* #define OID_802_3_MAXIMUM_LIST_SIZE	0x01010104 */
-/* #define OID_802_3_MAC_OPTIONS		0x01010105 */
-			
-#define OID_802_3_RCV_ERROR_ALIGNMENT	0x01020101
-#define OID_802_3_XMIT_ONE_COLLISION	0x01020102
-#define OID_802_3_XMIT_MORE_COLLISIONS	0x01020103
-#define OID_802_3_XMIT_DEFERRED			0x01020201
-#define OID_802_3_XMIT_MAX_COLLISIONS	0x01020202
-#define OID_802_3_RCV_OVERRUN			0x01020203
-#define OID_802_3_XMIT_UNDERRUN			0x01020204
-#define OID_802_3_XMIT_TIMES_CRS_LOST	0x01020206
-#define OID_802_3_XMIT_LATE_COLLISIONS	0x01020207
-
-/*
- * PnP and PM OIDs
- */
-#ifdef SK_POWER_MGMT
-#define OID_PNP_CAPABILITIES			0xFD010100
-#define OID_PNP_SET_POWER				0xFD010101
-#define OID_PNP_QUERY_POWER				0xFD010102
-#define OID_PNP_ADD_WAKE_UP_PATTERN		0xFD010103
-#define OID_PNP_REMOVE_WAKE_UP_PATTERN	0xFD010104
-#define OID_PNP_ENABLE_WAKE_UP			0xFD010106
-#endif /* SK_POWER_MGMT */
-
-#endif /* _NDIS_ */
-
-#define OID_SKGE_MDB_VERSION			0xFF010100
-#define OID_SKGE_SUPPORTED_LIST			0xFF010101
-#define OID_SKGE_VPD_FREE_BYTES			0xFF010102
-#define OID_SKGE_VPD_ENTRIES_LIST		0xFF010103
-#define OID_SKGE_VPD_ENTRIES_NUMBER		0xFF010104
-#define OID_SKGE_VPD_KEY				0xFF010105
-#define OID_SKGE_VPD_VALUE				0xFF010106
-#define OID_SKGE_VPD_ACCESS				0xFF010107
-#define OID_SKGE_VPD_ACTION				0xFF010108
-			
-#define OID_SKGE_PORT_NUMBER			0xFF010110
-#define OID_SKGE_DEVICE_TYPE			0xFF010111
-#define OID_SKGE_DRIVER_DESCR			0xFF010112
-#define OID_SKGE_DRIVER_VERSION			0xFF010113
-#define OID_SKGE_HW_DESCR				0xFF010114
-#define OID_SKGE_HW_VERSION				0xFF010115
-#define OID_SKGE_CHIPSET				0xFF010116
-#define OID_SKGE_ACTION					0xFF010117
-#define OID_SKGE_RESULT					0xFF010118
-#define OID_SKGE_BUS_TYPE				0xFF010119
-#define OID_SKGE_BUS_SPEED				0xFF01011A
-#define OID_SKGE_BUS_WIDTH				0xFF01011B
-/* 0xFF01011C unused */
-#define OID_SKGE_DIAG_ACTION			0xFF01011D
-#define OID_SKGE_DIAG_RESULT			0xFF01011E
-#define OID_SKGE_MTU					0xFF01011F
-#define OID_SKGE_PHYS_CUR_ADDR			0xFF010120
-#define OID_SKGE_PHYS_FAC_ADDR			0xFF010121
-#define OID_SKGE_PMD					0xFF010122
-#define OID_SKGE_CONNECTOR				0xFF010123
-#define OID_SKGE_LINK_CAP				0xFF010124
-#define OID_SKGE_LINK_MODE				0xFF010125
-#define OID_SKGE_LINK_MODE_STATUS		0xFF010126
-#define OID_SKGE_LINK_STATUS			0xFF010127
-#define OID_SKGE_FLOWCTRL_CAP			0xFF010128
-#define OID_SKGE_FLOWCTRL_MODE			0xFF010129
-#define OID_SKGE_FLOWCTRL_STATUS		0xFF01012A
-#define OID_SKGE_PHY_OPERATION_CAP		0xFF01012B
-#define OID_SKGE_PHY_OPERATION_MODE		0xFF01012C
-#define OID_SKGE_PHY_OPERATION_STATUS	0xFF01012D
-#define OID_SKGE_MULTICAST_LIST			0xFF01012E
-#define OID_SKGE_CURRENT_PACKET_FILTER	0xFF01012F
-
-#define OID_SKGE_TRAP					0xFF010130
-#define OID_SKGE_TRAP_NUMBER			0xFF010131
-
-#define OID_SKGE_RLMT_MODE				0xFF010140
-#define OID_SKGE_RLMT_PORT_NUMBER		0xFF010141
-#define OID_SKGE_RLMT_PORT_ACTIVE		0xFF010142
-#define OID_SKGE_RLMT_PORT_PREFERRED	0xFF010143
-#define OID_SKGE_INTERMEDIATE_SUPPORT	0xFF010160
-
-#define OID_SKGE_SPEED_CAP				0xFF010170
-#define OID_SKGE_SPEED_MODE				0xFF010171
-#define OID_SKGE_SPEED_STATUS			0xFF010172
-
-#define OID_SKGE_BOARDLEVEL				0xFF010180
-
-#define OID_SKGE_SENSOR_NUMBER			0xFF020100			
-#define OID_SKGE_SENSOR_INDEX			0xFF020101
-#define OID_SKGE_SENSOR_DESCR			0xFF020102
-#define OID_SKGE_SENSOR_TYPE			0xFF020103
-#define OID_SKGE_SENSOR_VALUE			0xFF020104
-#define OID_SKGE_SENSOR_WAR_THRES_LOW	0xFF020105
-#define OID_SKGE_SENSOR_WAR_THRES_UPP	0xFF020106
-#define OID_SKGE_SENSOR_ERR_THRES_LOW	0xFF020107
-#define OID_SKGE_SENSOR_ERR_THRES_UPP	0xFF020108
-#define OID_SKGE_SENSOR_STATUS			0xFF020109
-#define OID_SKGE_SENSOR_WAR_CTS			0xFF02010A
-#define OID_SKGE_SENSOR_ERR_CTS			0xFF02010B
-#define OID_SKGE_SENSOR_WAR_TIME		0xFF02010C
-#define OID_SKGE_SENSOR_ERR_TIME		0xFF02010D
-
-#define OID_SKGE_CHKSM_NUMBER			0xFF020110
-#define OID_SKGE_CHKSM_RX_OK_CTS		0xFF020111
-#define OID_SKGE_CHKSM_RX_UNABLE_CTS	0xFF020112
-#define OID_SKGE_CHKSM_RX_ERR_CTS		0xFF020113
-#define OID_SKGE_CHKSM_TX_OK_CTS		0xFF020114
-#define OID_SKGE_CHKSM_TX_UNABLE_CTS	0xFF020115
-
-#define OID_SKGE_STAT_TX				0xFF020120
-#define OID_SKGE_STAT_TX_OCTETS			0xFF020121
-#define OID_SKGE_STAT_TX_BROADCAST		0xFF020122
-#define OID_SKGE_STAT_TX_MULTICAST		0xFF020123
-#define OID_SKGE_STAT_TX_UNICAST		0xFF020124
-#define OID_SKGE_STAT_TX_LONGFRAMES		0xFF020125
-#define OID_SKGE_STAT_TX_BURST			0xFF020126
-#define OID_SKGE_STAT_TX_PFLOWC			0xFF020127
-#define OID_SKGE_STAT_TX_FLOWC			0xFF020128
-#define OID_SKGE_STAT_TX_SINGLE_COL		0xFF020129
-#define OID_SKGE_STAT_TX_MULTI_COL		0xFF02012A
-#define OID_SKGE_STAT_TX_EXCESS_COL		0xFF02012B
-#define OID_SKGE_STAT_TX_LATE_COL		0xFF02012C
-#define OID_SKGE_STAT_TX_DEFFERAL		0xFF02012D
-#define OID_SKGE_STAT_TX_EXCESS_DEF		0xFF02012E
-#define OID_SKGE_STAT_TX_UNDERRUN		0xFF02012F
-#define OID_SKGE_STAT_TX_CARRIER		0xFF020130
-/* #define OID_SKGE_STAT_TX_UTIL		0xFF020131 */
-#define OID_SKGE_STAT_TX_64				0xFF020132
-#define OID_SKGE_STAT_TX_127			0xFF020133
-#define OID_SKGE_STAT_TX_255			0xFF020134
-#define OID_SKGE_STAT_TX_511			0xFF020135
-#define OID_SKGE_STAT_TX_1023			0xFF020136
-#define OID_SKGE_STAT_TX_MAX			0xFF020137
-#define OID_SKGE_STAT_TX_SYNC			0xFF020138
-#define OID_SKGE_STAT_TX_SYNC_OCTETS	0xFF020139
-#define OID_SKGE_STAT_RX				0xFF02013A
-#define OID_SKGE_STAT_RX_OCTETS			0xFF02013B
-#define OID_SKGE_STAT_RX_BROADCAST		0xFF02013C
-#define OID_SKGE_STAT_RX_MULTICAST		0xFF02013D
-#define OID_SKGE_STAT_RX_UNICAST		0xFF02013E
-#define OID_SKGE_STAT_RX_PFLOWC			0xFF02013F
-#define OID_SKGE_STAT_RX_FLOWC			0xFF020140
-#define OID_SKGE_STAT_RX_PFLOWC_ERR		0xFF020141
-#define OID_SKGE_STAT_RX_FLOWC_UNKWN	0xFF020142
-#define OID_SKGE_STAT_RX_BURST			0xFF020143
-#define OID_SKGE_STAT_RX_MISSED			0xFF020144
-#define OID_SKGE_STAT_RX_FRAMING		0xFF020145
-#define OID_SKGE_STAT_RX_OVERFLOW		0xFF020146
-#define OID_SKGE_STAT_RX_JABBER			0xFF020147
-#define OID_SKGE_STAT_RX_CARRIER		0xFF020148
-#define OID_SKGE_STAT_RX_IR_LENGTH		0xFF020149
-#define OID_SKGE_STAT_RX_SYMBOL			0xFF02014A
-#define OID_SKGE_STAT_RX_SHORTS			0xFF02014B
-#define OID_SKGE_STAT_RX_RUNT			0xFF02014C
-#define OID_SKGE_STAT_RX_CEXT			0xFF02014D
-#define OID_SKGE_STAT_RX_TOO_LONG		0xFF02014E
-#define OID_SKGE_STAT_RX_FCS			0xFF02014F
-/* #define OID_SKGE_STAT_RX_UTIL		0xFF020150 */
-#define OID_SKGE_STAT_RX_64				0xFF020151
-#define OID_SKGE_STAT_RX_127			0xFF020152
-#define OID_SKGE_STAT_RX_255			0xFF020153
-#define OID_SKGE_STAT_RX_511			0xFF020154
-#define OID_SKGE_STAT_RX_1023			0xFF020155
-#define OID_SKGE_STAT_RX_MAX			0xFF020156
-#define OID_SKGE_STAT_RX_LONGFRAMES		0xFF020157
-
-#define OID_SKGE_RLMT_CHANGE_CTS		0xFF020160
-#define OID_SKGE_RLMT_CHANGE_TIME		0xFF020161
-#define OID_SKGE_RLMT_CHANGE_ESTIM		0xFF020162
-#define OID_SKGE_RLMT_CHANGE_THRES		0xFF020163
-
-#define OID_SKGE_RLMT_PORT_INDEX		0xFF020164
-#define OID_SKGE_RLMT_STATUS			0xFF020165
-#define OID_SKGE_RLMT_TX_HELLO_CTS		0xFF020166
-#define OID_SKGE_RLMT_RX_HELLO_CTS		0xFF020167
-#define OID_SKGE_RLMT_TX_SP_REQ_CTS		0xFF020168
-#define OID_SKGE_RLMT_RX_SP_CTS			0xFF020169
-
-#define OID_SKGE_RLMT_MONITOR_NUMBER	0xFF010150
-#define OID_SKGE_RLMT_MONITOR_INDEX		0xFF010151
-#define OID_SKGE_RLMT_MONITOR_ADDR		0xFF010152
-#define OID_SKGE_RLMT_MONITOR_ERRS		0xFF010153
-#define OID_SKGE_RLMT_MONITOR_TIMESTAMP	0xFF010154
-#define OID_SKGE_RLMT_MONITOR_ADMIN		0xFF010155
-
-#define OID_SKGE_TX_SW_QUEUE_LEN		0xFF020170
-#define OID_SKGE_TX_SW_QUEUE_MAX		0xFF020171
-#define OID_SKGE_TX_RETRY				0xFF020172
-#define OID_SKGE_RX_INTR_CTS			0xFF020173
-#define OID_SKGE_TX_INTR_CTS			0xFF020174
-#define OID_SKGE_RX_NO_BUF_CTS			0xFF020175
-#define OID_SKGE_TX_NO_BUF_CTS			0xFF020176
-#define OID_SKGE_TX_USED_DESCR_NO		0xFF020177
-#define OID_SKGE_RX_DELIVERED_CTS		0xFF020178
-#define OID_SKGE_RX_OCTETS_DELIV_CTS	0xFF020179
-#define OID_SKGE_RX_HW_ERROR_CTS		0xFF02017A
-#define OID_SKGE_TX_HW_ERROR_CTS		0xFF02017B
-#define OID_SKGE_IN_ERRORS_CTS			0xFF02017C
-#define OID_SKGE_OUT_ERROR_CTS			0xFF02017D
-#define OID_SKGE_ERR_RECOVERY_CTS		0xFF02017E
-#define OID_SKGE_SYSUPTIME				0xFF02017F
-
-#define OID_SKGE_ALL_DATA				0xFF020190
-
-/* Defines for VCT. */
-#define OID_SKGE_VCT_GET				0xFF020200
-#define OID_SKGE_VCT_SET				0xFF020201
-#define OID_SKGE_VCT_STATUS				0xFF020202
-
-#ifdef SK_DIAG_SUPPORT
-/* Defines for driver DIAG mode. */
-#define OID_SKGE_DIAG_MODE				0xFF020204
-#endif /* SK_DIAG_SUPPORT */
-
-/* New OIDs */
-#define OID_SKGE_DRIVER_RELDATE			0xFF020210
-#define OID_SKGE_DRIVER_FILENAME		0xFF020211
-#define OID_SKGE_CHIPID					0xFF020212
-#define OID_SKGE_RAMSIZE				0xFF020213
-#define OID_SKGE_VAUXAVAIL				0xFF020214
-#define OID_SKGE_PHY_TYPE				0xFF020215
-#define OID_SKGE_PHY_LP_MODE			0xFF020216
-
-/* VCT struct to store a backup copy of VCT data after a port reset. */
-typedef struct s_PnmiVct {
-	SK_U8			VctStatus;
-	SK_U8			PCableLen;
-	SK_U32			PMdiPairLen[4];
-	SK_U8			PMdiPairSts[4];
-} SK_PNMI_VCT;
-
-
-/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */
-#define SK_PNMI_VCT_NONE		0
-#define SK_PNMI_VCT_OLD_VCT_DATA	1
-#define SK_PNMI_VCT_NEW_VCT_DATA	2
-#define SK_PNMI_VCT_OLD_DSP_DATA	4
-#define SK_PNMI_VCT_NEW_DSP_DATA	8
-#define SK_PNMI_VCT_RUNNING		16
-
-
-/* VCT cable test status. */
-#define SK_PNMI_VCT_NORMAL_CABLE		0
-#define SK_PNMI_VCT_SHORT_CABLE			1
-#define SK_PNMI_VCT_OPEN_CABLE			2
-#define SK_PNMI_VCT_TEST_FAIL			3
-#define SK_PNMI_VCT_IMPEDANCE_MISMATCH		4
-
-#define	OID_SKGE_TRAP_SEN_WAR_LOW		500
-#define OID_SKGE_TRAP_SEN_WAR_UPP		501
-#define	OID_SKGE_TRAP_SEN_ERR_LOW		502
-#define OID_SKGE_TRAP_SEN_ERR_UPP		503
-#define OID_SKGE_TRAP_RLMT_CHANGE_THRES	520
-#define OID_SKGE_TRAP_RLMT_CHANGE_PORT	521
-#define OID_SKGE_TRAP_RLMT_PORT_DOWN	522
-#define OID_SKGE_TRAP_RLMT_PORT_UP		523
-#define OID_SKGE_TRAP_RLMT_SEGMENTATION	524
-
-#ifdef SK_DIAG_SUPPORT
-/* Defines for driver DIAG mode. */
-#define SK_DIAG_ATTACHED	2
-#define SK_DIAG_RUNNING		1
-#define SK_DIAG_IDLE		0
-#endif /* SK_DIAG_SUPPORT */
-
-/*
- * Generic PNMI IOCTL subcommand definitions.
- */
-#define	SK_GET_SINGLE_VAR		1
-#define	SK_SET_SINGLE_VAR		2
-#define	SK_PRESET_SINGLE_VAR	3
-#define	SK_GET_FULL_MIB			4
-#define	SK_SET_FULL_MIB			5
-#define	SK_PRESET_FULL_MIB		6
-
-
-/*
- * Define error numbers and messages for syslog
- */
-#define SK_PNMI_ERR001		(SK_ERRBASE_PNMI + 1)
-#define SK_PNMI_ERR001MSG	"SkPnmiGetStruct: Unknown OID"
-#define SK_PNMI_ERR002		(SK_ERRBASE_PNMI + 2)
-#define SK_PNMI_ERR002MSG	"SkPnmiGetStruct: Cannot read VPD keys"
-#define SK_PNMI_ERR003		(SK_ERRBASE_PNMI + 3)
-#define SK_PNMI_ERR003MSG	"OidStruct: Called with wrong OID"
-#define SK_PNMI_ERR004		(SK_ERRBASE_PNMI + 4)
-#define SK_PNMI_ERR004MSG	"OidStruct: Called with wrong action"
-#define SK_PNMI_ERR005		(SK_ERRBASE_PNMI + 5)
-#define SK_PNMI_ERR005MSG	"Perform: Cannot reset driver"
-#define SK_PNMI_ERR006		(SK_ERRBASE_PNMI + 6)
-#define SK_PNMI_ERR006MSG	"Perform: Unknown OID action command"
-#define SK_PNMI_ERR007		(SK_ERRBASE_PNMI + 7)
-#define SK_PNMI_ERR007MSG	"General: Driver description not initialized"
-#define SK_PNMI_ERR008		(SK_ERRBASE_PNMI + 8)
-#define SK_PNMI_ERR008MSG	"Addr: Tried to get unknown OID"
-#define SK_PNMI_ERR009		(SK_ERRBASE_PNMI + 9)
-#define SK_PNMI_ERR009MSG	"Addr: Unknown OID"
-#define SK_PNMI_ERR010		(SK_ERRBASE_PNMI + 10)
-#define SK_PNMI_ERR010MSG	"CsumStat: Unknown OID"
-#define SK_PNMI_ERR011		(SK_ERRBASE_PNMI + 11)
-#define SK_PNMI_ERR011MSG	"SensorStat: Sensor descr string too long"
-#define SK_PNMI_ERR012		(SK_ERRBASE_PNMI + 12)
-#define SK_PNMI_ERR012MSG	"SensorStat: Unknown OID"
-#define SK_PNMI_ERR013		(SK_ERRBASE_PNMI + 13)
-#define SK_PNMI_ERR013MSG	""
-#define SK_PNMI_ERR014		(SK_ERRBASE_PNMI + 14)
-#define SK_PNMI_ERR014MSG	"Vpd: Cannot read VPD keys"
-#define SK_PNMI_ERR015		(SK_ERRBASE_PNMI + 15)
-#define SK_PNMI_ERR015MSG	"Vpd: Internal array for VPD keys to small"
-#define SK_PNMI_ERR016		(SK_ERRBASE_PNMI + 16)
-#define SK_PNMI_ERR016MSG	"Vpd: Key string too long"
-#define SK_PNMI_ERR017		(SK_ERRBASE_PNMI + 17)
-#define SK_PNMI_ERR017MSG	"Vpd: Invalid VPD status pointer"
-#define SK_PNMI_ERR018		(SK_ERRBASE_PNMI + 18)
-#define SK_PNMI_ERR018MSG	"Vpd: VPD data not valid"
-#define SK_PNMI_ERR019		(SK_ERRBASE_PNMI + 19)
-#define SK_PNMI_ERR019MSG	"Vpd: VPD entries list string too long"
-#define SK_PNMI_ERR021		(SK_ERRBASE_PNMI + 21)
-#define SK_PNMI_ERR021MSG	"Vpd: VPD data string too long"
-#define SK_PNMI_ERR022		(SK_ERRBASE_PNMI + 22)
-#define SK_PNMI_ERR022MSG	"Vpd: VPD data string too long should be errored before"
-#define SK_PNMI_ERR023		(SK_ERRBASE_PNMI + 23)
-#define SK_PNMI_ERR023MSG	"Vpd: Unknown OID in get action"
-#define SK_PNMI_ERR024		(SK_ERRBASE_PNMI + 24)
-#define SK_PNMI_ERR024MSG	"Vpd: Unknown OID in preset/set action"
-#define SK_PNMI_ERR025		(SK_ERRBASE_PNMI + 25)
-#define SK_PNMI_ERR025MSG	"Vpd: Cannot write VPD after modify entry"
-#define SK_PNMI_ERR026		(SK_ERRBASE_PNMI + 26)
-#define SK_PNMI_ERR026MSG	"Vpd: Cannot update VPD"
-#define SK_PNMI_ERR027		(SK_ERRBASE_PNMI + 27)
-#define SK_PNMI_ERR027MSG	"Vpd: Cannot delete VPD entry"
-#define SK_PNMI_ERR028		(SK_ERRBASE_PNMI + 28)
-#define SK_PNMI_ERR028MSG	"Vpd: Cannot update VPD after delete entry"
-#define SK_PNMI_ERR029		(SK_ERRBASE_PNMI + 29)
-#define SK_PNMI_ERR029MSG	"General: Driver description string too long"
-#define SK_PNMI_ERR030		(SK_ERRBASE_PNMI + 30)
-#define SK_PNMI_ERR030MSG	"General: Driver version not initialized"
-#define SK_PNMI_ERR031		(SK_ERRBASE_PNMI + 31)
-#define SK_PNMI_ERR031MSG	"General: Driver version string too long"
-#define SK_PNMI_ERR032		(SK_ERRBASE_PNMI + 32)
-#define SK_PNMI_ERR032MSG	"General: Cannot read VPD Name for HW descr"
-#define SK_PNMI_ERR033		(SK_ERRBASE_PNMI + 33)
-#define SK_PNMI_ERR033MSG	"General: HW description string too long"
-#define SK_PNMI_ERR034		(SK_ERRBASE_PNMI + 34)
-#define SK_PNMI_ERR034MSG	"General: Unknown OID"
-#define SK_PNMI_ERR035		(SK_ERRBASE_PNMI + 35)
-#define SK_PNMI_ERR035MSG	"Rlmt: Unknown OID"
-#define SK_PNMI_ERR036		(SK_ERRBASE_PNMI + 36)
-#define SK_PNMI_ERR036MSG	""
-#define SK_PNMI_ERR037		(SK_ERRBASE_PNMI + 37)
-#define SK_PNMI_ERR037MSG	"Rlmt: SK_RLMT_MODE_CHANGE event return not 0"
-#define SK_PNMI_ERR038		(SK_ERRBASE_PNMI + 38)
-#define SK_PNMI_ERR038MSG	"Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0"
-#define SK_PNMI_ERR039		(SK_ERRBASE_PNMI + 39)
-#define SK_PNMI_ERR039MSG	"RlmtStat: Unknown OID"
-#define SK_PNMI_ERR040		(SK_ERRBASE_PNMI + 40)
-#define SK_PNMI_ERR040MSG	"PowerManagement: Unknown OID"
-#define SK_PNMI_ERR041		(SK_ERRBASE_PNMI + 41)
-#define SK_PNMI_ERR041MSG	"MacPrivateConf: Unknown OID"
-#define SK_PNMI_ERR042		(SK_ERRBASE_PNMI + 42)
-#define SK_PNMI_ERR042MSG	"MacPrivateConf: SK_HWEV_SET_ROLE returned not 0"
-#define SK_PNMI_ERR043		(SK_ERRBASE_PNMI + 43)
-#define SK_PNMI_ERR043MSG	"MacPrivateConf: SK_HWEV_SET_LMODE returned not 0"
-#define SK_PNMI_ERR044		(SK_ERRBASE_PNMI + 44)
-#define SK_PNMI_ERR044MSG	"MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0"
-#define SK_PNMI_ERR045		(SK_ERRBASE_PNMI + 45)
-#define SK_PNMI_ERR045MSG	"MacPrivateConf: SK_HWEV_SET_SPEED returned not 0"
-#define SK_PNMI_ERR046		(SK_ERRBASE_PNMI + 46)
-#define SK_PNMI_ERR046MSG	"Monitor: Unknown OID"
-#define SK_PNMI_ERR047		(SK_ERRBASE_PNMI + 47)
-#define SK_PNMI_ERR047MSG	"SirqUpdate: Event function returns not 0"
-#define SK_PNMI_ERR048		(SK_ERRBASE_PNMI + 48)
-#define SK_PNMI_ERR048MSG	"RlmtUpdate: Event function returns not 0"
-#define SK_PNMI_ERR049		(SK_ERRBASE_PNMI + 49)
-#define SK_PNMI_ERR049MSG	"SkPnmiInit: Invalid size of 'CounterOffset' struct!!"
-#define SK_PNMI_ERR050		(SK_ERRBASE_PNMI + 50)
-#define SK_PNMI_ERR050MSG	"SkPnmiInit: Invalid size of 'StatAddr' table!!"
-#define SK_PNMI_ERR051		(SK_ERRBASE_PNMI + 51)
-#define SK_PNMI_ERR051MSG	"SkPnmiEvent: Port switch suspicious"
-#define SK_PNMI_ERR052		(SK_ERRBASE_PNMI + 52)
-#define SK_PNMI_ERR052MSG	""
-#define SK_PNMI_ERR053		(SK_ERRBASE_PNMI + 53)
-#define SK_PNMI_ERR053MSG	"General: Driver release date not initialized"
-#define SK_PNMI_ERR054		(SK_ERRBASE_PNMI + 54)
-#define SK_PNMI_ERR054MSG	"General: Driver release date string too long"
-#define SK_PNMI_ERR055		(SK_ERRBASE_PNMI + 55)
-#define SK_PNMI_ERR055MSG	"General: Driver file name not initialized"
-#define SK_PNMI_ERR056		(SK_ERRBASE_PNMI + 56)
-#define SK_PNMI_ERR056MSG	"General: Driver file name string too long"
-
-/*
- * Management counter macros called by the driver
- */
-#define SK_PNMI_SET_DRIVER_DESCR(pAC,v)	((pAC)->Pnmi.pDriverDescription = \
-	(char *)(v))
-
-#define SK_PNMI_SET_DRIVER_VER(pAC,v)	((pAC)->Pnmi.pDriverVersion = \
-	(char *)(v))
-
-#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v)	((pAC)->Pnmi.pDriverReleaseDate = \
-	(char *)(v))
-
-#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v)	((pAC)->Pnmi.pDriverFileName = \
-	(char *)(v))
-
-#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \
-	{ \
-		(pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \
-		if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \
-			(pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \
-		} \
-	}
-#define SK_PNMI_CNT_TX_RETRY(pAC,p)	(((pAC)->Pnmi.Port[p].TxRetryCts)++)
-#define SK_PNMI_CNT_RX_INTR(pAC,p)	(((pAC)->Pnmi.Port[p].RxIntrCts)++)
-#define SK_PNMI_CNT_TX_INTR(pAC,p)	(((pAC)->Pnmi.Port[p].TxIntrCts)++)
-#define SK_PNMI_CNT_NO_RX_BUF(pAC,p)	(((pAC)->Pnmi.Port[p].RxNoBufCts)++)
-#define SK_PNMI_CNT_NO_TX_BUF(pAC,p)	(((pAC)->Pnmi.Port[p].TxNoBufCts)++)
-#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \
-	((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v));
-#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \
-	{ \
-		((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \
-		(pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \
-	}
-#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p)	(((pAC)->Pnmi.Port[p].ErrRecoveryCts)++);
-
-#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatSyncCts)++; \
-			(pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \
-		} \
-	}
-
-#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \
-		} \
-	}
-
-#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \
-		} \
-	}
-
-#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \
-	{ \
-		if ((p) < SK_MAX_MACS) { \
-			((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \
-		} \
-	}
-
-/*
- * Conversion Macros
- */
-#define SK_PNMI_PORT_INST2LOG(i)	((unsigned int)(i) - 1)
-#define SK_PNMI_PORT_LOG2INST(l)	((unsigned int)(l) + 1)
-#define SK_PNMI_PORT_PHYS2LOG(p)	((unsigned int)(p) + 1)
-#define SK_PNMI_PORT_LOG2PHYS(pAC,l)	((unsigned int)(l) - 1)
-#define SK_PNMI_PORT_PHYS2INST(pAC,p)	\
-	(pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2))
-#define SK_PNMI_PORT_INST2PHYS(pAC,i)	((unsigned int)(i) - 2)
-
-/*
- * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct
- */
-#define SK_PNMI_VPD_KEY_SIZE	5
-#define SK_PNMI_VPD_BUFSIZE		(VPD_SIZE)
-#define SK_PNMI_VPD_ENTRIES		(VPD_SIZE / 4)
-#define SK_PNMI_VPD_DATALEN		128 /*  Number of data bytes */
-
-#define SK_PNMI_MULTICAST_LISTLEN	64
-#define SK_PNMI_SENSOR_ENTRIES		(SK_MAX_SENSORS)
-#define SK_PNMI_CHECKSUM_ENTRIES	3
-#define SK_PNMI_MAC_ENTRIES			(SK_MAX_MACS + 1)
-#define SK_PNMI_MONITOR_ENTRIES		20
-#define SK_PNMI_TRAP_ENTRIES		10
-#define SK_PNMI_TRAPLEN				128
-#define SK_PNMI_STRINGLEN1			80
-#define SK_PNMI_STRINGLEN2			25
-#define SK_PNMI_TRAP_QUEUE_LEN		512
-
-typedef struct s_PnmiVpd {
-	char			VpdKey[SK_PNMI_VPD_KEY_SIZE];
-	char			VpdValue[SK_PNMI_VPD_DATALEN];
-	SK_U8			VpdAccess;
-	SK_U8			VpdAction;
-} SK_PNMI_VPD;
-
-typedef struct s_PnmiSensor {
-	SK_U8			SensorIndex;
-	char			SensorDescr[SK_PNMI_STRINGLEN2];
-	SK_U8			SensorType;
-	SK_U32			SensorValue;
-	SK_U32			SensorWarningThresholdLow;
-	SK_U32			SensorWarningThresholdHigh;
-	SK_U32			SensorErrorThresholdLow;
-	SK_U32			SensorErrorThresholdHigh;
-	SK_U8			SensorStatus;
-	SK_U64			SensorWarningCts;
-	SK_U64			SensorErrorCts;
-	SK_U64			SensorWarningTimestamp;
-	SK_U64			SensorErrorTimestamp;
-} SK_PNMI_SENSOR;
-
-typedef struct s_PnmiChecksum {
-	SK_U64			ChecksumRxOkCts;
-	SK_U64			ChecksumRxUnableCts;
-	SK_U64			ChecksumRxErrCts;
-	SK_U64			ChecksumTxOkCts;
-	SK_U64			ChecksumTxUnableCts;
-} SK_PNMI_CHECKSUM;
-
-typedef struct s_PnmiStat {
-	SK_U64			StatTxOkCts;
-	SK_U64			StatTxOctetsOkCts;
-	SK_U64			StatTxBroadcastOkCts;
-	SK_U64			StatTxMulticastOkCts;
-	SK_U64			StatTxUnicastOkCts;
-	SK_U64			StatTxLongFramesCts;
-	SK_U64			StatTxBurstCts;
-	SK_U64			StatTxPauseMacCtrlCts;
-	SK_U64			StatTxMacCtrlCts;
-	SK_U64			StatTxSingleCollisionCts;
-	SK_U64			StatTxMultipleCollisionCts;
-	SK_U64			StatTxExcessiveCollisionCts;
-	SK_U64			StatTxLateCollisionCts;
-	SK_U64			StatTxDeferralCts;
-	SK_U64			StatTxExcessiveDeferralCts;
-	SK_U64			StatTxFifoUnderrunCts;
-	SK_U64			StatTxCarrierCts;
-	SK_U64			Dummy1; /* StatTxUtilization */
-	SK_U64			StatTx64Cts;
-	SK_U64			StatTx127Cts;
-	SK_U64			StatTx255Cts;
-	SK_U64			StatTx511Cts;
-	SK_U64			StatTx1023Cts;
-	SK_U64			StatTxMaxCts;
-	SK_U64			StatTxSyncCts;
-	SK_U64			StatTxSyncOctetsCts;
-	SK_U64			StatRxOkCts;
-	SK_U64			StatRxOctetsOkCts;
-	SK_U64			StatRxBroadcastOkCts;
-	SK_U64			StatRxMulticastOkCts;
-	SK_U64			StatRxUnicastOkCts;
-	SK_U64			StatRxLongFramesCts;
-	SK_U64			StatRxPauseMacCtrlCts;
-	SK_U64			StatRxMacCtrlCts;
-	SK_U64			StatRxPauseMacCtrlErrorCts;
-	SK_U64			StatRxMacCtrlUnknownCts;
-	SK_U64			StatRxBurstCts;
-	SK_U64			StatRxMissedCts;
-	SK_U64			StatRxFramingCts;
-	SK_U64			StatRxFifoOverflowCts;
-	SK_U64			StatRxJabberCts;
-	SK_U64			StatRxCarrierCts;
-	SK_U64			StatRxIRLengthCts;
-	SK_U64			StatRxSymbolCts;
-	SK_U64			StatRxShortsCts;
-	SK_U64			StatRxRuntCts;
-	SK_U64			StatRxCextCts;
-	SK_U64			StatRxTooLongCts;
-	SK_U64			StatRxFcsCts;
-	SK_U64			Dummy2; /* StatRxUtilization */
-	SK_U64			StatRx64Cts;
-	SK_U64			StatRx127Cts;
-	SK_U64			StatRx255Cts;
-	SK_U64			StatRx511Cts;
-	SK_U64			StatRx1023Cts;
-	SK_U64			StatRxMaxCts;
-} SK_PNMI_STAT;
-
-typedef struct s_PnmiConf {
-	char			ConfMacCurrentAddr[6];
-	char			ConfMacFactoryAddr[6];
-	SK_U8			ConfPMD;
-	SK_U8			ConfConnector;
-	SK_U32			ConfPhyType;
-	SK_U32			ConfPhyMode;
-	SK_U8			ConfLinkCapability;
-	SK_U8			ConfLinkMode;
-	SK_U8			ConfLinkModeStatus;
-	SK_U8			ConfLinkStatus;
-	SK_U8			ConfFlowCtrlCapability;
-	SK_U8			ConfFlowCtrlMode;
-	SK_U8			ConfFlowCtrlStatus;
-	SK_U8			ConfPhyOperationCapability;
-	SK_U8			ConfPhyOperationMode;
-	SK_U8			ConfPhyOperationStatus;
-	SK_U8			ConfSpeedCapability;
-	SK_U8			ConfSpeedMode;
-	SK_U8			ConfSpeedStatus;
-} SK_PNMI_CONF;
-
-typedef struct s_PnmiRlmt {
-	SK_U32			RlmtIndex;
-	SK_U32			RlmtStatus;
-	SK_U64			RlmtTxHelloCts;
-	SK_U64			RlmtRxHelloCts;
-	SK_U64			RlmtTxSpHelloReqCts;
-	SK_U64			RlmtRxSpHelloCts;
-} SK_PNMI_RLMT;
-
-typedef struct s_PnmiRlmtMonitor {
-	SK_U32			RlmtMonitorIndex;
-	char			RlmtMonitorAddr[6];
-	SK_U64			RlmtMonitorErrorCts;
-	SK_U64			RlmtMonitorTimestamp;
-	SK_U8			RlmtMonitorAdmin;
-} SK_PNMI_RLMT_MONITOR;
-
-typedef struct s_PnmiRequestStatus {
-	SK_U32			ErrorStatus;
-	SK_U32			ErrorOffset;
-} SK_PNMI_REQUEST_STATUS;
-
-typedef struct s_PnmiStrucData {
-	SK_U32			MgmtDBVersion;
-	SK_PNMI_REQUEST_STATUS	ReturnStatus;
-	SK_U32			VpdFreeBytes;
-	char			VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE];
-	SK_U32			VpdEntriesNumber;
-	SK_PNMI_VPD		Vpd[SK_PNMI_VPD_ENTRIES];
-	SK_U32			PortNumber;
-	SK_U32			DeviceType;
-	char			DriverDescr[SK_PNMI_STRINGLEN1];
-	char			DriverVersion[SK_PNMI_STRINGLEN2];
-	char			DriverReleaseDate[SK_PNMI_STRINGLEN1];
-	char			DriverFileName[SK_PNMI_STRINGLEN1];
-	char			HwDescr[SK_PNMI_STRINGLEN1];
-	char			HwVersion[SK_PNMI_STRINGLEN2];
-	SK_U16			Chipset;
-	SK_U32			ChipId;
-	SK_U8			VauxAvail;
-	SK_U32			RamSize;
-	SK_U32			MtuSize;
-	SK_U32			Action;
-	SK_U32			TestResult;
-	SK_U8			BusType;
-	SK_U8			BusSpeed;
-	SK_U8			BusWidth;
-	SK_U8			SensorNumber;
-	SK_PNMI_SENSOR	Sensor[SK_PNMI_SENSOR_ENTRIES];
-	SK_U8			ChecksumNumber;
-	SK_PNMI_CHECKSUM	Checksum[SK_PNMI_CHECKSUM_ENTRIES];
-	SK_PNMI_STAT	Stat[SK_PNMI_MAC_ENTRIES];
-	SK_PNMI_CONF	Conf[SK_PNMI_MAC_ENTRIES];
-	SK_U8			RlmtMode;
-	SK_U32			RlmtPortNumber;
-	SK_U8			RlmtPortActive;
-	SK_U8			RlmtPortPreferred;
-	SK_U64			RlmtChangeCts;
-	SK_U64			RlmtChangeTime;
-	SK_U64			RlmtChangeEstimate;
-	SK_U64			RlmtChangeThreshold;
-	SK_PNMI_RLMT	Rlmt[SK_MAX_MACS];
-	SK_U32			RlmtMonitorNumber;
-	SK_PNMI_RLMT_MONITOR	RlmtMonitor[SK_PNMI_MONITOR_ENTRIES];
-	SK_U32			TrapNumber;
-	SK_U8			Trap[SK_PNMI_TRAP_QUEUE_LEN];
-	SK_U64			TxSwQueueLen;
-	SK_U64			TxSwQueueMax;
-	SK_U64			TxRetryCts;
-	SK_U64			RxIntrCts;
-	SK_U64			TxIntrCts;
-	SK_U64			RxNoBufCts;
-	SK_U64			TxNoBufCts;
-	SK_U64			TxUsedDescrNo;
-	SK_U64			RxDeliveredCts;
-	SK_U64			RxOctetsDeliveredCts;
-	SK_U64			RxHwErrorsCts;
-	SK_U64			TxHwErrorsCts;
-	SK_U64			InErrorsCts;
-	SK_U64			OutErrorsCts;
-	SK_U64			ErrRecoveryCts;
-	SK_U64			SysUpTime;
-} SK_PNMI_STRUCT_DATA;
-
-#define SK_PNMI_STRUCT_SIZE	(sizeof(SK_PNMI_STRUCT_DATA))
-#define SK_PNMI_MIN_STRUCT_SIZE	((unsigned int)(SK_UPTR)\
-				 &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes))
-														/*
-														 * ReturnStatus field
-														 * must be located
-														 * before VpdFreeBytes
-														 */
-
-/*
- * Various definitions
- */
-#define SK_PNMI_MAX_PROTOS		3
-
-#define SK_PNMI_CNT_NO			66	/* Must have the value of the enum
-									 * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK
-									 * for check while init phase 1
-									 */
-
-/*
- * Estimate data structure
- */
-typedef struct s_PnmiEstimate {
-	unsigned int	EstValueIndex;
-	SK_U64			EstValue[7];
-	SK_U64			Estimate;
-	SK_TIMER		EstTimer;
-} SK_PNMI_ESTIMATE;
-
-
-/*
- * VCT timer data structure
- */
-typedef struct s_VctTimer {
-	SK_TIMER		VctTimer;
-} SK_PNMI_VCT_TIMER;
-
-
-/*
- * PNMI specific adapter context structure
- */
-typedef struct s_PnmiPort {
-	SK_U64			StatSyncCts;
-	SK_U64			StatSyncOctetsCts;
-	SK_U64			StatRxLongFrameCts;
-	SK_U64			StatRxFrameTooLongCts;
-	SK_U64			StatRxPMaccErr;
-	SK_U64			TxSwQueueLen;
-	SK_U64			TxSwQueueMax;
-	SK_U64			TxRetryCts;
-	SK_U64			RxIntrCts;
-	SK_U64			TxIntrCts;
-	SK_U64			RxNoBufCts;
-	SK_U64			TxNoBufCts;
-	SK_U64			TxUsedDescrNo;
-	SK_U64			RxDeliveredCts;
-	SK_U64			RxOctetsDeliveredCts;
-	SK_U64			RxHwErrorsCts;
-	SK_U64			TxHwErrorsCts;
-	SK_U64			InErrorsCts;
-	SK_U64			OutErrorsCts;
-	SK_U64			ErrRecoveryCts;
-	SK_U64			RxShortZeroMark;
-	SK_U64			CounterOffset[SK_PNMI_CNT_NO];
-	SK_U32			CounterHigh[SK_PNMI_CNT_NO];
-	SK_BOOL			ActiveFlag;
-	SK_U8			Align[3];
-} SK_PNMI_PORT;
-
-
-typedef struct s_PnmiData {
-	SK_PNMI_PORT	Port	[SK_MAX_MACS];
-	SK_PNMI_PORT	BufPort	[SK_MAX_MACS]; /* 2002-09-13 pweber  */
-	SK_U64			VirtualCounterOffset[SK_PNMI_CNT_NO];
-	SK_U32			TestResult;
-	char			HwVersion[10];
-	SK_U16			Align01;
-
-	char			*pDriverDescription;
-	char			*pDriverVersion;
-	char			*pDriverReleaseDate;
-	char			*pDriverFileName;
-
-	int				MacUpdatedFlag;
-	int				RlmtUpdatedFlag;
-	int				SirqUpdatedFlag;
-
-	SK_U64			RlmtChangeCts;
-	SK_U64			RlmtChangeTime;
-	SK_PNMI_ESTIMATE	RlmtChangeEstimate;
-	SK_U64			RlmtChangeThreshold;
-
-	SK_U64			StartUpTime;
-	SK_U32			DeviceType;
-	char			PciBusSpeed;
-	char			PciBusWidth;
-	char			Chipset;
-	char			PMD;
-	char			Connector;
-	SK_BOOL			DualNetActiveFlag;
-	SK_U16			Align02;
-
-	char			TrapBuf[SK_PNMI_TRAP_QUEUE_LEN];
-	unsigned int	TrapBufFree;
-	unsigned int	TrapQueueBeg;
-	unsigned int	TrapQueueEnd;
-	unsigned int	TrapBufPad;
-	unsigned int	TrapUnique;
-	SK_U8		VctStatus[SK_MAX_MACS];
-	SK_PNMI_VCT	VctBackup[SK_MAX_MACS];
-	SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS];
-#ifdef SK_DIAG_SUPPORT
-	SK_U32			DiagAttached;
-#endif /* SK_DIAG_SUPPORT */
-} SK_PNMI;
-
-
-/*
- * Function prototypes
- */
-extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level);
-extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf,
-	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event,
-	SK_EVPARA Param);
-extern int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
-	unsigned int * pLen, SK_U32 NetIndex);
-
-#endif
diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h
deleted file mode 100644
index 3eec627..0000000
--- a/drivers/net/sk98lin/h/skgesirq.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgesirq.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.30 $
- * Date:	$Date: 2003/07/04 12:34:13 $
- * Purpose:	SK specific Gigabit Ethernet special IRQ functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _INC_SKGESIRQ_H_
-#define _INC_SKGESIRQ_H_
-
-/* Define return codes of SkGePortCheckUp and CheckShort */
-#define	SK_HW_PS_NONE		0	/* No action needed */
-#define	SK_HW_PS_RESTART	1	/* Restart needed */
-#define	SK_HW_PS_LINK		2	/* Link Up actions needed */
-
-/*
- * Define the Event the special IRQ/INI module can handle
- */
-#define SK_HWEV_WATIM			1	/* Timeout for WA Errata #2 XMAC */
-#define SK_HWEV_PORT_START		2	/* Port Start Event by RLMT */
-#define SK_HWEV_PORT_STOP		3	/* Port Stop Event by RLMT */
-#define SK_HWEV_CLEAR_STAT		4	/* Clear Statistics by PNMI */
-#define SK_HWEV_UPDATE_STAT		5	/* Update Statistics by PNMI */
-#define SK_HWEV_SET_LMODE		6	/* Set Link Mode by PNMI */
-#define SK_HWEV_SET_FLOWMODE	7	/* Set Flow Control Mode by PNMI */
-#define SK_HWEV_SET_ROLE		8	/* Set Master/Slave (Role) by PNMI */
-#define SK_HWEV_SET_SPEED		9	/* Set Link Speed by PNMI */
-#define SK_HWEV_HALFDUP_CHK		10	/* Half Duplex Hangup Workaround */
-
-#define SK_WA_ACT_TIME		(5000000UL)	/* 5 sec */
-#define SK_WA_INA_TIME		(100000UL)	/* 100 msec */
-
-#define SK_HALFDUP_CHK_TIME	(10000UL)	/* 10 msec */
-
-/*
- * Define the error numbers and messages
- */
-#define SKERR_SIRQ_E001		(SK_ERRBASE_SIRQ+0)
-#define SKERR_SIRQ_E001MSG	"Unknown event"
-#define SKERR_SIRQ_E002		(SKERR_SIRQ_E001+1)
-#define SKERR_SIRQ_E002MSG	"Packet timeout RX1"
-#define SKERR_SIRQ_E003		(SKERR_SIRQ_E002+1)
-#define SKERR_SIRQ_E003MSG	"Packet timeout RX2"
-#define SKERR_SIRQ_E004		(SKERR_SIRQ_E003+1)
-#define SKERR_SIRQ_E004MSG	"MAC 1 not correctly initialized"
-#define SKERR_SIRQ_E005		(SKERR_SIRQ_E004+1)
-#define SKERR_SIRQ_E005MSG	"MAC 2 not correctly initialized"
-#define SKERR_SIRQ_E006		(SKERR_SIRQ_E005+1)
-#define SKERR_SIRQ_E006MSG	"CHECK failure R1"
-#define SKERR_SIRQ_E007		(SKERR_SIRQ_E006+1)
-#define SKERR_SIRQ_E007MSG	"CHECK failure R2"
-#define SKERR_SIRQ_E008		(SKERR_SIRQ_E007+1)
-#define SKERR_SIRQ_E008MSG	"CHECK failure XS1"
-#define SKERR_SIRQ_E009		(SKERR_SIRQ_E008+1)
-#define SKERR_SIRQ_E009MSG	"CHECK failure XA1"
-#define SKERR_SIRQ_E010		(SKERR_SIRQ_E009+1)
-#define SKERR_SIRQ_E010MSG	"CHECK failure XS2"
-#define SKERR_SIRQ_E011		(SKERR_SIRQ_E010+1)
-#define SKERR_SIRQ_E011MSG	"CHECK failure XA2"
-#define SKERR_SIRQ_E012		(SKERR_SIRQ_E011+1)
-#define SKERR_SIRQ_E012MSG	"unexpected IRQ Master error"
-#define SKERR_SIRQ_E013		(SKERR_SIRQ_E012+1)
-#define SKERR_SIRQ_E013MSG	"unexpected IRQ Status error"
-#define SKERR_SIRQ_E014		(SKERR_SIRQ_E013+1)
-#define SKERR_SIRQ_E014MSG	"Parity error on RAM (read)"
-#define SKERR_SIRQ_E015		(SKERR_SIRQ_E014+1)
-#define SKERR_SIRQ_E015MSG	"Parity error on RAM (write)"
-#define SKERR_SIRQ_E016		(SKERR_SIRQ_E015+1)
-#define SKERR_SIRQ_E016MSG	"Parity error MAC 1"
-#define SKERR_SIRQ_E017		(SKERR_SIRQ_E016+1)
-#define SKERR_SIRQ_E017MSG	"Parity error MAC 2"
-#define SKERR_SIRQ_E018		(SKERR_SIRQ_E017+1)
-#define SKERR_SIRQ_E018MSG	"Parity error RX 1"
-#define SKERR_SIRQ_E019		(SKERR_SIRQ_E018+1)
-#define SKERR_SIRQ_E019MSG	"Parity error RX 2"
-#define SKERR_SIRQ_E020		(SKERR_SIRQ_E019+1)
-#define SKERR_SIRQ_E020MSG	"MAC transmit FIFO underrun"
-#define SKERR_SIRQ_E021		(SKERR_SIRQ_E020+1)
-#define SKERR_SIRQ_E021MSG	"Spurious TWSI interrupt"
-#define SKERR_SIRQ_E022		(SKERR_SIRQ_E021+1)
-#define SKERR_SIRQ_E022MSG	"Cable pair swap error"
-#define SKERR_SIRQ_E023		(SKERR_SIRQ_E022+1)
-#define SKERR_SIRQ_E023MSG	"Auto-negotiation error"
-#define SKERR_SIRQ_E024		(SKERR_SIRQ_E023+1)
-#define SKERR_SIRQ_E024MSG	"FIFO overflow error"
-#define SKERR_SIRQ_E025		(SKERR_SIRQ_E024+1)
-#define SKERR_SIRQ_E025MSG	"2 Pair Downshift detected"
-
-extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
-extern int  SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
-extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port);
-
-#endif	/* _INC_SKGESIRQ_H_ */
diff --git a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h
deleted file mode 100644
index 6a63f4a..0000000
--- a/drivers/net/sk98lin/h/ski2c.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/******************************************************************************
- *
- * Name:	ski2c.h
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.35 $
- * Date:	$Date: 2003/10/20 09:06:30 $
- * Purpose:	Defines to access Voltage and Temperature Sensor
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKI2C.H	contains all I2C specific defines
- */
-
-#ifndef _SKI2C_H_
-#define _SKI2C_H_
-
-typedef struct  s_Sensor SK_SENSOR;
-
-#include "h/skgei2c.h"
-
-/*
- * Define the I2C events.
- */
-#define SK_I2CEV_IRQ	1	/* IRQ happened Event */
-#define SK_I2CEV_TIM	2	/* Timeout event */
-#define SK_I2CEV_CLEAR	3	/* Clear MIB Values */
-
-/*
- * Define READ and WRITE Constants.
- */
-#define I2C_READ	0
-#define I2C_WRITE	1
-#define I2C_BURST	1
-#define I2C_SINGLE	0
-
-#define SKERR_I2C_E001		(SK_ERRBASE_I2C+0)
-#define SKERR_I2C_E001MSG	"Sensor index unknown"
-#define SKERR_I2C_E002		(SKERR_I2C_E001+1)
-#define SKERR_I2C_E002MSG	"TWSI: transfer does not complete"
-#define SKERR_I2C_E003		(SKERR_I2C_E002+1)
-#define SKERR_I2C_E003MSG	"LM80: NAK on device send"
-#define SKERR_I2C_E004		(SKERR_I2C_E003+1)
-#define SKERR_I2C_E004MSG	"LM80: NAK on register send"
-#define SKERR_I2C_E005		(SKERR_I2C_E004+1)
-#define SKERR_I2C_E005MSG	"LM80: NAK on device (2) send"
-#define SKERR_I2C_E006		(SKERR_I2C_E005+1)
-#define SKERR_I2C_E006MSG	"Unknown event"
-#define SKERR_I2C_E007		(SKERR_I2C_E006+1)
-#define SKERR_I2C_E007MSG	"LM80 read out of state"
-#define SKERR_I2C_E008		(SKERR_I2C_E007+1)
-#define SKERR_I2C_E008MSG	"Unexpected sensor read completed"
-#define SKERR_I2C_E009		(SKERR_I2C_E008+1)
-#define SKERR_I2C_E009MSG	"WARNING: temperature sensor out of range"
-#define SKERR_I2C_E010		(SKERR_I2C_E009+1)
-#define SKERR_I2C_E010MSG	"WARNING: voltage sensor out of range"
-#define SKERR_I2C_E011		(SKERR_I2C_E010+1)
-#define SKERR_I2C_E011MSG	"ERROR: temperature sensor out of range"
-#define SKERR_I2C_E012		(SKERR_I2C_E011+1)
-#define SKERR_I2C_E012MSG	"ERROR: voltage sensor out of range"
-#define SKERR_I2C_E013		(SKERR_I2C_E012+1)
-#define SKERR_I2C_E013MSG	"ERROR: couldn't init sensor"
-#define SKERR_I2C_E014		(SKERR_I2C_E013+1)
-#define SKERR_I2C_E014MSG	"WARNING: fan sensor out of range"
-#define SKERR_I2C_E015		(SKERR_I2C_E014+1)
-#define SKERR_I2C_E015MSG	"ERROR: fan sensor out of range"
-#define SKERR_I2C_E016		(SKERR_I2C_E015+1)
-#define SKERR_I2C_E016MSG	"TWSI: active transfer does not complete"
-
-/*
- * Define Timeout values
- */
-#define SK_I2C_TIM_LONG		2000000L	/* 2 seconds */
-#define SK_I2C_TIM_SHORT	 100000L	/* 100 milliseconds */
-#define SK_I2C_TIM_WATCH	1000000L	/* 1 second */
-
-/*
- * Define trap and error log hold times
- */
-#ifndef	SK_SEN_ERR_TR_HOLD
-#define SK_SEN_ERR_TR_HOLD		(4*SK_TICKS_PER_SEC)
-#endif
-#ifndef	SK_SEN_ERR_LOG_HOLD
-#define SK_SEN_ERR_LOG_HOLD		(60*SK_TICKS_PER_SEC)
-#endif
-#ifndef	SK_SEN_WARN_TR_HOLD
-#define SK_SEN_WARN_TR_HOLD		(15*SK_TICKS_PER_SEC)
-#endif
-#ifndef	SK_SEN_WARN_LOG_HOLD
-#define SK_SEN_WARN_LOG_HOLD	(15*60*SK_TICKS_PER_SEC)
-#endif
-
-/*
- * Defines for SenType
- */
-#define SK_SEN_UNKNOWN	0
-#define SK_SEN_TEMP		1
-#define SK_SEN_VOLT		2
-#define SK_SEN_FAN		3
-
-/*
- * Define for the SenErrorFlag
- */
-#define SK_SEN_ERR_NOT_PRESENT	0	/* Error Flag: Sensor not present */
-#define SK_SEN_ERR_OK			1	/* Error Flag: O.K. */
-#define SK_SEN_ERR_WARN			2	/* Error Flag: Warning */
-#define SK_SEN_ERR_ERR			3	/* Error Flag: Error */
-#define SK_SEN_ERR_FAULTY		4	/* Error Flag: Faulty */
-
-/*
- * Define the Sensor struct
- */
-struct	s_Sensor {
-	char	*SenDesc;			/* Description */
-	int		SenType;			/* Voltage or Temperature */
-	SK_I32	SenValue;			/* Current value of the sensor */
-	SK_I32	SenThreErrHigh;		/* High error Threshhold of this sensor */
-	SK_I32	SenThreWarnHigh;	/* High warning Threshhold of this sensor */
-	SK_I32	SenThreErrLow;		/* Lower error Threshold of the sensor */
-	SK_I32	SenThreWarnLow;		/* Lower warning Threshold of the sensor */
-	int		SenErrFlag;			/* Sensor indicated an error */
-	SK_BOOL	SenInit;			/* Is sensor initialized ? */
-	SK_U64	SenErrCts;			/* Error trap counter */
-	SK_U64	SenWarnCts;			/* Warning trap counter */
-	SK_U64	SenBegErrTS;		/* Begin error timestamp */
-	SK_U64	SenBegWarnTS;		/* Begin warning timestamp */
-	SK_U64	SenLastErrTrapTS;	/* Last error trap timestamp */
-	SK_U64	SenLastErrLogTS;	/* Last error log timestamp */
-	SK_U64	SenLastWarnTrapTS;	/* Last warning trap timestamp */
-	SK_U64	SenLastWarnLogTS;	/* Last warning log timestamp */
-	int		SenState;			/* Sensor State (see HW specific include) */
-	int		(*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen);
-								/* Sensors read function */
-	SK_U16	SenReg;				/* Register Address for this sensor */
-	SK_U8	SenDev;				/* Device Selection for this sensor */
-};
-
-typedef	struct	s_I2c {
-	SK_SENSOR	SenTable[SK_MAX_SENSORS];	/* Sensor Table */
-	int			CurrSens;	/* Which sensor is currently queried */
-	int			MaxSens;	/* Max. number of sensors */
-	int			TimerMode;	/* Use the timer also to watch the state machine */
-	int			InitLevel;	/* Initialized Level */
-#ifndef SK_DIAG
-	int			DummyReads;	/* Number of non-checked dummy reads */
-	SK_TIMER	SenTimer;	/* Sensors timer */
-#endif /* !SK_DIAG */
-} SK_I2C;
-
-extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level);
-#ifdef SK_DIAG
-extern	SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg,
-						 int Burst);
-#else /* !SK_DIAG */
-extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
-extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC);
-extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC);
-#endif /* !SK_DIAG */
-#endif /* n_SKI2C_H */
-
diff --git a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h
deleted file mode 100644
index 2ec40d4..0000000
--- a/drivers/net/sk98lin/h/skqueue.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/******************************************************************************
- *
- * Name:	skqueue.h
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.16 $
- * Date:	$Date: 2003/09/16 12:50:32 $
- * Purpose:	Defines for the Event queue
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKQUEUE.H	contains all defines and types for the event queue
- */
-
-#ifndef _SKQUEUE_H_
-#define _SKQUEUE_H_
-
-
-/*
- * define the event classes to be served
- */
-#define	SKGE_DRV	1	/* Driver Event Class */
-#define	SKGE_RLMT	2	/* RLMT Event Class */
-#define	SKGE_I2C	3	/* I2C Event Class */
-#define	SKGE_PNMI	4	/* PNMI Event Class */
-#define	SKGE_CSUM	5	/* Checksum Event Class */
-#define	SKGE_HWAC	6	/* Hardware Access Event Class */
-
-#define	SKGE_SWT	9	/* Software Timer Event Class */
-#define	SKGE_LACP	10	/* LACP Aggregation Event Class */
-#define	SKGE_RSF	11	/* RSF Aggregation Event Class */
-#define	SKGE_MARKER	12	/* MARKER Aggregation Event Class */
-#define	SKGE_FD		13	/* FD Distributor Event Class */
-
-/*
- * define event queue as circular buffer
- */
-#define SK_MAX_EVENT	64
-
-/*
- * Parameter union for the Para stuff
- */
-typedef	union u_EvPara {
-	void	*pParaPtr;	/* Parameter Pointer */
-	SK_U64	Para64;		/* Parameter 64bit version */
-	SK_U32	Para32[2];	/* Parameter Array of 32bit parameters */
-} SK_EVPARA;
-
-/*
- * Event Queue
- *	skqueue.c
- * events are class/value pairs
- *	class	is addressee, e.g. RLMT, PNMI etc.
- *	value	is command, e.g. line state change, ring op change etc.
- */
-typedef	struct s_EventElem {
-	SK_U32		Class;			/* Event class */
-	SK_U32		Event;			/* Event value */
-	SK_EVPARA	Para;			/* Event parameter */
-} SK_EVENTELEM;
-
-typedef	struct s_Queue {
-	SK_EVENTELEM	EvQueue[SK_MAX_EVENT];
-	SK_EVENTELEM	*EvPut;
-	SK_EVENTELEM	*EvGet;
-} SK_QUEUE;
-
-extern	void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level);
-extern	void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event,
-	SK_EVPARA Para);
-extern	int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc);
-
-
-/* Define Error Numbers and messages */
-#define	SKERR_Q_E001	(SK_ERRBASE_QUEUE+0)
-#define	SKERR_Q_E001MSG	"Event queue overflow"
-#define	SKERR_Q_E002	(SKERR_Q_E001+1)
-#define	SKERR_Q_E002MSG	"Undefined event class"
-#endif	/* _SKQUEUE_H_ */
-
diff --git a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h
deleted file mode 100644
index ca75dfd..0000000
--- a/drivers/net/sk98lin/h/skrlmt.h
+++ /dev/null
@@ -1,438 +0,0 @@
-/******************************************************************************
- *
- * Name:	skrlmt.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.37 $
- * Date:	$Date: 2003/04/15 09:43:43 $
- * Purpose:	Header file for Redundant Link ManagemenT.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the header file for Redundant Link ManagemenT.
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	...
- *	"sktypes.h"
- *	"skqueue.h"
- *	"skaddr.h"
- *	"skrlmt.h"
- *	...
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKRLMT_H
-#define __INC_SKRLMT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-/* defines ********************************************************************/
-
-#define	SK_RLMT_NET_DOWN_TEMP	1	/* NET_DOWN due to last port down. */
-#define	SK_RLMT_NET_DOWN_FINAL	2	/* NET_DOWN due to RLMT_STOP. */
-
-/* ----- Default queue sizes - must be multiples of 8 KB ----- */
-
-/* Less than 8 KB free in RX queue => pause frames. */
-#define SK_RLMT_STANDBY_QRXSIZE	128	/* Size of rx standby queue in KB. */
-#define SK_RLMT_STANDBY_QXASIZE	32	/* Size of async standby queue in KB. */
-#define SK_RLMT_STANDBY_QXSSIZE	0	/* Size of sync standby queue in KB. */
-
-#define SK_RLMT_MAX_TX_BUF_SIZE	60	/* Maximum RLMT transmit size. */
-
-/* ----- PORT states ----- */
-
-#define SK_RLMT_PS_INIT			0	/* Port state: Init. */
-#define SK_RLMT_PS_LINK_DOWN	1	/* Port state: Link down. */
-#define SK_RLMT_PS_DOWN			2	/* Port state: Port down. */
-#define SK_RLMT_PS_GOING_UP		3	/* Port state: Going up. */
-#define SK_RLMT_PS_UP			4	/* Port state: Up. */
-
-/* ----- RLMT states ----- */
-
-#define SK_RLMT_RS_INIT			0	/* RLMT state: Init. */
-#define SK_RLMT_RS_NET_DOWN		1	/* RLMT state: Net down. */
-#define SK_RLMT_RS_NET_UP		2	/* RLMT state: Net up. */
-
-/* ----- PORT events ----- */
-
-#define SK_RLMT_LINK_UP			1001	/* Link came up. */
-#define SK_RLMT_LINK_DOWN		1002	/* Link went down. */
-#define SK_RLMT_PORT_ADDR		1003	/* Port address changed. */
-
-/* ----- RLMT events ----- */
-
-#define SK_RLMT_START			2001	/* Start RLMT. */
-#define SK_RLMT_STOP			2002	/* Stop RLMT. */
-#define SK_RLMT_PACKET_RECEIVED	2003	/* Packet was received for RLMT. */
-#define SK_RLMT_STATS_CLEAR		2004	/* Clear statistics. */
-#define SK_RLMT_STATS_UPDATE	2005	/* Update statistics. */
-#define SK_RLMT_PREFPORT_CHANGE	2006	/* Change preferred port. */
-#define SK_RLMT_MODE_CHANGE		2007	/* New RlmtMode. */
-#define SK_RLMT_SET_NETS		2008	/* Number of Nets (1 or 2). */
-
-/* ----- RLMT mode bits ----- */
-
-/*
- * CAUTION:	These defines are private to RLMT.
- *			Please use the RLMT mode defines below.
- */
-
-#define SK_RLMT_CHECK_LINK		  1		/* Check Link. */
-#define SK_RLMT_CHECK_LOC_LINK	  2		/* Check other link on same adapter. */
-#define SK_RLMT_CHECK_SEG		  4		/* Check segmentation. */
-
-#ifndef RLMT_CHECK_REMOTE
-#define SK_RLMT_CHECK_OTHERS	SK_RLMT_CHECK_LOC_LINK
-#else	/* RLMT_CHECK_REMOTE */
-#define SK_RLMT_CHECK_REM_LINK	  8		/* Check link(s) on other adapter(s). */
-#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED	3
-#define SK_RLMT_CHECK_OTHERS	\
-		(SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
-#endif	/* RLMT_CHECK_REMOTE */
-
-#ifndef SK_RLMT_ENABLE_TRANSPARENT
-#define SK_RLMT_TRANSPARENT		  0		/* RLMT transparent - inactive. */
-#else	/* SK_RLMT_ENABLE_TRANSPARENT */
-#define SK_RLMT_TRANSPARENT		128		/* RLMT transparent. */
-#endif	/* SK_RLMT_ENABLE_TRANSPARENT */
-
-/* ----- RLMT modes ----- */
-
-/* Check Link State. */
-#define SK_RLMT_MODE_CLS	(SK_RLMT_CHECK_LINK)
-
-/* Check Local Ports: check other links on the same adapter. */
-#define SK_RLMT_MODE_CLP	(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK)
-
-/* Check Local Ports and Segmentation Status. */
-#define SK_RLMT_MODE_CLPSS	\
-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG)
-
-#ifdef RLMT_CHECK_REMOTE
-/* Check Local and Remote Ports: check links (local or remote). */
-	Name of define TBD!
-#define SK_RLMT_MODE_CRP	\
-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
-
-/* Check Local and Remote Ports and Segmentation Status. */
-	Name of define TBD!
-#define SK_RLMT_MODE_CRPSS	\
-		(SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \
-		SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG)
-#endif	/* RLMT_CHECK_REMOTE */
-
-/* ----- RLMT lookahead result bits ----- */
-
-#define SK_RLMT_RX_RLMT			1	/* Give packet to RLMT. */
-#define SK_RLMT_RX_PROTOCOL		2	/* Give packet to protocol. */
-
-/* Macros */
-
-#if 0
-SK_AC		*pAC		/* adapter context */
-SK_U32		PortNum		/* receiving port */
-unsigned	PktLen		/* received packet's length */
-SK_BOOL		IsBc		/* Flag: packet is broadcast */
-unsigned	*pOffset	/* offs. of bytes to present to SK_RLMT_LOOKAHEAD */
-unsigned	*pNumBytes	/* #Bytes to present to SK_RLMT_LOOKAHEAD */
-#endif	/* 0 */
-
-#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \
-	SK_AC	*_pAC; \
-	SK_U32	_PortNum; \
-	_pAC = (pAC); \
-	_PortNum = (SK_U32)(PortNum); \
-	/* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \
-	_pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \
-    if (_pAC->Rlmt.RlmtOff) { \
-		*(pNumBytes) = 0; \
-    } \
-    else {\
-        if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \
-    		*(pNumBytes) = 0; \
-    	} \
-    	else if (IsBc) { \
-    		if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \
-    			*(pNumBytes) = 6; \
-    			*(pOffset) = 6; \
-    		} \
-    		else { \
-    			*(pNumBytes) = 0; \
-    		} \
-    	} \
-    	else { \
-    		if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \
-    			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-    			*(pNumBytes) = 0; \
-    		} \
-    		else { \
-    			*(pNumBytes) = 6; \
-    			*(pOffset) = 0; \
-    		} \
-    	} \
-    } \
-}
-
-#if 0
-SK_AC		*pAC		/* adapter context */
-SK_U32		PortNum		/* receiving port */
-SK_U8		*pLaPacket,	/* received packet's data (points to pOffset) */
-SK_BOOL		IsBc		/* Flag: packet is broadcast */
-SK_BOOL		IsMc		/* Flag: packet is multicast */
-unsigned	*pForRlmt	/* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */
-SK_RLMT_LOOKAHEAD() expects *pNumBytes from
-packet offset *pOffset (s.a.) at *pLaPacket.
-
-If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is
-BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler
-can trash unneeded parts of the if construction.
-#endif	/* 0 */
-
-#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \
-	SK_AC	*_pAC; \
-	SK_U32	_PortNum; \
-	SK_U8	*_pLaPacket; \
-	_pAC = (pAC); \
-	_PortNum = (SK_U32)(PortNum); \
-	_pLaPacket = (SK_U8 *)(pLaPacket); \
-	if (IsBc) {\
-		if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \
-			_PortNum].Net->NetNumber].CurrentMacAddress.a)) { \
-			_pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \
-			_pAC->Rlmt.CheckSwitch = SK_TRUE; \
-		} \
-		/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-		*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-	} \
-	else if (IsMc) { \
-		if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \
-			_pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \
-			if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \
-				*(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \
-			} \
-			else { \
-				*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-			} \
-		} \
-		else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \
-			*(pForRlmt) = SK_RLMT_RX_RLMT; \
-		} \
-		else { \
-			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-			*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-		} \
-	} \
-	else { \
-		if (SK_ADDR_EQUAL( \
-			_pLaPacket, \
-			_pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \
-			*(pForRlmt) = SK_RLMT_RX_RLMT; \
-		} \
-		else { \
-			/* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
-			*(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
-		} \
-	} \
-}
-
-#ifdef SK_RLMT_FAST_LOOKAHEAD
-Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead.
-#endif	/* SK_RLMT_FAST_LOOKAHEAD */
-#ifdef SK_RLMT_SLOW_LOOKAHEAD
-Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead.
-#endif	/* SK_RLMT_SLOW_LOOKAHEAD */
-
-/* typedefs *******************************************************************/
-
-#ifdef SK_RLMT_MBUF_PRIVATE
-typedef struct s_RlmtMbuf {
-	some content
-} SK_RLMT_MBUF;
-#endif	/* SK_RLMT_MBUF_PRIVATE */
-
-
-#ifdef SK_LA_INFO
-typedef struct s_Rlmt_PacketInfo {
-	unsigned	PacketLength;			/* Length of packet. */
-	unsigned	PacketType;				/* Directed/Multicast/Broadcast. */
-} SK_RLMT_PINFO;
-#endif	/* SK_LA_INFO */
-
-
-typedef struct s_RootId {
-	SK_U8		Id[8];					/* Root Bridge Id. */
-} SK_RLMT_ROOT_ID;
-
-
-typedef struct s_port {
-	SK_MAC_ADDR	CheckAddr;
-	SK_BOOL		SuspectTx;
-} SK_PORT_CHECK;
-
-
-typedef struct s_RlmtNet SK_RLMT_NET;
-
-
-typedef struct s_RlmtPort {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_U8			PortState;				/* Current state of this port. */
-
-	/* For PNMI */
-	SK_BOOL			LinkDown;
-	SK_BOOL			PortDown;
-	SK_U8			Align01;
-
-	SK_U32			PortNumber;				/* Number of port on adapter. */
-	SK_RLMT_NET *	Net;					/* Net port belongs to. */
-
-	SK_U64			TxHelloCts;
-	SK_U64			RxHelloCts;
-	SK_U64			TxSpHelloReqCts;
-	SK_U64			RxSpHelloCts;
-
-/* ----- Private part ----- */
-
-/*	SK_U64			PacketsRx; */				/* Total packets received. */
-	SK_U32			PacketsPerTimeSlot;		/* Packets rxed between TOs. */
-/*	SK_U32			DataPacketsPerTimeSlot; */	/* Data packets ... */
-	SK_U32			BpduPacketsPerTimeSlot;	/* BPDU packets rxed in TS. */
-	SK_U64			BcTimeStamp;			/* Time of last BC receive. */
-	SK_U64			GuTimeStamp;			/* Time of entering GOING_UP. */
-
-	SK_TIMER		UpTimer;				/* Timer struct Link/Port up. */
-	SK_TIMER		DownRxTimer;			/* Timer struct down rx. */
-	SK_TIMER		DownTxTimer;			/* Timer struct down tx. */
-
-	SK_U32			CheckingState;			/* Checking State. */
-
-	SK_ADDR_PORT *	AddrPort;
-
-	SK_U8			Random[4];				/* Random value. */
-	unsigned		PortsChecked;			/* #ports checked. */
-	unsigned		PortsSuspect;			/* #ports checked that are s. */
-	SK_PORT_CHECK	PortCheck[1];
-/*	SK_PORT_CHECK	PortCheck[SK_MAX_MACS - 1]; */
-
-	SK_BOOL			PortStarted;			/* Port is started. */
-	SK_BOOL			PortNoRx;				/* NoRx for >= 1 time slot. */
-	SK_BOOL			RootIdSet;
-	SK_RLMT_ROOT_ID	Root;					/* Root Bridge Id. */
-} SK_RLMT_PORT;
-
-
-struct s_RlmtNet {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_U32			NetNumber;			/* Number of net. */
-
-	SK_RLMT_PORT *	Port[SK_MAX_MACS];	/* Ports that belong to this net. */
-	SK_U32			NumPorts;			/* Number of ports. */
-	SK_U32			PrefPort;			/* Preferred port. */
-
-	/* For PNMI */
-
-	SK_U32			ChgBcPrio;			/* Change Priority of last broadcast received */
-	SK_U32			RlmtMode;			/* Check ... */
-	SK_U32			ActivePort;			/* Active port. */
-	SK_U32			Preference;		/* 0xFFFFFFFF: Automatic. */
-
-	SK_U8			RlmtState;			/* Current RLMT state. */
-
-/* ----- Private part ----- */
-	SK_BOOL			RootIdSet;
-	SK_U16			Align01;
-
-	int				LinksUp;			/* #Links up. */
-	int				PortsUp;			/* #Ports up. */
-	SK_U32			TimeoutValue;		/* RLMT timeout value. */
-
-	SK_U32			CheckingState;		/* Checking State. */
-	SK_RLMT_ROOT_ID	Root;				/* Root Bridge Id. */
-
-	SK_TIMER		LocTimer;			/* Timer struct. */
-	SK_TIMER		SegTimer;			/* Timer struct. */
-};
-
-
-typedef struct s_Rlmt {
-
-/* ----- Public part (read-only) ----- */
-
-	SK_U32			NumNets;			/* Number of nets. */
-	SK_U32			NetsStarted;		/* Number of nets started. */
-	SK_RLMT_NET		Net[SK_MAX_NETS];	/* Array of available nets. */
-	SK_RLMT_PORT	Port[SK_MAX_MACS];	/* Array of available ports. */
-
-/* ----- Private part ----- */
-	SK_BOOL			CheckSwitch;
-	SK_BOOL			RlmtOff;            /* set to zero if the Mac addresses 
-                                           are equal or the second one 
-                                           is zero */
-	SK_U16			Align01;
-
-} SK_RLMT;
-
-
-extern	SK_MAC_ADDR	BridgeMcAddr;
-extern	SK_MAC_ADDR	SkRlmtMcAddr;
-
-/* function prototypes ********************************************************/
-
-
-#ifndef SK_KR_PROTO
-
-/* Functions provided by SkRlmt */
-
-/* ANSI/C++ compliant function prototypes */
-
-extern	void	SkRlmtInit(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	int		Level);
-
-extern	int	SkRlmtEvent(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_U32		Event,
-	SK_EVPARA	Para);
-
-#else	/* defined(SK_KR_PROTO) */
-
-/* Non-ANSI/C++ compliant function prototypes */
-
-#error KR-style function prototypes are not yet provided.
-
-#endif	/* defined(SK_KR_PROTO)) */
-
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_SKRLMT_H */
diff --git a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h
deleted file mode 100644
index 04e6d7c..0000000
--- a/drivers/net/sk98lin/h/sktimer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/******************************************************************************
- *
- * Name:	sktimer.h
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.11 $
- * Date:	$Date: 2003/09/16 12:58:18 $
- * Purpose:	Defines for the timer functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKTIMER.H	contains all defines and types for the timer functions
- */
-
-#ifndef	_SKTIMER_H_
-#define _SKTIMER_H_
-
-#include "h/skqueue.h"
-
-/*
- * SK timer
- * - needed wherever a timer is used. Put this in your data structure
- *   wherever you want.
- */
-typedef	struct s_Timer SK_TIMER;
-
-struct s_Timer {
-	SK_TIMER	*TmNext;	/* linked list */
-	SK_U32		TmClass;	/* Timer Event class */
-	SK_U32		TmEvent;	/* Timer Event value */
-	SK_EVPARA	TmPara;		/* Timer Event parameter */
-	SK_U32		TmDelta;	/* delta time */
-	int			TmActive;	/* flag: active/inactive */
-};
-
-/*
- * Timer control struct.
- * - use in Adapters context name pAC->Tim
- */
-typedef	struct s_TimCtrl {
-	SK_TIMER	*StQueue;	/* Head of Timer queue */
-} SK_TIMCTRL;
-
-extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level);
-extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer);
-extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer,
-	SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para);
-extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc);
-#endif	/* _SKTIMER_H_ */
diff --git a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h
deleted file mode 100644
index 40edc96..0000000
--- a/drivers/net/sk98lin/h/sktypes.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/******************************************************************************
- *
- * Name:	sktypes.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.2 $
- * Date:	$Date: 2003/10/07 08:16:51 $
- * Purpose:	Define data types for Linux
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
- 
-/******************************************************************************
- *
- * Description:
- *
- * In this file, all data types that are needed by the common modules
- * are mapped to Linux data types.
- * 
- *
- * Include File Hierarchy:
- *
- *
- ******************************************************************************/
-
-#ifndef __INC_SKTYPES_H
-#define __INC_SKTYPES_H
-
-
-/* defines *******************************************************************/
-
-/*
- * Data types with a specific size. 'I' = signed, 'U' = unsigned.
- */
-#define SK_I8	s8
-#define SK_U8	u8
-#define SK_I16	s16
-#define SK_U16	u16
-#define SK_I32	s32
-#define SK_U32	u32
-#define SK_I64	s64
-#define SK_U64	u64
-
-#define SK_UPTR	ulong		/* casting pointer <-> integral */
-
-/*
-* Boolean type.
-*/
-#define SK_BOOL		SK_U8
-#define SK_FALSE	0
-#define SK_TRUE		(!SK_FALSE)
-
-/* typedefs *******************************************************************/
-
-/* function prototypes ********************************************************/
-
-#endif	/* __INC_SKTYPES_H */
diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h
deleted file mode 100644
index a1a7294..0000000
--- a/drivers/net/sk98lin/h/skversion.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/******************************************************************************
- *
- * Name:	version.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.5 $
- * Date:	$Date: 2003/10/07 08:16:51 $
- * Purpose:	SK specific Error log support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifdef	lint
-static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH.";
-static const char SysKonnectBuildNumber[] =
-	"@(#)SK-BUILD: 6.23 PL: 01"; 
-#endif	/* !defined(lint) */
-
-#define BOOT_STRING	"sk98lin: Network Device Driver v6.23\n" \
-			"(C)Copyright 1999-2004 Marvell(R)."
-
-#define VER_STRING	"6.23"
-#define DRIVER_FILE_NAME	"sk98lin"
-#define DRIVER_REL_DATE		"Feb-13-2004"
-
-
diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h
deleted file mode 100644
index fdd9e48..0000000
--- a/drivers/net/sk98lin/h/skvpd.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/******************************************************************************
- *
- * Name:	skvpd.h
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.15 $
- * Date:	$Date: 2003/01/13 10:39:38 $
- * Purpose:	Defines and Macros for VPD handling
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2003 SysKonnect GmbH.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * skvpd.h	contains Diagnostic specific defines for VPD handling
- */
-
-#ifndef __INC_SKVPD_H_
-#define __INC_SKVPD_H_
-
-/*
- * Define Resource Type Identifiers and VPD keywords
- */
-#define	RES_ID		0x82	/* Resource Type ID String (Product Name) */
-#define RES_VPD_R	0x90	/* start of VPD read only area */
-#define RES_VPD_W	0x91	/* start of VPD read/write area */
-#define RES_END		0x78	/* Resource Type End Tag */
-
-#ifndef VPD_NAME
-#define VPD_NAME	"Name"	/* Product Name, VPD name of RES_ID */
-#endif	/* VPD_NAME */
-#define VPD_PN		"PN"	/* Adapter Part Number */
-#define	VPD_EC		"EC"	/* Adapter Engineering Level */
-#define VPD_MN		"MN"	/* Manufacture ID */
-#define VPD_SN		"SN"	/* Serial Number */
-#define VPD_CP		"CP"	/* Extended Capability */
-#define VPD_RV		"RV"	/* Checksum and Reserved */
-#define	VPD_YA		"YA"	/* Asset Tag Identifier */
-#define VPD_VL		"VL"	/* First Error Log Message (SK specific) */
-#define VPD_VF		"VF"	/* Second Error Log Message (SK specific) */
-#define VPD_RW		"RW"	/* Remaining Read / Write Area */
-
-/* 'type' values for vpd_setup_para() */
-#define VPD_RO_KEY	1	/* RO keys are "PN", "EC", "MN", "SN", "RV" */
-#define VPD_RW_KEY	2	/* RW keys are "Yx", "Vx", and "RW" */
-
-/* 'op' values for vpd_setup_para() */
-#define	ADD_KEY		1	/* add the key at the pos "RV" or "RW" */
-#define OWR_KEY		2	/* overwrite key if already exists */
-
-/*
- * Define READ and WRITE Constants.
- */
-
-#define VPD_DEV_ID_GENESIS 	0x4300
-
-#define	VPD_SIZE_YUKON		256
-#define	VPD_SIZE_GENESIS	512
-#define	VPD_SIZE			512
-#define VPD_READ	0x0000
-#define VPD_WRITE	0x8000
-
-#define VPD_STOP(pAC,IoC)	VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE)
-
-#define VPD_GET_RES_LEN(p)	((unsigned int) \
-					(* (SK_U8 *)&(p)[1]) |\
-					((* (SK_U8 *)&(p)[2]) << 8))
-#define VPD_GET_VPD_LEN(p)	((unsigned int)(* (SK_U8 *)&(p)[2]))
-#define VPD_GET_VAL(p)		((char *)&(p)[3])
-
-#define VPD_MAX_LEN	50
-
-/* VPD status */
-	/* bit 7..1 reserved */
-#define VPD_VALID	(1<<0)	/* VPD data buffer, vpd_free_ro, */
-							/* and vpd_free_rw valid	 */
-
-/*
- * VPD structs
- */
-typedef	struct s_vpd_status {
-	unsigned short	Align01;			/* Alignment */
-	unsigned short	vpd_status;			/* VPD status, description see above */
-	int				vpd_free_ro;		/* unused bytes in read only area */
-	int				vpd_free_rw;		/* bytes available in read/write area */
-} SK_VPD_STATUS;
-
-typedef	struct s_vpd {
-	SK_VPD_STATUS	v;					/* VPD status structure */
-	char			vpd_buf[VPD_SIZE];	/* VPD buffer */
-	int				rom_size;			/* VPD ROM Size from PCI_OUR_REG_2 */
-	int				vpd_size;			/* saved VPD-size */
-} SK_VPD;
-
-typedef	struct s_vpd_para {
-	unsigned int	p_len;	/* parameter length */
-	char			*p_val;	/* points to the value */
-} SK_VPD_PARA;
-
-/*
- * structure of Large Resource Type Identifiers
- */
-
-/* was removed because of alignment problems */
-
-/*
- * structure of VPD keywords
- */
-typedef	struct s_vpd_key {
-	char			p_key[2];	/* 2 bytes ID string */
-	unsigned char	p_len;		/* 1 byte length */
-	char			p_val;		/* start of the value string */
-} SK_VPD_KEY;
-
-
-/*
- * System specific VPD macros
- */
-#ifndef SKDIAG
-#ifndef VPD_DO_IO
-#define VPD_OUT8(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgByte(pAC,Addr,Val)
-#define VPD_OUT16(pAC,IoC,Addr,Val)	(void)SkPciWriteCfgWord(pAC,Addr,Val)
-#define VPD_IN8(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgByte(pAC,Addr,pVal)
-#define VPD_IN16(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgWord(pAC,Addr,pVal)
-#define VPD_IN32(pAC,IoC,Addr,pVal)	(void)SkPciReadCfgDWord(pAC,Addr,pVal)
-#else	/* VPD_DO_IO */
-#define VPD_OUT8(pAC,IoC,Addr,Val)	SK_OUT8(IoC,PCI_C(Addr),Val)
-#define VPD_OUT16(pAC,IoC,Addr,Val)	SK_OUT16(IoC,PCI_C(Addr),Val)
-#define VPD_IN8(pAC,IoC,Addr,pVal)	SK_IN8(IoC,PCI_C(Addr),pVal)
-#define VPD_IN16(pAC,IoC,Addr,pVal)	SK_IN16(IoC,PCI_C(Addr),pVal)
-#define VPD_IN32(pAC,IoC,Addr,pVal)	SK_IN32(IoC,PCI_C(Addr),pVal)
-#endif	/* VPD_DO_IO */
-#else	/* SKDIAG */
-#define VPD_OUT8(pAC,Ioc,Addr,Val) {			\
-		if ((pAC)->DgT.DgUseCfgCycle)			\
-			SkPciWriteCfgByte(pAC,Addr,Val);	\
-		else									\
-			SK_OUT8(pAC,PCI_C(Addr),Val);		\
-		}
-#define VPD_OUT16(pAC,Ioc,Addr,Val) {			\
-		if ((pAC)->DgT.DgUseCfgCycle)			\
-			SkPciWriteCfgWord(pAC,Addr,Val);	\
-		else						\
-			SK_OUT16(pAC,PCI_C(Addr),Val);		\
-		}
-#define VPD_IN8(pAC,Ioc,Addr,pVal) {			\
-		if ((pAC)->DgT.DgUseCfgCycle) 			\
-			SkPciReadCfgByte(pAC,Addr,pVal);	\
-		else						\
-			SK_IN8(pAC,PCI_C(Addr),pVal); 		\
-		}
-#define VPD_IN16(pAC,Ioc,Addr,pVal) {			\
-		if ((pAC)->DgT.DgUseCfgCycle) 			\
-			SkPciReadCfgWord(pAC,Addr,pVal);	\
-		else						\
-			SK_IN16(pAC,PCI_C(Addr),pVal); 		\
-		}
-#define VPD_IN32(pAC,Ioc,Addr,pVal) {			\
-		if ((pAC)->DgT.DgUseCfgCycle)			\
-			SkPciReadCfgDWord(pAC,Addr,pVal);	\
-		else						\
-			SK_IN32(pAC,PCI_C(Addr),pVal);		\
-		}
-#endif	/* nSKDIAG */
-
-/* function prototypes ********************************************************/
-
-#ifndef	SK_KR_PROTO
-#ifdef SKDIAG
-extern SK_U32	VpdReadDWord(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	int			addr);
-#endif	/* SKDIAG */
-
-extern SK_VPD_STATUS	*VpdStat(
-	SK_AC		*pAC,
-	SK_IOC		IoC);
-
-extern int	VpdKeys(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*buf,
-	int			*len,
-	int			*elements);
-
-extern int	VpdRead(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	const char	*key,
-	char		*buf,
-	int			*len);
-
-extern SK_BOOL	VpdMayWrite(
-	char		*key);
-
-extern int	VpdWrite(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	const char	*key,
-	const char	*buf);
-
-extern int	VpdDelete(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*key);
-
-extern int	VpdUpdate(
-	SK_AC		*pAC,
-	SK_IOC		IoC);
-
-#ifdef	SKDIAG
-extern int	VpdReadBlock(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*buf,
-	int			addr,
-	int			len);
-
-extern int	VpdWriteBlock(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	char		*buf,
-	int			addr,
-	int			len);
-#endif	/* SKDIAG */
-#else	/* SK_KR_PROTO */
-extern SK_U32	VpdReadDWord();
-extern SK_VPD_STATUS	*VpdStat();
-extern int	VpdKeys();
-extern int	VpdRead();
-extern SK_BOOL	VpdMayWrite();
-extern int	VpdWrite();
-extern int	VpdDelete();
-extern int	VpdUpdate();
-#endif	/* SK_KR_PROTO */
-
-#endif	/* __INC_SKVPD_H_ */
diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h
deleted file mode 100644
index 7f8e6d0..0000000
--- a/drivers/net/sk98lin/h/xmac_ii.h
+++ /dev/null
@@ -1,1579 +0,0 @@
-/******************************************************************************
- *
- * Name:	xmac_ii.h
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.52 $
- * Date:	$Date: 2003/10/02 16:35:50 $
- * Purpose:	Defines and Macros for Gigabit Ethernet Controller
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_XMAC_H
-#define __INC_XMAC_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* __cplusplus */
-
-/* defines ********************************************************************/
-
-/*
- * XMAC II registers
- *
- * The XMAC registers are 16 or 32 bits wide.
- * The XMACs host processor interface is set to 16 bit mode,
- * therefore ALL registers will be addressed with 16 bit accesses.
- *
- * The following macros are provided to access the XMAC registers
- * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(),
- * XM_INHASH(), and XM_OUTHASH().
- * The macros are defined in SkGeHw.h.
- *
- * Note:	NA reg	= Network Address e.g DA, SA etc.
- *
- */
-#define XM_MMU_CMD		0x0000	/* 16 bit r/w	MMU Command Register */
-	/* 0x0004:		reserved */
-#define XM_POFF			0x0008	/* 32 bit r/w	Packet Offset Register */
-#define XM_BURST		0x000c	/* 32 bit r/w	Burst Register for half duplex*/
-#define XM_1L_VLAN_TAG	0x0010	/* 16 bit r/w	One Level VLAN Tag ID */
-#define XM_2L_VLAN_TAG	0x0014	/* 16 bit r/w	Two Level VLAN Tag ID */
-	/* 0x0018 - 0x001e:	reserved */
-#define XM_TX_CMD		0x0020	/* 16 bit r/w	Transmit Command Register */
-#define XM_TX_RT_LIM	0x0024	/* 16 bit r/w	Transmit Retry Limit Register */
-#define XM_TX_STIME		0x0028	/* 16 bit r/w	Transmit Slottime Register */
-#define XM_TX_IPG		0x002c	/* 16 bit r/w	Transmit Inter Packet Gap */
-#define XM_RX_CMD		0x0030	/* 16 bit r/w	Receive Command Register */
-#define XM_PHY_ADDR		0x0034	/* 16 bit r/w	PHY Address Register */
-#define XM_PHY_DATA		0x0038	/* 16 bit r/w	PHY Data Register */
-	/* 0x003c: 		reserved */
-#define XM_GP_PORT		0x0040	/* 32 bit r/w	General Purpose Port Register */
-#define XM_IMSK			0x0044	/* 16 bit r/w	Interrupt Mask Register */
-#define XM_ISRC			0x0048	/* 16 bit r/o	Interrupt Status Register */
-#define XM_HW_CFG		0x004c	/* 16 bit r/w	Hardware Config Register */
-	/* 0x0050 - 0x005e:	reserved */
-#define XM_TX_LO_WM		0x0060	/* 16 bit r/w	Tx FIFO Low Water Mark */
-#define XM_TX_HI_WM		0x0062	/* 16 bit r/w	Tx FIFO High Water Mark */
-#define XM_TX_THR		0x0064	/* 16 bit r/w	Tx Request Threshold */
-#define XM_HT_THR		0x0066	/* 16 bit r/w	Host Request Threshold */
-#define XM_PAUSE_DA		0x0068	/* NA reg r/w	Pause Destination Address */
-	/* 0x006e: 		reserved */
-#define XM_CTL_PARA		0x0070	/* 32 bit r/w	Control Parameter Register */
-#define XM_MAC_OPCODE	0x0074	/* 16 bit r/w	Opcode for MAC control frames */
-#define XM_MAC_PTIME	0x0076	/* 16 bit r/w	Pause time for MAC ctrl frames*/
-#define XM_TX_STAT		0x0078	/* 32 bit r/o	Tx Status LIFO Register */
-
-	/* 0x0080 - 0x00fc:	16 NA reg r/w	Exact Match Address Registers */
-	/* 				use the XM_EXM() macro to address */
-#define XM_EXM_START	0x0080	/* r/w	Start Address of the EXM Regs */
-
-	/*
-	 * XM_EXM(Reg)
-	 *
-	 * returns the XMAC address offset of specified Exact Match Addr Reg
-	 *
-	 * para:	Reg	EXM register to addr	(0 .. 15)
-	 *
-	 * usage:	XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]);
-	 */
-#define XM_EXM(Reg)	(XM_EXM_START + ((Reg) << 3))
-
-#define XM_SRC_CHK		0x0100	/* NA reg r/w	Source Check Address Register */
-#define XM_SA			0x0108	/* NA reg r/w	Station Address Register */
-#define XM_HSM			0x0110	/* 64 bit r/w	Hash Match Address Registers */
-#define XM_RX_LO_WM		0x0118	/* 16 bit r/w	Receive Low Water Mark */
-#define XM_RX_HI_WM		0x011a	/* 16 bit r/w	Receive High Water Mark */
-#define XM_RX_THR		0x011c	/* 32 bit r/w	Receive Request Threshold */
-#define XM_DEV_ID		0x0120	/* 32 bit r/o	Device ID Register */
-#define XM_MODE			0x0124	/* 32 bit r/w	Mode Register */
-#define XM_LSA			0x0128	/* NA reg r/o	Last Source Register */
-	/* 0x012e:		reserved */
-#define XM_TS_READ		0x0130	/* 32 bit r/o	Time Stamp Read Register */
-#define XM_TS_LOAD		0x0134	/* 32 bit r/o	Time Stamp Load Value */
-	/* 0x0138 - 0x01fe:	reserved */
-#define XM_STAT_CMD	0x0200	/* 16 bit r/w	Statistics Command Register */
-#define XM_RX_CNT_EV	0x0204	/* 32 bit r/o	Rx Counter Event Register */
-#define XM_TX_CNT_EV	0x0208	/* 32 bit r/o	Tx Counter Event Register */
-#define XM_RX_EV_MSK	0x020c	/* 32 bit r/w	Rx Counter Event Mask */
-#define XM_TX_EV_MSK	0x0210	/* 32 bit r/w	Tx Counter Event Mask */
-	/* 0x0204 - 0x027e:	reserved */
-#define XM_TXF_OK		0x0280	/* 32 bit r/o	Frames Transmitted OK Conuter */
-#define XM_TXO_OK_HI	0x0284	/* 32 bit r/o	Octets Transmitted OK High Cnt*/
-#define XM_TXO_OK_LO	0x0288	/* 32 bit r/o	Octets Transmitted OK Low Cnt */
-#define XM_TXF_BC_OK	0x028c	/* 32 bit r/o	Broadcast Frames Xmitted OK */
-#define XM_TXF_MC_OK	0x0290	/* 32 bit r/o	Multicast Frames Xmitted OK */
-#define XM_TXF_UC_OK	0x0294	/* 32 bit r/o	Unicast Frames Xmitted OK */
-#define XM_TXF_LONG		0x0298	/* 32 bit r/o	Tx Long Frame Counter */
-#define XM_TXE_BURST	0x029c	/* 32 bit r/o	Tx Burst Event Counter */
-#define XM_TXF_MPAUSE	0x02a0	/* 32 bit r/o	Tx Pause MAC Ctrl Frame Cnt */
-#define XM_TXF_MCTRL	0x02a4	/* 32 bit r/o	Tx MAC Ctrl Frame Counter */
-#define XM_TXF_SNG_COL	0x02a8	/* 32 bit r/o	Tx Single Collision Counter */
-#define XM_TXF_MUL_COL	0x02ac	/* 32 bit r/o	Tx Multiple Collision Counter */
-#define XM_TXF_ABO_COL	0x02b0	/* 32 bit r/o	Tx aborted due to Exces. Col. */
-#define XM_TXF_LAT_COL	0x02b4	/* 32 bit r/o	Tx Late Collision Counter */
-#define XM_TXF_DEF		0x02b8	/* 32 bit r/o	Tx Deferred Frame Counter */
-#define XM_TXF_EX_DEF	0x02bc	/* 32 bit r/o	Tx Excessive Deferall Counter */
-#define XM_TXE_FIFO_UR	0x02c0	/* 32 bit r/o	Tx FIFO Underrun Event Cnt */
-#define XM_TXE_CS_ERR	0x02c4	/* 32 bit r/o	Tx Carrier Sense Error Cnt */
-#define XM_TXP_UTIL		0x02c8	/* 32 bit r/o	Tx Utilization in % */
-	/* 0x02cc - 0x02ce:	reserved */
-#define XM_TXF_64B		0x02d0	/* 32 bit r/o	64 Byte Tx Frame Counter */
-#define XM_TXF_127B		0x02d4	/* 32 bit r/o	65-127 Byte Tx Frame Counter */
-#define XM_TXF_255B		0x02d8	/* 32 bit r/o	128-255 Byte Tx Frame Counter */
-#define XM_TXF_511B		0x02dc	/* 32 bit r/o	256-511 Byte Tx Frame Counter */
-#define XM_TXF_1023B	0x02e0	/* 32 bit r/o	512-1023 Byte Tx Frame Counter*/
-#define XM_TXF_MAX_SZ	0x02e4	/* 32 bit r/o	1024-MaxSize Byte Tx Frame Cnt*/
-	/* 0x02e8 - 0x02fe:	reserved */
-#define XM_RXF_OK		0x0300	/* 32 bit r/o	Frames Received OK */
-#define XM_RXO_OK_HI	0x0304	/* 32 bit r/o	Octets Received OK High Cnt */
-#define XM_RXO_OK_LO	0x0308	/* 32 bit r/o	Octets Received OK Low Counter*/
-#define XM_RXF_BC_OK	0x030c	/* 32 bit r/o	Broadcast Frames Received OK */
-#define XM_RXF_MC_OK	0x0310	/* 32 bit r/o	Multicast Frames Received OK */
-#define XM_RXF_UC_OK	0x0314	/* 32 bit r/o	Unicast Frames Received OK */
-#define XM_RXF_MPAUSE	0x0318	/* 32 bit r/o	Rx Pause MAC Ctrl Frame Cnt */
-#define XM_RXF_MCTRL	0x031c	/* 32 bit r/o	Rx MAC Ctrl Frame Counter */
-#define XM_RXF_INV_MP	0x0320	/* 32 bit r/o	Rx invalid Pause Frame Cnt */
-#define XM_RXF_INV_MOC	0x0324	/* 32 bit r/o	Rx Frames with inv. MAC Opcode*/
-#define XM_RXE_BURST	0x0328	/* 32 bit r/o	Rx Burst Event Counter */
-#define XM_RXE_FMISS	0x032c	/* 32 bit r/o	Rx Missed Frames Event Cnt */
-#define XM_RXF_FRA_ERR	0x0330	/* 32 bit r/o	Rx Framing Error Counter */
-#define XM_RXE_FIFO_OV	0x0334	/* 32 bit r/o	Rx FIFO overflow Event Cnt */
-#define XM_RXF_JAB_PKT	0x0338	/* 32 bit r/o	Rx Jabber Packet Frame Cnt */
-#define XM_RXE_CAR_ERR	0x033c	/* 32 bit r/o	Rx Carrier Event Error Cnt */
-#define XM_RXF_LEN_ERR	0x0340	/* 32 bit r/o	Rx in Range Length Error */
-#define XM_RXE_SYM_ERR	0x0344	/* 32 bit r/o	Rx Symbol Error Counter */
-#define XM_RXE_SHT_ERR	0x0348	/* 32 bit r/o	Rx Short Event Error Cnt */
-#define XM_RXE_RUNT		0x034c	/* 32 bit r/o	Rx Runt Event Counter */
-#define XM_RXF_LNG_ERR	0x0350	/* 32 bit r/o	Rx Frame too Long Error Cnt */
-#define XM_RXF_FCS_ERR	0x0354	/* 32 bit r/o	Rx Frame Check Seq. Error Cnt */
-	/* 0x0358 - 0x035a:	reserved */
-#define XM_RXF_CEX_ERR	0x035c	/* 32 bit r/o	Rx Carrier Ext Error Frame Cnt*/
-#define XM_RXP_UTIL		0x0360	/* 32 bit r/o	Rx Utilization in % */
-	/* 0x0364 - 0x0366:	reserved */
-#define XM_RXF_64B		0x0368	/* 32 bit r/o	64 Byte Rx Frame Counter */
-#define XM_RXF_127B		0x036c	/* 32 bit r/o	65-127 Byte Rx Frame Counter */
-#define XM_RXF_255B		0x0370	/* 32 bit r/o	128-255 Byte Rx Frame Counter */
-#define XM_RXF_511B		0x0374	/* 32 bit r/o	256-511 Byte Rx Frame Counter */
-#define XM_RXF_1023B	0x0378	/* 32 bit r/o	512-1023 Byte Rx Frame Counter*/
-#define XM_RXF_MAX_SZ	0x037c	/* 32 bit r/o	1024-MaxSize Byte Rx Frame Cnt*/
-	/* 0x02e8 - 0x02fe:	reserved */
-
-
-/*----------------------------------------------------------------------------*/
-/*
- * XMAC Bit Definitions
- *
- * If the bit access behaviour differs from the register access behaviour
- * (r/w, r/o) this is documented after the bit number.
- * The following bit access behaviours are used:
- *	(sc)	self clearing
- *	(ro)	read only
- */
-
-/*	XM_MMU_CMD	16 bit r/w	MMU Command Register */
-								/* Bit 15..13:	reserved */
-#define XM_MMU_PHY_RDY	(1<<12)	/* Bit 12:	PHY Read Ready */
-#define XM_MMU_PHY_BUSY	(1<<11)	/* Bit 11:	PHY Busy */
-#define XM_MMU_IGN_PF	(1<<10)	/* Bit 10:	Ignore Pause Frame */
-#define XM_MMU_MAC_LB	(1<<9)	/* Bit  9:	Enable MAC Loopback */
-								/* Bit  8:	reserved */
-#define XM_MMU_FRC_COL	(1<<7)	/* Bit  7:	Force Collision */
-#define XM_MMU_SIM_COL	(1<<6)	/* Bit  6:	Simulate Collision */
-#define XM_MMU_NO_PRE	(1<<5)	/* Bit  5:	No MDIO Preamble */
-#define XM_MMU_GMII_FD	(1<<4)	/* Bit  4:	GMII uses Full Duplex */
-#define XM_MMU_RAT_CTRL	(1<<3)	/* Bit  3:	Enable Rate Control */
-#define XM_MMU_GMII_LOOP (1<<2)	/* Bit  2:	PHY is in Loopback Mode */
-#define XM_MMU_ENA_RX	(1<<1)	/* Bit  1:	Enable Receiver */
-#define XM_MMU_ENA_TX	(1<<0)	/* Bit  0:	Enable Transmitter */
-
-
-/*	XM_TX_CMD	16 bit r/w	Transmit Command Register */
-								/* Bit 15..7:	reserved */
-#define XM_TX_BK2BK		(1<<6)	/* Bit  6:	Ignor Carrier Sense (Tx Bk2Bk)*/
-#define XM_TX_ENC_BYP	(1<<5)	/* Bit  5:	Set Encoder in Bypass Mode */
-#define XM_TX_SAM_LINE	(1<<4)	/* Bit  4: (sc)	Start utilization calculation */
-#define XM_TX_NO_GIG_MD	(1<<3)	/* Bit  3:	Disable Carrier Extension */
-#define XM_TX_NO_PRE	(1<<2)	/* Bit  2:	Disable Preamble Generation */
-#define XM_TX_NO_CRC	(1<<1)	/* Bit  1:	Disable CRC Generation */
-#define XM_TX_AUTO_PAD	(1<<0)	/* Bit  0:	Enable Automatic Padding */
-
-
-/*	XM_TX_RT_LIM	16 bit r/w	Transmit Retry Limit Register */
-								/* Bit 15..5:	reserved */
-#define XM_RT_LIM_MSK	0x1f	/* Bit  4..0:	Tx Retry Limit */
-
-
-/*	XM_TX_STIME	16 bit r/w	Transmit Slottime Register */
-								/* Bit 15..7:	reserved */
-#define XM_STIME_MSK	0x7f	/* Bit  6..0:	Tx Slottime bits */
-
-
-/*	XM_TX_IPG	16 bit r/w	Transmit Inter Packet Gap */
-								/* Bit 15..8:	reserved */
-#define XM_IPG_MSK		0xff	/* Bit  7..0:	IPG value bits */
-
-
-/*	XM_RX_CMD	16 bit r/w	Receive Command Register */
-								/* Bit 15..9:	reserved */
-#define XM_RX_LENERR_OK (1<<8)	/* Bit  8	don't set Rx Err bit for */
-								/*		inrange error packets */
-#define XM_RX_BIG_PK_OK	(1<<7)	/* Bit  7	don't set Rx Err bit for */
-								/*		jumbo packets */
-#define XM_RX_IPG_CAP	(1<<6)	/* Bit  6	repl. type field with IPG */
-#define XM_RX_TP_MD		(1<<5)	/* Bit  5:	Enable transparent Mode */
-#define XM_RX_STRIP_FCS	(1<<4)	/* Bit  4:	Enable FCS Stripping */
-#define XM_RX_SELF_RX	(1<<3)	/* Bit  3: 	Enable Rx of own packets */
-#define XM_RX_SAM_LINE	(1<<2)	/* Bit  2: (sc)	Start utilization calculation */
-#define XM_RX_STRIP_PAD	(1<<1)	/* Bit  1:	Strip pad bytes of Rx frames */
-#define XM_RX_DIS_CEXT	(1<<0)	/* Bit  0:	Disable carrier ext. check */
-
-
-/*	XM_PHY_ADDR	16 bit r/w	PHY Address Register */
-								/* Bit 15..5:	reserved */
-#define XM_PHY_ADDR_SZ	0x1f	/* Bit  4..0:	PHY Address bits */
-
-
-/*	XM_GP_PORT	32 bit r/w	General Purpose Port Register */
-								/* Bit 31..7:	reserved */
-#define XM_GP_ANIP		(1L<<6)	/* Bit  6: (ro)	Auto-Neg. in progress */
-#define XM_GP_FRC_INT	(1L<<5)	/* Bit  5: (sc)	Force Interrupt */
-								/* Bit  4:	reserved */
-#define XM_GP_RES_MAC	(1L<<3)	/* Bit  3: (sc)	Reset MAC and FIFOs */
-#define XM_GP_RES_STAT	(1L<<2)	/* Bit  2: (sc)	Reset the statistics module */
-								/* Bit  1:	reserved */
-#define XM_GP_INP_ASS	(1L<<0)	/* Bit  0: (ro) GP Input Pin asserted */
-
-
-/*	XM_IMSK		16 bit r/w	Interrupt Mask Register */
-/*	XM_ISRC		16 bit r/o	Interrupt Status Register */
-								/* Bit 15:	reserved */
-#define XM_IS_LNK_AE	(1<<14) /* Bit 14:	Link Asynchronous Event */
-#define XM_IS_TX_ABORT	(1<<13) /* Bit 13:	Transmit Abort, late Col. etc */
-#define XM_IS_FRC_INT	(1<<12) /* Bit 12:	Force INT bit set in GP */
-#define XM_IS_INP_ASS	(1<<11)	/* Bit 11:	Input Asserted, GP bit 0 set */
-#define XM_IS_LIPA_RC	(1<<10)	/* Bit 10:	Link Partner requests config */
-#define XM_IS_RX_PAGE	(1<<9)	/* Bit  9:	Page Received */
-#define XM_IS_TX_PAGE	(1<<8)	/* Bit  8:	Next Page Loaded for Transmit */
-#define XM_IS_AND		(1<<7)	/* Bit  7:	Auto-Negotiation Done */
-#define XM_IS_TSC_OV	(1<<6)	/* Bit  6:	Time Stamp Counter Overflow */
-#define XM_IS_RXC_OV	(1<<5)	/* Bit  5:	Rx Counter Event Overflow */
-#define XM_IS_TXC_OV	(1<<4)	/* Bit  4:	Tx Counter Event Overflow */
-#define XM_IS_RXF_OV	(1<<3)	/* Bit  3:	Receive FIFO Overflow */
-#define XM_IS_TXF_UR	(1<<2)	/* Bit  2:	Transmit FIFO Underrun */
-#define XM_IS_TX_COMP	(1<<1)	/* Bit  1:	Frame Tx Complete */
-#define XM_IS_RX_COMP	(1<<0)	/* Bit  0:	Frame Rx Complete */
-
-#define XM_DEF_MSK	(~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\
-			XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR))
-
-
-/*	XM_HW_CFG	16 bit r/w	Hardware Config Register */
-								/* Bit 15.. 4:	reserved */
-#define XM_HW_GEN_EOP	(1<<3)	/* Bit  3:	generate End of Packet pulse */
-#define XM_HW_COM4SIG	(1<<2)	/* Bit  2:	use Comma Detect for Sig. Det.*/
-								/* Bit  1:	reserved */
-#define XM_HW_GMII_MD	(1<<0)	/* Bit  0:	GMII Interface selected */
-
-
-/*	XM_TX_LO_WM	16 bit r/w	Tx FIFO Low Water Mark */
-/*	XM_TX_HI_WM	16 bit r/w	Tx FIFO High Water Mark */
-								/* Bit 15..10	reserved */
-#define XM_TX_WM_MSK	0x01ff	/* Bit  9.. 0	Tx FIFO Watermark bits */
-
-/*	XM_TX_THR	16 bit r/w	Tx Request Threshold */
-/*	XM_HT_THR	16 bit r/w	Host Request Threshold */
-/*	XM_RX_THR	16 bit r/w	Rx Request Threshold */
-								/* Bit 15..11	reserved */
-#define XM_THR_MSK		0x03ff	/* Bit 10.. 0	Rx/Tx Request Threshold bits */
-
-
-/*	XM_TX_STAT	32 bit r/o	Tx Status LIFO Register */
-#define XM_ST_VALID		(1UL<<31)	/* Bit 31:	Status Valid */
-#define XM_ST_BYTE_CNT	(0x3fffL<<17)	/* Bit 30..17:	Tx frame Length */
-#define XM_ST_RETRY_CNT	(0x1fL<<12)	/* Bit 16..12:	Retry Count */
-#define XM_ST_EX_COL	(1L<<11)	/* Bit 11:	Excessive Collisions */
-#define XM_ST_EX_DEF	(1L<<10)	/* Bit 10:	Excessive Deferral */
-#define XM_ST_BURST		(1L<<9)		/* Bit  9:	p. xmitted in burst md*/
-#define XM_ST_DEFER		(1L<<8)		/* Bit  8:	packet was defered */
-#define XM_ST_BC		(1L<<7)		/* Bit  7:	Broadcast packet */
-#define XM_ST_MC		(1L<<6)		/* Bit  6:	Multicast packet */
-#define XM_ST_UC		(1L<<5)		/* Bit  5:	Unicast packet */
-#define XM_ST_TX_UR		(1L<<4)		/* Bit  4:	FIFO Underrun occured */
-#define XM_ST_CS_ERR	(1L<<3)		/* Bit  3:	Carrier Sense Error */
-#define XM_ST_LAT_COL	(1L<<2)		/* Bit  2:	Late Collision Error */
-#define XM_ST_MUL_COL	(1L<<1)		/* Bit  1:	Multiple Collisions */
-#define XM_ST_SGN_COL	(1L<<0)		/* Bit  0:	Single Collision */
-
-/*	XM_RX_LO_WM	16 bit r/w	Receive Low Water Mark */
-/*	XM_RX_HI_WM	16 bit r/w	Receive High Water Mark */
-									/* Bit 15..11:	reserved */
-#define XM_RX_WM_MSK	0x03ff		/* Bit 11.. 0:	Rx FIFO Watermark bits */
-
-
-/*	XM_DEV_ID	32 bit r/o	Device ID Register */
-#define XM_DEV_OUI	(0x00ffffffUL<<8)	/* Bit 31..8:	Device OUI */
-#define XM_DEV_REV	(0x07L << 5)		/* Bit  7..5:	Chip Rev Num */
-
-
-/*	XM_MODE		32 bit r/w	Mode Register */
-									/* Bit 31..27:	reserved */
-#define XM_MD_ENA_REJ	(1L<<26)	/* Bit 26:	Enable Frame Reject */
-#define XM_MD_SPOE_E	(1L<<25)	/* Bit 25:	Send Pause on Edge */
-									/* 		extern generated */
-#define XM_MD_TX_REP	(1L<<24)	/* Bit 24:	Transmit Repeater Mode */
-#define XM_MD_SPOFF_I	(1L<<23)	/* Bit 23:	Send Pause on FIFO full */
-									/*		intern generated */
-#define XM_MD_LE_STW	(1L<<22)	/* Bit 22:	Rx Stat Word in Little Endian */
-#define XM_MD_TX_CONT	(1L<<21)	/* Bit 21:	Send Continuous */
-#define XM_MD_TX_PAUSE	(1L<<20)	/* Bit 20: (sc)	Send Pause Frame */
-#define XM_MD_ATS		(1L<<19)	/* Bit 19:	Append Time Stamp */
-#define XM_MD_SPOL_I	(1L<<18)	/* Bit 18:	Send Pause on Low */
-									/*		intern generated */
-#define XM_MD_SPOH_I	(1L<<17)	/* Bit 17:	Send Pause on High */
-									/*		intern generated */
-#define XM_MD_CAP		(1L<<16)	/* Bit 16:	Check Address Pair */
-#define XM_MD_ENA_HASH	(1L<<15)	/* Bit 15:	Enable Hashing */
-#define XM_MD_CSA		(1L<<14)	/* Bit 14:	Check Station Address */
-#define XM_MD_CAA		(1L<<13)	/* Bit 13:	Check Address Array */
-#define XM_MD_RX_MCTRL	(1L<<12)	/* Bit 12:	Rx MAC Control Frame */
-#define XM_MD_RX_RUNT	(1L<<11)	/* Bit 11:	Rx Runt Frames */
-#define XM_MD_RX_IRLE	(1L<<10)	/* Bit 10:	Rx in Range Len Err Frame */
-#define XM_MD_RX_LONG	(1L<<9)		/* Bit  9:	Rx Long Frame */
-#define XM_MD_RX_CRCE	(1L<<8)		/* Bit  8:	Rx CRC Error Frame */
-#define XM_MD_RX_ERR	(1L<<7)		/* Bit  7:	Rx Error Frame */
-#define XM_MD_DIS_UC	(1L<<6)		/* Bit  6:	Disable Rx Unicast */
-#define XM_MD_DIS_MC	(1L<<5)		/* Bit  5:	Disable Rx Multicast */
-#define XM_MD_DIS_BC	(1L<<4)		/* Bit  4:	Disable Rx Broadcast */
-#define XM_MD_ENA_PROM	(1L<<3)		/* Bit  3:	Enable Promiscuous */
-#define XM_MD_ENA_BE	(1L<<2)		/* Bit  2:	Enable Big Endian */
-#define XM_MD_FTF		(1L<<1)		/* Bit  1: (sc)	Flush Tx FIFO */
-#define XM_MD_FRF		(1L<<0)		/* Bit  0: (sc)	Flush Rx FIFO */
-
-#define XM_PAUSE_MODE	(XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
-#define XM_DEF_MODE		(XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
-				XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA)
-
-/*	XM_STAT_CMD	16 bit r/w	Statistics Command Register */
-								/* Bit 16..6:	reserved */
-#define XM_SC_SNP_RXC	(1<<5)	/* Bit  5: (sc)	Snap Rx Counters */
-#define XM_SC_SNP_TXC	(1<<4)	/* Bit  4: (sc)	Snap Tx Counters */
-#define XM_SC_CP_RXC	(1<<3)	/* Bit  3: 	Copy Rx Counters Continuously */
-#define XM_SC_CP_TXC	(1<<2)	/* Bit  2:	Copy Tx Counters Continuously */
-#define XM_SC_CLR_RXC	(1<<1)	/* Bit  1: (sc)	Clear Rx Counters */
-#define XM_SC_CLR_TXC	(1<<0)	/* Bit  0: (sc) Clear Tx Counters */
-
-
-/*	XM_RX_CNT_EV	32 bit r/o	Rx Counter Event Register */
-/*	XM_RX_EV_MSK	32 bit r/w	Rx Counter Event Mask */
-#define XMR_MAX_SZ_OV	(1UL<<31)	/* Bit 31:	1024-MaxSize Rx Cnt Ov*/
-#define XMR_1023B_OV	(1L<<30)	/* Bit 30:	512-1023Byte Rx Cnt Ov*/
-#define XMR_511B_OV		(1L<<29)	/* Bit 29:	256-511 Byte Rx Cnt Ov*/
-#define XMR_255B_OV		(1L<<28)	/* Bit 28:	128-255 Byte Rx Cnt Ov*/
-#define XMR_127B_OV		(1L<<27)	/* Bit 27:	65-127 Byte Rx Cnt Ov */
-#define XMR_64B_OV		(1L<<26)	/* Bit 26:	64 Byte Rx Cnt Ov */
-#define XMR_UTIL_OV		(1L<<25)	/* Bit 25:	Rx Util Cnt Overflow */
-#define XMR_UTIL_UR		(1L<<24)	/* Bit 24:	Rx Util Cnt Underrun */
-#define XMR_CEX_ERR_OV	(1L<<23)	/* Bit 23:	CEXT Err Cnt Ov */
-									/* Bit 22:	reserved */
-#define XMR_FCS_ERR_OV	(1L<<21)	/* Bit 21:	Rx FCS Error Cnt Ov */
-#define XMR_LNG_ERR_OV	(1L<<20)	/* Bit 20:	Rx too Long Err Cnt Ov*/
-#define XMR_RUNT_OV		(1L<<19)	/* Bit 19:	Runt Event Cnt Ov */
-#define XMR_SHT_ERR_OV	(1L<<18)	/* Bit 18:	Rx Short Ev Err Cnt Ov*/
-#define XMR_SYM_ERR_OV	(1L<<17)	/* Bit 17:	Rx Sym Err Cnt Ov */
-									/* Bit 16:	reserved */
-#define XMR_CAR_ERR_OV	(1L<<15)	/* Bit 15:	Rx Carr Ev Err Cnt Ov */
-#define XMR_JAB_PKT_OV	(1L<<14)	/* Bit 14:	Rx Jabb Packet Cnt Ov */
-#define XMR_FIFO_OV		(1L<<13)	/* Bit 13:	Rx FIFO Ov Ev Cnt Ov */
-#define XMR_FRA_ERR_OV	(1L<<12)	/* Bit 12:	Rx Framing Err Cnt Ov */
-#define XMR_FMISS_OV	(1L<<11)	/* Bit 11:	Rx Missed Ev Cnt Ov */
-#define XMR_BURST		(1L<<10)	/* Bit 10:	Rx Burst Event Cnt Ov */
-#define XMR_INV_MOC		(1L<<9)		/* Bit  9:	Rx with inv. MAC OC Ov*/
-#define XMR_INV_MP		(1L<<8)		/* Bit  8:	Rx inv Pause Frame Ov */
-#define XMR_MCTRL_OV	(1L<<7)		/* Bit  7:	Rx MAC Ctrl-F Cnt Ov */
-#define XMR_MPAUSE_OV	(1L<<6)		/* Bit  6:	Rx Pause MAC Ctrl-F Ov*/
-#define XMR_UC_OK_OV	(1L<<5)		/* Bit  5:	Rx Unicast Frame CntOv*/
-#define XMR_MC_OK_OV	(1L<<4)		/* Bit  4:	Rx Multicast Cnt Ov */
-#define XMR_BC_OK_OV	(1L<<3)		/* Bit  3:	Rx Broadcast Cnt Ov */
-#define XMR_OK_LO_OV	(1L<<2)		/* Bit  2:	Octets Rx OK Low CntOv*/
-#define XMR_OK_HI_OV	(1L<<1)		/* Bit  1:	Octets Rx OK Hi Cnt Ov*/
-#define XMR_OK_OV		(1L<<0)		/* Bit  0:	Frames Received Ok Ov */
-
-#define XMR_DEF_MSK		(XMR_OK_LO_OV | XMR_OK_HI_OV)
-
-/*	XM_TX_CNT_EV	32 bit r/o	Tx Counter Event Register */
-/*	XM_TX_EV_MSK	32 bit r/w	Tx Counter Event Mask */
-									/* Bit 31..26:	reserved */
-#define XMT_MAX_SZ_OV	(1L<<25)	/* Bit 25:	1024-MaxSize Tx Cnt Ov*/
-#define XMT_1023B_OV	(1L<<24)	/* Bit 24:	512-1023Byte Tx Cnt Ov*/
-#define XMT_511B_OV		(1L<<23)	/* Bit 23:	256-511 Byte Tx Cnt Ov*/
-#define XMT_255B_OV		(1L<<22)	/* Bit 22:	128-255 Byte Tx Cnt Ov*/
-#define XMT_127B_OV		(1L<<21)	/* Bit 21:	65-127 Byte Tx Cnt Ov */
-#define XMT_64B_OV		(1L<<20)	/* Bit 20:	64 Byte Tx Cnt Ov */
-#define XMT_UTIL_OV		(1L<<19)	/* Bit 19:	Tx Util Cnt Overflow */
-#define XMT_UTIL_UR		(1L<<18)	/* Bit 18:	Tx Util Cnt Underrun */
-#define XMT_CS_ERR_OV	(1L<<17)	/* Bit 17:	Tx Carr Sen Err Cnt Ov*/
-#define XMT_FIFO_UR_OV	(1L<<16)	/* Bit 16:	Tx FIFO Ur Ev Cnt Ov */
-#define XMT_EX_DEF_OV	(1L<<15)	/* Bit 15:	Tx Ex Deferall Cnt Ov */
-#define XMT_DEF			(1L<<14)	/* Bit 14:	Tx Deferred Cnt Ov */
-#define XMT_LAT_COL_OV	(1L<<13)	/* Bit 13:	Tx Late Col Cnt Ov */
-#define XMT_ABO_COL_OV	(1L<<12)	/* Bit 12:	Tx abo dueto Ex Col Ov*/
-#define XMT_MUL_COL_OV	(1L<<11)	/* Bit 11:	Tx Mult Col Cnt Ov */
-#define XMT_SNG_COL		(1L<<10)	/* Bit 10:	Tx Single Col Cnt Ov */
-#define XMT_MCTRL_OV	(1L<<9)		/* Bit  9:	Tx MAC Ctrl Counter Ov*/
-#define XMT_MPAUSE		(1L<<8)		/* Bit  8:	Tx Pause MAC Ctrl-F Ov*/
-#define XMT_BURST		(1L<<7)		/* Bit  7:	Tx Burst Event Cnt Ov */
-#define XMT_LONG		(1L<<6)		/* Bit  6:	Tx Long Frame Cnt Ov */
-#define XMT_UC_OK_OV	(1L<<5)		/* Bit  5:	Tx Unicast Cnt Ov */
-#define XMT_MC_OK_OV	(1L<<4)		/* Bit  4:	Tx Multicast Cnt Ov */
-#define XMT_BC_OK_OV	(1L<<3)		/* Bit  3:	Tx Broadcast Cnt Ov */
-#define XMT_OK_LO_OV	(1L<<2)		/* Bit  2:	Octets Tx OK Low CntOv*/
-#define XMT_OK_HI_OV	(1L<<1)		/* Bit  1:	Octets Tx OK Hi Cnt Ov*/
-#define XMT_OK_OV		(1L<<0)		/* Bit  0:	Frames Tx Ok Ov */
-
-#define XMT_DEF_MSK		(XMT_OK_LO_OV | XMT_OK_HI_OV)
-
-/*
- * Receive Frame Status Encoding
- */
-#define XMR_FS_LEN	(0x3fffUL<<18)	/* Bit 31..18:	Rx Frame Length */
-#define XMR_FS_2L_VLAN	(1L<<17)	/* Bit 17:	tagged wh 2Lev VLAN ID*/
-#define XMR_FS_1L_VLAN	(1L<<16)	/* Bit 16:	tagged wh 1Lev VLAN ID*/
-#define XMR_FS_BC		(1L<<15)	/* Bit 15:	Broadcast Frame */
-#define XMR_FS_MC		(1L<<14)	/* Bit 14:	Multicast Frame */
-#define XMR_FS_UC		(1L<<13)	/* Bit 13:	Unicast Frame */
-									/* Bit 12:	reserved */
-#define XMR_FS_BURST	(1L<<11)	/* Bit 11:	Burst Mode */
-#define XMR_FS_CEX_ERR	(1L<<10)	/* Bit 10:	Carrier Ext. Error */
-#define XMR_FS_802_3	(1L<<9)		/* Bit  9:	802.3 Frame */
-#define XMR_FS_COL_ERR	(1L<<8)		/* Bit  8:	Collision Error */
-#define XMR_FS_CAR_ERR	(1L<<7)		/* Bit  7:	Carrier Event Error */
-#define XMR_FS_LEN_ERR	(1L<<6)		/* Bit  6:	In-Range Length Error */
-#define XMR_FS_FRA_ERR	(1L<<5)		/* Bit  5:	Framing Error */
-#define XMR_FS_RUNT		(1L<<4)		/* Bit  4:	Runt Frame */
-#define XMR_FS_LNG_ERR	(1L<<3)		/* Bit  3:	Giant (Jumbo) Frame */
-#define XMR_FS_FCS_ERR	(1L<<2)		/* Bit  2:	Frame Check Sequ Err */
-#define XMR_FS_ERR		(1L<<1)		/* Bit  1:	Frame Error */
-#define XMR_FS_MCTRL	(1L<<0)		/* Bit  0:	MAC Control Packet */
-
-/*
- * XMR_FS_ERR will be set if
- *	XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
- *	XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR
- * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue
- * XMR_FS_ERR unless the corresponding bit in the Receive Command
- * Register is set.
- */
-#define XMR_FS_ANY_ERR	XMR_FS_ERR
-
-/*----------------------------------------------------------------------------*/
-/*
- * XMAC-PHY Registers, indirect addressed over the XMAC
- */
-#define PHY_XMAC_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_XMAC_STAT		0x01	/* 16 bit r/w	PHY Status Register */
-#define PHY_XMAC_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_XMAC_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_XMAC_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_XMAC_AUNE_LP	0x05	/* 16 bit r/o	Link Partner Abi Reg */
-#define PHY_XMAC_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_XMAC_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_XMAC_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* 0x09 - 0x0e:		reserved */
-#define PHY_XMAC_EXT_STAT	0x0f	/* 16 bit r/o	Ext Status Register */
-#define PHY_XMAC_RES_ABI	0x10	/* 16 bit r/o	PHY Resolved Ability */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Broadcom-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_BCOM_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_BCOM_STAT		0x01	/* 16 bit r/o	PHY Status Register */
-#define PHY_BCOM_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_BCOM_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_BCOM_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_BCOM_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
-#define PHY_BCOM_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_BCOM_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_BCOM_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* Broadcom-specific registers */
-#define PHY_BCOM_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Ctrl Reg */
-#define PHY_BCOM_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b - 0x0e:		reserved */
-#define PHY_BCOM_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
-#define PHY_BCOM_P_EXT_CTRL	0x10	/* 16 bit r/w	PHY Extended Ctrl Reg */
-#define PHY_BCOM_P_EXT_STAT	0x11	/* 16 bit r/o	PHY Extended Stat Reg */
-#define PHY_BCOM_RE_CTR		0x12	/* 16 bit r/w	Receive Error Counter */
-#define PHY_BCOM_FC_CTR		0x13	/* 16 bit r/w	False Carrier Sense Cnt */
-#define PHY_BCOM_RNO_CTR	0x14	/* 16 bit r/w	Receiver NOT_OK Cnt */
-	/* 0x15 - 0x17:		reserved */
-#define PHY_BCOM_AUX_CTRL	0x18	/* 16 bit r/w	Auxiliary Control Reg */
-#define PHY_BCOM_AUX_STAT	0x19	/* 16 bit r/o	Auxiliary Stat Summary */
-#define PHY_BCOM_INT_STAT	0x1a	/* 16 bit r/o	Interrupt Status Reg */
-#define PHY_BCOM_INT_MASK	0x1b	/* 16 bit r/w	Interrupt Mask Reg */
-	/* 0x1c:		reserved */
-	/* 0x1d - 0x1f:		test registers */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Marvel-PHY Registers, indirect addressed over GMAC
- */
-#define PHY_MARV_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_MARV_STAT		0x01	/* 16 bit r/o	PHY Status Register */
-#define PHY_MARV_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_MARV_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_MARV_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_MARV_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
-#define PHY_MARV_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_MARV_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_MARV_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* Marvel-specific registers */
-#define PHY_MARV_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Ctrl Reg */
-#define PHY_MARV_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b - 0x0e:		reserved */
-#define PHY_MARV_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
-#define PHY_MARV_PHY_CTRL	0x10	/* 16 bit r/w	PHY Specific Ctrl Reg */
-#define PHY_MARV_PHY_STAT	0x11	/* 16 bit r/o	PHY Specific Stat Reg */
-#define PHY_MARV_INT_MASK	0x12	/* 16 bit r/w	Interrupt Mask Reg */
-#define PHY_MARV_INT_STAT	0x13	/* 16 bit r/o	Interrupt Status Reg */
-#define PHY_MARV_EXT_CTRL	0x14	/* 16 bit r/w	Ext. PHY Specific Ctrl */
-#define PHY_MARV_RXE_CNT	0x15	/* 16 bit r/w	Receive Error Counter */
-#define PHY_MARV_EXT_ADR	0x16	/* 16 bit r/w	Ext. Ad. for Cable Diag. */
-	/* 0x17:		reserved */
-#define PHY_MARV_LED_CTRL	0x18	/* 16 bit r/w	LED Control Reg */
-#define PHY_MARV_LED_OVER	0x19	/* 16 bit r/w	Manual LED Override Reg */
-#define PHY_MARV_EXT_CTRL_2	0x1a	/* 16 bit r/w	Ext. PHY Specific Ctrl 2 */
-#define PHY_MARV_EXT_P_STAT	0x1b	/* 16 bit r/w	Ext. PHY Spec. Stat Reg */
-#define PHY_MARV_CABLE_DIAG	0x1c	/* 16 bit r/o	Cable Diagnostic Reg */
-	/* 0x1d - 0x1f:		reserved */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Level One-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_LONE_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_LONE_STAT		0x01	/* 16 bit r/o	PHY Status Register */
-#define PHY_LONE_ID0		0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_LONE_ID1		0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_LONE_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_LONE_AUNE_LP	0x05	/* 16 bit r/o	Link Part Ability Reg */
-#define PHY_LONE_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_LONE_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_LONE_NEPG_LP	0x08	/* 16 bit r/o	Next Page Link Partner */
-	/* Level One-specific registers */
-#define PHY_LONE_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg*/
-#define PHY_LONE_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b -0x0e:		reserved */
-#define PHY_LONE_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Reg */
-#define PHY_LONE_PORT_CFG	0x10	/* 16 bit r/w	Port Configuration Reg*/
-#define PHY_LONE_Q_STAT		0x11	/* 16 bit r/o	Quick Status Reg */
-#define PHY_LONE_INT_ENAB	0x12	/* 16 bit r/w	Interrupt Enable Reg */
-#define PHY_LONE_INT_STAT	0x13	/* 16 bit r/o	Interrupt Status Reg */
-#define PHY_LONE_LED_CFG	0x14	/* 16 bit r/w	LED Configuration Reg */
-#define PHY_LONE_PORT_CTRL	0x15	/* 16 bit r/w	Port Control Reg */
-#define PHY_LONE_CIM		0x16	/* 16 bit r/o	CIM Reg */
-	/* 0x17 -0x1c:		reserved */
-
-/*----------------------------------------------------------------------------*/
-/*
- * National-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_NAT_CTRL		0x00	/* 16 bit r/w	PHY Control Register */
-#define PHY_NAT_STAT		0x01	/* 16 bit r/w	PHY Status Register */
-#define PHY_NAT_ID0			0x02	/* 16 bit r/o	PHY ID0 Register */
-#define PHY_NAT_ID1			0x03	/* 16 bit r/o	PHY ID1 Register */
-#define PHY_NAT_AUNE_ADV	0x04	/* 16 bit r/w	Auto-Neg. Advertisement */
-#define PHY_NAT_AUNE_LP		0x05	/* 16 bit r/o	Link Partner Ability Reg */
-#define PHY_NAT_AUNE_EXP	0x06	/* 16 bit r/o	Auto-Neg. Expansion Reg */
-#define PHY_NAT_NEPG		0x07	/* 16 bit r/w	Next Page Register */
-#define PHY_NAT_NEPG_LP		0x08	/* 16 bit r/o	Next Page Link Partner Reg */
-	/* National-specific registers */
-#define PHY_NAT_1000T_CTRL	0x09	/* 16 bit r/w	1000Base-T Control Reg */
-#define PHY_NAT_1000T_STAT	0x0a	/* 16 bit r/o	1000Base-T Status Reg */
-	/* 0x0b -0x0e:		reserved */
-#define PHY_NAT_EXT_STAT	0x0f	/* 16 bit r/o	Extended Status Register */
-#define PHY_NAT_EXT_CTRL1	0x10	/* 16 bit r/o	Extended Control Reg1 */
-#define PHY_NAT_Q_STAT1		0x11	/* 16 bit r/o	Quick Status Reg1 */
-#define PHY_NAT_10B_OP		0x12	/* 16 bit r/o	10Base-T Operations Reg */
-#define PHY_NAT_EXT_CTRL2	0x13	/* 16 bit r/o	Extended Control Reg1 */
-#define PHY_NAT_Q_STAT2		0x14	/* 16 bit r/o	Quick Status Reg2 */
-	/* 0x15 -0x18:		reserved */
-#define PHY_NAT_PHY_ADDR	0x19	/* 16 bit r/o	PHY Address Register */
-
-
-/*----------------------------------------------------------------------------*/
-
-/*
- * PHY bit definitions
- * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are
- * XMAC/Broadcom/LevelOne/National/Marvell-specific.
- * All other are general.
- */
-
-/*****  PHY_XMAC_CTRL	16 bit r/w	PHY Control Register *****/
-/*****  PHY_BCOM_CTRL	16 bit r/w	PHY Control Register *****/
-/*****  PHY_MARV_CTRL	16 bit r/w	PHY Status Register *****/
-/*****  PHY_LONE_CTRL	16 bit r/w	PHY Control Register *****/
-#define PHY_CT_RESET	(1<<15)	/* Bit 15: (sc)	clear all PHY related regs */
-#define PHY_CT_LOOP		(1<<14)	/* Bit 14:	enable Loopback over PHY */
-#define PHY_CT_SPS_LSB	(1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */
-#define PHY_CT_ANE		(1<<12)	/* Bit 12:	Auto-Negotiation Enabled */
-#define PHY_CT_PDOWN	(1<<11)	/* Bit 11: (BC,L1) Power Down Mode */
-#define PHY_CT_ISOL		(1<<10)	/* Bit 10: (BC,L1) Isolate Mode */
-#define PHY_CT_RE_CFG	(1<<9)	/* Bit  9: (sc) Restart Auto-Negotiation */
-#define PHY_CT_DUP_MD	(1<<8)	/* Bit  8:	Duplex Mode */
-#define PHY_CT_COL_TST	(1<<7)	/* Bit  7: (BC,L1) Collision Test enabled */
-#define PHY_CT_SPS_MSB	(1<<6)	/* Bit  6: (BC,L1) Speed select, upper bit */
-								/* Bit  5..0:	reserved */
-
-#define PHY_CT_SP1000	PHY_CT_SPS_MSB	/* enable speed of 1000 Mbps */
-#define PHY_CT_SP100	PHY_CT_SPS_LSB	/* enable speed of  100 Mbps */
-#define PHY_CT_SP10		(0)				/* enable speed of   10 Mbps */
-
-
-/*****  PHY_XMAC_STAT	16 bit r/w	PHY Status Register *****/
-/*****  PHY_BCOM_STAT	16 bit r/w	PHY Status Register *****/
-/*****  PHY_MARV_STAT	16 bit r/w	PHY Status Register *****/
-/*****  PHY_LONE_STAT	16 bit r/w	PHY Status Register *****/
-								/* Bit 15..9:	reserved */
-				/*	(BC/L1) 100/10 Mbps cap bits ignored*/
-#define PHY_ST_EXT_ST	(1<<8)	/* Bit  8:	Extended Status Present */
-								/* Bit  7:	reserved */
-#define PHY_ST_PRE_SUP	(1<<6)	/* Bit  6: (BC/L1) preamble suppression */
-#define PHY_ST_AN_OVER	(1<<5)	/* Bit  5:	Auto-Negotiation Over */
-#define PHY_ST_REM_FLT	(1<<4)	/* Bit  4:	Remote Fault Condition Occured */
-#define PHY_ST_AN_CAP	(1<<3)	/* Bit  3:	Auto-Negotiation Capability */
-#define PHY_ST_LSYNC	(1<<2)	/* Bit  2:	Link Synchronized */
-#define PHY_ST_JAB_DET	(1<<1)	/* Bit  1: (BC/L1) Jabber Detected */
-#define PHY_ST_EXT_REG	(1<<0)	/* Bit  0:	Extended Register available */
-
-
-/*****	PHY_XMAC_ID1		16 bit r/o	PHY ID1 Register */
-/*****	PHY_BCOM_ID1		16 bit r/o	PHY ID1 Register */
-/*****	PHY_MARV_ID1		16 bit r/o	PHY ID1 Register */
-/*****	PHY_LONE_ID1		16 bit r/o	PHY ID1 Register */
-#define PHY_I1_OUI_MSK	(0x3f<<10)	/* Bit 15..10:	Organization Unique ID */
-#define PHY_I1_MOD_NUM	(0x3f<<4)	/* Bit  9.. 4:	Model Number */
-#define PHY_I1_REV_MSK	0x0f		/* Bit  3.. 0:	Revision Number */
-
-/* different Broadcom PHY Ids */
-#define PHY_BCOM_ID1_A1		0x6041
-#define PHY_BCOM_ID1_B2		0x6043
-#define PHY_BCOM_ID1_C0		0x6044
-#define PHY_BCOM_ID1_C5		0x6047
-
-
-/*****  PHY_XMAC_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_XMAC_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
-#define PHY_AN_NXT_PG	(1<<15)	/* Bit 15:	Request Next Page */
-#define PHY_X_AN_ACK	(1<<14)	/* Bit 14: (ro)	Acknowledge Received */
-#define PHY_X_AN_RFB	(3<<12)	/* Bit 13..12:	Remote Fault Bits */
-								/* Bit 11.. 9:	reserved */
-#define PHY_X_AN_PAUSE	(3<<7)	/* Bit  8.. 7:	Pause Bits */
-#define PHY_X_AN_HD		(1<<6)	/* Bit  6:	Half Duplex */
-#define PHY_X_AN_FD		(1<<5)	/* Bit  5:	Full Duplex */
-								/* Bit  4.. 0:	reserved */
-
-/*****  PHY_BCOM_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_BCOM_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
-								/* Bit 14:	reserved */
-#define PHY_B_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
-								/* Bit 12:	reserved */
-#define PHY_B_AN_ASP	(1<<11)	/* Bit 11:	Asymmetric Pause */
-#define PHY_B_AN_PC		(1<<10)	/* Bit 10:	Pause Capable */
-								/* Bit  9..5:	100/10 BT cap bits ingnored */
-#define PHY_B_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
-
-/*****  PHY_LONE_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_LONE_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
-								/* Bit 14:	reserved */
-#define PHY_L_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
-								/* Bit 12:	reserved */
-#define PHY_L_AN_ASP	(1<<11)	/* Bit 11:	Asymmetric Pause */
-#define PHY_L_AN_PC		(1<<10)	/* Bit 10:	Pause Capable */
-								/* Bit  9..5:	100/10 BT cap bits ingnored */
-#define PHY_L_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
-
-/*****  PHY_NAT_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_NAT_AUNE_LP		16 bit r/o	Link Partner Ability Reg *****/
-/*	PHY_AN_NXT_PG		(see XMAC) Bit 15:	Request Next Page */
-								/* Bit 14:	reserved */
-#define PHY_N_AN_RF		(1<<13)	/* Bit 13:	Remote Fault */
-								/* Bit 12:	reserved */
-#define PHY_N_AN_100F	(1<<11)	/* Bit 11:	100Base-T2 FD Support */
-#define PHY_N_AN_100H	(1<<10)	/* Bit 10:	100Base-T2 HD Support */
-								/* Bit  9..5:	100/10 BT cap bits ingnored */
-#define PHY_N_AN_SEL	0x1f	/* Bit 4..0:	Selector Field, 00001=Ethernet*/
-
-/* field type definition for PHY_x_AN_SEL */
-#define PHY_SEL_TYPE	0x01	/* 00001 = Ethernet */
-
-/*****  PHY_XMAC_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-								/* Bit 15..4:	reserved */
-#define PHY_ANE_LP_NP	(1<<3)	/* Bit  3:	Link Partner can Next Page */
-#define PHY_ANE_LOC_NP	(1<<2)	/* Bit  2:	Local PHY can Next Page */
-#define PHY_ANE_RX_PG	(1<<1)	/* Bit  1:	Page Received */
-								/* Bit  0:	reserved */
-
-/*****  PHY_BCOM_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-/*****  PHY_LONE_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-/*****  PHY_MARV_AUNE_EXP	16 bit r/o	Auto-Negotiation Expansion Reg *****/
-								/* Bit 15..5:	reserved */
-#define PHY_ANE_PAR_DF	(1<<4)	/* Bit  4:	Parallel Detection Fault */
-/*	PHY_ANE_LP_NP		(see XMAC) Bit  3:	Link Partner can Next Page */
-/*	PHY_ANE_LOC_NP		(see XMAC) Bit  2:	Local PHY can Next Page */
-/*	PHY_ANE_RX_PG		(see XMAC) Bit  1:	Page Received */
-#define PHY_ANE_LP_CAP	(1<<0)	/* Bit  0:	Link Partner Auto-Neg. Cap. */ 	
-
-/*****  PHY_XMAC_NEPG		16 bit r/w	Next Page Register *****/
-/*****  PHY_BCOM_NEPG		16 bit r/w	Next Page Register *****/
-/*****  PHY_LONE_NEPG		16 bit r/w	Next Page Register *****/
-/*****  PHY_XMAC_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
-/*****  PHY_BCOM_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
-/*****  PHY_LONE_NEPG_LP	16 bit r/o	Next Page Link Partner *****/
-#define PHY_NP_MORE		(1<<15)	/* Bit 15:	More, Next Pages to follow */
-#define PHY_NP_ACK1		(1<<14)	/* Bit 14: (ro)	Ack1, for receiving a message */
-#define PHY_NP_MSG_VAL	(1<<13)	/* Bit 13:	Message Page valid */
-#define PHY_NP_ACK2		(1<<12)	/* Bit 12:	Ack2, comply with msg content */
-#define PHY_NP_TOG		(1<<11)	/* Bit 11:	Toggle Bit, ensure sync */
-#define PHY_NP_MSG		0x07ff	/* Bit 10..0:	Message from/to Link Partner */
-
-/*
- * XMAC-Specific
- */
-/*****  PHY_XMAC_EXT_STAT	16 bit r/w	Extended Status Register *****/
-#define PHY_X_EX_FD		(1<<15)	/* Bit 15:	Device Supports Full Duplex */
-#define PHY_X_EX_HD		(1<<14)	/* Bit 14:	Device Supports Half Duplex */
-								/* Bit 13..0:	reserved */
-
-/*****  PHY_XMAC_RES_ABI	16 bit r/o	PHY Resolved Ability *****/
-								/* Bit 15..9:	reserved */
-#define PHY_X_RS_PAUSE	(3<<7)	/* Bit  8..7:	selected Pause Mode */
-#define PHY_X_RS_HD		(1<<6)	/* Bit  6:	Half Duplex Mode selected */
-#define PHY_X_RS_FD		(1<<5)	/* Bit  5:	Full Duplex Mode selected */
-#define PHY_X_RS_ABLMIS (1<<4)	/* Bit  4:	duplex or pause cap mismatch */
-#define PHY_X_RS_PAUMIS (1<<3)	/* Bit  3:	pause capability mismatch */
-								/* Bit  2..0:	reserved */
-/*
- * Remote Fault Bits (PHY_X_AN_RFB) encoding
- */
-#define X_RFB_OK		(0<<12)	/* Bit 13..12	No errors, Link OK */
-#define X_RFB_LF		(1<<12)	/* Bit 13..12	Link Failure */
-#define X_RFB_OFF		(2<<12)	/* Bit 13..12	Offline */
-#define X_RFB_AN_ERR	(3<<12)	/* Bit 13..12	Auto-Negotiation Error */
-
-/*
- * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding
- */
-#define PHY_X_P_NO_PAUSE	(0<<7)	/* Bit  8..7:	no Pause Mode */
-#define PHY_X_P_SYM_MD		(1<<7)	/* Bit  8..7:	symmetric Pause Mode */
-#define PHY_X_P_ASYM_MD		(2<<7)	/* Bit  8..7:	asymmetric Pause Mode */
-#define PHY_X_P_BOTH_MD		(3<<7)	/* Bit  8..7:	both Pause Mode */
-
-
-/*
- * Broadcom-Specific
- */
-/*****  PHY_BCOM_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_B_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_B_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
-#define PHY_B_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
-#define PHY_B_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
-#define PHY_B_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_B_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-									/* Bit  7..0:	reserved */
-
-/*****  PHY_BCOM_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-/*****  PHY_MARV_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-#define PHY_B_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
-#define PHY_B_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
-#define PHY_B_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
-#define PHY_B_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status */
-#define PHY_B_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
-#define PHY_B_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
-									/* Bit  9..8:	reserved */
-#define PHY_B_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
-
-/*****  PHY_BCOM_EXT_STAT	16 bit r/o	Extended Status Register *****/
-#define PHY_B_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
-#define PHY_B_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
-#define PHY_B_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
-#define PHY_B_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
-									/* Bit 11..0:	reserved */
-
-/*****  PHY_BCOM_P_EXT_CTRL	16 bit r/w	PHY Extended Control Reg *****/
-#define PHY_B_PEC_MAC_PHY	(1<<15)	/* Bit 15:	10BIT/GMI-Interface */
-#define PHY_B_PEC_DIS_CROSS	(1<<14)	/* Bit 14:	Disable MDI Crossover */
-#define PHY_B_PEC_TX_DIS	(1<<13)	/* Bit 13:	Tx output Disabled */
-#define PHY_B_PEC_INT_DIS	(1<<12)	/* Bit 12:	Interrupts Disabled */
-#define PHY_B_PEC_F_INT		(1<<11)	/* Bit 11:	Force Interrupt */
-#define PHY_B_PEC_BY_45		(1<<10)	/* Bit 10:	Bypass 4B5B-Decoder */
-#define PHY_B_PEC_BY_SCR	(1<<9)	/* Bit  9:	Bypass Scrambler */
-#define PHY_B_PEC_BY_MLT3	(1<<8)	/* Bit  8:	Bypass MLT3 Encoder */
-#define PHY_B_PEC_BY_RXA	(1<<7)	/* Bit  7:	Bypass Rx Alignm. */
-#define PHY_B_PEC_RES_SCR	(1<<6)	/* Bit  6:	Reset Scrambler */
-#define PHY_B_PEC_EN_LTR	(1<<5)	/* Bit  5:	Ena LED Traffic Mode */
-#define PHY_B_PEC_LED_ON	(1<<4)	/* Bit  4:	Force LED's on */
-#define PHY_B_PEC_LED_OFF	(1<<3)	/* Bit  3:	Force LED's off */
-#define PHY_B_PEC_EX_IPG	(1<<2)	/* Bit  2:	Extend Tx IPG Mode */
-#define PHY_B_PEC_3_LED		(1<<1)	/* Bit  1:	Three Link LED mode */
-#define PHY_B_PEC_HIGH_LA	(1<<0)	/* Bit  0:	GMII FIFO Elasticy */
-
-/*****  PHY_BCOM_P_EXT_STAT	16 bit r/o	PHY Extended Status Reg *****/
-									/* Bit 15..14:	reserved */
-#define PHY_B_PES_CROSS_STAT	(1<<13)	/* Bit 13:	MDI Crossover Status */
-#define PHY_B_PES_INT_STAT	(1<<12)	/* Bit 12:	Interrupt Status */
-#define PHY_B_PES_RRS		(1<<11)	/* Bit 11:	Remote Receiver Stat. */
-#define PHY_B_PES_LRS		(1<<10)	/* Bit 10:	Local Receiver Stat. */
-#define PHY_B_PES_LOCKED	(1<<9)	/* Bit  9:	Locked */
-#define PHY_B_PES_LS		(1<<8)	/* Bit  8:	Link Status */
-#define PHY_B_PES_RF		(1<<7)	/* Bit  7:	Remote Fault */
-#define PHY_B_PES_CE_ER		(1<<6)	/* Bit  6:	Carrier Ext Error */
-#define PHY_B_PES_BAD_SSD	(1<<5)	/* Bit  5:	Bad SSD */
-#define PHY_B_PES_BAD_ESD	(1<<4)	/* Bit  4:	Bad ESD */
-#define PHY_B_PES_RX_ER		(1<<3)	/* Bit  3:	Receive Error */
-#define PHY_B_PES_TX_ER		(1<<2)	/* Bit  2:	Transmit Error */
-#define PHY_B_PES_LOCK_ER	(1<<1)	/* Bit  1:	Lock Error */
-#define PHY_B_PES_MLT3_ER	(1<<0)	/* Bit  0:	MLT3 code Error */
-
-/*****  PHY_BCOM_FC_CTR		16 bit r/w	False Carrier Counter *****/
-									/* Bit 15..8:	reserved */
-#define PHY_B_FC_CTR		0xff	/* Bit  7..0:	False Carrier Counter */
-
-/*****  PHY_BCOM_RNO_CTR	16 bit r/w	Receive NOT_OK Counter *****/
-#define PHY_B_RC_LOC_MSK	0xff00	/* Bit 15..8:	Local Rx NOT_OK cnt */
-#define PHY_B_RC_REM_MSK	0x00ff	/* Bit  7..0:	Remote Rx NOT_OK cnt */
-
-/*****  PHY_BCOM_AUX_CTRL	16 bit r/w	Auxiliary Control Reg *****/
-#define PHY_B_AC_L_SQE		(1<<15)	/* Bit 15:	Low Squelch */
-#define PHY_B_AC_LONG_PACK	(1<<14)	/* Bit 14:	Rx Long Packets */
-#define PHY_B_AC_ER_CTRL	(3<<12)	/* Bit 13..12:	Edgerate Control */
-									/* Bit 11:	reserved */
-#define PHY_B_AC_TX_TST		(1<<10) /* Bit 10:	Tx test bit, always 1 */
-									/* Bit  9.. 8:	reserved */
-#define PHY_B_AC_DIS_PRF	(1<<7)	/* Bit  7:	dis part resp filter */
-									/* Bit  6:	reserved */
-#define PHY_B_AC_DIS_PM		(1<<5)	/* Bit  5:	dis power management */
-									/* Bit  4:	reserved */
-#define PHY_B_AC_DIAG		(1<<3)	/* Bit  3:	Diagnostic Mode */
-									/* Bit  2.. 0:	reserved */
-
-/*****  PHY_BCOM_AUX_STAT	16 bit r/o	Auxiliary Status Reg *****/
-#define PHY_B_AS_AN_C		(1<<15)	/* Bit 15:	AutoNeg complete */
-#define PHY_B_AS_AN_CA		(1<<14)	/* Bit 14:	AN Complete Ack */
-#define PHY_B_AS_ANACK_D	(1<<13)	/* Bit 13:	AN Ack Detect */
-#define PHY_B_AS_ANAB_D		(1<<12)	/* Bit 12:	AN Ability Detect */
-#define PHY_B_AS_NPW		(1<<11)	/* Bit 11:	AN Next Page Wait */
-#define PHY_B_AS_AN_RES_MSK	(7<<8)	/* Bit 10..8:	AN HDC */
-#define PHY_B_AS_PDF		(1<<7)	/* Bit  7:	Parallel Detect. Fault */
-#define PHY_B_AS_RF			(1<<6)	/* Bit  6:	Remote Fault */
-#define PHY_B_AS_ANP_R		(1<<5)	/* Bit  5:	AN Page Received */
-#define PHY_B_AS_LP_ANAB	(1<<4)	/* Bit  4:	LP AN Ability */
-#define PHY_B_AS_LP_NPAB	(1<<3)	/* Bit  3:	LP Next Page Ability */
-#define PHY_B_AS_LS			(1<<2)	/* Bit  2:	Link Status */
-#define PHY_B_AS_PRR		(1<<1)	/* Bit  1:	Pause Resolution-Rx */
-#define PHY_B_AS_PRT		(1<<0)	/* Bit  0:	Pause Resolution-Tx */
-
-#define PHY_B_AS_PAUSE_MSK	(PHY_B_AS_PRR | PHY_B_AS_PRT)
-
-/*****  PHY_BCOM_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
-/*****  PHY_BCOM_INT_MASK	16 bit r/w	Interrupt Mask Reg *****/
-									/* Bit 15:	reserved */
-#define PHY_B_IS_PSE		(1<<14)	/* Bit 14:	Pair Swap Error */
-#define PHY_B_IS_MDXI_SC	(1<<13)	/* Bit 13:	MDIX Status Change */
-#define PHY_B_IS_HCT		(1<<12)	/* Bit 12:	counter above 32k */
-#define PHY_B_IS_LCT		(1<<11)	/* Bit 11:	counter above 128 */
-#define PHY_B_IS_AN_PR		(1<<10)	/* Bit 10:	Page Received */
-#define PHY_B_IS_NO_HDCL	(1<<9)	/* Bit  9:	No HCD Link */
-#define PHY_B_IS_NO_HDC		(1<<8)	/* Bit  8:	No HCD */
-#define PHY_B_IS_NEG_USHDC	(1<<7)	/* Bit  7:	Negotiated Unsup. HCD */
-#define PHY_B_IS_SCR_S_ER	(1<<6)	/* Bit  6:	Scrambler Sync Error */
-#define PHY_B_IS_RRS_CHANGE	(1<<5)	/* Bit  5:	Remote Rx Stat Change */
-#define PHY_B_IS_LRS_CHANGE	(1<<4)	/* Bit  4:	Local Rx Stat Change */
-#define PHY_B_IS_DUP_CHANGE	(1<<3)	/* Bit  3:	Duplex Mode Change */
-#define PHY_B_IS_LSP_CHANGE	(1<<2)	/* Bit  2:	Link Speed Change */
-#define PHY_B_IS_LST_CHANGE	(1<<1)	/* Bit  1:	Link Status Changed */
-#define PHY_B_IS_CRC_ER		(1<<0)	/* Bit  0:	CRC Error */
-
-#define PHY_B_DEF_MSK	(~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
-
-/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
-#define PHY_B_P_NO_PAUSE	(0<<10)	/* Bit 11..10:	no Pause Mode */
-#define PHY_B_P_SYM_MD		(1<<10)	/* Bit 11..10:	symmetric Pause Mode */
-#define PHY_B_P_ASYM_MD		(2<<10)	/* Bit 11..10:	asymmetric Pause Mode */
-#define PHY_B_P_BOTH_MD		(3<<10)	/* Bit 11..10:	both Pause Mode */
-
-/*
- * Resolved Duplex mode and Capabilities (Aux Status Summary Reg)
- */
-#define PHY_B_RES_1000FD	(7<<8)	/* Bit 10..8:	1000Base-T Full Dup. */
-#define PHY_B_RES_1000HD	(6<<8)	/* Bit 10..8:	1000Base-T Half Dup. */
-/* others: 100/10: invalid for us */
-
-/*
- * Level One-Specific
- */
-/*****  PHY_LONE_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_L_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_L_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
-#define PHY_L_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
-#define PHY_L_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
-#define PHY_L_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_L_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-									/* Bit  7..0:	reserved */
-
-/*****  PHY_LONE_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-#define PHY_L_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
-#define PHY_L_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
-#define PHY_L_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
-#define PHY_L_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status */
-#define PHY_L_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
-#define PHY_L_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
-									/* Bit  9..8:	reserved */
-#define PHY_B_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
-
-/*****  PHY_LONE_EXT_STAT	16 bit r/o	Extended Status Register *****/
-#define PHY_L_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
-#define PHY_L_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
-#define PHY_L_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
-#define PHY_L_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
-									/* Bit 11..0:	reserved */
-
-/*****  PHY_LONE_PORT_CFG	16 bit r/w	Port Configuration Reg *****/
-#define PHY_L_PC_REP_MODE	(1<<15)	/* Bit 15:	Repeater Mode */
-									/* Bit 14:	reserved */
-#define PHY_L_PC_TX_DIS		(1<<13)	/* Bit 13:	Tx output Disabled */
-#define PHY_L_PC_BY_SCR		(1<<12)	/* Bit 12:	Bypass Scrambler */
-#define PHY_L_PC_BY_45		(1<<11)	/* Bit 11:	Bypass 4B5B-Decoder */
-#define PHY_L_PC_JAB_DIS	(1<<10)	/* Bit 10:	Jabber Disabled */
-#define PHY_L_PC_SQE		(1<<9)	/* Bit  9:	Enable Heartbeat */
-#define PHY_L_PC_TP_LOOP	(1<<8)	/* Bit  8:	TP Loopback */
-#define PHY_L_PC_SSS		(1<<7)	/* Bit  7:	Smart Speed Selection */
-#define PHY_L_PC_FIFO_SIZE	(1<<6)	/* Bit  6:	FIFO Size */
-#define PHY_L_PC_PRE_EN		(1<<5)	/* Bit  5:	Preamble Enable */
-#define PHY_L_PC_CIM		(1<<4)	/* Bit  4:	Carrier Integrity Mon */
-#define PHY_L_PC_10_SER		(1<<3)	/* Bit  3:	Use Serial Output */
-#define PHY_L_PC_ANISOL		(1<<2)	/* Bit  2:	Unisolate Port */
-#define PHY_L_PC_TEN_BIT	(1<<1)	/* Bit  1:	10bit iface mode on */
-#define PHY_L_PC_ALTCLOCK	(1<<0)	/* Bit  0: (ro)	ALTCLOCK Mode on */
-
-/*****  PHY_LONE_Q_STAT		16 bit r/o	Quick Status Reg *****/
-#define PHY_L_QS_D_RATE		(3<<14)	/* Bit 15..14:	Data Rate */
-#define PHY_L_QS_TX_STAT	(1<<13)	/* Bit 13:	Transmitting */
-#define PHY_L_QS_RX_STAT	(1<<12)	/* Bit 12:	Receiving */
-#define PHY_L_QS_COL_STAT	(1<<11)	/* Bit 11:	Collision */
-#define PHY_L_QS_L_STAT		(1<<10)	/* Bit 10:	Link is up */
-#define PHY_L_QS_DUP_MOD	(1<<9)	/* Bit  9:	Full/Half Duplex */
-#define PHY_L_QS_AN			(1<<8)	/* Bit  8:	AutoNeg is On */
-#define PHY_L_QS_AN_C		(1<<7)	/* Bit  7:	AN is Complete */
-#define PHY_L_QS_LLE		(7<<4)	/* Bit  6:	Line Length Estim. */
-#define PHY_L_QS_PAUSE		(1<<3)	/* Bit  3:	LP advertised Pause */
-#define PHY_L_QS_AS_PAUSE	(1<<2)	/* Bit  2:	LP adv. asym. Pause */
-#define PHY_L_QS_ISOLATE	(1<<1)	/* Bit  1:	CIM Isolated */
-#define PHY_L_QS_EVENT		(1<<0)	/* Bit  0:	Event has occurred */
-
-/*****  PHY_LONE_INT_ENAB	16 bit r/w	Interrupt Enable Reg *****/
-/*****  PHY_LONE_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
-									/* Bit 15..14:	reserved */
-#define PHY_L_IS_AN_F		(1<<13)	/* Bit 13:	Auto-Negotiation fault */
-									/* Bit 12:	not described */
-#define PHY_L_IS_CROSS		(1<<11)	/* Bit 11:	Crossover used */
-#define PHY_L_IS_POL		(1<<10)	/* Bit 10:	Polarity correct. used */
-#define PHY_L_IS_SS			(1<<9)	/* Bit  9:	Smart Speed Downgrade */
-#define PHY_L_IS_CFULL		(1<<8)	/* Bit  8:	Counter Full */
-#define PHY_L_IS_AN_C		(1<<7)	/* Bit  7:	AutoNeg Complete */
-#define PHY_L_IS_SPEED		(1<<6)	/* Bit  6:	Speed Changed */
-#define PHY_L_IS_DUP		(1<<5)	/* Bit  5:	Duplex Changed */
-#define PHY_L_IS_LS			(1<<4)	/* Bit  4:	Link Status Changed */
-#define PHY_L_IS_ISOL		(1<<3)	/* Bit  3:	Isolate Occured */
-#define PHY_L_IS_MDINT		(1<<2)	/* Bit  2: (ro)	STAT: MII Int Pending */
-#define PHY_L_IS_INTEN		(1<<1)	/* Bit  1:	ENAB: Enable IRQs */
-#define PHY_L_IS_FORCE		(1<<0)	/* Bit  0:	ENAB: Force Interrupt */
-
-/* int. mask */
-#define PHY_L_DEF_MSK		(PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN)
-
-/*****  PHY_LONE_LED_CFG	16 bit r/w	LED Configuration Reg *****/
-#define PHY_L_LC_LEDC		(3<<14)	/* Bit 15..14:	Col/Blink/On/Off */
-#define PHY_L_LC_LEDR		(3<<12)	/* Bit 13..12:	Rx/Blink/On/Off */
-#define PHY_L_LC_LEDT		(3<<10)	/* Bit 11..10:	Tx/Blink/On/Off */
-#define PHY_L_LC_LEDG		(3<<8)	/* Bit  9..8:	Giga/Blink/On/Off */
-#define PHY_L_LC_LEDS		(3<<6)	/* Bit  7..6:	10-100/Blink/On/Off */
-#define PHY_L_LC_LEDL		(3<<4)	/* Bit  5..4:	Link/Blink/On/Off */
-#define PHY_L_LC_LEDF		(3<<2)	/* Bit  3..2:	Duplex/Blink/On/Off */
-#define PHY_L_LC_PSTRECH	(1<<1)	/* Bit  1:	Strech LED Pulses */
-#define PHY_L_LC_FREQ		(1<<0)	/* Bit  0:	30/100 ms */
-
-/*****  PHY_LONE_PORT_CTRL	16 bit r/w	Port Control Reg *****/
-#define PHY_L_PC_TX_TCLK	(1<<15)	/* Bit 15:	Enable TX_TCLK */
-									/* Bit 14:	reserved */
-#define PHY_L_PC_ALT_NP		(1<<13)	/* Bit 14:	Alternate Next Page */
-#define PHY_L_PC_GMII_ALT	(1<<12)	/* Bit 13:	Alternate GMII driver */
-									/* Bit 11:	reserved */
-#define PHY_L_PC_TEN_CRS	(1<<10)	/* Bit 10:	Extend CRS*/
-									/* Bit  9..0:	not described */
-
-/*****  PHY_LONE_CIM		16 bit r/o	CIM Reg *****/
-#define PHY_L_CIM_ISOL		(255<<8)/* Bit 15..8:	Isolate Count */
-#define PHY_L_CIM_FALSE_CAR	(255<<0)/* Bit  7..0:	False Carrier Count */
-
-
-/*
- * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
- */
-#define PHY_L_P_NO_PAUSE	(0<<10)	/* Bit 11..10:	no Pause Mode */
-#define PHY_L_P_SYM_MD		(1<<10)	/* Bit 11..10:	symmetric Pause Mode */
-#define PHY_L_P_ASYM_MD		(2<<10)	/* Bit 11..10:	asymmetric Pause Mode */
-#define PHY_L_P_BOTH_MD		(3<<10)	/* Bit 11..10:	both Pause Mode */
-
-
-/*
- * National-Specific
- */
-/*****  PHY_NAT_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_N_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_N_1000C_MSE		(1<<12)	/* Bit 12:	Master/Slave Enable */
-#define PHY_N_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration */
-#define PHY_N_1000C_RD		(1<<10)	/* Bit 10:	Repeater/DTE */
-#define PHY_N_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_N_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-#define PHY_N_1000C_APC		(1<<7)	/* Bit  7:	Asymmetric Pause Cap. */
-									/* Bit  6..0:	reserved */
-
-/*****  PHY_NAT_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
-#define PHY_N_1000S_MSF		(1<<15)	/* Bit 15:	Master/Slave Fault */
-#define PHY_N_1000S_MSR		(1<<14)	/* Bit 14:	Master/Slave Result */
-#define PHY_N_1000S_LRS		(1<<13)	/* Bit 13:	Local Receiver Status */
-#define PHY_N_1000S_RRS		(1<<12)	/* Bit 12:	Remote Receiver Status*/
-#define PHY_N_1000S_LP_FD	(1<<11)	/* Bit 11:	Link Partner can FD */
-#define PHY_N_1000S_LP_HD	(1<<10)	/* Bit 10:	Link Partner can HD */
-#define PHY_N_1000C_LP_APC	(1<<9)	/* Bit  9:	LP Asym. Pause Cap. */
-									/* Bit  8:	reserved */
-#define PHY_N_1000S_IEC		0xff	/* Bit  7..0:	Idle Error Count */
-
-/*****  PHY_NAT_EXT_STAT	16 bit r/o	Extended Status Register *****/
-#define PHY_N_ES_X_FD_CAP	(1<<15)	/* Bit 15:	1000Base-X FD capable */
-#define PHY_N_ES_X_HD_CAP	(1<<14)	/* Bit 14:	1000Base-X HD capable */
-#define PHY_N_ES_T_FD_CAP	(1<<13)	/* Bit 13:	1000Base-T FD capable */
-#define PHY_N_ES_T_HD_CAP	(1<<12)	/* Bit 12:	1000Base-T HD capable */
-									/* Bit 11..0:	reserved */
-
-/* todo: those are still missing */
-/*****  PHY_NAT_EXT_CTRL1	16 bit r/o	Extended Control Reg1 *****/
-/*****  PHY_NAT_Q_STAT1		16 bit r/o	Quick Status Reg1 *****/
-/*****  PHY_NAT_10B_OP		16 bit r/o	10Base-T Operations Reg *****/
-/*****  PHY_NAT_EXT_CTRL2	16 bit r/o	Extended Control Reg1 *****/
-/*****  PHY_NAT_Q_STAT2		16 bit r/o	Quick Status Reg2 *****/
-/*****  PHY_NAT_PHY_ADDR	16 bit r/o	PHY Address Register *****/
-
-/*
- * Marvell-Specific
- */
-/*****  PHY_MARV_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement *****/
-/*****  PHY_MARV_AUNE_LP	16 bit r/w	Link Part Ability Reg *****/
-#define PHY_M_AN_NXT_PG		BIT_15	/* Request Next Page */
-#define PHY_M_AN_ACK		BIT_14	/* (ro)	Acknowledge Received */
-#define PHY_M_AN_RF			BIT_13	/* Remote Fault */
-									/* Bit 12:	reserved */
-#define PHY_M_AN_ASP		BIT_11	/* Asymmetric Pause */
-#define PHY_M_AN_PC			BIT_10	/* MAC Pause implemented */
-#define PHY_M_AN_100_FD		BIT_8	/* Advertise 100Base-TX Full Duplex */
-#define PHY_M_AN_100_HD		BIT_7	/* Advertise 100Base-TX Half Duplex */
-#define PHY_M_AN_10_FD		BIT_6	/* Advertise 10Base-TX Full Duplex */
-#define PHY_M_AN_10_HD		BIT_5	/* Advertise 10Base-TX Half Duplex */
-
-/* special defines for FIBER (88E1011S only) */
-#define PHY_M_AN_ASP_X		BIT_8	/* Asymmetric Pause */
-#define PHY_M_AN_PC_X		BIT_7	/* MAC Pause implemented */
-#define PHY_M_AN_1000X_AHD	BIT_6	/* Advertise 10000Base-X Half Duplex */
-#define PHY_M_AN_1000X_AFD	BIT_5	/* Advertise 10000Base-X Full Duplex */
-
-/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
-#define PHY_M_P_NO_PAUSE_X	(0<<7)	/* Bit  8.. 7:	no Pause Mode */
-#define PHY_M_P_SYM_MD_X	(1<<7)	/* Bit  8.. 7:	symmetric Pause Mode */
-#define PHY_M_P_ASYM_MD_X	(2<<7)	/* Bit  8.. 7:	asymmetric Pause Mode */
-#define PHY_M_P_BOTH_MD_X	(3<<7)	/* Bit  8.. 7:	both Pause Mode */
-
-/*****  PHY_MARV_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
-#define PHY_M_1000C_TEST	(7<<13)	/* Bit 15..13:	Test Modes */
-#define PHY_M_1000C_MSE		(1<<12)	/* Bit 12:	Manual Master/Slave Enable */
-#define PHY_M_1000C_MSC		(1<<11)	/* Bit 11:	M/S Configuration (1=Master) */
-#define PHY_M_1000C_MPD		(1<<10)	/* Bit 10:	Multi-Port Device */
-#define PHY_M_1000C_AFD		(1<<9)	/* Bit  9:	Advertise Full Duplex */
-#define PHY_M_1000C_AHD		(1<<8)	/* Bit  8:	Advertise Half Duplex */
-									/* Bit  7..0:	reserved */
-
-/*****  PHY_MARV_PHY_CTRL	16 bit r/w	PHY Specific Ctrl Reg *****/
-#define PHY_M_PC_TX_FFD_MSK	(3<<14)	/* Bit 15..14:	Tx FIFO Depth Mask */
-#define PHY_M_PC_RX_FFD_MSK	(3<<12)	/* Bit 13..12:	Rx FIFO Depth Mask */
-#define PHY_M_PC_ASS_CRS_TX	(1<<11)	/* Bit 11:	Assert CRS on Transmit */
-#define PHY_M_PC_FL_GOOD	(1<<10)	/* Bit 10:	Force Link Good */
-#define PHY_M_PC_EN_DET_MSK	(3<<8)	/* Bit  9.. 8:	Energy Detect Mask */
-#define PHY_M_PC_ENA_EXT_D	(1<<7)	/* Bit  7:	Enable Ext. Distance (10BT) */
-#define PHY_M_PC_MDIX_MSK	(3<<5)	/* Bit  6.. 5:	MDI/MDIX Config. Mask */
-#define PHY_M_PC_DIS_125CLK	(1<<4)	/* Bit  4:	Disable 125 CLK */
-#define PHY_M_PC_MAC_POW_UP	(1<<3)	/* Bit  3:	MAC Power up */
-#define PHY_M_PC_SQE_T_ENA	(1<<2)	/* Bit  2:	SQE Test Enabled */
-#define PHY_M_PC_POL_R_DIS	(1<<1)	/* Bit  1:	Polarity Reversal Disabled */
-#define PHY_M_PC_DIS_JABBER	(1<<0)	/* Bit  0:	Disable Jabber */
-
-#define PHY_M_PC_EN_DET			SHIFT8(2)	/* Energy Detect (Mode 1) */
-#define PHY_M_PC_EN_DET_PLUS	SHIFT8(3)	/* Energy Detect Plus (Mode 2) */
-
-#define PHY_M_PC_MDI_XMODE(x)	SHIFT5(x)	
-#define PHY_M_PC_MAN_MDI	0    	/* 00 = Manual MDI configuration */
-#define PHY_M_PC_MAN_MDIX	1		/* 01 = Manual MDIX configuration */
-#define PHY_M_PC_ENA_AUTO	3		/* 11 = Enable Automatic Crossover */
-
-/*****  PHY_MARV_PHY_STAT	16 bit r/o	PHY Specific Status Reg *****/
-#define PHY_M_PS_SPEED_MSK	(3<<14)	/* Bit 15..14:	Speed Mask */
-#define PHY_M_PS_SPEED_1000	(1<<15)	/*       10 = 1000 Mbps */
-#define PHY_M_PS_SPEED_100	(1<<14)	/*       01 =  100 Mbps */
-#define PHY_M_PS_SPEED_10	0		/*       00 =   10 Mbps */
-#define PHY_M_PS_FULL_DUP	(1<<13)	/* Bit 13:	Full Duplex */
-#define PHY_M_PS_PAGE_REC	(1<<12)	/* Bit 12:	Page Received */
-#define PHY_M_PS_SPDUP_RES	(1<<11)	/* Bit 11:	Speed & Duplex Resolved */
-#define PHY_M_PS_LINK_UP	(1<<10)	/* Bit 10:	Link Up */
-#define PHY_M_PS_CABLE_MSK	(3<<7)	/* Bit  9.. 7:	Cable Length Mask */
-#define PHY_M_PS_MDI_X_STAT	(1<<6)	/* Bit  6:	MDI Crossover Stat (1=MDIX) */
-#define PHY_M_PS_DOWNS_STAT	(1<<5)	/* Bit  5:	Downshift Status (1=downsh.) */
-#define PHY_M_PS_ENDET_STAT	(1<<4)	/* Bit  4:	Energy Detect Status (1=act) */
-#define PHY_M_PS_TX_P_EN	(1<<3)	/* Bit  3:	Tx Pause Enabled */
-#define PHY_M_PS_RX_P_EN	(1<<2)	/* Bit  2:	Rx Pause Enabled */
-#define PHY_M_PS_POL_REV	(1<<1)	/* Bit  1:	Polarity Reversed */
-#define PHY_M_PC_JABBER		(1<<0)	/* Bit  0:	Jabber */
-
-#define PHY_M_PS_PAUSE_MSK	(PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
-
-/*****  PHY_MARV_INT_MASK	16 bit r/w	Interrupt Mask Reg *****/
-/*****  PHY_MARV_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
-#define PHY_M_IS_AN_ERROR	(1<<15)	/* Bit 15:	Auto-Negotiation Error */
-#define PHY_M_IS_LSP_CHANGE	(1<<14)	/* Bit 14:	Link Speed Changed */
-#define PHY_M_IS_DUP_CHANGE	(1<<13)	/* Bit 13:	Duplex Mode Changed */
-#define PHY_M_IS_AN_PR		(1<<12)	/* Bit 12:	Page Received */
-#define PHY_M_IS_AN_COMPL	(1<<11)	/* Bit 11:	Auto-Negotiation Completed */
-#define PHY_M_IS_LST_CHANGE	(1<<10)	/* Bit 10:	Link Status Changed */
-#define PHY_M_IS_SYMB_ERROR	(1<<9)	/* Bit  9:	Symbol Error */
-#define PHY_M_IS_FALSE_CARR	(1<<8)	/* Bit  8:	False Carrier */
-#define PHY_M_IS_FIFO_ERROR	(1<<7)	/* Bit  7:	FIFO Overflow/Underrun Error */
-#define PHY_M_IS_MDI_CHANGE	(1<<6)	/* Bit  6:	MDI Crossover Changed */
-#define PHY_M_IS_DOWNSH_DET	(1<<5)	/* Bit  5:	Downshift Detected */
-#define PHY_M_IS_END_CHANGE	(1<<4)	/* Bit  4:	Energy Detect Changed */
-									/* Bit  3..2:	reserved */
-#define PHY_M_IS_POL_CHANGE	(1<<1)	/* Bit  1:	Polarity Changed */
-#define PHY_M_IS_JABBER		(1<<0)	/* Bit  0:	Jabber */
-
-#define PHY_M_DEF_MSK		(PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \
-							PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
-
-/*****  PHY_MARV_EXT_CTRL	16 bit r/w	Ext. PHY Specific Ctrl *****/
-#define PHY_M_EC_M_DSC_MSK	(3<<10)	/* Bit 11..10:	Master downshift counter */
-#define PHY_M_EC_S_DSC_MSK	(3<<8)	/* Bit  9.. 8:	Slave  downshift counter */
-#define PHY_M_EC_MAC_S_MSK	(7<<4)	/* Bit  6.. 4:	Def. MAC interface speed */
-#define PHY_M_EC_FIB_AN_ENA	(1<<3)	/* Bit  3:	Fiber Auto-Neg. Enable */
-
-#define PHY_M_EC_M_DSC(x)		SHIFT10(x)	/* 00=1x; 01=2x; 10=3x; 11=4x */
-#define PHY_M_EC_S_DSC(x)		SHIFT8(x)	/* 00=dis; 01=1x; 10=2x; 11=3x */
-#define PHY_M_EC_MAC_S(x)		SHIFT4(x)	/* 01X=0; 110=2.5; 111=25 (MHz) */
-
-#define MAC_TX_CLK_0_MHZ	2
-#define MAC_TX_CLK_2_5_MHZ	6
-#define MAC_TX_CLK_25_MHZ	7
-
-/*****  PHY_MARV_LED_CTRL	16 bit r/w	LED Control Reg *****/
-#define PHY_M_LEDC_DIS_LED	(1<<15)	/* Bit 15:	Disable LED */
-#define PHY_M_LEDC_PULS_MSK	(7<<12)	/* Bit 14..12:  Pulse Stretch Mask */
-#define PHY_M_LEDC_F_INT	(1<<11)	/* Bit 11:	Force Interrupt */
-#define PHY_M_LEDC_BL_R_MSK	(7<<8)	/* Bit 10.. 8:  Blink Rate Mask */
-									/* Bit  7.. 5:	reserved */
-#define PHY_M_LEDC_LINK_MSK	(3<<3)	/* Bit  4.. 3:	Link Control Mask */
-#define PHY_M_LEDC_DP_CTRL	(1<<2)	/* Bit  2:	Duplex Control */
-#define PHY_M_LEDC_RX_CTRL	(1<<1)	/* Bit  1:	Rx activity / Link */
-#define PHY_M_LEDC_TX_CTRL	(1<<0)	/* Bit  0:	Tx activity / Link */
-
-#define PHY_M_LED_PULS_DUR(x)	SHIFT12(x)	/* Pulse Stretch Duration */
-
-#define	PULS_NO_STR		0		/* no pulse stretching */
-#define	PULS_21MS		1		/* 21 ms to 42 ms */
-#define PULS_42MS		2		/* 42 ms to 84 ms */
-#define PULS_84MS		3		/* 84 ms to 170 ms */
-#define PULS_170MS		4		/* 170 ms to 340 ms */
-#define PULS_340MS		5		/* 340 ms to 670 ms */
-#define PULS_670MS		6		/* 670 ms to 1.3 s */
-#define PULS_1300MS		7		/* 1.3 s to 2.7 s */
-
-#define PHY_M_LED_BLINK_RT(x)	SHIFT8(x)	/* Blink Rate */
-
-#define BLINK_42MS		0		/* 42 ms */
-#define BLINK_84MS		1		/* 84 ms */
-#define BLINK_170MS		2		/* 170 ms */
-#define BLINK_340MS		3		/* 340 ms */
-#define BLINK_670MS		4		/* 670 ms */
-								/* values 5 - 7: reserved */
-
-/*****  PHY_MARV_LED_OVER	16 bit r/w	Manual LED Override Reg *****/
-#define PHY_M_LED_MO_DUP(x)		SHIFT10(x)	/* Bit 11..10:  Duplex */
-#define PHY_M_LED_MO_10(x)		SHIFT8(x)	/* Bit  9.. 8:  Link 10 */
-#define PHY_M_LED_MO_100(x)		SHIFT6(x)	/* Bit  7.. 6:  Link 100 */
-#define PHY_M_LED_MO_1000(x)	SHIFT4(x)	/* Bit  5.. 4:  Link 1000 */
-#define PHY_M_LED_MO_RX(x)		SHIFT2(x)	/* Bit  3.. 2:  Rx */
-#define PHY_M_LED_MO_TX(x)		SHIFT0(x)	/* Bit  1.. 0:  Tx */
-
-#define MO_LED_NORM			0
-#define MO_LED_BLINK		1
-#define MO_LED_OFF			2
-#define MO_LED_ON			3
-
-/*****  PHY_MARV_EXT_CTRL_2	16 bit r/w	Ext. PHY Specific Ctrl 2 *****/
-									/* Bit 15.. 7:	reserved */
-#define PHY_M_EC2_FI_IMPED	(1<<6)	/* Bit  6:	Fiber Input  Impedance */
-#define PHY_M_EC2_FO_IMPED	(1<<5)	/* Bit  5:	Fiber Output Impedance */
-#define PHY_M_EC2_FO_M_CLK	(1<<4)	/* Bit  4:	Fiber Mode Clock Enable */
-#define PHY_M_EC2_FO_BOOST	(1<<3)	/* Bit  3:	Fiber Output Boost */
-#define PHY_M_EC2_FO_AM_MSK	7		/* Bit  2.. 0:	Fiber Output Amplitude */
-
-/*****	PHY_MARV_EXT_P_STAT 16 bit r/w	Ext. PHY Specific Status *****/
-#define PHY_M_FC_AUTO_SEL	(1<<15)	/* Bit 15:	Fiber/Copper Auto Sel. dis. */
-#define PHY_M_FC_AN_REG_ACC (1<<14) /* Bit 14:	Fiber/Copper Autoneg. reg acc */
-#define PHY_M_FC_RESULUTION (1<<13)	/* Bit 13:	Fiber/Copper Resulution */
-#define PHY_M_SER_IF_AN_BP  (1<<12) /* Bit 12:	Ser IF autoneg. bypass enable */
-#define PHY_M_SER_IF_BP_ST	(1<<11) /* Bit 11:	Ser IF autoneg. bypass status */
-#define PHY_M_IRQ_POLARITY	(1<<10) /* Bit 10:	IRQ polarity */
-									/* Bit 9..4: reserved */
-#define PHY_M_UNDOC1		(1<< 7) /* undocumented bit !! */
-#define PHY_M_MODE_MASK		(0xf<<0)/* Bit 3..0: copy of HWCFG MODE[3:0] */
-
-
-/*****  PHY_MARV_CABLE_DIAG	16 bit r/o	Cable Diagnostic Reg *****/
-#define PHY_M_CABD_ENA_TEST	(1<<15)	/* Bit 15:	Enable Test */
-#define PHY_M_CABD_STAT_MSK	(3<<13)	/* Bit 14..13:	Status */
-									/* Bit 12.. 8:	reserved */
-#define PHY_M_CABD_DIST_MSK	0xff	/* Bit  7.. 0:	Distance */
-
-/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
-#define CABD_STAT_NORMAL	0
-#define CABD_STAT_SHORT		1
-#define CABD_STAT_OPEN		2
-#define CABD_STAT_FAIL		3
-
-
-/*
- * GMAC registers
- *
- * The GMAC registers are 16 or 32 bits wide.
- * The GMACs host processor interface is 16 bits wide,
- * therefore ALL registers will be addressed with 16 bit accesses.
- *
- * The following macros are provided to access the GMAC registers
- * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(),
- * GM_INHASH(), and GM_OUTHASH().
- * The macros are defined in SkGeHw.h.
- *
- * Note:	NA reg	= Network Address e.g DA, SA etc.
- *
- */
-
-/* Port Registers */
-#define GM_GP_STAT		0x0000		/* 16 bit r/o	General Purpose Status */
-#define GM_GP_CTRL		0x0004		/* 16 bit r/w	General Purpose Control */
-#define GM_TX_CTRL		0x0008		/* 16 bit r/w	Transmit Control Reg. */
-#define GM_RX_CTRL		0x000c		/* 16 bit r/w	Receive Control Reg. */
-#define GM_TX_FLOW_CTRL	0x0010		/* 16 bit r/w	Transmit Flow-Control */
-#define GM_TX_PARAM		0x0014		/* 16 bit r/w	Transmit Parameter Reg. */
-#define GM_SERIAL_MODE	0x0018		/* 16 bit r/w	Serial Mode Register */
-
-/* Source Address Registers */
-#define GM_SRC_ADDR_1L	0x001c		/* 16 bit r/w	Source Address 1 (low) */
-#define GM_SRC_ADDR_1M	0x0020		/* 16 bit r/w	Source Address 1 (middle) */
-#define GM_SRC_ADDR_1H	0x0024		/* 16 bit r/w	Source Address 1 (high) */
-#define GM_SRC_ADDR_2L	0x0028		/* 16 bit r/w	Source Address 2 (low) */
-#define GM_SRC_ADDR_2M	0x002c		/* 16 bit r/w	Source Address 2 (middle) */
-#define GM_SRC_ADDR_2H	0x0030		/* 16 bit r/w	Source Address 2 (high) */
-
-/* Multicast Address Hash Registers */
-#define GM_MC_ADDR_H1	0x0034		/* 16 bit r/w	Multicast Address Hash 1 */
-#define GM_MC_ADDR_H2	0x0038		/* 16 bit r/w	Multicast Address Hash 2 */
-#define GM_MC_ADDR_H3	0x003c		/* 16 bit r/w	Multicast Address Hash 3 */
-#define GM_MC_ADDR_H4	0x0040		/* 16 bit r/w	Multicast Address Hash 4 */
-
-/* Interrupt Source Registers */
-#define GM_TX_IRQ_SRC	0x0044		/* 16 bit r/o	Tx Overflow IRQ Source */
-#define GM_RX_IRQ_SRC	0x0048		/* 16 bit r/o	Rx Overflow IRQ Source */
-#define GM_TR_IRQ_SRC	0x004c		/* 16 bit r/o	Tx/Rx Over. IRQ Source */
-
-/* Interrupt Mask Registers */
-#define GM_TX_IRQ_MSK	0x0050		/* 16 bit r/w	Tx Overflow IRQ Mask */
-#define GM_RX_IRQ_MSK	0x0054		/* 16 bit r/w	Rx Overflow IRQ Mask */
-#define GM_TR_IRQ_MSK	0x0058		/* 16 bit r/w	Tx/Rx Over. IRQ Mask */
-
-/* Serial Management Interface (SMI) Registers */
-#define GM_SMI_CTRL		0x0080		/* 16 bit r/w	SMI Control Register */
-#define GM_SMI_DATA		0x0084		/* 16 bit r/w	SMI Data Register */
-#define GM_PHY_ADDR		0x0088		/* 16 bit r/w	GPHY Address Register */
-
-/* MIB Counters */
-#define GM_MIB_CNT_BASE	0x0100		/* Base Address of MIB Counters */
-#define GM_MIB_CNT_SIZE	44			/* Number of MIB Counters */
-
-/*
- * MIB Counters base address definitions (low word) -
- * use offset 4 for access to high word	(32 bit r/o)
- */
-#define GM_RXF_UC_OK \
-			(GM_MIB_CNT_BASE + 0)	/* Unicast Frames Received OK */
-#define GM_RXF_BC_OK \
-			(GM_MIB_CNT_BASE + 8)	/* Broadcast Frames Received OK */
-#define GM_RXF_MPAUSE \
-			(GM_MIB_CNT_BASE + 16)	/* Pause MAC Ctrl Frames Received */
-#define GM_RXF_MC_OK \
-			(GM_MIB_CNT_BASE + 24)	/* Multicast Frames Received OK */
-#define GM_RXF_FCS_ERR \
-			(GM_MIB_CNT_BASE + 32)	/* Rx Frame Check Seq. Error */
-	/* GM_MIB_CNT_BASE + 40:	reserved */
-#define GM_RXO_OK_LO \
-			(GM_MIB_CNT_BASE + 48)	/* Octets Received OK Low */
-#define GM_RXO_OK_HI \
-			(GM_MIB_CNT_BASE + 56)	/* Octets Received OK High */
-#define GM_RXO_ERR_LO \
-			(GM_MIB_CNT_BASE + 64)	/* Octets Received Invalid Low */
-#define GM_RXO_ERR_HI \
-			(GM_MIB_CNT_BASE + 72)	/* Octets Received Invalid High */
-#define GM_RXF_SHT \
-			(GM_MIB_CNT_BASE + 80)	/* Frames <64 Byte Received OK */
-#define GM_RXE_FRAG \
-			(GM_MIB_CNT_BASE + 88)	/* Frames <64 Byte Received with FCS Err */
-#define GM_RXF_64B \
-			(GM_MIB_CNT_BASE + 96)	/* 64 Byte Rx Frame */
-#define GM_RXF_127B \
-			(GM_MIB_CNT_BASE + 104)	/* 65-127 Byte Rx Frame */
-#define GM_RXF_255B \
-			(GM_MIB_CNT_BASE + 112)	/* 128-255 Byte Rx Frame */
-#define GM_RXF_511B \
-			(GM_MIB_CNT_BASE + 120)	/* 256-511 Byte Rx Frame */
-#define GM_RXF_1023B \
-			(GM_MIB_CNT_BASE + 128)	/* 512-1023 Byte Rx Frame */
-#define GM_RXF_1518B \
-			(GM_MIB_CNT_BASE + 136)	/* 1024-1518 Byte Rx Frame */
-#define GM_RXF_MAX_SZ \
-			(GM_MIB_CNT_BASE + 144)	/* 1519-MaxSize Byte Rx Frame */
-#define GM_RXF_LNG_ERR \
-			(GM_MIB_CNT_BASE + 152)	/* Rx Frame too Long Error */
-#define GM_RXF_JAB_PKT \
-			(GM_MIB_CNT_BASE + 160)	/* Rx Jabber Packet Frame */
-	/* GM_MIB_CNT_BASE + 168:	reserved */
-#define GM_RXE_FIFO_OV \
-			(GM_MIB_CNT_BASE + 176)	/* Rx FIFO overflow Event */
-	/* GM_MIB_CNT_BASE + 184:	reserved */
-#define GM_TXF_UC_OK \
-			(GM_MIB_CNT_BASE + 192)	/* Unicast Frames Xmitted OK */
-#define GM_TXF_BC_OK \
-			(GM_MIB_CNT_BASE + 200)	/* Broadcast Frames Xmitted OK */
-#define GM_TXF_MPAUSE \
-			(GM_MIB_CNT_BASE + 208)	/* Pause MAC Ctrl Frames Xmitted */
-#define GM_TXF_MC_OK \
-			(GM_MIB_CNT_BASE + 216)	/* Multicast Frames Xmitted OK */
-#define GM_TXO_OK_LO \
-			(GM_MIB_CNT_BASE + 224)	/* Octets Transmitted OK Low */
-#define GM_TXO_OK_HI \
-			(GM_MIB_CNT_BASE + 232)	/* Octets Transmitted OK High */
-#define GM_TXF_64B \
-			(GM_MIB_CNT_BASE + 240)	/* 64 Byte Tx Frame */
-#define GM_TXF_127B \
-			(GM_MIB_CNT_BASE + 248)	/* 65-127 Byte Tx Frame */
-#define GM_TXF_255B \
-			(GM_MIB_CNT_BASE + 256)	/* 128-255 Byte Tx Frame */
-#define GM_TXF_511B \
-			(GM_MIB_CNT_BASE + 264)	/* 256-511 Byte Tx Frame */
-#define GM_TXF_1023B \
-			(GM_MIB_CNT_BASE + 272)	/* 512-1023 Byte Tx Frame */
-#define GM_TXF_1518B \
-			(GM_MIB_CNT_BASE + 280)	/* 1024-1518 Byte Tx Frame */
-#define GM_TXF_MAX_SZ \
-			(GM_MIB_CNT_BASE + 288)	/* 1519-MaxSize Byte Tx Frame */
-	/* GM_MIB_CNT_BASE + 296:	reserved */
-#define GM_TXF_COL \
-			(GM_MIB_CNT_BASE + 304)	/* Tx Collision */
-#define GM_TXF_LAT_COL \
-			(GM_MIB_CNT_BASE + 312)	/* Tx Late Collision */
-#define GM_TXF_ABO_COL \
-			(GM_MIB_CNT_BASE + 320)	/* Tx aborted due to Exces. Col. */
-#define GM_TXF_MUL_COL \
-			(GM_MIB_CNT_BASE + 328)	/* Tx Multiple Collision */
-#define GM_TXF_SNG_COL \
-			(GM_MIB_CNT_BASE + 336)	/* Tx Single Collision */
-#define GM_TXE_FIFO_UR \
-			(GM_MIB_CNT_BASE + 344)	/* Tx FIFO Underrun Event */
-
-/*----------------------------------------------------------------------------*/
-/*
- * GMAC Bit Definitions
- *
- * If the bit access behaviour differs from the register access behaviour
- * (r/w, r/o) this is documented after the bit number.
- * The following bit access behaviours are used:
- *	(sc)	self clearing
- *	(r/o)	read only
- */
-
-/*	GM_GP_STAT	16 bit r/o	General Purpose Status Register */
-#define GM_GPSR_SPEED		(1<<15) /* Bit 15:	Port Speed (1 = 100 Mbps) */
-#define GM_GPSR_DUPLEX		(1<<14) /* Bit 14:	Duplex Mode (1 = Full) */
-#define GM_GPSR_FC_TX_DIS	(1<<13) /* Bit 13:	Tx Flow-Control Mode Disabled */
-#define GM_GPSR_LINK_UP		(1<<12)	/* Bit 12:	Link Up Status */
-#define GM_GPSR_PAUSE		(1<<11)	/* Bit 11:	Pause State */
-#define GM_GPSR_TX_ACTIVE	(1<<10)	/* Bit 10:	Tx in Progress */
-#define GM_GPSR_EXC_COL		(1<<9)	/* Bit  9:	Excessive Collisions Occured */
-#define GM_GPSR_LAT_COL		(1<<8)	/* Bit  8:	Late Collisions Occured */
-								/* Bit  7..6:	reserved */
-#define GM_GPSR_PHY_ST_CH	(1<<5)	/* Bit  5:	PHY Status Change */
-#define GM_GPSR_GIG_SPEED	(1<<4)	/* Bit  4:	Gigabit Speed (1 = 1000 Mbps) */
-#define GM_GPSR_PART_MODE	(1<<3)	/* Bit  3:	Partition mode */
-#define GM_GPSR_FC_RX_DIS	(1<<2)	/* Bit  2:	Rx Flow-Control Mode Disabled */
-#define GM_GPSR_PROM_EN		(1<<1)	/* Bit  1:	Promiscuous Mode Enabled */
-								/* Bit  0:	reserved */
-	
-/*	GM_GP_CTRL	16 bit r/w	General Purpose Control Register */
-								/* Bit 15:	reserved */
-#define GM_GPCR_PROM_ENA	(1<<14)	/* Bit 14:	Enable Promiscuous Mode */
-#define GM_GPCR_FC_TX_DIS	(1<<13) /* Bit 13:	Disable Tx Flow-Control Mode */
-#define GM_GPCR_TX_ENA		(1<<12) /* Bit 12:	Enable Transmit */
-#define GM_GPCR_RX_ENA		(1<<11) /* Bit 11:	Enable Receive */
-#define GM_GPCR_BURST_ENA	(1<<10)	/* Bit 10:	Enable Burst Mode */
-#define GM_GPCR_LOOP_ENA	(1<<9)	/* Bit  9:	Enable MAC Loopback Mode */
-#define GM_GPCR_PART_ENA	(1<<8)	/* Bit  8:	Enable Partition Mode */
-#define GM_GPCR_GIGS_ENA	(1<<7)	/* Bit  7:	Gigabit Speed (1000 Mbps) */
-#define GM_GPCR_FL_PASS		(1<<6)	/* Bit  6:	Force Link Pass */
-#define GM_GPCR_DUP_FULL	(1<<5)	/* Bit  5:	Full Duplex Mode */
-#define GM_GPCR_FC_RX_DIS	(1<<4)	/* Bit  4:	Disable Rx Flow-Control Mode */
-#define GM_GPCR_SPEED_100	(1<<3)  /* Bit  3:	Port Speed 100 Mbps */
-#define GM_GPCR_AU_DUP_DIS	(1<<2)	/* Bit  2:	Disable Auto-Update Duplex */
-#define GM_GPCR_AU_FCT_DIS	(1<<1)	/* Bit  1:	Disable Auto-Update Flow-C. */
-#define GM_GPCR_AU_SPD_DIS	(1<<0)	/* Bit  0:	Disable Auto-Update Speed */
-
-#define GM_GPCR_SPEED_1000	(GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
-#define GM_GPCR_AU_ALL_DIS	(GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\
-							 GM_GPCR_AU_SPD_DIS)
-	
-/*	GM_TX_CTRL				16 bit r/w	Transmit Control Register */
-#define GM_TXCR_FORCE_JAM	(1<<15)	/* Bit 15:	Force Jam / Flow-Control */
-#define GM_TXCR_CRC_DIS		(1<<14)	/* Bit 14:	Disable insertion of CRC */
-#define GM_TXCR_PAD_DIS		(1<<13)	/* Bit 13:	Disable padding of packets */
-#define GM_TXCR_COL_THR_MSK	(7<<10)	/* Bit 12..10:	Collision Threshold */
-
-#define TX_COL_THR(x)		(SHIFT10(x) & GM_TXCR_COL_THR_MSK)
-
-#define TX_COL_DEF			0x04
-	
-/*	GM_RX_CTRL				16 bit r/w	Receive Control Register */
-#define GM_RXCR_UCF_ENA		(1<<15)	/* Bit 15:	Enable Unicast filtering */
-#define GM_RXCR_MCF_ENA		(1<<14)	/* Bit 14:	Enable Multicast filtering */
-#define GM_RXCR_CRC_DIS		(1<<13)	/* Bit 13:	Remove 4-byte CRC */
-#define GM_RXCR_PASS_FC		(1<<12)	/* Bit 12:	Pass FC packets to FIFO */
-	
-/*	GM_TX_PARAM				16 bit r/w	Transmit Parameter Register */
-#define GM_TXPA_JAMLEN_MSK	(0x03<<14)	/* Bit 15..14:	Jam Length */
-#define GM_TXPA_JAMIPG_MSK	(0x1f<<9)	/* Bit 13..9:	Jam IPG */
-#define GM_TXPA_JAMDAT_MSK	(0x1f<<4)	/* Bit  8..4:	IPG Jam to Data */
-								/* Bit  3..0:	reserved */
-
-#define TX_JAM_LEN_VAL(x)	(SHIFT14(x) & GM_TXPA_JAMLEN_MSK)
-#define TX_JAM_IPG_VAL(x)	(SHIFT9(x) & GM_TXPA_JAMIPG_MSK)
-#define TX_IPG_JAM_DATA(x)	(SHIFT4(x) & GM_TXPA_JAMDAT_MSK)
-
-#define TX_JAM_LEN_DEF		0x03
-#define TX_JAM_IPG_DEF		0x0b
-#define TX_IPG_JAM_DEF		0x1c
-
-/*	GM_SERIAL_MODE			16 bit r/w	Serial Mode Register */
-#define GM_SMOD_DATABL_MSK	(0x1f<<11)	/* Bit 15..11:	Data Blinder (r/o) */
-#define GM_SMOD_LIMIT_4		(1<<10)	/* Bit 10:	4 consecutive Tx trials */
-#define GM_SMOD_VLAN_ENA	(1<<9)	/* Bit  9:	Enable VLAN  (Max. Frame Len) */
-#define GM_SMOD_JUMBO_ENA	(1<<8)	/* Bit  8:	Enable Jumbo (Max. Frame Len) */
-								/* Bit  7..5:	reserved */
-#define GM_SMOD_IPG_MSK		0x1f	/* Bit 4..0:	Inter-Packet Gap (IPG) */
-	
-#define DATA_BLIND_VAL(x)	(SHIFT11(x) & GM_SMOD_DATABL_MSK)
-#define DATA_BLIND_DEF		0x04
-
-#define IPG_DATA_VAL(x)		(x & GM_SMOD_IPG_MSK)
-#define IPG_DATA_DEF		0x1e
-
-/*	GM_SMI_CTRL				16 bit r/w	SMI Control Register */
-#define GM_SMI_CT_PHY_A_MSK	(0x1f<<11)	/* Bit 15..11:	PHY Device Address */
-#define GM_SMI_CT_REG_A_MSK	(0x1f<<6)	/* Bit 10.. 6:	PHY Register Address */
-#define GM_SMI_CT_OP_RD		(1<<5)	/* Bit  5:	OpCode Read (0=Write)*/
-#define GM_SMI_CT_RD_VAL	(1<<4)	/* Bit  4:	Read Valid (Read completed) */
-#define GM_SMI_CT_BUSY		(1<<3)	/* Bit  3:	Busy (Operation in progress) */
-								/* Bit   2..0:	reserved */
-	
-#define GM_SMI_CT_PHY_AD(x)	(SHIFT11(x) & GM_SMI_CT_PHY_A_MSK)
-#define GM_SMI_CT_REG_AD(x)	(SHIFT6(x) & GM_SMI_CT_REG_A_MSK)
-
-	/*	GM_PHY_ADDR				16 bit r/w	GPHY Address Register */
-								/* Bit  15..6:	reserved */
-#define GM_PAR_MIB_CLR		(1<<5)	/* Bit  5:	Set MIB Clear Counter Mode */
-#define GM_PAR_MIB_TST		(1<<4)	/* Bit  4:	MIB Load Counter (Test Mode) */
-								/* Bit   3..0:	reserved */
-	
-/* Receive Frame Status Encoding */
-#define GMR_FS_LEN	(0xffffUL<<16)	/* Bit 31..16:	Rx Frame Length */
-								/* Bit  15..14:	reserved */
-#define GMR_FS_VLAN		(1L<<13)	/* Bit 13:	VLAN Packet */
-#define GMR_FS_JABBER	(1L<<12)	/* Bit 12:	Jabber Packet */
-#define GMR_FS_UN_SIZE	(1L<<11)	/* Bit 11:	Undersize Packet */
-#define GMR_FS_MC		(1L<<10)	/* Bit 10:	Multicast Packet */
-#define GMR_FS_BC		(1L<<9)		/* Bit  9:	Broadcast Packet */
-#define GMR_FS_RX_OK	(1L<<8)		/* Bit  8:	Receive OK (Good Packet) */
-#define GMR_FS_GOOD_FC	(1L<<7)		/* Bit  7:	Good Flow-Control Packet */
-#define GMR_FS_BAD_FC	(1L<<6)		/* Bit  6:	Bad  Flow-Control Packet */
-#define GMR_FS_MII_ERR	(1L<<5)		/* Bit  5:	MII Error */
-#define GMR_FS_LONG_ERR	(1L<<4)		/* Bit  4:	Too Long Packet */
-#define GMR_FS_FRAGMENT	(1L<<3)		/* Bit  3:	Fragment */
-								/* Bit  2:	reserved */
-#define GMR_FS_CRC_ERR	(1L<<1)		/* Bit  1:	CRC Error */
-#define GMR_FS_RX_FF_OV	(1L<<0)		/* Bit  0:	Rx FIFO Overflow */
-
-/*
- * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
- */
-#define GMR_FS_ANY_ERR	(GMR_FS_CRC_ERR | \
-			GMR_FS_LONG_ERR | \
-			GMR_FS_MII_ERR | \
-			GMR_FS_BAD_FC | \
-			GMR_FS_GOOD_FC | \
-			GMR_FS_JABBER)
-
-/* Rx GMAC FIFO Flush Mask (default) */
-#define RX_FF_FL_DEF_MSK	(GMR_FS_CRC_ERR | \
-			GMR_FS_RX_FF_OV | \
-			GMR_FS_MII_ERR | \
-			GMR_FS_BAD_FC | \
-			GMR_FS_GOOD_FC | \
-			GMR_FS_UN_SIZE | \
-			GMR_FS_JABBER)
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
-#endif	/* __INC_XMAC_H */
diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
deleted file mode 100644
index 6e6c56a..0000000
--- a/drivers/net/sk98lin/skaddr.c
+++ /dev/null
@@ -1,1788 +0,0 @@
-/******************************************************************************
- *
- * Name:	skaddr.c
- * Project:	Gigabit Ethernet Adapters, ADDR-Module
- * Version:	$Revision: 1.52 $
- * Date:	$Date: 2003/06/02 13:46:15 $
- * Purpose:	Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage multicast addresses, address override,
- * and promiscuous mode on GEnesis and Yukon adapters.
- *
- * Address Layout:
- *	port address:		physical MAC address
- *	1st exact match:	logical MAC address (GEnesis only)
- *	2nd exact match:	RLMT multicast (GEnesis only)
- *	exact match 3-13:	OS-specific multicasts (GEnesis only)
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell.";
-#endif /* DEBUG ||!LINT || !SK_SLIM */
-
-#define __SKADDR_C
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* defines ********************************************************************/
-
-
-#define XMAC_POLY	0xEDB88320UL	/* CRC32-Poly - XMAC: Little Endian */
-#define GMAC_POLY	0x04C11DB7L	/* CRC16-Poly - GMAC: Little Endian */
-#define HASH_BITS	6				/* #bits in hash */
-#define	SK_MC_BIT	0x01
-
-/* Error numbers and messages. */
-
-#define SKERR_ADDR_E001		(SK_ERRBASE_ADDR + 0)
-#define SKERR_ADDR_E001MSG	"Bad Flags."
-#define SKERR_ADDR_E002		(SKERR_ADDR_E001 + 1)
-#define SKERR_ADDR_E002MSG	"New Error."
-
-/* typedefs *******************************************************************/
-
-/* None. */
-
-/* global variables ***********************************************************/
-
-/* 64-bit hash values with all bits set. */
-
-static const SK_U16	OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
-
-/* local variables ************************************************************/
-
-#ifdef DEBUG
-static int	Next0[SK_MAX_MACS] = {0};
-#endif	/* DEBUG */
-
-static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			   SK_MAC_ADDR *pMc, int Flags);
-static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			     int Flags);
-static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
-static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
-				       SK_U32 PortNumber, int NewPromMode);
-static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			   SK_MAC_ADDR *pMc, int Flags);
-static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
-			     int Flags);
-static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
-static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
-				       SK_U32 PortNumber, int NewPromMode);
-
-/* functions ******************************************************************/
-
-/******************************************************************************
- *
- *	SkAddrInit - initialize data, set state to init
- *
- * Description:
- *
- *	SK_INIT_DATA
- *	============
- *
- *	This routine clears the multicast tables and resets promiscuous mode.
- *	Some entries are reserved for the "logical MAC address", the
- *	SK-RLMT multicast address, and the BPDU multicast address.
- *
- *
- *	SK_INIT_IO
- *	==========
- *
- *	All permanent MAC addresses are read from EPROM.
- *	If the current MAC addresses are not already set in software,
- *	they are set to the values of the permanent addresses.
- *	The current addresses are written to the corresponding MAC.
- *
- *
- *	SK_INIT_RUN
- *	===========
- *
- *	Nothing.
- *
- * Context:
- *	init, pageable
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- */
-int	SkAddrInit(
-SK_AC	*pAC,	/* the adapter context */
-SK_IOC	IoC,	/* I/O context */
-int		Level)	/* initialization level */
-{
-	int			j;
-	SK_U32		i;
-	SK_U8		*InAddr;
-	SK_U16		*OutAddr;
-	SK_ADDR_PORT	*pAPort;
-
-	switch (Level) {
-	case SK_INIT_DATA:
-		SK_MEMSET((char *) &pAC->Addr, (SK_U8) 0,
-            (SK_U16) sizeof(SK_ADDR));
-
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			pAPort = &pAC->Addr.Port[i];
-			pAPort->PromMode = SK_PROM_MODE_NONE;
-			
-			pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
-			pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
-			pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
-			pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
-		}
-#ifdef xDEBUG
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
-				SK_ADDR_FIRST_MATCH_RLMT) {
-				Next0[i] |= 4;
-			}
-		}
-#endif	/* DEBUG */
-		/* pAC->Addr.InitDone = SK_INIT_DATA; */
-		break;
-
-    case SK_INIT_IO:
-#ifndef SK_NO_RLMT
-		for (i = 0; i < SK_MAX_NETS; i++) {
-			pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
-		}
-#endif /* !SK_NO_RLMT */
-#ifdef xDEBUG
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
-				SK_ADDR_FIRST_MATCH_RLMT) {
-				Next0[i] |= 8;
-			}
-		}
-#endif	/* DEBUG */
-		
-		/* Read permanent logical MAC address from Control Register File. */
-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-			InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
-			SK_IN8(IoC, B2_MAC_1 + j, InAddr);
-		}
-
-		if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
-			/* Set the current logical MAC address to the permanent one. */
-			pAC->Addr.Net[0].CurrentMacAddress =
-				pAC->Addr.Net[0].PermanentMacAddress;
-			pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
-		}
-
-		/* Set the current logical MAC address. */
-		pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
-			pAC->Addr.Net[0].CurrentMacAddress;
-#if SK_MAX_NETS > 1
-		/* Set logical MAC address for net 2 to (log | 3). */
-		if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
-			pAC->Addr.Net[1].PermanentMacAddress =
-				pAC->Addr.Net[0].PermanentMacAddress;
-			pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
-			/* Set the current logical MAC address to the permanent one. */
-			pAC->Addr.Net[1].CurrentMacAddress =
-				pAC->Addr.Net[1].PermanentMacAddress;
-			pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
-		}
-#endif	/* SK_MAX_NETS > 1 */
-
-#ifdef DEBUG
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
-					i,
-					pAC->Addr.Net[i].PermanentMacAddress.a[0],
-					pAC->Addr.Net[i].PermanentMacAddress.a[1],
-					pAC->Addr.Net[i].PermanentMacAddress.a[2],
-					pAC->Addr.Net[i].PermanentMacAddress.a[3],
-					pAC->Addr.Net[i].PermanentMacAddress.a[4],
-					pAC->Addr.Net[i].PermanentMacAddress.a[5]))
-			
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
-					i,
-					pAC->Addr.Net[i].CurrentMacAddress.a[0],
-					pAC->Addr.Net[i].CurrentMacAddress.a[1],
-					pAC->Addr.Net[i].CurrentMacAddress.a[2],
-					pAC->Addr.Net[i].CurrentMacAddress.a[3],
-					pAC->Addr.Net[i].CurrentMacAddress.a[4],
-					pAC->Addr.Net[i].CurrentMacAddress.a[5]))
-		}
-#endif	/* DEBUG */
-
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			pAPort = &pAC->Addr.Port[i];
-
-			/* Read permanent port addresses from Control Register File. */
-			for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-				InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
-				SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
-			}
-
-			if (!pAPort->CurrentMacAddressSet) {
-				/*
-				 * Set the current and previous physical MAC address
-				 * of this port to its permanent MAC address.
-				 */
-				pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
-				pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
-				pAPort->CurrentMacAddressSet = SK_TRUE;
-			}
-
-			/* Set port's current physical MAC address. */
-			OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-#ifdef GENESIS
-			if (pAC->GIni.GIGenesis) {
-				XM_OUTADDR(IoC, i, XM_SA, OutAddr);
-			}
-#endif /* GENESIS */
-#ifdef YUKON
-			if (!pAC->GIni.GIGenesis) {
-				GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
-			}
-#endif /* YUKON */
-#ifdef DEBUG
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-					pAPort->PermanentMacAddress.a[0],
-					pAPort->PermanentMacAddress.a[1],
-					pAPort->PermanentMacAddress.a[2],
-					pAPort->PermanentMacAddress.a[3],
-					pAPort->PermanentMacAddress.a[4],
-					pAPort->PermanentMacAddress.a[5]))
-			
-			SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
-				("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-					pAPort->CurrentMacAddress.a[0],
-					pAPort->CurrentMacAddress.a[1],
-					pAPort->CurrentMacAddress.a[2],
-					pAPort->CurrentMacAddress.a[3],
-					pAPort->CurrentMacAddress.a[4],
-					pAPort->CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-		}
-		/* pAC->Addr.InitDone = SK_INIT_IO; */
-		break;
-
-	case SK_INIT_RUN:
-#ifdef xDEBUG
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			if (pAC->Addr.Port[i].NextExactMatchRlmt <
-				SK_ADDR_FIRST_MATCH_RLMT) {
-				Next0[i] |= 16;
-			}
-		}
-#endif	/* DEBUG */
-
-		/* pAC->Addr.InitDone = SK_INIT_RUN; */
-		break;
-
-	default:	/* error */
-		break;
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrInit */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrMcClear - clear the multicast table
- *
- * Description:
- *	This routine clears the multicast table.
- *
- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- *	immediately.
- *
- *	It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
- *	to the adapter in use. The real work is done there.
- *
- * Context:
- *	runtime, pageable
- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- *	may be called after SK_INIT_IO without limitation
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrMcClear(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber,	/* Index of affected port */
-int		Flags)		/* permanent/non-perm, sw-only */
-{
-	int ReturnCode;
-	
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-	
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
-	}
-	else {
-		ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
-	}
-
-	return (ReturnCode);
-
-}	/* SkAddrMcClear */
-
-#endif /* !SK_SLIM */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrXmacMcClear - clear the multicast table
- *
- * Description:
- *	This routine clears the multicast table
- *	(either entry 2 or entries 3-16 and InexactFilter) of the given port.
- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- *	immediately.
- *
- * Context:
- *	runtime, pageable
- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- *	may be called after SK_INIT_IO without limitation
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrXmacMcClear(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber,	/* Index of affected port */
-int		Flags)		/* permanent/non-perm, sw-only */
-{
-	int i;
-
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-
-		/* Clear RLMT multicast addresses. */
-		pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
-	}
-	else {	/* not permanent => DRV */
-
-		/* Clear InexactFilter */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
-		}
-
-		/* Clear DRV multicast addresses. */
-
-		pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
-	}
-
-	if (!(Flags & SK_MC_SW_ONLY)) {
-		(void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrXmacMcClear */
-
-#endif /* !SK_SLIM */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrGmacMcClear - clear the multicast table
- *
- * Description:
- *	This routine clears the multicast hashing table (InexactFilter)
- *	(either the RLMT or the driver bits) of the given port.
- *
- *	If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- *	immediately.
- *
- * Context:
- *	runtime, pageable
- *	may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- *	may be called after SK_INIT_IO without limitation
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrGmacMcClear(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber,	/* Index of affected port */
-int		Flags)		/* permanent/non-perm, sw-only */
-{
-	int i;
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
-#endif	/* DEBUG */
-
-	/* Clear InexactFilter */
-	for (i = 0; i < 8; i++) {
-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
-	}
-	
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-		
-		/* Copy DRV bits to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
-			
-			/* Clear InexactRlmtFilter. */
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
-
-		}		
-	}
-	else {	/* not permanent => DRV */
-		
-		/* Copy RLMT bits to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
-			
-			/* Clear InexactDrvFilter. */
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
-		}
-	}
-	
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
-#endif	/* DEBUG */
-	
-	if (!(Flags & SK_MC_SW_ONLY)) {
-		(void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
-	}
-	
-	return (SK_ADDR_SUCCESS);
-
-}	/* SkAddrGmacMcClear */
-
-#ifndef SK_ADDR_CHEAT
-
-/******************************************************************************
- *
- *	SkXmacMcHash - hash multicast address
- *
- * Description:
- *	This routine computes the hash value for a multicast address.
- *	A CRC32 algorithm is used.
- *
- * Notes:
- *	The code was adapted from the XaQti data sheet.
- *
- * Context:
- *	runtime, pageable
- *
- * Returns:
- *	Hash value of multicast address.
- */
-static SK_U32 SkXmacMcHash(
-unsigned char *pMc)	/* Multicast address */
-{
-	SK_U32 Idx;
-	SK_U32 Bit;
-	SK_U32 Data;
-	SK_U32 Crc;
-
-	Crc = 0xFFFFFFFFUL;
-	for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
-		Data = *pMc++;
-		for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
-			Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
-		}
-	}
-
-	return (Crc & ((1 << HASH_BITS) - 1));
-
-}	/* SkXmacMcHash */
-
-
-/******************************************************************************
- *
- *	SkGmacMcHash - hash multicast address
- *
- * Description:
- *	This routine computes the hash value for a multicast address.
- *	A CRC16 algorithm is used.
- *
- * Notes:
- *
- *
- * Context:
- *	runtime, pageable
- *
- * Returns:
- *	Hash value of multicast address.
- */
-static SK_U32 SkGmacMcHash(
-unsigned char *pMc)	/* Multicast address */
-{
-	SK_U32 Data;
-	SK_U32 TmpData;
-	SK_U32 Crc;
-	int Byte;
-	int Bit;
-
-	Crc = 0xFFFFFFFFUL;
-	for (Byte = 0; Byte < 6; Byte++) {
-		/* Get next byte. */
-		Data = (SK_U32) pMc[Byte];
-		
-		/* Change bit order in byte. */
-		TmpData = Data;
-		for (Bit = 0; Bit < 8; Bit++) {
-			if (TmpData & 1L) {
-				Data |=  1L << (7 - Bit);
-			}
-			else {
-				Data &= ~(1L << (7 - Bit));
-			}
-			TmpData >>= 1;
-		}
-		
-		Crc ^= (Data << 24);
-		for (Bit = 0; Bit < 8; Bit++) {
-			if (Crc & 0x80000000) {
-				Crc = (Crc << 1) ^ GMAC_POLY;
-			}
-			else {
-				Crc <<= 1;
-			}
-		}
-	}
-	
-	return (Crc & ((1 << HASH_BITS) - 1));
-
-}	/* SkGmacMcHash */
-
-#endif	/* !SK_ADDR_CHEAT */
-
-/******************************************************************************
- *
- *	SkAddrMcAdd - add a multicast address to a port
- *
- * Description:
- *	This routine enables reception for a given address on the given port.
- *
- *	It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
- *	adapter in use. The real work is done there.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_DATA
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_MC_ILLEGAL_ADDRESS
- *	SK_MC_ILLEGAL_PORT
- *	SK_MC_RLMT_OVERFLOW
- */
-int	SkAddrMcAdd(
-SK_AC		*pAC,		/* adapter context */
-SK_IOC		IoC,		/* I/O context */
-SK_U32		PortNumber,	/* Port Number */
-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
-int			Flags)		/* permanent/non-permanent */
-{
-	int ReturnCode;
-	
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-	
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
-	}
-	else {
-		ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
-	}
-
-	return (ReturnCode);
-
-}	/* SkAddrMcAdd */
-
-
-/******************************************************************************
- *
- *	SkAddrXmacMcAdd - add a multicast address to a port
- *
- * Description:
- *	This routine enables reception for a given address on the given port.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- *	The multicast bit is only checked if there are no free exact match
- *	entries.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_DATA
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_MC_ILLEGAL_ADDRESS
- *	SK_MC_RLMT_OVERFLOW
- */
-static int	SkAddrXmacMcAdd(
-SK_AC		*pAC,		/* adapter context */
-SK_IOC		IoC,		/* I/O context */
-SK_U32		PortNumber,	/* Port Number */
-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
-int		Flags)		/* permanent/non-permanent */
-{
-	int	i;
-	SK_U8	Inexact;
-#ifndef SK_ADDR_CHEAT
-	SK_U32 HashBit;
-#endif	/* !defined(SK_ADDR_CHEAT) */
-
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-#ifdef xDEBUG
-		if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
-			SK_ADDR_FIRST_MATCH_RLMT) {
-			Next0[PortNumber] |= 1;
-			return (SK_MC_RLMT_OVERFLOW);
-		}
-#endif	/* DEBUG */
-		
-		if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
-			SK_ADDR_LAST_MATCH_RLMT) {
-			return (SK_MC_RLMT_OVERFLOW);
-		}
-
-		/* Set a RLMT multicast address. */
-
-		pAC->Addr.Port[PortNumber].Exact[
-			pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
-
-		return (SK_MC_FILTERING_EXACT);
-	}
-
-#ifdef xDEBUG
-	if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
-		SK_ADDR_FIRST_MATCH_DRV) {
-			Next0[PortNumber] |= 2;
-		return (SK_MC_RLMT_OVERFLOW);
-	}
-#endif	/* DEBUG */
-	
-	if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
-
-		/* Set exact match entry. */
-		pAC->Addr.Port[PortNumber].Exact[
-			pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
-
-		/* Clear InexactFilter */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
-		}
-	}
-	else {
-		if (!(pMc->a[0] & SK_MC_BIT)) {
-			/* Hashing only possible with multicast addresses */
-			return (SK_MC_ILLEGAL_ADDRESS);
-		}
-#ifndef SK_ADDR_CHEAT
-		/* Compute hash value of address. */
-		HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
-
-		/* Add bit to InexactFilter. */
-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
-			1 << (HashBit % 8);
-#else	/* SK_ADDR_CHEAT */
-		/* Set all bits in InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
-		}
-#endif	/* SK_ADDR_CHEAT */
-	}
-
-	for (Inexact = 0, i = 0; i < 8; i++) {
-		Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
-	}
-
-	if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
-		return (SK_MC_FILTERING_EXACT);
-	}
-	else {
-		return (SK_MC_FILTERING_INEXACT);
-	}
-
-}	/* SkAddrXmacMcAdd */
-
-
-/******************************************************************************
- *
- *	SkAddrGmacMcAdd - add a multicast address to a port
- *
- * Description:
- *	This routine enables reception for a given address on the given port.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_DATA
- *
- * Returns:
- *	SK_MC_FILTERING_INEXACT
- *	SK_MC_ILLEGAL_ADDRESS
- */
-static int	SkAddrGmacMcAdd(
-SK_AC		*pAC,		/* adapter context */
-SK_IOC		IoC,		/* I/O context */
-SK_U32		PortNumber,	/* Port Number */
-SK_MAC_ADDR	*pMc,		/* multicast address to be added */
-int		Flags)		/* permanent/non-permanent */
-{
-	int	i;
-#ifndef SK_ADDR_CHEAT
-	SK_U32 HashBit;
-#endif	/* !defined(SK_ADDR_CHEAT) */
-		
-	if (!(pMc->a[0] & SK_MC_BIT)) {
-		/* Hashing only possible with multicast addresses */
-		return (SK_MC_ILLEGAL_ADDRESS);
-	}
-	
-#ifndef SK_ADDR_CHEAT
-	
-	/* Compute hash value of address. */
-	HashBit = SkGmacMcHash(&pMc->a[0]);
-	
-	if (Flags & SK_ADDR_PERMANENT) {	/* permanent => RLMT */
-		
-		/* Add bit to InexactRlmtFilter. */
-		pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
-			1 << (HashBit % 8);
-		
-		/* Copy bit to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
-		}
-#ifdef DEBUG
-		SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
-#endif	/* DEBUG */
-	}
-	else {	/* not permanent => DRV */
-		
-		/* Add bit to InexactDrvFilter. */
-		pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
-			1 << (HashBit % 8);
-		
-		/* Copy bit to InexactFilter. */
-		for (i = 0; i < 8; i++) {
-			pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
-				pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
-		}
-#ifdef DEBUG
-		SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
-			pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
-#endif	/* DEBUG */
-	}
-	
-#else	/* SK_ADDR_CHEAT */
-	
-	/* Set all bits in InexactFilter. */
-	for (i = 0; i < 8; i++) {
-		pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
-	}
-#endif	/* SK_ADDR_CHEAT */
-		
-	return (SK_MC_FILTERING_INEXACT);
-	
-}	/* SkAddrGmacMcAdd */
-
-#endif /* !SK_SLIM */
-
-/******************************************************************************
- *
- *	SkAddrMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- *	This routine enables reception of the addresses contained in a local
- *	table for a given port.
- *	It also programs the port's current physical MAC address.
- *
- *	It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
- *	to the adapter in use. The real work is done there.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrMcUpdate(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber)	/* Port Number */
-{
-	int ReturnCode = 0;
-#if (!defined(SK_SLIM) || defined(DEBUG))
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-#endif /* !SK_SLIM || DEBUG */
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
-	}
-#endif /* GENESIS */
-#ifdef YUKON
-	if (!pAC->GIni.GIGenesis) {
-		ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
-	}
-#endif /* YUKON */
-	return (ReturnCode);
-
-}	/* SkAddrMcUpdate */
-
-
-#ifdef GENESIS
-
-/******************************************************************************
- *
- *	SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- *	This routine enables reception of the addresses contained in a local
- *	table for a given port.
- *	It also programs the port's current physical MAC address.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrXmacMcUpdate(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber)	/* Port Number */
-{
-	SK_U32		i;
-	SK_U8		Inexact;
-	SK_U16		*OutAddr;
-	SK_ADDR_PORT	*pAPort;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
-	
-	pAPort = &pAC->Addr.Port[PortNumber];
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
-#endif /* DEBUG */
-
-	/* Start with 0 to also program the logical MAC address. */
-	for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
-		/* Set exact match address i on XMAC */
-		OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
-		XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
-	}
-
-	/* Clear other permanent exact match addresses on XMAC */
-	if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
-		
-		SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
-			SK_ADDR_LAST_MATCH_RLMT);
-	}
-
-	for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
-		OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
-		XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
-	}
-
-	/* Clear other non-permanent exact match addresses on XMAC */
-	if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
-		
-		SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
-			SK_ADDR_LAST_MATCH_DRV);
-	}
-
-	for (Inexact = 0, i = 0; i < 8; i++) {
-		Inexact |= pAPort->InexactFilter.Bytes[i];
-	}
-
-	if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
-		
-		/* Set all bits in 64-bit hash register. */
-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if (Inexact != 0) {
-		
-		/* Set 64-bit hash register to InexactFilter. */
-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else {
-		/* Disable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
-	}
-
-	if (pAPort->PromMode != SK_PROM_MODE_NONE) {
-		(void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
-	}
-
-	/* Set port's current physical MAC address. */
-	OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-	
-	XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
-
-#ifdef xDEBUG
-	for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
-		SK_U8		InAddr8[6];
-		SK_U16		*InAddr;
-
-		/* Get exact match address i from port PortNumber. */
-		InAddr = (SK_U16 *) &InAddr8[0];
-		
-		XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
-		
-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-			("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
-			 "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
-				i,
-				PortNumber,
-				InAddr8[0],
-				InAddr8[1],
-				InAddr8[2],
-				InAddr8[3],
-				InAddr8[4],
-				InAddr8[5],
-				pAPort->Exact[i].a[0],
-				pAPort->Exact[i].a[1],
-				pAPort->Exact[i].a[2],
-				pAPort->Exact[i].a[3],
-				pAPort->Exact[i].a[4],
-				pAPort->Exact[i].a[5]))
-	}
-#endif /* DEBUG */
-
-	/* Determine return value. */
-	if (Inexact == 0 && pAPort->PromMode == 0) {
-		return (SK_MC_FILTERING_EXACT);
-	}
-	else {
-		return (SK_MC_FILTERING_INEXACT);
-	}
-	
-}	/* SkAddrXmacMcUpdate */
-
-#endif  /* GENESIS */
-
-#ifdef YUKON
-
-/******************************************************************************
- *
- *	SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- *	This routine enables reception of the addresses contained in a local
- *	table for a given port.
- *	It also programs the port's current physical MAC address.
- *
- * Notes:
- *	The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_MC_FILTERING_EXACT
- *	SK_MC_FILTERING_INEXACT
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrGmacMcUpdate(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* I/O context */
-SK_U32	PortNumber)	/* Port Number */
-{
-#ifndef SK_SLIM
-	SK_U32		i;
-	SK_U8		Inexact;
-#endif	/* not SK_SLIM */
-	SK_U16		*OutAddr;
-	SK_ADDR_PORT	*pAPort;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
-	
-	pAPort = &pAC->Addr.Port[PortNumber];
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
-#endif /* DEBUG */
-	
-#ifndef SK_SLIM
-	for (Inexact = 0, i = 0; i < 8; i++) {
-		Inexact |= pAPort->InexactFilter.Bytes[i];
-	}
-	
-	/* Set 64-bit hash register to InexactFilter. */
-	GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
-		&pAPort->InexactFilter.Bytes[0]);
-	
-	if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {				
-		
-		/* Set all bits in 64-bit hash register. */
-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else {	
-		/* Enable Hashing. */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	
-	if (pAPort->PromMode != SK_PROM_MODE_NONE) {
-		(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
-	}
-#else /* SK_SLIM */
-
-	/* Set all bits in 64-bit hash register. */
-	GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-
-	/* Enable Hashing */
-	SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	
-	(void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
-	
-#endif /* SK_SLIM */
-	
-	/* Set port's current physical MAC address. */
-	OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-	GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
-	
-	/* Set port's current logical MAC address. */
-	OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
-	GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
-	
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-			pAPort->Exact[0].a[0],
-			pAPort->Exact[0].a[1],
-			pAPort->Exact[0].a[2],
-			pAPort->Exact[0].a[3],
-			pAPort->Exact[0].a[4],
-			pAPort->Exact[0].a[5]))
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-		("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-			pAPort->CurrentMacAddress.a[0],
-			pAPort->CurrentMacAddress.a[1],
-			pAPort->CurrentMacAddress.a[2],
-			pAPort->CurrentMacAddress.a[3],
-			pAPort->CurrentMacAddress.a[4],
-			pAPort->CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-	
-#ifndef SK_SLIM
-	/* Determine return value. */
-	if (Inexact == 0 && pAPort->PromMode == 0) {
-		return (SK_MC_FILTERING_EXACT);
-	}
-	else {
-		return (SK_MC_FILTERING_INEXACT);
-	}
-#else /* SK_SLIM */
-	return (SK_MC_FILTERING_INEXACT);
-#endif /* SK_SLIM */
-	
-}	/* SkAddrGmacMcUpdate */
-
-#endif /* YUKON */
-
-#ifndef SK_NO_MAO
-
-/******************************************************************************
- *
- *	SkAddrOverride - override a port's MAC address
- *
- * Description:
- *	This routine overrides the MAC address of one port.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS if successful.
- *	SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
- *	SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
- *	SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
- */
-int	SkAddrOverride(
-SK_AC		*pAC,				/* adapter context */
-SK_IOC		IoC,				/* I/O context */
-SK_U32		PortNumber,			/* Port Number */
-SK_MAC_ADDR	SK_FAR *pNewAddr,	/* new MAC address */
-int			Flags)				/* logical/physical MAC address */
-{
-#ifndef SK_NO_RLMT
-	SK_EVPARA	Para;
-#endif /* !SK_NO_RLMT */
-	SK_U32		NetNumber;
-	SK_U32		i;
-	SK_U16		SK_FAR *OutAddr;
-
-#ifndef SK_NO_RLMT
-	NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
-#else
-	NetNumber = 0;
-#endif /* SK_NO_RLMT */
-#if (!defined(SK_SLIM) || defined(DEBUG))
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-#endif /* !SK_SLIM || DEBUG */
-	if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
-		return (SK_ADDR_MULTICAST_ADDRESS);
-	}
-
-	if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
-		return (SK_ADDR_TOO_EARLY);
-	}
-
-	if (Flags & SK_ADDR_SET_LOGICAL) {	/* Activate logical MAC address. */
-		/* Parameter *pNewAddr is ignored. */
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-		}
-#ifndef SK_NO_RLMT
-		/* Set PortNumber to number of net's active port. */
-		PortNumber = pAC->Rlmt.Net[NetNumber].
-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
-		pAC->Addr.Port[PortNumber].Exact[0] =
-			pAC->Addr.Net[NetNumber].CurrentMacAddress;
-
-		/* Write address to first exact match entry of active port. */
-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
-	}
-	else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
-		/* Deactivate logical MAC address. */
-		/* Parameter *pNewAddr is ignored. */
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-		}
-#ifndef SK_NO_RLMT
-		/* Set PortNumber to number of net's active port. */
-		PortNumber = pAC->Rlmt.Net[NetNumber].
-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
-			pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
-		}
-
-		/* Write address to first exact match entry of active port. */
-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
-	}
-	else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) {	/* Physical MAC address. */
-		if (SK_ADDR_EQUAL(pNewAddr->a,
-			pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
-			return (SK_ADDR_DUPLICATE_ADDRESS);
-		}
-
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-
-			if (SK_ADDR_EQUAL(pNewAddr->a,
-				pAC->Addr.Port[i].CurrentMacAddress.a)) {
-				if (i == PortNumber) {
-					return (SK_ADDR_SUCCESS);
-				}
-				else {
-					return (SK_ADDR_DUPLICATE_ADDRESS);
-				}
-			}
-		}
-
-		pAC->Addr.Port[PortNumber].PreviousMacAddress =
-			pAC->Addr.Port[PortNumber].CurrentMacAddress;
-		pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
-
-		/* Change port's physical MAC address. */
-		OutAddr = (SK_U16 SK_FAR *) pNewAddr;
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
-		}
-#endif /* GENESIS */
-#ifdef YUKON
-		if (!pAC->GIni.GIGenesis) {
-			GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
-		}
-#endif /* YUKON */
-
-#ifndef SK_NO_RLMT
-		/* Report address change to RLMT. */
-		Para.Para32[0] = PortNumber;
-		Para.Para32[0] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
-#endif /* !SK_NO_RLMT */
-	}
-	else {	/* Logical MAC address. */
-		if (SK_ADDR_EQUAL(pNewAddr->a,
-			pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
-			return (SK_ADDR_SUCCESS);
-		}
-		
-		for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
-			if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
-				return (SK_ADDR_TOO_EARLY);
-			}
-
-			if (SK_ADDR_EQUAL(pNewAddr->a,
-				pAC->Addr.Port[i].CurrentMacAddress.a)) {
-				return (SK_ADDR_DUPLICATE_ADDRESS);
-			}
-		}
-		
-		/*
-		 * In case that the physical and the logical MAC addresses are equal
-		 * we must also change the physical MAC address here.
-		 * In this case we have an adapter which initially was programmed with
-		 * two identical MAC addresses.
-		 */
-		if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
-				pAC->Addr.Port[PortNumber].Exact[0].a)) {
-			
-			pAC->Addr.Port[PortNumber].PreviousMacAddress =
-				pAC->Addr.Port[PortNumber].CurrentMacAddress;
-			pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
-			
-#ifndef SK_NO_RLMT
-			/* Report address change to RLMT. */
-			Para.Para32[0] = PortNumber;
-			Para.Para32[0] = -1;
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
-#endif /* !SK_NO_RLMT */
-		}
-		
-#ifndef SK_NO_RLMT
-		/* Set PortNumber to number of net's active port. */
-		PortNumber = pAC->Rlmt.Net[NetNumber].
-			Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
-		pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
-		pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
-#ifdef DEBUG
-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-			("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
-				pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
-		
-		SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
-			("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
-				pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-
-        /* Write address to first exact match entry of active port. */
-		(void) SkAddrMcUpdate(pAC, IoC, PortNumber);
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrOverride */
-
-
-#endif /* SK_NO_MAO */
-
-/******************************************************************************
- *
- *	SkAddrPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- *	This routine manages promiscuous mode:
- *	- none
- *	- all LLC frames
- *	- all MC frames
- *
- *	It calls either SkAddrXmacPromiscuousChange or
- *	SkAddrGmacPromiscuousChange, according to the adapter in use.
- *	The real work is done there.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrPromiscuousChange(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
-int		NewPromMode)	/* new promiscuous mode */
-{
-	int ReturnCode = 0;
-#if (!defined(SK_SLIM) || defined(DEBUG))
-	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-#endif /* !SK_SLIM || DEBUG */
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		ReturnCode =
-			SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
-	}
-#endif /* GENESIS */
-#ifdef YUKON
-	if (!pAC->GIni.GIGenesis) {
-		ReturnCode =
-			SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
-	}
-#endif /* YUKON */
-
-	return (ReturnCode);
-
-}	/* SkAddrPromiscuousChange */
-
-#ifdef GENESIS
-
-/******************************************************************************
- *
- *	SkAddrXmacPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- *	This routine manages promiscuous mode:
- *	- none
- *	- all LLC frames
- *	- all MC frames
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrXmacPromiscuousChange(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
-int		NewPromMode)	/* new promiscuous mode */
-{
-	int			i;
-	SK_BOOL		InexactModeBit;
-	SK_U8		Inexact;
-	SK_U8		HwInexact;
-	SK_FILTER64	HwInexactFilter;
-	SK_U16		LoMode;		/* Lower 16 bits of XMAC Mode Register. */
-	int			CurPromMode = SK_PROM_MODE_NONE;
-
-	/* Read CurPromMode from Hardware. */
-	XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
-
-	if ((LoMode & XM_MD_ENA_PROM) != 0) {
-		/* Promiscuous mode! */
-		CurPromMode |= SK_PROM_MODE_LLC;
-	}
-	
-	for (Inexact = 0xFF, i = 0; i < 8; i++) {
-		Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
-	}
-	if (Inexact == 0xFF) {
-		CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
-	}
-	else {
-		/* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
-		XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
-		
-		InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
-
-		/* Read 64-bit hash register from XMAC */
-		XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
-
-		for (HwInexact = 0xFF, i = 0; i < 8; i++) {
-			HwInexact &= HwInexactFilter.Bytes[i];
-		}
-
-		if (InexactModeBit && (HwInexact == 0xFF)) {
-			CurPromMode |= SK_PROM_MODE_ALL_MC;
-		}
-	}
-
-	pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
-
-	if (NewPromMode == CurPromMode) {
-		return (SK_ADDR_SUCCESS);
-	}
-
-	if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(CurPromMode & SK_PROM_MODE_ALL_MC)) {	/* All MC. */
-		
-		/* Set all bits in 64-bit hash register. */
-		XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
-
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(NewPromMode & SK_PROM_MODE_ALL_MC)) {	/* Norm MC. */
-		for (Inexact = 0, i = 0; i < 8; i++) {
-			Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
-		}
-		if (Inexact == 0) {
-			/* Disable Hashing */
-			SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
-		}
-		else {
-			/* Set 64-bit hash register to InexactFilter. */
-			XM_OUTHASH(IoC, PortNumber, XM_HSM,
-				&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
-
-			/* Enable Hashing */
-			SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-		}
-	}
-
-	if ((NewPromMode & SK_PROM_MODE_LLC) &&
-		!(CurPromMode & SK_PROM_MODE_LLC)) {	/* Prom. LLC */
-		/* Set the MAC in Promiscuous Mode */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if ((CurPromMode & SK_PROM_MODE_LLC) &&
-		!(NewPromMode & SK_PROM_MODE_LLC)) {	/* Norm. LLC. */
-		/* Clear Promiscuous Mode */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
-	}
-	
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrXmacPromiscuousChange */
-
-#endif /* GENESIS */
-
-#ifdef YUKON
-
-/******************************************************************************
- *
- *	SkAddrGmacPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- *	This routine manages promiscuous mode:
- *	- none
- *	- all LLC frames
- *	- all MC frames
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-static int	SkAddrGmacPromiscuousChange(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	PortNumber,		/* port whose promiscuous mode changes */
-int		NewPromMode)	/* new promiscuous mode */
-{
-	SK_U16		ReceiveControl;	/* GMAC Receive Control Register */
-	int		CurPromMode = SK_PROM_MODE_NONE;
-
-	/* Read CurPromMode from Hardware. */
-	GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
-
-	if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
-		/* Promiscuous mode! */
-		CurPromMode |= SK_PROM_MODE_LLC;
-	}
-
-	if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
-		/* All Multicast mode! */
-		CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
-	}
-
-	pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
-
-	if (NewPromMode == CurPromMode) {
-		return (SK_ADDR_SUCCESS);
-	}
-	
-	if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(CurPromMode & SK_PROM_MODE_ALL_MC)) {	/* All MC */
-		
-		/* Set all bits in 64-bit hash register. */
-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-		
-		/* Enable Hashing */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	
-	if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
-		!(NewPromMode & SK_PROM_MODE_ALL_MC)) {	/* Norm. MC */
-
-		/* Set 64-bit hash register to InexactFilter. */
-		GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
-			&pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
-
-		/* Enable Hashing. */
-		SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-
-	if ((NewPromMode & SK_PROM_MODE_LLC) &&
-		!(CurPromMode & SK_PROM_MODE_LLC)) {	/* Prom. LLC */
-		
-		/* Set the MAC to Promiscuous Mode. */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
-	}
-	else if ((CurPromMode & SK_PROM_MODE_LLC) &&
-		!(NewPromMode & SK_PROM_MODE_LLC)) {	/* Norm. LLC */
-		
-		/* Clear Promiscuous Mode. */
-		SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
-	}
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrGmacPromiscuousChange */
-
-#endif /* YUKON */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- *	SkAddrSwap - swap address info
- *
- * Description:
- *	This routine swaps address info of two ports.
- *
- * Context:
- *	runtime, pageable
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	SK_ADDR_SUCCESS
- *	SK_ADDR_ILLEGAL_PORT
- */
-int	SkAddrSwap(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* I/O context */
-SK_U32	FromPortNumber,		/* Port1 Index */
-SK_U32	ToPortNumber)		/* Port2 Index */
-{
-	int			i;
-	SK_U8		Byte;
-	SK_MAC_ADDR	MacAddr;
-	SK_U32		DWord;
-
-	if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-
-	if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-
-	if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
-		return (SK_ADDR_ILLEGAL_PORT);
-	}
-
-	/*
-	 * Swap:
-	 * - Exact Match Entries (GEnesis and Yukon)
-	 *   Yukon uses first entry for the logical MAC
-	 *   address (stored in the second GMAC register).
-	 * - FirstExactMatchRlmt (GEnesis only)
-	 * - NextExactMatchRlmt (GEnesis only)
-	 * - FirstExactMatchDrv (GEnesis only)
-	 * - NextExactMatchDrv (GEnesis only)
-	 * - 64-bit filter (InexactFilter)
-	 * - Promiscuous Mode
-	 * of ports.
-	 */
-
-	for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
-		MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
-		pAC->Addr.Port[FromPortNumber].Exact[i] =
-			pAC->Addr.Port[ToPortNumber].Exact[i];
-		pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
-	}
-
-	for (i = 0; i < 8; i++) {
-		Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
-		pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
-			pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
-		pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
-	}
-	
-	i = pAC->Addr.Port[FromPortNumber].PromMode;
-	pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
-	pAC->Addr.Port[ToPortNumber].PromMode = i;
-	
-	if (pAC->GIni.GIGenesis) {
-		DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
-		pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
-			pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
-		pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
-		
-		DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
-		pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
-			pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
-		pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
-		
-		DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
-		pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
-			pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
-		pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
-		
-		DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
-		pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
-			pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
-		pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
-	}
-	
-	/* CAUTION: Solution works if only ports of one adapter are in use. */
-	for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
-		Net->NetNumber].NumPorts; i++) {
-		if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
-			Port[i]->PortNumber == ToPortNumber) {
-			pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
-				ActivePort = i;
-			/* 20001207 RA: Was "ToPortNumber;". */
-		}
-	}
-	
-	(void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
-	(void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
-
-	return (SK_ADDR_SUCCESS);
-	
-}	/* SkAddrSwap */
-
-#endif /* !SK_SLIM */
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
-
diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c
deleted file mode 100644
index 37ce03f..0000000
--- a/drivers/net/sk98lin/skdim.c
+++ /dev/null
@@ -1,742 +0,0 @@
-/******************************************************************************
- *
- * Name:	skdim.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.5 $
- * Date:	$Date: 2003/11/28 12:55:40 $
- * Purpose:	All functions to maintain interrupt moderation
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage the dynamic interrupt moderation on both   
- * GEnesis and Yukon adapters.
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef	lint
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect.";
-#endif
-
-#define __SKADDR_C
-
-#ifdef __cplusplus
-#error C++ is not yet supported.
-extern "C" {
-#endif
-
-/*******************************************************************************
-**
-** Includes
-**
-*******************************************************************************/
-
-#ifndef __INC_SKDRV1ST_H
-#include "h/skdrv1st.h"
-#endif
-
-#ifndef __INC_SKDRV2ND_H
-#include "h/skdrv2nd.h"
-#endif
-
-#include	<linux/kernel_stat.h>
-
-/*******************************************************************************
-**
-** Defines
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Typedefs
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Local function prototypes 
-**
-*******************************************************************************/
-
-static unsigned int GetCurrentSystemLoad(SK_AC *pAC);
-static SK_U64       GetIsrCalls(SK_AC *pAC);
-static SK_BOOL      IsIntModEnabled(SK_AC *pAC);
-static void         SetCurrIntCtr(SK_AC *pAC);
-static void         EnableIntMod(SK_AC *pAC); 
-static void         DisableIntMod(SK_AC *pAC);
-static void         ResizeDimTimerDuration(SK_AC *pAC);
-static void         DisplaySelectedModerationType(SK_AC *pAC);
-static void         DisplaySelectedModerationMask(SK_AC *pAC);
-static void         DisplayDescrRatio(SK_AC *pAC);
-
-/*******************************************************************************
-**
-** Global variables
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Local variables
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Global functions 
-**
-*******************************************************************************/
-
-/*******************************************************************************
-** Function     : SkDimModerate
-** Description  : Called in every ISR to check if moderation is to be applied
-**                or not for the current number of interrupts
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-void 
-SkDimModerate(SK_AC *pAC) {
-    unsigned int CurrSysLoad    = 0;  /* expressed in percent */
-    unsigned int LoadIncrease   = 0;  /* expressed in percent */
-    SK_U64       ThresholdInts  = 0;
-    SK_U64       IsrCallsPerSec = 0;
-
-#define M_DIMINFO pAC->DynIrqModInfo
-
-    if (!IsIntModEnabled(pAC)) {
-        if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-            CurrSysLoad = GetCurrentSystemLoad(pAC);
-            if (CurrSysLoad > 75) {
-                    /* 
-                    ** More than 75% total system load! Enable the moderation 
-                    ** to shield the system against too many interrupts.
-                    */
-                    EnableIntMod(pAC);
-            } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) {
-                LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad);
-                if (LoadIncrease > ((M_DIMINFO.PrevSysLoad *
-                                         C_INT_MOD_ENABLE_PERCENTAGE) / 100)) {
-                    if (CurrSysLoad > 10) {
-                        /* 
-                        ** More than 50% increase with respect to the 
-                        ** previous load of the system. Most likely this 
-                        ** is due to our ISR-proc...
-                        */
-                        EnableIntMod(pAC);
-                    }
-                }
-            } else {
-                /*
-                ** Neither too much system load at all nor too much increase
-                ** with respect to the previous system load. Hence, we can leave
-                ** the ISR-handling like it is without enabling moderation.
-                */
-            }
-            M_DIMINFO.PrevSysLoad = CurrSysLoad;
-        }   
-    } else {
-        if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-            ThresholdInts  = ((M_DIMINFO.MaxModIntsPerSec *
-                                   C_INT_MOD_DISABLE_PERCENTAGE) / 100);
-            IsrCallsPerSec = GetIsrCalls(pAC);
-            if (IsrCallsPerSec <= ThresholdInts) {
-                /* 
-                ** The number of interrupts within the last second is 
-                ** lower than the disable_percentage of the desried 
-                ** maxrate. Therefore we can disable the moderation.
-                */
-                DisableIntMod(pAC);
-                M_DIMINFO.MaxModIntsPerSec = 
-                   (M_DIMINFO.MaxModIntsPerSecUpperLimit +
-                    M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2;
-            } else {
-                /*
-                ** The number of interrupts per sec is the same as expected.
-                ** Evalulate the descriptor-ratio. If it has changed, a resize 
-                ** in the moderation timer might be useful
-                */
-                if (M_DIMINFO.AutoSizing) {
-                    ResizeDimTimerDuration(pAC);
-                }
-            }
-        }
-    }
-
-    /*
-    ** Some information to the log...
-    */
-    if (M_DIMINFO.DisplayStats) {
-        DisplaySelectedModerationType(pAC);
-        DisplaySelectedModerationMask(pAC);
-        DisplayDescrRatio(pAC);
-    }
-
-    M_DIMINFO.NbrProcessedDescr = 0; 
-    SetCurrIntCtr(pAC);
-}
-
-/*******************************************************************************
-** Function     : SkDimStartModerationTimer
-** Description  : Starts the audit-timer for the dynamic interrupt moderation
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-void 
-SkDimStartModerationTimer(SK_AC *pAC) {
-    SK_EVPARA    EventParam;   /* Event struct for timer event */
- 
-    SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
-    EventParam.Para32[0] = SK_DRV_MODERATION_TIMER;
-    SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer,
-                 SK_DRV_MODERATION_TIMER_LENGTH,
-                 SKGE_DRV, SK_DRV_TIMER, EventParam);
-}
-
-/*******************************************************************************
-** Function     : SkDimEnableModerationIfNeeded
-** Description  : Either enables or disables moderation
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : This function is called when a particular adapter is opened
-**                There is no Disable function, because when all interrupts 
-**                might be disable, the moderation timer has no meaning at all
-******************************************************************************/
-
-void
-SkDimEnableModerationIfNeeded(SK_AC *pAC) {
-
-    if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) {
-        EnableIntMod(pAC);   /* notification print in this function */
-    } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-        SkDimStartModerationTimer(pAC);
-        if (M_DIMINFO.DisplayStats) {
-            printk("Dynamic moderation has been enabled\n");
-        }
-    } else {
-        if (M_DIMINFO.DisplayStats) {
-            printk("No moderation has been enabled\n");
-        }
-    }
-}
-
-/*******************************************************************************
-** Function     : SkDimDisplayModerationSettings
-** Description  : Displays the current settings regarding interrupt moderation
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-void 
-SkDimDisplayModerationSettings(SK_AC *pAC) {
-    DisplaySelectedModerationType(pAC);
-    DisplaySelectedModerationMask(pAC);
-}
-
-/*******************************************************************************
-**
-** Local functions 
-**
-*******************************************************************************/
-
-/*******************************************************************************
-** Function     : GetCurrentSystemLoad
-** Description  : Retrieves the current system load of the system. This load
-**                is evaluated for all processors within the system.
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : unsigned int: load expressed in percentage
-** Notes        : The possible range being returned is from 0 up to 100.
-**                Whereas 0 means 'no load at all' and 100 'system fully loaded'
-**                It is impossible to determine what actually causes the system
-**                to be in 100%, but maybe that is due to too much interrupts.
-*******************************************************************************/
-
-static unsigned int
-GetCurrentSystemLoad(SK_AC *pAC) {
-	unsigned long jif         = jiffies;
-	unsigned int  UserTime    = 0;
-	unsigned int  SystemTime  = 0;
-	unsigned int  NiceTime    = 0;
-	unsigned int  IdleTime    = 0;
-	unsigned int  TotalTime   = 0;
-	unsigned int  UsedTime    = 0;
-	unsigned int  SystemLoad  = 0;
-
-	/* unsigned int  NbrCpu      = 0; */
-
-	/*
-	** The following lines have been commented out, because
-	** from kernel 2.5.44 onwards, the kernel-owned structure
-	**
-	**      struct kernel_stat kstat
-	**
-	** is not marked as an exported symbol in the file
-	**
-	**      kernel/ksyms.c 
-	**
-	** As a consequence, using this driver as KLM is not possible
-	** and any access of the structure kernel_stat via the 
-	** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided.
-	**
-	** The kstat-information might be added again in future 
-	** versions of the 2.5.xx kernel, but for the time being, 
-	** number of interrupts will serve as indication how much 
-	** load we currently have... 
-	**
-	** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) {
-	**	UserTime   = UserTime   + kstat_cpu(NbrCpu).cpustat.user;
-	**	NiceTime   = NiceTime   + kstat_cpu(NbrCpu).cpustat.nice;
-	**	SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system;
-	** }
-	*/
-	SK_U64 ThresholdInts  = 0;
-	SK_U64 IsrCallsPerSec = 0;
-
-	ThresholdInts  = ((M_DIMINFO.MaxModIntsPerSec *
-			   C_INT_MOD_ENABLE_PERCENTAGE) + 100);
-	IsrCallsPerSec = GetIsrCalls(pAC);
-	if (IsrCallsPerSec >= ThresholdInts) {
-	    /*
-	    ** We do not know how much the real CPU-load is!
-	    ** Return 80% as a default in order to activate DIM
-	    */
-	    SystemLoad = 80;
-	    return (SystemLoad);  
-	} 
-
-	UsedTime  = UserTime + NiceTime + SystemTime;
-
-	IdleTime  = jif * num_online_cpus() - UsedTime;
-	TotalTime = UsedTime + IdleTime;
-
-	SystemLoad = ( 100 * (UsedTime  - M_DIMINFO.PrevUsedTime) ) /
-						(TotalTime - M_DIMINFO.PrevTotalTime);
-
-	if (M_DIMINFO.DisplayStats) {
-		printk("Current system load is: %u\n", SystemLoad);
-	}
-
-	M_DIMINFO.PrevTotalTime = TotalTime;
-	M_DIMINFO.PrevUsedTime  = UsedTime;
-
-	return (SystemLoad);
-}
-
-/*******************************************************************************
-** Function     : GetIsrCalls
-** Description  : Depending on the selected moderation mask, this function will
-**                return the number of interrupts handled in the previous time-
-**                frame. This evaluated number is based on the current number 
-**                of interrupts stored in PNMI-context and the previous stored 
-**                interrupts.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : int:   the number of interrupts being executed in the last
-**                       timeframe
-** Notes        : It makes only sense to call this function, when dynamic 
-**                interrupt moderation is applied
-*******************************************************************************/
-
-static SK_U64
-GetIsrCalls(SK_AC *pAC) {
-    SK_U64   RxPort0IntDiff = 0;
-    SK_U64   RxPort1IntDiff = 0;
-    SK_U64   TxPort0IntDiff = 0;
-    SK_U64   TxPort1IntDiff = 0;
-
-    if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) {
-        if (pAC->GIni.GIMacsFound == 2) {
-            TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1TxIntrCts;
-        }
-        TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0TxIntrCts;
-    } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) {
-        if (pAC->GIni.GIMacsFound == 2) {
-            RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1RxIntrCts;
-        }
-        RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0RxIntrCts;
-    } else {
-        if (pAC->GIni.GIMacsFound == 2) {
-            RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1RxIntrCts;
-            TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - 
-                             pAC->DynIrqModInfo.PrevPort1TxIntrCts;
-        } 
-        RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0RxIntrCts;
-        TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort0TxIntrCts;
-    }
-
-    return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff);
-}
-
-/*******************************************************************************
-** Function     : GetRxCalls
-** Description  : This function will return the number of times a receive inter-
-**                rupt was processed. This is needed to evaluate any resizing 
-**                factor.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : SK_U64: the number of RX-ints being processed
-** Notes        : It makes only sense to call this function, when dynamic 
-**                interrupt moderation is applied
-*******************************************************************************/
-
-static SK_U64
-GetRxCalls(SK_AC *pAC) {
-    SK_U64   RxPort0IntDiff = 0;
-    SK_U64   RxPort1IntDiff = 0;
-
-    if (pAC->GIni.GIMacsFound == 2) {
-        RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - 
-                         pAC->DynIrqModInfo.PrevPort1RxIntrCts;
-    }
-    RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - 
-                     pAC->DynIrqModInfo.PrevPort0RxIntrCts;
-
-    return (RxPort0IntDiff + RxPort1IntDiff);
-}
-
-/*******************************************************************************
-** Function     : SetCurrIntCtr
-** Description  : Will store the current number orf occured interrupts in the 
-**                adapter context. This is needed to evaluated the number of 
-**                interrupts within a current timeframe.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void (!)
-** Notes        : -
-*******************************************************************************/
-
-static void
-SetCurrIntCtr(SK_AC *pAC) {
-    if (pAC->GIni.GIMacsFound == 2) {
-        pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts;
-        pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts;
-    } 
-    pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts;
-    pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts;
-}
-
-/*******************************************************************************
-** Function     : IsIntModEnabled()
-** Description  : Retrieves the current value of the interrupts moderation
-**                command register. Its content determines whether any 
-**                moderation is running or not.
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : SK_TRUE  : if mod timer running
-**                SK_FALSE : if no moderation is being performed
-** Notes        : -
-*******************************************************************************/
-
-static SK_BOOL
-IsIntModEnabled(SK_AC *pAC) {
-    unsigned long CtrCmd;
-
-    SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd);
-    if ((CtrCmd & TIM_START) == TIM_START) {
-       return SK_TRUE;
-    } else {
-       return SK_FALSE;
-    }
-}
-
-/*******************************************************************************
-** Function     : EnableIntMod()
-** Description  : Enables the interrupt moderation using the values stored in
-**                in the pAC->DynIntMod data structure
-** Programmer   : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns      : -
-** Notes        : -
-*******************************************************************************/
-
-static void
-EnableIntMod(SK_AC *pAC) {
-    unsigned long ModBase;
-
-    if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-       ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    } else {
-       ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    }
-
-    SK_OUT32(pAC->IoBase, B2_IRQM_INI,  ModBase);
-    SK_OUT32(pAC->IoBase, B2_IRQM_MSK,  pAC->DynIrqModInfo.MaskIrqModeration);
-    SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
-    if (M_DIMINFO.DisplayStats) {
-        printk("Enabled interrupt moderation (%i ints/sec)\n",
-               M_DIMINFO.MaxModIntsPerSec);
-    }
-}
-
-/*******************************************************************************
-** Function     : DisableIntMod()
-** Description  : Disables the interrupt moderation independent of what inter-
-**                rupts are running or not
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : -
-** Notes        : -
-*******************************************************************************/
-
-static void 
-DisableIntMod(SK_AC *pAC) {
-
-    SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP);
-    if (M_DIMINFO.DisplayStats) {
-        printk("Disabled interrupt moderation\n");
-    }
-} 
-
-/*******************************************************************************
-** Function     : ResizeDimTimerDuration();
-** Description  : Checks the current used descriptor ratio and resizes the 
-**                duration timer (longer/smaller) if possible. 
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : -
-** Notes        : There are both maximum and minimum timer duration value. 
-**                This function assumes that interrupt moderation is already
-**                enabled!
-*******************************************************************************/
-
-static void 
-ResizeDimTimerDuration(SK_AC *pAC) {
-    SK_BOOL IncreaseTimerDuration;
-    int     TotalMaxNbrDescr;
-    int     UsedDescrRatio;
-    int     RatioDiffAbs;
-    int     RatioDiffRel;
-    int     NewMaxModIntsPerSec;
-    int     ModAdjValue;
-    long    ModBase;
-
-    /*
-    ** Check first if we are allowed to perform any modification
-    */
-    if (IsIntModEnabled(pAC)) { 
-        if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) {
-            return; 
-        } else {
-            if (M_DIMINFO.ModJustEnabled) {
-                M_DIMINFO.ModJustEnabled = SK_FALSE;
-                return;
-            }
-        }
-    }
-
-    /*
-    ** If we got until here, we have to evaluate the amount of the
-    ** descriptor ratio change...
-    */
-    TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
-    UsedDescrRatio   = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr;
-
-    if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) {
-        RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio);
-        RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio;
-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
-        IncreaseTimerDuration = SK_FALSE;  /* in other words: DECREASE */
-    } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) {
-        RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
-        RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
-        IncreaseTimerDuration = SK_TRUE;   /* in other words: INCREASE */
-    } else {
-        RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
-        RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
-        M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
-        IncreaseTimerDuration = SK_TRUE;   /* in other words: INCREASE */
-    }
-
-    /*
-    ** Now we can determine the change in percent
-    */
-    if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    } else {
-       ModAdjValue = 1;  /*  1% change - maybe some other value in future */
-    }
-
-    if (IncreaseTimerDuration) {
-       NewMaxModIntsPerSec =  M_DIMINFO.MaxModIntsPerSec +
-                             (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
-    } else {
-       NewMaxModIntsPerSec =  M_DIMINFO.MaxModIntsPerSec -
-                             (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
-    }
-
-    /* 
-    ** Check if we exceed boundaries...
-    */
-    if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) ||
-         (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) {
-        if (M_DIMINFO.DisplayStats) {
-            printk("Cannot change ModTim from %i to %i ints/sec\n",
-                   M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
-        }
-        return;
-    } else {
-        if (M_DIMINFO.DisplayStats) {
-            printk("Resized ModTim from %i to %i ints/sec\n",
-                   M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
-        }
-    }
-
-    M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec;
-
-    if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-        ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    } else {
-        ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
-    }
-
-    /* 
-    ** We do not need to touch any other registers
-    */
-    SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
-} 
-
-/*******************************************************************************
-** Function     : DisplaySelectedModerationType()
-** Description  : Displays what type of moderation we have
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void!
-** Notes        : -
-*******************************************************************************/
-
-static void
-DisplaySelectedModerationType(SK_AC *pAC) {
-
-    if (pAC->DynIrqModInfo.DisplayStats) {
-        if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
-             printk("Static int moderation runs with %i INTS/sec\n",
-                    pAC->DynIrqModInfo.MaxModIntsPerSec);
-        } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
-             if (IsIntModEnabled(pAC)) {
-                printk("Dynamic int moderation runs with %i INTS/sec\n",
-                       pAC->DynIrqModInfo.MaxModIntsPerSec);
-             } else {
-                printk("Dynamic int moderation currently not applied\n");
-             }
-        } else {
-             printk("No interrupt moderation selected!\n");
-        }
-    }
-}
-
-/*******************************************************************************
-** Function     : DisplaySelectedModerationMask()
-** Description  : Displays what interrupts are moderated
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void!
-** Notes        : -
-*******************************************************************************/
-
-static void
-DisplaySelectedModerationMask(SK_AC *pAC) {
-
-    if (pAC->DynIrqModInfo.DisplayStats) {
-        if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) {
-            switch (pAC->DynIrqModInfo.MaskIrqModeration) {
-                case IRQ_MASK_TX_ONLY: 
-                   printk("Only Tx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_RX_ONLY: 
-                   printk("Only Rx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_SP_ONLY: 
-                   printk("Only special-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_TX_RX: 
-                   printk("Tx- and Rx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_SP_RX: 
-                   printk("Special- and Rx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_SP_TX: 
-                   printk("Special- and Tx-interrupts are moderated\n");
-                   break;
-                case IRQ_MASK_RX_TX_SP:
-                   printk("All Rx-, Tx and special-interrupts are moderated\n");
-                   break;
-                default:
-                   printk("Don't know what is moderated\n");
-                   break;
-            }
-        } else {
-            printk("No specific interrupts masked for moderation\n");
-        }
-    } 
-}
-
-/*******************************************************************************
-** Function     : DisplayDescrRatio
-** Description  : Like the name states...
-** Programmer   : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns      : void!
-** Notes        : -
-*******************************************************************************/
-
-static void
-DisplayDescrRatio(SK_AC *pAC) {
-    int TotalMaxNbrDescr = 0;
-
-    if (pAC->DynIrqModInfo.DisplayStats) {
-        TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
-        printk("Ratio descriptors: %i/%i\n",
-               M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr);
-    }
-}
-
-/*******************************************************************************
-**
-** End of file
-**
-*******************************************************************************/
diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
deleted file mode 100644
index 3646069..0000000
--- a/drivers/net/sk98lin/skethtool.c
+++ /dev/null
@@ -1,628 +0,0 @@
-/******************************************************************************
- *
- * Name:        skethtool.c
- * Project:     GEnesis, PCI Gigabit Ethernet Adapter
- * Version:     $Revision: 1.7 $
- * Date:        $Date: 2004/09/29 13:32:07 $
- * Purpose:     All functions regarding ethtool handling
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2004 Marvell.
- *
- *	Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet 
- *      Server Adapters.
- *
- *	Author: Ralph Roesler (rroesler@syskonnect.de)
- *	        Mirko Lindner (mlindner@syskonnect.de)
- *
- *	Address all question to: linux@syskonnect.de
- *
- *	The technical manual for the adapters is available from SysKonnect's
- *	web pages: www.syskonnect.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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- *****************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-#include "h/skversion.h"
-
-#include <linux/ethtool.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-
-/******************************************************************************
- *
- * Defines
- *
- *****************************************************************************/
-
-#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half  | SUPPORTED_10baseT_Full  | \
-                         SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
-                         SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \
-                         SUPPORTED_TP)
-
-#define ADV_COPPER_ALL  (ADVERTISED_10baseT_Half  | ADVERTISED_10baseT_Full  | \
-                         ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
-                         ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \
-                         ADVERTISED_TP)
-
-#define SUPP_FIBRE_ALL  (SUPPORTED_1000baseT_Full | \
-                         SUPPORTED_FIBRE          | \
-                         SUPPORTED_Autoneg)
-
-#define ADV_FIBRE_ALL   (ADVERTISED_1000baseT_Full | \
-                         ADVERTISED_FIBRE          | \
-                         ADVERTISED_Autoneg)
-
-
-/******************************************************************************
- *
- * Local Functions
- *
- *****************************************************************************/
-
-/*****************************************************************************
- *
- * 	getSettings - retrieves the current settings of the selected adapter
- *
- * Description:
- *	The current configuration of the selected adapter is returned.
- *	This configuration involves a)speed, b)duplex and c)autoneg plus
- *	a number of other variables.
- *
- * Returns:    always 0
- *
- */
-static int getSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	const DEV_NET *pNet = netdev_priv(dev);
-	int port = pNet->PortNr;
-	const SK_AC *pAC = pNet->pAC;
-	const SK_GEPORT *pPort = &pAC->GIni.GP[port];
-
-	static int DuplexAutoNegConfMap[9][3]= {
-		{ -1                     , -1         , -1              },
-		{ 0                      , -1         , -1              },
-		{ SK_LMODE_HALF          , DUPLEX_HALF, AUTONEG_DISABLE },
-		{ SK_LMODE_FULL          , DUPLEX_FULL, AUTONEG_DISABLE },
-		{ SK_LMODE_AUTOHALF      , DUPLEX_HALF, AUTONEG_ENABLE  },
-		{ SK_LMODE_AUTOFULL      , DUPLEX_FULL, AUTONEG_ENABLE  },
-		{ SK_LMODE_AUTOBOTH      , DUPLEX_FULL, AUTONEG_ENABLE  },
-		{ SK_LMODE_AUTOSENSE     , -1         , -1              },
-		{ SK_LMODE_INDETERMINATED, -1         , -1              }
-	};
-	static int SpeedConfMap[6][2] = {
-		{ 0                       , -1         },
-		{ SK_LSPEED_AUTO          , -1         },
-		{ SK_LSPEED_10MBPS        , SPEED_10   },
-		{ SK_LSPEED_100MBPS       , SPEED_100  },
-		{ SK_LSPEED_1000MBPS      , SPEED_1000 },
-		{ SK_LSPEED_INDETERMINATED, -1         }
-	};
-	static int AdvSpeedMap[6][2] = {
-		{ 0                       , -1         },
-		{ SK_LSPEED_AUTO          , -1         },
-		{ SK_LSPEED_10MBPS        , ADVERTISED_10baseT_Half   | ADVERTISED_10baseT_Full },
-		{ SK_LSPEED_100MBPS       , ADVERTISED_100baseT_Half  | ADVERTISED_100baseT_Full },
-		{ SK_LSPEED_1000MBPS      , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full},
-		{ SK_LSPEED_INDETERMINATED, -1         }
-	};
-
-	ecmd->phy_address = port;
-	ecmd->speed       = SpeedConfMap[pPort->PLinkSpeedUsed][1];
-	ecmd->duplex      = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1];
-	ecmd->autoneg     = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2];
-	ecmd->transceiver = XCVR_INTERNAL;
-
-	if (pAC->GIni.GICopperType) {
-		ecmd->port        = PORT_TP;
-		ecmd->supported   = (SUPP_COPPER_ALL|SUPPORTED_Autoneg);
-		if (pAC->GIni.GIGenesis) {
-			ecmd->supported &= ~(SUPPORTED_10baseT_Half);
-			ecmd->supported &= ~(SUPPORTED_10baseT_Full);
-			ecmd->supported &= ~(SUPPORTED_100baseT_Half);
-			ecmd->supported &= ~(SUPPORTED_100baseT_Full);
-		} else {
-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-				ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
-			} 
-#ifdef CHIP_ID_YUKON_FE
-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
-				ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
-				ecmd->supported &= ~(SUPPORTED_1000baseT_Full);
-			}
-#endif
-		}
-		if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) {
-			ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1];
-			if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-				ecmd->advertising &= ~(SUPPORTED_1000baseT_Half);
-			} 
-		} else {
-			ecmd->advertising = ecmd->supported;
-		}
-
-		if (ecmd->autoneg == AUTONEG_ENABLE) 
-			ecmd->advertising |= ADVERTISED_Autoneg;
-	} else {
-		ecmd->port        = PORT_FIBRE;
-		ecmd->supported   = SUPP_FIBRE_ALL;
-		ecmd->advertising = ADV_FIBRE_ALL;
-	}
-	return 0;
-}
-
-/*
- * MIB infrastructure uses instance value starting at 1
- * based on board and port.
- */
-static inline u32 pnmiInstance(const DEV_NET *pNet)
-{
-	return 1 + (pNet->pAC->RlmtNets == 2) + pNet->PortNr;
-}
-
-/*****************************************************************************
- *
- *	setSettings - configures the settings of a selected adapter
- *
- * Description:
- *	Possible settings that may be altered are a)speed, b)duplex or 
- *	c)autonegotiation.
- *
- * Returns:
- *	0:	everything fine, no error
- *	<0:	the return value is the error code of the failure 
- */
-static int setSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	u32 instance;
-	char buf[4];
-	int len = 1;
-
-	if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100 
-	    && ecmd->speed != SPEED_1000)
-		return -EINVAL;
-
-	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
-		return -EINVAL;
-
-	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
-		return -EINVAL;
-
-	if (ecmd->autoneg == AUTONEG_DISABLE)
-		*buf = (ecmd->duplex == DUPLEX_FULL) 
-			? SK_LMODE_FULL : SK_LMODE_HALF;
-	else
-		*buf = (ecmd->duplex == DUPLEX_FULL) 
-			? SK_LMODE_AUTOFULL : SK_LMODE_AUTOHALF;
-	
-	instance = pnmiInstance(pNet);
-	if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE, 
-			   &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
-		return -EINVAL;
-
-	switch(ecmd->speed) {
-	case SPEED_1000:
-		*buf = SK_LSPEED_1000MBPS;
-		break;
-	case SPEED_100:
-		*buf = SK_LSPEED_100MBPS;
-		break;
-	case SPEED_10:
-		*buf = SK_LSPEED_10MBPS;
-	}
-
-	if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, 
-			 &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
-		return -EINVAL;
-
-	return 0;
-}
-
-/*****************************************************************************
- *
- * 	getDriverInfo - returns generic driver and adapter information
- *
- * Description:
- *	Generic driver information is returned via this function, such as
- *	the name of the driver, its version and and firmware version.
- *	In addition to this, the location of the selected adapter is 
- *	returned as a bus info string (e.g. '01:05.0').
- *	
- * Returns:	N/A
- *
- */
-static void getDriverInfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-	const DEV_NET	*pNet = netdev_priv(dev);
-	const SK_AC *pAC = pNet->pAC;
-	char vers[32];
-
-	snprintf(vers, sizeof(vers)-1, VER_STRING "(v%d.%d)",
-		(pAC->GIni.GIPciHwRev >> 4) & 0xf, pAC->GIni.GIPciHwRev & 0xf);
-
-	strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver));
-	strcpy(info->version, vers);
-	strcpy(info->fw_version, "N/A");
-	strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN);
-}
-
-/*
- * Ethtool statistics support.
- */
-static const char StringsStats[][ETH_GSTRING_LEN] = {
-	"rx_packets",	"tx_packets",
-	"rx_bytes",	"tx_bytes",
-	"rx_errors",	"tx_errors",	
-	"rx_dropped",	"tx_dropped",
-	"multicasts",	"collisions",	
-	"rx_length_errors",		"rx_buffer_overflow_errors",
-	"rx_crc_errors",		"rx_frame_errors",
-	"rx_too_short_errors",		"rx_too_long_errors",
-	"rx_carrier_extension_errors",	"rx_symbol_errors",
-	"rx_llc_mac_size_errors",	"rx_carrier_errors",	
-	"rx_jabber_errors",		"rx_missed_errors",
-	"tx_abort_collision_errors",	"tx_carrier_errors",
-	"tx_buffer_underrun_errors",	"tx_heartbeat_errors",
-	"tx_window_errors",
-};
-
-static int getStatsCount(struct net_device *dev)
-{
-	return ARRAY_SIZE(StringsStats);
-}
-
-static void getStrings(struct net_device *dev, u32 stringset, u8 *data)
-{
-	switch(stringset) {
-	case ETH_SS_STATS:
-		memcpy(data, *StringsStats, sizeof(StringsStats));
-		break;
-	}
-}
-
-static void getEthtoolStats(struct net_device *dev,
-			    struct ethtool_stats *stats, u64 *data)
-{
-	const DEV_NET	*pNet = netdev_priv(dev);
-	const SK_AC *pAC = pNet->pAC;
-	const SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
-
-	*data++ = pPnmiStruct->Stat[0].StatRxOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxOctetsOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxOctetsOkCts;
-	*data++ = pPnmiStruct->InErrorsCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
-	*data++ = pPnmiStruct->RxNoBufCts;
-	*data++ = pPnmiStruct->TxNoBufCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxMulticastOkCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxRuntCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFifoOverflowCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFcsCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxFramingCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxShortsCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxTooLongCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxCextCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxSymbolCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxIRLengthCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxCarrierCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxJabberCts;
-	*data++ = pPnmiStruct->Stat[0].StatRxMissedCts;
-	*data++ = pAC->stats.tx_aborted_errors;
-	*data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxFifoUnderrunCts;
-	*data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
-	*data++ = pAC->stats.tx_window_errors;
-}
-
-
-/*****************************************************************************
- *
- * 	toggleLeds - Changes the LED state of an adapter
- *
- * Description:
- *	This function changes the current state of all LEDs of an adapter so
- *	that it can be located by a user. 
- *
- * Returns:	N/A
- *
- */
-static void toggleLeds(DEV_NET *pNet, int on)
-{
-	SK_AC *pAC = pNet->pAC;
-	int port = pNet->PortNr;
-	void __iomem *io = pAC->IoBase;
-
-	if (pAC->GIni.GIGenesis) {
-		SK_OUT8(io, MR_ADDR(port,LNK_LED_REG), 
-			on ? SK_LNK_ON : SK_LNK_OFF);
-		SkGeYellowLED(pAC, io, 
-			      on ? (LED_ON >> 1) : (LED_OFF >> 1));
-		SkGeXmitLED(pAC, io, MR_ADDR(port,RX_LED_INI),
-			    on ? SK_LED_TST : SK_LED_DIS);
-
-		if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM)
-			SkXmPhyWrite(pAC, io, port, PHY_BCOM_P_EXT_CTRL, 
-				     on ? PHY_B_PEC_LED_ON : PHY_B_PEC_LED_OFF);
-		else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE)
-			SkXmPhyWrite(pAC, io, port, PHY_LONE_LED_CFG,
-				     on ? 0x0800 : PHY_L_LC_LEDT);
-		else
-			SkGeXmitLED(pAC, io, MR_ADDR(port,TX_LED_INI),
-				    on ? SK_LED_TST : SK_LED_DIS);
-	} else {
-		const u16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON)  |
-				      PHY_M_LED_MO_10(MO_LED_ON)   |
-				      PHY_M_LED_MO_100(MO_LED_ON)  |
-				      PHY_M_LED_MO_1000(MO_LED_ON) | 
-				      PHY_M_LED_MO_RX(MO_LED_ON));
-		const u16  YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF)  |
-					PHY_M_LED_MO_10(MO_LED_OFF)   |
-					PHY_M_LED_MO_100(MO_LED_OFF)  |
-					PHY_M_LED_MO_1000(MO_LED_OFF) | 
-					PHY_M_LED_MO_RX(MO_LED_OFF));
-	
-
-		SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_CTRL,0);
-		SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_OVER, 
-			     on ? YukLedOn : YukLedOff);
-	}
-}
-
-/*****************************************************************************
- *
- * 	skGeBlinkTimer - Changes the LED state of an adapter
- *
- * Description:
- *	This function changes the current state of all LEDs of an adapter so
- *	that it can be located by a user. If the requested time interval for
- *	this test has elapsed, this function cleans up everything that was 
- *	temporarily setup during the locate NIC test. This involves of course
- *	also closing or opening any adapter so that the initial board state 
- *	is recovered.
- *
- * Returns:	N/A
- *
- */
-void SkGeBlinkTimer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *) data;
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	toggleLeds(pNet, pAC->LedsOn);
-
-	pAC->LedsOn = !pAC->LedsOn;
-	mod_timer(&pAC->BlinkTimer, jiffies + HZ/4);
-}
-
-/*****************************************************************************
- *
- * 	locateDevice - start the locate NIC feature of the elected adapter 
- *
- * Description:
- *	This function is used if the user want to locate a particular NIC.
- *	All LEDs are regularly switched on and off, so the NIC can easily
- *	be identified.
- *
- * Returns:	
- *	==0:	everything fine, no error, locateNIC test was started
- *	!=0:	one locateNIC test runs already
- *
- */
-static int locateDevice(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
-		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
-
-	/* start blinking */
-	pAC->LedsOn = 0;
-	mod_timer(&pAC->BlinkTimer, jiffies);
-	msleep_interruptible(data * 1000);
-	del_timer_sync(&pAC->BlinkTimer);
-	toggleLeds(pNet, 0);
-
-	return 0;
-}
-
-/*****************************************************************************
- *
- * 	getPauseParams - retrieves the pause parameters
- *
- * Description:
- *	All current pause parameters of a selected adapter are placed 
- *	in the passed ethtool_pauseparam structure and are returned.
- *
- * Returns:	N/A
- *
- */
-static void getPauseParams(struct net_device *dev, struct ethtool_pauseparam *epause) 
-{
-	DEV_NET	*pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
-
-	epause->rx_pause = (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
-		  (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM);
-
-	epause->tx_pause = epause->rx_pause || (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND);
-	epause->autoneg = epause->rx_pause || epause->tx_pause;
-}
-
-/*****************************************************************************
- *
- *	setPauseParams - configures the pause parameters of an adapter
- *
- * Description:
- *	This function sets the Rx or Tx pause parameters 
- *
- * Returns:
- *	==0:	everything fine, no error
- *	!=0:	the return value is the error code of the failure 
- */
-static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *epause)
-{
-	DEV_NET	*pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
-	u32	instance = pnmiInstance(pNet);
-	struct ethtool_pauseparam old;
-	u8	oldspeed = pPort->PLinkSpeedUsed;
-	char	buf[4];
-	int	len = 1;
-	int ret;
-
-	/*
-	** we have to determine the current settings to see if 
-	** the operator requested any modification of the flow 
-	** control parameters...
-	*/
-	getPauseParams(dev, &old);
-
-	/*
-	** perform modifications regarding the changes 
-	** requested by the operator
-	*/
-	if (epause->autoneg != old.autoneg) 
-		*buf = epause->autoneg ? SK_FLOW_MODE_NONE : SK_FLOW_MODE_SYMMETRIC;
-	else {
-		if (epause->rx_pause && epause->tx_pause) 
-			*buf = SK_FLOW_MODE_SYMMETRIC;
-		else if (epause->rx_pause && !epause->tx_pause)
-			*buf =  SK_FLOW_MODE_SYM_OR_REM;
-		else if (!epause->rx_pause && epause->tx_pause)
-			*buf =  SK_FLOW_MODE_LOC_SEND;
-		else
-			*buf = SK_FLOW_MODE_NONE;
-	}
-
-	ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE,
-			 &buf, &len, instance, pNet->NetNr);
-
-	if (ret != SK_PNMI_ERR_OK) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
-			   ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", ret));
-		goto err;
-	}
-
-	/*
-	** It may be that autoneg has been disabled! Therefore
-	** set the speed to the previously used value...
-	*/
-	if (!epause->autoneg) {
-		len = 1;
-		ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, 
-				   &oldspeed, &len, instance, pNet->NetNr);
-		if (ret != SK_PNMI_ERR_OK) 
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
-				   ("ethtool (sk98lin): error setting speed (%i)\n", ret));
-	}
- err:
-        return ret ? -EIO : 0;
-}
-
-/* Only Yukon supports checksum offload. */
-static int setScatterGather(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
-		return -EOPNOTSUPP;
-	return ethtool_op_set_sg(dev, data);
-}
-
-static int setTxCsum(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
-		return -EOPNOTSUPP;
-
-	return ethtool_op_set_tx_csum(dev, data);
-}
-
-static u32 getRxCsum(struct net_device *dev)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	return pAC->RxPort[pNet->PortNr].RxCsum;
-}
-
-static int setRxCsum(struct net_device *dev, u32 data)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
-		return -EOPNOTSUPP;
-
-	pAC->RxPort[pNet->PortNr].RxCsum = data != 0;
-	return 0;
-}
-
-static int getRegsLen(struct net_device *dev)
-{
-	return 0x4000;
-}
-
-/*
- * Returns copy of whole control register region
- * Note: skip RAM address register because accessing it will
- * 	 cause bus hangs!
- */
-static void getRegs(struct net_device *dev, struct ethtool_regs *regs,
-			  void *p)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	const void __iomem *io = pNet->pAC->IoBase;
-
-	regs->version = 1;
-	memset(p, 0, regs->len);
-	memcpy_fromio(p, io, B3_RAM_ADDR);
-
-	memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
-		      regs->len - B3_RI_WTO_R1);
-}
-
-const struct ethtool_ops SkGeEthtoolOps = {
-	.get_settings		= getSettings,
-	.set_settings		= setSettings,
-	.get_drvinfo		= getDriverInfo,
-	.get_strings		= getStrings,
-	.get_stats_count	= getStatsCount,
-	.get_ethtool_stats	= getEthtoolStats,
-	.phys_id		= locateDevice,
-	.get_pauseparam		= getPauseParams,
-	.set_pauseparam		= setPauseParams,
-	.get_link		= ethtool_op_get_link,
-	.get_perm_addr		= ethtool_op_get_perm_addr,
-	.get_sg			= ethtool_op_get_sg,
-	.set_sg			= setScatterGather,
-	.get_tx_csum		= ethtool_op_get_tx_csum,
-	.set_tx_csum		= setTxCsum,
-	.get_rx_csum		= getRxCsum,
-	.set_rx_csum		= setRxCsum,
-	.get_regs		= getRegs,
-	.get_regs_len		= getRegsLen,
-};
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
deleted file mode 100644
index bf21862..0000000
--- a/drivers/net/sk98lin/skge.c
+++ /dev/null
@@ -1,5211 +0,0 @@
-/******************************************************************************
- *
- * Name:	skge.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.45 $
- * Date:       	$Date: 2004/02/12 14:41:02 $
- * Purpose:	The main driver source module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet 
- *      Server Adapters.
- *
- *	Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and
- *	SysKonnects GEnesis Solaris driver
- *	Author: Christoph Goos (cgoos@syskonnect.de)
- *	        Mirko Lindner (mlindner@syskonnect.de)
- *
- *	Address all question to: linux@syskonnect.de
- *
- *	The technical manual for the adapters is available from SysKonnect's
- *	web pages: www.syskonnect.com
- *	Goto "Support" and search Knowledge Base for "manual".
- *	
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Possible compiler options (#define xxx / -Dxxx):
- *
- *	debugging can be enable by changing SK_DEBUG_CHKMOD and
- *	SK_DEBUG_CHKCAT in makefile (described there).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- *	This is the main module of the Linux GE driver.
- *	
- *	All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h
- *	are part of SysKonnect's COMMON MODULES for the SK-98xx adapters.
- *	Those are used for drivers on multiple OS', so some thing may seem
- *	unnecessary complicated on Linux. Please do not try to 'clean up'
- *	them without VERY good reasons, because this will make it more
- *	difficult to keep the Linux driver in synchronisation with the
- *	other versions.
- *
- * Include file hierarchy:
- *
- *	<linux/module.h>
- *
- *	"h/skdrv1st.h"
- *		<linux/types.h>
- *		<linux/kernel.h>
- *		<linux/string.h>
- *		<linux/errno.h>
- *		<linux/ioport.h>
- *		<linux/slab.h>
- *		<linux/interrupt.h>
- *		<linux/pci.h>
- *		<linux/bitops.h>
- *		<asm/byteorder.h>
- *		<asm/io.h>
- *		<linux/netdevice.h>
- *		<linux/etherdevice.h>
- *		<linux/skbuff.h>
- *	    those three depending on kernel version used:
- *		<linux/bios32.h>
- *		<linux/init.h>
- *		<asm/uaccess.h>
- *		<net/checksum.h>
- *
- *		"h/skerror.h"
- *		"h/skdebug.h"
- *		"h/sktypes.h"
- *		"h/lm80.h"
- *		"h/xmac_ii.h"
- *
- *      "h/skdrv2nd.h"
- *		"h/skqueue.h"
- *		"h/skgehwt.h"
- *		"h/sktimer.h"
- *		"h/ski2c.h"
- *		"h/skgepnmi.h"
- *		"h/skvpd.h"
- *		"h/skgehw.h"
- *		"h/skgeinit.h"
- *		"h/skaddr.h"
- *		"h/skgesirq.h"
- *		"h/skrlmt.h"
- *
- ******************************************************************************/
-
-#include	"h/skversion.h"
-
-#include	<linux/in.h>
-#include	<linux/module.h>
-#include	<linux/moduleparam.h>
-#include	<linux/init.h>
-#include	<linux/dma-mapping.h>
-#include	<linux/ip.h>
-#include	<linux/mii.h>
-#include	<linux/mm.h>
-
-#include	"h/skdrv1st.h"
-#include	"h/skdrv2nd.h"
-
-/*******************************************************************************
- *
- * Defines
- *
- ******************************************************************************/
-
-/* for debuging on x86 only */
-/* #define BREAKPOINT() asm(" int $3"); */
-
-/* use the transmit hw checksum driver functionality */
-#define USE_SK_TX_CHECKSUM
-
-/* use the receive hw checksum driver functionality */
-#define USE_SK_RX_CHECKSUM
-
-/* use the scatter-gather functionality with sendfile() */
-#define SK_ZEROCOPY
-
-/* use of a transmit complete interrupt */
-#define USE_TX_COMPLETE
-
-/*
- * threshold for copying small receive frames
- * set to 0 to avoid copying, set to 9001 to copy all frames
- */
-#define SK_COPY_THRESHOLD	50
-
-/* number of adapters that can be configured via command line params */
-#define SK_MAX_CARD_PARAM	16
-
-
-
-/*
- * use those defines for a compile-in version of the driver instead
- * of command line parameters
- */
-// #define LINK_SPEED_A	{"Auto", }
-// #define LINK_SPEED_B	{"Auto", }
-// #define AUTO_NEG_A	{"Sense", }
-// #define AUTO_NEG_B	{"Sense", }
-// #define DUP_CAP_A	{"Both", }
-// #define DUP_CAP_B	{"Both", }
-// #define FLOW_CTRL_A	{"SymOrRem", }
-// #define FLOW_CTRL_B	{"SymOrRem", }
-// #define ROLE_A	{"Auto", }
-// #define ROLE_B	{"Auto", }
-// #define PREF_PORT	{"A", }
-// #define CON_TYPE 	{"Auto", }
-// #define RLMT_MODE	{"CheckLinkState", }
-
-#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
-#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
-#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
-
-
-/* Set blink mode*/
-#define OEM_CONFIG_VALUE (	SK_ACT_LED_BLINK | \
-				SK_DUP_LED_NORMAL | \
-				SK_LED_LINK100_ON)
-
-
-/* Isr return value */
-#define SkIsrRetVar	irqreturn_t
-#define SkIsrRetNone	IRQ_NONE
-#define SkIsrRetHandled	IRQ_HANDLED
-
-
-/*******************************************************************************
- *
- * Local Function Prototypes
- *
- ******************************************************************************/
-
-static void	FreeResources(struct SK_NET_DEVICE *dev);
-static int	SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC);
-static SK_BOOL	BoardAllocMem(SK_AC *pAC);
-static void	BoardFreeMem(SK_AC *pAC);
-static void	BoardInitMem(SK_AC *pAC);
-static void	SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL);
-static SkIsrRetVar	SkGeIsr(int irq, void *dev_id);
-static SkIsrRetVar	SkGeIsrOnePort(int irq, void *dev_id);
-static int	SkGeOpen(struct SK_NET_DEVICE *dev);
-static int	SkGeClose(struct SK_NET_DEVICE *dev);
-static int	SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev);
-static int	SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p);
-static void	SkGeSetRxMode(struct SK_NET_DEVICE *dev);
-static struct	net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
-static int	SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
-static void	GetConfiguration(SK_AC*);
-static int	XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
-static void	FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
-static void	FillRxRing(SK_AC*, RX_PORT*);
-static SK_BOOL	FillRxDescriptor(SK_AC*, RX_PORT*);
-static void	ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);
-static void	ClearAndStartRx(SK_AC*, int);
-static void	ClearTxIrq(SK_AC*, int, int);
-static void	ClearRxRing(SK_AC*, RX_PORT*);
-static void	ClearTxRing(SK_AC*, TX_PORT*);
-static int	SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu);
-static void	PortReInitBmu(SK_AC*, int);
-static int	SkGeIocMib(DEV_NET*, unsigned int, int);
-static int	SkGeInitPCI(SK_AC *pAC);
-static void	StartDrvCleanupTimer(SK_AC *pAC);
-static void	StopDrvCleanupTimer(SK_AC *pAC);
-static int	XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
-
-#ifdef SK_DIAG_SUPPORT
-static SK_U32   ParseDeviceNbrFromSlotName(const char *SlotName);
-static int      SkDrvInitAdapter(SK_AC *pAC, int devNbr);
-static int      SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
-#endif
-
-/*******************************************************************************
- *
- * Extern Function Prototypes
- *
- ******************************************************************************/
-extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);	
-extern void SkDimDisplayModerationSettings(SK_AC *pAC);
-extern void SkDimStartModerationTimer(SK_AC *pAC);
-extern void SkDimModerate(SK_AC *pAC);
-extern void SkGeBlinkTimer(unsigned long data);
-
-#ifdef DEBUG
-static void	DumpMsg(struct sk_buff*, char*);
-static void	DumpData(char*, int);
-static void	DumpLong(char*, int);
-#endif
-
-/* global variables *********************************************************/
-static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
-extern const struct ethtool_ops SkGeEthtoolOps;
-
-/* local variables **********************************************************/
-static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
-static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
-
-/*****************************************************************************
- *
- *	SkPciWriteCfgDWord - write a 32 bit value to pci config space
- *
- * Description:
- *	This routine writes a 32 bit value to the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-static inline int SkPciWriteCfgDWord(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U32 Val)		/* pointer to store the read value */
-{
-	pci_write_config_dword(pAC->PciDev, PciAddr, Val);
-	return(0);
-} /* SkPciWriteCfgDWord */
-
-/*****************************************************************************
- *
- * 	SkGeInitPCI - Init the PCI resources
- *
- * Description:
- *	This function initialize the PCI resources and IO
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-static __devinit int SkGeInitPCI(SK_AC *pAC)
-{
-	struct SK_NET_DEVICE *dev = pAC->dev[0];
-	struct pci_dev *pdev = pAC->PciDev;
-	int retval;
-
-	dev->mem_start = pci_resource_start (pdev, 0);
-	pci_set_master(pdev);
-
-	retval = pci_request_regions(pdev, "sk98lin");
-	if (retval)
-		goto out;
-
-#ifdef SK_BIG_ENDIAN
-	/*
-	 * On big endian machines, we use the adapter's aibility of
-	 * reading the descriptors as big endian.
-	 */
-	{
-		SK_U32		our2;
-		SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2);
-		our2 |= PCI_REV_DESC;
-		SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
-	}
-#endif
-
-	/*
-	 * Remap the regs into kernel space.
-	 */
-	pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000);
-	if (!pAC->IoBase) {
-		retval = -EIO;
-		goto out_release;
-	}
-
-	return 0;
-
- out_release:
-	pci_release_regions(pdev);
- out:
-	return retval;
-}
-
-
-/*****************************************************************************
- *
- * 	FreeResources - release resources allocated for adapter
- *
- * Description:
- *	This function releases the IRQ, unmaps the IO and
- *	frees the desriptor ring.
- *
- * Returns: N/A
- *	
- */
-static void FreeResources(struct SK_NET_DEVICE *dev)
-{
-SK_U32 AllocFlag;
-DEV_NET		*pNet;
-SK_AC		*pAC;
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	AllocFlag = pAC->AllocFlag;
-	if (pAC->PciDev) {
-		pci_release_regions(pAC->PciDev);
-	}
-	if (AllocFlag & SK_ALLOC_IRQ) {
-		free_irq(dev->irq, dev);
-	}
-	if (pAC->IoBase) {
-		iounmap(pAC->IoBase);
-	}
-	if (pAC->pDescrMem) {
-		BoardFreeMem(pAC);
-	}
-	
-} /* FreeResources */
-
-MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
-MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
-MODULE_LICENSE("GPL");
-
-#ifdef LINK_SPEED_A
-static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED;
-#else
-static char *Speed_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef LINK_SPEED_B
-static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED;
-#else
-static char *Speed_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef AUTO_NEG_A
-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
-#else
-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef DUP_CAP_A
-static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A;
-#else
-static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef FLOW_CTRL_A
-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A;
-#else
-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef ROLE_A
-static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A;
-#else
-static char *Role_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef AUTO_NEG_B
-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B;
-#else
-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef DUP_CAP_B
-static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B;
-#else
-static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef FLOW_CTRL_B
-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B;
-#else
-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef ROLE_B
-static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B;
-#else
-static char *Role_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef CON_TYPE
-static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE;
-#else
-static char *ConType[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef PREF_PORT
-static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT;
-#else
-static char *PrefPort[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef RLMT_MODE
-static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE;
-#else
-static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-static int   IntsPerSec[SK_MAX_CARD_PARAM];
-static char *Moderation[SK_MAX_CARD_PARAM];
-static char *ModerationMask[SK_MAX_CARD_PARAM];
-static char *AutoSizing[SK_MAX_CARD_PARAM];
-static char *Stats[SK_MAX_CARD_PARAM];
-
-module_param_array(Speed_A, charp, NULL, 0);
-module_param_array(Speed_B, charp, NULL, 0);
-module_param_array(AutoNeg_A, charp, NULL, 0);
-module_param_array(AutoNeg_B, charp, NULL, 0);
-module_param_array(DupCap_A, charp, NULL, 0);
-module_param_array(DupCap_B, charp, NULL, 0);
-module_param_array(FlowCtrl_A, charp, NULL, 0);
-module_param_array(FlowCtrl_B, charp, NULL, 0);
-module_param_array(Role_A, charp, NULL, 0);
-module_param_array(Role_B, charp, NULL, 0);
-module_param_array(ConType, charp, NULL, 0);
-module_param_array(PrefPort, charp, NULL, 0);
-module_param_array(RlmtMode, charp, NULL, 0);
-/* used for interrupt moderation */
-module_param_array(IntsPerSec, int, NULL, 0);
-module_param_array(Moderation, charp, NULL, 0);
-module_param_array(Stats, charp, NULL, 0);
-module_param_array(ModerationMask, charp, NULL, 0);
-module_param_array(AutoSizing, charp, NULL, 0);
-
-/*****************************************************************************
- *
- * 	SkGeBoardInit - do level 0 and 1 initialization
- *
- * Description:
- *	This function prepares the board hardware for running. The desriptor
- *	ring is set up, the IRQ is allocated and the configuration settings
- *	are examined.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
-{
-short	i;
-unsigned long Flags;
-char	*DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */
-char	*VerStr	= VER_STRING;
-int	Ret;			/* return code of request_irq */
-SK_BOOL	DualNet;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("IoBase: %08lX\n", (unsigned long)pAC->IoBase));
-	for (i=0; i<SK_MAX_MACS; i++) {
-		pAC->TxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0];
-		pAC->TxPort[i][0].PortIndex = i;
-		pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i];
-		pAC->RxPort[i].PortIndex = i;
-	}
-
-	/* Initialize the mutexes */
-	for (i=0; i<SK_MAX_MACS; i++) {
-		spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock);
-		spin_lock_init(&pAC->RxPort[i].RxDesRingLock);
-	}
-	spin_lock_init(&pAC->SlowPathLock);
-
-	/* setup phy_id blink timer */
-	pAC->BlinkTimer.function = SkGeBlinkTimer;
-	pAC->BlinkTimer.data = (unsigned long) dev;
-	init_timer(&pAC->BlinkTimer);
-
-	/* level 0 init common modules here */
-	
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	/* Does a RESET on board ...*/
-	if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
-		printk("HWInit (0) failed.\n");
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		return -EIO;
-	}
-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_DATA);
-	SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA);
-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA);
-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA);
-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA);
-
-	pAC->BoardLevel = SK_INIT_DATA;
-	pAC->RxBufSize  = ETH_BUF_SIZE;
-
-	SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString);
-	SK_PNMI_SET_DRIVER_VER(pAC, VerStr);
-
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	/* level 1 init common modules here (HW init) */
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
-		printk("sk98lin: HWInit (1) failed.\n");
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		return -EIO;
-	}
-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_IO);
-	SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
-
-	/* Set chipset type support */
-	pAC->ChipsetType = 0;
-	if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) ||
-		(pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) {
-		pAC->ChipsetType = 1;
-	}
-
-	GetConfiguration(pAC);
-	if (pAC->RlmtNets == 2) {
-		pAC->GIni.GIPortUsage = SK_MUL_LINK;
-	}
-
-	pAC->BoardLevel = SK_INIT_IO;
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	if (pAC->GIni.GIMacsFound == 2) {
-		 Ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
-	} else if (pAC->GIni.GIMacsFound == 1) {
-		Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED,
-			"sk98lin", dev);
-	} else {
-		printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
-		       pAC->GIni.GIMacsFound);
-		return -EIO;
-	}
-
-	if (Ret) {
-		printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
-		       dev->irq);
-		return Ret;
-	}
-	pAC->AllocFlag |= SK_ALLOC_IRQ;
-
-	/* Alloc memory for this board (Mem for RxD/TxD) : */
-	if(!BoardAllocMem(pAC)) {
-		printk("No memory for descriptor rings.\n");
-		return -ENOMEM;
-	}
-
-	BoardInitMem(pAC);
-	/* tschilling: New common function with minimum size check. */
-	DualNet = SK_FALSE;
-	if (pAC->RlmtNets == 2) {
-		DualNet = SK_TRUE;
-	}
-	
-	if (SkGeInitAssignRamToQueues(
-		pAC,
-		pAC->ActivePort,
-		DualNet)) {
-		BoardFreeMem(pAC);
-		printk("sk98lin: SkGeInitAssignRamToQueues failed.\n");
-		return -EIO;
-	}
-
-	return (0);
-} /* SkGeBoardInit */
-
-
-/*****************************************************************************
- *
- * 	BoardAllocMem - allocate the memory for the descriptor rings
- *
- * Description:
- *	This function allocates the memory for all descriptor rings.
- *	Each ring is aligned for the desriptor alignment and no ring
- *	has a 4 GByte boundary in it (because the upper 32 bit must
- *	be constant for all descriptiors in one rings).
- *
- * Returns:
- *	SK_TRUE, if all memory could be allocated
- *	SK_FALSE, if not
- */
-static __devinit SK_BOOL BoardAllocMem(SK_AC	*pAC)
-{
-caddr_t		pDescrMem;	/* pointer to descriptor memory area */
-size_t		AllocLength;	/* length of complete descriptor area */
-int		i;		/* loop counter */
-unsigned long	BusAddr;
-
-	
-	/* rings plus one for alignment (do not cross 4 GB boundary) */
-	/* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */
-#if (BITS_PER_LONG == 32)
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
-#else
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
-		+ RX_RING_SIZE + 8;
-#endif
-
-	pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength,
-					 &pAC->pDescrMemDMA);
-
-	if (pDescrMem == NULL) {
-		return (SK_FALSE);
-	}
-	pAC->pDescrMem = pDescrMem;
-	BusAddr = (unsigned long) pAC->pDescrMemDMA;
-
-	/* Descriptors need 8 byte alignment, and this is ensured
-	 * by pci_alloc_consistent.
-	 */
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
-			("TX%d/A: pDescrMem: %lX,   PhysDescrMem: %lX\n",
-			i, (unsigned long) pDescrMem,
-			BusAddr));
-		pAC->TxPort[i][0].pTxDescrRing = pDescrMem;
-		pAC->TxPort[i][0].VTxDescrRing = BusAddr;
-		pDescrMem += TX_RING_SIZE;
-		BusAddr += TX_RING_SIZE;
-	
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
-			("RX%d: pDescrMem: %lX,   PhysDescrMem: %lX\n",
-			i, (unsigned long) pDescrMem,
-			(unsigned long)BusAddr));
-		pAC->RxPort[i].pRxDescrRing = pDescrMem;
-		pAC->RxPort[i].VRxDescrRing = BusAddr;
-		pDescrMem += RX_RING_SIZE;
-		BusAddr += RX_RING_SIZE;
-	} /* for */
-	
-	return (SK_TRUE);
-} /* BoardAllocMem */
-
-
-/****************************************************************************
- *
- *	BoardFreeMem - reverse of BoardAllocMem
- *
- * Description:
- *	Free all memory allocated in BoardAllocMem: adapter context,
- *	descriptor rings, locks.
- *
- * Returns:	N/A
- */
-static void BoardFreeMem(
-SK_AC		*pAC)
-{
-size_t		AllocLength;	/* length of complete descriptor area */
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("BoardFreeMem\n"));
-#if (BITS_PER_LONG == 32)
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
-#else
-	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
-		+ RX_RING_SIZE + 8;
-#endif
-
-	pci_free_consistent(pAC->PciDev, AllocLength,
-			    pAC->pDescrMem, pAC->pDescrMemDMA);
-	pAC->pDescrMem = NULL;
-} /* BoardFreeMem */
-
-
-/*****************************************************************************
- *
- * 	BoardInitMem - initiate the descriptor rings
- *
- * Description:
- *	This function sets the descriptor rings up in memory.
- *	The adapter is initialized with the descriptor start addresses.
- *
- * Returns:	N/A
- */
-static __devinit void BoardInitMem(SK_AC *pAC)
-{
-int	i;		/* loop counter */
-int	RxDescrSize;	/* the size of a rx descriptor rounded up to alignment*/
-int	TxDescrSize;	/* the size of a tx descriptor rounded up to alignment*/
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("BoardInitMem\n"));
-
-	RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
-	pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize;
-	TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
-	pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize;
-	
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		SetupRing(
-			pAC,
-			pAC->TxPort[i][0].pTxDescrRing,
-			pAC->TxPort[i][0].VTxDescrRing,
-			(RXD**)&pAC->TxPort[i][0].pTxdRingHead,
-			(RXD**)&pAC->TxPort[i][0].pTxdRingTail,
-			(RXD**)&pAC->TxPort[i][0].pTxdRingPrev,
-			&pAC->TxPort[i][0].TxdRingFree,
-			SK_TRUE);
-		SetupRing(
-			pAC,
-			pAC->RxPort[i].pRxDescrRing,
-			pAC->RxPort[i].VRxDescrRing,
-			&pAC->RxPort[i].pRxdRingHead,
-			&pAC->RxPort[i].pRxdRingTail,
-			&pAC->RxPort[i].pRxdRingPrev,
-			&pAC->RxPort[i].RxdRingFree,
-			SK_FALSE);
-	}
-} /* BoardInitMem */
-
-
-/*****************************************************************************
- *
- * 	SetupRing - create one descriptor ring
- *
- * Description:
- *	This function creates one descriptor ring in the given memory area.
- *	The head, tail and number of free descriptors in the ring are set.
- *
- * Returns:
- *	none
- */
-static void SetupRing(
-SK_AC		*pAC,
-void		*pMemArea,	/* a pointer to the memory area for the ring */
-uintptr_t	VMemArea,	/* the virtual bus address of the memory area */
-RXD		**ppRingHead,	/* address where the head should be written */
-RXD		**ppRingTail,	/* address where the tail should be written */
-RXD		**ppRingPrev,	/* address where the tail should be written */
-int		*pRingFree,	/* address where the # of free descr. goes */
-SK_BOOL		IsTx)		/* flag: is this a tx ring */
-{
-int	i;		/* loop counter */
-int	DescrSize;	/* the size of a descriptor rounded up to alignment*/
-int	DescrNum;	/* number of descriptors per ring */
-RXD	*pDescr;	/* pointer to a descriptor (receive or transmit) */
-RXD	*pNextDescr;	/* pointer to the next descriptor */
-RXD	*pPrevDescr;	/* pointer to the previous descriptor */
-uintptr_t VNextDescr;	/* the virtual bus address of the next descriptor */
-
-	if (IsTx == SK_TRUE) {
-		DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *
-			DESCR_ALIGN;
-		DescrNum = TX_RING_SIZE / DescrSize;
-	} else {
-		DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *
-			DESCR_ALIGN;
-		DescrNum = RX_RING_SIZE / DescrSize;
-	}
-	
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
-		("Descriptor size: %d   Descriptor Number: %d\n",
-		DescrSize,DescrNum));
-	
-	pDescr = (RXD*) pMemArea;
-	pPrevDescr = NULL;
-	pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
-	VNextDescr = VMemArea + DescrSize;
-	for(i=0; i<DescrNum; i++) {
-		/* set the pointers right */
-		pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
-		pDescr->pNextRxd = pNextDescr;
-		if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN;
-
-		/* advance one step */
-		pPrevDescr = pDescr;
-		pDescr = pNextDescr;
-		pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
-		VNextDescr += DescrSize;
-	}
-	pPrevDescr->pNextRxd = (RXD*) pMemArea;
-	pPrevDescr->VNextRxd = VMemArea;
-	pDescr = (RXD*) pMemArea;
-	*ppRingHead = (RXD*) pMemArea;
-	*ppRingTail = *ppRingHead;
-	*ppRingPrev = pPrevDescr;
-	*pRingFree = DescrNum;
-} /* SetupRing */
-
-
-/*****************************************************************************
- *
- * 	PortReInitBmu - re-initiate the descriptor rings for one port
- *
- * Description:
- *	This function reinitializes the descriptor rings of one port
- *	in memory. The port must be stopped before.
- *	The HW is initialized with the descriptor start addresses.
- *
- * Returns:
- *	none
- */
-static void PortReInitBmu(
-SK_AC	*pAC,		/* pointer to adapter context */
-int	PortIndex)	/* index of the port for which to re-init */
-{
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("PortReInitBmu "));
-
-	/* set address of first descriptor of ring in BMU */
-	SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L,
-		(uint32_t)(((caddr_t)
-		(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
-		pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
-		pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) &
-		0xFFFFFFFF));
-	SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H,
-		(uint32_t)(((caddr_t)
-		(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
-		pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
-		pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32));
-	SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L,
-		(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
-		pAC->RxPort[PortIndex].pRxDescrRing +
-		pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF));
-	SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H,
-		(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
-		pAC->RxPort[PortIndex].pRxDescrRing +
-		pAC->RxPort[PortIndex].VRxDescrRing) >> 32));
-} /* PortReInitBmu */
-
-
-/****************************************************************************
- *
- *	SkGeIsr - handle adapter interrupts
- *
- * Description:
- *	The interrupt routine is called when the network adapter
- *	generates an interrupt. It may also be called if another device
- *	shares this interrupt vector with the driver.
- *
- * Returns: N/A
- *
- */
-static SkIsrRetVar SkGeIsr(int irq, void *dev_id)
-{
-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
-DEV_NET		*pNet;
-SK_AC		*pAC;
-SK_U32		IntSrc;		/* interrupts source register contents */	
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	/*
-	 * Check and process if its our interrupt
-	 */
-	SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
-	if (IntSrc == 0) {
-		return SkIsrRetNone;
-	}
-
-	while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
-#if 0 /* software irq currently not used */
-		if (IntSrc & IS_IRQ_SW) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("Software IRQ\n"));
-		}
-#endif
-		if (IntSrc & IS_R1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF RX1 IRQ\n"));
-			ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
-			SK_PNMI_CNT_RX_INTR(pAC, 0);
-		}
-		if (IntSrc & IS_R2_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF RX2 IRQ\n"));
-			ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
-			SK_PNMI_CNT_RX_INTR(pAC, 1);
-		}
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		if (IntSrc & IS_XA1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF AS TX1 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 0);
-			spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-			FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
-			spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-		}
-		if (IntSrc & IS_XA2_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF AS TX2 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 1);
-			spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
-			FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
-			spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
-		}
-#if 0 /* only if sync. queues used */
-		if (IntSrc & IS_XS1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF SY TX1 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 1);
-			spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-			FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
-			spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-			ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
-		}
-		if (IntSrc & IS_XS2_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF SY TX2 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 1);
-			spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
-			FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
-			spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
-			ClearTxIrq(pAC, 1, TX_PRIO_HIGH);
-		}
-#endif
-#endif
-
-		/* do all IO at once */
-		if (IntSrc & IS_R1_F)
-			ClearAndStartRx(pAC, 0);
-		if (IntSrc & IS_R2_F)
-			ClearAndStartRx(pAC, 1);
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		if (IntSrc & IS_XA1_F)
-			ClearTxIrq(pAC, 0, TX_PRIO_LOW);
-		if (IntSrc & IS_XA2_F)
-			ClearTxIrq(pAC, 1, TX_PRIO_LOW);
-#endif
-		SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
-	} /* while (IntSrc & IRQ_MASK != 0) */
-
-	IntSrc &= pAC->GIni.GIValIrqMask;
-	if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
-			("SPECIAL IRQ DP-Cards => %x\n", IntSrc));
-		pAC->CheckQueue = SK_FALSE;
-		spin_lock(&pAC->SlowPathLock);
-		if (IntSrc & SPECIAL_IRQS)
-			SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
-
-		SkEventDispatcher(pAC, pAC->IoBase);
-		spin_unlock(&pAC->SlowPathLock);
-	}
-	/*
-	 * do it all again is case we cleared an interrupt that
-	 * came in after handling the ring (OUTs may be delayed
-	 * in hardware buffers, but are through after IN)
-	 *
-	 * rroesler: has been commented out and shifted to
-	 *           SkGeDrvEvent(), because it is timer
-	 *           guarded now
-	 *
-	ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
-	ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
-	 */
-
-	if (pAC->CheckQueue) {
-		pAC->CheckQueue = SK_FALSE;
-		spin_lock(&pAC->SlowPathLock);
-		SkEventDispatcher(pAC, pAC->IoBase);
-		spin_unlock(&pAC->SlowPathLock);
-	}
-
-	/* IRQ is processed - Enable IRQs again*/
-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-
-		return SkIsrRetHandled;
-} /* SkGeIsr */
-
-
-/****************************************************************************
- *
- *	SkGeIsrOnePort - handle adapter interrupts for single port adapter
- *
- * Description:
- *	The interrupt routine is called when the network adapter
- *	generates an interrupt. It may also be called if another device
- *	shares this interrupt vector with the driver.
- *	This is the same as above, but handles only one port.
- *
- * Returns: N/A
- *
- */
-static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id)
-{
-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
-DEV_NET		*pNet;
-SK_AC		*pAC;
-SK_U32		IntSrc;		/* interrupts source register contents */	
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	/*
-	 * Check and process if its our interrupt
-	 */
-	SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
-	if (IntSrc == 0) {
-		return SkIsrRetNone;
-	}
-	
-	while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
-#if 0 /* software irq currently not used */
-		if (IntSrc & IS_IRQ_SW) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("Software IRQ\n"));
-		}
-#endif
-		if (IntSrc & IS_R1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF RX1 IRQ\n"));
-			ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
-			SK_PNMI_CNT_RX_INTR(pAC, 0);
-		}
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		if (IntSrc & IS_XA1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF AS TX1 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 0);
-			spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-			FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
-			spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-		}
-#if 0 /* only if sync. queues used */
-		if (IntSrc & IS_XS1_F) {
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_INT_SRC,
-				("EOF SY TX1 IRQ\n"));
-			SK_PNMI_CNT_TX_INTR(pAC, 0);
-			spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-			FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
-			spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-			ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
-		}
-#endif
-#endif
-
-		/* do all IO at once */
-		if (IntSrc & IS_R1_F)
-			ClearAndStartRx(pAC, 0);
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
-		if (IntSrc & IS_XA1_F)
-			ClearTxIrq(pAC, 0, TX_PRIO_LOW);
-#endif
-		SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
-	} /* while (IntSrc & IRQ_MASK != 0) */
-	
-	IntSrc &= pAC->GIni.GIValIrqMask;
-	if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
-			("SPECIAL IRQ SP-Cards => %x\n", IntSrc));
-		pAC->CheckQueue = SK_FALSE;
-		spin_lock(&pAC->SlowPathLock);
-		if (IntSrc & SPECIAL_IRQS)
-			SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
-
-		SkEventDispatcher(pAC, pAC->IoBase);
-		spin_unlock(&pAC->SlowPathLock);
-	}
-	/*
-	 * do it all again is case we cleared an interrupt that
-	 * came in after handling the ring (OUTs may be delayed
-	 * in hardware buffers, but are through after IN)
-	 *
-	 * rroesler: has been commented out and shifted to
-	 *           SkGeDrvEvent(), because it is timer
-	 *           guarded now
-	 *
-	ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
-	 */
-
-	/* IRQ is processed - Enable IRQs again*/
-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-
-		return SkIsrRetHandled;
-} /* SkGeIsrOnePort */
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/****************************************************************************
- *
- * 	SkGePollController - polling receive, for netconsole
- *
- * Description:
- *	Polling receive - used by netconsole and other diagnostic tools
- *	to allow network i/o with interrupts disabled.
- *
- * Returns: N/A
- */
-static void SkGePollController(struct net_device *dev)
-{
-	disable_irq(dev->irq);
-	SkGeIsr(dev->irq, dev);
-	enable_irq(dev->irq);
-}
-#endif
-
-/****************************************************************************
- *
- *	SkGeOpen - handle start of initialized adapter
- *
- * Description:
- *	This function starts the initialized adapter.
- *	The board level variable is set and the adapter is
- *	brought to full functionality.
- *	The device flags are set for operation.
- *	Do all necessary level 2 initialization, enable interrupts and
- *	give start command to RLMT.
- *
- * Returns:
- *	0 on success
- *	!= 0 on error
- */
-static int SkGeOpen(
-struct SK_NET_DEVICE	*dev)
-{
-	DEV_NET			*pNet;
-	SK_AC			*pAC;
-	unsigned long	Flags;		/* for spin lock */
-	int				i;
-	SK_EVPARA		EvPara;		/* an event parameter union */
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));
-
-#ifdef SK_DIAG_SUPPORT
-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
-		if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-			return (-1);   /* still in use by diag; deny actions */
-		} 
-	}
-#endif
-
-	/* Set blink mode */
-	if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab ))
-		pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE;
-
-	if (pAC->BoardLevel == SK_INIT_DATA) {
-		/* level 1 init common modules here */
-		if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
-			printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name);
-			return (-1);
-		}
-		SkI2cInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		SkEventInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		SkPnmiInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		SkAddrInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		SkRlmtInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		SkTimerInit	(pAC, pAC->IoBase, SK_INIT_IO);
-		pAC->BoardLevel = SK_INIT_IO;
-	}
-
-	if (pAC->BoardLevel != SK_INIT_RUN) {
-		/* tschilling: Level 2 init modules here, check return value. */
-		if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) {
-			printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name);
-			return (-1);
-		}
-		SkI2cInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		SkEventInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		SkPnmiInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		SkAddrInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		SkRlmtInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		SkTimerInit	(pAC, pAC->IoBase, SK_INIT_RUN);
-		pAC->BoardLevel = SK_INIT_RUN;
-	}
-
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		/* Enable transmit descriptor polling. */
-		SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
-		FillRxRing(pAC, &pAC->RxPort[i]);
-	}
-	SkGeYellowLED(pAC, pAC->IoBase, 1);
-
-	StartDrvCleanupTimer(pAC);
-	SkDimEnableModerationIfNeeded(pAC);	
-	SkDimDisplayModerationSettings(pAC);
-
-	pAC->GIni.GIValIrqMask &= IRQ_MASK;
-
-	/* enable Interrupts */
-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-	SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
-
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
-	if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) {
-		EvPara.Para32[0] = pAC->RlmtNets;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
-			EvPara);
-		EvPara.Para32[0] = pAC->RlmtMode;
-		EvPara.Para32[1] = 0;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE,
-			EvPara);
-	}
-
-	EvPara.Para32[0] = pNet->NetNr;
-	EvPara.Para32[1] = -1;
-	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-	SkEventDispatcher(pAC, pAC->IoBase);
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	pAC->MaxPorts++;
-
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeOpen suceeded\n"));
-
-	return (0);
-} /* SkGeOpen */
-
-
-/****************************************************************************
- *
- *	SkGeClose - Stop initialized adapter
- *
- * Description:
- *	Close initialized adapter.
- *
- * Returns:
- *	0 - on success
- *	error code - on error
- */
-static int SkGeClose(
-struct SK_NET_DEVICE	*dev)
-{
-	DEV_NET		*pNet;
-	DEV_NET		*newPtrNet;
-	SK_AC		*pAC;
-
-	unsigned long	Flags;		/* for spin lock */
-	int		i;
-	int		PortIdx;
-	SK_EVPARA	EvPara;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-
-#ifdef SK_DIAG_SUPPORT
-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
-		if (pAC->DiagFlowCtrl == SK_FALSE) {
-			/* 
-			** notify that the interface which has been closed
-			** by operator interaction must not be started up 
-			** again when the DIAG has finished. 
-			*/
-			newPtrNet = netdev_priv(pAC->dev[0]);
-			if (newPtrNet == pNet) {
-				pAC->WasIfUp[0] = SK_FALSE;
-			} else {
-				pAC->WasIfUp[1] = SK_FALSE;
-			}
-			return 0; /* return to system everything is fine... */
-		} else {
-			pAC->DiagFlowCtrl = SK_FALSE;
-		}
-	}
-#endif
-
-	netif_stop_queue(dev);
-
-	if (pAC->RlmtNets == 1)
-		PortIdx = pAC->ActivePort;
-	else
-		PortIdx = pNet->NetNr;
-
-        StopDrvCleanupTimer(pAC);
-
-	/*
-	 * Clear multicast table, promiscuous mode ....
-	 */
-	SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
-	SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-		SK_PROM_MODE_NONE);
-
-	if (pAC->MaxPorts == 1) {
-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-		/* disable interrupts */
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		EvPara.Para32[0] = pNet->NetNr;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		SkEventDispatcher(pAC, pAC->IoBase);
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		/* stop the hardware */
-		SkGeDeInit(pAC, pAC->IoBase);
-		pAC->BoardLevel = SK_INIT_DATA;
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	} else {
-
-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-		EvPara.Para32[0] = pNet->NetNr;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara);
-		SkEventDispatcher(pAC, pAC->IoBase);
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		
-		/* Stop port */
-		spin_lock_irqsave(&pAC->TxPort[pNet->PortNr]
-			[TX_PRIO_LOW].TxDesRingLock, Flags);
-		SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
-			SK_STOP_ALL, SK_HARD_RST);
-		spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr]
-			[TX_PRIO_LOW].TxDesRingLock, Flags);
-	}
-
-	if (pAC->RlmtNets == 1) {
-		/* clear all descriptor rings */
-		for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-			ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
-			ClearRxRing(pAC, &pAC->RxPort[i]);
-			ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]);
-		}
-	} else {
-		/* clear port descriptor rings */
-		ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
-		ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
-		ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
-	}
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeClose: done "));
-
-	SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
-	SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), 
-			sizeof(SK_PNMI_STRUCT_DATA));
-
-	pAC->MaxPorts--;
-
-	return (0);
-} /* SkGeClose */
-
-
-/*****************************************************************************
- *
- * 	SkGeXmit - Linux frame transmit function
- *
- * Description:
- *	The system calls this function to send frames onto the wire.
- *	It puts the frame in the tx descriptor ring. If the ring is
- *	full then, the 'tbusy' flag is set.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- * WARNING: returning 1 in 'tbusy' case caused system crashes (double
- *	allocated skb's) !!!
- */
-static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)
-{
-DEV_NET		*pNet;
-SK_AC		*pAC;
-int			Rc;	/* return code of XmitFrame */
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-
-	if ((!skb_shinfo(skb)->nr_frags) ||
-		(pAC->GIni.GIChipId == CHIP_ID_GENESIS)) {
-		/* Don't activate scatter-gather and hardware checksum */
-
-		if (pAC->RlmtNets == 2)
-			Rc = XmitFrame(
-				pAC,
-				&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
-				skb);
-		else
-			Rc = XmitFrame(
-				pAC,
-				&pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
-				skb);
-	} else {
-		/* scatter-gather and hardware TCP checksumming anabled*/
-		if (pAC->RlmtNets == 2)
-			Rc = XmitFrameSG(
-				pAC,
-				&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
-				skb);
-		else
-			Rc = XmitFrameSG(
-				pAC,
-				&pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
-				skb);
-	}
-
-	/* Transmitter out of resources? */
-	if (Rc <= 0) {
-		netif_stop_queue(dev);
-	}
-
-	/* If not taken, give buffer ownership back to the
-	 * queueing layer.
-	 */
-	if (Rc < 0)
-		return (1);
-
-	dev->trans_start = jiffies;
-	return (0);
-} /* SkGeXmit */
-
-
-/*****************************************************************************
- *
- * 	XmitFrame - fill one socket buffer into the transmit ring
- *
- * Description:
- *	This function puts a message into the transmit descriptor ring
- *	if there is a descriptors left.
- *	Linux skb's consist of only one continuous buffer.
- *	The first step locks the ring. It is held locked
- *	all time to avoid problems with SWITCH_../PORT_RESET.
- *	Then the descriptoris allocated.
- *	The second part is linking the buffer to the descriptor.
- *	At the very last, the Control field of the descriptor
- *	is made valid for the BMU and a start TX command is given
- *	if necessary.
- *
- * Returns:
- *	> 0 - on succes: the number of bytes in the message
- *	= 0 - on resource shortage: this frame sent or dropped, now
- *		the ring is full ( -> set tbusy)
- *	< 0 - on failure: other problems ( -> return failure to upper layers)
- */
-static int XmitFrame(
-SK_AC 		*pAC,		/* pointer to adapter context           */
-TX_PORT		*pTxPort,	/* pointer to struct of port to send to */
-struct sk_buff	*pMessage)	/* pointer to send-message              */
-{
-	TXD		*pTxd;		/* the rxd to fill */
-	TXD		*pOldTxd;
-	unsigned long	 Flags;
-	SK_U64		 PhysAddr;
-	int		 BytesSend = pMessage->len;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
-
-	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-#ifndef USE_TX_COMPLETE
-	FreeTxDescriptors(pAC, pTxPort);
-#endif
-	if (pTxPort->TxdRingFree == 0) {
-		/* 
-		** no enough free descriptors in ring at the moment.
-		** Maybe free'ing some old one help?
-		*/
-		FreeTxDescriptors(pAC, pTxPort);
-		if (pTxPort->TxdRingFree == 0) {
-			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-			SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_TX_PROGRESS,
-				("XmitFrame failed\n"));
-			/* 
-			** the desired message can not be sent
-			** Because tbusy seems to be set, the message 
-			** should not be freed here. It will be used 
-			** by the scheduler of the ethernet handler 
-			*/
-			return (-1);
-		}
-	}
-
-	/*
-	** If the passed socket buffer is of smaller MTU-size than 60,
-	** copy everything into new buffer and fill all bytes between
-	** the original packet end and the new packet end of 60 with 0x00.
-	** This is to resolve faulty padding by the HW with 0xaa bytes.
-	*/
-	if (BytesSend < C_LEN_ETHERNET_MINSIZE) {
-		if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) {
-			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-			return 0;
-		}
-		pMessage->len = C_LEN_ETHERNET_MINSIZE;
-	}
-
-	/* 
-	** advance head counter behind descriptor needed for this frame, 
-	** so that needed descriptor is reserved from that on. The next
-	** action will be to add the passed buffer to the TX-descriptor
-	*/
-	pTxd = pTxPort->pTxdRingHead;
-	pTxPort->pTxdRingHead = pTxd->pNextTxd;
-	pTxPort->TxdRingFree--;
-
-#ifdef SK_DUMP_TX
-	DumpMsg(pMessage, "XmitFrame");
-#endif
-
-	/* 
-	** First step is to map the data to be sent via the adapter onto
-	** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4
-	** and 2.6 need to use pci_map_page() for that mapping.
-	*/
-	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
-					virt_to_page(pMessage->data),
-					((unsigned long) pMessage->data & ~PAGE_MASK),
-					pMessage->len,
-					PCI_DMA_TODEVICE);
-	pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
-	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-	pTxd->pMBuf     = pMessage;
-
-	if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
-		u16 hdrlen = skb_transport_offset(pMessage);
-		u16 offset = hdrlen + pMessage->csum_offset;
-
-		if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
-			(pAC->GIni.GIChipRev == 0) &&
-			(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
-			pTxd->TBControl = BMU_TCP_CHECK;
-		} else {
-			pTxd->TBControl = BMU_UDP_CHECK;
-		}
-
-		pTxd->TcpSumOfs = 0;
-		pTxd->TcpSumSt  = hdrlen;
-		pTxd->TcpSumWr  = offset;
-
-		pTxd->TBControl |= BMU_OWN | BMU_STF | 
-				   BMU_SW  | BMU_EOF |
-#ifdef USE_TX_COMPLETE
-				   BMU_IRQ_EOF |
-#endif
-				   pMessage->len;
-        } else {
-		pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK | 
-				  BMU_SW  | BMU_EOF |
-#ifdef USE_TX_COMPLETE
-				   BMU_IRQ_EOF |
-#endif
-			pMessage->len;
-	}
-
-	/* 
-	** If previous descriptor already done, give TX start cmd 
-	*/
-	pOldTxd = xchg(&pTxPort->pTxdRingPrev, pTxd);
-	if ((pOldTxd->TBControl & BMU_OWN) == 0) {
-		SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
-	}	
-
-	/* 
-	** after releasing the lock, the skb may immediately be free'd 
-	*/
-	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-	if (pTxPort->TxdRingFree != 0) {
-		return (BytesSend);
-	} else {
-		return (0);
-	}
-
-} /* XmitFrame */
-
-/*****************************************************************************
- *
- * 	XmitFrameSG - fill one socket buffer into the transmit ring
- *                (use SG and TCP/UDP hardware checksumming)
- *
- * Description:
- *	This function puts a message into the transmit descriptor ring
- *	if there is a descriptors left.
- *
- * Returns:
- *	> 0 - on succes: the number of bytes in the message
- *	= 0 - on resource shortage: this frame sent or dropped, now
- *		the ring is full ( -> set tbusy)
- *	< 0 - on failure: other problems ( -> return failure to upper layers)
- */
-static int XmitFrameSG(
-SK_AC 		*pAC,		/* pointer to adapter context           */
-TX_PORT		*pTxPort,	/* pointer to struct of port to send to */
-struct sk_buff	*pMessage)	/* pointer to send-message              */
-{
-
-	TXD		*pTxd;
-	TXD		*pTxdFst;
-	TXD		*pTxdLst;
-	int 	 	 CurrFrag;
-	int		 BytesSend;
-	skb_frag_t	*sk_frag;
-	SK_U64		 PhysAddr;
-	unsigned long	 Flags;
-	SK_U32		 Control;
-
-	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-#ifndef USE_TX_COMPLETE
-	FreeTxDescriptors(pAC, pTxPort);
-#endif
-	if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) {
-		FreeTxDescriptors(pAC, pTxPort);
-		if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) {
-			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-			SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_TX_PROGRESS,
-				("XmitFrameSG failed - Ring full\n"));
-				/* this message can not be sent now */
-			return(-1);
-		}
-	}
-
-	pTxd      = pTxPort->pTxdRingHead;
-	pTxdFst   = pTxd;
-	pTxdLst   = pTxd;
-	BytesSend = 0;
-
-	/* 
-	** Map the first fragment (header) into the DMA-space
-	*/
-	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
-			virt_to_page(pMessage->data),
-			((unsigned long) pMessage->data & ~PAGE_MASK),
-			skb_headlen(pMessage),
-			PCI_DMA_TODEVICE);
-
-	pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
-	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-
-	/* 
-	** Does the HW need to evaluate checksum for TCP or UDP packets? 
-	*/
-	if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
-		u16 hdrlen = skb_transport_offset(pMessage);
-		u16 offset = hdrlen + pMessage->csum_offset;
-
-		Control = BMU_STFWD;
-
-		/* 
-		** We have to use the opcode for tcp here,  because the
-		** opcode for udp is not working in the hardware yet 
-		** (Revision 2.0)
-		*/
-		if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
-			(pAC->GIni.GIChipRev == 0) &&
-			(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
-			Control |= BMU_TCP_CHECK;
-		} else {
-			Control |= BMU_UDP_CHECK;
-		}
-
-		pTxd->TcpSumOfs = 0;
-		pTxd->TcpSumSt  = hdrlen;
-		pTxd->TcpSumWr  = offset;
-	} else
-		Control = BMU_CHECK | BMU_SW;
-
-	pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage);
-
-	pTxd = pTxd->pNextTxd;
-	pTxPort->TxdRingFree--;
-	BytesSend += skb_headlen(pMessage);
-
-	/* 
-	** Browse over all SG fragments and map each of them into the DMA space
-	*/
-	for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) {
-		sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag];
-		/* 
-		** we already have the proper value in entry
-		*/
-		PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
-						 sk_frag->page,
-						 sk_frag->page_offset,
-						 sk_frag->size,
-						 PCI_DMA_TODEVICE);
-
-		pTxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
-		pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-		pTxd->pMBuf     = pMessage;
-		
-		pTxd->TBControl = Control | BMU_OWN | sk_frag->size;
-
-		/* 
-		** Do we have the last fragment? 
-		*/
-		if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags )  {
-#ifdef USE_TX_COMPLETE
-			pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF;
-#else
-			pTxd->TBControl |= BMU_EOF;
-#endif
-			pTxdFst->TBControl |= BMU_OWN | BMU_SW;
-		}
-		pTxdLst = pTxd;
-		pTxd    = pTxd->pNextTxd;
-		pTxPort->TxdRingFree--;
-		BytesSend += sk_frag->size;
-	}
-
-	/* 
-	** If previous descriptor already done, give TX start cmd 
-	*/
-	if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) {
-		SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
-	}
-
-	pTxPort->pTxdRingPrev = pTxdLst;
-	pTxPort->pTxdRingHead = pTxd;
-
-	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-
-	if (pTxPort->TxdRingFree > 0) {
-		return (BytesSend);
-	} else {
-		return (0);
-	}
-}
-
-/*****************************************************************************
- *
- * 	FreeTxDescriptors - release descriptors from the descriptor ring
- *
- * Description:
- *	This function releases descriptors from a transmit ring if they
- *	have been sent by the BMU.
- *	If a descriptors is sent, it can be freed and the message can
- *	be freed, too.
- *	The SOFTWARE controllable bit is used to prevent running around a
- *	completely free ring for ever. If this bit is no set in the
- *	frame (by XmitFrame), this frame has never been sent or is
- *	already freed.
- *	The Tx descriptor ring lock must be held while calling this function !!!
- *
- * Returns:
- *	none
- */
-static void FreeTxDescriptors(
-SK_AC	*pAC,		/* pointer to the adapter context */
-TX_PORT	*pTxPort)	/* pointer to destination port structure */
-{
-TXD	*pTxd;		/* pointer to the checked descriptor */
-TXD	*pNewTail;	/* pointer to 'end' of the ring */
-SK_U32	Control;	/* TBControl field of descriptor */
-SK_U64	PhysAddr;	/* address of DMA mapping */
-
-	pNewTail = pTxPort->pTxdRingTail;
-	pTxd     = pNewTail;
-	/*
-	** loop forever; exits if BMU_SW bit not set in start frame
-	** or BMU_OWN bit set in any frame
-	*/
-	while (1) {
-		Control = pTxd->TBControl;
-		if ((Control & BMU_SW) == 0) {
-			/*
-			** software controllable bit is set in first
-			** fragment when given to BMU. Not set means that
-			** this fragment was never sent or is already
-			** freed ( -> ring completely free now).
-			*/
-			pTxPort->pTxdRingTail = pTxd;
-			netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
-			return;
-		}
-		if (Control & BMU_OWN) {
-			pTxPort->pTxdRingTail = pTxd;
-			if (pTxPort->TxdRingFree > 0) {
-				netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
-			}
-			return;
-		}
-		
-		/* 
-		** release the DMA mapping, because until not unmapped
-		** this buffer is considered being under control of the
-		** adapter card!
-		*/
-		PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
-		PhysAddr |= (SK_U64) pTxd->VDataLow;
-		pci_unmap_page(pAC->PciDev, PhysAddr,
-				 pTxd->pMBuf->len,
-				 PCI_DMA_TODEVICE);
-
-		if (Control & BMU_EOF)
-			DEV_KFREE_SKB_ANY(pTxd->pMBuf);	/* free message */
-
-		pTxPort->TxdRingFree++;
-		pTxd->TBControl &= ~BMU_SW;
-		pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
-	} /* while(forever) */
-} /* FreeTxDescriptors */
-
-/*****************************************************************************
- *
- * 	FillRxRing - fill the receive ring with valid descriptors
- *
- * Description:
- *	This function fills the receive ring descriptors with data
- *	segments and makes them valid for the BMU.
- *	The active ring is filled completely, if possible.
- *	The non-active ring is filled only partial to save memory.
- *
- * Description of rx ring structure:
- *	head - points to the descriptor which will be used next by the BMU
- *	tail - points to the next descriptor to give to the BMU
- *	
- * Returns:	N/A
- */
-static void FillRxRing(
-SK_AC		*pAC,		/* pointer to the adapter context */
-RX_PORT		*pRxPort)	/* ptr to port struct for which the ring
-				   should be filled */
-{
-unsigned long	Flags;
-
-	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
-	while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) {
-		if(!FillRxDescriptor(pAC, pRxPort))
-			break;
-	}
-	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
-} /* FillRxRing */
-
-
-/*****************************************************************************
- *
- * 	FillRxDescriptor - fill one buffer into the receive ring
- *
- * Description:
- *	The function allocates a new receive buffer and
- *	puts it into the next descriptor.
- *
- * Returns:
- *	SK_TRUE - a buffer was added to the ring
- *	SK_FALSE - a buffer could not be added
- */
-static SK_BOOL FillRxDescriptor(
-SK_AC		*pAC,		/* pointer to the adapter context struct */
-RX_PORT		*pRxPort)	/* ptr to port struct of ring to fill */
-{
-struct sk_buff	*pMsgBlock;	/* pointer to a new message block */
-RXD		*pRxd;		/* the rxd to fill */
-SK_U16		Length;		/* data fragment length */
-SK_U64		PhysAddr;	/* physical address of a rx buffer */
-
-	pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC);
-	if (pMsgBlock == NULL) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-			SK_DBGCAT_DRV_ENTRY,
-			("%s: Allocation of rx buffer failed !\n",
-			pAC->dev[pRxPort->PortIndex]->name));
-		SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex);
-		return(SK_FALSE);
-	}
-	skb_reserve(pMsgBlock, 2); /* to align IP frames */
-	/* skb allocated ok, so add buffer */
-	pRxd = pRxPort->pRxdRingTail;
-	pRxPort->pRxdRingTail = pRxd->pNextRxd;
-	pRxPort->RxdRingFree--;
-	Length = pAC->RxBufSize;
-	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
-		virt_to_page(pMsgBlock->data),
-		((unsigned long) pMsgBlock->data &
-		~PAGE_MASK),
-		pAC->RxBufSize - 2,
-		PCI_DMA_FROMDEVICE);
-
-	pRxd->VDataLow  = (SK_U32) (PhysAddr & 0xffffffff);
-	pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-	pRxd->pMBuf     = pMsgBlock;
-	pRxd->RBControl = BMU_OWN       | 
-			  BMU_STF       | 
-			  BMU_IRQ_EOF   | 
-			  BMU_TCP_CHECK | 
-			  Length;
-	return (SK_TRUE);
-
-} /* FillRxDescriptor */
-
-
-/*****************************************************************************
- *
- * 	ReQueueRxBuffer - fill one buffer back into the receive ring
- *
- * Description:
- *	Fill a given buffer back into the rx ring. The buffer
- *	has been previously allocated and aligned, and its phys.
- *	address calculated, so this is no more necessary.
- *
- * Returns: N/A
- */
-static void ReQueueRxBuffer(
-SK_AC		*pAC,		/* pointer to the adapter context struct */
-RX_PORT		*pRxPort,	/* ptr to port struct of ring to fill */
-struct sk_buff	*pMsg,		/* pointer to the buffer */
-SK_U32		PhysHigh,	/* phys address high dword */
-SK_U32		PhysLow)	/* phys address low dword */
-{
-RXD		*pRxd;		/* the rxd to fill */
-SK_U16		Length;		/* data fragment length */
-
-	pRxd = pRxPort->pRxdRingTail;
-	pRxPort->pRxdRingTail = pRxd->pNextRxd;
-	pRxPort->RxdRingFree--;
-	Length = pAC->RxBufSize;
-
-	pRxd->VDataLow  = PhysLow;
-	pRxd->VDataHigh = PhysHigh;
-	pRxd->pMBuf     = pMsg;
-	pRxd->RBControl = BMU_OWN       | 
-			  BMU_STF       |
-			  BMU_IRQ_EOF   | 
-			  BMU_TCP_CHECK | 
-			  Length;
-	return;
-} /* ReQueueRxBuffer */
-
-/*****************************************************************************
- *
- * 	ReceiveIrq - handle a receive IRQ
- *
- * Description:
- *	This function is called when a receive IRQ is set.
- *	It walks the receive descriptor ring and sends up all
- *	frames that are complete.
- *
- * Returns:	N/A
- */
-static void ReceiveIrq(
-	SK_AC		*pAC,			/* pointer to adapter context */
-	RX_PORT		*pRxPort,		/* pointer to receive port struct */
-	SK_BOOL		SlowPathLock)	/* indicates if SlowPathLock is needed */
-{
-RXD				*pRxd;			/* pointer to receive descriptors */
-SK_U32			Control;		/* control field of descriptor */
-struct sk_buff	*pMsg;			/* pointer to message holding frame */
-struct sk_buff	*pNewMsg;		/* pointer to a new message for copying frame */
-int				FrameLength;	/* total length of received frame */
-SK_MBUF			*pRlmtMbuf;		/* ptr to a buffer for giving a frame to rlmt */
-SK_EVPARA		EvPara;			/* an event parameter union */	
-unsigned long	Flags;			/* for spin lock */
-int				PortIndex = pRxPort->PortIndex;
-unsigned int	Offset;
-unsigned int	NumBytes;
-unsigned int	ForRlmt;
-SK_BOOL			IsBc;
-SK_BOOL			IsMc;
-SK_BOOL  IsBadFrame; 			/* Bad frame */
-
-SK_U32			FrameStat;
-SK_U64			PhysAddr;
-
-rx_start:	
-	/* do forever; exit if BMU_OWN found */
-	for ( pRxd = pRxPort->pRxdRingHead ;
-		  pRxPort->RxdRingFree < pAC->RxDescrPerRing ;
-		  pRxd = pRxd->pNextRxd,
-		  pRxPort->pRxdRingHead = pRxd,
-		  pRxPort->RxdRingFree ++) {
-
-		/*
-		 * For a better understanding of this loop
-		 * Go through every descriptor beginning at the head
-		 * Please note: the ring might be completely received so the OWN bit
-		 * set is not a good crirteria to leave that loop.
-		 * Therefore the RingFree counter is used.
-		 * On entry of this loop pRxd is a pointer to the Rxd that needs
-		 * to be checked next.
-		 */
-
-		Control = pRxd->RBControl;
-	
-		/* check if this descriptor is ready */
-		if ((Control & BMU_OWN) != 0) {
-			/* this descriptor is not yet ready */
-			/* This is the usual end of the loop */
-			/* We don't need to start the ring again */
-			FillRxRing(pAC, pRxPort);
-			return;
-		}
-                pAC->DynIrqModInfo.NbrProcessedDescr++;
-
-		/* get length of frame and check it */
-		FrameLength = Control & BMU_BBC;
-		if (FrameLength > pAC->RxBufSize) {
-			goto rx_failed;
-		}
-
-		/* check for STF and EOF */
-		if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) {
-			goto rx_failed;
-		}
-
-		/* here we have a complete frame in the ring */
-		pMsg = pRxd->pMBuf;
-
-		FrameStat = pRxd->FrameStat;
-
-		/* check for frame length mismatch */
-#define XMR_FS_LEN_SHIFT        18
-#define GMR_FS_LEN_SHIFT        16
-		if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-			if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-					SK_DBGCAT_DRV_RX_PROGRESS,
-					("skge: Frame length mismatch (%u/%u).\n",
-					FrameLength,
-					(SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
-				goto rx_failed;
-			}
-		}
-		else {
-			if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-					SK_DBGCAT_DRV_RX_PROGRESS,
-					("skge: Frame length mismatch (%u/%u).\n",
-					FrameLength,
-					(SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
-				goto rx_failed;
-			}
-		}
-
-		/* Set Rx Status */
-		if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-			IsBc = (FrameStat & XMR_FS_BC) != 0;
-			IsMc = (FrameStat & XMR_FS_MC) != 0;
-			IsBadFrame = (FrameStat &
-				(XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0;
-		} else {
-			IsBc = (FrameStat & GMR_FS_BC) != 0;
-			IsMc = (FrameStat & GMR_FS_MC) != 0;
-			IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) ||
-							((FrameStat & GMR_FS_RX_OK) == 0));
-		}
-
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
-			("Received frame of length %d on port %d\n",
-			FrameLength, PortIndex));
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
-			("Number of free rx descriptors: %d\n",
-			pRxPort->RxdRingFree));
-/* DumpMsg(pMsg, "Rx");	*/
-
-		if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {
-#if 0
-			(FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {
-#endif
-			/* there is a receive error in this frame */
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_RX_PROGRESS,
-				("skge: Error in received frame, dropped!\n"
-				"Control: %x\nRxStat: %x\n",
-				Control, FrameStat));
-
-			ReQueueRxBuffer(pAC, pRxPort, pMsg,
-				pRxd->VDataHigh, pRxd->VDataLow);
-
-			continue;
-		}
-
-		/*
-		 * if short frame then copy data to reduce memory waste
-		 */
-		if ((FrameLength < SK_COPY_THRESHOLD) &&
-			((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) {
-			/*
-			 * Short frame detected and allocation successfull
-			 */
-			/* use new skb and copy data */
-			skb_reserve(pNewMsg, 2);
-			skb_put(pNewMsg, FrameLength);
-			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
-			PhysAddr |= (SK_U64) pRxd->VDataLow;
-
-			pci_dma_sync_single_for_cpu(pAC->PciDev,
-						    (dma_addr_t) PhysAddr,
-						    FrameLength,
-						    PCI_DMA_FROMDEVICE);
-			skb_copy_to_linear_data(pNewMsg, pMsg, FrameLength);
-
-			pci_dma_sync_single_for_device(pAC->PciDev,
-						       (dma_addr_t) PhysAddr,
-						       FrameLength,
-						       PCI_DMA_FROMDEVICE);
-			ReQueueRxBuffer(pAC, pRxPort, pMsg,
-				pRxd->VDataHigh, pRxd->VDataLow);
-
-			pMsg = pNewMsg;
-
-		}
-		else {
-			/*
-			 * if large frame, or SKB allocation failed, pass
-			 * the SKB directly to the networking
-			 */
-
-			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
-			PhysAddr |= (SK_U64) pRxd->VDataLow;
-
-			/* release the DMA mapping */
-			pci_unmap_single(pAC->PciDev,
-					 PhysAddr,
-					 pAC->RxBufSize - 2,
-					 PCI_DMA_FROMDEVICE);
-
-			/* set length in message */
-			skb_put(pMsg, FrameLength);
-		} /* frame > SK_COPY_TRESHOLD */
-
-#ifdef USE_SK_RX_CHECKSUM
-		pMsg->csum = pRxd->TcpSums & 0xffff;
-		pMsg->ip_summed = CHECKSUM_COMPLETE;
-#else
-		pMsg->ip_summed = CHECKSUM_NONE;
-#endif
-
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("V"));
-		ForRlmt = SK_RLMT_RX_PROTOCOL;
-#if 0
-		IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;
-#endif
-		SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,
-			IsBc, &Offset, &NumBytes);
-		if (NumBytes != 0) {
-#if 0
-			IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;
-#endif
-			SK_RLMT_LOOKAHEAD(pAC, PortIndex,
-				&pMsg->data[Offset],
-				IsBc, IsMc, &ForRlmt);
-		}
-		if (ForRlmt == SK_RLMT_RX_PROTOCOL) {
-					SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("W"));
-			/* send up only frames from active port */
-			if ((PortIndex == pAC->ActivePort) ||
-				(pAC->RlmtNets == 2)) {
-				/* frame for upper layer */
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U"));
-#ifdef xDEBUG
-				DumpMsg(pMsg, "Rx");
-#endif
-				SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,
-					FrameLength, pRxPort->PortIndex);
-
-				pMsg->protocol = eth_type_trans(pMsg,
-					pAC->dev[pRxPort->PortIndex]);
-				netif_rx(pMsg);
-				pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
-			}
-			else {
-				/* drop frame */
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-					SK_DBGCAT_DRV_RX_PROGRESS,
-					("D"));
-				DEV_KFREE_SKB(pMsg);
-			}
-			
-		} /* if not for rlmt */
-		else {
-			/* packet for rlmt */
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-				SK_DBGCAT_DRV_RX_PROGRESS, ("R"));
-			pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
-				pAC->IoBase, FrameLength);
-			if (pRlmtMbuf != NULL) {
-				pRlmtMbuf->pNext = NULL;
-				pRlmtMbuf->Length = FrameLength;
-				pRlmtMbuf->PortIdx = PortIndex;
-				EvPara.pParaPtr = pRlmtMbuf;
-				memcpy((char*)(pRlmtMbuf->pData),
-					   (char*)(pMsg->data),
-					   FrameLength);
-
-				/* SlowPathLock needed? */
-				if (SlowPathLock == SK_TRUE) {
-					spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-					SkEventQueue(pAC, SKGE_RLMT,
-						SK_RLMT_PACKET_RECEIVED,
-						EvPara);
-					pAC->CheckQueue = SK_TRUE;
-					spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-				} else {
-					SkEventQueue(pAC, SKGE_RLMT,
-						SK_RLMT_PACKET_RECEIVED,
-						EvPara);
-					pAC->CheckQueue = SK_TRUE;
-				}
-
-				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
-					SK_DBGCAT_DRV_RX_PROGRESS,
-					("Q"));
-			}
-			if ((pAC->dev[pRxPort->PortIndex]->flags &
-				(IFF_PROMISC | IFF_ALLMULTI)) != 0 ||
-				(ForRlmt & SK_RLMT_RX_PROTOCOL) ==
-				SK_RLMT_RX_PROTOCOL) {
-				pMsg->protocol = eth_type_trans(pMsg,
-					pAC->dev[pRxPort->PortIndex]);
-				netif_rx(pMsg);
-				pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
-			}
-			else {
-				DEV_KFREE_SKB(pMsg);
-			}
-
-		} /* if packet for rlmt */
-	} /* for ... scanning the RXD ring */
-
-	/* RXD ring is empty -> fill and restart */
-	FillRxRing(pAC, pRxPort);
-	/* do not start if called from Close */
-	if (pAC->BoardLevel > SK_INIT_DATA) {
-		ClearAndStartRx(pAC, PortIndex);
-	}
-	return;
-
-rx_failed:
-	/* remove error frame */
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
-		("Schrottdescriptor, length: 0x%x\n", FrameLength));
-
-	/* release the DMA mapping */
-
-	PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
-	PhysAddr |= (SK_U64) pRxd->VDataLow;
-	pci_unmap_page(pAC->PciDev,
-			 PhysAddr,
-			 pAC->RxBufSize - 2,
-			 PCI_DMA_FROMDEVICE);
-	DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
-	pRxd->pMBuf = NULL;
-	pRxPort->RxdRingFree++;
-	pRxPort->pRxdRingHead = pRxd->pNextRxd;
-	goto rx_start;
-
-} /* ReceiveIrq */
-
-
-/*****************************************************************************
- *
- * 	ClearAndStartRx - give a start receive command to BMU, clear IRQ
- *
- * Description:
- *	This function sends a start command and a clear interrupt
- *	command for one receive queue to the BMU.
- *
- * Returns: N/A
- *	none
- */
-static void ClearAndStartRx(
-SK_AC	*pAC,		/* pointer to the adapter context */
-int	PortIndex)	/* index of the receive port (XMAC) */
-{
-	SK_OUT8(pAC->IoBase,
-		RxQueueAddr[PortIndex]+Q_CSR,
-		CSR_START | CSR_IRQ_CL_F);
-} /* ClearAndStartRx */
-
-
-/*****************************************************************************
- *
- * 	ClearTxIrq - give a clear transmit IRQ command to BMU
- *
- * Description:
- *	This function sends a clear tx IRQ command for one
- *	transmit queue to the BMU.
- *
- * Returns: N/A
- */
-static void ClearTxIrq(
-SK_AC	*pAC,		/* pointer to the adapter context */
-int	PortIndex,	/* index of the transmit port (XMAC) */
-int	Prio)		/* priority or normal queue */
-{
-	SK_OUT8(pAC->IoBase, 
-		TxQueueAddr[PortIndex][Prio]+Q_CSR,
-		CSR_IRQ_CL_F);
-} /* ClearTxIrq */
-
-
-/*****************************************************************************
- *
- * 	ClearRxRing - remove all buffers from the receive ring
- *
- * Description:
- *	This function removes all receive buffers from the ring.
- *	The receive BMU must be stopped before calling this function.
- *
- * Returns: N/A
- */
-static void ClearRxRing(
-SK_AC	*pAC,		/* pointer to adapter context */
-RX_PORT	*pRxPort)	/* pointer to rx port struct */
-{
-RXD		*pRxd;	/* pointer to the current descriptor */
-unsigned long	Flags;
-SK_U64		PhysAddr;
-
-	if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
-		return;
-	}
-	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
-	pRxd = pRxPort->pRxdRingHead;
-	do {
-		if (pRxd->pMBuf != NULL) {
-
-			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
-			PhysAddr |= (SK_U64) pRxd->VDataLow;
-			pci_unmap_page(pAC->PciDev,
-					 PhysAddr,
-					 pAC->RxBufSize - 2,
-					 PCI_DMA_FROMDEVICE);
-			DEV_KFREE_SKB(pRxd->pMBuf);
-			pRxd->pMBuf = NULL;
-		}
-		pRxd->RBControl &= BMU_OWN;
-		pRxd = pRxd->pNextRxd;
-		pRxPort->RxdRingFree++;
-	} while (pRxd != pRxPort->pRxdRingTail);
-	pRxPort->pRxdRingTail = pRxPort->pRxdRingHead;
-	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
-} /* ClearRxRing */
-
-/*****************************************************************************
- *
- *	ClearTxRing - remove all buffers from the transmit ring
- *
- * Description:
- *	This function removes all transmit buffers from the ring.
- *	The transmit BMU must be stopped before calling this function
- *	and transmitting at the upper level must be disabled.
- *	The BMU own bit of all descriptors is cleared, the rest is
- *	done by calling FreeTxDescriptors.
- *
- * Returns: N/A
- */
-static void ClearTxRing(
-SK_AC	*pAC,		/* pointer to adapter context */
-TX_PORT	*pTxPort)	/* pointer to tx prt struct */
-{
-TXD		*pTxd;		/* pointer to the current descriptor */
-int		i;
-unsigned long	Flags;
-
-	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-	pTxd = pTxPort->pTxdRingHead;
-	for (i=0; i<pAC->TxDescrPerRing; i++) {
-		pTxd->TBControl &= ~BMU_OWN;
-		pTxd = pTxd->pNextTxd;
-	}
-	FreeTxDescriptors(pAC, pTxPort);
-	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-} /* ClearTxRing */
-
-/*****************************************************************************
- *
- * 	SkGeSetMacAddr - Set the hardware MAC address
- *
- * Description:
- *	This function sets the MAC address used by the adapter.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
-{
-
-DEV_NET *pNet = netdev_priv(dev);
-SK_AC	*pAC = pNet->pAC;
-
-struct sockaddr	*addr = p;
-unsigned long	Flags;
-	
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeSetMacAddr starts now...\n"));
-	if(netif_running(dev))
-		return -EBUSY;
-
-	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
-	
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
-	if (pAC->RlmtNets == 2)
-		SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr,
-			(SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
-	else
-		SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort,
-			(SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
-
-	
-	
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	return 0;
-} /* SkGeSetMacAddr */
-
-
-/*****************************************************************************
- *
- * 	SkGeSetRxMode - set receive mode
- *
- * Description:
- *	This function sets the receive mode of an adapter. The adapter
- *	supports promiscuous mode, allmulticast mode and a number of
- *	multicast addresses. If more multicast addresses the available
- *	are selected, a hash function in the hardware is used.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static void SkGeSetRxMode(struct SK_NET_DEVICE *dev)
-{
-
-DEV_NET		*pNet;
-SK_AC		*pAC;
-
-struct dev_mc_list	*pMcList;
-int			i;
-int			PortIdx;
-unsigned long		Flags;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeSetRxMode starts now... "));
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	if (pAC->RlmtNets == 1)
-		PortIdx = pAC->ActivePort;
-	else
-		PortIdx = pNet->NetNr;
-
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	if (dev->flags & IFF_PROMISC) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-			("PROMISCUOUS mode\n"));
-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-			SK_PROM_MODE_LLC);
-	} else if (dev->flags & IFF_ALLMULTI) {
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-			("ALLMULTI mode\n"));
-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-			SK_PROM_MODE_ALL_MC);
-	} else {
-		SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
-			SK_PROM_MODE_NONE);
-		SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
-
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-			("Number of MC entries: %d ", dev->mc_count));
-		
-		pMcList = dev->mc_list;
-		for (i=0; i<dev->mc_count; i++, pMcList = pMcList->next) {
-			SkAddrMcAdd(pAC, pAC->IoBase, PortIdx,
-				(SK_MAC_ADDR*)pMcList->dmi_addr, 0);
-			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA,
-				("%02x:%02x:%02x:%02x:%02x:%02x\n",
-				pMcList->dmi_addr[0],
-				pMcList->dmi_addr[1],
-				pMcList->dmi_addr[2],
-				pMcList->dmi_addr[3],
-				pMcList->dmi_addr[4],
-				pMcList->dmi_addr[5]));
-		}
-		SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx);
-	}
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	
-	return;
-} /* SkGeSetRxMode */
-
-
-/*****************************************************************************
- *
- * 	SkGeChangeMtu - set the MTU to another value
- *
- * Description:
- *	This function sets is called whenever the MTU size is changed
- *	(ifconfig mtu xxx dev ethX). If the MTU is bigger than standard
- *	ethernet MTU size, long frame support is activated.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
-{
-DEV_NET		*pNet;
-struct net_device *pOtherDev;
-SK_AC		*pAC;
-unsigned long	Flags;
-int		i;
-SK_EVPARA 	EvPara;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeChangeMtu starts now...\n"));
-
-	pNet = netdev_priv(dev);
-	pAC  = pNet->pAC;
-
-	if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
-		return -EINVAL;
-	}
-
-	if(pAC->BoardLevel != SK_INIT_RUN) {
-		return -EINVAL;
-	}
-
-#ifdef SK_DIAG_SUPPORT
-	if (pAC->DiagModeActive == DIAG_ACTIVE) {
-		if (pAC->DiagFlowCtrl == SK_FALSE) {
-			return -1; /* still in use, deny any actions of MTU */
-		} else {
-			pAC->DiagFlowCtrl = SK_FALSE;
-		}
-	}
-#endif
-
-	pOtherDev = pAC->dev[1 - pNet->NetNr];
-
-	if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500)
-	     && (NewMtu <= 1500))
-		return 0;
-
-	pAC->RxBufSize = NewMtu + 32;
-	dev->mtu = NewMtu;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("New MTU: %d\n", NewMtu));
-
-	/* 
-	** Prevent any reconfiguration while changing the MTU 
-	** by disabling any interrupts 
-	*/
-	SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
-	/* 
-	** Notify RLMT that any ports are to be stopped
-	*/
-	EvPara.Para32[0] =  0;
-	EvPara.Para32[1] = -1;
-	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		EvPara.Para32[0] =  1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-	} else {
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-	}
-
-	/*
-	** After calling the SkEventDispatcher(), RLMT is aware about
-	** the stopped ports -> configuration can take place!
-	*/
-	SkEventDispatcher(pAC, pAC->IoBase);
-
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
-		netif_stop_queue(pAC->dev[i]);
-
-	}
-
-	/*
-	** Depending on the desired MTU size change, a different number of 
-	** RX buffers need to be allocated
-	*/
-	if (NewMtu > 1500) {
-	    /* 
-	    ** Use less rx buffers 
-	    */
-	    for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		    pAC->RxPort[i].RxFillLimit =  pAC->RxDescrPerRing -
-						 (pAC->RxDescrPerRing / 4);
-		} else {
-		    if (i == pAC->ActivePort) {
-			pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 
-						    (pAC->RxDescrPerRing / 4);
-		    } else {
-			pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - 
-						    (pAC->RxDescrPerRing / 10);
-		    }
-		}
-	    }
-	} else {
-	    /* 
-	    ** Use the normal amount of rx buffers 
-	    */
-	    for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		    pAC->RxPort[i].RxFillLimit = 1;
-		} else {
-		    if (i == pAC->ActivePort) {
-			pAC->RxPort[i].RxFillLimit = 1;
-		    } else {
-			pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
-						    (pAC->RxDescrPerRing / 4);
-		    }
-		}
-	    }
-	}
-	
-	SkGeDeInit(pAC, pAC->IoBase);
-
-	/*
-	** enable/disable hardware support for long frames
-	*/
-	if (NewMtu > 1500) {
-// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
-		pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
-	} else {
-	    if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		pAC->GIni.GIPortUsage = SK_MUL_LINK;
-	    } else {
-		pAC->GIni.GIPortUsage = SK_RED_LINK;
-	    }
-	}
-
-	SkGeInit(   pAC, pAC->IoBase, SK_INIT_IO);
-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_IO);
-	SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
-	
-	/*
-	** tschilling:
-	** Speed and others are set back to default in level 1 init!
-	*/
-	GetConfiguration(pAC);
-	
-	SkGeInit(   pAC, pAC->IoBase, SK_INIT_RUN);
-	SkI2cInit(  pAC, pAC->IoBase, SK_INIT_RUN);
-	SkEventInit(pAC, pAC->IoBase, SK_INIT_RUN);
-	SkPnmiInit( pAC, pAC->IoBase, SK_INIT_RUN);
-	SkAddrInit( pAC, pAC->IoBase, SK_INIT_RUN);
-	SkRlmtInit( pAC, pAC->IoBase, SK_INIT_RUN);
-	SkTimerInit(pAC, pAC->IoBase, SK_INIT_RUN);
-
-	/*
-	** clear and reinit the rx rings here
-	*/
-	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
-		ClearRxRing(pAC, &pAC->RxPort[i]);
-		FillRxRing(pAC, &pAC->RxPort[i]);
-
-		/* 
-		** Enable transmit descriptor polling
-		*/
-		SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
-		FillRxRing(pAC, &pAC->RxPort[i]);
-	};
-
-	SkGeYellowLED(pAC, pAC->IoBase, 1);
-	SkDimEnableModerationIfNeeded(pAC);	
-	SkDimDisplayModerationSettings(pAC);
-
-	netif_start_queue(pAC->dev[pNet->PortNr]);
-	for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
-		spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
-	}
-
-	/* 
-	** Enable Interrupts again 
-	*/
-	SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-	SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
-
-	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-	SkEventDispatcher(pAC, pAC->IoBase);
-
-	/* 
-	** Notify RLMT about the changing and restarting one (or more) ports
-	*/
-	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		EvPara.Para32[0] = pAC->RlmtNets;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara);
-		EvPara.Para32[0] = pNet->PortNr;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-			
-		if (netif_running(pOtherDev)) {
-			DEV_NET *pOtherNet = netdev_priv(pOtherDev);
-			EvPara.Para32[0] = pOtherNet->PortNr;
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-		}
-	} else {
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-	}
-
-	SkEventDispatcher(pAC, pAC->IoBase);
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	
-	/*
-	** While testing this driver with latest kernel 2.5 (2.5.70), it 
-	** seems as if upper layers have a problem to handle a successful
-	** return value of '0'. If such a zero is returned, the complete 
-	** system hangs for several minutes (!), which is in acceptable.
-	**
-	** Currently it is not clear, what the exact reason for this problem
-	** is. The implemented workaround for 2.5 is to return the desired 
-	** new MTU size if all needed changes for the new MTU size where 
-	** performed. In kernels 2.2 and 2.4, a zero value is returned,
-	** which indicates the successful change of the mtu-size.
-	*/
-	return NewMtu;
-
-} /* SkGeChangeMtu */
-
-
-/*****************************************************************************
- *
- * 	SkGeStats - return ethernet device statistics
- *
- * Description:
- *	This function return statistic data about the ethernet device
- *	to the operating system.
- *
- * Returns:
- *	pointer to the statistic structure.
- */
-static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
-{
-DEV_NET *pNet = netdev_priv(dev);
-SK_AC	*pAC = pNet->pAC;
-SK_PNMI_STRUCT_DATA *pPnmiStruct;       /* structure for all Pnmi-Data */
-SK_PNMI_STAT    *pPnmiStat;             /* pointer to virtual XMAC stat. data */
-SK_PNMI_CONF    *pPnmiConf;             /* pointer to virtual link config. */
-unsigned int    Size;                   /* size of pnmi struct */
-unsigned long	Flags;			/* for spin lock */
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeStats starts now...\n"));
-	pPnmiStruct = &pAC->PnmiStruct;
-
-#ifdef SK_DIAG_SUPPORT
-        if ((pAC->DiagModeActive == DIAG_NOTACTIVE) &&
-                (pAC->BoardLevel == SK_INIT_RUN)) {
-#endif
-        SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA));
-        spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-        Size = SK_PNMI_STRUCT_SIZE;
-		SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr);
-        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-#ifdef SK_DIAG_SUPPORT
-	}
-#endif
-
-        pPnmiStat = &pPnmiStruct->Stat[0];
-        pPnmiConf = &pPnmiStruct->Conf[0];
-
-	pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF;
-	pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF;
-	pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
-	pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
-	
-        if (dev->mtu <= 1500) {
-                pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
-        } else {
-                pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
-                        pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
-	}
-
-
-	if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12)
-		pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts;
-
-	pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
-	pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF;
-	pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF;
-	pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF;
-	pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
-
-	/* detailed rx_errors: */
-	pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF;
-	pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
-	pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF;
-	pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF;
-	pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
-	pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF;
-
-	/* detailed tx_errors */
-	pAC->stats.tx_aborted_errors = (SK_U32) 0;
-	pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
-	pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF;
-	pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
-	pAC->stats.tx_window_errors = (SK_U32) 0;
-
-	return(&pAC->stats);
-} /* SkGeStats */
-
-/*
- * Basic MII register access
- */
-static int SkGeMiiIoctl(struct net_device *dev,
-			struct mii_ioctl_data *data, int cmd)
-{
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	SK_IOC IoC = pAC->IoBase;
-	int Port = pNet->PortNr;
-	SK_GEPORT *pPrt = &pAC->GIni.GP[Port];
-	unsigned long Flags;
-	int err = 0;
-	int reg = data->reg_num & 0x1f;
-	SK_U16 val = data->val_in;
-
-	if (!netif_running(dev))
-		return -ENODEV;	/* Phy still in reset */
-
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	switch(cmd) {
-	case SIOCGMIIPHY:
-		data->phy_id = pPrt->PhyAddr;
-
-		/* fallthru */
-	case SIOCGMIIREG:
-		if (pAC->GIni.GIGenesis)
-			SkXmPhyRead(pAC, IoC, Port, reg, &val);
-		else
-			SkGmPhyRead(pAC, IoC, Port, reg, &val);
-
-		data->val_out = val;
-		break;
-
-	case SIOCSMIIREG:
-		if (!capable(CAP_NET_ADMIN))
-			err = -EPERM;
-
-		else if (pAC->GIni.GIGenesis)
-			SkXmPhyWrite(pAC, IoC, Port, reg, val);
-		else
-			SkGmPhyWrite(pAC, IoC, Port, reg, val);
-		break;
-	default:
-		err = -EOPNOTSUPP;
-	}
-        spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	return err;
-}
-
-
-/*****************************************************************************
- *
- * 	SkGeIoctl - IO-control function
- *
- * Description:
- *	This function is called if an ioctl is issued on the device.
- *	There are three subfunction for reading, writing and test-writing
- *	the private MIB data structure (useful for SysKonnect-internal tools).
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd)
-{
-DEV_NET		*pNet;
-SK_AC		*pAC;
-void		*pMemBuf;
-struct pci_dev  *pdev = NULL;
-SK_GE_IOCTL	Ioctl;
-unsigned int	Err = 0;
-int		Size = 0;
-int             Ret = 0;
-unsigned int	Length = 0;
-int		HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeIoctl starts now...\n"));
-
-	pNet = netdev_priv(dev);
-	pAC = pNet->pAC;
-	
-	if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG)
-	    return SkGeMiiIoctl(dev, if_mii(rq), cmd);
-
-	if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) {
-		return -EFAULT;
-	}
-
-	switch(cmd) {
-	case SK_IOCTL_SETMIB:
-	case SK_IOCTL_PRESETMIB:
-		if (!capable(CAP_NET_ADMIN)) return -EPERM;
- 	case SK_IOCTL_GETMIB:
-		if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
-			Ioctl.Len<sizeof(pAC->PnmiStruct)?
-			Ioctl.Len : sizeof(pAC->PnmiStruct))) {
-			return -EFAULT;
-		}
-		Size = SkGeIocMib(pNet, Ioctl.Len, cmd);
-		if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct,
-			Ioctl.Len<Size? Ioctl.Len : Size)) {
-			return -EFAULT;
-		}
-		Ioctl.Len = Size;
-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
-			return -EFAULT;
-		}
-		break;
-	case SK_IOCTL_GEN:
-		if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
-			Length = Ioctl.Len;
-		} else {
-			Length = sizeof(pAC->PnmiStruct) + HeaderLength;
-		}
-		if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
-			return -ENOMEM;
-		}
-		if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-		if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-		if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-		Ioctl.Len = Length;
-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
-			Err = -EFAULT;
-			goto fault_gen;
-		}
-fault_gen:
-		kfree(pMemBuf); /* cleanup everything */
-		break;
-#ifdef SK_DIAG_SUPPORT
-       case SK_IOCTL_DIAG:
-		if (!capable(CAP_NET_ADMIN)) return -EPERM;
-		if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
-			Length = Ioctl.Len;
-		} else {
-			Length = sizeof(pAC->PnmiStruct) + HeaderLength;
-		}
-		if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
-			return -ENOMEM;
-		}
-		if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
-			Err = -EFAULT;
-			goto fault_diag;
-		}
-		pdev = pAC->PciDev;
-		Length = 3 * sizeof(SK_U32);  /* Error, Bus and Device */
-		/* 
-		** While coding this new IOCTL interface, only a few lines of code
-		** are to to be added. Therefore no dedicated function has been 
-		** added. If more functionality is added, a separate function 
-		** should be used...
-		*/
-		* ((SK_U32 *)pMemBuf) = 0;
-		* ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
-		* ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
-		if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
-			Err = -EFAULT;
-			goto fault_diag;
-		}
-		Ioctl.Len = Length;
-		if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
-			Err = -EFAULT;
-			goto fault_diag;
-		}
-fault_diag:
-		kfree(pMemBuf); /* cleanup everything */
-		break;
-#endif
-	default:
-		Err = -EOPNOTSUPP;
-	}
-
-	return(Err);
-
-} /* SkGeIoctl */
-
-
-/*****************************************************************************
- *
- * 	SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message
- *
- * Description:
- *	This function reads/writes the MIB data using PNMI (Private Network
- *	Management Interface).
- *	The destination for the data must be provided with the
- *	ioctl call and is given to the driver in the form of
- *	a user space address.
- *	Copying from the user-provided data area into kernel messages
- *	and back is done by copy_from_user and copy_to_user calls in
- *	SkGeIoctl.
- *
- * Returns:
- *	returned size from PNMI call
- */
-static int SkGeIocMib(
-DEV_NET		*pNet,	/* pointer to the adapter context */
-unsigned int	Size,	/* length of ioctl data */
-int		mode)	/* flag for set/preset */
-{
-unsigned long	Flags;	/* for spin lock */
-SK_AC		*pAC;
-
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("SkGeIocMib starts now...\n"));
-	pAC = pNet->pAC;
-	/* access MIB */
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	switch(mode) {
-	case SK_IOCTL_GETMIB:
-		SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
-			pNet->NetNr);
-		break;
-	case SK_IOCTL_PRESETMIB:
-		SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
-			pNet->NetNr);
-		break;
-	case SK_IOCTL_SETMIB:
-		SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
-			pNet->NetNr);
-		break;
-	default:
-		break;
-	}
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
-		("MIB data access succeeded\n"));
-	return (Size);
-} /* SkGeIocMib */
-
-
-/*****************************************************************************
- *
- * 	GetConfiguration - read configuration information
- *
- * Description:
- *	This function reads per-adapter configuration information from
- *	the options provided on the command line.
- *
- * Returns:
- *	none
- */
-static void GetConfiguration(
-SK_AC	*pAC)	/* pointer to the adapter context structure */
-{
-SK_I32	Port;		/* preferred port */
-SK_BOOL	AutoSet;
-SK_BOOL DupSet;
-int	LinkSpeed          = SK_LSPEED_AUTO;	/* Link speed */
-int	AutoNeg            = 1;			/* autoneg off (0) or on (1) */
-int	DuplexCap          = 0;			/* 0=both,1=full,2=half */
-int	FlowCtrl           = SK_FLOW_MODE_SYM_OR_REM;	/* FlowControl  */
-int	MSMode             = SK_MS_MODE_AUTO;	/* master/slave mode    */
-
-SK_BOOL IsConTypeDefined   = SK_TRUE;
-SK_BOOL IsLinkSpeedDefined = SK_TRUE;
-SK_BOOL IsFlowCtrlDefined  = SK_TRUE;
-SK_BOOL IsRoleDefined      = SK_TRUE;
-SK_BOOL IsModeDefined      = SK_TRUE;
-/*
- *	The two parameters AutoNeg. and DuplexCap. map to one configuration
- *	parameter. The mapping is described by this table:
- *	DuplexCap ->	|	both	|	full	|	half	|
- *	AutoNeg		|		|		|		|
- *	-----------------------------------------------------------------
- *	Off		|    illegal	|	Full	|	Half	|
- *	-----------------------------------------------------------------
- *	On		|   AutoBoth	|   AutoFull	|   AutoHalf	|
- *	-----------------------------------------------------------------
- *	Sense		|   AutoSense	|   AutoSense	|   AutoSense	|
- */
-int	Capabilities[3][3] =
-		{ {                -1, SK_LMODE_FULL     , SK_LMODE_HALF     },
-		  {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF },
-		  {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} };
-
-#define DC_BOTH	0
-#define DC_FULL 1
-#define DC_HALF 2
-#define AN_OFF	0
-#define AN_ON	1
-#define AN_SENS	2
-#define M_CurrPort pAC->GIni.GP[Port]
-
-
-	/*
-	** Set the default values first for both ports!
-	*/
-	for (Port = 0; Port < SK_MAX_MACS; Port++) {
-		M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
-		M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
-		M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-		M_CurrPort.PLinkSpeed    = SK_LSPEED_AUTO;
-	}
-
-	/*
-	** Check merged parameter ConType. If it has not been used,
-	** verify any other parameter (e.g. AutoNeg) and use default values. 
-	**
-	** Stating both ConType and other lowlevel link parameters is also
-	** possible. If this is the case, the passed ConType-parameter is 
-	** overwritten by the lowlevel link parameter.
-	**
-	** The following settings are used for a merged ConType-parameter:
-	**
-	** ConType   DupCap   AutoNeg   FlowCtrl      Role      Speed
-	** -------   ------   -------   --------   ----------   -----
-	**  Auto      Both      On      SymOrRem      Auto       Auto
-	**  100FD     Full      Off       None      <ignored>    100
-	**  100HD     Half      Off       None      <ignored>    100
-	**  10FD      Full      Off       None      <ignored>    10
-	**  10HD      Half      Off       None      <ignored>    10
-	** 
-	** This ConType parameter is used for all ports of the adapter!
-	*/
-        if ( (ConType != NULL)                && 
-	     (pAC->Index < SK_MAX_CARD_PARAM) &&
-	     (ConType[pAC->Index] != NULL) ) {
-
-			/* Check chipset family */
-			if ((!pAC->ChipsetType) && 
-				(strcmp(ConType[pAC->Index],"Auto")!=0) &&
-				(strcmp(ConType[pAC->Index],"")!=0)) {
-				/* Set the speed parameter back */
-					printk("sk98lin: Illegal value \"%s\" " 
-							"for ConType."
-							" Using Auto.\n", 
-							ConType[pAC->Index]);
-
-					sprintf(ConType[pAC->Index], "Auto");	
-			}
-
-				if (strcmp(ConType[pAC->Index],"")==0) {
-			IsConTypeDefined = SK_FALSE; /* No ConType defined */
-				} else if (strcmp(ConType[pAC->Index],"Auto")==0) {
-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
-			M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-			M_CurrPort.PLinkSpeed    = SK_LSPEED_AUTO;
-		    }
-                } else if (strcmp(ConType[pAC->Index],"100FD")==0) {
-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-			M_CurrPort.PLinkSpeed    = SK_LSPEED_100MBPS;
-		    }
-                } else if (strcmp(ConType[pAC->Index],"100HD")==0) {
-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-			M_CurrPort.PLinkSpeed    = SK_LSPEED_100MBPS;
-		    }
-                } else if (strcmp(ConType[pAC->Index],"10FD")==0) {
-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-			M_CurrPort.PLinkSpeed    = SK_LSPEED_10MBPS;
-		    }
-                } else if (strcmp(ConType[pAC->Index],"10HD")==0) {
-		    for (Port = 0; Port < SK_MAX_MACS; Port++) {
-			M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
-			M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
-			M_CurrPort.PMSMode       = SK_MS_MODE_AUTO;
-			M_CurrPort.PLinkSpeed    = SK_LSPEED_10MBPS;
-		    }
-                } else { 
-		    printk("sk98lin: Illegal value \"%s\" for ConType\n", 
-			ConType[pAC->Index]);
-		    IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */
-		}
-        } else {
-	    IsConTypeDefined = SK_FALSE; /* No ConType defined */
-	}
-
-	/*
-	** Parse any parameter settings for port A:
-	** a) any LinkSpeed stated?
-	*/
-	if (Speed_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		Speed_A[pAC->Index] != NULL) {
-		if (strcmp(Speed_A[pAC->Index],"")==0) {
-		    IsLinkSpeedDefined = SK_FALSE;
-		} else if (strcmp(Speed_A[pAC->Index],"Auto")==0) {
-		    LinkSpeed = SK_LSPEED_AUTO;
-		} else if (strcmp(Speed_A[pAC->Index],"10")==0) {
-		    LinkSpeed = SK_LSPEED_10MBPS;
-		} else if (strcmp(Speed_A[pAC->Index],"100")==0) {
-		    LinkSpeed = SK_LSPEED_100MBPS;
-		} else if (strcmp(Speed_A[pAC->Index],"1000")==0) {
-		    LinkSpeed = SK_LSPEED_1000MBPS;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for Speed_A\n",
-			Speed_A[pAC->Index]);
-		    IsLinkSpeedDefined = SK_FALSE;
-		}
-	} else {
-	    IsLinkSpeedDefined = SK_FALSE;
-	}
-
-	/* 
-	** Check speed parameter: 
-	**    Only copper type adapter and GE V2 cards 
-	*/
-	if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
-		((LinkSpeed != SK_LSPEED_AUTO) &&
-		(LinkSpeed != SK_LSPEED_1000MBPS))) {
-		printk("sk98lin: Illegal value for Speed_A. "
-			"Not a copper card or GE V2 card\n    Using "
-			"speed 1000\n");
-		LinkSpeed = SK_LSPEED_1000MBPS;
-	}
-	
-	/*	
-	** Decide whether to set new config value if somethig valid has
-	** been received.
-	*/
-	if (IsLinkSpeedDefined) {
-		pAC->GIni.GP[0].PLinkSpeed = LinkSpeed;
-	} 
-
-	/* 
-	** b) Any Autonegotiation and DuplexCapabilities set?
-	**    Please note that both belong together...
-	*/
-	AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */
-	AutoSet = SK_FALSE;
-	if (AutoNeg_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		AutoNeg_A[pAC->Index] != NULL) {
-		AutoSet = SK_TRUE;
-		if (strcmp(AutoNeg_A[pAC->Index],"")==0) {
-		    AutoSet = SK_FALSE;
-		} else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) {
-		    AutoNeg = AN_ON;
-		} else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) {
-		    AutoNeg = AN_OFF;
-		} else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) {
-		    AutoNeg = AN_SENS;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n",
-			AutoNeg_A[pAC->Index]);
-		}
-	}
-
-	DuplexCap = DC_BOTH;
-	DupSet    = SK_FALSE;
-	if (DupCap_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		DupCap_A[pAC->Index] != NULL) {
-		DupSet = SK_TRUE;
-		if (strcmp(DupCap_A[pAC->Index],"")==0) {
-		    DupSet = SK_FALSE;
-		} else if (strcmp(DupCap_A[pAC->Index],"Both")==0) {
-		    DuplexCap = DC_BOTH;
-		} else if (strcmp(DupCap_A[pAC->Index],"Full")==0) {
-		    DuplexCap = DC_FULL;
-		} else if (strcmp(DupCap_A[pAC->Index],"Half")==0) {
-		    DuplexCap = DC_HALF;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for DupCap_A\n",
-			DupCap_A[pAC->Index]);
-		}
-	}
-
-	/* 
-	** Check for illegal combinations 
-	*/
-	if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
-		((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
-		(DuplexCap == SK_LMODE_STAT_HALF)) &&
-		(pAC->ChipsetType)) {
-		    printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
-					"    Using Full Duplex.\n");
-				DuplexCap = DC_FULL;
-	}
-
-	if ( AutoSet && AutoNeg==AN_SENS && DupSet) {
-		printk("sk98lin, Port A: DuplexCapabilities"
-			" ignored using Sense mode\n");
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
-		printk("sk98lin: Port A: Illegal combination"
-			" of values AutoNeg. and DuplexCap.\n    Using "
-			"Full Duplex\n");
-		DuplexCap = DC_FULL;
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
-		DuplexCap = DC_FULL;
-	}
-	
-	if (!AutoSet && DupSet) {
-		printk("sk98lin: Port A: Duplex setting not"
-			" possible in\n    default AutoNegotiation mode"
-			" (Sense).\n    Using AutoNegotiation On\n");
-		AutoNeg = AN_ON;
-	}
-	
-	/* 
-	** set the desired mode 
-	*/
-	if (AutoSet || DupSet) {
-	    pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
-	}
-	
-	/* 
-	** c) Any Flowcontrol-parameter set?
-	*/
-	if (FlowCtrl_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		FlowCtrl_A[pAC->Index] != NULL) {
-		if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) {
-		    IsFlowCtrlDefined = SK_FALSE;
-		} else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) {
-		    FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
-		} else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) {
-		    FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
-		} else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) {
-		    FlowCtrl = SK_FLOW_MODE_LOC_SEND;
-		} else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) {
-		    FlowCtrl = SK_FLOW_MODE_NONE;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n",
-                        FlowCtrl_A[pAC->Index]);
-		    IsFlowCtrlDefined = SK_FALSE;
-		}
-	} else {
-	   IsFlowCtrlDefined = SK_FALSE;
-	}
-
-	if (IsFlowCtrlDefined) {
-	    if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
-		printk("sk98lin: Port A: FlowControl"
-			" impossible without AutoNegotiation,"
-			" disabled\n");
-		FlowCtrl = SK_FLOW_MODE_NONE;
-	    }
-	    pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl;
-	}
-
-	/*
-	** d) What is with the RoleParameter?
-	*/
-	if (Role_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		Role_A[pAC->Index] != NULL) {
-		if (strcmp(Role_A[pAC->Index],"")==0) {
-		   IsRoleDefined = SK_FALSE;
-		} else if (strcmp(Role_A[pAC->Index],"Auto")==0) {
-		    MSMode = SK_MS_MODE_AUTO;
-		} else if (strcmp(Role_A[pAC->Index],"Master")==0) {
-		    MSMode = SK_MS_MODE_MASTER;
-		} else if (strcmp(Role_A[pAC->Index],"Slave")==0) {
-		    MSMode = SK_MS_MODE_SLAVE;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for Role_A\n",
-			Role_A[pAC->Index]);
-		    IsRoleDefined = SK_FALSE;
-		}
-	} else {
-	   IsRoleDefined = SK_FALSE;
-	}
-
-	if (IsRoleDefined == SK_TRUE) {
-	    pAC->GIni.GP[0].PMSMode = MSMode;
-	}
-	
-
-	
-	/* 
-	** Parse any parameter settings for port B:
-	** a) any LinkSpeed stated?
-	*/
-	IsConTypeDefined   = SK_TRUE;
-	IsLinkSpeedDefined = SK_TRUE;
-	IsFlowCtrlDefined  = SK_TRUE;
-	IsModeDefined      = SK_TRUE;
-
-	if (Speed_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		Speed_B[pAC->Index] != NULL) {
-		if (strcmp(Speed_B[pAC->Index],"")==0) {
-		    IsLinkSpeedDefined = SK_FALSE;
-		} else if (strcmp(Speed_B[pAC->Index],"Auto")==0) {
-		    LinkSpeed = SK_LSPEED_AUTO;
-		} else if (strcmp(Speed_B[pAC->Index],"10")==0) {
-		    LinkSpeed = SK_LSPEED_10MBPS;
-		} else if (strcmp(Speed_B[pAC->Index],"100")==0) {
-		    LinkSpeed = SK_LSPEED_100MBPS;
-		} else if (strcmp(Speed_B[pAC->Index],"1000")==0) {
-		    LinkSpeed = SK_LSPEED_1000MBPS;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for Speed_B\n",
-			Speed_B[pAC->Index]);
-		    IsLinkSpeedDefined = SK_FALSE;
-		}
-	} else {
-	    IsLinkSpeedDefined = SK_FALSE;
-	}
-
-	/* 
-	** Check speed parameter:
-	**    Only copper type adapter and GE V2 cards 
-	*/
-	if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
-		((LinkSpeed != SK_LSPEED_AUTO) &&
-		(LinkSpeed != SK_LSPEED_1000MBPS))) {
-		printk("sk98lin: Illegal value for Speed_B. "
-			"Not a copper card or GE V2 card\n    Using "
-			"speed 1000\n");
-		LinkSpeed = SK_LSPEED_1000MBPS;
-	}
-
-	/*      
-	** Decide whether to set new config value if somethig valid has
-	** been received.
-	*/
-        if (IsLinkSpeedDefined) {
-	    pAC->GIni.GP[1].PLinkSpeed = LinkSpeed;
-	}
-
-	/* 
-	** b) Any Autonegotiation and DuplexCapabilities set?
-	**    Please note that both belong together...
-	*/
-	AutoNeg = AN_SENS; /* default: do auto Sense */
-	AutoSet = SK_FALSE;
-	if (AutoNeg_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		AutoNeg_B[pAC->Index] != NULL) {
-		AutoSet = SK_TRUE;
-		if (strcmp(AutoNeg_B[pAC->Index],"")==0) {
-		    AutoSet = SK_FALSE;
-		} else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) {
-		    AutoNeg = AN_ON;
-		} else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) {
-		    AutoNeg = AN_OFF;
-		} else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) {
-		    AutoNeg = AN_SENS;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n",
-			AutoNeg_B[pAC->Index]);
-		}
-	}
-
-	DuplexCap = DC_BOTH;
-	DupSet    = SK_FALSE;
-	if (DupCap_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		DupCap_B[pAC->Index] != NULL) {
-		DupSet = SK_TRUE;
-		if (strcmp(DupCap_B[pAC->Index],"")==0) {
-		    DupSet = SK_FALSE;
-		} else if (strcmp(DupCap_B[pAC->Index],"Both")==0) {
-		    DuplexCap = DC_BOTH;
-		} else if (strcmp(DupCap_B[pAC->Index],"Full")==0) {
-		    DuplexCap = DC_FULL;
-		} else if (strcmp(DupCap_B[pAC->Index],"Half")==0) {
-		    DuplexCap = DC_HALF;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for DupCap_B\n",
-			DupCap_B[pAC->Index]);
-		}
-	}
-
-	
-	/* 
-	** Check for illegal combinations 
-	*/
-	if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
-		((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
-		(DuplexCap == SK_LMODE_STAT_HALF)) &&
-		(pAC->ChipsetType)) {
-		    printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
-					"    Using Full Duplex.\n");
-				DuplexCap = DC_FULL;
-	}
-
-	if (AutoSet && AutoNeg==AN_SENS && DupSet) {
-		printk("sk98lin, Port B: DuplexCapabilities"
-			" ignored using Sense mode\n");
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
-		printk("sk98lin: Port B: Illegal combination"
-			" of values AutoNeg. and DuplexCap.\n    Using "
-			"Full Duplex\n");
-		DuplexCap = DC_FULL;
-	}
-
-	if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
-		DuplexCap = DC_FULL;
-	}
-	
-	if (!AutoSet && DupSet) {
-		printk("sk98lin: Port B: Duplex setting not"
-			" possible in\n    default AutoNegotiation mode"
-			" (Sense).\n    Using AutoNegotiation On\n");
-		AutoNeg = AN_ON;
-	}
-
-	/* 
-	** set the desired mode 
-	*/
-	if (AutoSet || DupSet) {
-	    pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
-	}
-
-	/*
-	** c) Any FlowCtrl parameter set?
-	*/
-	if (FlowCtrl_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		FlowCtrl_B[pAC->Index] != NULL) {
-		if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) {
-		    IsFlowCtrlDefined = SK_FALSE;
-		} else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) {
-		    FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
-		} else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) {
-		    FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
-		} else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) {
-		    FlowCtrl = SK_FLOW_MODE_LOC_SEND;
-		} else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) {
-		    FlowCtrl = SK_FLOW_MODE_NONE;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n",
-			FlowCtrl_B[pAC->Index]);
-		    IsFlowCtrlDefined = SK_FALSE;
-		}
-	} else {
-		IsFlowCtrlDefined = SK_FALSE;
-	}
-
-	if (IsFlowCtrlDefined) {
-	    if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
-		printk("sk98lin: Port B: FlowControl"
-			" impossible without AutoNegotiation,"
-			" disabled\n");
-		FlowCtrl = SK_FLOW_MODE_NONE;
-	    }
-	    pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl;
-	}
-
-	/*
-	** d) What is the RoleParameter?
-	*/
-	if (Role_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		Role_B[pAC->Index] != NULL) {
-		if (strcmp(Role_B[pAC->Index],"")==0) {
-		    IsRoleDefined = SK_FALSE;
-		} else if (strcmp(Role_B[pAC->Index],"Auto")==0) {
-		    MSMode = SK_MS_MODE_AUTO;
-		} else if (strcmp(Role_B[pAC->Index],"Master")==0) {
-		    MSMode = SK_MS_MODE_MASTER;
-		} else if (strcmp(Role_B[pAC->Index],"Slave")==0) {
-		    MSMode = SK_MS_MODE_SLAVE;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for Role_B\n",
-			Role_B[pAC->Index]);
-		    IsRoleDefined = SK_FALSE;
-		}
-	} else {
-	    IsRoleDefined = SK_FALSE;
-	}
-
-	if (IsRoleDefined) {
-	    pAC->GIni.GP[1].PMSMode = MSMode;
-	}
-	
-	/*
-	** Evaluate settings for both ports
-	*/
-	pAC->ActivePort = 0;
-	if (PrefPort != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		PrefPort[pAC->Index] != NULL) {
-		if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */
-			pAC->ActivePort             =  0;
-			pAC->Rlmt.Net[0].Preference = -1; /* auto */
-			pAC->Rlmt.Net[0].PrefPort   =  0;
-		} else if (strcmp(PrefPort[pAC->Index],"A") == 0) {
-			/*
-			** do not set ActivePort here, thus a port
-			** switch is issued after net up.
-			*/
-			Port                        = 0;
-			pAC->Rlmt.Net[0].Preference = Port;
-			pAC->Rlmt.Net[0].PrefPort   = Port;
-		} else if (strcmp(PrefPort[pAC->Index],"B") == 0) {
-			/*
-			** do not set ActivePort here, thus a port
-			** switch is issued after net up.
-			*/
-			if (pAC->GIni.GIMacsFound == 1) {
-				printk("sk98lin: Illegal value \"B\" for PrefPort.\n"
-					"      Port B not available on single port adapters.\n");
-
-				pAC->ActivePort             =  0;
-				pAC->Rlmt.Net[0].Preference = -1; /* auto */
-				pAC->Rlmt.Net[0].PrefPort   =  0;
-			} else {
-				Port                        = 1;
-				pAC->Rlmt.Net[0].Preference = Port;
-				pAC->Rlmt.Net[0].PrefPort   = Port;
-			}
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for PrefPort\n",
-			PrefPort[pAC->Index]);
-		}
-	}
-
-	pAC->RlmtNets = 1;
-
-	if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
-		RlmtMode[pAC->Index] != NULL) {
-		if (strcmp(RlmtMode[pAC->Index], "") == 0) {
-			pAC->RlmtMode = 0;
-		} else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
-			pAC->RlmtMode = SK_RLMT_CHECK_LINK;
-		} else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
-			pAC->RlmtMode = SK_RLMT_CHECK_LINK |
-					SK_RLMT_CHECK_LOC_LINK;
-		} else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) {
-			pAC->RlmtMode = SK_RLMT_CHECK_LINK     |
-					SK_RLMT_CHECK_LOC_LINK |
-					SK_RLMT_CHECK_SEG;
-		} else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) &&
-			(pAC->GIni.GIMacsFound == 2)) {
-			pAC->RlmtMode = SK_RLMT_CHECK_LINK;
-			pAC->RlmtNets = 2;
-		} else {
-		    printk("sk98lin: Illegal value \"%s\" for"
-			" RlmtMode, using default\n", 
-			RlmtMode[pAC->Index]);
-			pAC->RlmtMode = 0;
-		}
-	} else {
-		pAC->RlmtMode = 0;
-	}
-	
-	/*
-	** Check the interrupt moderation parameters
-	*/
-	if (Moderation[pAC->Index] != NULL) {
-		if (strcmp(Moderation[pAC->Index], "") == 0) {
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
-		} else if (strcmp(Moderation[pAC->Index], "Static") == 0) {
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC;
-		} else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) {
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC;
-		} else if (strcmp(Moderation[pAC->Index], "None") == 0) {
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
-		} else {
-	   		printk("sk98lin: Illegal value \"%s\" for Moderation.\n"
-				"      Disable interrupt moderation.\n",
-				Moderation[pAC->Index]);
-			pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
-		}
-	} else {
-		pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
-	}
-
-	if (Stats[pAC->Index] != NULL) {
-		if (strcmp(Stats[pAC->Index], "Yes") == 0) {
-			pAC->DynIrqModInfo.DisplayStats = SK_TRUE;
-		} else {
-			pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
-		}
-	} else {
-		pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
-	}
-
-	if (ModerationMask[pAC->Index] != NULL) {
-		if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
-		} else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY;
-		} else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY;
-		} else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
-		} else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
-		} else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
-		} else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
-		} else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
-		} else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
-		} else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) {
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
-		} else { /* some rubbish */
-			pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
-		}
-	} else {  /* operator has stated nothing */
-		pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
-	}
-
-	if (AutoSizing[pAC->Index] != NULL) {
-		if (strcmp(AutoSizing[pAC->Index], "On") == 0) {
-			pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
-		} else {
-			pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
-		}
-	} else {  /* operator has stated nothing */
-		pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
-	}
-
-	if (IntsPerSec[pAC->Index] != 0) {
-		if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) || 
-			(IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) {
-	   		printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n"
-				"      Using default value of %i.\n", 
-				IntsPerSec[pAC->Index],
-				C_INT_MOD_IPS_LOWER_RANGE,
-				C_INT_MOD_IPS_UPPER_RANGE,
-				C_INTS_PER_SEC_DEFAULT);
-			pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
-		} else {
-			pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index];
-		}
-	} else {
-		pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
-	}
-
-	/*
-	** Evaluate upper and lower moderation threshold
-	*/
-	pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit =
-		pAC->DynIrqModInfo.MaxModIntsPerSec +
-		(pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
-
-	pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit =
-		pAC->DynIrqModInfo.MaxModIntsPerSec -
-		(pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
-
-	pAC->DynIrqModInfo.PrevTimeVal = jiffies;  /* initial value */
-
-
-} /* GetConfiguration */
-
-
-/*****************************************************************************
- *
- * 	ProductStr - return a adapter identification string from vpd
- *
- * Description:
- *	This function reads the product name string from the vpd area
- *	and puts it the field pAC->DeviceString.
- *
- * Returns: N/A
- */
-static inline int ProductStr(
-	SK_AC	*pAC,		/* pointer to adapter context */
-	char    *DeviceStr,	/* result string */
-	int      StrLen		/* length of the string */
-)
-{
-char	Keyword[] = VPD_NAME;	/* vpd productname identifier */
-int	ReturnCode;		/* return code from vpd_read */
-unsigned long Flags;
-
-	spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-	ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen);
-	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
-	return ReturnCode;
-} /* ProductStr */
-
-/*****************************************************************************
- *
- *      StartDrvCleanupTimer - Start timer to check for descriptors which
- *                             might be placed in descriptor ring, but
- *                             havent been handled up to now
- *
- * Description:
- *      This function requests a HW-timer fo the Yukon card. The actions to
- *      perform when this timer expires, are located in the SkDrvEvent().
- *
- * Returns: N/A
- */
-static void
-StartDrvCleanupTimer(SK_AC *pAC) {
-    SK_EVPARA    EventParam;   /* Event struct for timer event */
-
-    SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
-    EventParam.Para32[0] = SK_DRV_RX_CLEANUP_TIMER;
-    SkTimerStart(pAC, pAC->IoBase, &pAC->DrvCleanupTimer,
-                 SK_DRV_RX_CLEANUP_TIMER_LENGTH,
-                 SKGE_DRV, SK_DRV_TIMER, EventParam);
-}
-
-/*****************************************************************************
- *
- *      StopDrvCleanupTimer - Stop timer to check for descriptors
- *
- * Description:
- *      This function requests a HW-timer fo the Yukon card. The actions to
- *      perform when this timer expires, are located in the SkDrvEvent().
- *
- * Returns: N/A
- */
-static void
-StopDrvCleanupTimer(SK_AC *pAC) {
-    SkTimerStop(pAC, pAC->IoBase, &pAC->DrvCleanupTimer);
-    SK_MEMSET((char *) &pAC->DrvCleanupTimer, 0, sizeof(SK_TIMER));
-}
-
-/****************************************************************************/
-/* functions for common modules *********************************************/
-/****************************************************************************/
-
-
-/*****************************************************************************
- *
- *	SkDrvAllocRlmtMbuf - allocate an RLMT mbuf
- *
- * Description:
- *	This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure
- *	is embedded into a socket buff data area.
- *
- * Context:
- *	runtime
- *
- * Returns:
- *	NULL or pointer to Mbuf.
- */
-SK_MBUF *SkDrvAllocRlmtMbuf(
-SK_AC		*pAC,		/* pointer to adapter context */
-SK_IOC		IoC,		/* the IO-context */
-unsigned	BufferSize)	/* size of the requested buffer */
-{
-SK_MBUF		*pRlmtMbuf;	/* pointer to a new rlmt-mbuf structure */
-struct sk_buff	*pMsgBlock;	/* pointer to a new message block */
-
-	pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC);
-	if (pMsgBlock == NULL) {
-		return (NULL);
-	}
-	pRlmtMbuf = (SK_MBUF*) pMsgBlock->data;
-	skb_reserve(pMsgBlock, sizeof(SK_MBUF));
-	pRlmtMbuf->pNext = NULL;
-	pRlmtMbuf->pOs = pMsgBlock;
-	pRlmtMbuf->pData = pMsgBlock->data;	/* Data buffer. */
-	pRlmtMbuf->Size = BufferSize;		/* Data buffer size. */
-	pRlmtMbuf->Length = 0;		/* Length of packet (<= Size). */
-	return (pRlmtMbuf);
-
-} /* SkDrvAllocRlmtMbuf */
-
-
-/*****************************************************************************
- *
- *	SkDrvFreeRlmtMbuf - free an RLMT mbuf
- *
- * Description:
- *	This routine frees one or more RLMT mbuf(s).
- *
- * Context:
- *	runtime
- *
- * Returns:
- *	Nothing
- */
-void  SkDrvFreeRlmtMbuf(
-SK_AC		*pAC,		/* pointer to adapter context */
-SK_IOC		IoC,		/* the IO-context */
-SK_MBUF		*pMbuf)		/* size of the requested buffer */
-{
-SK_MBUF		*pFreeMbuf;
-SK_MBUF		*pNextMbuf;
-
-	pFreeMbuf = pMbuf;
-	do {
-		pNextMbuf = pFreeMbuf->pNext;
-		DEV_KFREE_SKB_ANY(pFreeMbuf->pOs);
-		pFreeMbuf = pNextMbuf;
-	} while ( pFreeMbuf != NULL );
-} /* SkDrvFreeRlmtMbuf */
-
-
-/*****************************************************************************
- *
- *	SkOsGetTime - provide a time value
- *
- * Description:
- *	This routine provides a time value. The unit is 1/HZ (defined by Linux).
- *	It is not used for absolute time, but only for time differences.
- *
- *
- * Returns:
- *	Time value
- */
-SK_U64 SkOsGetTime(SK_AC *pAC)
-{
-	SK_U64	PrivateJiffies;
-	SkOsGetTimeCurrent(pAC, &PrivateJiffies);
-	return PrivateJiffies;
-} /* SkOsGetTime */
-
-
-/*****************************************************************************
- *
- *	SkPciReadCfgDWord - read a 32 bit value from pci config space
- *
- * Description:
- *	This routine reads a 32 bit value from the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciReadCfgDWord(
-SK_AC *pAC,		/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U32 *pVal)		/* pointer to store the read value */
-{
-	pci_read_config_dword(pAC->PciDev, PciAddr, pVal);
-	return(0);
-} /* SkPciReadCfgDWord */
-
-
-/*****************************************************************************
- *
- *	SkPciReadCfgWord - read a 16 bit value from pci config space
- *
- * Description:
- *	This routine reads a 16 bit value from the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciReadCfgWord(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U16 *pVal)		/* pointer to store the read value */
-{
-	pci_read_config_word(pAC->PciDev, PciAddr, pVal);
-	return(0);
-} /* SkPciReadCfgWord */
-
-
-/*****************************************************************************
- *
- *	SkPciReadCfgByte - read a 8 bit value from pci config space
- *
- * Description:
- *	This routine reads a 8 bit value from the pci configuration
- *	space.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciReadCfgByte(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U8 *pVal)		/* pointer to store the read value */
-{
-	pci_read_config_byte(pAC->PciDev, PciAddr, pVal);
-	return(0);
-} /* SkPciReadCfgByte */
-
-
-/*****************************************************************************
- *
- *	SkPciWriteCfgWord - write a 16 bit value to pci config space
- *
- * Description:
- *	This routine writes a 16 bit value to the pci configuration
- *	space. The flag PciConfigUp indicates whether the config space
- *	is accesible or must be set up first.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciWriteCfgWord(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U16 Val)		/* pointer to store the read value */
-{
-	pci_write_config_word(pAC->PciDev, PciAddr, Val);
-	return(0);
-} /* SkPciWriteCfgWord */
-
-
-/*****************************************************************************
- *
- *	SkPciWriteCfgWord - write a 8 bit value to pci config space
- *
- * Description:
- *	This routine writes a 8 bit value to the pci configuration
- *	space. The flag PciConfigUp indicates whether the config space
- *	is accesible or must be set up first.
- *
- * Returns:
- *	0 - indicate everything worked ok.
- *	!= 0 - error indication
- */
-int SkPciWriteCfgByte(
-SK_AC *pAC,	/* Adapter Control structure pointer */
-int PciAddr,		/* PCI register address */
-SK_U8 Val)		/* pointer to store the read value */
-{
-	pci_write_config_byte(pAC->PciDev, PciAddr, Val);
-	return(0);
-} /* SkPciWriteCfgByte */
-
-
-/*****************************************************************************
- *
- *	SkDrvEvent - handle driver events
- *
- * Description:
- *	This function handles events from all modules directed to the driver
- *
- * Context:
- *	Is called under protection of slow path lock.
- *
- * Returns:
- *	0 if everything ok
- *	< 0  on error
- *	
- */
-int SkDrvEvent(
-SK_AC *pAC,		/* pointer to adapter context */
-SK_IOC IoC,		/* io-context */
-SK_U32 Event,		/* event-id */
-SK_EVPARA Param)	/* event-parameter */
-{
-SK_MBUF		*pRlmtMbuf;	/* pointer to a rlmt-mbuf structure */
-struct sk_buff	*pMsg;		/* pointer to a message block */
-int		FromPort;	/* the port from which we switch away */
-int		ToPort;		/* the port we switch to */
-SK_EVPARA	NewPara;	/* parameter for further events */
-int		Stat;
-unsigned long	Flags;
-SK_BOOL		DualNet;
-
-	switch (Event) {
-	case SK_DRV_ADAP_FAIL:
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("ADAPTER FAIL EVENT\n"));
-		printk("%s: Adapter failed.\n", pAC->dev[0]->name);
-		/* disable interrupts */
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		/* cgoos */
-		break;
-	case SK_DRV_PORT_FAIL:
-		FromPort = Param.Para32[0];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT FAIL EVENT, Port: %d\n", FromPort));
-		if (FromPort == 0) {
-			printk("%s: Port A failed.\n", pAC->dev[0]->name);
-		} else {
-			printk("%s: Port B failed.\n", pAC->dev[1]->name);
-		}
-		/* cgoos */
-		break;
-	case SK_DRV_PORT_RESET:	 /* SK_U32 PortIdx */
-		/* action list 4 */
-		FromPort = Param.Para32[0];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT RESET EVENT, Port: %d ", FromPort));
-		NewPara.Para64 = FromPort;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
-		spin_lock_irqsave(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-
-		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
-		netif_carrier_off(pAC->dev[Param.Para32[0]]);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		
-		/* clear rx ring from received frames */
-		ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
-		
-		ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
-		spin_lock_irqsave(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		
-		/* tschilling: Handling of return value inserted. */
-		if (SkGeInitPort(pAC, IoC, FromPort)) {
-			if (FromPort == 0) {
-				printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
-			} else {
-				printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
-			}
-		}
-		SkAddrMcUpdate(pAC,IoC, FromPort);
-		PortReInitBmu(pAC, FromPort);
-		SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
-		ClearAndStartRx(pAC, FromPort);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		break;
-	case SK_DRV_NET_UP:	 /* SK_U32 PortIdx */
-	{	struct net_device *dev = pAC->dev[Param.Para32[0]];
-		/* action list 5 */
-		FromPort = Param.Para32[0];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("NET UP EVENT, Port: %d ", Param.Para32[0]));
-		/* Mac update */
-		SkAddrMcUpdate(pAC,IoC, FromPort);
-
-		if (DoPrintInterfaceChange) {
-		printk("%s: network connection up using"
-			" port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]);
-
-		/* tschilling: Values changed according to LinkSpeedUsed. */
-		Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
-		if (Stat == SK_LSPEED_STAT_10MBPS) {
-			printk("    speed:           10\n");
-		} else if (Stat == SK_LSPEED_STAT_100MBPS) {
-			printk("    speed:           100\n");
-		} else if (Stat == SK_LSPEED_STAT_1000MBPS) {
-			printk("    speed:           1000\n");
-		} else {
-			printk("    speed:           unknown\n");
-		}
-
-
-		Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
-		if (Stat == SK_LMODE_STAT_AUTOHALF ||
-			Stat == SK_LMODE_STAT_AUTOFULL) {
-			printk("    autonegotiation: yes\n");
-		}
-		else {
-			printk("    autonegotiation: no\n");
-		}
-		if (Stat == SK_LMODE_STAT_AUTOHALF ||
-			Stat == SK_LMODE_STAT_HALF) {
-			printk("    duplex mode:     half\n");
-		}
-		else {
-			printk("    duplex mode:     full\n");
-		}
-		Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus;
-		if (Stat == SK_FLOW_STAT_REM_SEND ) {
-			printk("    flowctrl:        remote send\n");
-		}
-		else if (Stat == SK_FLOW_STAT_LOC_SEND ){
-			printk("    flowctrl:        local send\n");
-		}
-		else if (Stat == SK_FLOW_STAT_SYMMETRIC ){
-			printk("    flowctrl:        symmetric\n");
-		}
-		else {
-			printk("    flowctrl:        none\n");
-		}
-		
-		/* tschilling: Check against CopperType now. */
-		if ((pAC->GIni.GICopperType == SK_TRUE) &&
-			(pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
-			SK_LSPEED_STAT_1000MBPS)) {
-			Stat = pAC->GIni.GP[FromPort].PMSStatus;
-			if (Stat == SK_MS_STAT_MASTER ) {
-				printk("    role:            master\n");
-			}
-			else if (Stat == SK_MS_STAT_SLAVE ) {
-				printk("    role:            slave\n");
-			}
-			else {
-				printk("    role:            ???\n");
-			}
-		}
-
-		/* 
-		   Display dim (dynamic interrupt moderation) 
-		   informations
-		 */
-		if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC)
-			printk("    irq moderation:  static (%d ints/sec)\n",
-					pAC->DynIrqModInfo.MaxModIntsPerSec);
-		else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC)
-			printk("    irq moderation:  dynamic (%d ints/sec)\n",
-					pAC->DynIrqModInfo.MaxModIntsPerSec);
-		else
-			printk("    irq moderation:  disabled\n");
-
-
-		printk("    scatter-gather:  %s\n",
-		       (dev->features & NETIF_F_SG) ? "enabled" : "disabled");
-		printk("    tx-checksum:     %s\n",
-		       (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled");
-		printk("    rx-checksum:     %s\n",
-		       pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled");
-
-		} else {
-                        DoPrintInterfaceChange = SK_TRUE;
-                }
-	
-		if ((Param.Para32[0] != pAC->ActivePort) &&
-			(pAC->RlmtNets == 1)) {
-			NewPara.Para32[0] = pAC->ActivePort;
-			NewPara.Para32[1] = Param.Para32[0];
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
-				NewPara);
-		}
-
-		/* Inform the world that link protocol is up. */
-		netif_carrier_on(dev);
-		break;
-	}
-	case SK_DRV_NET_DOWN:	 /* SK_U32 Reason */
-		/* action list 7 */
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("NET DOWN EVENT "));
-		if (DoPrintInterfaceChange) {
-			printk("%s: network connection down\n", 
-				pAC->dev[Param.Para32[1]]->name);
-		} else {
-			DoPrintInterfaceChange = SK_TRUE;
-		}
-		netif_carrier_off(pAC->dev[Param.Para32[1]]);
-		break;
-	case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT SWITCH HARD "));
-	case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
-	/* action list 6 */
-		printk("%s: switching to port %c\n", pAC->dev[0]->name,
-			'A'+Param.Para32[1]);
-	case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
-		FromPort = Param.Para32[0];
-		ToPort = Param.Para32[1];
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("PORT SWITCH EVENT, From: %d  To: %d (Pref %d) ",
-			FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort));
-		NewPara.Para64 = FromPort;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
-		NewPara.Para64 = ToPort;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
-		spin_lock_irqsave(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
-		SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
-		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-
-		ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
-		ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
-		
-		ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
-		ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
-		spin_lock_irqsave(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		pAC->ActivePort = ToPort;
-#if 0
-		SetQueueSizes(pAC);
-#else
-		/* tschilling: New common function with minimum size check. */
-		DualNet = SK_FALSE;
-		if (pAC->RlmtNets == 2) {
-			DualNet = SK_TRUE;
-		}
-		
-		if (SkGeInitAssignRamToQueues(
-			pAC,
-			pAC->ActivePort,
-			DualNet)) {
-			spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-			spin_unlock_irqrestore(
-				&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-				Flags);
-			printk("SkGeInitAssignRamToQueues failed.\n");
-			break;
-		}
-#endif
-		/* tschilling: Handling of return values inserted. */
-		if (SkGeInitPort(pAC, IoC, FromPort) ||
-			SkGeInitPort(pAC, IoC, ToPort)) {
-			printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
-		}
-		if (Event == SK_DRV_SWITCH_SOFT) {
-			SkMacRxTxEnable(pAC, IoC, FromPort);
-		}
-		SkMacRxTxEnable(pAC, IoC, ToPort);
-		SkAddrSwap(pAC, IoC, FromPort, ToPort);
-		SkAddrMcUpdate(pAC, IoC, FromPort);
-		SkAddrMcUpdate(pAC, IoC, ToPort);
-		PortReInitBmu(pAC, FromPort);
-		PortReInitBmu(pAC, ToPort);
-		SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
-		SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
-		ClearAndStartRx(pAC, FromPort);
-		ClearAndStartRx(pAC, ToPort);
-		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
-			Flags);
-		break;
-	case SK_DRV_RLMT_SEND:	 /* SK_MBUF *pMb */
-		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-			("RLS "));
-		pRlmtMbuf = (SK_MBUF*) Param.pParaPtr;
-		pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
-		skb_put(pMsg, pRlmtMbuf->Length);
-		if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
-			pMsg) < 0)
-
-			DEV_KFREE_SKB_ANY(pMsg);
-		break;
-	case SK_DRV_TIMER:
-		if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) {
-			/*
-			** expiration of the moderation timer implies that
-			** dynamic moderation is to be applied
-			*/
-			SkDimStartModerationTimer(pAC);
-			SkDimModerate(pAC);
-                        if (pAC->DynIrqModInfo.DisplayStats) {
-			    SkDimDisplayModerationSettings(pAC);
-                        }
-                } else if (Param.Para32[0] == SK_DRV_RX_CLEANUP_TIMER) {
-			/*
-			** check if we need to check for descriptors which
-			** haven't been handled the last millisecs
-			*/
-			StartDrvCleanupTimer(pAC);
-			if (pAC->GIni.GIMacsFound == 2) {
-				ReceiveIrq(pAC, &pAC->RxPort[1], SK_FALSE);
-			}
-			ReceiveIrq(pAC, &pAC->RxPort[0], SK_FALSE);
-		} else {
-			printk("Expiration of unknown timer\n");
-		}
-		break;
-	default:
-		break;
-	}
-	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
-		("END EVENT "));
-	
-	return (0);
-} /* SkDrvEvent */
-
-
-/*****************************************************************************
- *
- *	SkErrorLog - log errors
- *
- * Description:
- *	This function logs errors to the system buffer and to the console
- *
- * Returns:
- *	0 if everything ok
- *	< 0  on error
- *	
- */
-void SkErrorLog(
-SK_AC	*pAC,
-int	ErrClass,
-int	ErrNum,
-char	*pErrorMsg)
-{
-char	ClassStr[80];
-
-	switch (ErrClass) {
-	case SK_ERRCL_OTHER:
-		strcpy(ClassStr, "Other error");
-		break;
-	case SK_ERRCL_CONFIG:
-		strcpy(ClassStr, "Configuration error");
-		break;
-	case SK_ERRCL_INIT:
-		strcpy(ClassStr, "Initialization error");
-		break;
-	case SK_ERRCL_NORES:
-		strcpy(ClassStr, "Out of resources error");
-		break;
-	case SK_ERRCL_SW:
-		strcpy(ClassStr, "internal Software error");
-		break;
-	case SK_ERRCL_HW:
-		strcpy(ClassStr, "Hardware failure");
-		break;
-	case SK_ERRCL_COMM:
-		strcpy(ClassStr, "Communication error");
-		break;
-	}
-	printk(KERN_INFO "%s: -- ERROR --\n        Class:  %s\n"
-		"        Nr:  0x%x\n        Msg:  %s\n", pAC->dev[0]->name,
-		ClassStr, ErrNum, pErrorMsg);
-
-} /* SkErrorLog */
-
-#ifdef SK_DIAG_SUPPORT
-
-/*****************************************************************************
- *
- *	SkDrvEnterDiagMode - handles DIAG attach request
- *
- * Description:
- *	Notify the kernel to NOT access the card any longer due to DIAG
- *	Deinitialize the Card
- *
- * Returns:
- *	int
- */
-int SkDrvEnterDiagMode(
-SK_AC   *pAc)   /* pointer to adapter context */
-{
-	DEV_NET *pNet = netdev_priv(pAc->dev[0]);
-	SK_AC   *pAC  = pNet->pAC;
-
-	SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct), 
-			sizeof(SK_PNMI_STRUCT_DATA));
-
-	pAC->DiagModeActive = DIAG_ACTIVE;
-	if (pAC->BoardLevel > SK_INIT_DATA) {
-		if (netif_running(pAC->dev[0])) {
-			pAC->WasIfUp[0] = SK_TRUE;
-			pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose      */
-			DoPrintInterfaceChange = SK_FALSE;
-			SkDrvDeInitAdapter(pAC, 0);  /* performs SkGeClose */
-		} else {
-			pAC->WasIfUp[0] = SK_FALSE;
-		}
-		if (pNet != netdev_priv(pAC->dev[1])) {
-			pNet = netdev_priv(pAC->dev[1]);
-			if (netif_running(pAC->dev[1])) {
-				pAC->WasIfUp[1] = SK_TRUE;
-				pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
-				DoPrintInterfaceChange = SK_FALSE;
-				SkDrvDeInitAdapter(pAC, 1);  /* do SkGeClose  */
-			} else {
-				pAC->WasIfUp[1] = SK_FALSE;
-			}
-		}
-		pAC->BoardLevel = SK_INIT_DATA;
-	}
-	return(0);
-}
-
-/*****************************************************************************
- *
- *	SkDrvLeaveDiagMode - handles DIAG detach request
- *
- * Description:
- *	Notify the kernel to may access the card again after use by DIAG
- *	Initialize the Card
- *
- * Returns:
- * 	int
- */
-int SkDrvLeaveDiagMode(
-SK_AC   *pAc)   /* pointer to adapter control context */
-{ 
-	SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup), 
-			sizeof(SK_PNMI_STRUCT_DATA));
-	pAc->DiagModeActive    = DIAG_NOTACTIVE;
-	pAc->Pnmi.DiagAttached = SK_DIAG_IDLE;
-        if (pAc->WasIfUp[0] == SK_TRUE) {
-                pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
-		DoPrintInterfaceChange = SK_FALSE;
-                SkDrvInitAdapter(pAc, 0);    /* first device  */
-        }
-        if (pAc->WasIfUp[1] == SK_TRUE) {
-                pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
-		DoPrintInterfaceChange = SK_FALSE;
-                SkDrvInitAdapter(pAc, 1);    /* second device */
-        }
-	return(0);
-}
-
-/*****************************************************************************
- *
- *	ParseDeviceNbrFromSlotName - Evaluate PCI device number
- *
- * Description:
- * 	This function parses the PCI slot name information string and will
- *	retrieve the devcie number out of it. The slot_name maintianed by
- *	linux is in the form of '02:0a.0', whereas the first two characters 
- *	represent the bus number in hex (in the sample above this is 
- *	pci bus 0x02) and the next two characters the device number (0x0a).
- *
- * Returns:
- *	SK_U32: The device number from the PCI slot name
- */ 
-
-static SK_U32 ParseDeviceNbrFromSlotName(
-const char *SlotName)   /* pointer to pci slot name eg. '02:0a.0' */
-{
-	char	*CurrCharPos	= (char *) SlotName;
-	int	FirstNibble	= -1;
-	int	SecondNibble	= -1;
-	SK_U32	Result		=  0;
-
-	while (*CurrCharPos != '\0') {
-		if (*CurrCharPos == ':') { 
-			while (*CurrCharPos != '.') {
-				CurrCharPos++;  
-				if (	(*CurrCharPos >= '0') && 
-					(*CurrCharPos <= '9')) {
-					if (FirstNibble == -1) {
-						/* dec. value for '0' */
-						FirstNibble = *CurrCharPos - 48;
-					} else {
-						SecondNibble = *CurrCharPos - 48;
-					}  
-				} else if (	(*CurrCharPos >= 'a') && 
-						(*CurrCharPos <= 'f')  ) {
-					if (FirstNibble == -1) {
-						FirstNibble = *CurrCharPos - 87; 
-					} else {
-						SecondNibble = *CurrCharPos - 87; 
-					}
-				} else {
-					Result = 0;
-				}
-			}
-
-			Result = FirstNibble;
-			Result = Result << 4; /* first nibble is higher one */
-			Result = Result | SecondNibble;
-		}
-		CurrCharPos++;   /* next character */
-	}
-	return (Result);
-}
-
-/****************************************************************************
- *
- *	SkDrvDeInitAdapter - deinitialize adapter (this function is only 
- *				called if Diag attaches to that card)
- *
- * Description:
- *	Close initialized adapter.
- *
- * Returns:
- *	0 - on success
- *	error code - on error
- */
-static int SkDrvDeInitAdapter(
-SK_AC   *pAC,		/* pointer to adapter context   */
-int      devNbr)	/* what device is to be handled */
-{
-	struct SK_NET_DEVICE *dev;
-
-	dev = pAC->dev[devNbr];
-
-	/* On Linux 2.6 the network driver does NOT mess with reference
-	** counts.  The driver MUST be able to be unloaded at any time
-	** due to the possibility of hotplug.
-	*/
-	if (SkGeClose(dev) != 0) {
-		return (-1);
-	}
-	return (0);
-
-} /* SkDrvDeInitAdapter() */
-
-/****************************************************************************
- *
- *	SkDrvInitAdapter - Initialize adapter (this function is only 
- *				called if Diag deattaches from that card)
- *
- * Description:
- *	Close initialized adapter.
- *
- * Returns:
- *	0 - on success
- *	error code - on error
- */
-static int SkDrvInitAdapter(
-SK_AC   *pAC,		/* pointer to adapter context   */
-int      devNbr)	/* what device is to be handled */
-{
-	struct SK_NET_DEVICE *dev;
-
-	dev = pAC->dev[devNbr];
-
-	if (SkGeOpen(dev) != 0) {
-		return (-1);
-	}
-
-	/*
-	** Use correct MTU size and indicate to kernel TX queue can be started
-	*/ 
-	if (SkGeChangeMtu(dev, dev->mtu) != 0) {
-		return (-1);
-	} 
-	return (0);
-
-} /* SkDrvInitAdapter */
-
-#endif
-
-#ifdef DEBUG
-/****************************************************************************/
-/* "debug only" section *****************************************************/
-/****************************************************************************/
-
-
-/*****************************************************************************
- *
- *	DumpMsg - print a frame
- *
- * Description:
- *	This function prints frames to the system logfile/to the console.
- *
- * Returns: N/A
- *	
- */
-static void DumpMsg(struct sk_buff *skb, char *str)
-{
-	int	msglen;
-
-	if (skb == NULL) {
-		printk("DumpMsg(): NULL-Message\n");
-		return;
-	}
-
-	if (skb->data == NULL) {
-		printk("DumpMsg(): Message empty\n");
-		return;
-	}
-
-	msglen = skb->len;
-	if (msglen > 64)
-		msglen = 64;
-
-	printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len);
-
-	DumpData((char *)skb->data, msglen);
-
-	printk("------- End of message ---------\n");
-} /* DumpMsg */
-
-
-
-/*****************************************************************************
- *
- *	DumpData - print a data area
- *
- * Description:
- *	This function prints a area of data to the system logfile/to the
- *	console.
- *
- * Returns: N/A
- *	
- */
-static void DumpData(char *p, int size)
-{
-register int    i;
-int	haddr, addr;
-char	hex_buffer[180];
-char	asc_buffer[180];
-char	HEXCHAR[] = "0123456789ABCDEF";
-
-	addr = 0;
-	haddr = 0;
-	hex_buffer[0] = 0;
-	asc_buffer[0] = 0;
-	for (i=0; i < size; ) {
-		if (*p >= '0' && *p <='z')
-			asc_buffer[addr] = *p;
-		else
-			asc_buffer[addr] = '.';
-		addr++;
-		asc_buffer[addr] = 0;
-		hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[*p & 0x0f];
-		haddr++;
-		hex_buffer[haddr] = ' ';
-		haddr++;
-		hex_buffer[haddr] = 0;
-		p++;
-		i++;
-		if (i%16 == 0) {
-			printk("%s  %s\n", hex_buffer, asc_buffer);
-			addr = 0;
-			haddr = 0;
-		}
-	}
-} /* DumpData */
-
-
-/*****************************************************************************
- *
- *	DumpLong - print a data area as long values
- *
- * Description:
- *	This function prints a area of data to the system logfile/to the
- *	console.
- *
- * Returns: N/A
- *	
- */
-static void DumpLong(char *pc, int size)
-{
-register int    i;
-int	haddr, addr;
-char	hex_buffer[180];
-char	asc_buffer[180];
-char	HEXCHAR[] = "0123456789ABCDEF";
-long	*p;
-int	l;
-
-	addr = 0;
-	haddr = 0;
-	hex_buffer[0] = 0;
-	asc_buffer[0] = 0;
-	p = (long*) pc;
-	for (i=0; i < size; ) {
-		l = (long) *p;
-		hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf];
-		haddr++;
-		hex_buffer[haddr] = HEXCHAR[l & 0x0f];
-		haddr++;
-		hex_buffer[haddr] = ' ';
-		haddr++;
-		hex_buffer[haddr] = 0;
-		p++;
-		i++;
-		if (i%8 == 0) {
-			printk("%4x %s\n", (i-8)*4, hex_buffer);
-			haddr = 0;
-		}
-	}
-	printk("------------------------\n");
-} /* DumpLong */
-
-#endif
-
-static int __devinit skge_probe_one(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	SK_AC			*pAC;
-	DEV_NET			*pNet = NULL;
-	struct net_device	*dev = NULL;
-	static int boards_found = 0;
-	int error = -ENODEV;
-	int using_dac = 0;
-	char DeviceStr[80];
-
-	if (pci_enable_device(pdev))
-		goto out;
- 
-	/* Configure DMA attributes. */
-	if (sizeof(dma_addr_t) > sizeof(u32) &&
-	    !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
-		using_dac = 1;
-		error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
-		if (error < 0) {
-			printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA "
-			       "for consistent allocations\n", pci_name(pdev));
-			goto out_disable_device;
-		}
-	} else {
-		error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-		if (error) {
-			printk(KERN_ERR "sk98lin %s no usable DMA configuration\n",
-			       pci_name(pdev));
-			goto out_disable_device;
-		}
-	}
-
- 	error = -ENOMEM;
- 	dev = alloc_etherdev(sizeof(DEV_NET));
- 	if (!dev) {
-		printk(KERN_ERR "sk98lin: unable to allocate etherdev "
-		       "structure!\n");
-		goto out_disable_device;
-	}
-
-	pNet = netdev_priv(dev);
-	pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL);
-	if (!pNet->pAC) {
-		printk(KERN_ERR "sk98lin: unable to allocate adapter "
-		       "structure!\n");
-		goto out_free_netdev;
-	}
-
-	pAC = pNet->pAC;
-	pAC->PciDev = pdev;
-
-	pAC->dev[0] = dev;
-	pAC->dev[1] = dev;
-	pAC->CheckQueue = SK_FALSE;
-
-	dev->irq = pdev->irq;
-
-	error = SkGeInitPCI(pAC);
-	if (error) {
-		printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
-		goto out_free_netdev;
-	}
-
-	SET_MODULE_OWNER(dev);
-	dev->open =		&SkGeOpen;
-	dev->stop =		&SkGeClose;
-	dev->hard_start_xmit =	&SkGeXmit;
-	dev->get_stats =	&SkGeStats;
-	dev->set_multicast_list = &SkGeSetRxMode;
-	dev->set_mac_address =	&SkGeSetMacAddr;
-	dev->do_ioctl =		&SkGeIoctl;
-	dev->change_mtu =	&SkGeChangeMtu;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller =	&SkGePollController;
-#endif
-	SET_NETDEV_DEV(dev, &pdev->dev);
-	SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-
-	/* Use only if yukon hardware */
-	if (pAC->ChipsetType) {
-#ifdef USE_SK_TX_CHECKSUM
-		dev->features |= NETIF_F_IP_CSUM;
-#endif
-#ifdef SK_ZEROCOPY
-		dev->features |= NETIF_F_SG;
-#endif
-#ifdef USE_SK_RX_CHECKSUM
-		pAC->RxPort[0].RxCsum = 1;
-#endif
-	}
-
-	if (using_dac)
-		dev->features |= NETIF_F_HIGHDMA;
-
-	pAC->Index = boards_found++;
-
-	error = SkGeBoardInit(dev, pAC);
-	if (error)
-		goto out_free_netdev;
-
-	/* Read Adapter name from VPD */
-	if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) {
-		error = -EIO;
-		printk(KERN_ERR "sk98lin: Could not read VPD data.\n");
-		goto out_free_resources;
-	}
-
-	/* Register net device */
-	error = register_netdev(dev);
-	if (error) {
-		printk(KERN_ERR "sk98lin: Could not register device.\n");
-		goto out_free_resources;
-	}
-
-	/* Print adapter specific string from vpd */
-	printk("%s: %s\n", dev->name, DeviceStr);
-
-	/* Print configuration settings */
-	printk("      PrefPort:%c  RlmtMode:%s\n",
-		'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
-		(pAC->RlmtMode==0)  ? "Check Link State" :
-		((pAC->RlmtMode==1) ? "Check Link State" :
-		((pAC->RlmtMode==3) ? "Check Local Port" :
-		((pAC->RlmtMode==7) ? "Check Segmentation" :
-		((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
-
-	SkGeYellowLED(pAC, pAC->IoBase, 1);
-
-	memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
-	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
-	pNet->PortNr = 0;
-	pNet->NetNr  = 0;
-
-	boards_found++;
-
-	pci_set_drvdata(pdev, dev);
-
-	/* More then one port found */
-	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-		dev = alloc_etherdev(sizeof(DEV_NET));
-		if (!dev) {
-			printk(KERN_ERR "sk98lin: unable to allocate etherdev "
-				"structure!\n");
-			goto single_port;
-		}
-
-		pNet          = netdev_priv(dev);
-		pNet->PortNr  = 1;
-		pNet->NetNr   = 1;
-		pNet->pAC     = pAC;
-
-		dev->open               = &SkGeOpen;
-		dev->stop               = &SkGeClose;
-		dev->hard_start_xmit    = &SkGeXmit;
-		dev->get_stats          = &SkGeStats;
-		dev->set_multicast_list = &SkGeSetRxMode;
-		dev->set_mac_address    = &SkGeSetMacAddr;
-		dev->do_ioctl           = &SkGeIoctl;
-		dev->change_mtu         = &SkGeChangeMtu;
-		SET_NETDEV_DEV(dev, &pdev->dev);
-		SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-
-		if (pAC->ChipsetType) {
-#ifdef USE_SK_TX_CHECKSUM
-			dev->features |= NETIF_F_IP_CSUM;
-#endif
-#ifdef SK_ZEROCOPY
-			dev->features |= NETIF_F_SG;
-#endif
-#ifdef USE_SK_RX_CHECKSUM
-			pAC->RxPort[1].RxCsum = 1;
-#endif
-		}
-
-		if (using_dac)
-			dev->features |= NETIF_F_HIGHDMA;
-
-		error = register_netdev(dev);
-		if (error) {
-			printk(KERN_ERR "sk98lin: Could not register device"
-			       " for second port. (%d)\n", error);
-			free_netdev(dev);
-			goto single_port;
-		}
-
-		pAC->dev[1]   = dev;
-		memcpy(&dev->dev_addr,
-		       &pAC->Addr.Net[1].CurrentMacAddress, 6);
-		memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
-		printk("%s: %s\n", dev->name, DeviceStr);
-		printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
-	}
-
-single_port:
-
-	/* Save the hardware revision */
-	pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
-		(pAC->GIni.GIPciHwRev & 0x0F);
-
-	/* Set driver globals */
-	pAC->Pnmi.pDriverFileName    = DRIVER_FILE_NAME;
-	pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
-
-	memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
-	memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
-
-	return 0;
-
- out_free_resources:
-	FreeResources(dev);
- out_free_netdev:
-	free_netdev(dev);
- out_disable_device:
-	pci_disable_device(pdev);
- out:
-	return error;
-}
-
-static void __devexit skge_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	struct net_device *otherdev = pAC->dev[1];
-
-	unregister_netdev(dev);
-
-	SkGeYellowLED(pAC, pAC->IoBase, 0);
-
-	if (pAC->BoardLevel == SK_INIT_RUN) {
-		SK_EVPARA EvPara;
-		unsigned long Flags;
-
-		/* board is still alive */
-		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-		EvPara.Para32[0] = 0;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		EvPara.Para32[0] = 1;
-		EvPara.Para32[1] = -1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-		SkEventDispatcher(pAC, pAC->IoBase);
-		/* disable interrupts */
-		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-		SkGeDeInit(pAC, pAC->IoBase);
-		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-		pAC->BoardLevel = SK_INIT_DATA;
-		/* We do NOT check here, if IRQ was pending, of course*/
-	}
-
-	if (pAC->BoardLevel == SK_INIT_IO) {
-		/* board is still alive */
-		SkGeDeInit(pAC, pAC->IoBase);
-		pAC->BoardLevel = SK_INIT_DATA;
-	}
-
-	FreeResources(dev);
-	free_netdev(dev);
-	if (otherdev != dev)
-		free_netdev(otherdev);
-	kfree(pAC);
-}
-
-#ifdef CONFIG_PM
-static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	struct net_device *otherdev = pAC->dev[1];
-
-	if (netif_running(dev)) {
-		netif_carrier_off(dev);
-		DoPrintInterfaceChange = SK_FALSE;
-		SkDrvDeInitAdapter(pAC, 0);  /* performs SkGeClose */
-		netif_device_detach(dev);
-	}
-	if (otherdev != dev) {
-		if (netif_running(otherdev)) {
-			netif_carrier_off(otherdev);
-			DoPrintInterfaceChange = SK_FALSE;
-			SkDrvDeInitAdapter(pAC, 1);  /* performs SkGeClose */
-			netif_device_detach(otherdev);
-		}
-	}
-
-	pci_save_state(pdev);
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
-	if (pAC->AllocFlag & SK_ALLOC_IRQ) {
-		free_irq(dev->irq, dev);
-	}
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-	return 0;
-}
-
-static int skge_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	DEV_NET *pNet = netdev_priv(dev);
-	SK_AC *pAC = pNet->pAC;
-	struct net_device *otherdev = pAC->dev[1];
-	int ret;
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	ret = pci_enable_device(pdev);
-	if (ret) {
-		printk(KERN_WARNING "sk98lin: unable to enable device %s "
-				"in resume\n", dev->name);
-		goto err_out;
-	}
-	pci_set_master(pdev);
-	if (pAC->GIni.GIMacsFound == 2)
-		ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
-	else
-		ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, "sk98lin", dev);
-	if (ret) {
-		printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
-		ret = -EBUSY;
-		goto err_out_disable_pdev;
-	}
-
-	netif_device_attach(dev);
-	if (netif_running(dev)) {
-		DoPrintInterfaceChange = SK_FALSE;
-		SkDrvInitAdapter(pAC, 0);    /* first device  */
-	}
-	if (otherdev != dev) {
-		netif_device_attach(otherdev);
-		if (netif_running(otherdev)) {
-			DoPrintInterfaceChange = SK_FALSE;
-			SkDrvInitAdapter(pAC, 1);    /* second device  */
-		}
-	}
-
-	return 0;
-
-err_out_disable_pdev:
-	pci_disable_device(pdev);
-err_out:
-	pAC->AllocFlag &= ~SK_ALLOC_IRQ;
-	dev->irq = 0;
-	return ret;
-}
-#else
-#define skge_suspend NULL
-#define skge_resume NULL
-#endif
-
-static struct pci_device_id skge_pci_tbl[] = {
-	{ PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-/* DLink card does not have valid VPD so this driver gags
- *	{ PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- */
-	{ PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
-	{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
-
-static struct pci_driver skge_driver = {
-	.name		= "sk98lin",
-	.id_table	= skge_pci_tbl,
-	.probe		= skge_probe_one,
-	.remove		= __devexit_p(skge_remove_one),
-	.suspend	= skge_suspend,
-	.resume		= skge_resume,
-};
-
-static int __init skge_init(void)
-{
-	printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver"
-	       " and is scheduled for removal\n");
-
-	return pci_register_driver(&skge_driver);
-}
-
-static void __exit skge_exit(void)
-{
-	pci_unregister_driver(&skge_driver);
-}
-
-module_init(skge_init);
-module_exit(skge_exit);
diff --git a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c
deleted file mode 100644
index db67099..0000000
--- a/drivers/net/sk98lin/skgehwt.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgehwt.c
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.15 $
- * Date:	$Date: 2003/09/16 13:41:23 $
- * Purpose:	Hardware Timer
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *	Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgehwt.c,v 1.15 2003/09/16 13:41:23 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
- *   Hardware Timer function queue management.
- */
-intro()
-{}
-#endif
-
-/*
- * Prototypes of local functions.
- */
-#define	SK_HWT_MAX	(65000)
-
-/* correction factor */
-#define	SK_HWT_FAC	(1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100)
-
-/*
- * Initialize hardware timer.
- *
- * Must be called during init level 1.
- */
-void	SkHwtInit(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	pAC->Hwt.TStart = 0 ;
-	pAC->Hwt.TStop	= 0 ;
-	pAC->Hwt.TActive = SK_FALSE;
-
-	SkHwtStop(pAC, Ioc);
-}
-
-/*
- *
- * Start hardware timer (clock ticks are 16us).
- *
- */
-void	SkHwtStart(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc,	/* IoContext */
-SK_U32	Time)	/* Time in units of 16us to load the timer with. */
-{
-	SK_U32	Cnt;
-
-	if (Time > SK_HWT_MAX)
-		Time = SK_HWT_MAX;
-
-	pAC->Hwt.TStart = Time;
-	pAC->Hwt.TStop = 0L;
-
-	Cnt = Time;
-
-	/*
-	 * if time < 16 us
-	 *	time = 16 us
-	 */
-	if (!Cnt) {
-		Cnt++;
-	}
-
-	SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC);
-	
-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_START);	/* Start timer. */
-
-	pAC->Hwt.TActive = SK_TRUE;
-}
-
-/*
- * Stop hardware timer.
- * and clear the timer IRQ
- */
-void	SkHwtStop(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP);
-	
-	SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ);
-
-	pAC->Hwt.TActive = SK_FALSE;
-}
-
-
-/*
- *	Stop hardware timer and read time elapsed since last start.
- *
- * returns
- *	The elapsed time since last start in units of 16us.
- *
- */
-SK_U32	SkHwtRead(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	SK_U32	TRead;
-	SK_U32	IStatus;
-
-	if (pAC->Hwt.TActive) {
-		
-		SkHwtStop(pAC, Ioc);
-
-		SK_IN32(Ioc, B2_TI_VAL, &TRead);
-		TRead /= SK_HWT_FAC;
-
-		SK_IN32(Ioc, B0_ISRC, &IStatus);
-
-		/* Check if timer expired (or wraped around) */
-		if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) {
-			
-			SkHwtStop(pAC, Ioc);
-			
-			pAC->Hwt.TStop = pAC->Hwt.TStart;
-		}
-		else {
-			
-			pAC->Hwt.TStop = pAC->Hwt.TStart - TRead;
-		}
-	}
-	return(pAC->Hwt.TStop);
-}
-
-/*
- * interrupt source= timer
- */
-void	SkHwtIsr(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	Ioc)	/* IoContext */
-{
-	SkHwtStop(pAC, Ioc);
-	
-	pAC->Hwt.TStop = pAC->Hwt.TStart;
-	
-	SkTimerDone(pAC, Ioc);
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c
deleted file mode 100644
index 67f1d6a..0000000
--- a/drivers/net/sk98lin/skgeinit.c
+++ /dev/null
@@ -1,2005 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgeinit.c
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.97 $
- * Date:	$Date: 2003/10/02 16:45:31 $
- * Purpose:	Contains functions to initialize the adapter
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* global variables ***********************************************************/
-
-/* local variables ************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgeinit.c,v 1.97 2003/10/02 16:45:31 rschmidt Exp $ (C) Marvell.";
-#endif
-
-struct s_QOffTab {
-	int	RxQOff;		/* Receive Queue Address Offset */
-	int	XsQOff;		/* Sync Tx Queue Address Offset */
-	int	XaQOff;		/* Async Tx Queue Address Offset */
-};
-static struct s_QOffTab QOffTab[] = {
-	{Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2}
-};
-
-struct s_Config {
-	char	ScanString[8];
-	SK_U32	Value;
-};
-
-static struct s_Config OemConfig = {
-	{'O','E','M','_','C','o','n','f'},
-#ifdef SK_OEM_CONFIG
-	OEM_CONFIG_VALUE,
-#else
-	0,
-#endif
-};
-
-/******************************************************************************
- *
- *	SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings
- *
- * Description:
- *	Enable or disable the descriptor polling of the transmit descriptor
- *	ring(s) (TxD) for port 'Port'.
- *	The new configuration is *not* saved over any SkGeStopPort() and
- *	SkGeInitPort() calls.
- *
- * Returns:
- *	nothing
- */
-void SkGePollTxD(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL PollTxD)	/* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
-{
-	SK_GEPORT *pPrt;
-	SK_U32	DWord;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	DWord = (SK_U32)(PollTxD ? CSR_ENA_POL : CSR_DIS_POL);
-
-	if (pPrt->PXSQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord);
-	}
-	
-	if (pPrt->PXAQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord);
-	}
-}	/* SkGePollTxD */
-
-
-/******************************************************************************
- *
- *	SkGeYellowLED() - Switch the yellow LED on or off.
- *
- * Description:
- *	Switch the yellow LED on or off.
- *
- * Note:
- *	This function may be called any time after SkGeInit(Level 1).
- *
- * Returns:
- *	nothing
- */
-void SkGeYellowLED(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		State)		/* yellow LED state, 0 = OFF, 0 != ON */
-{
-	if (State == 0) {
-		/* Switch yellow LED OFF */
-		SK_OUT8(IoC, B0_LED, LED_STAT_OFF);
-	}
-	else {
-		/* Switch yellow LED ON */
-		SK_OUT8(IoC, B0_LED, LED_STAT_ON);
-	}
-}	/* SkGeYellowLED */
-
-
-#if (!defined(SK_SLIM) || defined(GENESIS))
-/******************************************************************************
- *
- *	SkGeXmitLED() - Modify the Operational Mode of a transmission LED.
- *
- * Description:
- *	The Rx or Tx LED which is specified by 'Led' will be
- *	enabled, disabled or switched on in test mode.
- *
- * Note:
- *	'Led' must contain the address offset of the LEDs INI register.
- *
- * Usage:
- *	SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
- *
- * Returns:
- *	nothing
- */
-void SkGeXmitLED(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Led,		/* offset to the LED Init Value register */
-int		Mode)		/* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */
-{
-	SK_U32	LedIni;
-
-	switch (Mode) {
-	case SK_LED_ENA:
-		LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
-		SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni);
-		SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
-		break;
-	case SK_LED_TST:
-		SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON);
-		SK_OUT32(IoC, Led + XMIT_LED_CNT, 100);
-		SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
-		break;
-	case SK_LED_DIS:
-	default:
-		/*
-		 * Do NOT stop the LED Timer here. The LED might be
-		 * in on state. But it needs to go off.
-		 */
-		SK_OUT32(IoC, Led + XMIT_LED_CNT, 0);
-		SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF);
-		break;
-	}
-			
-	/*
-	 * 1000BT: The Transmit LED is driven by the PHY.
-	 * But the default LED configuration is used for
-	 * Level One and Broadcom PHYs.
-	 * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.)
-	 * (In this case it has to be added here. But we will see. XXX)
-	 */
-}	/* SkGeXmitLED */
-#endif	/* !SK_SLIM || GENESIS */
-
-
-/******************************************************************************
- *
- *	DoCalcAddr() - Calculates the start and the end address of a queue.
- *
- * Description:
- *	This function calculates the start and the end address of a queue.
- *  Afterwards the 'StartVal' is incremented to the next start position.
- *	If the port is already initialized the calculated values
- *	will be checked against the configured values and an
- *	error will be returned, if they are not equal.
- *	If the port is not initialized the values will be written to
- *	*StartAdr and *EndAddr.
- *
- * Returns:
- *	0:	success
- *	1:	configuration error
- */
-static int DoCalcAddr(
-SK_AC		*pAC, 				/* adapter context */
-SK_GEPORT	SK_FAR *pPrt,		/* port index */
-int			QuSize,				/* size of the queue to configure in kB */
-SK_U32		SK_FAR *StartVal,	/* start value for address calculation */
-SK_U32		SK_FAR *QuStartAddr,/* start addr to calculate */
-SK_U32		SK_FAR *QuEndAddr)	/* end address to calculate */
-{
-	SK_U32	EndVal;
-	SK_U32	NextStart;
-	int		Rtv;
-
-	Rtv = 0;
-	if (QuSize == 0) {
-		EndVal = *StartVal;
-		NextStart = EndVal;
-	}
-	else {
-		EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1;
-		NextStart = EndVal + 1;
-	}
-
-	if (pPrt->PState >= SK_PRT_INIT) {
-		if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) {
-			Rtv = 1;
-		}
-	}
-	else {
-		*QuStartAddr = *StartVal;
-		*QuEndAddr = EndVal;
-	}
-
-	*StartVal = NextStart;
-	return(Rtv);
-}	/* DoCalcAddr */
-
-/******************************************************************************
- *
- *	SkGeInitAssignRamToQueues() - allocate default queue sizes
- *
- * Description:
- *	This function assigns the memory to the different queues and ports.
- *	When DualNet is set to SK_TRUE all ports get the same amount of memory.
- *  Otherwise the first port gets most of the memory and all the
- *	other ports just the required minimum.
- *	This function can only be called when pAC->GIni.GIRamSize and
- *	pAC->GIni.GIMacsFound have been initialized, usually this happens
- *	at init level 1
- *
- * Returns:
- *	0 - ok
- *	1 - invalid input values
- *	2 - not enough memory
- */
-
-int SkGeInitAssignRamToQueues(
-SK_AC	*pAC,			/* Adapter context */
-int		ActivePort,		/* Active Port in RLMT mode */
-SK_BOOL	DualNet)		/* adapter context */
-{
-	int	i;
-	int	UsedKilobytes;			/* memory already assigned */
-	int	ActivePortKilobytes;	/* memory available for active port */
-	SK_GEPORT *pGePort;
-
-	UsedKilobytes = 0;
-
-	if (ActivePort >= pAC->GIni.GIMacsFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-			("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n",
-			ActivePort));
-		return(1);
-	}
-	if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) +
-		((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-			("SkGeInitAssignRamToQueues: Not enough memory (%d)\n",
-			 pAC->GIni.GIRamSize));
-		return(2);
-	}
-
-	if (DualNet) {
-		/* every port gets the same amount of memory */
-		ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound;
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
-			pGePort = &pAC->GIni.GP[i];
-			
-			/* take away the minimum memory for active queues */
-			ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
-
-			/* receive queue gets the minimum + 80% of the rest */
-			pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((
-				ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100))
-				+ SK_MIN_RXQ_SIZE;
-
-			ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
-
-			/* synchronous transmit queue */
-			pGePort->PXSQSize = 0;
-
-			/* asynchronous transmit queue */
-			pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes +
-				SK_MIN_TXQ_SIZE);
-		}
-	}
-	else {	
-		/* Rlmt Mode or single link adapter */
-
-		/* Set standby queue size defaults for all standby ports */
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
-			if (i != ActivePort) {
-				pGePort = &pAC->GIni.GP[i];
-
-				pGePort->PRxQSize = SK_MIN_RXQ_SIZE;
-				pGePort->PXAQSize = SK_MIN_TXQ_SIZE;
-				pGePort->PXSQSize = 0;
-
-				/* Count used RAM */
-				UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize;
-			}
-		}
-		/* what's left? */
-		ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes;
-
-		/* assign it to the active port */
-		/* first take away the minimum memory */
-		ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
-		pGePort = &pAC->GIni.GP[ActivePort];
-
-		/* receive queue get's the minimum + 80% of the rest */
-		pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes *
-			(unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE;
-
-		ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
-
-		/* synchronous transmit queue */
-		pGePort->PXSQSize = 0;
-
-		/* asynchronous transmit queue */
-		pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) +
-			SK_MIN_TXQ_SIZE;
-	}
-#ifdef VCPU
-	VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n",
-		pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize);
-#endif /* VCPU */
-
-	return(0);
-}	/* SkGeInitAssignRamToQueues */
-
-/******************************************************************************
- *
- *	SkGeCheckQSize() - Checks the Adapters Queue Size Configuration
- *
- * Description:
- *	This function verifies the Queue Size Configuration specified
- *	in the variables PRxQSize, PXSQSize, and PXAQSize of all
- *	used ports.
- *	This requirements must be fullfilled to have a valid configuration:
- *		- The size of all queues must not exceed GIRamSize.
- *		- The queue sizes must be specified in units of 8 kB.
- *		- The size of Rx queues of available ports must not be
- *		  smaller than 16 kB.
- *		- The size of at least one Tx queue (synch. or asynch.)
- *        of available ports must not be smaller than 16 kB
- *        when Jumbo Frames are used.
- *		- The RAM start and end addresses must not be changed
- *		  for ports which are already initialized.
- *	Furthermore SkGeCheckQSize() defines the Start and End Addresses
- *  of all ports and stores them into the HWAC port	structure.
- *
- * Returns:
- *	0:	Queue Size Configuration valid
- *	1:	Queue Size Configuration invalid
- */
-static int SkGeCheckQSize(
-SK_AC	 *pAC,		/* adapter context */
-int		 Port)		/* port index */
-{
-	SK_GEPORT *pPrt;
-	int	i;
-	int	Rtv;
-	int	Rtv2;
-	SK_U32	StartAddr;
-#ifndef SK_SLIM
-	int	UsedMem;	/* total memory used (max. found ports) */
-#endif	
-
-	Rtv = 0;
-	
-#ifndef SK_SLIM
-
-	UsedMem = 0;
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		pPrt = &pAC->GIni.GP[i];
-
-		if ((pPrt->PRxQSize & QZ_UNITS) != 0 ||
-			(pPrt->PXSQSize & QZ_UNITS) != 0 ||
-			(pPrt->PXAQSize & QZ_UNITS) != 0) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
-			return(1);
-		}
-
-		if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG);
-			return(1);
-		}
-		
-		/*
-		 * the size of at least one Tx queue (synch. or asynch.) has to be > 0.
-		 * if Jumbo Frames are used, this size has to be >= 16 kB.
-		 */
-		if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) ||
-			(pAC->GIni.GIPortUsage == SK_JUMBO_LINK &&
-            ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) ||
-			 (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) {
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG);
-				return(1);
-		}
-		
-		UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize;
-	}
-	
-	if (UsedMem > pAC->GIni.GIRamSize) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
-		return(1);
-	}
-#endif	/* !SK_SLIM */
-
-	/* Now start address calculation */
-	StartAddr = pAC->GIni.GIRamOffs;
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		pPrt = &pAC->GIni.GP[i];
-
-		/* Calculate/Check values for the receive queue */
-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr,
-			&pPrt->PRxQRamStart, &pPrt->PRxQRamEnd);
-		Rtv |= Rtv2;
-
-		/* Calculate/Check values for the synchronous Tx queue */
-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr,
-			&pPrt->PXsQRamStart, &pPrt->PXsQRamEnd);
-		Rtv |= Rtv2;
-
-		/* Calculate/Check values for the asynchronous Tx queue */
-		Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr,
-			&pPrt->PXaQRamStart, &pPrt->PXaQRamEnd);
-		Rtv |= Rtv2;
-
-		if (Rtv) {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG);
-			return(1);
-		}
-	}
-
-	return(0);
-}	/* SkGeCheckQSize */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkGeInitMacArb() - Initialize the MAC Arbiter
- *
- * Description:
- *	This function initializes the MAC Arbiter.
- *	It must not be called if there is still an
- *	initialized or active port.
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitMacArb(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	/* release local reset */
-	SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR);
-
-	/* configure timeout values */
-	SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53);
-	SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53);
-	SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53);
-	SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53);
-
-	SK_OUT8(IoC, B3_MA_RCINI_RX1, 0);
-	SK_OUT8(IoC, B3_MA_RCINI_RX2, 0);
-	SK_OUT8(IoC, B3_MA_RCINI_TX1, 0);
-	SK_OUT8(IoC, B3_MA_RCINI_TX2, 0);
-
-	/* recovery values are needed for XMAC II Rev. B2 only */
-	/* Fast Output Enable Mode was intended to use with Rev. B2, but now? */
-
-	/*
-	 * There is no start or enable button to push, therefore
-	 * the MAC arbiter is configured and enabled now.
-	 */
-}	/* SkGeInitMacArb */
-
-
-/******************************************************************************
- *
- *	SkGeInitPktArb() - Initialize the Packet Arbiter
- *
- * Description:
- *	This function initializes the Packet Arbiter.
- *	It must not be called if there is still an
- *	initialized or active port.
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitPktArb(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	/* release local reset */
-	SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR);
-
-	/* configure timeout values */
-	SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX);
-	SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX);
-	SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX);
-	SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX);
-
-	/*
-	 * enable timeout timers if jumbo frames not used
-	 * NOTE: the packet arbiter timeout interrupt is needed for
-	 * half duplex hangup workaround
-	 */
-	if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) {
-		if (pAC->GIni.GIMacsFound == 1) {
-			SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1);
-		}
-		else {
-			SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2);
-		}
-	}
-}	/* SkGeInitPktArb */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkGeInitMacFifo() - Initialize the MAC FIFOs
- *
- * Description:
- *	Initialize all MAC FIFOs of the specified port
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitMacFifo(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_U16	Word;
-#ifdef VCPU
-	SK_U32	DWord;
-#endif /* VCPU */
-	/*
-	 * For each FIFO:
-	 *	- release local reset
-	 *	- use default value for MAC FIFO size
-	 *	- setup defaults for the control register
-	 *	- enable the FIFO
-	 */
-	
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* Configure Rx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF);
-		SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
-	
-		/* Configure Tx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
-		SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
-	
-		/* Enable frame flushing if jumbo frames used */
-		if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-			SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH);
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* set Rx GMAC FIFO Flush Mask */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK);
-		
-		Word = (SK_U16)GMF_RX_CTRL_DEF;
-
-		/* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
-		if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-
-			Word &= ~GMF_RX_F_FL_ON;
-		}
-		
-		/* Configure Rx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word);
-		
-		/* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
-		
-		/* Configure Tx MAC FIFO */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
-		SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF);
-		
-#ifdef VCPU
-		SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord);
-		SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord);
-#endif /* VCPU */
-		
-		/* set Tx GMAC FIFO Almost Empty Threshold */
-/*		SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */
-	}
-#endif /* YUKON */
-
-}	/* SkGeInitMacFifo */
-
-#ifdef	SK_LNK_SYNC_CNT
-/******************************************************************************
- *
- *	SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting
- *
- * Description:
- *	This function starts the Link Sync Counter of the specified
- *	port and enables the generation of an Link Sync IRQ.
- *	The Link Sync Counter may be used to detect an active link,
- *	if autonegotiation is not used.
- *
- * Note:
- *	o To ensure receiving the Link Sync Event the LinkSyncCounter
- *	  should be initialized BEFORE clearing the XMAC's reset!
- *	o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this
- *	  function.
- *
- * Returns:
- *	nothing
- */
-void SkGeLoadLnkSyncCnt(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U32	CntVal)		/* Counter value */
-{
-	SK_U32	OrgIMsk;
-	SK_U32	NewIMsk;
-	SK_U32	ISrc;
-	SK_BOOL	IrqPend;
-
-	/* stop counter */
-	SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP);
-
-	/*
-	 * ASIC problem:
-	 * Each time starting the Link Sync Counter an IRQ is generated
-	 * by the adapter. See problem report entry from 21.07.98
-	 *
-	 * Workaround:	Disable Link Sync IRQ and clear the unexpeced IRQ
-	 *		if no IRQ is already pending.
-	 */
-	IrqPend = SK_FALSE;
-	SK_IN32(IoC, B0_ISRC, &ISrc);
-	SK_IN32(IoC, B0_IMSK, &OrgIMsk);
-	if (Port == MAC_1) {
-		NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1;
-		if ((ISrc & IS_LNK_SYNC_M1) != 0) {
-			IrqPend = SK_TRUE;
-		}
-	}
-	else {
-		NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2;
-		if ((ISrc & IS_LNK_SYNC_M2) != 0) {
-			IrqPend = SK_TRUE;
-		}
-	}
-	if (!IrqPend) {
-		SK_OUT32(IoC, B0_IMSK, NewIMsk);
-	}
-
-	/* load counter */
-	SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal);
-
-	/* start counter */
-	SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START);
-
-	if (!IrqPend) {
-		/* clear the unexpected IRQ, and restore the interrupt mask */
-		SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ);
-		SK_OUT32(IoC, B0_IMSK, OrgIMsk);
-	}
-}	/* SkGeLoadLnkSyncCnt*/
-#endif	/* SK_LNK_SYNC_CNT */
-
-#if defined(SK_DIAG) || defined(SK_CFG_SYNC)
-/******************************************************************************
- *
- *	SkGeCfgSync() - Configure synchronous bandwidth for this port.
- *
- * Description:
- *	This function may be used to configure synchronous bandwidth
- *	to the specified port. This may be done any time after
- *	initializing the port. The configuration values are NOT saved
- *	in the HWAC port structure and will be overwritten any
- *	time when stopping and starting the port.
- *	Any values for the synchronous configuration will be ignored
- *	if the size of the synchronous queue is zero!
- *
- *	The default configuration for the synchronous service is
- *	TXA_ENA_FSYNC. This means if the size of
- *	the synchronous queue is unequal zero but no specific
- *	synchronous bandwidth is configured, the synchronous queue
- *	will always have the 'unlimited' transmit priority!
- *
- *	This mode will be restored if the synchronous bandwidth is
- *	deallocated ('IntTime' = 0 and 'LimCount' = 0).
- *
- * Returns:
- *	0:	success
- *	1:	parameter configuration error
- *	2:	try to configure quality of service although no
- *		synchronous queue is configured
- */
-int SkGeCfgSync(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U32	IntTime,	/* Interval Timer Value in units of 8ns */
-SK_U32	LimCount,	/* Number of bytes to transfer during IntTime */
-int		SyncMode)	/* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */
-{
-	int Rtv;
-
-	Rtv = 0;
-
-	/* check the parameters */
-	if (LimCount > IntTime ||
-		(LimCount == 0 && IntTime != 0) ||
-		(LimCount != 0 && IntTime == 0)) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
-		return(1);
-	}
-	
-	if (pAC->GIni.GP[Port].PXSQSize == 0) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG);
-		return(2);
-	}
-	
-	/* calculate register values */
-	IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100;
-	LimCount = LimCount / 8;
-	
-	if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
-		return(1);
-	}
-
-	/*
-	 * - Enable 'Force Sync' to ensure the synchronous queue
-	 *   has the priority while configuring the new values.
-	 * - Also 'disable alloc' to ensure the settings complies
-	 *   to the SyncMode parameter.
-	 * - Disable 'Rate Control' to configure the new values.
-	 * - write IntTime and LimCount
-	 * - start 'Rate Control' and disable 'Force Sync'
-	 *   if Interval Timer or Limit Counter not zero.
-	 */
-	SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
-		TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
-	
-	SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime);
-	SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount);
-	
-	SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
-		(SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC)));
-	
-	if (IntTime != 0 || LimCount != 0) {
-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC);
-	}
-
-	return(0);
-}	/* SkGeCfgSync */
-#endif /* SK_DIAG || SK_CFG_SYNC*/
-
-
-/******************************************************************************
- *
- *	DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue
- *
- * Desccription:
- *	If the queue is used, enable and initialize it.
- *	Make sure the queue is still reset, if it is not used.
- *
- * Returns:
- *	nothing
- */
-static void DoInitRamQueue(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* IO context */
-int		QuIoOffs,		/* Queue IO Address Offset */
-SK_U32	QuStartAddr,	/* Queue Start Address */
-SK_U32	QuEndAddr,		/* Queue End Address */
-int		QuType)			/* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */
-{
-	SK_U32	RxUpThresVal;
-	SK_U32	RxLoThresVal;
-
-	if (QuStartAddr != QuEndAddr) {
-		/* calculate thresholds, assume we have a big Rx queue */
-		RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8;
-		RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8;
-
-		/* build HW address format */
-		QuStartAddr = QuStartAddr / 8;
-		QuEndAddr = QuEndAddr / 8;
-
-		/* release local reset */
-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR);
-
-		/* configure addresses */
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr);
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr);
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr);
-		SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr);
-
-		switch (QuType) {
-		case SK_RX_SRAM_Q:
-			/* configure threshold for small Rx Queue */
-			RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8;
-
-			/* continue with SK_RX_BRAM_Q */
-		case SK_RX_BRAM_Q:
-			/* write threshold for Rx Queue */
-
-			SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal);
-			SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal);
-
-			/* the high priority threshold not used */
-			break;
-		case SK_TX_RAM_Q:
-			/*
-			 * Do NOT use Store & Forward under normal operation due to
-			 * performance optimization (GENESIS only).
-			 * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB)
-			 * or YUKON is used ((GMAC Tx FIFO is only 1 kB)
-			 * we NEED Store & Forward of the RAM buffer.
-			 */
-			if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK ||
-				pAC->GIni.GIYukon) {
-				/* enable Store & Forward Mode for the Tx Side */
-				SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD);
-			}
-			break;
-		}
-
-		/* set queue operational */
-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD);
-	}
-	else {
-		/* ensure the queue is still disabled */
-		SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET);
-	}
-}	/* DoInitRamQueue */
-
-
-/******************************************************************************
- *
- *	SkGeInitRamBufs() - Initialize the RAM Buffer Queues
- *
- * Description:
- *	Initialize all RAM Buffer Queues of the specified port
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitRamBufs(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT *pPrt;
-	int RxQType;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) {
-		RxQType = SK_RX_SRAM_Q; 	/* small Rx Queue */
-	}
-	else {
-		RxQType = SK_RX_BRAM_Q;		/* big Rx Queue */
-	}
-
-	DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart,
-		pPrt->PRxQRamEnd, RxQType);
-	
-	DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart,
-		pPrt->PXsQRamEnd, SK_TX_RAM_Q);
-	
-	DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart,
-		pPrt->PXaQRamEnd, SK_TX_RAM_Q);
-
-}	/* SkGeInitRamBufs */
-
-
-/******************************************************************************
- *
- *	SkGeInitRamIface() - Initialize the RAM Interface
- *
- * Description:
- *	This function initializes the Adapters RAM Interface.
- *
- * Note:
- *	This function is used in the diagnostics.
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitRamIface(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	/* release local reset */
-	SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR);
-
-	/* configure timeout values */
-	SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53);
-	SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53);
-
-}	/* SkGeInitRamIface */
-
-
-/******************************************************************************
- *
- *	SkGeInitBmu() - Initialize the BMU state machines
- *
- * Description:
- *	Initialize all BMU state machines of the specified port
- *
- * Returns:
- *	nothing
- */
-static void SkGeInitBmu(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U32		RxWm;
-	SK_U32		TxWm;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	RxWm = SK_BMU_RX_WM;
-	TxWm = SK_BMU_TX_WM;
-	
-	if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) {
-		/* for better performance */
-		RxWm /= 2;
-		TxWm /= 2;
-	}
-
-	/* Rx Queue: Release all local resets and set the watermark */
-	SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET);
-	SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm);
-
-	/*
-	 * Tx Queue: Release all local resets if the queue is used !
-	 * 		set watermark
-	 */
-	if (pPrt->PXSQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET);
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm);
-	}
-	
-	if (pPrt->PXAQSize != 0) {
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET);
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm);
-	}
-	/*
-	 * Do NOT enable the descriptor poll timers here, because
-	 * the descriptor addresses are not specified yet.
-	 */
-}	/* SkGeInitBmu */
-
-
-/******************************************************************************
- *
- *	TestStopBit() -	Test the stop bit of the queue
- *
- * Description:
- *	Stopping a queue is not as simple as it seems to be.
- *	If descriptor polling is enabled, it may happen
- *	that RX/TX stop is done and SV idle is NOT set.
- *	In this case we have to issue another stop command.
- *
- * Returns:
- *	The queues control status register
- */
-static SK_U32 TestStopBit(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		QuIoOffs)	/* Queue IO Address Offset */
-{
-	SK_U32	QuCsr;	/* CSR contents */
-
-	SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
-	
-	if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) {
-		/* Stop Descriptor overridden by start command */
-		SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP);
-
-		SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
-	}
-	
-	return(QuCsr);
-}	/* TestStopBit */
-
-
-/******************************************************************************
- *
- *	SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'.
- *
- * Description:
- *	After calling this function the descriptor rings and Rx and Tx
- *	queues of this port may be reconfigured.
- *
- *	It is possible to stop the receive and transmit path separate or
- *	both together.
- *
- *	Dir =	SK_STOP_TX 	Stops the transmit path only and resets the MAC.
- *				The receive queue is still active and
- *				the pending Rx frames may be still transferred
- *				into the RxD.
- *		SK_STOP_RX	Stop the receive path. The tansmit path
- *				has to be stopped once before.
- *		SK_STOP_ALL	SK_STOP_TX + SK_STOP_RX
- *
- *	RstMode = SK_SOFT_RST	Resets the MAC. The PHY is still alive.
- *			SK_HARD_RST	Resets the MAC and the PHY.
- *
- * Example:
- *	1) A Link Down event was signaled for a port. Therefore the activity
- *	of this port should be stopped and a hardware reset should be issued
- *	to enable the workaround of XMAC Errata #2. But the received frames
- *	should not be discarded.
- *		...
- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST);
- *		(transfer all pending Rx frames)
- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST);
- *		...
- *
- *	2) An event was issued which request the driver to switch
- *	the 'virtual active' link to an other already active port
- *	as soon as possible. The frames in the receive queue of this
- *	port may be lost. But the PHY must not be reset during this
- *	event.
- *		...
- *		SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST);
- *		...
- *
- * Extended Description:
- *	If SK_STOP_TX is set,
- *		o disable the MAC's receive and transmitter to prevent
- *		  from sending incomplete frames
- *		o stop the port's transmit queues before terminating the
- *		  BMUs to prevent from performing incomplete PCI cycles
- *		  on the PCI bus
- *		- The network Rx and Tx activity and PCI Tx transfer is
- *		  disabled now.
- *		o reset the MAC depending on the RstMode
- *		o Stop Interval Timer and Limit Counter of Tx Arbiter,
- *		  also disable Force Sync bit and Enable Alloc bit.
- *		o perform a local reset of the port's Tx path
- *			- reset the PCI FIFO of the async Tx queue
- *			- reset the PCI FIFO of the sync Tx queue
- *			- reset the RAM Buffer async Tx queue
- *			- reset the RAM Buffer sync Tx queue
- *			- reset the MAC Tx FIFO
- *		o switch Link and Tx LED off, stop the LED counters
- *
- *	If SK_STOP_RX is set,
- *		o stop the port's receive queue
- *		- The path data transfer activity is fully stopped now.
- *		o perform a local reset of the port's Rx path
- *			- reset the PCI FIFO of the Rx queue
- *			- reset the RAM Buffer receive queue
- *			- reset the MAC Rx FIFO
- *		o switch Rx LED off, stop the LED counter
- *
- *	If all ports are stopped,
- *		o reset the RAM Interface.
- *
- * Notes:
- *	o This function may be called during the driver states RESET_PORT and
- *	  SWITCH_PORT.
- */
-void SkGeStopPort(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* I/O context */
-int		Port,	/* port to stop (MAC_1 + n) */
-int		Dir,	/* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */
-int		RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */
-{
-#ifndef SK_DIAG
-	SK_EVPARA Para;
-#endif /* !SK_DIAG */
-	SK_GEPORT *pPrt;
-	SK_U32	DWord;
-	SK_U32	XsCsr;
-	SK_U32	XaCsr;
-	SK_U64	ToutStart;
-	int		i;
-	int		ToutCnt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if ((Dir & SK_STOP_TX) != 0) {
-		/* disable receiver and transmitter */
-		SkMacRxTxDisable(pAC, IoC, Port);
-		
-		/* stop both transmit queues */
-		/*
-		 * If the BMU is in the reset state CSR_STOP will terminate
-		 * immediately.
-		 */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP);
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP);
-
-		ToutStart = SkOsGetTime(pAC);
-		ToutCnt = 0;
-		do {
-			/*
-			 * Clear packet arbiter timeout to make sure
-			 * this loop will terminate.
-			 */
-			SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
-				PA_CLR_TO_TX1 : PA_CLR_TO_TX2));
-
-			/*
-			 * If the transfer stucks at the MAC the STOP command will not
-			 * terminate if we don't flush the XMAC's transmit FIFO !
-			 */
-			SkMacFlushTxFifo(pAC, IoC, Port);
-
-			XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
-			XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
-
-			if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) {
-				/*
-				 * Timeout of 1/18 second reached.
-				 * This needs to be checked at 1/18 sec only.
-				 */
-				ToutCnt++;
-				if (ToutCnt > 1) {
-					/* Might be a problem when the driver event handler
-					 * calls StopPort again. XXX.
-					 */
-
-					/* Fatal Error, Loop aborted */
-					SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018,
-						SKERR_HWI_E018MSG);
-#ifndef SK_DIAG
-					Para.Para64 = Port;
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-#endif /* !SK_DIAG */
-					return;
-				}
-				/*
-				 * Cache incoherency workaround: Assume a start command
-				 * has been lost while sending the frame.
-				 */
-				ToutStart = SkOsGetTime(pAC);
-
-				if ((XsCsr & CSR_STOP) != 0) {
-					SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START);
-				}
-				if ((XaCsr & CSR_STOP) != 0) {
-					SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START);
-				}
-			}
-
-			/*
-			 * Because of the ASIC problem report entry from 21.08.1998 it is
-			 * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set.
-			 */
-		} while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE ||
-				 (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
-
-		/* Reset the MAC depending on the RstMode */
-		if (RstMode == SK_SOFT_RST) {
-			SkMacSoftRst(pAC, IoC, Port);
-		}
-		else {
-			SkMacHardRst(pAC, IoC, Port);
-		}
- 		
-		/* Disable Force Sync bit and Enable Alloc bit */
-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
-			TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
-		
-		/* Stop Interval Timer and Limit Counter of Tx Arbiter */
-		SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L);
-		SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L);
-
-		/* Perform a local reset of the port's Tx path */
-
-		/* Reset the PCI FIFO of the async Tx queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET);
-		/* Reset the PCI FIFO of the sync Tx queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET);
-		/* Reset the RAM Buffer async Tx queue */
-		SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET);
-		/* Reset the RAM Buffer sync Tx queue */
-		SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET);
-		
-		/* Reset Tx MAC FIFO */
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			/* Note: MFF_RST_SET does NOT reset the XMAC ! */
-			SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET);
-
-			/* switch Link and Tx LED off, stop the LED counters */
-			/* Link LED is switched off by the RLMT and the Diag itself */
-			SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS);
-		}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-		if (pAC->GIni.GIYukon) {
-			/* Reset TX MAC FIFO */
-			SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
-		}
-#endif /* YUKON */
-	}
-
-	if ((Dir & SK_STOP_RX) != 0) {
-		/*
-		 * The RX Stop Command will not terminate if no buffers
-		 * are queued in the RxD ring. But it will always reach
-		 * the Idle state. Therefore we can use this feature to
-		 * stop the transfer of received packets.
-		 */
-		/* stop the port's receive queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP);
-		
-		i = 100;
-		do {
-			/*
-			 * Clear packet arbiter timeout to make sure
-			 * this loop will terminate
-			 */
-			SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
-				PA_CLR_TO_RX1 : PA_CLR_TO_RX2));
-
-			DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff);
-
-			/* timeout if i==0 (bug fix for #10748) */
-			if (--i == 0) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024,
-					SKERR_HWI_E024MSG);
-				break;
-			}
-			/*
-			 * because of the ASIC problem report entry from 21.08.98
-			 * it is required to wait until CSR_STOP is reset and
-			 * CSR_SV_IDLE is set.
-			 */
-		} while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
-
-		/* The path data transfer activity is fully stopped now */
-
-		/* Perform a local reset of the port's Rx path */
-
-		 /*	Reset the PCI FIFO of the Rx queue */
-		SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET);
-		/* Reset the RAM Buffer receive queue */
-		SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET);
-
-		/* Reset Rx MAC FIFO */
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			
-			SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET);
-
-			/* switch Rx LED off, stop the LED counter */
-			SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS);
-		}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-		if (pAC->GIni.GIYukon) {
-			/* Reset Rx MAC FIFO */
-			SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
-		}
-#endif /* YUKON */
-	}
-}	/* SkGeStopPort */
-
-
-/******************************************************************************
- *
- *	SkGeInit0() - Level 0 Initialization
- *
- * Description:
- *	- Initialize the BMU address offsets
- *
- * Returns:
- *	nothing
- */
-static void SkGeInit0(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	int i;
-	SK_GEPORT *pPrt;
-
-	for (i = 0; i < SK_MAX_MACS; i++) {
-		pPrt = &pAC->GIni.GP[i];
-
-		pPrt->PState = SK_PRT_RESET;
-		pPrt->PRxQOff = QOffTab[i].RxQOff;
-		pPrt->PXsQOff = QOffTab[i].XsQOff;
-		pPrt->PXaQOff = QOffTab[i].XaQOff;
-		pPrt->PCheckPar = SK_FALSE;
-		pPrt->PIsave = 0;
-		pPrt->PPrevShorts = 0;
-		pPrt->PLinkResCt = 0;
-		pPrt->PAutoNegTOCt = 0;
-		pPrt->PPrevRx = 0;
-		pPrt->PPrevFcs = 0;
-		pPrt->PRxLim = SK_DEF_RX_WA_LIM;
-		pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
-		pPrt->PLinkSpeedCap = (SK_U8)SK_LSPEED_CAP_1000MBPS;
-		pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_1000MBPS;
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_UNKNOWN;
-		pPrt->PLinkModeConf = (SK_U8)SK_LMODE_AUTOSENSE;
-		pPrt->PFlowCtrlMode = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
-		pPrt->PLinkCap = (SK_U8)(SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL |
-			SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL);
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-		pPrt->PFlowCtrlCap = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
-		pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
-		pPrt->PMSCap = 0;
-		pPrt->PMSMode = (SK_U8)SK_MS_MODE_AUTO;
-		pPrt->PMSStatus = (SK_U8)SK_MS_STAT_UNSET;
-		pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
-		pPrt->PAutoNegFail = SK_FALSE;
-		pPrt->PHWLinkUp = SK_FALSE;
-		pPrt->PLinkBroken = SK_TRUE; /* See WA code */
-		pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
-		pPrt->PMacColThres = TX_COL_DEF;
-		pPrt->PMacJamLen = TX_JAM_LEN_DEF;
-		pPrt->PMacJamIpgVal	= TX_JAM_IPG_DEF;
-		pPrt->PMacJamIpgData = TX_IPG_JAM_DEF;
-		pPrt->PMacIpgData = IPG_DATA_DEF;
-		pPrt->PMacLimit4 = SK_FALSE;
-	}
-
-	pAC->GIni.GIPortUsage = SK_RED_LINK;
-	pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value;
-	pAC->GIni.GIValIrqMask = IS_ALL_MSK;
-
-}	/* SkGeInit0*/
-
-
-/******************************************************************************
- *
- *	SkGeInit1() - Level 1 Initialization
- *
- * Description:
- *	o Do a software reset.
- *	o Clear all reset bits.
- *	o Verify that the detected hardware is present.
- *	  Return an error if not.
- *	o Get the hardware configuration
- *		+ Read the number of MACs/Ports.
- *		+ Read the RAM size.
- *		+ Read the PCI Revision Id.
- *		+ Find out the adapters host clock speed
- *		+ Read and check the PHY type
- *
- * Returns:
- *	0:	success
- *	5:	Unexpected PHY type detected
- *	6:	HW self test failed
- */
-static int SkGeInit1(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	SK_U8	Byte;
-	SK_U16	Word;
-	SK_U16	CtrlStat;
-	SK_U32	DWord;
-	int	RetVal;
-	int	i;
-
-	RetVal = 0;
-
-	/* save CLK_RUN bits (YUKON-Lite) */
-	SK_IN16(IoC, B0_CTST, &CtrlStat);
-
-	/* do the SW-reset */
-	SK_OUT8(IoC, B0_CTST, CS_RST_SET);
-
-	/* release the SW-reset */
-	SK_OUT8(IoC, B0_CTST, CS_RST_CLR);
-
-	/* reset all error bits in the PCI STATUS register */
-	/*
-	 * Note: PCI Cfg cycles cannot be used, because they are not
-	 *		 available on some platforms after 'boot time'.
-	 */
-	SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-	
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-	SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
-	/* release Master Reset */
-	SK_OUT8(IoC, B0_CTST, CS_MRST_CLR);
-
-#ifdef CLK_RUN
-	CtrlStat |= CS_CLK_RUN_ENA;
-#endif /* CLK_RUN */
-
-	/* restore CLK_RUN bits */
-	SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat &
-		(CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)));
-
-	/* read Chip Identification Number */
-	SK_IN8(IoC, B2_CHIP_ID, &Byte);
-	pAC->GIni.GIChipId = Byte;
-	
-	/* read number of MACs */
-	SK_IN8(IoC, B2_MAC_CFG, &Byte);
-	pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2;
-	
-	/* get Chip Revision Number */
-	pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4);
-
-	/* get diff. PCI parameters */
-	SK_IN16(IoC, B0_CTST, &CtrlStat);
-	
-	/* read the adapters RAM size */
-	SK_IN8(IoC, B2_E_0, &Byte);
-	
-	pAC->GIni.GIGenesis = SK_FALSE;
-	pAC->GIni.GIYukon = SK_FALSE;
-	pAC->GIni.GIYukonLite = SK_FALSE;
-
-#ifdef GENESIS
-	if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-
-		pAC->GIni.GIGenesis = SK_TRUE;
-
-		if (Byte == (SK_U8)3) {						
-			/* special case: 4 x 64k x 36, offset = 0x80000 */
-			pAC->GIni.GIRamSize = 1024;
-			pAC->GIni.GIRamOffs = (SK_U32)512 * 1024;
-		}
-		else {
-			pAC->GIni.GIRamSize = (int)Byte * 512;
-			pAC->GIni.GIRamOffs = 0;
-		}
-		/* all GE adapters work with 53.125 MHz host clock */
-		pAC->GIni.GIHstClkFact = SK_FACT_53;
-		
-		/* set Descr. Poll Timer Init Value to 250 ms */
-		pAC->GIni.GIPollTimerVal =
-			SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100;
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) {
-		
-		pAC->GIni.GIYukon = SK_TRUE;
-		
-		pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4;
-		
-		pAC->GIni.GIRamOffs = 0;
-		
-		/* WA for chip Rev. A */
-		pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON &&
-			pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0;
-		
-		/* get PM Capabilities of PCI config space */
-		SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word);
-
-		/* check if VAUX is available */
-		if (((CtrlStat & CS_VAUX_AVAIL) != 0) &&
-			/* check also if PME from D3cold is set */
-			((Word & PCI_PME_D3C_SUP) != 0)) {
-			/* set entry in GE init struct */
-			pAC->GIni.GIVauxAvail = SK_TRUE;
-		}
-		
-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
-			/* this is Rev. A1 */
-			pAC->GIni.GIYukonLite = SK_TRUE;
-		}
-		else {
-			/* save Flash-Address Register */
-			SK_IN32(IoC, B2_FAR, &DWord);
-
-			/* test Flash-Address Register */
-			SK_OUT8(IoC, B2_FAR + 3, 0xff);
-			SK_IN8(IoC, B2_FAR + 3, &Byte);
-
-			if (Byte != 0) {
-				/* this is Rev. A0 */
-				pAC->GIni.GIYukonLite = SK_TRUE;
-
-				/* restore Flash-Address Register */
-				SK_OUT32(IoC, B2_FAR, DWord);
-			}
-		}
-
-		/* switch power to VCC (WA for VAUX problem) */
-		SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
-			PC_VAUX_OFF | PC_VCC_ON));
-
-		/* read the Interrupt source */
-		SK_IN32(IoC, B0_ISRC, &DWord);
-		
-		if ((DWord & IS_HW_ERR) != 0) {
-			/* read the HW Error Interrupt source */
-			SK_IN32(IoC, B0_HWE_ISRC, &DWord);
-			
-			if ((DWord & IS_IRQ_SENSOR) != 0) {
-				/* disable HW Error IRQ */
-				pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
-			}
-		}
-		
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-			/* set GMAC Link Control reset */
-			SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET);
-
-			/* clear GMAC Link Control reset */
-			SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
-		}
-		/* all YU chips work with 78.125 MHz host clock */
-		pAC->GIni.GIHstClkFact = SK_FACT_78;
-		
-		pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;	/* 215 ms */
-	}
-#endif /* YUKON */
-
-	/* check if 64-bit PCI Slot is present */
-	pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0);
-	
-	/* check if 66 MHz PCI Clock is active */
-	pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0);
-
-	/* read PCI HW Revision Id. */
-	SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte);
-	pAC->GIni.GIPciHwRev = Byte;
-
-	/* read the PMD type */
-	SK_IN8(IoC, B2_PMD_TYP, &Byte);
-	pAC->GIni.GICopperType = (SK_U8)(Byte == 'T');
-
-	/* read the PHY type */
-	SK_IN8(IoC, B2_E_1, &Byte);
-
-	Byte &= 0x0f;	/* the PHY type is stored in the lower nibble */
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			switch (Byte) {
-			case SK_PHY_XMAC:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC;
-				break;
-			case SK_PHY_BCOM:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM;
-				pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
-					SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
-				break;
-#ifdef OTHER_PHY
-			case SK_PHY_LONE:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE;
-				break;
-			case SK_PHY_NAT:
-				pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT;
-				break;
-#endif /* OTHER_PHY */
-			default:
-				/* ERROR: unexpected PHY type detected */
-				RetVal = 5;
-				break;
-			}
-		}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-		if (pAC->GIni.GIYukon) {
-			
-			if (Byte < (SK_U8)SK_PHY_MARV_COPPER) {
-				/* if this field is not initialized */
-				Byte = (SK_U8)SK_PHY_MARV_COPPER;
-				
-				pAC->GIni.GICopperType = SK_TRUE;
-			}
-			
-			pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV;
-			
-			if (pAC->GIni.GICopperType) {
-
-				pAC->GIni.GP[i].PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_AUTO |
-					SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS |
-					SK_LSPEED_CAP_1000MBPS);
-				
-				pAC->GIni.GP[i].PLinkSpeed = (SK_U8)SK_LSPEED_AUTO;
-				
-				pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
-					SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
-			}
-			else {
-				Byte = (SK_U8)SK_PHY_MARV_FIBER;
-			}
-		}
-#endif /* YUKON */
-		
-		pAC->GIni.GP[i].PhyType = (int)Byte;
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-			("PHY type: %d  PHY addr: %04x\n", Byte,
-			pAC->GIni.GP[i].PhyAddr));
-	}
-	
-	/* get MAC Type & set function pointers dependent on */
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		pAC->GIni.GIMacType = SK_MAC_XMAC;
-
-		pAC->GIni.GIFunc.pFnMacUpdateStats	= SkXmUpdateStats;
-		pAC->GIni.GIFunc.pFnMacStatistic	= SkXmMacStatistic;
-		pAC->GIni.GIFunc.pFnMacResetCounter	= SkXmResetCounter;
-		pAC->GIni.GIFunc.pFnMacOverflow		= SkXmOverflowStatus;
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		pAC->GIni.GIMacType = SK_MAC_GMAC;
-
-		pAC->GIni.GIFunc.pFnMacUpdateStats	= SkGmUpdateStats;
-		pAC->GIni.GIFunc.pFnMacStatistic	= SkGmMacStatistic;
-		pAC->GIni.GIFunc.pFnMacResetCounter	= SkGmResetCounter;
-		pAC->GIni.GIFunc.pFnMacOverflow		= SkGmOverflowStatus;
-
-#ifdef SPECIAL_HANDLING
-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-			/* check HW self test result */
-			SK_IN8(IoC, B2_E_3, &Byte);
-			if (Byte & B2_E3_RES_MASK) {
-				RetVal = 6;
-			}
-		}
-#endif
-	}
-#endif /* YUKON */
-	
-	return(RetVal);
-}	/* SkGeInit1 */
-
-
-/******************************************************************************
- *
- *	SkGeInit2() - Level 2 Initialization
- *
- * Description:
- *	- start the Blink Source Counter
- *	- start the Descriptor Poll Timer
- *	- configure the MAC-Arbiter
- *	- configure the Packet-Arbiter
- *	- enable the Tx Arbiters
- *	- enable the RAM Interface Arbiter
- *
- * Returns:
- *	nothing
- */
-static void SkGeInit2(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-#ifdef GENESIS
-	SK_U32	DWord;
-#endif /* GENESIS */
-	int		i;
-
-	/* start the Descriptor Poll Timer */
-	if (pAC->GIni.GIPollTimerVal != 0) {
-		if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) {
-			pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG);
-		}
-		SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal);
-		SK_OUT8(IoC, B28_DPT_CTRL, DPT_START);
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* start the Blink Source Counter */
-		DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
-
-		SK_OUT32(IoC, B2_BSC_INI, DWord);
-		SK_OUT8(IoC, B2_BSC_CTRL, BSC_START);
-
-		/*
-		 * Configure the MAC Arbiter and the Packet Arbiter.
-		 * They will be started once and never be stopped.
-		 */
-		SkGeInitMacArb(pAC, IoC);
-
-		SkGeInitPktArb(pAC, IoC);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* start Time Stamp Timer */
-		SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START);
-	}
-#endif /* YUKON */
-
-	/* enable the Tx Arbiters */
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB);
-	}
-
-	/* enable the RAM Interface Arbiter */
-	SkGeInitRamIface(pAC, IoC);
-
-}	/* SkGeInit2 */
-
-/******************************************************************************
- *
- *	SkGeInit() - Initialize the GE Adapter with the specified level.
- *
- * Description:
- *	Level	0:	Initialize the Module structures.
- *	Level	1:	Generic Hardware Initialization. The IOP/MemBase pointer has
- *				to be set before calling this level.
- *
- *			o Do a software reset.
- *			o Clear all reset bits.
- *			o Verify that the detected hardware is present.
- *			  Return an error if not.
- *			o Get the hardware configuration
- *				+ Set GIMacsFound with the number of MACs.
- *				+ Store the RAM size in GIRamSize.
- *				+ Save the PCI Revision ID in GIPciHwRev.
- *			o return an error
- *				if Number of MACs > SK_MAX_MACS
- *
- *			After returning from Level 0 the adapter
- *			may be accessed with IO operations.
- *
- *	Level	2:	start the Blink Source Counter
- *
- * Returns:
- *	0:	success
- *	1:	Number of MACs exceeds SK_MAX_MACS	(after level 1)
- *	2:	Adapter not present or not accessible
- *	3:	Illegal initialization level
- *	4:	Initialization Level 1 Call missing
- *	5:	Unexpected PHY type detected
- *	6:	HW self test failed
- */
-int	SkGeInit(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Level)		/* initialization level */
-{
-	int		RetVal;		/* return value */
-	SK_U32	DWord;
-
-	RetVal = 0;
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
-		("SkGeInit(Level %d)\n", Level));
-
-	switch (Level) {
-	case SK_INIT_DATA:
-		/* Initialization Level 0 */
-		SkGeInit0(pAC, IoC);
-		pAC->GIni.GILevel = SK_INIT_DATA;
-		break;
-	
-	case SK_INIT_IO:
-		/* Initialization Level 1 */
-		RetVal = SkGeInit1(pAC, IoC);
-		if (RetVal != 0) {
-			break;
-		}
-
-		/* check if the adapter seems to be accessible */
-		SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL);
-		SK_IN32(IoC, B2_IRQM_INI, &DWord);
-		SK_OUT32(IoC, B2_IRQM_INI, 0L);
-		
-		if (DWord != SK_TEST_VAL) {
-			RetVal = 2;
-			break;
-		}
-
-		/* check if the number of GIMacsFound matches SK_MAX_MACS */
-		if (pAC->GIni.GIMacsFound > SK_MAX_MACS) {
-			RetVal = 1;
-			break;
-		}
-
-		/* Level 1 successfully passed */
-		pAC->GIni.GILevel = SK_INIT_IO;
-		break;
-	
-	case SK_INIT_RUN:
-		/* Initialization Level 2 */
-		if (pAC->GIni.GILevel != SK_INIT_IO) {
-#ifndef SK_DIAG
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG);
-#endif /* !SK_DIAG */
-			RetVal = 4;
-			break;
-		}
-		SkGeInit2(pAC, IoC);
-
-		/* Level 2 successfully passed */
-		pAC->GIni.GILevel = SK_INIT_RUN;
-		break;
-	
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG);
-		RetVal = 3;
-		break;
-	}
-
-	return(RetVal);
-}	/* SkGeInit */
-
-
-/******************************************************************************
- *
- *	SkGeDeInit() - Deinitialize the adapter
- *
- * Description:
- *	All ports of the adapter will be stopped if not already done.
- *	Do a software reset and switch off all LEDs.
- *
- * Returns:
- *	nothing
- */
-void SkGeDeInit(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC)		/* IO context */
-{
-	int	i;
-	SK_U16	Word;
-
-#if (!defined(SK_SLIM) && !defined(VCPU))
-	/* ensure I2C is ready */
-	SkI2cWaitIrq(pAC, IoC);
-#endif	
-
-	/* stop all current transfer activity */
-	for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-		if (pAC->GIni.GP[i].PState != SK_PRT_STOP &&
-			pAC->GIni.GP[i].PState != SK_PRT_RESET) {
-
-			SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST);
-		}
-	}
-
-	/* Reset all bits in the PCI STATUS register */
-	/*
-	 * Note: PCI Cfg cycles cannot be used, because they are not
-	 *	 available on some platforms after 'boot time'.
-	 */
-	SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-	
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-	SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
-	SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
-	/* do the reset, all LEDs are switched off now */
-	SK_OUT8(IoC, B0_CTST, CS_RST_SET);
-	
-	pAC->GIni.GILevel = SK_INIT_DATA;
-}	/* SkGeDeInit */
-
-
-/******************************************************************************
- *
- *	SkGeInitPort()	Initialize the specified port.
- *
- * Description:
- *	PRxQSize, PXSQSize, and PXAQSize has to be
- *	configured for the specified port before calling this function.
- *  The descriptor rings has to be initialized too.
- *
- *	o (Re)configure queues of the specified port.
- *	o configure the MAC of the specified port.
- *	o put ASIC and MAC(s) in operational mode.
- *	o initialize Rx/Tx and Sync LED
- *	o initialize RAM Buffers and MAC FIFOs
- *
- *	The port is ready to connect when returning.
- *
- * Note:
- *	The MAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- *	0:	success
- *	1:	Queue size initialization error. The configured values
- *		for PRxQSize, PXSQSize, or PXAQSize are invalid for one
- *		or more queues. The specified port was NOT initialized.
- *		An error log entry was generated.
- *	2:	The port has to be stopped before it can be initialized again.
- */
-int SkGeInitPort(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port to configure */
-{
-	SK_GEPORT *pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (SkGeCheckQSize(pAC, Port) != 0) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG);
-		return(1);
-	}
-	
-	if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG);
-		return(2);
-	}
-
-	/* configuration ok, initialize the Port now */
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* initialize Rx, Tx and Link LED */
-		/*
-		 * If 1000BT Phy needs LED initialization than swap
-		 * LED and XMAC initialization order
-		 */
-		SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
-		SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA);
-		/* The Link LED is initialized by RLMT or Diagnostics itself */
-		
-		SkXmInitMac(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-
-		SkGmInitMac(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-	
-	/* do NOT initialize the Link Sync Counter */
-
-	SkGeInitMacFifo(pAC, IoC, Port);
-	
-	SkGeInitRamBufs(pAC, IoC, Port);
-	
-	if (pPrt->PXSQSize != 0) {
-		/* enable Force Sync bit if synchronous queue available */
-		SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC);
-	}
-	
-	SkGeInitBmu(pAC, IoC, Port);
-
-	/* mark port as initialized */
-	pPrt->PState = SK_PRT_INIT;
-
-	return(0);
-}	/* SkGeInitPort */
diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c
deleted file mode 100644
index 0a6f67a..0000000
--- a/drivers/net/sk98lin/skgemib.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgemib.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.11 $
- * Date:	$Date: 2003/09/15 13:38:12 $
- * Purpose:	Private Network Management Interface Management Database
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * PRIVATE OID handler function prototypes
- */
-PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action,
-	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action,
-	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int* pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-
-#ifdef SK_POWER_MGMT
-PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-#endif /* SK_POWER_MGMT */
-
-#ifdef SK_DIAG_SUPPORT
-PNMI_STATIC int DiagActions(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance,
-	unsigned int TableIndex, SK_U32 NetIndex);
-#endif /* SK_DIAG_SUPPORT */
-
-
-/* defines *******************************************************************/
-#define ID_TABLE_SIZE (sizeof(IdTable)/sizeof(IdTable[0]))
-
-
-/* global variables **********************************************************/
-
-/*
- * Table to correlate OID with handler function and index to
- * hardware register stored in StatAddress if applicable.
- */
-PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = {
-	{OID_GEN_XMIT_OK,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX},
-	{OID_GEN_RCV_OK,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX},
-	{OID_GEN_XMIT_ERROR,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_GEN_RCV_ERROR,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_GEN_RCV_NO_BUFFER,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_GEN_DIRECTED_FRAMES_XMIT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST},
-	{OID_GEN_MULTICAST_FRAMES_XMIT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST},
-	{OID_GEN_BROADCAST_FRAMES_XMIT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST},
-	{OID_GEN_DIRECTED_FRAMES_RCV,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST},
-	{OID_GEN_MULTICAST_FRAMES_RCV,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST},
-	{OID_GEN_BROADCAST_FRAMES_RCV,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST},
-	{OID_GEN_RCV_CRC_ERROR,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS},
-	{OID_GEN_TRANSMIT_QUEUE_LENGTH,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_802_3_PERMANENT_ADDRESS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, 0},
-	{OID_802_3_CURRENT_ADDRESS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, 0},
-	{OID_802_3_RCV_ERROR_ALIGNMENT,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING},
-	{OID_802_3_XMIT_ONE_COLLISION,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL},
-	{OID_802_3_XMIT_MORE_COLLISIONS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL},
-	{OID_802_3_XMIT_DEFERRED,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL},
-	{OID_802_3_XMIT_MAX_COLLISIONS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL},
-	{OID_802_3_RCV_OVERRUN,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW},
-	{OID_802_3_XMIT_UNDERRUN,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN},
-	{OID_802_3_XMIT_TIMES_CRS_LOST,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER},
-	{OID_802_3_XMIT_LATE_COLLISIONS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL},
-#ifdef SK_POWER_MGMT
-	{OID_PNP_CAPABILITIES,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, PowerManagement, 0},
-	{OID_PNP_SET_POWER,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, PowerManagement, 0},
-	{OID_PNP_QUERY_POWER,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, PowerManagement, 0},
-	{OID_PNP_ADD_WAKE_UP_PATTERN,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, PowerManagement, 0},
-	{OID_PNP_REMOVE_WAKE_UP_PATTERN,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, PowerManagement, 0},
-	{OID_PNP_ENABLE_WAKE_UP,
-		0,
-		0,
-		0,
-		SK_PNMI_RW, PowerManagement, 0},
-#endif /* SK_POWER_MGMT */
-#ifdef SK_DIAG_SUPPORT
-	{OID_SKGE_DIAG_MODE,
-		0,
-		0,
-		0,
-		SK_PNMI_RW, DiagActions, 0},
-#endif /* SK_DIAG_SUPPORT */
-	{OID_SKGE_MDB_VERSION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(MgmtDBVersion),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SUPPORTED_LIST,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_ALL_DATA,
-		0,
-		0,
-		0,
-		SK_PNMI_RW, OidStruct, 0},
-	{OID_SKGE_VPD_FREE_BYTES,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VpdFreeBytes),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ENTRIES_LIST,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VpdEntriesList),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ENTRIES_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VpdEntriesNumber),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_KEY,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_VALUE,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ACCESS,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess),
-		SK_PNMI_RO, Vpd, 0},
-	{OID_SKGE_VPD_ACTION,
-		SK_PNMI_VPD_ENTRIES,
-		sizeof(SK_PNMI_VPD),
-		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction),
-		SK_PNMI_RW, Vpd, 0},
-	{OID_SKGE_PORT_NUMBER,		
-		1,
-		0,
-		SK_PNMI_MAI_OFF(PortNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DEVICE_TYPE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DeviceType),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_DESCR,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverDescr),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_VERSION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverVersion),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_RELDATE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverReleaseDate),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_DRIVER_FILENAME,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(DriverFileName),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_HW_DESCR,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(HwDescr),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_HW_VERSION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(HwVersion),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_CHIPSET,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(Chipset),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_CHIPID,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(ChipId),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RAMSIZE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RamSize),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_VAUXAVAIL,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(VauxAvail),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_ACTION,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(Action),
-		SK_PNMI_RW, Perform, 0},
-	{OID_SKGE_RESULT,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TestResult),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_BUS_TYPE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(BusType),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_BUS_SPEED,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(BusSpeed),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_BUS_WIDTH,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(BusWidth),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_SW_QUEUE_LEN,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxSwQueueLen),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_SW_QUEUE_MAX,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxSwQueueMax),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_RETRY,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxRetryCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_INTR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxIntrCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_INTR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxIntrCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_NO_BUF_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxNoBufCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_NO_BUF_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxNoBufCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_USED_DESCR_NO,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxUsedDescrNo),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_DELIVERED_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxDeliveredCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_OCTETS_DELIV_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxOctetsDeliveredCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RX_HW_ERROR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RxHwErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TX_HW_ERROR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TxHwErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_IN_ERRORS_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(InErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_OUT_ERROR_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(OutErrorsCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_ERR_RECOVERY_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(ErrRecoveryCts),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SYSUPTIME,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(SysUpTime),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SENSOR_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(SensorNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_SENSOR_INDEX,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_DESCR,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_TYPE,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_VALUE,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_THRES_LOW,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_THRES_UPP,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_THRES_LOW,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_THRES_UPP,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_STATUS,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_CTS,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_CTS,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_WAR_TIME,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_SENSOR_ERR_TIME,
-		SK_PNMI_SENSOR_ENTRIES,
-		sizeof(SK_PNMI_SENSOR),
-		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp),
-		SK_PNMI_RO, SensorStat, 0},
-	{OID_SKGE_CHKSM_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(ChecksumNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_CHKSM_RX_OK_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_RX_UNABLE_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_RX_ERR_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_TX_OK_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_CHKSM_TX_UNABLE_CTS,
-		SKCS_NUM_PROTOCOLS,
-		sizeof(SK_PNMI_CHECKSUM),
-		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts),
-		SK_PNMI_RO, CsumStat, 0},
-	{OID_SKGE_STAT_TX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX},
-	{OID_SKGE_STAT_TX_OCTETS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET},
-	{OID_SKGE_STAT_TX_BROADCAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST},
-	{OID_SKGE_STAT_TX_MULTICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST},
-	{OID_SKGE_STAT_TX_UNICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST},
-	{OID_SKGE_STAT_TX_LONGFRAMES,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES},
-	{OID_SKGE_STAT_TX_BURST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST},
-	{OID_SKGE_STAT_TX_PFLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC},
-	{OID_SKGE_STAT_TX_FLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC},
-	{OID_SKGE_STAT_TX_SINGLE_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL},
-	{OID_SKGE_STAT_TX_MULTI_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL},
-	{OID_SKGE_STAT_TX_EXCESS_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL},
-	{OID_SKGE_STAT_TX_LATE_COL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL},
-	{OID_SKGE_STAT_TX_DEFFERAL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL},
-	{OID_SKGE_STAT_TX_EXCESS_DEF,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF},
-	{OID_SKGE_STAT_TX_UNDERRUN,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN},
-	{OID_SKGE_STAT_TX_CARRIER,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER},
-/*	{OID_SKGE_STAT_TX_UTIL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization),
-		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
-	{OID_SKGE_STAT_TX_64,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64},
-	{OID_SKGE_STAT_TX_127,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127},
-	{OID_SKGE_STAT_TX_255,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255},
-	{OID_SKGE_STAT_TX_511,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511},
-	{OID_SKGE_STAT_TX_1023,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023},
-	{OID_SKGE_STAT_TX_MAX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX},
-	{OID_SKGE_STAT_TX_SYNC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC},
-	{OID_SKGE_STAT_TX_SYNC_OCTETS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET},
-	{OID_SKGE_STAT_RX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX},
-	{OID_SKGE_STAT_RX_OCTETS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET},
-	{OID_SKGE_STAT_RX_BROADCAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST},
-	{OID_SKGE_STAT_RX_MULTICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST},
-	{OID_SKGE_STAT_RX_UNICAST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST},
-	{OID_SKGE_STAT_RX_LONGFRAMES,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES},
-	{OID_SKGE_STAT_RX_PFLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC},
-	{OID_SKGE_STAT_RX_FLOWC,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC},
-	{OID_SKGE_STAT_RX_PFLOWC_ERR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR},
-	{OID_SKGE_STAT_RX_FLOWC_UNKWN,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN},
-	{OID_SKGE_STAT_RX_BURST,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST},
-	{OID_SKGE_STAT_RX_MISSED,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED},
-	{OID_SKGE_STAT_RX_FRAMING,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING},
-	{OID_SKGE_STAT_RX_OVERFLOW,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW},
-	{OID_SKGE_STAT_RX_JABBER,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER},
-	{OID_SKGE_STAT_RX_CARRIER,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER},
-	{OID_SKGE_STAT_RX_IR_LENGTH,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH},
-	{OID_SKGE_STAT_RX_SYMBOL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL},
-	{OID_SKGE_STAT_RX_SHORTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS},
-	{OID_SKGE_STAT_RX_RUNT,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT},
-	{OID_SKGE_STAT_RX_CEXT,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT},
-	{OID_SKGE_STAT_RX_TOO_LONG,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG},
-	{OID_SKGE_STAT_RX_FCS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS},
-/*	{OID_SKGE_STAT_RX_UTIL,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization),
-		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
-	{OID_SKGE_STAT_RX_64,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64},
-	{OID_SKGE_STAT_RX_127,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127},
-	{OID_SKGE_STAT_RX_255,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255},
-	{OID_SKGE_STAT_RX_511,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511},
-	{OID_SKGE_STAT_RX_1023,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023},
-	{OID_SKGE_STAT_RX_MAX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_STAT),
-		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts),
-		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX},
-	{OID_SKGE_PHYS_CUR_ADDR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr),
-		SK_PNMI_RW, Addr, 0},
-	{OID_SKGE_PHYS_FAC_ADDR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr),
-		SK_PNMI_RO, Addr, 0},
-	{OID_SKGE_PMD,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_CONNECTOR,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_PHY_TYPE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_LINK_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_LINK_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_LINK_MODE_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_LINK_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_FLOWCTRL_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_FLOWCTRL_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_FLOWCTRL_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_PHY_OPERATION_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_PHY_OPERATION_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_PHY_OPERATION_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_SPEED_CAP,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_SPEED_MODE,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_SPEED_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_CONF),
-		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus),
-		SK_PNMI_RO, MacPrivateConf, 0},
-	{OID_SKGE_TRAP,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(Trap),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_TRAP_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(TrapNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RLMT_MODE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtMode),
-		SK_PNMI_RW, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtPortNumber),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_ACTIVE,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtPortActive),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_PREFERRED,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtPortPreferred),
-		SK_PNMI_RW, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_CTS,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeCts),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_TIME,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeTime),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_ESTIM,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeEstimate),
-		SK_PNMI_RO, Rlmt, 0},
-	{OID_SKGE_RLMT_CHANGE_THRES,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtChangeThreshold),
-		SK_PNMI_RW, Rlmt, 0},
-	{OID_SKGE_RLMT_PORT_INDEX,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_STATUS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_TX_HELLO_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_RX_HELLO_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_TX_SP_REQ_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_RX_SP_CTS,
-		SK_PNMI_MAC_ENTRIES,
-		sizeof(SK_PNMI_RLMT),
-		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts),
-		SK_PNMI_RO, RlmtStat, 0},
-	{OID_SKGE_RLMT_MONITOR_NUMBER,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(RlmtMonitorNumber),
-		SK_PNMI_RO, General, 0},
-	{OID_SKGE_RLMT_MONITOR_INDEX,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_ADDR,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_ERRS,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_TIMESTAMP,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp),
-		SK_PNMI_RO, Monitor, 0},
-	{OID_SKGE_RLMT_MONITOR_ADMIN,
-		SK_PNMI_MONITOR_ENTRIES,
-		sizeof(SK_PNMI_RLMT_MONITOR),
-		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin),
-		SK_PNMI_RW, Monitor, 0},
-	{OID_SKGE_MTU,
-		1,
-		0,
-		SK_PNMI_MAI_OFF(MtuSize),
-		SK_PNMI_RW, MacPrivateConf, 0},
-	{OID_SKGE_VCT_GET,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Vct, 0},
-	{OID_SKGE_VCT_SET,
-		0,
-		0,
-		0,
-		SK_PNMI_WO, Vct, 0},
-	{OID_SKGE_VCT_STATUS,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, Vct, 0},
-	{OID_SKGE_BOARDLEVEL,
-		0,
-		0,
-		0,
-		SK_PNMI_RO, General, 0},
-};
-
diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c
deleted file mode 100644
index b36dd9a..0000000
--- a/drivers/net/sk98lin/skgepnmi.c
+++ /dev/null
@@ -1,8210 +0,0 @@
-/*****************************************************************************
- *
- * Name:	skgepnmi.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.111 $
- * Date:	$Date: 2003/09/15 13:35:35 $
- * Purpose:	Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-#ifndef _lint
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell.";
-#endif /* !_lint */
-
-#include "h/skdrv1st.h"
-#include "h/sktypes.h"
-#include "h/xmac_ii.h"
-#include "h/skdebug.h"
-#include "h/skqueue.h"
-#include "h/skgepnmi.h"
-#include "h/skgesirq.h"
-#include "h/skcsum.h"
-#include "h/skvpd.h"
-#include "h/skgehw.h"
-#include "h/skgeinit.h"
-#include "h/skdrv2nd.h"
-#include "h/skgepnm2.h"
-#ifdef SK_POWER_MGMT
-#include "h/skgepmgt.h"
-#endif
-/* defines *******************************************************************/
-
-#ifndef DEBUG
-#define PNMI_STATIC	static
-#else	/* DEBUG */
-#define PNMI_STATIC
-#endif /* DEBUG */
-
-/*
- * Public Function prototypes
- */
-int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level);
-int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
-	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param);
-int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
-	unsigned int * pLen, SK_U32 NetIndex);
-
-
-/*
- * Private Function prototypes
- */
-
-PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
-	PhysPortIndex);
-PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
-	PhysPortIndex);
-PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
-PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
-PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
-	unsigned int PhysPortIndex, unsigned int StatIndex);
-PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
-	unsigned int StatIndex, SK_U32 NetIndex);
-PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
-PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
-	unsigned int *pEntries);
-PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
-	unsigned int KeyArrLen, unsigned int *pKeyNo);
-PNMI_STATIC int LookupId(SK_U32 Id);
-PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
-	unsigned int LastMac);
-PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
-	unsigned int *pLen, SK_U32 NetIndex);
-PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
-	char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
-PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
-	unsigned int PortIndex);
-PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
-	unsigned int SensorIndex);
-PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
-PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
-PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
-PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
-PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf,
-	unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32);
-
-/*
- * Table to correlate OID with handler function and index to
- * hardware register stored in StatAddress if applicable.
- */
-#include "skgemib.c"
-
-/* global variables **********************************************************/
-
-/*
- * Overflow status register bit table and corresponding counter
- * dependent on MAC type - the number relates to the size of overflow
- * mask returned by the pFnMacOverflow function
- */
-PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = {
-/* Bit0  */	{ SK_PNMI_HTX, 				SK_PNMI_HTX_UNICAST},
-/* Bit1  */	{ SK_PNMI_HTX_OCTETHIGH, 	SK_PNMI_HTX_BROADCAST},
-/* Bit2  */	{ SK_PNMI_HTX_OCTETLOW, 	SK_PNMI_HTX_PMACC},
-/* Bit3  */	{ SK_PNMI_HTX_BROADCAST, 	SK_PNMI_HTX_MULTICAST},
-/* Bit4  */	{ SK_PNMI_HTX_MULTICAST, 	SK_PNMI_HTX_OCTETLOW},
-/* Bit5  */	{ SK_PNMI_HTX_UNICAST, 		SK_PNMI_HTX_OCTETHIGH},
-/* Bit6  */	{ SK_PNMI_HTX_LONGFRAMES, 	SK_PNMI_HTX_64},
-/* Bit7  */	{ SK_PNMI_HTX_BURST, 		SK_PNMI_HTX_127},
-/* Bit8  */	{ SK_PNMI_HTX_PMACC, 		SK_PNMI_HTX_255},
-/* Bit9  */	{ SK_PNMI_HTX_MACC, 		SK_PNMI_HTX_511},
-/* Bit10 */	{ SK_PNMI_HTX_SINGLE_COL, 	SK_PNMI_HTX_1023},
-/* Bit11 */	{ SK_PNMI_HTX_MULTI_COL, 	SK_PNMI_HTX_MAX},
-/* Bit12 */	{ SK_PNMI_HTX_EXCESS_COL, 	SK_PNMI_HTX_LONGFRAMES},
-/* Bit13 */	{ SK_PNMI_HTX_LATE_COL, 	SK_PNMI_HTX_RESERVED},
-/* Bit14 */	{ SK_PNMI_HTX_DEFFERAL, 	SK_PNMI_HTX_COL},
-/* Bit15 */	{ SK_PNMI_HTX_EXCESS_DEF, 	SK_PNMI_HTX_LATE_COL},
-/* Bit16 */	{ SK_PNMI_HTX_UNDERRUN, 	SK_PNMI_HTX_EXCESS_COL},
-/* Bit17 */	{ SK_PNMI_HTX_CARRIER, 		SK_PNMI_HTX_MULTI_COL},
-/* Bit18 */	{ SK_PNMI_HTX_UTILUNDER, 	SK_PNMI_HTX_SINGLE_COL},
-/* Bit19 */	{ SK_PNMI_HTX_UTILOVER, 	SK_PNMI_HTX_UNDERRUN},
-/* Bit20 */	{ SK_PNMI_HTX_64, 			SK_PNMI_HTX_RESERVED},
-/* Bit21 */	{ SK_PNMI_HTX_127, 			SK_PNMI_HTX_RESERVED},
-/* Bit22 */	{ SK_PNMI_HTX_255, 			SK_PNMI_HTX_RESERVED},
-/* Bit23 */	{ SK_PNMI_HTX_511, 			SK_PNMI_HTX_RESERVED},
-/* Bit24 */	{ SK_PNMI_HTX_1023, 		SK_PNMI_HTX_RESERVED},
-/* Bit25 */	{ SK_PNMI_HTX_MAX, 			SK_PNMI_HTX_RESERVED},
-/* Bit26 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit27 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit28 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit29 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit30 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit31 */	{ SK_PNMI_HTX_RESERVED, 	SK_PNMI_HTX_RESERVED},
-/* Bit32 */	{ SK_PNMI_HRX, 				SK_PNMI_HRX_UNICAST},
-/* Bit33 */	{ SK_PNMI_HRX_OCTETHIGH, 	SK_PNMI_HRX_BROADCAST},
-/* Bit34 */	{ SK_PNMI_HRX_OCTETLOW, 	SK_PNMI_HRX_PMACC},
-/* Bit35 */	{ SK_PNMI_HRX_BROADCAST, 	SK_PNMI_HRX_MULTICAST},
-/* Bit36 */	{ SK_PNMI_HRX_MULTICAST, 	SK_PNMI_HRX_FCS},
-/* Bit37 */	{ SK_PNMI_HRX_UNICAST, 		SK_PNMI_HRX_RESERVED},
-/* Bit38 */	{ SK_PNMI_HRX_PMACC, 		SK_PNMI_HRX_OCTETLOW},
-/* Bit39 */	{ SK_PNMI_HRX_MACC, 		SK_PNMI_HRX_OCTETHIGH},
-/* Bit40 */	{ SK_PNMI_HRX_PMACC_ERR, 	SK_PNMI_HRX_BADOCTETLOW},
-/* Bit41 */	{ SK_PNMI_HRX_MACC_UNKWN,	SK_PNMI_HRX_BADOCTETHIGH},
-/* Bit42 */	{ SK_PNMI_HRX_BURST, 		SK_PNMI_HRX_UNDERSIZE},
-/* Bit43 */	{ SK_PNMI_HRX_MISSED, 		SK_PNMI_HRX_RUNT},
-/* Bit44 */	{ SK_PNMI_HRX_FRAMING, 		SK_PNMI_HRX_64},
-/* Bit45 */	{ SK_PNMI_HRX_OVERFLOW, 	SK_PNMI_HRX_127},
-/* Bit46 */	{ SK_PNMI_HRX_JABBER, 		SK_PNMI_HRX_255},
-/* Bit47 */	{ SK_PNMI_HRX_CARRIER, 		SK_PNMI_HRX_511},
-/* Bit48 */	{ SK_PNMI_HRX_IRLENGTH, 	SK_PNMI_HRX_1023},
-/* Bit49 */	{ SK_PNMI_HRX_SYMBOL, 		SK_PNMI_HRX_MAX},
-/* Bit50 */	{ SK_PNMI_HRX_SHORTS, 		SK_PNMI_HRX_LONGFRAMES},
-/* Bit51 */	{ SK_PNMI_HRX_RUNT, 		SK_PNMI_HRX_TOO_LONG},
-/* Bit52 */	{ SK_PNMI_HRX_TOO_LONG, 	SK_PNMI_HRX_JABBER},
-/* Bit53 */	{ SK_PNMI_HRX_FCS, 			SK_PNMI_HRX_RESERVED},
-/* Bit54 */	{ SK_PNMI_HRX_RESERVED, 	SK_PNMI_HRX_OVERFLOW},
-/* Bit55 */	{ SK_PNMI_HRX_CEXT, 		SK_PNMI_HRX_RESERVED},
-/* Bit56 */	{ SK_PNMI_HRX_UTILUNDER, 	SK_PNMI_HRX_RESERVED},
-/* Bit57 */	{ SK_PNMI_HRX_UTILOVER, 	SK_PNMI_HRX_RESERVED},
-/* Bit58 */	{ SK_PNMI_HRX_64, 			SK_PNMI_HRX_RESERVED},
-/* Bit59 */	{ SK_PNMI_HRX_127, 			SK_PNMI_HRX_RESERVED},
-/* Bit60 */	{ SK_PNMI_HRX_255, 			SK_PNMI_HRX_RESERVED},
-/* Bit61 */	{ SK_PNMI_HRX_511, 			SK_PNMI_HRX_RESERVED},
-/* Bit62 */	{ SK_PNMI_HRX_1023, 		SK_PNMI_HRX_RESERVED},
-/* Bit63 */	{ SK_PNMI_HRX_MAX, 			SK_PNMI_HRX_RESERVED}
-};
-
-/*
- * Table for hardware register saving on resets and port switches
- */
-PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = {
-	/* SK_PNMI_HTX */
-	{{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_OCTETHIGH */
-	{{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}},
-	/* SK_PNMI_HTX_OCTETLOW */
-	{{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}},
-	/* SK_PNMI_HTX_BROADCAST */
-	{{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}},
-	/* SK_PNMI_HTX_MULTICAST */
-	{{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}},
-	/* SK_PNMI_HTX_UNICAST */
-	{{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}},
-	/* SK_PNMI_HTX_BURST */
-	{{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_PMACC */
-	{{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}},
-	/* SK_PNMI_HTX_MACC */
-	{{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_COL */
-	{{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_SINGLE_COL */
-	{{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_MULTI_COL */
-	{{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_EXCESS_COL */
-	{{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_LATE_COL */
-	{{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}},
-	/* SK_PNMI_HTX_DEFFERAL */
-	{{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_EXCESS_DEF */
-	{{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_UNDERRUN */
-	{{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}},
-	/* SK_PNMI_HTX_CARRIER */
-	{{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_UTILUNDER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_UTILOVER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_64 */
-	{{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}},
-	/* SK_PNMI_HTX_127 */
-	{{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}},
-	/* SK_PNMI_HTX_255 */
-	{{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}},
-	/* SK_PNMI_HTX_511 */
-	{{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}},
-	/* SK_PNMI_HTX_1023 */
-	{{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}},
-	/* SK_PNMI_HTX_MAX */
-	{{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}},
-	/* SK_PNMI_HTX_LONGFRAMES  */
-	{{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}},
-	/* SK_PNMI_HTX_SYNC */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_SYNC_OCTET */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HTX_RESERVED */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX */
-	{{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_OCTETHIGH */
-	{{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}},
-	/* SK_PNMI_HRX_OCTETLOW */
-	{{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}},
-	/* SK_PNMI_HRX_BADOCTETHIGH */
-	{{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}},
-	/* SK_PNMI_HRX_BADOCTETLOW */
-	{{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}},
-	/* SK_PNMI_HRX_BROADCAST */
-	{{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}},
-	/* SK_PNMI_HRX_MULTICAST */
-	{{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}},
-	/* SK_PNMI_HRX_UNICAST */
-	{{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}},
-	/* SK_PNMI_HRX_PMACC */
-	{{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}},
-	/* SK_PNMI_HRX_MACC */
-	{{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_PMACC_ERR */
-	{{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_MACC_UNKWN */
-	{{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_BURST */
-	{{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_MISSED */
-	{{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_FRAMING */
-	{{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_UNDERSIZE */
-	{{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}},
-	/* SK_PNMI_HRX_OVERFLOW */
-	{{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}},
-	/* SK_PNMI_HRX_JABBER */
-	{{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}},
-	/* SK_PNMI_HRX_CARRIER */
-	{{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_IRLENGTH */
-	{{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_SYMBOL */
-	{{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_SHORTS */
-	{{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_RUNT */
-	{{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}},
-	/* SK_PNMI_HRX_TOO_LONG */
-	{{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}},
-	/* SK_PNMI_HRX_FCS */
-	{{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}},
-	/* SK_PNMI_HRX_CEXT */
-	{{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_UTILUNDER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_UTILOVER */
-	{{0, SK_FALSE}, {0, SK_FALSE}},
-	/* SK_PNMI_HRX_64 */
-	{{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}},
-	/* SK_PNMI_HRX_127 */
-	{{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}},
-	/* SK_PNMI_HRX_255 */
-	{{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}},
-	/* SK_PNMI_HRX_511 */
-	{{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}},
-	/* SK_PNMI_HRX_1023 */
-	{{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}},
-	/* SK_PNMI_HRX_MAX */
-	{{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}},
-	/* SK_PNMI_HRX_LONGFRAMES */
-	{{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}},
-	/* SK_PNMI_HRX_RESERVED */
-	{{0, SK_FALSE}, {0, SK_FALSE}}
-};
-
-
-/*****************************************************************************
- *
- * Public functions
- *
- */
-
-/*****************************************************************************
- *
- * SkPnmiInit - Init function of PNMI
- *
- * Description:
- *	SK_INIT_DATA: Initialises the data structures
- *	SK_INIT_IO:   Resets the XMAC statistics, determines the device and
- *	              connector type.
- *	SK_INIT_RUN:  Starts a timer event for port switch per hour
- *	              calculation.
- *
- * Returns:
- *	Always 0
- */
-int SkPnmiInit(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Level)		/* Initialization level */
-{
-	unsigned int	PortMax;	/* Number of ports */
-	unsigned int	PortIndex;	/* Current port index in loop */
-	SK_U16		Val16;		/* Multiple purpose 16 bit variable */
-	SK_U8		Val8;		/* Mulitple purpose 8 bit variable */
-	SK_EVPARA	EventParam;	/* Event struct for timer event */
-	SK_PNMI_VCT	*pVctBackupData;
-
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiInit: Called, level=%d\n", Level));
-
-	switch (Level) {
-
-	case SK_INIT_DATA:
-		SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
-		pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
-		pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-		pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
-		for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
-
-			pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
-			pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
-		}
-
-#ifdef SK_PNMI_CHECK
-		if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) {
-			
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG);
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
-					   ("CounterOffset struct size (%d) differs from"
-						"SK_PNMI_MAX_IDX (%d)\n",
-						SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX));
-		}
-
-		if (SK_PNMI_MAX_IDX !=
-			(sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) {
-			
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG);
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
-					   ("StatAddr table size (%d) differs from "
-						"SK_PNMI_MAX_IDX (%d)\n",
-						(sizeof(StatAddr) /
-						 (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)),
-						 SK_PNMI_MAX_IDX));
-		}
-#endif /* SK_PNMI_CHECK */
-		break;
-
-	case SK_INIT_IO:
-		/*
-		 * Reset MAC counters
-		 */
-		PortMax = pAC->GIni.GIMacsFound;
-
-		for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
-
-			pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex);
-		}
-		
-		/* Initialize DSP variables for Vct() to 0xff => Never written! */		
-		for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
-			pAC->GIni.GP[PortIndex].PCableLen = 0xff;
-			pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex];
-			pVctBackupData->PCableLen = 0xff;
-		}
-		
-		/*
-		 * Get pci bus speed
-		 */
-		SK_IN16(IoC, B0_CTST, &Val16);
-		if ((Val16 & CS_BUS_CLOCK) == 0) {
-
-			pAC->Pnmi.PciBusSpeed = 33;
-		}
-		else {
-			pAC->Pnmi.PciBusSpeed = 66;
-		}
-
-		/*
-		 * Get pci bus width
-		 */
-		SK_IN16(IoC, B0_CTST, &Val16);
-		if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
-
-			pAC->Pnmi.PciBusWidth = 32;
-		}
-		else {
-			pAC->Pnmi.PciBusWidth = 64;
-		}
-
-		/*
-		 * Get chipset
-		 */
-		switch (pAC->GIni.GIChipId) {
-		case CHIP_ID_GENESIS:
-			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
-			break;
-
-		case CHIP_ID_YUKON:
-			pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
-			break;
-
-		default:
-			break;
-		}
-
-		/*
-		 * Get PMD and DeviceType
-		 */
-		SK_IN8(IoC, B2_PMD_TYP, &Val8);
-		switch (Val8) {
-		case 'S':
-			pAC->Pnmi.PMD = 3;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020002;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020001;
-			}
-			break;
-
-		case 'L':
-			pAC->Pnmi.PMD = 2;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020004;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020003;
-			}
-			break;
-
-		case 'C':
-			pAC->Pnmi.PMD = 4;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020006;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020005;
-			}
-			break;
-
-		case 'T':
-			pAC->Pnmi.PMD = 5;
-			if (pAC->GIni.GIMacsFound > 1) {
-
-				pAC->Pnmi.DeviceType = 0x00020008;
-			}
-			else {
-				pAC->Pnmi.DeviceType = 0x00020007;
-			}
-			break;
-
-		default :
-			pAC->Pnmi.PMD = 1;
-			pAC->Pnmi.DeviceType = 0;
-			break;
-		}
-
-		/*
-		 * Get connector
-		 */
-		SK_IN8(IoC, B2_CONN_TYP, &Val8);
-		switch (Val8) {
-		case 'C':
-			pAC->Pnmi.Connector = 2;
-			break;
-
-		case 'D':
-			pAC->Pnmi.Connector = 3;
-			break;
-
-		case 'F':
-			pAC->Pnmi.Connector = 4;
-			break;
-
-		case 'J':
-			pAC->Pnmi.Connector = 5;
-			break;
-
-		case 'V':
-			pAC->Pnmi.Connector = 6;
-			break;
-
-		default:
-			pAC->Pnmi.Connector = 1;
-			break;
-		}
-		break;
-
-	case SK_INIT_RUN:
-		/*
-		 * Start timer for RLMT change counter
-		 */
-		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
-			28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
-			EventParam);
-		break;
-
-	default:
-		break; /* Nothing todo */
-	}
-
-	return (0);
-}
-
-/*****************************************************************************
- *
- * SkPnmiGetVar - Retrieves the value of a single OID
- *
- * Description:
- *	Calls a general sub-function for all this stuff. If the instance
- *	-1 is passed, the values of all instances are returned in an
- *	array of values.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
- *	                         the data.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-static int SkPnmiGetVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-void *pBuf,		/* Buffer to which the management data will be copied */
-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
-			Id, *pLen, Instance, NetIndex));
-
-	return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
-		Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiPreSetVar - Presets the value of a single OID
- *
- * Description:
- *	Calls a general sub-function for all this stuff. The preset does
- *	the same as a set, but returns just before finally setting the
- *	new value. This is useful to check if a set might be successfull.
- *	If the instance -1 is passed, an array of values is supposed and
- *	all instances of the OID will be set.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-static int SkPnmiPreSetVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-void *pBuf,		/* Buffer to which the management data will be copied */
-unsigned int *pLen,	/* Total length of management data */
-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
-			Id, *pLen, Instance, NetIndex));
-
-
-	return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
-		Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiSetVar - Sets the value of a single OID
- *
- * Description:
- *	Calls a general sub-function for all this stuff. The preset does
- *	the same as a set, but returns just before finally setting the
- *	new value. This is useful to check if a set might be successfull.
- *	If the instance -1 is passed, an array of values is supposed and
- *	all instances of the OID will be set.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-int SkPnmiSetVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-void *pBuf,		/* Buffer to which the management data will be copied */
-unsigned int *pLen,	/* Total length of management data */
-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
-			Id, *pLen, Instance, NetIndex));
-
-	return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
-		Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	Runs through the IdTable, queries the single OIDs and stores the
- *	returned data into the management database structure
- *	SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
- *	is stored in the IdTable. The return value of the function will also
- *	be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
- *	minimum size of SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
- *	                         the data.
- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
- */
-int SkPnmiGetStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-void *pBuf,		/* Buffer to which the management data will be copied. */
-unsigned int *pLen,	/* Length of buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	TableIndex;
-	unsigned int	DstOffset;
-	unsigned int	InstanceNo;
-	unsigned int	InstanceCnt;
-	SK_U32		Instance;
-	unsigned int	TmpLen;
-	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
-
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
-			*pLen, NetIndex));
-
-	if (*pLen < SK_PNMI_STRUCT_SIZE) {
-
-		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
-
-			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
-				(SK_U32)(-1));
-		}
-
-		*pLen = SK_PNMI_STRUCT_SIZE;
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-    /*
-     * Check NetIndex
-     */
-	if (NetIndex >= pAC->Rlmt.NumNets) {
-		return (SK_PNMI_ERR_UNKNOWN_NET);
-	}
-
-	/* Update statistic */
-	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
-
-	if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
-		SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	/*
-	 * Increment semaphores to indicate that an update was
-	 * already done
-	 */
-	pAC->Pnmi.MacUpdatedFlag ++;
-	pAC->Pnmi.RlmtUpdatedFlag ++;
-	pAC->Pnmi.SirqUpdatedFlag ++;
-
-	/* Get vpd keys for instance calculation */
-	Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
-	if (Ret != SK_PNMI_ERR_OK) {
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		pAC->Pnmi.RlmtUpdatedFlag --;
-		pAC->Pnmi.SirqUpdatedFlag --;
-
-		SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	/* Retrieve values */
-	SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
-	for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
-
-		InstanceNo = IdTable[TableIndex].InstanceNo;
-		for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
-			InstanceCnt ++) {
-
-			DstOffset = IdTable[TableIndex].Offset +
-				(InstanceCnt - 1) *
-				IdTable[TableIndex].StructSize;
-
-			/*
-			 * For the VPD the instance is not an index number
-			 * but the key itself. Determin with the instance
-			 * counter the VPD key to be used.
-			 */
-			if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
-				IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
-				IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
-				IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
-
-				SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
-			}
-			else {
-				Instance = (SK_U32)InstanceCnt;
-			}
-
-			TmpLen = *pLen - DstOffset;
-			Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
-				IdTable[TableIndex].Id, (char *)pBuf +
-				DstOffset, &TmpLen, Instance, TableIndex, NetIndex);
-
-			/*
-			 * An unknown instance error means that we reached
-			 * the last instance of that variable. Proceed with
-			 * the next OID in the table and ignore the return
-			 * code.
-			 */
-			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
-
-                break;
-			}
-
-			if (Ret != SK_PNMI_ERR_OK) {
-
-				pAC->Pnmi.MacUpdatedFlag --;
-				pAC->Pnmi.RlmtUpdatedFlag --;
-				pAC->Pnmi.SirqUpdatedFlag --;
-
-				SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
-				SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-				return (Ret);
-			}
-		}
-	}
-
-	pAC->Pnmi.MacUpdatedFlag --;
-	pAC->Pnmi.RlmtUpdatedFlag --;
-	pAC->Pnmi.SirqUpdatedFlag --;
-
-	*pLen = SK_PNMI_STRUCT_SIZE;
-	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
-	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	Calls a general sub-function for all this set stuff. The preset does
- *	the same as a set, but returns just before finally setting the
- *	new value. This is useful to check if a set might be successfull.
- *	The sub-function runs through the IdTable, checks which OIDs are able
- *	to set, and calls the handler function of the OID to perform the
- *	preset. The return value of the function will also be stored in
- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- *	SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- */
-int SkPnmiPreSetStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-void *pBuf,		/* Buffer which contains the data to be set */
-unsigned int *pLen,	/* Length of buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
-			*pLen, NetIndex));
-
-	return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
-    					pLen, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	Calls a general sub-function for all this set stuff. The return value
- *	of the function will also be stored in SK_PNMI_STRUCT_DATA if the
- *	passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
- *	The sub-function runs through the IdTable, checks which OIDs are able
- *	to set, and calls the handler function of the OID to perform the
- *	set. The return value of the function will also be stored in
- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- *	SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- */
-int SkPnmiSetStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-void *pBuf,		/* Buffer which contains the data to be set */
-unsigned int *pLen,	/* Length of buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-		("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
-			*pLen, NetIndex));
-
-	return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
-    					pLen, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiEvent - Event handler
- *
- * Description:
- *	Handles the following events:
- *	SK_PNMI_EVT_SIRQ_OVERFLOW     When a hardware counter overflows an
- *	                              interrupt will be generated which is
- *	                              first handled by SIRQ which generates a
- *	                              this event. The event increments the
- *	                              upper 32 bit of the 64 bit counter.
- *	SK_PNMI_EVT_SEN_XXX           The event is generated by the I2C module
- *	                              when a sensor reports a warning or
- *	                              error. The event will store a trap
- *	                              message in the trap buffer.
- *	SK_PNMI_EVT_CHG_EST_TIMER     The timer event was initiated by this
- *	                              module and is used to calculate the
- *	                              port switches per hour.
- *	SK_PNMI_EVT_CLEAR_COUNTER     The event clears all counters and
- *	                              timestamps.
- *	SK_PNMI_EVT_XMAC_RESET        The event is generated by the driver
- *	                              before a hard reset of the XMAC is
- *	                              performed. All counters will be saved
- *	                              and added to the hardware counter
- *	                              values after reset to grant continuous
- *	                              counter values.
- *	SK_PNMI_EVT_RLMT_PORT_UP      Generated by RLMT to notify that a port
- *	                              went logically up. A trap message will
- *	                              be stored to the trap buffer.
- *	SK_PNMI_EVT_RLMT_PORT_DOWN    Generated by RLMT to notify that a port
- *	                              went logically down. A trap message will
- *	                              be stored to the trap buffer.
- *	SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
- *	                              spanning tree root bridges were
- *	                              detected. A trap message will be stored
- *	                              to the trap buffer.
- *	SK_PNMI_EVT_RLMT_ACTIVE_DOWN  Notifies PNMI that an active port went
- *	                              down. PNMI will not further add the
- *	                              statistic values to the virtual port.
- *	SK_PNMI_EVT_RLMT_ACTIVE_UP    Notifies PNMI that a port went up and
- *	                              is now an active port. PNMI will now
- *	                              add the statistic data of this port to
- *	                              the virtual port.
- *	SK_PNMI_EVT_RLMT_SET_NETS     Notifies PNMI about the net mode. The first parameter
- *	                              contains the number of nets. 1 means single net, 2 means
- *	                              dual net. The second parameter is -1
- *
- * Returns:
- *	Always 0
- */
-int SkPnmiEvent(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Event,		/* Event-Id */
-SK_EVPARA Param)	/* Event dependent parameter */
-{
-	unsigned int	PhysPortIndex;
-    unsigned int	MaxNetNumber;
-	int			CounterIndex;
-	int			Ret;
-	SK_U16		MacStatus;
-	SK_U64		OverflowStatus;
-	SK_U64		Mask;
-	int			MacType;
-	SK_U64		Value;
-	SK_U32		Val32;
-	SK_U16		Register;
-	SK_EVPARA	EventParam;
-	SK_U64		NewestValue;
-	SK_U64		OldestValue;
-	SK_U64		Delta;
-	SK_PNMI_ESTIMATE *pEst;
-	SK_U32		NetIndex;
-	SK_GEPORT	*pPrt;
-	SK_PNMI_VCT	*pVctBackupData;
-	SK_U32		RetCode;
-	int		i;
-	SK_U32		CableLength;
-
-
-#ifdef DEBUG
-	if (Event != SK_PNMI_EVT_XMAC_RESET) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-			("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
-			(unsigned int)Event, (unsigned int)Param.Para64));
-	}
-#endif /* DEBUG */
-	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
-
-	MacType = pAC->GIni.GIMacType;
-	
-	switch (Event) {
-
-	case SK_PNMI_EVT_SIRQ_OVERFLOW:
-		PhysPortIndex = (int)Param.Para32[0];
-		MacStatus = (SK_U16)Param.Para32[1];
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter"
-				 " wrong, PhysPortIndex=0x%x\n",
-				PhysPortIndex));
-			return (0);
-		}
-#endif /* DEBUG */
-		OverflowStatus = 0;
-
-		/*
-		 * Check which source caused an overflow interrupt.
-		 */
-		if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex,
-				MacStatus, &OverflowStatus) != 0) ||
-			(OverflowStatus == 0)) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-
-		/*
-		 * Check the overflow status register and increment
-		 * the upper dword of corresponding counter.
-		 */
-		for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
-			CounterIndex ++) {
-
-			Mask = (SK_U64)1 << CounterIndex;
-			if ((OverflowStatus & Mask) == 0) {
-
-				continue;
-			}
-
-			switch (StatOvrflwBit[CounterIndex][MacType]) {
-
-			case SK_PNMI_HTX_UTILUNDER:
-			case SK_PNMI_HTX_UTILOVER:
-				if (MacType == SK_MAC_XMAC) {
-					XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register);
-					Register |= XM_TX_SAM_LINE;
-					XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register);
-				}
-				break;
-
-			case SK_PNMI_HRX_UTILUNDER:
-			case SK_PNMI_HRX_UTILOVER:
-				if (MacType == SK_MAC_XMAC) {
-					XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register);
-					Register |= XM_RX_SAM_LINE;
-					XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register);
-				}
-				break;
-
-			case SK_PNMI_HTX_OCTETHIGH:
-			case SK_PNMI_HTX_OCTETLOW:
-			case SK_PNMI_HTX_RESERVED:
-			case SK_PNMI_HRX_OCTETHIGH:
-			case SK_PNMI_HRX_OCTETLOW:
-			case SK_PNMI_HRX_IRLENGTH:
-			case SK_PNMI_HRX_RESERVED:
-			
-			/*
-			 * the following counters aren't be handled (id > 63)
-			 */
-			case SK_PNMI_HTX_SYNC:
-			case SK_PNMI_HTX_SYNC_OCTET:
-				break;
-
-			case SK_PNMI_HRX_LONGFRAMES:
-				if (MacType == SK_MAC_GMAC) {
-					pAC->Pnmi.Port[PhysPortIndex].
-						CounterHigh[CounterIndex] ++;
-				}
-				break;
-
-			default:
-				pAC->Pnmi.Port[PhysPortIndex].
-					CounterHigh[CounterIndex] ++;
-			}
-		}
-		break;
-
-	case SK_PNMI_EVT_SEN_WAR_LOW:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-	case SK_PNMI_EVT_SEN_WAR_UPP:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-	case SK_PNMI_EVT_SEN_ERR_LOW:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-	
-	case SK_PNMI_EVT_SEN_ERR_UPP:
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate
-		 * an event for user space applications with the
-		 * SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
-			(unsigned int)Param.Para64);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-	case SK_PNMI_EVT_CHG_EST_TIMER:
-		/*
-		 * Calculate port switch average on a per hour basis
-		 *   Time interval for check       : 28125 ms
-		 *   Number of values for average  : 8
-		 *
-		 * Be careful in changing these values, on change check
-		 *   - typedef of SK_PNMI_ESTIMATE (Size of EstValue
-		 *     array one less than value number)
-		 *   - Timer initialization SkTimerStart() in SkPnmiInit
-		 *   - Delta value below must be multiplicated with
-		 *     power of 2
-		 *
-		 */
-		pEst = &pAC->Pnmi.RlmtChangeEstimate;
-		CounterIndex = pEst->EstValueIndex + 1;
-		if (CounterIndex == 7) {
-
-			CounterIndex = 0;
-		}
-		pEst->EstValueIndex = CounterIndex;
-
-		NewestValue = pAC->Pnmi.RlmtChangeCts;
-		OldestValue = pEst->EstValue[CounterIndex];
-		pEst->EstValue[CounterIndex] = NewestValue;
-
-		/*
-		 * Calculate average. Delta stores the number of
-		 * port switches per 28125 * 8 = 225000 ms
-		 */
-		if (NewestValue >= OldestValue) {
-
-			Delta = NewestValue - OldestValue;
-		}
-		else {
-			/* Overflow situation */
-			Delta = (SK_U64)(0 - OldestValue) + NewestValue;
-		}
-
-		/*
-		 * Extrapolate delta to port switches per hour.
-		 *     Estimate = Delta * (3600000 / 225000)
-		 *              = Delta * 16
-		 *              = Delta << 4
-		 */
-		pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
-
-		/*
-		 * Check if threshold is exceeded. If the threshold is
-		 * permanently exceeded every 28125 ms an event will be
-		 * generated to remind the user of this condition.
-		 */
-		if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
-			(pAC->Pnmi.RlmtChangeEstimate.Estimate >=
-			pAC->Pnmi.RlmtChangeThreshold)) {
-
-			QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
-			(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		}
-
-		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
-			28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
-			EventParam);
-		break;
-
-	case SK_PNMI_EVT_CLEAR_COUNTER:
-		/*
-		 *  Param.Para32[0] contains the NetIndex (0 ..1).
-		 *  Param.Para32[1] is reserved, contains -1.
-		 */
-		NetIndex = (SK_U32)Param.Para32[0];
-
-#ifdef DEBUG
-		if (NetIndex >= pAC->Rlmt.NumNets) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
-				NetIndex));
-
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Set all counters and timestamps to zero.
-		 * The according NetIndex is required as a
-		 * parameter of the event.
-		 */
-		ResetCounter(pAC, IoC, NetIndex);
-		break;
-
-	case SK_PNMI_EVT_XMAC_RESET:
-		/*
-		 * To grant continuous counter values store the current
-		 * XMAC statistic values to the entries 1..n of the
-		 * CounterOffset array. XMAC Errata #2
-		 */
-#ifdef DEBUG
-		if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
-				(unsigned int)Param.Para64));
-			return (0);
-		}
-#endif
-		PhysPortIndex = (unsigned int)Param.Para64;
-
-		/*
-		 * Update XMAC statistic to get fresh values
-		 */
-		Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-		if (Ret != SK_PNMI_ERR_OK) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-		/*
-		 * Increment semaphore to indicate that an update was
-		 * already done
-		 */
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
-			CounterIndex ++) {
-
-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
-				continue;
-			}
-
-			pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] =
-				GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-			
-			pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0;
-		}
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		break;
-
-	case SK_PNMI_EVT_RLMT_PORT_UP:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter"
-                 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
-
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
-		/* Bugfix for XMAC errata (#10620)*/
-		if (MacType == SK_MAC_XMAC) {
-			/* Add incremental difference to offset (#10620)*/
-			(void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
-				XM_RXE_SHT_ERR, &Val32);
-			
-			Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
-				 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
-			pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] +=
-				Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark;
-		}
-		
-		/* Tell VctStatus() that a link was up meanwhile. */
-		pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK;		
-		break;
-
-    case SK_PNMI_EVT_RLMT_PORT_DOWN:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter"
-                 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
-
-			return (0);
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
-		/* Bugfix #10620 - get zero level for incremental difference */
-		if (MacType == SK_MAC_XMAC) {
-
-			(void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
-				XM_RXE_SHT_ERR, &Val32);
-			
-			pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark =
-				(((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
-				 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
-		}
-		break;
-
-	case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-		NetIndex = (SK_U32)Param.Para32[1];
-
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
-				PhysPortIndex));
-		}
-
-		if (NetIndex >= pAC->Rlmt.NumNets) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
-				NetIndex));
-		}
-#endif /* DEBUG */
-
-		/*
-		 * For now, ignore event if NetIndex != 0.
-		 */
-		if (Param.Para32[1] != 0) {
-
-			return (0);
-		}
-
-		/*
-		 * Nothing to do if port is already inactive
-		 */
-		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-			return (0);
-		}
-
-		/*
-		 * Update statistic counters to calculate new offset for the virtual
-		 * port and increment semaphore to indicate that an update was already
-		 * done.
-		 */
-		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
-			SK_PNMI_ERR_OK) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		/*
-		 * Calculate new counter offset for virtual port to grant continous
-		 * counting on port switches. The virtual port consists of all currently
-		 * active ports. The port down event indicates that a port is removed
-		 * from the virtual port. Therefore add the counter value of the removed
-		 * port to the CounterOffset for the virtual port to grant the same
-		 * counter value.
-		 */
-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
-			CounterIndex ++) {
-
-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
-				continue;
-			}
-
-			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
-			pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
-		}
-
-		/*
-		 * Set port to inactive
-		 */
-		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		break;
-
-	case SK_PNMI_EVT_RLMT_ACTIVE_UP:
-		PhysPortIndex = (unsigned int)Param.Para32[0];
-		NetIndex = (SK_U32)Param.Para32[1];
-
-#ifdef DEBUG
-		if (PhysPortIndex >= SK_MAX_MACS) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
-				PhysPortIndex));
-		}
-
-		if (NetIndex >= pAC->Rlmt.NumNets) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
-				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
-				NetIndex));
-		}
-#endif /* DEBUG */
-
-		/*
-		 * For now, ignore event if NetIndex != 0.
-		 */
-		if (Param.Para32[1] != 0) {
-
-			return (0);
-		}
-
-		/*
-		 * Nothing to do if port is already active
-		 */
-		if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-			return (0);
-		}
-
-		/*
-		 * Statistic maintenance
-		 */
-		pAC->Pnmi.RlmtChangeCts ++;
-		pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueRlmtNewMacTrap(pAC, PhysPortIndex);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
-		/*
-		 * Update statistic counters to calculate new offset for the virtual
-		 * port and increment semaphore to indicate that an update was
-		 * already done.
-		 */
-		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
-			SK_PNMI_ERR_OK) {
-
-			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-			return (0);
-		}
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		/*
-		 * Calculate new counter offset for virtual port to grant continous
-		 * counting on port switches. A new port is added to the virtual port.
-		 * Therefore substract the counter value of the new port from the
-		 * CounterOffset for the virtual port to grant the same value.
-		 */
-		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
-			CounterIndex ++) {
-
-			if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
-				continue;
-			}
-
-			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
-			pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
-		}
-
-		/* Set port to active */
-		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
-
-		pAC->Pnmi.MacUpdatedFlag --;
-		break;
-
-	case SK_PNMI_EVT_RLMT_SEGMENTATION:
-		/*
-		 * Para.Para32[0] contains the NetIndex.
-		 */
-
-		/*
-		 * Store a trap message in the trap buffer and generate an event for
-		 * user space applications with the SK_DRIVER_SENDEVENT macro.
-		 */
-		QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
-		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
-		break;
-
-    case SK_PNMI_EVT_RLMT_SET_NETS:
-		/*
-		 *  Param.Para32[0] contains the number of Nets.
-		 *  Param.Para32[1] is reserved, contains -1.
-		 */
-	    /*
-    	 * Check number of nets
-		 */
-		MaxNetNumber = pAC->GIni.GIMacsFound;
-		if (((unsigned int)Param.Para32[0] < 1)
-			|| ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
-			return (SK_PNMI_ERR_UNKNOWN_NET);
-		}
-
-        if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */
-        	pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
-        }
-        else { /* dual net mode */
-        	pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
-        }
-        break;
-
-    case SK_PNMI_EVT_VCT_RESET:
-		PhysPortIndex = Param.Para32[0];
-		pPrt = &pAC->GIni.GP[PhysPortIndex];
-		pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
-		
-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
-			RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
-			if (RetCode == 2) {
-				/*
-				 * VCT test is still running.
-				 * Start VCT timer counter again.
-				 */
-				SK_MEMSET((char *) &Param, 0, sizeof(Param));
-				Param.Para32[0] = PhysPortIndex;
-				Param.Para32[1] = -1;
-				SkTimerStart(pAC, IoC,
-					&pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
-				4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
-				break;
-			}
-			pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
-			pAC->Pnmi.VctStatus[PhysPortIndex] |=
-				(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
-			
-			/* Copy results for later use to PNMI struct. */
-			for (i = 0; i < 4; i++)  {
-				if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
-					if ((pPrt->PMdiPairLen[i] > 35) &&
-						(pPrt->PMdiPairLen[i] < 0xff)) {
-						pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
-					}
-				}
-				if ((pPrt->PMdiPairLen[i] > 35) &&
-					(pPrt->PMdiPairLen[i] != 0xff)) {
-					CableLength = 1000 *
-						(((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
-				}
-				else {
-					CableLength = 0;
-				}
-				pVctBackupData->PMdiPairLen[i] = CableLength;
-				pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
-			}
-			
-			Param.Para32[0] = PhysPortIndex;
-			Param.Para32[1] = -1;
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param);
-			SkEventDispatcher(pAC, IoC);
-		}
-		
-		break;
-
-	default:
-		break;
-	}
-
-	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
-	return (0);
-}
-
-
-/******************************************************************************
- *
- * Private functions
- *
- */
-
-/*****************************************************************************
- *
- * PnmiVar - Gets, presets, and sets single OIDs
- *
- * Description:
- *	Looks up the requested OID, calls the corresponding handler
- *	function, and passes the parameters with the get, preset, or
- *	set command. The function is called by SkGePnmiGetVar,
- *	SkGePnmiPreSetVar, or SkGePnmiSetVar.
- *
- * Returns:
- *	SK_PNMI_ERR_XXX. For details have a look at the description of the
- *	calling functions.
- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
- */
-PNMI_STATIC int PnmiVar(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* Total length of pBuf management data  */
-SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	TableIndex;
-	int		Ret;
-
-
-	if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_OID);
-	}
-	
-    /* Check NetIndex */
-	if (NetIndex >= pAC->Rlmt.NumNets) {
-		return (SK_PNMI_ERR_UNKNOWN_NET);
-	}
-
-	SK_PNMI_CHECKFLAGS("PnmiVar: On call");
-
-	Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
-		Instance, TableIndex, NetIndex);
-
-	SK_PNMI_CHECKFLAGS("PnmiVar: On return");
-
-	return (Ret);
-}
-
-/*****************************************************************************
- *
- * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
- *
- * Description:
- *	The return value of the function will also be stored in
- *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- *	SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
- *	checks which OIDs are able to set, and calls the handler function of
- *	the OID to perform the set. The return value of the function will
- *	also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
- *	minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
- *	by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
- *
- * Returns:
- *	SK_PNMI_ERR_XXX. The codes are described in the calling functions.
- *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
- */
-PNMI_STATIC int PnmiStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int  Action,	/* PRESET/SET action to be performed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* Length of pBuf management data buffer */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	TableIndex;
-	unsigned int	DstOffset;
-	unsigned int	Len;
-	unsigned int	InstanceNo;
-	unsigned int	InstanceCnt;
-	SK_U32		Instance;
-	SK_U32		Id;
-
-
-	/* Check if the passed buffer has the right size */
-	if (*pLen < SK_PNMI_STRUCT_SIZE) {
-
-		/* Check if we can return the error within the buffer */
-		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
-
-			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
-				(SK_U32)(-1));
-		}
-
-		*pLen = SK_PNMI_STRUCT_SIZE;
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-	
-    /* Check NetIndex */
-	if (NetIndex >= pAC->Rlmt.NumNets) {
-		return (SK_PNMI_ERR_UNKNOWN_NET);
-	}
-	
-	SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
-
-	/*
-	 * Update the values of RLMT and SIRQ and increment semaphores to
-	 * indicate that an update was already done.
-	 */
-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
-		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
-		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-		return (Ret);
-	}
-
-	pAC->Pnmi.RlmtUpdatedFlag ++;
-	pAC->Pnmi.SirqUpdatedFlag ++;
-
-	/* Preset/Set values */
-	for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
-
-		if ((IdTable[TableIndex].Access != SK_PNMI_RW) &&
-			(IdTable[TableIndex].Access != SK_PNMI_WO)) {
-
-			continue;
-		}
-
-		InstanceNo = IdTable[TableIndex].InstanceNo;
-		Id = IdTable[TableIndex].Id;
-
-		for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
-			InstanceCnt ++) {
-
-			DstOffset = IdTable[TableIndex].Offset +
-				(InstanceCnt - 1) *
-				IdTable[TableIndex].StructSize;
-
-			/*
-			 * Because VPD multiple instance variables are
-			 * not setable we do not need to evaluate VPD
-			 * instances. Have a look to VPD instance
-			 * calculation in SkPnmiGetStruct().
-			 */
-			Instance = (SK_U32)InstanceCnt;
-
-			/*
-			 * Evaluate needed buffer length
-			 */
-			Len = 0;
-			Ret = IdTable[TableIndex].Func(pAC, IoC,
-				SK_PNMI_GET, IdTable[TableIndex].Id,
-				NULL, &Len, Instance, TableIndex, NetIndex);
-
-			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
-
-				break;
-			}
-			if (Ret != SK_PNMI_ERR_TOO_SHORT) {
-
-				pAC->Pnmi.RlmtUpdatedFlag --;
-				pAC->Pnmi.SirqUpdatedFlag --;
-
-				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
-				SK_PNMI_SET_STAT(pBuf,
-					SK_PNMI_ERR_GENERAL, DstOffset);
-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			if (Id == OID_SKGE_VPD_ACTION) {
-
-				switch (*(pBuf + DstOffset)) {
-
-				case SK_PNMI_VPD_CREATE:
-					Len = 3 + *(pBuf + DstOffset + 3);
-					break;
-
-				case SK_PNMI_VPD_DELETE:
-					Len = 3;
-					break;
-
-				default:
-					Len = 1;
-					break;
-				}
-			}
-
-			/* Call the OID handler function */
-			Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
-				IdTable[TableIndex].Id, pBuf + DstOffset,
-				&Len, Instance, TableIndex, NetIndex);
-
-			if (Ret != SK_PNMI_ERR_OK) {
-
-				pAC->Pnmi.RlmtUpdatedFlag --;
-				pAC->Pnmi.SirqUpdatedFlag --;
-
-				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
-				SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
-					DstOffset);
-				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-		}
-	}
-
-	pAC->Pnmi.RlmtUpdatedFlag --;
-	pAC->Pnmi.SirqUpdatedFlag --;
-
-	SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
-	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * LookupId - Lookup an OID in the IdTable
- *
- * Description:
- *	Scans the IdTable to find the table entry of an OID.
- *
- * Returns:
- *	The table index or -1 if not found.
- */
-PNMI_STATIC int LookupId(
-SK_U32 Id)		/* Object identifier to be searched */
-{
-	int i;
-
-	for (i = 0; i < ID_TABLE_SIZE; i++) {
-
-		if (IdTable[i].Id == Id) {
-
-			return i;
-		}
-	}
-
-	return (-1);
-}
-
-/*****************************************************************************
- *
- * OidStruct - Handler of OID_SKGE_ALL_DATA
- *
- * Description:
- *	This OID performs a Get/Preset/SetStruct call and returns all data
- *	in a SK_PNMI_STRUCT_DATA structure.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int OidStruct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	if (Id != OID_SKGE_ALL_DATA) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003,
-			SK_PNMI_ERR003MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	/*
-	 * Check instance. We only handle single instance variables
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	switch (Action) {
-
-	case SK_PNMI_GET:
-		return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-
-	case SK_PNMI_PRESET:
-		return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-
-	case SK_PNMI_SET:
-		return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-	}
-
-	SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
-
-	*pLen = 0;
-	return (SK_PNMI_ERR_GENERAL);
-}
-
-/*****************************************************************************
- *
- * Perform - OID handler of OID_SKGE_ACTION
- *
- * Description:
- *	None.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Perform(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int	Ret;
-	SK_U32	ActionOp;
-
-
-	/*
-	 * Check instance. We only handle single instance variables
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	if (*pLen < sizeof(SK_U32)) {
-
-		*pLen = sizeof(SK_U32);
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-	/* Check if a get should be performed */
-	if (Action == SK_PNMI_GET) {
-
-		/* A get is easy. We always return the same value */
-		ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
-		SK_PNMI_STORE_U32(pBuf, ActionOp);
-		*pLen = sizeof(SK_U32);
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Continue with PRESET/SET action */
-	if (*pLen > sizeof(SK_U32)) {
-
-		return (SK_PNMI_ERR_BAD_VALUE);
-	}
-
-	/* Check if the command is a known one */
-	SK_PNMI_READ_U32(pBuf, ActionOp);
-	if (*pLen > sizeof(SK_U32) ||
-		(ActionOp != SK_PNMI_ACT_IDLE &&
-		ActionOp != SK_PNMI_ACT_RESET &&
-		ActionOp != SK_PNMI_ACT_SELFTEST &&
-		ActionOp != SK_PNMI_ACT_RESETCNT)) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_BAD_VALUE);
-	}
-
-	/* A preset ends here */
-	if (Action == SK_PNMI_PRESET) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	switch (ActionOp) {
-
-	case SK_PNMI_ACT_IDLE:
-		/* Nothing to do */
-		break;
-
-	case SK_PNMI_ACT_RESET:
-		/*
-		 * Perform a driver reset or something that comes near
-		 * to this.
-		 */
-		Ret = SK_DRIVER_RESET(pAC, IoC);
-		if (Ret != 0) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005,
-				SK_PNMI_ERR005MSG);
-
-			return (SK_PNMI_ERR_GENERAL);
-		}
-		break;
-
-	case SK_PNMI_ACT_SELFTEST:
-		/*
-		 * Perform a driver selftest or something similar to this.
-		 * Currently this feature is not used and will probably
-		 * implemented in another way.
-		 */
-		Ret = SK_DRIVER_SELFTEST(pAC, IoC);
-		pAC->Pnmi.TestResult = Ret;
-		break;
-
-	case SK_PNMI_ACT_RESETCNT:
-		/* Set all counters and timestamps to zero */
-		ResetCounter(pAC, IoC, NetIndex);
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006,
-			SK_PNMI_ERR006MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX
- *
- * Description:
- *	Retrieves the statistic values of the virtual port (logical
- *	index 0). Only special OIDs of NDIS are handled which consist
- *	of a 32 bit instead of a 64 bit value. The OIDs are public
- *	because perhaps some other platform can use them too.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Mac8023Stat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex,	/* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int     Ret;
-	SK_U64  StatVal;
-	SK_U32  StatVal32;
-	SK_BOOL Is64BitReq = SK_FALSE;
-
-	/*
-	 * Only the active Mac is returned
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Check action type
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	switch (Id) {
-
-	case OID_802_3_PERMANENT_ADDRESS:
-	case OID_802_3_CURRENT_ADDRESS:
-		if (*pLen < sizeof(SK_MAC_ADDR)) {
-
-			*pLen = sizeof(SK_MAC_ADDR);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-#ifndef SK_NDIS_64BIT_CTR
-		if (*pLen < sizeof(SK_U32)) {
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-#else /* SK_NDIS_64BIT_CTR */
-
-		/* for compatibility, at least 32bit are required for OID */
-		if (*pLen < sizeof(SK_U32)) {
-			/*
-			* but indicate handling for 64bit values,
-			* if insufficient space is provided
-			*/
-			*pLen = sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
-#endif /* SK_NDIS_64BIT_CTR */
-		break;
-	}
-
-	/*
-	 * Update all statistics, because we retrieve virtual MAC, which
-	 * consists of multiple physical statistics and increment semaphore
-	 * to indicate that an update was already done.
-	 */
-	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-	if ( Ret != SK_PNMI_ERR_OK) {
-
-		*pLen = 0;
-		return (Ret);
-	}
-	pAC->Pnmi.MacUpdatedFlag ++;
-
-	/*
-	 * Get value (MAC Index 0 identifies the virtual MAC)
-	 */
-	switch (Id) {
-
-	case OID_802_3_PERMANENT_ADDRESS:
-		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
-		*pLen = sizeof(SK_MAC_ADDR);
-		break;
-
-	case OID_802_3_CURRENT_ADDRESS:
-		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
-		*pLen = sizeof(SK_MAC_ADDR);
-		break;
-
-	default:
-		StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
-
-		/* by default 32bit values are evaluated */
-		if (!Is64BitReq) {
-			StatVal32 = (SK_U32)StatVal;
-			SK_PNMI_STORE_U32(pBuf, StatVal32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, StatVal);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-	}
-
-	pAC->Pnmi.MacUpdatedFlag --;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX
- *
- * Description:
- *	Retrieves the MAC statistic data.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int MacPrivateStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	LogPortMax;
-	unsigned int	LogPortIndex;
-	unsigned int	PhysPortMax;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	int				MacType;
-	int				Ret;
-	SK_U64			StatVal;
-	
-	
-
-	/* Calculate instance if wished. MAC index 0 is the virtual MAC */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-	
-	MacType = pAC->GIni.GIMacType;
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
-		LogPortMax--;
-	}
-
-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > LogPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
-		Limit = LogPortIndex + 1;
-	}
-
-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
-		LogPortIndex = 0;
-		Limit = LogPortMax;
-	}
-
-	/* Check action */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
-
-		*pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-	/*
-	 * Update MAC statistic and increment semaphore to indicate that
-	 * an update was already done.
-	 */
-	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-	if (Ret != SK_PNMI_ERR_OK) {
-
-		*pLen = 0;
-		return (Ret);
-	}
-	pAC->Pnmi.MacUpdatedFlag ++;
-
-	/* Get value */
-	Offset = 0;
-	for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-		switch (Id) {
-
-/* XXX not yet implemented due to XMAC problems
-		case OID_SKGE_STAT_TX_UTIL:
-			return (SK_PNMI_ERR_GENERAL);
-*/
-/* XXX not yet implemented due to XMAC problems
-		case OID_SKGE_STAT_RX_UTIL:
-			return (SK_PNMI_ERR_GENERAL);
-*/
-		case OID_SKGE_STAT_RX:
-			if (MacType == SK_MAC_GMAC) {
-				StatVal =
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_BROADCAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_MULTICAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_UNICAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HRX_UNDERSIZE, NetIndex);
-			}
-			else {
-				StatVal = GetStatVal(pAC, IoC, LogPortIndex,
-					IdTable[TableIndex].Param, NetIndex);
-			}
-			break;
-
-		case OID_SKGE_STAT_TX:
-			if (MacType == SK_MAC_GMAC) {
-				StatVal =
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HTX_BROADCAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HTX_MULTICAST, NetIndex) +
-					GetStatVal(pAC, IoC, LogPortIndex,
-							   SK_PNMI_HTX_UNICAST, NetIndex);
-			}
-			else {
-				StatVal = GetStatVal(pAC, IoC, LogPortIndex,
-					IdTable[TableIndex].Param, NetIndex);
-			}
-			break;
-
-		default:
-			StatVal = GetStatVal(pAC, IoC, LogPortIndex,
-				IdTable[TableIndex].Param, NetIndex);
-		}
-		SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
-
-		Offset += sizeof(SK_U64);
-	}
-	*pLen = Offset;
-
-	pAC->Pnmi.MacUpdatedFlag --;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
- *
- * Description:
- *	Get/Presets/Sets the current and factory MAC address. The MAC
- *	address of the virtual port, which is reported to the OS, may
- *	not be changed, but the physical ones. A set to the virtual port
- *	will be ignored. No error should be reported because otherwise
- *	a multiple instance set (-1) would always fail.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Addr(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	LogPortMax;
-	unsigned int	PhysPortMax;
-	unsigned int	LogPortIndex;
-	unsigned int	PhysPortIndex;
-	unsigned int	Limit;
-	unsigned int	Offset = 0;
-
-	/*
-	 * Calculate instance if wished. MAC index 0 is the virtual
-	 * MAC.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
-		LogPortMax--;
-	}
-
-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > LogPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
-		Limit = LogPortIndex + 1;
-	}
-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
-		LogPortIndex = 0;
-		Limit = LogPortMax;
-	}
-
-	/*
-	 * Perform Action
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/* Check length */
-		if (*pLen < (Limit - LogPortIndex) * 6) {
-
-			*pLen = (Limit - LogPortIndex) * 6;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		/*
-		 * Get value
-		 */
-		for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-			switch (Id) {
-
-			case OID_SKGE_PHYS_CUR_ADDR:
-				if (LogPortIndex == 0) {
-					CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
-				}
-				else {
-					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-
-					CopyMac(pBuf + Offset,
-						&pAC->Addr.Port[PhysPortIndex].CurrentMacAddress);
-				}
-				Offset += 6;
-				break;
-
-			case OID_SKGE_PHYS_FAC_ADDR:
-				if (LogPortIndex == 0) {
-					CopyMac(pBuf + Offset,
-						&pAC->Addr.Net[NetIndex].PermanentMacAddress);
-				}
-				else {
-					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-						pAC, LogPortIndex);
-
-					CopyMac(pBuf + Offset,
-						&pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
-				}
-				Offset += 6;
-				break;
-
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008,
-					SK_PNMI_ERR008MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-
-		*pLen = Offset;
-	}
-	else {
-		/*
-		 * The logical MAC address may not be changed only
-		 * the physical ones
-		 */
-		if (Id == OID_SKGE_PHYS_FAC_ADDR) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_READ_ONLY);
-		}
-
-		/*
-		 * Only the current address may be changed
-		 */
-		if (Id != OID_SKGE_PHYS_CUR_ADDR) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009,
-				SK_PNMI_ERR009MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/* Check length */
-		if (*pLen < (Limit - LogPortIndex) * 6) {
-
-			*pLen = (Limit - LogPortIndex) * 6;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		if (*pLen > (Limit - LogPortIndex) * 6) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-
-		/*
-		 * Check Action
-		 */
-		if (Action == SK_PNMI_PRESET) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_OK);
-		}
-
-		/*
-		 * Set OID_SKGE_MAC_CUR_ADDR
-		 */
-		for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
-
-			/*
-			 * A set to virtual port and set of broadcast
-			 * address will be ignored
-			 */
-			if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
-				"\xff\xff\xff\xff\xff\xff", 6) == 0) {
-
-				continue;
-			}
-
-			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC,
-				LogPortIndex);
-
-			Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
-				(SK_MAC_ADDR *)(pBuf + Offset),
-				(LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS :
-				SK_ADDR_PHYSICAL_ADDRESS));
-			if (Ret != SK_ADDR_OVERRIDE_SUCCESS) {
-
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-		*pLen = Offset;
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX
- *
- * Description:
- *	Retrieves the statistic values of the CSUM module. The CSUM data
- *	structure must be available in the SK_AC even if the CSUM module
- *	is not included, because PNMI reads the statistic data from the
- *	CSUM part of SK_AC directly.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int CsumStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	Index;
-	unsigned int	Limit;
-	unsigned int	Offset = 0;
-	SK_U64		StatVal;
-
-
-	/*
-	 * Calculate instance if wished
-	 */
-	if (Instance != (SK_U32)(-1)) {
-
-		if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		Index = (unsigned int)Instance - 1;
-		Limit = Index + 1;
-	}
-	else {
-		Index = 0;
-		Limit = SKCS_NUM_PROTOCOLS;
-	}
-
-	/*
-	 * Check action
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
-
-		*pLen = (Limit - Index) * sizeof(SK_U64);
-		return (SK_PNMI_ERR_TOO_SHORT);
-	}
-
-	/*
-	 * Get value
-	 */
-	for (; Index < Limit; Index ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_CHKSM_RX_OK_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts;
-			break;
-
-		case OID_SKGE_CHKSM_RX_UNABLE_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts;
-			break;
-
-		case OID_SKGE_CHKSM_RX_ERR_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts;
-			break;
-
-		case OID_SKGE_CHKSM_TX_OK_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts;
-			break;
-
-		case OID_SKGE_CHKSM_TX_UNABLE_CTS:
-			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts;
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010,
-				SK_PNMI_ERR010MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
-		Offset += sizeof(SK_U64);
-	}
-
-	/*
-	 * Store used buffer space
-	 */
-	*pLen = Offset;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX
- *
- * Description:
- *	Retrieves the statistic values of the I2C module, which handles
- *	the temperature and voltage sensors.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int SensorStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	i;
-	unsigned int	Index;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	unsigned int	Len;
-	SK_U32		Val32;
-	SK_U64		Val64;
-
-
-	/*
-	 * Calculate instance if wished
-	 */
-	if ((Instance != (SK_U32)(-1))) {
-
-		if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-
-		Index = (unsigned int)Instance -1;
-		Limit = (unsigned int)Instance;
-	}
-	else {
-		Index = 0;
-		Limit = (unsigned int) pAC->I2c.MaxSens;
-	}
-
-	/*
-	 * Check action
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/* Check length */
-	switch (Id) {
-
-	case OID_SKGE_SENSOR_VALUE:
-	case OID_SKGE_SENSOR_WAR_THRES_LOW:
-	case OID_SKGE_SENSOR_WAR_THRES_UPP:
-	case OID_SKGE_SENSOR_ERR_THRES_LOW:
-	case OID_SKGE_SENSOR_ERR_THRES_UPP:
-		if (*pLen < (Limit - Index) * sizeof(SK_U32)) {
-
-			*pLen = (Limit - Index) * sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_SENSOR_DESCR:
-		for (Offset = 0, i = Index; i < Limit; i ++) {
-
-			Len = (unsigned int)
-				SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1;
-			if (Len >= SK_PNMI_STRINGLEN2) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011,
-					SK_PNMI_ERR011MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			Offset += Len;
-		}
-		if (*pLen < Offset) {
-
-			*pLen = Offset;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_SENSOR_INDEX:
-	case OID_SKGE_SENSOR_TYPE:
-	case OID_SKGE_SENSOR_STATUS:
-		if (*pLen < Limit - Index) {
-
-			*pLen = Limit - Index;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_SENSOR_WAR_CTS:
-	case OID_SKGE_SENSOR_WAR_TIME:
-	case OID_SKGE_SENSOR_ERR_CTS:
-	case OID_SKGE_SENSOR_ERR_TIME:
-		if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
-
-			*pLen = (Limit - Index) * sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012,
-			SK_PNMI_ERR012MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-
-	}
-
-	/*
-	 * Get value
-	 */
-	for (Offset = 0; Index < Limit; Index ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_SENSOR_INDEX:
-			*(pBuf + Offset) = (char)Index;
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SENSOR_DESCR:
-			Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
-			SK_MEMCPY(pBuf + Offset + 1,
-				pAC->I2c.SenTable[Index].SenDesc, Len);
-			*(pBuf + Offset) = (char)Len;
-			Offset += Len + 1;
-			break;
-
-		case OID_SKGE_SENSOR_TYPE:
-			*(pBuf + Offset) =
-				(char)pAC->I2c.SenTable[Index].SenType;
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SENSOR_VALUE:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_THRES_LOW:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
-				SenThreWarnLow;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_THRES_UPP:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
-				SenThreWarnHigh;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_THRES_LOW:
-			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
-				SenThreErrLow;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_THRES_UPP:
-			Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_SENSOR_STATUS:
-			*(pBuf + Offset) =
-				(char)pAC->I2c.SenTable[Index].SenErrFlag;
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_CTS:
-			Val64 = pAC->I2c.SenTable[Index].SenWarnCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_CTS:
-			Val64 = pAC->I2c.SenTable[Index].SenErrCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_SENSOR_WAR_TIME:
-			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
-				SenBegWarnTS);
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_SENSOR_ERR_TIME:
-			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
-				SenBegErrTS);
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-				("SensorStat: Unknown OID should be handled before"));
-
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-
-	/*
-	 * Store used buffer space
-	 */
-	*pLen = Offset;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Vpd - OID handler function of OID_SKGE_VPD_XXX
- *
- * Description:
- *	Get/preset/set of VPD data. As instance the name of a VPD key
- *	can be passed. The Instance parameter is a SK_U32 and can be
- *	used as a string buffer for the VPD key, because their maximum
- *	length is 4 byte.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Vpd(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_VPD_STATUS	*pVpdStatus;
-	unsigned int	BufLen;
-	char		Buf[256];
-	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
-	char		KeyStr[SK_PNMI_VPD_KEY_SIZE];
-	unsigned int	KeyNo;
-	unsigned int	Offset;
-	unsigned int	Index;
-	unsigned int	FirstIndex;
-	unsigned int	LastIndex;
-	unsigned int	Len;
-	int		Ret;
-	SK_U32		Val32;
-
-	/*
-	 * Get array of all currently stored VPD keys
-	 */
-	Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo);
-	if (Ret != SK_PNMI_ERR_OK) {
-		*pLen = 0;
-		return (Ret);
-	}
-
-	/*
-	 * If instance is not -1, try to find the requested VPD key for
-	 * the multiple instance variables. The other OIDs as for example
-	 * OID VPD_ACTION are single instance variables and must be
-	 * handled separatly.
-	 */
-	FirstIndex = 0;
-	LastIndex = KeyNo;
-
-	if ((Instance != (SK_U32)(-1))) {
-
-		if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE ||
-			Id == OID_SKGE_VPD_ACCESS) {
-
-			SK_STRNCPY(KeyStr, (char *)&Instance, 4);
-			KeyStr[4] = 0;
-
-			for (Index = 0; Index < KeyNo; Index ++) {
-
-				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
-					FirstIndex = Index;
-					LastIndex = Index+1;
-					break;
-				}
-			}
-			if (Index == KeyNo) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_UNKNOWN_INST);
-			}
-		}
-		else if (Instance != 1) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-	}
-
-	/*
-	 * Get value, if a query should be performed
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		switch (Id) {
-
-		case OID_SKGE_VPD_FREE_BYTES:
-			/* Check length of buffer */
-			if (*pLen < sizeof(SK_U32)) {
-
-				*pLen = sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/* Get number of free bytes */
-			pVpdStatus = VpdStat(pAC, IoC);
-			if (pVpdStatus == NULL) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017,
-					SK_PNMI_ERR017MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018,
-					SK_PNMI_ERR018MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			
-			Val32 = (SK_U32)pVpdStatus->vpd_free_rw;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_VPD_ENTRIES_LIST:
-			/* Check length */
-			for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
-
-				Len += SK_STRLEN(KeyArr[Index]) + 1;
-			}
-			if (*pLen < Len) {
-
-				*pLen = Len;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			/* Get value */
-			*(pBuf) = (char)Len - 1;
-			for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
-
-				Len = SK_STRLEN(KeyArr[Index]);
-				SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len);
-
-				Offset += Len;
-
-				if (Index < KeyNo - 1) {
-
-					*(pBuf + Offset) = ' ';
-					Offset ++;
-				}
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_ENTRIES_NUMBER:
-			/* Check length */
-			if (*pLen < sizeof(SK_U32)) {
-
-				*pLen = sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			Val32 = (SK_U32)KeyNo;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_VPD_KEY:
-			/* Check buffer length, if it is large enough */
-			for (Len = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				Len += SK_STRLEN(KeyArr[Index]) + 1;
-			}
-			if (*pLen < Len) {
-
-				*pLen = Len;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			/*
-			 * Get the key to an intermediate buffer, because
-			 * we have to prepend a length byte.
-			 */
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				Len = SK_STRLEN(KeyArr[Index]);
-
-				*(pBuf + Offset) = (char)Len;
-				SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index],
-					Len);
-				Offset += Len + 1;
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_VALUE:
-			/* Check the buffer length if it is large enough */
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				BufLen = 256;
-				if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
-					(int *)&BufLen) > 0 ||
-					BufLen >= SK_PNMI_VPD_DATALEN) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR021,
-						SK_PNMI_ERR021MSG);
-
-					return (SK_PNMI_ERR_GENERAL);
-				}
-				Offset += BufLen + 1;
-			}
-			if (*pLen < Offset) {
-
-				*pLen = Offset;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			/*
-			 * Get the value to an intermediate buffer, because
-			 * we have to prepend a length byte.
-			 */
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				BufLen = 256;
-				if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
-					(int *)&BufLen) > 0 ||
-					BufLen >= SK_PNMI_VPD_DATALEN) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR022,
-						SK_PNMI_ERR022MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-
-				*(pBuf + Offset) = (char)BufLen;
-				SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen);
-				Offset += BufLen + 1;
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_ACCESS:
-			if (*pLen < LastIndex - FirstIndex) {
-
-				*pLen = LastIndex - FirstIndex;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-
-			for (Offset = 0, Index = FirstIndex;
-				Index < LastIndex; Index ++) {
-
-				if (VpdMayWrite(KeyArr[Index])) {
-
-					*(pBuf + Offset) = SK_PNMI_VPD_RW;
-				}
-				else {
-					*(pBuf + Offset) = SK_PNMI_VPD_RO;
-				}
-				Offset ++;
-			}
-			*pLen = Offset;
-			break;
-
-		case OID_SKGE_VPD_ACTION:
-			Offset = LastIndex - FirstIndex;
-			if (*pLen < Offset) {
-
-				*pLen = Offset;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			SK_MEMSET(pBuf, 0, Offset);
-			*pLen = Offset;
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023,
-				SK_PNMI_ERR023MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-	else {
-		/* The only OID which can be set is VPD_ACTION */
-		if (Id != OID_SKGE_VPD_ACTION) {
-
-			if (Id == OID_SKGE_VPD_FREE_BYTES ||
-				Id == OID_SKGE_VPD_ENTRIES_LIST ||
-				Id == OID_SKGE_VPD_ENTRIES_NUMBER ||
-				Id == OID_SKGE_VPD_KEY ||
-				Id == OID_SKGE_VPD_VALUE ||
-				Id == OID_SKGE_VPD_ACCESS) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_READ_ONLY);
-			}
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024,
-				SK_PNMI_ERR024MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/*
-		 * From this point we handle VPD_ACTION. Check the buffer
-		 * length. It should at least have the size of one byte.
-		 */
-		if (*pLen < 1) {
-
-			*pLen = 1;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		/*
-		 * The first byte contains the VPD action type we should
-		 * perform.
-		 */
-		switch (*pBuf) {
-
-		case SK_PNMI_VPD_IGNORE:
-			/* Nothing to do */
-			break;
-
-		case SK_PNMI_VPD_CREATE:
-			/*
-			 * We have to create a new VPD entry or we modify
-			 * an existing one. Check first the buffer length.
-			 */
-			if (*pLen < 4) {
-
-				*pLen = 4;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			KeyStr[0] = pBuf[1];
-			KeyStr[1] = pBuf[2];
-			KeyStr[2] = 0;
-
-			/*
-			 * Is the entry writable or does it belong to the
-			 * read-only area?
-			 */
-			if (!VpdMayWrite(KeyStr)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			Offset = (int)pBuf[3] & 0xFF;
-
-			SK_MEMCPY(Buf, pBuf + 4, Offset);
-			Buf[Offset] = 0;
-
-			/* A preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			/* Write the new entry or modify an existing one */
-			Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
-			if (Ret == SK_PNMI_VPD_NOWRITE ) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			else if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025,
-					SK_PNMI_ERR025MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-
-			/*
-			 * Perform an update of the VPD data. This is
-			 * not mandantory, but just to be sure.
-			 */
-			Ret = VpdUpdate(pAC, IoC);
-			if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026,
-					SK_PNMI_ERR026MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		case SK_PNMI_VPD_DELETE:
-			/* Check if the buffer size is plausible */
-			if (*pLen < 3) {
-
-				*pLen = 3;
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			if (*pLen > 3) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			KeyStr[0] = pBuf[1];
-			KeyStr[1] = pBuf[2];
-			KeyStr[2] = 0;
-
-			/* Find the passed key in the array */
-			for (Index = 0; Index < KeyNo; Index ++) {
-
-				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
-
-					break;
-				}
-			}
-			/*
-			 * If we cannot find the key it is wrong, so we
-			 * return an appropriate error value.
-			 */
-			if (Index == KeyNo) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			/* Ok, you wanted it and you will get it */
-			Ret = VpdDelete(pAC, IoC, KeyStr);
-			if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027,
-					SK_PNMI_ERR027MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-
-			/*
-			 * Perform an update of the VPD data. This is
-			 * not mandantory, but just to be sure.
-			 */
-			Ret = VpdUpdate(pAC, IoC);
-			if (Ret != SK_PNMI_VPD_OK) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028,
-					SK_PNMI_ERR028MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		default:
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * General - OID handler function of various single instance OIDs
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int General(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	Index;
-	unsigned int	Len;
-	unsigned int	Offset;
-	unsigned int	Val;
-	SK_U8		Val8;
-	SK_U16		Val16;
-	SK_U32		Val32;
-	SK_U64		Val64;
-	SK_U64		Val64RxHwErrs = 0;
-	SK_U64		Val64TxHwErrs = 0;
-	SK_BOOL		Is64BitReq = SK_FALSE;
-	char		Buf[256];
-	int			MacType;
-
-	/*
-	 * Check instance. We only handle single instance variables.
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Check action. We only allow get requests.
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-	
-	MacType = pAC->GIni.GIMacType;
-	
-	/*
-	 * Check length for the various supported OIDs
-	 */
-	switch (Id) {
-
-	case OID_GEN_XMIT_ERROR:
-	case OID_GEN_RCV_ERROR:
-	case OID_GEN_RCV_NO_BUFFER:
-#ifndef SK_NDIS_64BIT_CTR
-		if (*pLen < sizeof(SK_U32)) {
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-#else /* SK_NDIS_64BIT_CTR */
-
-		/*
-		 * for compatibility, at least 32bit are required for oid
-		 */
-		if (*pLen < sizeof(SK_U32)) {
-			/*
-			* but indicate handling for 64bit values,
-			* if insufficient space is provided
-			*/
-			*pLen = sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-
-		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
-#endif /* SK_NDIS_64BIT_CTR */
-		break;
-
-	case OID_SKGE_PORT_NUMBER:
-	case OID_SKGE_DEVICE_TYPE:
-	case OID_SKGE_RESULT:
-	case OID_SKGE_RLMT_MONITOR_NUMBER:
-	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-	case OID_SKGE_TRAP_NUMBER:
-	case OID_SKGE_MDB_VERSION:
-	case OID_SKGE_BOARDLEVEL:
-	case OID_SKGE_CHIPID:
-	case OID_SKGE_RAMSIZE:
-		if (*pLen < sizeof(SK_U32)) {
-
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_CHIPSET:
-		if (*pLen < sizeof(SK_U16)) {
-
-			*pLen = sizeof(SK_U16);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_BUS_TYPE:
-	case OID_SKGE_BUS_SPEED:
-	case OID_SKGE_BUS_WIDTH:
-	case OID_SKGE_SENSOR_NUMBER:
-	case OID_SKGE_CHKSM_NUMBER:
-	case OID_SKGE_VAUXAVAIL:
-		if (*pLen < sizeof(SK_U8)) {
-
-			*pLen = sizeof(SK_U8);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_TX_SW_QUEUE_LEN:
-	case OID_SKGE_TX_SW_QUEUE_MAX:
-	case OID_SKGE_TX_RETRY:
-	case OID_SKGE_RX_INTR_CTS:
-	case OID_SKGE_TX_INTR_CTS:
-	case OID_SKGE_RX_NO_BUF_CTS:
-	case OID_SKGE_TX_NO_BUF_CTS:
-	case OID_SKGE_TX_USED_DESCR_NO:
-	case OID_SKGE_RX_DELIVERED_CTS:
-	case OID_SKGE_RX_OCTETS_DELIV_CTS:
-	case OID_SKGE_RX_HW_ERROR_CTS:
-	case OID_SKGE_TX_HW_ERROR_CTS:
-	case OID_SKGE_IN_ERRORS_CTS:
-	case OID_SKGE_OUT_ERROR_CTS:
-	case OID_SKGE_ERR_RECOVERY_CTS:
-	case OID_SKGE_SYSUPTIME:
-		if (*pLen < sizeof(SK_U64)) {
-
-			*pLen = sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		/* Checked later */
-		break;
-	}
-
-	/* Update statistic */
-	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
-		Id == OID_SKGE_TX_HW_ERROR_CTS ||
-		Id == OID_SKGE_IN_ERRORS_CTS ||
-		Id == OID_SKGE_OUT_ERROR_CTS ||
-		Id == OID_GEN_XMIT_ERROR ||
-		Id == OID_GEN_RCV_ERROR) {
-
-		/* Force the XMAC to update its statistic counters and
-		 * Increment semaphore to indicate that an update was
-		 * already done.
-		 */
-		Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
-		if (Ret != SK_PNMI_ERR_OK) {
-
-			*pLen = 0;
-			return (Ret);
-		}
-		pAC->Pnmi.MacUpdatedFlag ++;
-
-		/*
-		 * Some OIDs consist of multiple hardware counters. Those
-		 * values which are contained in all of them will be added
-		 * now.
-		 */
-		switch (Id) {
-
-		case OID_SKGE_RX_HW_ERROR_CTS:
-		case OID_SKGE_IN_ERRORS_CTS:
-		case OID_GEN_RCV_ERROR:
-			Val64RxHwErrs =
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
-	        break;
-
-		case OID_SKGE_TX_HW_ERROR_CTS:
-		case OID_SKGE_OUT_ERROR_CTS:
-		case OID_GEN_XMIT_ERROR:
-			Val64TxHwErrs =
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
-				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
-			break;
-		}
-	}
-
-	/*
-	 * Retrieve value
-	 */
-	switch (Id) {
-
-	case OID_SKGE_SUPPORTED_LIST:
-		Len = ID_TABLE_SIZE * sizeof(SK_U32);
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		for (Offset = 0, Index = 0; Offset < Len;
-			Offset += sizeof(SK_U32), Index ++) {
-
-			Val32 = (SK_U32)IdTable[Index].Id;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-		}
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_BOARDLEVEL:
-		Val32 = (SK_U32)pAC->GIni.GILevel;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_PORT_NUMBER:
-		Val32 = (SK_U32)pAC->GIni.GIMacsFound;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_DEVICE_TYPE:
-		Val32 = (SK_U32)pAC->Pnmi.DeviceType;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_DRIVER_DESCR:
-		if (pAC->Pnmi.pDriverDescription == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007,
-				SK_PNMI_ERR007MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029,
-				SK_PNMI_ERR029MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_DRIVER_VERSION:
-		if (pAC->Pnmi.pDriverVersion == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
-				SK_PNMI_ERR030MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
-				SK_PNMI_ERR031MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_DRIVER_RELDATE:
-		if (pAC->Pnmi.pDriverReleaseDate == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
-				SK_PNMI_ERR053MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
-				SK_PNMI_ERR054MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_DRIVER_FILENAME:
-		if (pAC->Pnmi.pDriverFileName == NULL) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
-				SK_PNMI_ERR055MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
-				SK_PNMI_ERR056MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_HW_DESCR:
-		/*
-		 * The hardware description is located in the VPD. This
-		 * query may move to the initialisation routine. But
-		 * the VPD data is cached and therefore a call here
-		 * will not make much difference.
-		 */
-		Len = 256;
-		if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032,
-				SK_PNMI_ERR032MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-		Len ++;
-		if (Len > SK_PNMI_STRINGLEN1) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033,
-				SK_PNMI_ERR033MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		*pBuf = (char)(Len - 1);
-		SK_MEMCPY(pBuf + 1, Buf, Len - 1);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_HW_VERSION:
-		/* Oh, I love to do some string manipulation */
-		if (*pLen < 5) {
-
-			*pLen = 5;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
-		pBuf[0] = 4;
-		pBuf[1] = 'v';
-		pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F));
-		pBuf[3] = '.';
-		pBuf[4] = (char)(0x30 | (Val8 & 0x0F));
-		*pLen = 5;
-		break;
-
-	case OID_SKGE_CHIPSET:
-		Val16 = pAC->Pnmi.Chipset;
-		SK_PNMI_STORE_U16(pBuf, Val16);
-		*pLen = sizeof(SK_U16);
-		break;
-
-	case OID_SKGE_CHIPID:
-		Val32 = pAC->GIni.GIChipId;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_RAMSIZE:
-		Val32 = pAC->GIni.GIRamSize;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_VAUXAVAIL:
-		*pBuf = (char) pAC->GIni.GIVauxAvail;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_BUS_TYPE:
-		*pBuf = (char) SK_PNMI_BUS_PCI;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_BUS_SPEED:
-		*pBuf = pAC->Pnmi.PciBusSpeed;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_BUS_WIDTH:
-		*pBuf = pAC->Pnmi.PciBusWidth;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_RESULT:
-		Val32 = pAC->Pnmi.TestResult;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_SENSOR_NUMBER:
-		*pBuf = (char)pAC->I2c.MaxSens;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_CHKSM_NUMBER:
-		*pBuf = SKCS_NUM_PROTOCOLS;
-		*pLen = sizeof(char);
-		break;
-
-	case OID_SKGE_TRAP_NUMBER:
-		GetTrapQueueLen(pAC, &Len, &Val);
-		Val32 = (SK_U32)Val;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_TRAP:
-		GetTrapQueueLen(pAC, &Len, &Val);
-		if (*pLen < Len) {
-
-			*pLen = Len;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		CopyTrapQueue(pAC, pBuf);
-		*pLen = Len;
-		break;
-
-	case OID_SKGE_RLMT_MONITOR_NUMBER:
-/* XXX Not yet implemented by RLMT therefore we return zero elements */
-		Val32 = 0;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_SKGE_TX_SW_QUEUE_LEN:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen +
-					pAC->Pnmi.BufPort[1].TxSwQueueLen;
-			}			
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxSwQueueLen +
-					pAC->Pnmi.Port[1].TxSwQueueLen;
-			}			
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-
-	case OID_SKGE_TX_SW_QUEUE_MAX:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax +
-					pAC->Pnmi.BufPort[1].TxSwQueueMax;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
-					pAC->Pnmi.Port[1].TxSwQueueMax;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_RETRY:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxRetryCts +
-					pAC->Pnmi.BufPort[1].TxRetryCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxRetryCts +
-					pAC->Pnmi.Port[1].TxRetryCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_INTR_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxIntrCts +
-					pAC->Pnmi.BufPort[1].RxIntrCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxIntrCts +
-					pAC->Pnmi.Port[1].RxIntrCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_INTR_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxIntrCts +
-					pAC->Pnmi.BufPort[1].TxIntrCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxIntrCts +
-					pAC->Pnmi.Port[1].TxIntrCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_NO_BUF_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts +
-					pAC->Pnmi.BufPort[1].RxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
-					pAC->Pnmi.Port[1].RxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_NO_BUF_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts +
-					pAC->Pnmi.BufPort[1].TxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
-					pAC->Pnmi.Port[1].TxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_USED_DESCR_NO:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo +
-					pAC->Pnmi.BufPort[1].TxUsedDescrNo;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
-					pAC->Pnmi.Port[1].TxUsedDescrNo;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_DELIVERED_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts +
-					pAC->Pnmi.BufPort[1].RxDeliveredCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
-					pAC->Pnmi.Port[1].RxDeliveredCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_OCTETS_DELIV_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts +
-					pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
-					pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_RX_HW_ERROR_CTS:
-		SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_TX_HW_ERROR_CTS:
-		SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_IN_ERRORS_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64RxHwErrs +
-					pAC->Pnmi.BufPort[0].RxNoBufCts +
-					pAC->Pnmi.BufPort[1].RxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64RxHwErrs +
-					pAC->Pnmi.Port[0].RxNoBufCts +
-					pAC->Pnmi.Port[1].RxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_OUT_ERROR_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64TxHwErrs +
-					pAC->Pnmi.BufPort[0].TxNoBufCts +
-					pAC->Pnmi.BufPort[1].TxNoBufCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = Val64TxHwErrs +
-					pAC->Pnmi.Port[0].TxNoBufCts +
-					pAC->Pnmi.Port[1].TxNoBufCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_ERR_RECOVERY_CTS:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts +
-					pAC->Pnmi.BufPort[1].ErrRecoveryCts;
-			}
-		}
-		else {
-			/* Dual net mode */
-			if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-				Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
-			}
-			/* Single net mode */
-			else {
-				Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
-					pAC->Pnmi.Port[1].ErrRecoveryCts;
-			}
-		}
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_SYSUPTIME:
-		Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-		Val64 -= pAC->Pnmi.StartUpTime;
-		SK_PNMI_STORE_U64(pBuf, Val64);
-		*pLen = sizeof(SK_U64);
-		break;
-
-	case OID_SKGE_MDB_VERSION:
-		Val32 = SK_PNMI_MDB_VERSION;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	case OID_GEN_RCV_ERROR:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-		}
-		else {
-			Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-		}
-
-		/*
-		 * by default 32bit values are evaluated
-		 */
-		if (!Is64BitReq) {
-			Val32 = (SK_U32)Val64;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-
-	case OID_GEN_XMIT_ERROR:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
-		}
-		else {
-			Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
-		}
-
-		/*
-		 * by default 32bit values are evaluated
-		 */
-		if (!Is64BitReq) {
-			Val32 = (SK_U32)Val64;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-
-	case OID_GEN_RCV_NO_BUFFER:
-		/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-		if (MacType == SK_MAC_XMAC) {
-			Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
-		}
-		else {
-			Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
-		}
-
-		/*
-		 * by default 32bit values are evaluated
-		 */
-		if (!Is64BitReq) {
-			Val32 = (SK_U32)Val64;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-		}
-		else {
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-		}
-		break;
-
-	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-		Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
-		SK_PNMI_STORE_U32(pBuf, Val32);
-		*pLen = sizeof(SK_U32);
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034,
-			SK_PNMI_ERR034MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
-		Id == OID_SKGE_TX_HW_ERROR_CTS ||
-		Id == OID_SKGE_IN_ERRORS_CTS ||
-		Id == OID_SKGE_OUT_ERROR_CTS ||
-		Id == OID_GEN_XMIT_ERROR ||
-		Id == OID_GEN_RCV_ERROR) {
-
-		pAC->Pnmi.MacUpdatedFlag --;
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance.
- *
- * Description:
- *	Get/Presets/Sets the RLMT OIDs.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Rlmt(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	int		Ret;
-	unsigned int	PhysPortIndex;
-	unsigned int	PhysPortMax;
-	SK_EVPARA	EventParam;
-	SK_U32		Val32;
-	SK_U64		Val64;
-
-
-	/*
-	 * Check instance. Only single instance OIDs are allowed here.
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Perform the requested action.
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/*
-		 * Check if the buffer length is large enough.
-		 */
-
-		switch (Id) {
-
-		case OID_SKGE_RLMT_MODE:
-		case OID_SKGE_RLMT_PORT_ACTIVE:
-		case OID_SKGE_RLMT_PORT_PREFERRED:
-			if (*pLen < sizeof(SK_U8)) {
-
-				*pLen = sizeof(SK_U8);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		case OID_SKGE_RLMT_PORT_NUMBER:
-			if (*pLen < sizeof(SK_U32)) {
-
-				*pLen = sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_CTS:
-		case OID_SKGE_RLMT_CHANGE_TIME:
-		case OID_SKGE_RLMT_CHANGE_ESTIM:
-		case OID_SKGE_RLMT_CHANGE_THRES:
-			if (*pLen < sizeof(SK_U64)) {
-
-				*pLen = sizeof(SK_U64);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035,
-				SK_PNMI_ERR035MSG);
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/*
-		 * Update RLMT statistic and increment semaphores to indicate
-		 * that an update was already done. Maybe RLMT will hold its
-		 * statistic always up to date some time. Then we can
-		 * remove this type of call.
-		 */
-		if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-			*pLen = 0;
-			return (Ret);
-		}
-		pAC->Pnmi.RlmtUpdatedFlag ++;
-
-		/*
-		 * Retrieve Value
-		*/
-		switch (Id) {
-
-		case OID_SKGE_RLMT_MODE:
-			*pBuf = (char)pAC->Rlmt.Net[0].RlmtMode;
-			*pLen = sizeof(char);
-			break;
-
-		case OID_SKGE_RLMT_PORT_NUMBER:
-			Val32 = (SK_U32)pAC->GIni.GIMacsFound;
-			SK_PNMI_STORE_U32(pBuf, Val32);
-			*pLen = sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_RLMT_PORT_ACTIVE:
-			*pBuf = 0;
-			/*
-			 * If multiple ports may become active this OID
-			 * doesn't make sense any more. A new variable in
-			 * the port structure should be created. However,
-			 * for this variable the first active port is
-			 * returned.
-			 */
-			PhysPortMax = pAC->GIni.GIMacsFound;
-
-			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
-				PhysPortIndex ++) {
-
-				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-					*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex);
-					break;
-				}
-			}
-			*pLen = sizeof(char);
-			break;
-
-		case OID_SKGE_RLMT_PORT_PREFERRED:
-			*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference);
-			*pLen = sizeof(char);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_CTS:
-			Val64 = pAC->Pnmi.RlmtChangeCts;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_TIME:
-			Val64 = pAC->Pnmi.RlmtChangeTime;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_ESTIM:
-			Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_THRES:
-			Val64 = pAC->Pnmi.RlmtChangeThreshold;
-			SK_PNMI_STORE_U64(pBuf, Val64);
-			*pLen = sizeof(SK_U64);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-				("Rlmt: Unknown OID should be handled before"));
-
-			pAC->Pnmi.RlmtUpdatedFlag --;
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		pAC->Pnmi.RlmtUpdatedFlag --;
-	}
-	else {
-		/* Perform a preset or set */
-		switch (Id) {
-
-		case OID_SKGE_RLMT_MODE:
-			/* Check if the buffer length is plausible */
-			if (*pLen < sizeof(char)) {
-
-				*pLen = sizeof(char);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/* Check if the value range is correct */
-			if (*pLen != sizeof(char) ||
-				(*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
-				*(SK_U8 *)pBuf > 15) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_OK);
-			}
-			/* Send an event to RLMT to change the mode */
-			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-			EventParam.Para32[0] |= (SK_U32)(*pBuf);
-			EventParam.Para32[1] = 0;
-			if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
-				EventParam) > 0) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037,
-					SK_PNMI_ERR037MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		case OID_SKGE_RLMT_PORT_PREFERRED:
-			/* Check if the buffer length is plausible */
-			if (*pLen < sizeof(char)) {
-
-				*pLen = sizeof(char);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/* Check if the value range is correct */
-			if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
-				(SK_U8)pAC->GIni.GIMacsFound) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_OK);
-			}
-
-			/*
-			 * Send an event to RLMT change the preferred port.
-			 * A param of -1 means automatic mode. RLMT will
-			 * make the decision which is the preferred port.
-			 */
-			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-			EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
-			EventParam.Para32[1] = NetIndex;
-			if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
-				EventParam) > 0) {
-
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038,
-					SK_PNMI_ERR038MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-			break;
-
-		case OID_SKGE_RLMT_CHANGE_THRES:
-			/* Check if the buffer length is plausible */
-			if (*pLen < sizeof(SK_U64)) {
-
-				*pLen = sizeof(SK_U64);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			/*
-			 * There are not many restrictions to the
-			 * value range.
-			 */
-			if (*pLen != sizeof(SK_U64)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-			/* A preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_OK);
-			}
-			/*
-			 * Store the new threshold, which will be taken
-			 * on the next timer event.
-			 */
-			SK_PNMI_READ_U64(pBuf, Val64);
-			pAC->Pnmi.RlmtChangeThreshold = Val64;
-			break;
-
-		default:
-			/* The other OIDs are not be able for set */
-			*pLen = 0;
-			return (SK_PNMI_ERR_READ_ONLY);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance.
- *
- * Description:
- *	Performs get requests on multiple instance variables.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int RlmtStat(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	PhysPortMax;
-	unsigned int	PhysPortIndex;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	int		Ret;
-	SK_U32		Val32;
-	SK_U64		Val64;
-
-	/*
-	 * Calculate the port indexes from the instance.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-
-	if ((Instance != (SK_U32)(-1))) {
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > PhysPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-
-		/* Single net mode */
-		PhysPortIndex = Instance - 1;
-
-		/* Dual net mode */
-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-			PhysPortIndex = NetIndex;
-		}
-
-		/* Both net modes */
-		Limit = PhysPortIndex + 1;
-	}
-	else {
-		/* Single net mode */
-		PhysPortIndex = 0;
-		Limit = PhysPortMax;
-
-		/* Dual net mode */
-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-			PhysPortIndex = NetIndex;
-			Limit = PhysPortIndex + 1;
-		}
-	}
-
-	/*
-	 * Currently only get requests are allowed.
-	 */
-	if (Action != SK_PNMI_GET) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/*
-	 * Check if the buffer length is large enough.
-	 */
-	switch (Id) {
-
-	case OID_SKGE_RLMT_PORT_INDEX:
-	case OID_SKGE_RLMT_STATUS:
-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
-
-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	case OID_SKGE_RLMT_TX_HELLO_CTS:
-	case OID_SKGE_RLMT_RX_HELLO_CTS:
-	case OID_SKGE_RLMT_TX_SP_REQ_CTS:
-	case OID_SKGE_RLMT_RX_SP_CTS:
-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) {
-
-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U64);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039,
-			SK_PNMI_ERR039MSG);
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-
-	}
-
-	/*
-	 * Update statistic and increment semaphores to indicate that
-	 * an update was already done.
-	 */
-	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
-		*pLen = 0;
-		return (Ret);
-	}
-	pAC->Pnmi.RlmtUpdatedFlag ++;
-
-	/*
-	 * Get value
-	 */
-	Offset = 0;
-	for (; PhysPortIndex < Limit; PhysPortIndex ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_RLMT_PORT_INDEX:
-			Val32 = PhysPortIndex;
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_RLMT_STATUS:
-			if (pAC->Rlmt.Port[PhysPortIndex].PortState ==
-				SK_RLMT_PS_INIT ||
-				pAC->Rlmt.Port[PhysPortIndex].PortState ==
-				SK_RLMT_PS_DOWN) {
-
-				Val32 = SK_PNMI_RLMT_STATUS_ERROR;
-			}
-			else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-				Val32 = SK_PNMI_RLMT_STATUS_ACTIVE;
-			}
-			else {
-				Val32 = SK_PNMI_RLMT_STATUS_STANDBY;
-			}
-			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-			Offset += sizeof(SK_U32);
-			break;
-
-		case OID_SKGE_RLMT_TX_HELLO_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_RX_HELLO_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_TX_SP_REQ_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		case OID_SKGE_RLMT_RX_SP_CTS:
-			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts;
-			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
-			Offset += sizeof(SK_U64);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-				("RlmtStat: Unknown OID should be errored before"));
-
-			pAC->Pnmi.RlmtUpdatedFlag --;
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-	*pLen = Offset;
-
-	pAC->Pnmi.RlmtUpdatedFlag --;
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacPrivateConf - OID handler function of OIDs concerning the configuration
- *
- * Description:
- *	Get/Presets/Sets the OIDs concerning the configuration.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int MacPrivateConf(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	PhysPortMax;
-	unsigned int	PhysPortIndex;
-	unsigned int	LogPortMax;
-	unsigned int	LogPortIndex;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	char		Val8;
-	char 		*pBufPtr;
-	int			Ret;
-	SK_EVPARA	EventParam;
-	SK_U32		Val32;
-
-	/*
-	 * Calculate instance if wished. MAC index 0 is the virtual MAC.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
-		LogPortMax--;
-	}
-
-	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
-		/* Check instance range */
-		if ((Instance < 1) || (Instance > LogPortMax)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
-		Limit = LogPortIndex + 1;
-	}
-
-	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
-		LogPortIndex = 0;
-		Limit = LogPortMax;
-	}
-
-	/*
-	 * Perform action
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/* Check length */
-		switch (Id) {
-
-		case OID_SKGE_PMD:
-		case OID_SKGE_CONNECTOR:
-		case OID_SKGE_LINK_CAP:
-		case OID_SKGE_LINK_MODE:
-		case OID_SKGE_LINK_MODE_STATUS:
-		case OID_SKGE_LINK_STATUS:
-		case OID_SKGE_FLOWCTRL_CAP:
-		case OID_SKGE_FLOWCTRL_MODE:
-		case OID_SKGE_FLOWCTRL_STATUS:
-		case OID_SKGE_PHY_OPERATION_CAP:
-		case OID_SKGE_PHY_OPERATION_MODE:
-		case OID_SKGE_PHY_OPERATION_STATUS:
-		case OID_SKGE_SPEED_CAP:
-		case OID_SKGE_SPEED_MODE:
-		case OID_SKGE_SPEED_STATUS:
-			if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
-
-				*pLen = (Limit - LogPortIndex) * sizeof(SK_U8);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-        case OID_SKGE_MTU:
-        case OID_SKGE_PHY_TYPE:
-			if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
-
-				*pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041,
-				SK_PNMI_ERR041MSG);
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		/*
-		 * Update statistic and increment semaphore to indicate
-		 * that an update was already done.
-		 */
-		if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
-			*pLen = 0;
-			return (Ret);
-		}
-		pAC->Pnmi.SirqUpdatedFlag ++;
-
-		/*
-		 * Get value
-		 */
-		Offset = 0;
-		for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-			pBufPtr = pBuf + Offset;
-			
-			switch (Id) {
-
-			case OID_SKGE_PMD:
-				*pBufPtr = pAC->Pnmi.PMD;
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_CONNECTOR:
-				*pBufPtr = pAC->Pnmi.Connector;
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_TYPE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						continue;
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-						Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
-						SK_PNMI_STORE_U32(pBufPtr, Val32);
-					}
-				}
-				else { /* DualNetMode */
-					
-					Val32 = pAC->GIni.GP[NetIndex].PhyType;
-					SK_PNMI_STORE_U32(pBufPtr, Val32);
-				}
-				Offset += sizeof(SK_U32);
-				break;
-
-			case OID_SKGE_LINK_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap;
-					}
-				}
-				else { /* DualNetMode */
-					
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_LINK_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_LINK_MODE_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr =
-							CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
-					}
-				}
-				else { /* DualNetMode */
-					
-					*pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex);
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_LINK_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex);
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_FLOWCTRL_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_FLOWCTRL_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_FLOWCTRL_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_OPERATION_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_OPERATION_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSMode;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_PHY_OPERATION_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus;
-					}
-				}
-				else {
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_SPEED_CAP:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical ports */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap;
-					}
-				}
-				else { /* DualNetMode */
-				
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_SPEED_MODE:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed;
-				}
-				Offset += sizeof(char);
-				break;
-
-			case OID_SKGE_SPEED_STATUS:
-				if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
-					if (LogPortIndex == 0) {
-						/* Get value for virtual port */
-						VirtualConf(pAC, IoC, Id, pBufPtr);
-					}
-					else {
-						/* Get value for physical port */
-						PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
-							pAC, LogPortIndex);
-	
-						*pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed;
-					}
-				}
-				else { /* DualNetMode */
-
-					*pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed;
-				}
-				Offset += sizeof(char);
-				break;
-			
-			case OID_SKGE_MTU:
-				Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex);
-				SK_PNMI_STORE_U32(pBufPtr, Val32);
-				Offset += sizeof(SK_U32);
-				break;
-
-			default:
-				SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-					("MacPrivateConf: Unknown OID should be handled before"));
-
-				pAC->Pnmi.SirqUpdatedFlag --;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-		*pLen = Offset;
-		pAC->Pnmi.SirqUpdatedFlag --;
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/*
-	 * From here SET or PRESET action. Check if the passed
-	 * buffer length is plausible.
-	 */
-	switch (Id) {
-
-	case OID_SKGE_LINK_MODE:
-	case OID_SKGE_FLOWCTRL_MODE:
-	case OID_SKGE_PHY_OPERATION_MODE:
-	case OID_SKGE_SPEED_MODE:
-		if (*pLen < Limit - LogPortIndex) {
-
-			*pLen = Limit - LogPortIndex;
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		if (*pLen != Limit - LogPortIndex) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-		break;
-
-	case OID_SKGE_MTU:
-		if (*pLen < sizeof(SK_U32)) {
-
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		if (*pLen != sizeof(SK_U32)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-		break;
-
-    default:
-		*pLen = 0;
-		return (SK_PNMI_ERR_READ_ONLY);
-	}
-
-	/*
-	 * Perform preset or set
-	 */
-	Offset = 0;
-	for (; LogPortIndex < Limit; LogPortIndex ++) {
-
-		switch (Id) {
-
-		case OID_SKGE_LINK_MODE:
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < SK_LMODE_HALF ||
-				(LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) ||
-				(LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with the new link mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].
-						ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_LMODE,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR043,
-							SK_PNMI_ERR043MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new link mode to
-				 * the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
-					EventParam) > 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR043,
-						SK_PNMI_ERR043MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_FLOWCTRL_MODE:
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < SK_FLOW_MODE_NONE ||
-				(LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) ||
-				(LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with the new flow control mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].
-						ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_FLOWMODE,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR044,
-							SK_PNMI_ERR044MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new flow control
-				 * mode to the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC,
-					SK_HWEV_SET_FLOWMODE, EventParam)
-					> 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR044,
-						SK_PNMI_ERR044MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_PHY_OPERATION_MODE :
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-				/* mode of this port remains unchanged */
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < SK_MS_MODE_AUTO ||
-				(LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) ||
-				(LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with new master/slave (role) mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].
-						ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_ROLE,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR042,
-							SK_PNMI_ERR042MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new master/slave
-				 * (role) mode to the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC,
-					SK_HWEV_SET_ROLE, EventParam) > 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR042,
-						SK_PNMI_ERR042MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_SPEED_MODE:
-			/* Check the value range */
-			Val8 = *(pBuf + Offset);
-			if (Val8 == 0) {
-
-				Offset += sizeof(char);
-				break;
-			}
-			if (Val8 < (SK_LSPEED_AUTO) ||
-				(LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) ||
-				(LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) {
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (LogPortIndex == 0) {
-
-				/*
-				 * The virtual port consists of all currently
-				 * active ports. Find them and send an event
-				 * with the new flow control mode to SIRQ.
-				 */
-				for (PhysPortIndex = 0;
-					PhysPortIndex < PhysPortMax;
-					PhysPortIndex ++) {
-
-					if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-						continue;
-					}
-
-					EventParam.Para32[0] = PhysPortIndex;
-					EventParam.Para32[1] = (SK_U32)Val8;
-					if (SkGeSirqEvent(pAC, IoC,
-						SK_HWEV_SET_SPEED,
-						EventParam) > 0) {
-
-						SK_ERR_LOG(pAC, SK_ERRCL_SW,
-							SK_PNMI_ERR045,
-							SK_PNMI_ERR045MSG);
-
-						*pLen = 0;
-						return (SK_PNMI_ERR_GENERAL);
-					}
-				}
-			}
-			else {
-				/*
-				 * Send an event with the new flow control
-				 * mode to the SIRQ module.
-				 */
-				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
-					pAC, LogPortIndex);
-				EventParam.Para32[1] = (SK_U32)Val8;
-				if (SkGeSirqEvent(pAC, IoC,
-					SK_HWEV_SET_SPEED,
-					EventParam) > 0) {
-
-					SK_ERR_LOG(pAC, SK_ERRCL_SW,
-						SK_PNMI_ERR045,
-						SK_PNMI_ERR045MSG);
-
-					*pLen = 0;
-					return (SK_PNMI_ERR_GENERAL);
-				}
-			}
-			Offset += sizeof(char);
-			break;
-
-		case OID_SKGE_MTU :
-			/* Check the value range */
-			Val32 = *(SK_U32*)(pBuf + Offset);
-			if (Val32 == 0) {
-				/* mtu of this port remains unchanged */
-				Offset += sizeof(SK_U32);
-				break;
-			}
-			if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
-				*pLen = 0;
-				return (SK_PNMI_ERR_BAD_VALUE);
-			}
-
-			/* The preset ends here */
-			if (Action == SK_PNMI_PRESET) {
-				return (SK_PNMI_ERR_OK);
-			}
-
-			if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
-				return (SK_PNMI_ERR_GENERAL);
-			}
-
-			Offset += sizeof(SK_U32);
-			break;
-		
-		default:
-            SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
-                ("MacPrivateConf: Unknown OID should be handled before set"));
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Monitor - OID handler function for RLMT_MONITOR_XXX
- *
- * Description:
- *	Because RLMT currently does not support the monitoring of
- *	remote adapter cards, we return always an empty table.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
- *	                         value range.
- *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-PNMI_STATIC int Monitor(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	unsigned int	Index;
-	unsigned int	Limit;
-	unsigned int	Offset;
-	unsigned int	Entries;
-
-	
-	/*
-	 * Calculate instance if wished.
-	 */
-	/* XXX Not yet implemented. Return always an empty table. */
-	Entries = 0;
-
-	if ((Instance != (SK_U32)(-1))) {
-
-		if ((Instance < 1) || (Instance > Entries)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-
-		Index = (unsigned int)Instance - 1;
-		Limit = (unsigned int)Instance;
-	}
-	else {
-		Index = 0;
-		Limit = Entries;
-	}
-
-	/*
-	 * Get/Set value
-	*/
-	if (Action == SK_PNMI_GET) {
-
-		for (Offset=0; Index < Limit; Index ++) {
-
-			switch (Id) {
-
-			case OID_SKGE_RLMT_MONITOR_INDEX:
-			case OID_SKGE_RLMT_MONITOR_ADDR:
-			case OID_SKGE_RLMT_MONITOR_ERRS:
-			case OID_SKGE_RLMT_MONITOR_TIMESTAMP:
-			case OID_SKGE_RLMT_MONITOR_ADMIN:
-				break;
-
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046,
-					SK_PNMI_ERR046MSG);
-
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		}
-		*pLen = Offset;
-	}
-	else {
-		/* Only MONITOR_ADMIN can be set */
-		if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_READ_ONLY);
-		}
-
-		/* Check if the length is plausible */
-		if (*pLen < (Limit - Index)) {
-
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		/* Okay, we have a wide value range */
-		if (*pLen != (Limit - Index)) {
-
-			*pLen = 0;
-			return (SK_PNMI_ERR_BAD_VALUE);
-		}
-/*
-		for (Offset=0; Index < Limit; Index ++) {
-		}
-*/
-/*
- * XXX Not yet implemented. Return always BAD_VALUE, because the table
- * is empty.
- */
-		*pLen = 0;
-		return (SK_PNMI_ERR_BAD_VALUE);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * VirtualConf - Calculates the values of configuration OIDs for virtual port
- *
- * Description:
- *	We handle here the get of the configuration group OIDs, which are
- *	a little bit complicated. The virtual port consists of all currently
- *	active physical ports. If multiple ports are active and configured
- *	differently we get in some trouble to return a single value. So we
- *	get the value of the first active port and compare it with that of
- *	the other active ports. If they are not the same, we return a value
- *	that indicates that the state is indeterminated.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void VirtualConf(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf)		/* Buffer used for the management data transfer */
-{
-	unsigned int	PhysPortMax;
-	unsigned int	PhysPortIndex;
-	SK_U8		Val8;
-	SK_U32		Val32;
-	SK_BOOL		PortActiveFlag;
-	SK_GEPORT	*pPrt;
-
-	*pBuf = 0;
-	PortActiveFlag = SK_FALSE;
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	
-	for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
-		PhysPortIndex ++) {
-
-		pPrt = &pAC->GIni.GP[PhysPortIndex];
-
-		/* Check if the physical port is active */
-		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-			continue;
-		}
-
-		PortActiveFlag = SK_TRUE;
-
-		switch (Id) {
-
-		case OID_SKGE_PHY_TYPE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-				Val32 = pPrt->PhyType;
-				SK_PNMI_STORE_U32(pBuf, Val32);
-				continue;
-			}
-
-		case OID_SKGE_LINK_CAP:
-
-			/*
-			 * Different capabilities should not happen, but
-			 * in the case of the cases OR them all together.
-			 * From a curious point of view the virtual port
-			 * is capable of all found capabilities.
-			 */
-			*pBuf |= pPrt->PLinkCap;
-			break;
-
-		case OID_SKGE_LINK_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PLinkModeConf;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different link
-			 * mode than the first one we return a value that
-			 * indicates that the link mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PLinkModeConf) {
-
-				*pBuf = SK_LMODE_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_LINK_MODE_STATUS:
-			/* Get the link mode of the physical port */
-			Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
-
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = Val8;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different link
-			 * mode status than the first one we return a value
-			 * that indicates that the link mode status is
-			 * indeterminated.
-			 */
-			if (*pBuf != Val8) {
-
-				*pBuf = SK_LMODE_STAT_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_LINK_STATUS:
-			/* Get the link status of the physical port */
-			Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
-
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = Val8;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different link
-			 * status than the first one, we return a value
-			 * that indicates that the link status is
-			 * indeterminated.
-			 */
-			if (*pBuf != Val8) {
-
-				*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_FLOWCTRL_CAP:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PFlowCtrlCap;
-				continue;
-			}
-
-			/*
-			 * From a curious point of view the virtual port
-			 * is capable of all found capabilities.
-			 */
-			*pBuf |= pPrt->PFlowCtrlCap;
-			break;
-
-		case OID_SKGE_FLOWCTRL_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PFlowCtrlMode;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control mode than the first one, we return a value
-			 * that indicates that the mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PFlowCtrlMode) {
-
-				*pBuf = SK_FLOW_MODE_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_FLOWCTRL_STATUS:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PFlowCtrlStatus;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control status than the first one, we return a
-			 * value that indicates that the status is
-			 * indeterminated.
-			 */
-			if (*pBuf != pPrt->PFlowCtrlStatus) {
-
-				*pBuf = SK_FLOW_STAT_INDETERMINATED;
-			}
-			break;
-		
-		case OID_SKGE_PHY_OPERATION_CAP:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PMSCap;
-				continue;
-			}
-
-			/*
-			 * From a curious point of view the virtual port
-			 * is capable of all found capabilities.
-			 */
-			*pBuf |= pPrt->PMSCap;
-			break;
-
-		case OID_SKGE_PHY_OPERATION_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PMSMode;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different master/
-			 * slave mode than the first one, we return a value
-			 * that indicates that the mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PMSMode) {
-
-				*pBuf = SK_MS_MODE_INDETERMINATED;
-			}
-			break;
-
-		case OID_SKGE_PHY_OPERATION_STATUS:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PMSStatus;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different master/
-			 * slave status than the first one, we return a
-			 * value that indicates that the status is
-			 * indeterminated.
-			 */
-			if (*pBuf != pPrt->PMSStatus) {
-
-				*pBuf = SK_MS_STAT_INDETERMINATED;
-			}
-			break;
-		
-		case OID_SKGE_SPEED_MODE:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PLinkSpeed;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control mode than the first one, we return a value
-			 * that indicates that the mode is indeterminated.
-			 */
-			if (*pBuf != pPrt->PLinkSpeed) {
-
-				*pBuf = SK_LSPEED_INDETERMINATED;
-			}
-			break;
-		
-		case OID_SKGE_SPEED_STATUS:
-			/* Check if it is the first active port */
-			if (*pBuf == 0) {
-
-				*pBuf = pPrt->PLinkSpeedUsed;
-				continue;
-			}
-
-			/*
-			 * If we find an active port with a different flow
-			 * control status than the first one, we return a
-			 * value that indicates that the status is
-			 * indeterminated.
-			 */
-			if (*pBuf != pPrt->PLinkSpeedUsed) {
-
-				*pBuf = SK_LSPEED_STAT_INDETERMINATED;
-			}
-			break;
-		}
-	}
-
-	/*
-	 * If no port is active return an indeterminated answer
-	 */
-	if (!PortActiveFlag) {
-
-		switch (Id) {
-
-		case OID_SKGE_LINK_CAP:
-			*pBuf = SK_LMODE_CAP_INDETERMINATED;
-			break;
-
-		case OID_SKGE_LINK_MODE:
-			*pBuf = SK_LMODE_INDETERMINATED;
-			break;
-
-		case OID_SKGE_LINK_MODE_STATUS:
-			*pBuf = SK_LMODE_STAT_INDETERMINATED;
-			break;
-
-		case OID_SKGE_LINK_STATUS:
-			*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
-			break;
-
-		case OID_SKGE_FLOWCTRL_CAP:
-		case OID_SKGE_FLOWCTRL_MODE:
-			*pBuf = SK_FLOW_MODE_INDETERMINATED;
-			break;
-
-		case OID_SKGE_FLOWCTRL_STATUS:
-			*pBuf = SK_FLOW_STAT_INDETERMINATED;
-			break;
-			
-		case OID_SKGE_PHY_OPERATION_CAP:
-			*pBuf = SK_MS_CAP_INDETERMINATED;
-			break;
-
-		case OID_SKGE_PHY_OPERATION_MODE:
-			*pBuf = SK_MS_MODE_INDETERMINATED;
-			break;
-
-		case OID_SKGE_PHY_OPERATION_STATUS:
-			*pBuf = SK_MS_STAT_INDETERMINATED;
-			break;
-		case OID_SKGE_SPEED_CAP:
-			*pBuf = SK_LSPEED_CAP_INDETERMINATED;
-			break;
-
-		case OID_SKGE_SPEED_MODE:
-			*pBuf = SK_LSPEED_INDETERMINATED;
-			break;
-
-		case OID_SKGE_SPEED_STATUS:
-			*pBuf = SK_LSPEED_STAT_INDETERMINATED;
-			break;
-		}
-	}
-}
-
-/*****************************************************************************
- *
- * CalculateLinkStatus - Determins the link status of a physical port
- *
- * Description:
- *	Determins the link status the following way:
- *	  LSTAT_PHY_DOWN:  Link is down
- *	  LSTAT_AUTONEG:   Auto-negotiation failed
- *	  LSTAT_LOG_DOWN:  Link is up but RLMT did not yet put the port
- *	                   logically up.
- *	  LSTAT_LOG_UP:    RLMT marked the port as up
- *
- * Returns:
- *	Link status of physical port
- */
-PNMI_STATIC SK_U8 CalculateLinkStatus(
-SK_AC *pAC,			/* Pointer to adapter context */
-SK_IOC IoC,			/* IO context handle */
-unsigned int PhysPortIndex)	/* Physical port index */
-{
-	SK_U8	Result;
-
-	if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) {
-
-		Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN;
-	}
-	else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) {
-
-		Result = SK_PNMI_RLMT_LSTAT_AUTONEG;
-				}
-	else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) {
-
-		Result = SK_PNMI_RLMT_LSTAT_LOG_UP;
-	}
-	else {
-		Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN;
-	}
-
-	return (Result);
-}
-
-/*****************************************************************************
- *
- * CalculateLinkModeStatus - Determins the link mode status of a phys. port
- *
- * Description:
- *	The COMMON module only tells us if the mode is half or full duplex.
- *	But in the decade of auto sensing it is useful for the user to
- *	know if the mode was negotiated or forced. Therefore we have a
- *	look to the mode, which was last used by the negotiation process.
- *
- * Returns:
- *	The link mode status
- */
-PNMI_STATIC SK_U8 CalculateLinkModeStatus(
-SK_AC *pAC,			/* Pointer to adapter context */
-SK_IOC IoC,			/* IO context handle */
-unsigned int PhysPortIndex)	/* Physical port index */
-{
-	SK_U8	Result;
-
-	/* Get the current mode, which can be full or half duplex */
-	Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
-
-	/* Check if no valid mode could be found (link is down) */
-	if (Result < SK_LMODE_STAT_HALF) {
-
-		Result = SK_LMODE_STAT_UNKNOWN;
-	}
-	else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
-
-		/*
-		 * Auto-negotiation was used to bring up the link. Change
-		 * the already found duplex status that it indicates
-		 * auto-negotiation was involved.
-		 */
-		if (Result == SK_LMODE_STAT_HALF) {
-
-			Result = SK_LMODE_STAT_AUTOHALF;
-		}
-		else if (Result == SK_LMODE_STAT_FULL) {
-
-			Result = SK_LMODE_STAT_AUTOFULL;
-		}
-	}
-
-	return (Result);
-}
-
-/*****************************************************************************
- *
- * GetVpdKeyArr - Obtain an array of VPD keys
- *
- * Description:
- *	Read the VPD keys and build an array of VPD keys, which are
- *	easy to access.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int GetVpdKeyArr(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-char *pKeyArr,		/* Ptr KeyArray */
-unsigned int KeyArrLen,	/* Length of array in bytes */
-unsigned int *pKeyNo)	/* Number of keys */
-{
-	unsigned int		BufKeysLen = SK_PNMI_VPD_BUFSIZE;
-	char			BufKeys[SK_PNMI_VPD_BUFSIZE];
-	unsigned int		StartOffset;
-	unsigned int		Offset;
-	int			Index;
-	int			Ret;
-
-
-	SK_MEMSET(pKeyArr, 0, KeyArrLen);
-
-	/*
-	 * Get VPD key list
-	 */
-	Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen,
-		(int *)pKeyNo);
-	if (Ret > 0) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014,
-			SK_PNMI_ERR014MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-	/* If no keys are available return now */
-	if (*pKeyNo == 0 || BufKeysLen == 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-	/*
-	 * If the key list is too long for us trunc it and give a
-	 * errorlog notification. This case should not happen because
-	 * the maximum number of keys is limited due to RAM limitations
-	 */
-	if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015,
-			SK_PNMI_ERR015MSG);
-
-		*pKeyNo = SK_PNMI_VPD_ENTRIES;
-	}
-
-	/*
-	 * Now build an array of fixed string length size and copy
-	 * the keys together.
-	 */
-	for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen;
-		Offset ++) {
-
-		if (BufKeys[Offset] != 0) {
-
-			continue;
-		}
-
-		if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016,
-				SK_PNMI_ERR016MSG);
-			return (SK_PNMI_ERR_GENERAL);
-		}
-
-		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
-			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
-
-		Index ++;
-		StartOffset = Offset + 1;
-	}
-
-	/* Last key not zero terminated? Get it anyway */
-	if (StartOffset < Offset) {
-
-		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
-			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SirqUpdate - Let the SIRQ update its internal values
- *
- * Description:
- *	Just to be sure that the SIRQ module holds its internal data
- *	structures up to date, we send an update event before we make
- *	any access.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int SirqUpdate(
-SK_AC *pAC,	/* Pointer to adapter context */
-SK_IOC IoC)	/* IO context handle */
-{
-	SK_EVPARA	EventParam;
-
-
-	/* Was the module already updated during the current PNMI call? */
-	if (pAC->Pnmi.SirqUpdatedFlag > 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Send an synchronuous update event to the module */
-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-	if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047,
-			SK_PNMI_ERR047MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * RlmtUpdate - Let the RLMT update its internal values
- *
- * Description:
- *	Just to be sure that the RLMT module holds its internal data
- *	structures up to date, we send an update event before we make
- *	any access.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int RlmtUpdate(
-SK_AC *pAC,	/* Pointer to adapter context */
-SK_IOC IoC,	/* IO context handle */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
-{
-	SK_EVPARA	EventParam;
-
-
-	/* Was the module already updated during the current PNMI call? */
-	if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Send an synchronuous update event to the module */
-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-	EventParam.Para32[0] = NetIndex;
-	EventParam.Para32[1] = (SK_U32)-1;
-	if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048,
-			SK_PNMI_ERR048MSG);
-
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacUpdate - Force the XMAC to output the current statistic
- *
- * Description:
- *	The XMAC holds its statistic internally. To obtain the current
- *	values we must send a command so that the statistic data will
- *	be written to a predefined memory area on the adapter.
- *
- * Returns:
- *	SK_PNMI_ERR_OK	     Task successfully performed.
- *	SK_PNMI_ERR_GENERAL  Something went wrong.
- */
-PNMI_STATIC int MacUpdate(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-unsigned int FirstMac,	/* Index of the first Mac to be updated */
-unsigned int LastMac)	/* Index of the last Mac to be updated */
-{
-	unsigned int	MacIndex;
-
-	/*
-	 * Were the statistics already updated during the
-	 * current PNMI call?
-	 */
-	if (pAC->Pnmi.MacUpdatedFlag > 0) {
-
-		return (SK_PNMI_ERR_OK);
-	}
-
-	/* Send an update command to all MACs specified */
-	for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
-
-		/*
-		 * 2002-09-13 pweber:	Freeze the current SW counters.
-		 *                      (That should be done as close as
-		 *                      possible to the update of the
-		 *                      HW counters)
-		 */
-		if (pAC->GIni.GIMacType == SK_MAC_XMAC) {
-			pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex];
-		}
-			
-		/* 2002-09-13 pweber:  Update the HW counter  */
-		if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) {
-
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	}
-
-	return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * GetStatVal - Retrieve an XMAC statistic counter
- *
- * Description:
- *	Retrieves the statistic counter of a virtual or physical port. The
- *	virtual port is identified by the index 0. It consists of all
- *	currently active ports. To obtain the counter value for this port
- *	we must add the statistic counter of all active ports. To grant
- *	continuous counter values for the virtual port even when port
- *	switches occur we must additionally add a delta value, which was
- *	calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event.
- *
- * Returns:
- *	Requested statistic value
- */
-PNMI_STATIC SK_U64 GetStatVal(
-SK_AC *pAC,					/* Pointer to adapter context */
-SK_IOC IoC,					/* IO context handle */
-unsigned int LogPortIndex,	/* Index of the logical Port to be processed */
-unsigned int StatIndex,		/* Index to statistic value */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
-{
-	unsigned int	PhysPortIndex;
-	unsigned int	PhysPortMax;
-	SK_U64			Val = 0;
-
-
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {	/* Dual net mode */
-
-		PhysPortIndex = NetIndex;
-		
-		Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
-	}
-	else {	/* Single Net mode */
-
-		if (LogPortIndex == 0) {
-
-			PhysPortMax = pAC->GIni.GIMacsFound;
-
-			/* Add counter of all active ports */
-			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
-				PhysPortIndex ++) {
-
-				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
-					Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
-				}
-			}
-
-			/* Correct value because of port switches */
-			Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
-		}
-		else {
-			/* Get counter value of physical port */
-			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-			
-			Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
-		}
-	}
-	return (Val);
-}
-
-/*****************************************************************************
- *
- * GetPhysStatVal - Get counter value for physical port
- *
- * Description:
- *	Builds a 64bit counter value. Except for the octet counters
- *	the lower 32bit are counted in hardware and the upper 32bit
- *	in software by monitoring counter overflow interrupts in the
- *	event handler. To grant continous counter values during XMAC
- *	resets (caused by a workaround) we must add a delta value.
- *	The delta was calculated in the event handler when a
- *	SK_PNMI_EVT_XMAC_RESET was received.
- *
- * Returns:
- *	Counter value
- */
-PNMI_STATIC SK_U64 GetPhysStatVal(
-SK_AC *pAC,					/* Pointer to adapter context */
-SK_IOC IoC,					/* IO context handle */
-unsigned int PhysPortIndex,	/* Index of the logical Port to be processed */
-unsigned int StatIndex)		/* Index to statistic value */
-{
-	SK_U64	Val = 0;
-	SK_U32	LowVal = 0;
-	SK_U32	HighVal = 0;
-	SK_U16	Word;
-	int		MacType;
-	unsigned int HelpIndex;
-	SK_GEPORT	*pPrt;
-	
-	SK_PNMI_PORT	*pPnmiPrt;
-	SK_GEMACFUNC	*pFnMac;
-	
-	pPrt = &pAC->GIni.GP[PhysPortIndex];
-	
-	MacType = pAC->GIni.GIMacType;
-	
-	/* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
-	if (MacType == SK_MAC_XMAC) {
-		pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex];
-	}
-	else {
-		pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex];
-	}
-	
-	pFnMac   = &pAC->GIni.GIFunc;
-
-	switch (StatIndex) {
-	case SK_PNMI_HTX:
-		if (MacType == SK_MAC_GMAC) {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg,
-							&LowVal);
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-		}
-		else {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-		}
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-	
-	case SK_PNMI_HRX:
-		if (MacType == SK_MAC_GMAC) {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg,
-							&LowVal);
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-							StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg,
-							&HighVal);
-			LowVal += HighVal;
-		}
-		else {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-		}
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_OCTET:
-	case SK_PNMI_HRX_OCTET:
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &HighVal);
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex + 1][MacType].Reg,
-									  &LowVal);
-		break;
-
-	case SK_PNMI_HTX_BURST:
-	case SK_PNMI_HTX_EXCESS_DEF:
-	case SK_PNMI_HTX_CARRIER:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_MACC:
-		/* GMAC only supports PAUSE MAC control frames */
-		if (MacType == SK_MAC_GMAC) {
-			HelpIndex = SK_PNMI_HTX_PMACC;
-		}
-		else {
-			HelpIndex = StatIndex;
-		}
-		
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-								StatAddr[HelpIndex][MacType].Reg,
-								&LowVal);
-
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_COL:
-	case SK_PNMI_HRX_UNDERSIZE:
-		/* Not supported by XMAC */
-		if (MacType == SK_MAC_XMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HTX_DEFFERAL:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			return (Val);
-		}
-		
-		/*
-		 * XMAC counts frames with deferred transmission
-		 * even in full-duplex mode.
-		 *
-		 * In full-duplex mode the counter remains constant!
-		 */
-		if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) ||
-			(pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) {
-
-			LowVal = 0;
-			HighVal = 0;
-		}
-		else {
-			/* Otherwise get contents of hardware register */
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		}
-		break;
-
-	case SK_PNMI_HRX_BADOCTET:
-		/* Not supported by XMAC */
-		if (MacType == SK_MAC_XMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &HighVal);
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex + 1][MacType].Reg,
-                                      &LowVal);
-		break;
-
-	case SK_PNMI_HTX_OCTETLOW:
-	case SK_PNMI_HRX_OCTETLOW:
-	case SK_PNMI_HRX_BADOCTETLOW:
-		return (Val);
-
-	case SK_PNMI_HRX_LONGFRAMES:
-		/* For XMAC the SW counter is managed by PNMI */
-		if (MacType == SK_MAC_XMAC) {
-			return (pPnmiPrt->StatRxLongFrameCts);
-		}
-		
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-		
-	case SK_PNMI_HRX_TOO_LONG:
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-								StatAddr[StatIndex][MacType].Reg,
-								&LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		
-		Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-
-		if (MacType == SK_MAC_GMAC) {
-			/* For GMAC the SW counter is additionally managed by PNMI */
-			Val += pPnmiPrt->StatRxFrameTooLongCts;
-		}
-		else {
-			/*
-			 * Frames longer than IEEE 802.3 frame max size are counted
-			 * by XMAC in frame_too_long counter even reception of long
-			 * frames was enabled and the frame was correct.
-			 * So correct the value by subtracting RxLongFrame counter.
-			 */
-			Val -= pPnmiPrt->StatRxLongFrameCts;
-		}
-
-		LowVal = (SK_U32)Val;
-		HighVal = (SK_U32)(Val >> 32);
-		break;
-		
-	case SK_PNMI_HRX_SHORTS:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			/* GM_RXE_FRAG?? */
-			return (Val);
-		}
-		
-		/*
-		 * XMAC counts short frame errors even if link down (#10620)
-		 *
-		 * If link-down the counter remains constant
-		 */
-		if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) {
-
-			/* Otherwise get incremental difference */
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-
-			Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-			Val -= pPnmiPrt->RxShortZeroMark;
-
-			LowVal = (SK_U32)Val;
-			HighVal = (SK_U32)(Val >> 32);
-		}
-		break;
-
-	case SK_PNMI_HRX_MACC:
-	case SK_PNMI_HRX_MACC_UNKWN:
-	case SK_PNMI_HRX_BURST:
-	case SK_PNMI_HRX_MISSED:
-	case SK_PNMI_HRX_FRAMING:
-	case SK_PNMI_HRX_CARRIER:
-	case SK_PNMI_HRX_IRLENGTH:
-	case SK_PNMI_HRX_SYMBOL:
-	case SK_PNMI_HRX_CEXT:
-		/* Not supported by GMAC */
-		if (MacType == SK_MAC_GMAC) {
-			return (Val);
-		}
-
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	case SK_PNMI_HRX_PMACC_ERR:
-		/* For GMAC the SW counter is managed by PNMI */
-		if (MacType == SK_MAC_GMAC) {
-			return (pPnmiPrt->StatRxPMaccErr);
-		}
-		
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-
-	/* SW counter managed by PNMI */
-	case SK_PNMI_HTX_SYNC:
-		LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
-		HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
-		break;
-
-	/* SW counter managed by PNMI */
-	case SK_PNMI_HTX_SYNC_OCTET:
-		LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
-		HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
-		break;
-
-	case SK_PNMI_HRX_FCS:
-		/*
-		 * Broadcom filters FCS errors and counts it in
-		 * Receive Error Counter register
-		 */
-		if (pPrt->PhyType == SK_PHY_BCOM) {
-			/* do not read while not initialized (PHY_READ hangs!)*/
-			if (pPrt->PState != SK_PRT_RESET) {
-				SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
-				
-				LowVal = Word;
-			}
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		}
-		else {
-			(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-										  StatAddr[StatIndex][MacType].Reg,
-										  &LowVal);
-			HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		}
-		break;
-
-	default:
-		(void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
-									  StatAddr[StatIndex][MacType].Reg,
-									  &LowVal);
-		HighVal = pPnmiPrt->CounterHigh[StatIndex];
-		break;
-	}
-
-	Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-
-	/* Correct value because of possible XMAC reset. XMAC Errata #2 */
-	Val += pPnmiPrt->CounterOffset[StatIndex];
-
-	return (Val);
-}
-
-/*****************************************************************************
- *
- * ResetCounter - Set all counters and timestamps to zero
- *
- * Description:
- *	Notifies other common modules which store statistic data to
- *	reset their counters and finally reset our own counters.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void ResetCounter(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-SK_U32 NetIndex)
-{
-	unsigned int	PhysPortIndex;
-	SK_EVPARA	EventParam;
-
-
-	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-
-	/* Notify sensor module */
-	SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
-
-	/* Notify RLMT module */
-	EventParam.Para32[0] = NetIndex;
-	EventParam.Para32[1] = (SK_U32)-1;
-	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
-	EventParam.Para32[1] = 0;
-
-	/* Notify SIRQ module */
-	SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
-
-	/* Notify CSUM module */
-#ifdef SK_USE_CSUM
-	EventParam.Para32[0] = NetIndex;
-	EventParam.Para32[1] = (SK_U32)-1;
-	SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
-		EventParam);
-#endif /* SK_USE_CSUM */
-	
-	/* Clear XMAC statistic */
-	for (PhysPortIndex = 0; PhysPortIndex <
-		(unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
-
-		(void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex);
-
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
-			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-			CounterOffset, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].CounterOffset));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
-			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-			StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatSyncOctetsCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-			StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatRxLongFrameCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-				  StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatRxFrameTooLongCts));
-		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
-				  StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[
-			PhysPortIndex].StatRxPMaccErr));
-	}
-
-	/*
-	 * Clear local statistics
-	 */
-	SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
-		  sizeof(pAC->Pnmi.VirtualCounterOffset));
-	pAC->Pnmi.RlmtChangeCts = 0;
-	pAC->Pnmi.RlmtChangeTime = 0;
-	SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
-		sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
-	pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
-	pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
-	pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
-	pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
-	pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
-	pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
-	pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
-	pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
-	pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
-	pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
-	pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
-	pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
-}
-
-/*****************************************************************************
- *
- * GetTrapEntry - Get an entry in the trap buffer
- *
- * Description:
- *	The trap buffer stores various events. A user application somehow
- *	gets notified that an event occured and retrieves the trap buffer
- *	contens (or simply polls the buffer). The buffer is organized as
- *	a ring which stores the newest traps at the beginning. The oldest
- *	traps are overwritten by the newest ones. Each trap entry has a
- *	unique number, so that applications may detect new trap entries.
- *
- * Returns:
- *	A pointer to the trap entry
- */
-PNMI_STATIC char* GetTrapEntry(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_U32 TrapId,		/* SNMP ID of the trap */
-unsigned int Size)	/* Space needed for trap entry */
-{
-	unsigned int		BufPad = pAC->Pnmi.TrapBufPad;
-	unsigned int		BufFree = pAC->Pnmi.TrapBufFree;
-	unsigned int		Beg = pAC->Pnmi.TrapQueueBeg;
-	unsigned int		End = pAC->Pnmi.TrapQueueEnd;
-	char			*pBuf = &pAC->Pnmi.TrapBuf[0];
-	int			Wrap;
-	unsigned int		NeededSpace;
-	unsigned int		EntrySize;
-	SK_U32			Val32;
-	SK_U64			Val64;
-
-
-	/* Last byte of entry will get a copy of the entry length */
-	Size ++;
-
-	/*
-	 * Calculate needed buffer space */
-	if (Beg >= Size) {
-
-		NeededSpace = Size;
-		Wrap = SK_FALSE;
-	}
-	else {
-		NeededSpace = Beg + Size;
-		Wrap = SK_TRUE;
-	}
-
-	/*
-	 * Check if enough buffer space is provided. Otherwise
-	 * free some entries. Leave one byte space between begin
-	 * and end of buffer to make it possible to detect whether
-	 * the buffer is full or empty
-	 */
-	while (BufFree < NeededSpace + 1) {
-
-		if (End == 0) {
-
-			End = SK_PNMI_TRAP_QUEUE_LEN;
-		}
-
-		EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
-		BufFree += EntrySize;
-		End -= EntrySize;
-#ifdef DEBUG
-		SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
-#endif /* DEBUG */
-		if (End == BufPad) {
-#ifdef DEBUG
-			SK_MEMSET(pBuf, (char)(-1), End);
-#endif /* DEBUG */
-			BufFree += End;
-			End = 0;
-			BufPad = 0;
-		}
-	}
-
-	/*
-	 * Insert new entry as first entry. Newest entries are
-	 * stored at the beginning of the queue.
-	 */
-	if (Wrap) {
-
-		BufPad = Beg;
-		Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
-	}
-	else {
-		Beg = Beg - Size;
-	}
-	BufFree -= NeededSpace;
-
-	/* Save the current offsets */
-	pAC->Pnmi.TrapQueueBeg = Beg;
-	pAC->Pnmi.TrapQueueEnd = End;
-	pAC->Pnmi.TrapBufPad = BufPad;
-	pAC->Pnmi.TrapBufFree = BufFree;
-
-	/* Initialize the trap entry */
-	*(pBuf + Beg + Size - 1) = (char)Size;
-	*(pBuf + Beg) = (char)Size;
-	Val32 = (pAC->Pnmi.TrapUnique) ++;
-	SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
-	SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
-	Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-	SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
-
-	return (pBuf + Beg);
-}
-
-/*****************************************************************************
- *
- * CopyTrapQueue - Copies the trap buffer for the TRAP OID
- *
- * Description:
- *	On a query of the TRAP OID the trap buffer contents will be
- *	copied continuously to the request buffer, which must be large
- *	enough. No length check is performed.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void CopyTrapQueue(
-SK_AC *pAC,		/* Pointer to adapter context */
-char *pDstBuf)		/* Buffer to which the queued traps will be copied */
-{
-	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
-	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
-	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
-	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
-	unsigned int	Len;
-	unsigned int	DstOff = 0;
-
-
-	while (Trap != End) {
-
-		Len = (unsigned int)*(pBuf + Trap);
-
-		/*
-		 * Last byte containing a copy of the length will
-		 * not be copied.
-		 */
-		*(pDstBuf + DstOff) = (char)(Len - 1);
-		SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
-		DstOff += Len - 1;
-
-		Trap += Len;
-		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
-
-			Trap = BufPad;
-		}
-	}
-}
-
-/*****************************************************************************
- *
- * GetTrapQueueLen - Get the length of the trap buffer
- *
- * Description:
- *	Evaluates the number of currently stored traps and the needed
- *	buffer size to retrieve them.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void GetTrapQueueLen(
-SK_AC *pAC,		/* Pointer to adapter context */
-unsigned int *pLen,	/* Length in Bytes of all queued traps */
-unsigned int *pEntries)	/* Returns number of trapes stored in queue */
-{
-	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
-	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
-	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
-	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
-	unsigned int	Len;
-	unsigned int	Entries = 0;
-	unsigned int	TotalLen = 0;
-
-
-	while (Trap != End) {
-
-		Len = (unsigned int)*(pBuf + Trap);
-		TotalLen += Len - 1;
-		Entries ++;
-
-		Trap += Len;
-		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
-
-			Trap = BufPad;
-		}
-	}
-
-	*pEntries = Entries;
-	*pLen = TotalLen;
-}
-
-/*****************************************************************************
- *
- * QueueSimpleTrap - Store a simple trap to the trap buffer
- *
- * Description:
- *	A simple trap is a trap with now additional data. It consists
- *	simply of a trap code.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueSimpleTrap(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_U32 TrapId)		/* Type of sensor trap */
-{
-	GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
-}
-
-/*****************************************************************************
- *
- * QueueSensorTrap - Stores a sensor trap in the trap buffer
- *
- * Description:
- *	Gets an entry in the trap buffer and fills it with sensor related
- *	data.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueSensorTrap(
-SK_AC *pAC,			/* Pointer to adapter context */
-SK_U32 TrapId,			/* Type of sensor trap */
-unsigned int SensorIndex)	/* Index of sensor which caused the trap */
-{
-	char		*pBuf;
-	unsigned int	Offset;
-	unsigned int	DescrLen;
-	SK_U32		Val32;
-
-
-	/* Get trap buffer entry */
-	DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
-	pBuf = GetTrapEntry(pAC, TrapId,
-		SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
-	Offset = SK_PNMI_TRAP_SIMPLE_LEN;
-
-	/* Store additionally sensor trap related data */
-	Val32 = OID_SKGE_SENSOR_INDEX;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = 4;
-	Val32 = (SK_U32)SensorIndex;
-	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
-	Offset += 9;
-	
-	Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = (char)DescrLen;
-	SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
-		DescrLen);
-	Offset += DescrLen + 5;
-
-	Val32 = OID_SKGE_SENSOR_TYPE;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = 1;
-	*(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
-	Offset += 6;
-
-	Val32 = OID_SKGE_SENSOR_VALUE;
-	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
-	*(pBuf + Offset + 4) = 4;
-	Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
-	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
-}
-
-/*****************************************************************************
- *
- * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
- *
- * Description:
- *	Nothing further to explain.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueRlmtNewMacTrap(
-SK_AC *pAC,		/* Pointer to adapter context */
-unsigned int ActiveMac)	/* Index (0..n) of the currently active port */
-{
-	char	*pBuf;
-	SK_U32	Val32;
-
-
-	pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
-		SK_PNMI_TRAP_RLMT_CHANGE_LEN);
-
-	Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
-	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
-}
-
-/*****************************************************************************
- *
- * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
- *
- * Description:
- *	Nothing further to explain.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void QueueRlmtPortTrap(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_U32 TrapId,		/* Type of RLMT port trap */
-unsigned int PortIndex)	/* Index of the port, which changed its state */
-{
-	char	*pBuf;
-	SK_U32	Val32;
-
-
-	pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
-
-	Val32 = OID_SKGE_RLMT_PORT_INDEX;
-	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
-	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
-}
-
-/*****************************************************************************
- *
- * CopyMac - Copies a MAC address
- *
- * Description:
- *	Nothing further to explain.
- *
- * Returns:
- *	Nothing
- */
-PNMI_STATIC void CopyMac(
-char *pDst,		/* Pointer to destination buffer */
-SK_MAC_ADDR *pMac)	/* Pointer of Source */
-{
-	int	i;
-
-
-	for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
-
-		*(pDst + i) = pMac->a[i];
-	}
-}
-
-#ifdef SK_POWER_MGMT
-/*****************************************************************************
- *
- * PowerManagement - OID handler function of PowerManagement OIDs
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                               exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-
-PNMI_STATIC int PowerManagement(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* Get/PreSet/Set action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
-unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
-{
-	
-	SK_U32	RetCode = SK_PNMI_ERR_GENERAL;
-
-	/*
-	 * Check instance. We only handle single instance variables
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-	
-    
-    /* Check length */
-    switch (Id) {
-
-    case OID_PNP_CAPABILITIES:
-        if (*pLen < sizeof(SK_PNP_CAPABILITIES)) {
-
-            *pLen = sizeof(SK_PNP_CAPABILITIES);
-            return (SK_PNMI_ERR_TOO_SHORT);
-        }
-        break;
-
-	case OID_PNP_SET_POWER:
-    case OID_PNP_QUERY_POWER:
-    	if (*pLen < sizeof(SK_DEVICE_POWER_STATE))
-    	{
-    		*pLen = sizeof(SK_DEVICE_POWER_STATE);
-    		return (SK_PNMI_ERR_TOO_SHORT);
-    	}
-        break;
-
-    case OID_PNP_ADD_WAKE_UP_PATTERN:
-    case OID_PNP_REMOVE_WAKE_UP_PATTERN:
-		if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) {
-
-			*pLen = sizeof(SK_PM_PACKET_PATTERN);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-    case OID_PNP_ENABLE_WAKE_UP:
-        if (*pLen < sizeof(SK_U32)) {
-
-            *pLen = sizeof(SK_U32);
-            return (SK_PNMI_ERR_TOO_SHORT);
-        }
-        break;
-    }
-	
-    /*
-	 * Perform action
-	 */
-	if (Action == SK_PNMI_GET) {
-
-		/*
-		 * Get value
-		 */
-		switch (Id) {
-
-		case OID_PNP_CAPABILITIES:
-			RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen);
-			break;
-
-		case OID_PNP_QUERY_POWER:
-			/* The Windows DDK describes: An OID_PNP_QUERY_POWER requests
-			 the miniport to indicate whether it can transition its NIC
-			 to the low-power state.
-			 A miniport driver must always return NDIS_STATUS_SUCCESS
-			 to a query of OID_PNP_QUERY_POWER. */
-			*pLen = sizeof(SK_DEVICE_POWER_STATE);
-            RetCode = SK_PNMI_ERR_OK;
-			break;
-
-			/* NDIS handles these OIDs as write-only.
-			 * So in case of get action the buffer with written length = 0
-			 * is returned
-			 */
-		case OID_PNP_SET_POWER:
-		case OID_PNP_ADD_WAKE_UP_PATTERN:
-		case OID_PNP_REMOVE_WAKE_UP_PATTERN:
-			*pLen = 0;	
-            RetCode = SK_PNMI_ERR_NOT_SUPPORTED;
-			break;
-
-		case OID_PNP_ENABLE_WAKE_UP:
-			RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen);
-			break;
-
-		default:
-			RetCode = SK_PNMI_ERR_GENERAL;
-			break;
-		}
-
-		return (RetCode);
-	}
-	
-
-	/*
-	 * Perform preset or set
-	 */
-	
-	/* POWER module does not support PRESET action */
-	if (Action == SK_PNMI_PRESET) {
-		return (SK_PNMI_ERR_OK);
-	}
-
-	switch (Id) {
-	case OID_PNP_SET_POWER:
-		RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen);	
-		break;
-
-	case OID_PNP_ADD_WAKE_UP_PATTERN:
-		RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen);	
-		break;
-		
-	case OID_PNP_REMOVE_WAKE_UP_PATTERN:
-		RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen);	
-		break;
-		
-	case OID_PNP_ENABLE_WAKE_UP:
-		RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen);
-		break;
-		
-	default:
-		RetCode = SK_PNMI_ERR_READ_ONLY;
-	}
-	
-	return (RetCode);
-}
-#endif /* SK_POWER_MGMT */
-
-#ifdef SK_DIAG_SUPPORT
-/*****************************************************************************
- *
- * DiagActions - OID handler function of Diagnostic driver 
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-
-PNMI_STATIC int DiagActions(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-
-	SK_U32	DiagStatus;
-	SK_U32	RetCode = SK_PNMI_ERR_GENERAL;
-
-	/*
-	 * Check instance. We only handle single instance variables.
-	 */
-	if (Instance != (SK_U32)(-1) && Instance != 1) {
-
-		*pLen = 0;
-		return (SK_PNMI_ERR_UNKNOWN_INST);
-	}
-
-	/*
-	 * Check length.
-	 */
-	switch (Id) {
-
-	case OID_SKGE_DIAG_MODE:
-		if (*pLen < sizeof(SK_U32)) {
-
-			*pLen = sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG);
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-
-	/* Perform action. */
-
-	/* GET value. */
-	if (Action == SK_PNMI_GET) {
-
-		switch (Id) {
-
-		case OID_SKGE_DIAG_MODE:
-			DiagStatus = pAC->Pnmi.DiagAttached;
-			SK_PNMI_STORE_U32(pBuf, DiagStatus);
-			*pLen = sizeof(SK_U32);	
-			RetCode = SK_PNMI_ERR_OK;
-			break;
-
-		default:
-			*pLen = 0;	
-			RetCode = SK_PNMI_ERR_GENERAL;
-			break;
-		}
-		return (RetCode); 
-	}
-
-	/* From here SET or PRESET value. */
-	
-	/* PRESET value is not supported. */
-	if (Action == SK_PNMI_PRESET) {
-		return (SK_PNMI_ERR_OK); 
-	}
-
-	/* SET value. */
-	switch (Id) {
-		case OID_SKGE_DIAG_MODE:
-
-			/* Handle the SET. */
-			switch (*pBuf) {
-
-				/* Attach the DIAG to this adapter. */
-				case SK_DIAG_ATTACHED:
-					/* Check if we come from running */
-					if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-
-						RetCode = SkDrvLeaveDiagMode(pAC);
-
-					}
-					else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) {
-
-						RetCode = SK_PNMI_ERR_OK;
-					}	
-					
-					else {
-
-						RetCode = SK_PNMI_ERR_GENERAL;
-
-					}
-					
-					if (RetCode == SK_PNMI_ERR_OK) {
-
-						pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED;
-					}
-					break;
-
-				/* Enter the DIAG mode in the driver. */
-				case SK_DIAG_RUNNING:
-					RetCode = SK_PNMI_ERR_OK;
-					
-					/*
-					 * If DiagAttached is set, we can tell the driver
-					 * to enter the DIAG mode.
-					 */
-					if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
-						/* If DiagMode is not active, we can enter it. */
-						if (!pAC->DiagModeActive) {
-
-							RetCode = SkDrvEnterDiagMode(pAC); 
-						}
-						else {
-
-							RetCode = SK_PNMI_ERR_GENERAL;
-						}
-					}
-					else {
-
-						RetCode = SK_PNMI_ERR_GENERAL;
-					}
-					
-					if (RetCode == SK_PNMI_ERR_OK) {
-
-						pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING;
-					}
-					break;
-
-				case SK_DIAG_IDLE:
-					/* Check if we come from running */
-					if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-
-						RetCode = SkDrvLeaveDiagMode(pAC);
-
-					}
-					else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
-
-						RetCode = SK_PNMI_ERR_OK;
-					}	
-					
-					else {
-
-						RetCode = SK_PNMI_ERR_GENERAL;
-
-					}
-
-					if (RetCode == SK_PNMI_ERR_OK) {
-
-						pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
-					}
-					break;
-
-				default:
-					RetCode = SK_PNMI_ERR_BAD_VALUE;
-					break;
-			}
-			break;
-
-		default:
-			RetCode = SK_PNMI_ERR_GENERAL;
-	}
-
-	if (RetCode == SK_PNMI_ERR_OK) {
-		*pLen = sizeof(SK_U32);
-	}
-	else {
-
-		*pLen = 0;
-	}
-	return (RetCode);
-}
-#endif /* SK_DIAG_SUPPORT */
-
-/*****************************************************************************
- *
- * Vct - OID handler function of  OIDs
- *
- * Description:
- *	The code is simple. No description necessary.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was performed successfully.
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
- *	                         the correct data (e.g. a 32bit value is
- *	                         needed, but a 16 bit value was passed).
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter).
- *	SK_PNMI_ERR_READ_ONLY	 Only the Get action is allowed.
- *
- */
-
-PNMI_STATIC int Vct(
-SK_AC *pAC,		/* Pointer to adapter context */
-SK_IOC IoC,		/* IO context handle */
-int Action,		/* GET/PRESET/SET action */
-SK_U32 Id,		/* Object ID that is to be processed */
-char *pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,	/* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance,	/* Instance (-1,2..n) that is to be queried */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-	SK_GEPORT	*pPrt;
-	SK_PNMI_VCT	*pVctBackupData;
-	SK_U32		LogPortMax;
-	SK_U32		PhysPortMax;
-	SK_U32		PhysPortIndex;
-	SK_U32		Limit;
-	SK_U32		Offset;
-	SK_BOOL		Link;
-	SK_U32		RetCode = SK_PNMI_ERR_GENERAL;
-	int		i;
-	SK_EVPARA	Para;
-	SK_U32		CableLength;
-	
-	/*
-	 * Calculate the port indexes from the instance.
-	 */
-	PhysPortMax = pAC->GIni.GIMacsFound;
-	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-	
-	/* Dual net mode? */
-	if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-		LogPortMax--;
-	}
-	
-	if ((Instance != (SK_U32) (-1))) {
-		/* Check instance range. */
-		if ((Instance < 2) || (Instance > LogPortMax)) {
-			*pLen = 0;
-			return (SK_PNMI_ERR_UNKNOWN_INST);
-		}
-		
-		if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
-			PhysPortIndex = NetIndex;
-		}
-		else {
-			PhysPortIndex = Instance - 2;
-		}
-		Limit = PhysPortIndex + 1;
-	}
-	else {
-		/*
-		 * Instance == (SK_U32) (-1), get all Instances of that OID.
-		 *
-		 * Not implemented yet. May be used in future releases.
-		 */
-		PhysPortIndex = 0;
-		Limit = PhysPortMax;
-	}
-	
-	pPrt = &pAC->GIni.GP[PhysPortIndex];
-	if (pPrt->PHWLinkUp) {
-		Link = SK_TRUE;
-	}
-	else {
-		Link = SK_FALSE;
-	}
-	
-	/* Check MAC type */
-	if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-	
-	/* Initialize backup data pointer. */
-	pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
-	
-	/* Check action type */
-	if (Action == SK_PNMI_GET) {
-		/* Check length */
-		switch (Id) {
-		
-		case OID_SKGE_VCT_GET:
-			if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
-				*pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-		
-		case OID_SKGE_VCT_STATUS:
-			if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
-				*pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
-				return (SK_PNMI_ERR_TOO_SHORT);
-			}
-			break;
-		
-		default:
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}	
-		
-		/* Get value */
-		Offset = 0;
-		for (; PhysPortIndex < Limit; PhysPortIndex++) {
-			switch (Id) {
-			
-			case OID_SKGE_VCT_GET:
-				if ((Link == SK_FALSE) &&
-					(pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
-					RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
-					if (RetCode == 0) {
-						pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
-						pAC->Pnmi.VctStatus[PhysPortIndex] |=
-							(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
-						
-						/* Copy results for later use to PNMI struct. */
-						for (i = 0; i < 4; i++)  {
-							if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
-								if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) {
-									pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
-								}
-							}
-							if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) {
-								CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
-							}
-							else {
-								CableLength = 0;
-							}
-							pVctBackupData->PMdiPairLen[i] = CableLength;
-							pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
-						}
-
-						Para.Para32[0] = PhysPortIndex;
-						Para.Para32[1] = -1;
-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
-						SkEventDispatcher(pAC, IoC);
-					}
-					else {
-						; /* VCT test is running. */
-					}
-				}
-				
-				/* Get all results. */
-				CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
-				Offset += sizeof(SK_U8);
-				*(pBuf + Offset) = pPrt->PCableLen;
-				Offset += sizeof(SK_U8);
-				for (i = 0; i < 4; i++)  {
-					SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]);
-					Offset += sizeof(SK_U32);
-				}
-				for (i = 0; i < 4; i++)  {
-					*(pBuf + Offset) = pVctBackupData->PMdiPairSts[i];
-					Offset += sizeof(SK_U8);
-				}
-				
-				RetCode = SK_PNMI_ERR_OK;
-				break;
-		
-			case OID_SKGE_VCT_STATUS:
-				CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
-				Offset += sizeof(SK_U8);
-				RetCode = SK_PNMI_ERR_OK;
-				break;
-			
-			default:
-				*pLen = 0;
-				return (SK_PNMI_ERR_GENERAL);
-			}
-		} /* for */
-		*pLen = Offset;
-		return (RetCode);
-	
-	} /* if SK_PNMI_GET */
-	
-	/*
-	 * From here SET or PRESET action. Check if the passed
-	 * buffer length is plausible.
-	 */
-	
-	/* Check length */
-	switch (Id) {
-	case OID_SKGE_VCT_SET:
-		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
-			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
-			return (SK_PNMI_ERR_TOO_SHORT);
-		}
-		break;
-	
-	default:
-		*pLen = 0;
-		return (SK_PNMI_ERR_GENERAL);
-	}
-	
-	/*
-	 * Perform preset or set.
-	 */
-	
-	/* VCT does not support PRESET action. */
-	if (Action == SK_PNMI_PRESET) {
-		return (SK_PNMI_ERR_OK);
-	}
-	
-	Offset = 0;
-	for (; PhysPortIndex < Limit; PhysPortIndex++) {
-		switch (Id) {
-		case OID_SKGE_VCT_SET: /* Start VCT test. */
-			if (Link == SK_FALSE) {
-				SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
-				
-				RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
-				if (RetCode == 0) { /* RetCode: 0 => Start! */
-					pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
-					pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA;
-					pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK;
-					
-					/*
-					 * Start VCT timer counter.
-					 */
-					SK_MEMSET((char *) &Para, 0, sizeof(Para));
-					Para.Para32[0] = PhysPortIndex;
-					Para.Para32[1] = -1;
-					SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
-						4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
-					SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
-					RetCode = SK_PNMI_ERR_OK;
-				}
-				else { /* RetCode: 2 => Running! */
-					SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
-					RetCode = SK_PNMI_ERR_OK;
-				}
-			}
-			else { /* RetCode: 4 => Link! */
-				RetCode = 4;
-				SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
-				RetCode = SK_PNMI_ERR_OK;
-			}
-			Offset += sizeof(SK_U32);
-			break;
-	
-		default:
-			*pLen = 0;
-			return (SK_PNMI_ERR_GENERAL);
-		}
-	} /* for */
-	*pLen = Offset;
-	return (RetCode);
-
-} /* Vct */
-
-
-PNMI_STATIC void CheckVctStatus(
-SK_AC		*pAC,
-SK_IOC		IoC,
-char		*pBuf,
-SK_U32		Offset,
-SK_U32		PhysPortIndex)
-{
-	SK_GEPORT 	*pPrt;
-	SK_PNMI_VCT	*pVctData;
-	SK_U32		RetCode;
-	
-	pPrt = &pAC->GIni.GP[PhysPortIndex];
-	
-	pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
-	pVctData->VctStatus = SK_PNMI_VCT_NONE;
-	
-	if (!pPrt->PHWLinkUp) {
-		
-		/* Was a VCT test ever made before? */
-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
-			if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) {
-				pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
-			}
-			else {
-				pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
-			}
-		}
-		
-		/* Check VCT test status. */
-		RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE);
-		if (RetCode == 2) { /* VCT test is running. */
-			pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
-		}
-		else { /* VCT data was copied to pAC here. Check PENDING state. */
-			if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
-				pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
-			}
-		}
-		
-		if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
-			pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
-		}
-	}
-	else {
-		
-		/* Was a VCT test ever made before? */
-		if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
-			pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
-			pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
-		}
-		
-		/* DSP only valid in 100/1000 modes. */
-		if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed !=
-			SK_LSPEED_STAT_10MBPS) {	
-			pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
-		}
-	}
-} /* CheckVctStatus */
-
-
-/*****************************************************************************
- *
- *      SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed
- *                       PNMI function depending on the subcommand and
- *                       returns all data belonging to the complete database
- *                       or OID request.
- *
- * Description:
- *	Looks up the requested subcommand, calls the corresponding handler
- *	function and passes all required parameters to it.
- *	The function is called by the driver. It is needed to handle the new
- *  generic PNMI IOCTL. This IOCTL is given to the driver and contains both
- *  the OID and a subcommand to decide what kind of request has to be done.
- *
- * Returns:
- *	SK_PNMI_ERR_OK           The request was successfully performed
- *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
- *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
- *	                         the data.
- *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
- *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- *                           exist (e.g. port instance 3 on a two port
- *	                         adapter.
- */
-int SkPnmiGenIoctl(
-SK_AC		*pAC,		/* Pointer to adapter context struct */
-SK_IOC		IoC,		/* I/O context */
-void		*pBuf,		/* Buffer used for the management data transfer */
-unsigned int *pLen,		/* Length of buffer */
-SK_U32		NetIndex)	/* NetIndex (0..n), in single net mode always zero */
-{
-SK_I32	Mode;			/* Store value of subcommand. */
-SK_U32	Oid;			/* Store value of OID. */
-int		ReturnCode;		/* Store return value to show status of PNMI action. */
-int 	HeaderLength;	/* Length of desired action plus OID. */
-
-	ReturnCode = SK_PNMI_ERR_GENERAL;
-	
-	SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
-	SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32));
-	HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
-	*pLen = *pLen - HeaderLength;
-	SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen);
-	
-	switch(Mode) {
-	case SK_GET_SINGLE_VAR:
-		ReturnCode = SkPnmiGetVar(pAC, IoC, Oid, 
-				(char *) pBuf + sizeof(SK_I32), pLen,
-				((SK_U32) (-1)), NetIndex);
-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
-		*pLen = *pLen + sizeof(SK_I32);
-		break;
-	case SK_PRESET_SINGLE_VAR:
-		ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid, 
-				(char *) pBuf + sizeof(SK_I32), pLen,
-				((SK_U32) (-1)), NetIndex);
-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
-		*pLen = *pLen + sizeof(SK_I32);
-		break;
-	case SK_SET_SINGLE_VAR:
-		ReturnCode = SkPnmiSetVar(pAC, IoC, Oid, 
-				(char *) pBuf + sizeof(SK_I32), pLen,
-				((SK_U32) (-1)), NetIndex);
-		SK_PNMI_STORE_U32(pBuf, ReturnCode);
-		*pLen = *pLen + sizeof(SK_I32);
-		break;
-	case SK_GET_FULL_MIB:
-		ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex);
-		break;
-	case SK_PRESET_FULL_MIB:
-		ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
-		break;
-	case SK_SET_FULL_MIB:
-		ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
-		break;
-	default:
-		break;
-	}
-	
-	return (ReturnCode);
-
-} /* SkGeIocGen */
diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c
deleted file mode 100644
index 3e7aa49..0000000
--- a/drivers/net/sk98lin/skgesirq.c
+++ /dev/null
@@ -1,2229 +0,0 @@
-/******************************************************************************
- *
- * Name:	skgesirq.c
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.92 $
- * Date:	$Date: 2003/09/16 14:37:07 $
- * Purpose:	Special IRQ module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *	Special Interrupt handler
- *
- *	The following abstract should show how this module is included
- *	in the driver path:
- *
- *	In the ISR of the driver the bits for frame transmission complete and
- *	for receive complete are checked and handled by the driver itself.
- *	The bits of the slow path mask are checked after that and then the
- *	entry into the so-called "slow path" is prepared. It is an implementors
- *	decision whether this is executed directly or just scheduled by
- *	disabling the mask. In the interrupt service routine some events may be
- *	generated, so it would be a good idea to call the EventDispatcher
- *	right after this ISR.
- *
- *	The Interrupt source register of the adapter is NOT read by this module.
- *  SO if the drivers implementor needs a while loop around the
- *	slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
- *	each loop entered.
- *
- *	However, the MAC Interrupt status registers are read in a while loop.
- *
- */
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#ifndef SK_SLIM
-#include "h/skgepnmi.h"		/* PNMI Definitions */
-#include "h/skrlmt.h"		/* RLMT Definitions */
-#endif
-#include "h/skdrv2nd.h"		/* Adapter Control and Driver specific Def. */
-
-/* local function prototypes */
-#ifdef GENESIS
-static int	SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* GENESIS */
-#ifdef YUKON
-static int	SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* YUKON */
-#ifdef OTHER_PHY
-static int	SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* OTHER_PHY */
-
-#ifdef GENESIS
-/*
- * array of Rx counter from XMAC which are checked
- * in AutoSense mode to check whether a link is not able to auto-negotiate.
- */
-static const SK_U16 SkGeRxRegs[]= {
-	XM_RXF_64B,
-	XM_RXF_127B,
-	XM_RXF_255B,
-	XM_RXF_511B,
-	XM_RXF_1023B,
-	XM_RXF_MAX_SZ
-} ;
-#endif /* GENESIS */
-
-#ifdef __C2MAN__
-/*
- *	Special IRQ function
- *
- *	General Description:
- *
- */
-intro()
-{}
-#endif
-
-/******************************************************************************
- *
- *	SkHWInitDefSense() - Default Autosensing mode initialization
- *
- * Description: sets the PLinkMode for HWInit
- *
- * Returns: N/A
- */
-static void SkHWInitDefSense(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	pPrt->PAutoNegTimeOut = 0;
-
-	if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
-		pPrt->PLinkMode = pPrt->PLinkModeConf;
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("AutoSensing: First mode %d on Port %d\n",
-		(int)SK_LMODE_AUTOFULL, Port));
-
-	pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
-
-	return;
-}	/* SkHWInitDefSense */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkHWSenseGetNext() - Get Next Autosensing Mode
- *
- * Description: gets the appropriate next mode
- *
- * Note:
- *
- */
-static SK_U8 SkHWSenseGetNext(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	pPrt->PAutoNegTimeOut = 0;
-
-    if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
-		/* Leave all as configured */
-		return(pPrt->PLinkModeConf);
-	}
-
-    if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
-		/* Return next mode AUTOBOTH */
-        return ((SK_U8)SK_LMODE_AUTOBOTH);
-	}
-
-	/* Return default autofull */
-    return ((SK_U8)SK_LMODE_AUTOFULL);
-}	/* SkHWSenseGetNext */
-
-
-/******************************************************************************
- *
- *	SkHWSenseSetNext() - Autosensing Set next mode
- *
- * Description:	sets the appropriate next mode
- *
- * Returns: N/A
- */
-static void SkHWSenseSetNext(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U8	NewMode)	/* New Mode to be written in sense mode */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	pPrt->PAutoNegTimeOut = 0;
-
-    if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("AutoSensing: next mode %d on Port %d\n",
-		(int)NewMode, Port));
-
-	pPrt->PLinkMode = NewMode;
-
-	return;
-}	/* SkHWSenseSetNext */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkHWLinkDown() - Link Down handling
- *
- * Description: handles the hardware link down signal
- *
- * Returns: N/A
- */
-void SkHWLinkDown(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Disable all MAC interrupts */
-	SkMacIrqDisable(pAC, IoC, Port);
-
-	/* Disable Receiver and Transmitter */
-	SkMacRxTxDisable(pAC, IoC, Port);
-	
-	/* Init default sense mode */
-	SkHWInitDefSense(pAC, IoC, Port);
-
-	if (pPrt->PHWLinkUp == SK_FALSE) {
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("Link down Port %d\n", Port));
-
-	/* Set Link to DOWN */
-	pPrt->PHWLinkUp = SK_FALSE;
-
-	/* Reset Port stati */
-    pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-    pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
-
-	/* Re-init Phy especially when the AutoSense default is set now */
-	SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
-
-	/* GP0: used for workaround of Rev. C Errata 2 */
-
-	/* Do NOT signal to RLMT */
-
-	/* Do NOT start the timer here */
-}	/* SkHWLinkDown */
-
-
-/******************************************************************************
- *
- *	SkHWLinkUp() - Link Up handling
- *
- * Description: handles the hardware link up signal
- *
- * Returns: N/A
- */
-static void SkHWLinkUp(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		/* We do NOT need to proceed on active link */
-		return;
-	}
-
-	pPrt->PHWLinkUp = SK_TRUE;
-	pPrt->PAutoNegFail = SK_FALSE;
-    pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-
-    if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
-        pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
-        pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
-		/* Link is up and no Auto-negotiation should be done */
-
-		/* Link speed should be the configured one */
-		switch (pPrt->PLinkSpeed) {
-		case SK_LSPEED_AUTO:
-			/* default is 1000 Mbps */
-		case SK_LSPEED_1000MBPS:
-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-			break;
-		case SK_LSPEED_100MBPS:
-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
-			break;
-		case SK_LSPEED_10MBPS:
-			pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
-			break;
-		}
-
-		/* Set Link Mode Status */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
-		}
-		else {
-            pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
-		}
-
-		/* No flow control without auto-negotiation */
-        pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
-
-		/* enable Rx/Tx */
-        (void)SkMacRxTxEnable(pAC, IoC, Port);
-	}
-}	/* SkHWLinkUp */
-
-
-/******************************************************************************
- *
- *	SkMacParity() - MAC parity workaround
- *
- * Description: handles MAC parity errors correctly
- *
- * Returns: N/A
- */
-static void SkMacParity(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index of the port failed */
-{
-	SK_EVPARA	Para;
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_U32		TxMax;		/* Tx Max Size Counter */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Clear IRQ Tx Parity Error */
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-
-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
-			(SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
-			pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
-	}
-#endif /* YUKON */
-	
-	if (pPrt->PCheckPar) {
-
-		if (Port == MAC_1) {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
-		}
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
-		}
-		Para.Para64 = Port;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		
-		Para.Para32[0] = Port;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
-		return;
-	}
-
-	/* Check whether frames with a size of 1k were sent */
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* Snap statistic counters */
-		(void)SkXmUpdateStats(pAC, IoC, Port);
-		
-		(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-
-		(void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
-	}
-#endif /* YUKON */
-	
-	if (TxMax > 0) {
-		/* From now on check the parity */
-		pPrt->PCheckPar = SK_TRUE;
-	}
-}	/* SkMacParity */
-
-
-/******************************************************************************
- *
- *	SkGeHwErr() - Hardware Error service routine
- *
- * Description: handles all HW Error interrupts
- *
- * Returns: N/A
- */
-static void SkGeHwErr(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-SK_U32	HwStatus)	/* Interrupt status word */
-{
-	SK_EVPARA	Para;
-	SK_U16		Word;
-
-	if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
-		/* PCI Errors occured */
-		if ((HwStatus & IS_IRQ_STAT) != 0) {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
-		}
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
-		}
-
-		/* Reset all bits in the PCI STATUS register */
-		SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-		
-		SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-        SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
-		SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
-		Para.Para64 = 0;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-
-		if ((HwStatus & IS_NO_STAT_M1) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
-		}
-
-		if ((HwStatus & IS_NO_STAT_M2) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
-		}
-
-		if ((HwStatus & IS_NO_TIST_M1) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
-		}
-
-		if ((HwStatus & IS_NO_TIST_M2) != 0) {
-			/* Ignore it */
-			/* This situation is also indicated in the descriptor */
-			SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* This is necessary only for Rx timing measurements */
-		if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
-			/* increment Time Stamp Timer counter (high) */
-			pAC->GIni.GITimeStampCnt++;
-
-			/* Clear Time Stamp Timer IRQ */
-			SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
-		}
-
-		if ((HwStatus & IS_IRQ_SENSOR) != 0) {
-			/* no sensors on 32-bit Yukon */
-			if (pAC->GIni.GIYukon32Bit) {
-				/* disable HW Error IRQ */
-				pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
-			}
-		}
-	}
-#endif /* YUKON */
-
-	if ((HwStatus & IS_RAM_RD_PAR) != 0) {
-		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
-		Para.Para64 = 0;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
-	}
-
-	if ((HwStatus & IS_RAM_WR_PAR) != 0) {
-		SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
-		Para.Para64 = 0;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
-	}
-
-	if ((HwStatus & IS_M1_PAR_ERR) != 0) {
-		SkMacParity(pAC, IoC, MAC_1);
-	}
-
-	if ((HwStatus & IS_M2_PAR_ERR) != 0) {
-		SkMacParity(pAC, IoC, MAC_2);
-	}
-
-	if ((HwStatus & IS_R1_PAR_ERR) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
-
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((HwStatus & IS_R2_PAR_ERR) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
-
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-}	/* SkGeHwErr */
-
-
-/******************************************************************************
- *
- *	SkGeSirqIsr() - Special Interrupt Service Routine
- *
- * Description: handles all non data transfer specific interrupts (slow path)
- *
- * Returns: N/A
- */
-void SkGeSirqIsr(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-SK_U32	Istatus)	/* Interrupt status word */
-{
-	SK_EVPARA	Para;
-	SK_U32		RegVal32;	/* Read register value */
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_U16 		PhyInt;
-	int			i;
-
-	if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
-		/* read the HW Error Interrupt source */
-		SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
-		
-		SkGeHwErr(pAC, IoC, RegVal32);
-	}
-
-	/*
-	 * Packet Timeout interrupts
-	 */
-	/* Check whether MACs are correctly initialized */
-	if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
-		pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
-		/* MAC 1 was not initialized but Packet timeout occured */
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
-			SKERR_SIRQ_E004MSG);
-	}
-
-	if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
-	    pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
-		/* MAC 2 was not initialized but Packet timeout occured */
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
-			SKERR_SIRQ_E005MSG);
-	}
-
-	if ((Istatus & IS_PA_TO_RX1) != 0) {
-		/* Means network is filling us up */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
-			SKERR_SIRQ_E002MSG);
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
-	}
-
-	if ((Istatus & IS_PA_TO_RX2) != 0) {
-		/* Means network is filling us up */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
-			SKERR_SIRQ_E003MSG);
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
-	}
-
-	if ((Istatus & IS_PA_TO_TX1) != 0) {
-		
-		pPrt = &pAC->GIni.GP[0];
-
-		/* May be a normal situation in a server with a slow network */
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
-
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			/*
-			 * workaround: if in half duplex mode, check for Tx hangup.
-			 * Read number of TX'ed bytes, wait for 10 ms, then compare
-			 * the number with current value. If nothing changed, we assume
-			 * that Tx is hanging and do a FIFO flush (see event routine).
-			 */
-			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
-				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
-				!pPrt->HalfDupTimerActive) {
-				/*
-				 * many more pack. arb. timeouts may come in between,
-				 * we ignore those
-				 */
-				pPrt->HalfDupTimerActive = SK_TRUE;
-				/* Snap statistic counters */
-				(void)SkXmUpdateStats(pAC, IoC, 0);
-
-				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
-
-				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
-				
-				(void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
-
-				pPrt->LastOctets += RegVal32;
-				
-				Para.Para32[0] = 0;
-				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
-					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
-			}
-		}
-#endif /* GENESIS */
-	}
-
-	if ((Istatus & IS_PA_TO_TX2) != 0) {
-		
-		pPrt = &pAC->GIni.GP[1];
-
-		/* May be a normal situation in a server with a slow network */
-		SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
-
-#ifdef GENESIS
-		if (pAC->GIni.GIGenesis) {
-			/* workaround: see above */
-			if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
-				 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
-				!pPrt->HalfDupTimerActive) {
-				pPrt->HalfDupTimerActive = SK_TRUE;
-				/* Snap statistic counters */
-				(void)SkXmUpdateStats(pAC, IoC, 1);
-
-				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
-
-				pPrt->LastOctets = (SK_U64)RegVal32 << 32;
-				
-				(void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
-
-				pPrt->LastOctets += RegVal32;
-				
-				Para.Para32[0] = 1;
-				SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
-					SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
-			}
-		}
-#endif /* GENESIS */
-	}
-
-	/* Check interrupts of the particular queues */
-	if ((Istatus & IS_R1_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
-			SKERR_SIRQ_E006MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_R2_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
-			SKERR_SIRQ_E007MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XS1_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
-			SKERR_SIRQ_E008MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XA1_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
-			SKERR_SIRQ_E009MSG);
-		Para.Para64 = MAC_1;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_1;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XS2_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
-			SKERR_SIRQ_E010MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	if ((Istatus & IS_XA2_C) != 0) {
-		/* Clear IRQ */
-		SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
-			SKERR_SIRQ_E011MSG);
-		Para.Para64 = MAC_2;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-		Para.Para32[0] = MAC_2;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-	/* External reg interrupt */
-	if ((Istatus & IS_EXT_REG) != 0) {
-		/* Test IRQs from PHY */
-		for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-			
-			pPrt = &pAC->GIni.GP[i];
-			
-			if (pPrt->PState == SK_PRT_RESET) {
-				continue;
-			}
-			
-#ifdef GENESIS
-			if (pAC->GIni.GIGenesis) {
-				
-				switch (pPrt->PhyType) {
-				
-				case SK_PHY_XMAC:
-					break;
-				
-				case SK_PHY_BCOM:
-					SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
-	
-					if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
-						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-							("Port %d Bcom Int: 0x%04X\n",
-							i, PhyInt));
-						SkPhyIsrBcom(pAC, IoC, i, PhyInt);
-					}
-					break;
-#ifdef OTHER_PHY
-				case SK_PHY_LONE:
-					SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
-					
-					if ((PhyInt & PHY_L_DEF_MSK) != 0) {
-						SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-							("Port %d Lone Int: %x\n",
-							i, PhyInt));
-						SkPhyIsrLone(pAC, IoC, i, PhyInt);
-					}
-					break;
-#endif /* OTHER_PHY */
-				}
-			}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-			if (pAC->GIni.GIYukon) {
-				/* Read PHY Interrupt Status */
-				SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
-
-				if ((PhyInt & PHY_M_DEF_MSK) != 0) {
-					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-						("Port %d Marv Int: 0x%04X\n",
-						i, PhyInt));
-					SkPhyIsrGmac(pAC, IoC, i, PhyInt);
-				}
-			}
-#endif /* YUKON */
-		}
-	}
-
-	/* I2C Ready interrupt */
-	if ((Istatus & IS_I2C_READY) != 0) {
-#ifdef SK_SLIM
-        SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-#else		
-		SkI2cIsr(pAC, IoC);
-#endif		
-	}
-
-	/* SW forced interrupt */
-	if ((Istatus & IS_IRQ_SW) != 0) {
-		/* clear the software IRQ */
-		SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
-	}
-
-	if ((Istatus & IS_LNK_SYNC_M1) != 0) {
-		/*
-		 * We do NOT need the Link Sync interrupt, because it shows
-		 * us only a link going down.
-		 */
-		/* clear interrupt */
-		SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
-	}
-
-	/* Check MAC after link sync counter */
-	if ((Istatus & IS_MAC1) != 0) {
-		/* IRQ from MAC 1 */
-		SkMacIrq(pAC, IoC, MAC_1);
-	}
-
-	if ((Istatus & IS_LNK_SYNC_M2) != 0) {
-		/*
-		 * We do NOT need the Link Sync interrupt, because it shows
-		 * us only a link going down.
-		 */
-		/* clear interrupt */
-		SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
-	}
-
-	/* Check MAC after link sync counter */
-	if ((Istatus & IS_MAC2) != 0) {
-		/* IRQ from MAC 2 */
-		SkMacIrq(pAC, IoC, MAC_2);
-	}
-
-	/* Timer interrupt (served last) */
-	if ((Istatus & IS_TIMINT) != 0) {
-		/* check for HW Errors */
-		if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
-			/* read the HW Error Interrupt source */
-			SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
-
-			SkGeHwErr(pAC, IoC, RegVal32);
-		}
-
-		SkHwtIsr(pAC, IoC);
-	}
-
-}	/* SkGeSirqIsr */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- */
-static int SkGePortCheckShorts(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port)		/* Which port should be checked */
-{
-	SK_U32		Shorts;			/* Short Event Counter */
-	SK_U32		CheckShorts;	/* Check value for Short Event Counter */
-	SK_U64		RxCts;			/* Rx Counter (packets on network) */
-	SK_U32		RxTmp;			/* Rx temp. Counter */
-	SK_U32		FcsErrCts;		/* FCS Error Counter */
-	SK_GEPORT	*pPrt;			/* GIni Port struct pointer */
-	int			Rtv;			/* Return value */
-	int			i;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Default: no action */
-	Rtv = SK_HW_PS_NONE;
-
-	(void)SkXmUpdateStats(pAC, IoC, Port);
-
-	/* Extra precaution: check for short Event counter */
-	(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
-
-	/*
-	 * Read Rx counters (packets seen on the network and not necessarily
-	 * really received.
-	 */
-	RxCts = 0;
-
-	for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) {
-		
-		(void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
-		
-		RxCts += (SK_U64)RxTmp;
-	}
-
-	/* On default: check shorts against zero */
-	CheckShorts = 0;
-
-	/* Extra precaution on active links */
-	if (pPrt->PHWLinkUp) {
-		/* Reset Link Restart counter */
-		pPrt->PLinkResCt = 0;
-		pPrt->PAutoNegTOCt = 0;
-
-		/* If link is up check for 2 */
-		CheckShorts = 2;
-
-		(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
-		
-		if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-		    pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
-		    (pPrt->PLinkMode == SK_LMODE_HALF ||
-			 pPrt->PLinkMode == SK_LMODE_FULL)) {
-			/*
-			 * This is autosensing and we are in the fallback
-			 * manual full/half duplex mode.
-			 */
-			if (RxCts == pPrt->PPrevRx) {
-				/* Nothing received, restart link */
-				pPrt->PPrevFcs = FcsErrCts;
-				pPrt->PPrevShorts = Shorts;
-				
-				return(SK_HW_PS_RESTART);
-			}
-			else {
-				pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
-			}
-		}
-
-		if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
-		    (!(FcsErrCts - pPrt->PPrevFcs))) {
-			/*
-			 * Note: The compare with zero above has to be done the way shown,
-			 * otherwise the Linux driver will have a problem.
-			 */
-			/*
-			 * We received a bunch of frames or no CRC error occured on the
-			 * network -> ok.
-			 */
-			pPrt->PPrevRx = RxCts;
-			pPrt->PPrevFcs = FcsErrCts;
-			pPrt->PPrevShorts = Shorts;
-
-			return(SK_HW_PS_NONE);
-		}
-
-		pPrt->PPrevFcs = FcsErrCts;
-	}
-
-
-	if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Short Event Count Restart Port %d \n", Port));
-		Rtv = SK_HW_PS_RESTART;
-	}
-
-	pPrt->PPrevShorts = Shorts;
-	pPrt->PPrevRx = RxCts;
-
-	return(Rtv);
-}	/* SkGePortCheckShorts */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUp() - Check if the link is up
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUp(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port)		/* Which port should be checked */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_BOOL		AutoNeg;	/* Is Auto-negotiation used ? */
-	int			Rtv;		/* Return value */
-
-	Rtv = SK_HW_PS_NONE;
-	
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		AutoNeg = SK_FALSE;
-	}
-	else {
-		AutoNeg = SK_TRUE;
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-
-		switch (pPrt->PhyType) {
-		
-		case SK_PHY_XMAC:
-			Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
-			break;
-		case SK_PHY_BCOM:
-			Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
-			break;
-		case SK_PHY_NAT:
-			Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
-			break;
-#endif /* OTHER_PHY */
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
-	}
-#endif /* YUKON */
-
-	return(Rtv);	
-}	/* SkGePortCheckUp */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpXmac(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_U32		Shorts;		/* Short Event Counter */
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U32		GpReg;		/* General Purpose register value */
-	SK_U16		Isrc;		/* Interrupt source register */
-	SK_U16		IsrcSum;	/* Interrupt source register sum */
-	SK_U16		LpAb;		/* Link Partner Ability */
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		ExtStat;	/* Extended Status Register */
-	SK_U8		NextMode;	/* Next AutoSensing Mode */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		if (pPrt->PhyType != SK_PHY_XMAC) {
-			return(SK_HW_PS_NONE);
-		}
-		else {
-			return(SkGePortCheckShorts(pAC, IoC, Port));
-		}
-	}
-
-	IsrcSum = pPrt->PIsave;
-	pPrt->PIsave = 0;
-
-	/* Now wait for each port's link */
-	if (pPrt->PLinkBroken) {
-		/* Link was broken */
-		XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
-
-		if ((GpReg & XM_GP_INP_ASS) == 0) {
-			/* The Link is in sync */
-			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-			IsrcSum |= Isrc;
-			SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
-			
-			if ((Isrc & XM_IS_INP_ASS) == 0) {
-				/* It has been in sync since last time */
-				/* Restart the PORT */
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-					("Link in sync Restart Port %d\n", Port));
-
-				(void)SkXmUpdateStats(pAC, IoC, Port);
-
-				/* We now need to reinitialize the PrevShorts counter */
-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
-				pPrt->PPrevShorts = Shorts;
-
-				pPrt->PLinkBroken = SK_FALSE;
-
-				/*
-				 * Link Restart Workaround:
-				 *  it may be possible that the other Link side
-				 *  restarts its link as well an we detect
-				 *  another LinkBroken. To prevent this
-				 *  happening we check for a maximum number
-				 *  of consecutive restart. If those happens,
-				 *  we do NOT restart the active link and
-				 *  check whether the link is now o.k.
-				 */
-				pPrt->PLinkResCt++;
-				
-				pPrt->PAutoNegTimeOut = 0;
-
-				if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
-					return(SK_HW_PS_RESTART);
-				}
-
-				pPrt->PLinkResCt = 0;
-				
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
-			}
-			else {
-				pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
-				
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
-
-				/* Do nothing more if link is broken */
-				return(SK_HW_PS_NONE);
-			}
-		}
-		else {
-			/* Do nothing more if link is broken */
-			return(SK_HW_PS_NONE);
-		}
-
-	}
-	else {
-		/* Link was not broken, check if it is */
-		XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-		IsrcSum |= Isrc;
-		if ((Isrc & XM_IS_INP_ASS) != 0) {
-			XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-			IsrcSum |= Isrc;
-			if ((Isrc & XM_IS_INP_ASS) != 0) {
-				XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-				IsrcSum |= Isrc;
-				if ((Isrc & XM_IS_INP_ASS) != 0) {
-					pPrt->PLinkBroken = SK_TRUE;
-					/* Re-Init Link partner Autoneg flag */
-					pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
-					SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-						("Link broken Port %d\n", Port));
-
-					/* Cable removed-> reinit sense mode */
-					SkHWInitDefSense(pAC, IoC, Port);
-
-					return(SK_HW_PS_RESTART);
-				}
-			}
-		}
-		else {
-			SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
-			
-			if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
-				return(SK_HW_PS_RESTART);
-			}
-		}
-	}
-
-	/*
-	 * here we usually can check whether the link is in sync and
-	 * auto-negotiation is done.
-	 */
-	XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
-	XM_IN16(IoC, Port, XM_ISRC, &Isrc);
-	IsrcSum |= Isrc;
-
-	SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
-	
-	if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
-		if ((GpReg & XM_GP_INP_ASS) == 0) {
-			/* Save Auto-negotiation Done interrupt only if link is in sync */
-			pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
-		}
-#ifdef DEBUG
-		if ((pPrt->PIsave & XM_IS_AND) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("AutoNeg done rescheduled Port %d\n", Port));
-		}
-#endif /* DEBUG */
-		return(SK_HW_PS_NONE);
-	}
-
-	if (AutoNeg) {
-		if ((IsrcSum & XM_IS_AND) != 0) {
-			SkHWLinkUp(pAC, IoC, Port);
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			if (Done != SK_AND_OK) {
-				/* Get PHY parameters, for debugging only */
-				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
-				SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
-					 Port, LpAb, ResAb));
-					
-				/* Try next possible mode */
-				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
-				SkHWLinkDown(pAC, IoC, Port);
-				if (Done == SK_AND_DUP_CAP) {
-					/* GoTo next mode */
-					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
-				}
-
-				return(SK_HW_PS_RESTART);
-			}
-			/*
-			 * Dummy Read extended status to prevent extra link down/ups
-			 * (clear Page Received bit if set)
-			 */
-			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
-			
-			return(SK_HW_PS_LINK);
-		}
-		
-		/* AutoNeg not done, but HW link is up. Check for timeouts */
-		pPrt->PAutoNegTimeOut++;
-		if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
-			/* Increase the Timeout counter */
-			pPrt->PAutoNegTOCt++;
-
-			/* Timeout occured */
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-				("AutoNeg timeout Port %d\n", Port));
-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-				pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
-				/* Set Link manually up */
-				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-					("Set manual full duplex Port %d\n", Port));
-			}
-
-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-				pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
-				pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
-				/*
-				 * This is rather complicated.
-				 * we need to check here whether the LIPA_AUTO
-				 * we saw before is false alert. We saw at one
-				 * switch ( SR8800) that on boot time it sends
-				 * just one auto-neg packet and does no further
-				 * auto-negotiation.
-				 * Solution: we restart the autosensing after
-				 * a few timeouts.
-				 */
-				pPrt->PAutoNegTOCt = 0;
-				pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
-				SkHWInitDefSense(pAC, IoC, Port);
-			}
-
-			/* Do the restart */
-			return(SK_HW_PS_RESTART);
-		}
-	}
-	else {
-		/* Link is up and we don't need more */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync(GP), Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		/*
-		 * Link sync (GP) and so assume a good connection. But if not received
-		 * a bunch of frames received in a time slot (maybe broken tx cable)
-		 * the port is restart.
-		 */
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpXmac */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpBcom(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U16		Isrc;		/* Interrupt source register */
-	SK_U16		PhyStat;	/* Phy Status Register */
-	SK_U16		ResAb;		/* Master/Slave resolution */
-	SK_U16		Ctrl;		/* Broadcom control flags */
-#ifdef DEBUG
-	SK_U16		LpAb;
-	SK_U16		ExtStat;
-#endif /* DEBUG */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Check for No HCD Link events (#10523) */
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
-
-#ifdef xDEBUG
-	if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) ==
-		(PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
-
-		SK_U32	Stat1, Stat2, Stat3;
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"CheckUp1 - Stat: %x, Mask: %x",
-			(void *)Isrc,
-			(void *)Stat1);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"Ctrl/Stat: %x, AN Adv/LP: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-	}
-#endif /* DEBUG */
-
-	if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
-		/*
-		 * Workaround BCom Errata:
-		 *	enable and disable loopback mode if "NO HCD" occurs.
-		 */
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
-			(SK_U16)(Ctrl | PHY_CT_LOOP));
-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
-			(SK_U16)(Ctrl & ~PHY_CT_LOOP));
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("No HCD Link event, Port %d\n", Port));
-#ifdef xDEBUG
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"No HCD link event, port %d.",
-			(void *)Port,
-			(void *)NULL);
-#endif /* DEBUG */
-	}
-
-	/* Not obsolete: link status bit is latched to 0 and autoclearing! */
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-
-	if (pPrt->PHWLinkUp) {
-		return(SK_HW_PS_NONE);
-	}
-
-#ifdef xDEBUG
-	{
-		SK_U32	Stat1, Stat2, Stat3;
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"CheckUp1a - Stat: %x, Mask: %x",
-			(void *)Isrc,
-			(void *)Stat1);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-		Stat1 = Stat1 << 16 | PhyStat;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"Ctrl/Stat: %x, AN Adv/LP: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-		Stat2 = Stat2 << 16 | ResAb;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-
-		Stat1 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
-		Stat1 = Stat1 << 16 | Stat2;
-		Stat2 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
-		Stat3 = 0;
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
-		Stat2 = Stat2 << 16 | Stat3;
-		CMSMPrintString(
-			pAC->pConfigTable,
-			MSG_TYPE_RUNTIME_INFO,
-			"PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
-			(void *)Stat1,
-			(void *)Stat2);
-	}
-#endif /* DEBUG */
-
-	/*
-	 * Here we usually can check whether the link is in sync and
-	 * auto-negotiation is done.
-	 */
-
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
-
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault port %d\n", Port));
-		
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		
-		return(SK_HW_PS_RESTART);
-	}
-
-	if ((PhyStat & PHY_ST_LSYNC) == 0) {
-		return(SK_HW_PS_NONE);
-	}
-	
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Port %d, ResAb: 0x%04X\n", Port, ResAb));
-
-	if (AutoNeg) {
-		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
-			
-			SkHWLinkUp(pAC, IoC, Port);
-			
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			
-			if (Done != SK_AND_OK) {
-#ifdef DEBUG
-				/* Get PHY parameters, for debugging only */
-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
-					Port, LpAb, ExtStat));
-#endif /* DEBUG */
-				return(SK_HW_PS_RESTART);
-			}
-			else {
-#ifdef xDEBUG
-				/* Dummy read ISR to prevent extra link downs/ups */
-				SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
-
-				if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
-					CMSMPrintString(
-						pAC->pConfigTable,
-						MSG_TYPE_RUNTIME_INFO,
-						"CheckUp2 - Stat: %x",
-						(void *)ExtStat,
-						(void *)NULL);
-				}
-#endif /* DEBUG */
-				return(SK_HW_PS_LINK);
-			}
-		}
-	}
-	else {	/* !AutoNeg */
-		/* Link is up and we don't need more. */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-
-#ifdef xDEBUG
-		/* Dummy read ISR to prevent extra link downs/ups */
-		SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
-
-		if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
-			CMSMPrintString(
-				pAC->pConfigTable,
-				MSG_TYPE_RUNTIME_INFO,
-				"CheckUp3 - Stat: %x",
-				(void *)ExtStat,
-				(void *)NULL);
-		}
-#endif /* DEBUG */
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync(GP), Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpGmac(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U16		PhyIsrc;	/* PHY Interrupt source */
-	SK_U16		PhyStat;	/* PPY Status */
-	SK_U16		PhySpecStat;/* PHY Specific Status */
-	SK_U16		ResAb;		/* Master/Slave resolution */
-	SK_EVPARA	Para;
-#ifdef DEBUG
-	SK_U16		Word;		/* I/O helper */
-#endif /* DEBUG */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		return(SK_HW_PS_NONE);
-	}
-
-	/* Read PHY Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
-
-	/* Read PHY Interrupt Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
-
-	if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc));
-	}
-
-	if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc));
-	}
-
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-	
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
-
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault port %d\n", Port));
-		
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		
-		return(SK_HW_PS_RESTART);
-	}
-
-	/* Read PHY Specific Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
-
-#ifdef DEBUG
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
-
-	if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 ||
-		(PhySpecStat & PHY_M_PS_PAGE_REC) != 0)  {
-		/* Read PHY Next Page Link Partner */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Page Received, NextPage: 0x%04X\n", Word));
-	}
-#endif /* DEBUG */
-
-	if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
-		return(SK_HW_PS_NONE);
-	}
-	
-	if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 ||
-		(PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) {
-		/* Downshift detected */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG);
-		
-		Para.Para64 = Port;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
-	}
-
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-	
-	pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
-	
-	if (AutoNeg) {
-		/* Auto-Negotiation Over ? */
-		if ((PhyStat & PHY_ST_AN_OVER) != 0) {
-			
-			SkHWLinkUp(pAC, IoC, Port);
-			
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			
-			if (Done != SK_AND_OK) {
-				return(SK_HW_PS_RESTART);
-			}
-			
-			return(SK_HW_PS_LINK);
-		}
-	}
-	else {	/* !AutoNeg */
-		/* Link is up and we don't need more */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync, Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpGmac */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpLone(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	int			Done;
-	SK_U16		Isrc;		/* Interrupt source register */
-	SK_U16		LpAb;		/* Link Partner Ability */
-	SK_U16		ExtStat;	/* Extended Status Register */
-	SK_U16		PhyStat;	/* Phy Status Register */
-	SK_U16		StatSum;
-	SK_U8		NextMode;	/* Next AutoSensing Mode */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PHWLinkUp) {
-		return(SK_HW_PS_NONE);
-	}
-
-	StatSum = pPrt->PIsave;
-	pPrt->PIsave = 0;
-
-	/*
-	 * here we usually can check whether the link is in sync and
-	 * auto-negotiation is done.
-	 */
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
-	StatSum |= PhyStat;
-
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-	
-	if ((PhyStat & PHY_ST_LSYNC) == 0) {
-		/* Save Auto-negotiation Done bit */
-		pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
-#ifdef DEBUG
-		if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("AutoNeg done rescheduled Port %d\n", Port));
-		}
-#endif /* DEBUG */
-		return(SK_HW_PS_NONE);
-	}
-
-	if (AutoNeg) {
-		if ((StatSum & PHY_ST_AN_OVER) != 0) {
-			SkHWLinkUp(pAC, IoC, Port);
-			Done = SkMacAutoNegDone(pAC, IoC, Port);
-			if (Done != SK_AND_OK) {
-				/* Get PHY parameters, for debugging only */
-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-					("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
-					 Port, LpAb, ExtStat));
-					
-				/* Try next possible mode */
-				NextMode = SkHWSenseGetNext(pAC, IoC, Port);
-				SkHWLinkDown(pAC, IoC, Port);
-				if (Done == SK_AND_DUP_CAP) {
-					/* GoTo next mode */
-					SkHWSenseSetNext(pAC, IoC, Port, NextMode);
-				}
-
-				return(SK_HW_PS_RESTART);
-
-			}
-			else {
-				/*
-				 * Dummy Read interrupt status to prevent
-				 * extra link down/ups
-				 */
-				SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
-				return(SK_HW_PS_LINK);
-			}
-		}
-		
-		/* AutoNeg not done, but HW link is up. Check for timeouts */
-		pPrt->PAutoNegTimeOut++;
-		if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
-			/* Timeout occured */
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-				("AutoNeg timeout Port %d\n", Port));
-			if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
-				pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
-				/* Set Link manually up */
-				SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
-				SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-					("Set manual full duplex Port %d\n", Port));
-			}
-
-			/* Do the restart */
-			return(SK_HW_PS_RESTART);
-		}
-	}
-	else {
-		/* Link is up and we don't need more */
-#ifdef DEBUG
-		if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-				("ERROR: Lipa auto detected on port %d\n", Port));
-		}
-#endif /* DEBUG */
-
-		/*
-		 * Dummy Read interrupt status to prevent
-		 * extra link down/ups
-		 */
-		SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("Link sync(GP), Port %d\n", Port));
-		SkHWLinkUp(pAC, IoC, Port);
-		
-		return(SK_HW_PS_LINK);
-	}
-
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpLone */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUpNat() - Check if the link is up on National PHY
- *
- * return:
- *	0	o.k. nothing needed
- *	1	Restart needed on this port
- *	2	Link came up
- */
-static int SkGePortCheckUpNat(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO Context */
-int		Port,		/* Which port should be checked */
-SK_BOOL	AutoNeg)	/* Is Auto-negotiation used ? */
-{
-	/* todo: National */
-	return(SK_HW_PS_NONE);
-}	/* SkGePortCheckUpNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- *	SkGeSirqEvent() - Event Service Routine
- *
- * Description:
- *
- * Notes:
- */
-int	SkGeSirqEvent(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* Io Context */
-SK_U32		Event,		/* Module specific Event */
-SK_EVPARA	Para)		/* Event specific Parameter */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_U32		Port;
-	SK_U32		Val32;
-	int			PortStat;
-	SK_U8		Val8;
-#ifdef GENESIS
-	SK_U64		Octets;
-#endif /* GENESIS */
-
-	Port = Para.Para32[0];
-	pPrt = &pAC->GIni.GP[Port];
-
-	switch (Event) {
-	case SK_HWEV_WATIM:
-		if (pPrt->PState == SK_PRT_RESET) {
-		
-			PortStat = SK_HW_PS_NONE;
-		}
-		else {
-			/* Check whether port came up */
-			PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
-		}
-
-		switch (PortStat) {
-		case SK_HW_PS_RESTART:
-			if (pPrt->PHWLinkUp) {
-				/* Set Link to down */
-				SkHWLinkDown(pAC, IoC, (int)Port);
-
-				/*
-				 * Signal directly to RLMT to ensure correct
-				 * sequence of SWITCH and RESET event.
-				 */
-				SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
-			}
-
-			/* Restart needed */
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
-			break;
-
-		case SK_HW_PS_LINK:
-			/* Signal to RLMT */
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
-			break;
-		}
-		
-		/* Start again the check Timer */
-		if (pPrt->PHWLinkUp) {
-			Val32 = SK_WA_ACT_TIME;
-		}
-		else {
-			Val32 = SK_WA_INA_TIME;
-		}
-
-		/* Todo: still needed for non-XMAC PHYs??? */
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-		break;
-
-	case SK_HWEV_PORT_START:
-		if (pPrt->PHWLinkUp) {
-			/*
-			 * Signal directly to RLMT to ensure correct
-			 * sequence of SWITCH and RESET event.
-			 */
-			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
-		}
-
-		SkHWLinkDown(pAC, IoC, (int)Port);
-
-		/* Schedule Port RESET */
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
-
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-		break;
-
-	case SK_HWEV_PORT_STOP:
-		if (pPrt->PHWLinkUp) {
-			/*
-			 * Signal directly to RLMT to ensure correct
-			 * sequence of SWITCH and RESET event.
-			 */
-			SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
-		}
-
-		/* Stop Workaround Timer */
-		SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
-
-		SkHWLinkDown(pAC, IoC, (int)Port);
-		break;
-
-	case SK_HWEV_UPDATE_STAT:
-		/* We do NOT need to update any statistics */
-		break;
-
-	case SK_HWEV_CLEAR_STAT:
-		/* We do NOT need to clear any statistics */
-		for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
-			pPrt->PPrevRx = 0;
-			pPrt->PPrevFcs = 0;
-			pPrt->PPrevShorts = 0;
-		}
-		break;
-
-	case SK_HWEV_SET_LMODE:
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PLinkModeConf != Val8) {
-			/* Set New link mode */
-			pPrt->PLinkModeConf = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-	case SK_HWEV_SET_FLOWMODE:
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PFlowCtrlMode != Val8) {
-			/* Set New Flow Control mode */
-			pPrt->PFlowCtrlMode = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-	case SK_HWEV_SET_ROLE:
-		/* not possible for fiber */
-		if (!pAC->GIni.GICopperType) {
-			break;
-		}
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PMSMode != Val8) {
-			/* Set New Role (Master/Slave) mode */
-			pPrt->PMSMode = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-	case SK_HWEV_SET_SPEED:
-		if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
-			break;
-		}
-		Val8 = (SK_U8)Para.Para32[1];
-		if (pPrt->PLinkSpeed != Val8) {
-			/* Set New Speed parameter */
-			pPrt->PLinkSpeed = Val8;
-
-			/* Restart Port */
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-		}
-		break;
-
-#ifdef GENESIS
-	case SK_HWEV_HALFDUP_CHK:
-		if (pAC->GIni.GIGenesis) {
-			/*
-			 * half duplex hangup workaround.
-			 * See packet arbiter timeout interrupt for description
-			 */
-			pPrt->HalfDupTimerActive = SK_FALSE;
-			if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
-				pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
-				/* Snap statistic counters */
-				(void)SkXmUpdateStats(pAC, IoC, Port);
-
-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
-
-				Octets = (SK_U64)Val32 << 32;
-				
-				(void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
-
-				Octets += Val32;
-				
-				if (pPrt->LastOctets == Octets) {
-					/* Tx hanging, a FIFO flush restarts it */
-					SkMacFlushTxFifo(pAC, IoC, Port);
-				}
-			}
-		}
-		break;
-#endif /* GENESIS */
-	
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
-		break;
-	}
-
-	return(0);
-}	/* SkGeSirqEvent */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkPhyIsrBcom() - PHY interrupt service routine
- *
- * Description: handles all interrupts from BCom PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrBcom(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* Io Context */
-int			Port,		/* Port Num = PHY Num */
-SK_U16		IStatus)	/* Interrupt Status */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_EVPARA	Para;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if ((IStatus & PHY_B_IS_PSE) != 0) {
-		/* Incorrectable pair swap error */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
-			SKERR_SIRQ_E022MSG);
-	}
-	
-	if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
-
-		SkHWLinkDown(pAC, IoC, Port);
-
-		Para.Para32[0] = (SK_U32)Port;
-		/* Signal to RLMT */
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-	}
-
-}	/* SkPhyIsrBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkPhyIsrGmac() - PHY interrupt service routine
- *
- * Description: handles all interrupts from Marvell PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrGmac(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* Io Context */
-int			Port,		/* Port Num = PHY Num */
-SK_U16		IStatus)	/* Interrupt Status */
-{
-	SK_GEPORT	*pPrt;		/* GIni Port struct pointer */
-	SK_EVPARA	Para;
-	SK_U16		Word;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
-
-		SkHWLinkDown(pAC, IoC, Port);
-
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNeg.Adv: 0x%04X\n", Word));
-		
-		/* Set Auto-negotiation advertisement */
-		if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
-			/* restore Asymmetric Pause bit */
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
-				(SK_U16)(Word | PHY_M_AN_ASP));
-		}
-		
-		Para.Para32[0] = (SK_U32)Port;
-		/* Signal to RLMT */
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-	
-	if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
-		/* Auto-Negotiation Error */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
-	}
-	
-	if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
-		/* FIFO Overflow/Underrun Error */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
-	}
-	
-}	/* SkPhyIsrGmac */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- *	SkPhyIsrLone() - PHY interrupt service routine
- *
- * Description: handles all interrupts from LONE PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrLone(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* Io Context */
-int		Port,		/* Port Num = PHY Num */
-SK_U16	IStatus)	/* Interrupt Status */
-{
-	SK_EVPARA	Para;
-
-	if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
-		
-		SkHWLinkDown(pAC, IoC, Port);
-
-		Para.Para32[0] = (SK_U32)Port;
-		/* Signal to RLMT */
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-	}
-
-}	/* SkPhyIsrLone */
-#endif /* OTHER_PHY */
-
-/* End of File */
diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c
deleted file mode 100644
index 79bf57c..0000000
--- a/drivers/net/sk98lin/ski2c.c
+++ /dev/null
@@ -1,1296 +0,0 @@
-/******************************************************************************
- *
- * Name:	ski2c.c
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.59 $
- * Date:	$Date: 2003/10/20 09:07:25 $
- * Purpose:	Functions to access Voltage and Temperature Sensor
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *	I2C Protocol
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. ";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/lm80.h"
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
-	I2C protocol implementation.
-
-	General Description:
-
-	The I2C protocol is used for the temperature sensors and for
-	the serial EEPROM which hold the configuration.
-
-	This file covers functions that allow to read write and do
-	some bulk requests a specified I2C address.
-
-	The Genesis has 2 I2C buses. One for the EEPROM which holds
-	the VPD Data and one for temperature and voltage sensor.
-	The following picture shows the I2C buses, I2C devices and
-	their control registers.
-
-	Note: The VPD functions are in skvpd.c
-.
-.	PCI Config I2C Bus for VPD Data:
-.
-.		      +------------+
-.		      | VPD EEPROM |
-.		      +------------+
-.			     |
-.			     | <-- I2C
-.			     |
-.		 +-----------+-----------+
-.		 |			 |
-.	+-----------------+	+-----------------+
-.	| PCI_VPD_ADR_REG |	| PCI_VPD_DAT_REG |
-.	+-----------------+	+-----------------+
-.
-.
-.	I2C Bus for LM80 sensor:
-.
-.			+-----------------+
-.			| Temperature and |
-.			| Voltage Sensor  |
-.			| 	LM80	  |
-.			+-----------------+
-.				|
-.				|
-.			I2C --> |
-.				|
-.			     +----+
-.	     +-------------->| OR |<--+
-.	     |		     +----+   |
-.     +------+------+		      |
-.     |		    |		      |
-. +--------+	+--------+	+----------+
-. | B2_I2C |	| B2_I2C |	|  B2_I2C  |
-. | _CTRL  |	| _DATA  |	|   _SW    |
-. +--------+	+--------+	+----------+
-.
-	The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL
-	and B2_I2C_DATA registers.
-	For driver software it is recommended to use the I2C control and
-	data register, because I2C bus timing is done by the ASIC and
-	an interrupt may be received when the I2C request is completed.
-
-	Clock Rate Timing:			MIN	MAX	generated by
-		VPD EEPROM:			50 kHz	100 kHz		HW
-		LM80 over I2C Ctrl/Data reg.	50 kHz	100 kHz		HW
-		LM80 over B2_I2C_SW register	0	400 kHz		SW
-
-	Note:	The clock generated by the hardware is dependend on the
-		PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD
-		clock is 50 kHz.
- */
-intro()
-{}
-#endif
-
-#ifdef SK_DIAG
-/*
- * I2C Fast Mode timing values used by the LM80.
- * If new devices are added to the I2C bus the timing values have to be checked.
- */
-#ifndef I2C_SLOW_TIMING
-#define	T_CLK_LOW			1300L	/* clock low time in ns */
-#define	T_CLK_HIGH		 	 600L	/* clock high time in ns */
-#define T_DATA_IN_SETUP		 100L	/* data in Set-up Time */
-#define T_START_HOLD		 600L	/* start condition hold time */
-#define T_START_SETUP		 600L	/* start condition Set-up time */
-#define	T_STOP_SETUP		 600L	/* stop condition Set-up time */
-#define T_BUS_IDLE			1300L	/* time the bus must free after Tx */
-#define	T_CLK_2_DATA_OUT	 900L	/* max. clock low to data output valid */
-#else	/* I2C_SLOW_TIMING */
-/* I2C Standard Mode Timing */
-#define	T_CLK_LOW			4700L	/* clock low time in ns */
-#define	T_CLK_HIGH			4000L	/* clock high time in ns */
-#define T_DATA_IN_SETUP		 250L	/* data in Set-up Time */
-#define T_START_HOLD		4000L	/* start condition hold time */
-#define T_START_SETUP		4700L	/* start condition Set-up time */
-#define	T_STOP_SETUP		4000L	/* stop condition Set-up time */
-#define T_BUS_IDLE			4700L	/* time the bus must free after Tx */
-#endif	/* !I2C_SLOW_TIMING */
-
-#define NS2BCLK(x)	(((x)*125)/10000)
-
-/*
- * I2C Wire Operations
- *
- * About I2C_CLK_LOW():
- *
- * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting
- * clock to low, to prevent the ASIC and the I2C data client from driving the
- * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client
- * send an 'ACK'). See also Concentrator Bugreport No. 10192.
- */
-#define I2C_DATA_HIGH(IoC)	SK_I2C_SET_BIT(IoC, I2C_DATA)
-#define	I2C_DATA_LOW(IoC)	SK_I2C_CLR_BIT(IoC, I2C_DATA)
-#define	I2C_DATA_OUT(IoC)	SK_I2C_SET_BIT(IoC, I2C_DATA_DIR)
-#define	I2C_DATA_IN(IoC)	SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA)
-#define	I2C_CLK_HIGH(IoC)	SK_I2C_SET_BIT(IoC, I2C_CLK)
-#define	I2C_CLK_LOW(IoC)	SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR)
-#define	I2C_START_COND(IoC)	SK_I2C_CLR_BIT(IoC, I2C_CLK)
-
-#define NS2CLKT(x)	((x*125L)/10000)
-
-/*--------------- I2C Interface Register Functions --------------- */
-
-/*
- * sending one bit
- */
-void SkI2cSndBit(
-SK_IOC	IoC,	/* I/O Context */
-SK_U8	Bit)	/* Bit to send */
-{
-	I2C_DATA_OUT(IoC);
-	if (Bit) {
-		I2C_DATA_HIGH(IoC);
-	}
-	else {
-		I2C_DATA_LOW(IoC);
-	}
-	SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
-	I2C_CLK_HIGH(IoC);
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
-	I2C_CLK_LOW(IoC);
-}	/* SkI2cSndBit*/
-
-
-/*
- * Signal a start to the I2C Bus.
- *
- * A start is signaled when data goes to low in a high clock cycle.
- *
- * Ends with Clock Low.
- *
- * Status: not tested
- */
-void SkI2cStart(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/* Init data and Clock to output lines */
-	/* Set Data high */
-	I2C_DATA_OUT(IoC);
-	I2C_DATA_HIGH(IoC);
-	/* Set Clock high */
-	I2C_CLK_HIGH(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
-
-	/* Set Data Low */
-	I2C_DATA_LOW(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
-
-	/* Clock low without Data to Input */
-	I2C_START_COND(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
-}	/* SkI2cStart */
-
-
-void SkI2cStop(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/* Init data and Clock to output lines */
-	/* Set Data low */
-	I2C_DATA_OUT(IoC);
-	I2C_DATA_LOW(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
-
-	/* Set Clock high */
-	I2C_CLK_HIGH(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
-
-	/*
-	 * Set Data High:	Do it by setting the Data Line to Input.
-	 *			Because of a pull up resistor the Data Line
-	 *			floods to high.
-	 */
-	I2C_DATA_IN(IoC);
-
-	/*
-	 *	When I2C activity is stopped
-	 *	 o	DATA should be set to input and
-	 *	 o	CLOCK should be set to high!
-	 */
-	SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
-}	/* SkI2cStop */
-
-
-/*
- * Receive just one bit via the I2C bus.
- *
- * Note:	Clock must be set to LOW before calling this function.
- *
- * Returns The received bit.
- */
-int SkI2cRcvBit(
-SK_IOC	IoC)	/* I/O Context */
-{
-	int	Bit;
-	SK_U8	I2cSwCtrl;
-
-	/* Init data as input line */
-	I2C_DATA_IN(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
-
-	I2C_CLK_HIGH(IoC);
-
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
-
-	SK_I2C_GET_SW(IoC, &I2cSwCtrl);
-	
-	Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
-
-	I2C_CLK_LOW(IoC);
-	SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
-
-	return(Bit);
-}	/* SkI2cRcvBit */
-
-
-/*
- * Receive an ACK.
- *
- * returns	0 If acknowledged
- *		1 in case of an error
- */
-int SkI2cRcvAck(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/*
-	 * Received bit must be zero.
-	 */
-	return(SkI2cRcvBit(IoC) != 0);
-}	/* SkI2cRcvAck */
-
-
-/*
- * Send an NACK.
- */
-void SkI2cSndNAck(
-SK_IOC	IoC)	/* I/O Context */
-{
-	/*
-	 * Received bit must be zero.
-	 */
-	SkI2cSndBit(IoC, 1);
-}	/* SkI2cSndNAck */
-
-
-/*
- * Send an ACK.
- */
-void SkI2cSndAck(
-SK_IOC IoC)	/* I/O Context */
-{
-	/*
-	 * Received bit must be zero.
-	 */
-	SkI2cSndBit(IoC, 0);
-}	/* SkI2cSndAck */
-
-
-/*
- * Send one byte to the I2C device and wait for ACK.
- *
- * Return acknowleged status.
- */
-int SkI2cSndByte(
-SK_IOC	IoC,	/* I/O Context */
-int		Byte)	/* byte to send */
-{
-	int	i;
-
-	for (i = 0; i < 8; i++) {
-		if (Byte & (1<<(7-i))) {
-			SkI2cSndBit(IoC, 1);
-		}
-		else {
-			SkI2cSndBit(IoC, 0);
-		}
-	}
-
-	return(SkI2cRcvAck(IoC));
-}	/* SkI2cSndByte */
-
-
-/*
- * Receive one byte and ack it.
- *
- * Return byte.
- */
-int SkI2cRcvByte(
-SK_IOC	IoC,	/* I/O Context */
-int		Last)	/* Last Byte Flag */
-{
-	int	i;
-	int	Byte = 0;
-
-	for (i = 0; i < 8; i++) {
-		Byte <<= 1;
-		Byte |= SkI2cRcvBit(IoC);
-	}
-
-	if (Last) {
-		SkI2cSndNAck(IoC);
-	}
-	else {
-		SkI2cSndAck(IoC);
-	}
-
-	return(Byte);
-}	/* SkI2cRcvByte */
-
-
-/*
- * Start dialog and send device address
- *
- * Return 0 if acknowleged, 1 in case of an error
- */
-int	SkI2cSndDev(
-SK_IOC	IoC,	/* I/O Context */
-int		Addr,	/* Device Address */
-int		Rw)		/* Read / Write Flag */
-{
-	SkI2cStart(IoC);
-	Rw = ~Rw;
-	Rw &= I2C_WRITE;
-	return(SkI2cSndByte(IoC, (Addr<<1) | Rw));
-}	/* SkI2cSndDev */
-
-#endif /* SK_DIAG */
-
-/*----------------- I2C CTRL Register Functions ----------*/
-
-/*
- * waits for a completion of an I2C transfer
- *
- * returns	0:	success, transfer completes
- *			1:	error,	 transfer does not complete, I2C transfer
- *						 killed, wait loop terminated.
- */
-static int	SkI2cWait(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-int		Event)	/* complete event to wait for (I2C_READ or I2C_WRITE) */
-{
-	SK_U64	StartTime;
-	SK_U64	CurrentTime;
-	SK_U32	I2cCtrl;
-
-	StartTime = SkOsGetTime(pAC);
-	
-	do {
-		CurrentTime = SkOsGetTime(pAC);
-
-		if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) {
-			
-			SK_I2C_STOP(IoC);
-#ifndef SK_DIAG
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
-#endif /* !SK_DIAG */
-			return(1);
-		}
-		
-		SK_I2C_GET_CTL(IoC, &I2cCtrl);
-
-#ifdef xYUKON_DBG
-		printf("StartTime=%lu, CurrentTime=%lu\n",
-			StartTime, CurrentTime);
-		if (kbhit()) {
-			return(1);
-		}
-#endif /* YUKON_DBG */
-	
-	} while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
-
-	return(0);
-}	/* SkI2cWait */
-
-
-/*
- * waits for a completion of an I2C transfer
- *
- * Returns
- *	Nothing
- */
-void SkI2cWaitIrq(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-	SK_SENSOR	*pSen;
-	SK_U64		StartTime;
-	SK_U32		IrqSrc;
-
-	pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-
-	if (pSen->SenState == SK_SEN_IDLE) {
-		return;
-	}
-
-	StartTime = SkOsGetTime(pAC);
-	
-	do {
-		if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
-			
-			SK_I2C_STOP(IoC);
-#ifndef SK_DIAG
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
-#endif /* !SK_DIAG */
-			return;
-		}
-		
-		SK_IN32(IoC, B0_ISRC, &IrqSrc);
-
-	} while ((IrqSrc & IS_I2C_READY) == 0);
-
-	pSen->SenState = SK_SEN_IDLE;
-	return;
-}	/* SkI2cWaitIrq */
-
-/*
- * writes a single byte or 4 bytes into the I2C device
- *
- * returns	0:	success
- *			1:	error
- */
-static int SkI2cWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	I2cData,	/* I2C Data to write */
-int		I2cDev,		/* I2C Device Address */
-int		I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
-int		I2cReg,		/* I2C Device Register Address */
-int		I2cBurst)	/* I2C Burst Flag */
-{
-	SK_OUT32(IoC, B2_I2C_DATA, I2cData);
-	
-	SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst);
-	
-	return(SkI2cWait(pAC, IoC, I2C_WRITE));
-}	/* SkI2cWrite*/
-
-
-#ifdef	SK_DIAG
-/*
- * reads a single byte or 4 bytes from the I2C device
- *
- * returns	the word read
- */
-SK_U32 SkI2cRead(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		I2cDev,		/* I2C Device Address */
-int		I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
-int		I2cReg,		/* I2C Device Register Address */
-int		I2cBurst)	/* I2C Burst Flag */
-{
-	SK_U32	Data;
-
-	SK_OUT32(IoC, B2_I2C_DATA, 0);
-	SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst);
-	
-	if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
-		w_print("%s\n", SKERR_I2C_E002MSG);
-	}
-	
-	SK_IN32(IoC, B2_I2C_DATA, &Data);
-	
-	return(Data);
-}	/* SkI2cRead */
-#endif /* SK_DIAG */
-
-
-/*
- * read a sensor's value
- *
- * This function reads a sensor's value from the I2C sensor chip. The sensor
- * is defined by its index into the sensors database in the struct pAC points
- * to.
- * Returns
- *		1 if the read is completed
- *		0 if the read must be continued (I2C Bus still allocated)
- */
-static int	SkI2cReadSensor(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_SENSOR	*pSen)	/* Sensor to be read */
-{
-    if (pSen->SenRead != NULL) {
-        return((*pSen->SenRead)(pAC, IoC, pSen));
-    }
-	else {
-        return(0); /* no success */
-	}
-}	/* SkI2cReadSensor */
-
-/*
- * Do the Init state 0 initialization
- */
-static int SkI2cInit0(
-SK_AC	*pAC)	/* Adapter Context */
-{
-	int	i;
-
-	/* Begin with first sensor */
-	pAC->I2c.CurrSens = 0;
-	
-	/* Begin with timeout control for state machine */
-	pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
-	
-	/* Set sensor number to zero */
-	pAC->I2c.MaxSens = 0;
-
-#ifndef SK_DIAG
-	/* Initialize Number of Dummy Reads */
-	pAC->I2c.DummyReads = SK_MAX_SENSORS;
-#endif
-
-	for (i = 0; i < SK_MAX_SENSORS; i++) {
-		pAC->I2c.SenTable[i].SenDesc = "unknown";
-		pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN;
-		pAC->I2c.SenTable[i].SenThreErrHigh = 0;
-		pAC->I2c.SenTable[i].SenThreErrLow = 0;
-		pAC->I2c.SenTable[i].SenThreWarnHigh = 0;
-		pAC->I2c.SenTable[i].SenThreWarnLow = 0;
-		pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
-		pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE;
-		pAC->I2c.SenTable[i].SenValue = 0;
-		pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT;
-		pAC->I2c.SenTable[i].SenErrCts = 0;
-		pAC->I2c.SenTable[i].SenBegErrTS = 0;
-		pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
-		pAC->I2c.SenTable[i].SenRead = NULL;
-		pAC->I2c.SenTable[i].SenDev = 0;
-	}
-
-	/* Now we are "INIT data"ed */
-	pAC->I2c.InitLevel = SK_INIT_DATA;
-	return(0);
-}	/* SkI2cInit0*/
-
-
-/*
- * Do the init state 1 initialization
- *
- * initialize the following register of the LM80:
- * Configuration register:
- * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
- *
- * Interrupt Mask Register 1:
- * - all interrupts are Disabled (0xff)
- *
- * Interrupt Mask Register 2:
- * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
- *
- * Fan Divisor/RST_OUT register:
- * - Divisors set to 1 (bits 00), all others 0s.
- *
- * OS# Configuration/Temperature resolution Register:
- * - all 0s
- *
- */
-static int SkI2cInit1(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-    int i;
-    SK_U8 I2cSwCtrl;
-	SK_GEPORT *pPrt;	/* GIni Port struct pointer */
-
-	if (pAC->I2c.InitLevel != SK_INIT_DATA) {
-		/* ReInit not needed in I2C module */
-		return(0);
-	}
-
-    /* Set the Direction of I2C-Data Pin to IN */
-    SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA);
-    /* Check for 32-Bit Yukon with Low at I2C-Data Pin */
-	SK_I2C_GET_SW(IoC, &I2cSwCtrl);
-
-	if ((I2cSwCtrl & I2C_DATA) == 0) {
-		/* this is a 32-Bit board */
-		pAC->GIni.GIYukon32Bit = SK_TRUE;
-        return(0);
-    }
-
-	/* Check for 64 Bit Yukon without sensors */
-	if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) {
-        return(0);
-    }
-
-	(void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
-	
-	(void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV,
-		LM80_CFG, 0);
-	
-	/*
-	 * MaxSens has to be updated here, because PhyType is not
-	 * set when performing Init Level 0
-	 */
-    pAC->I2c.MaxSens = 5;
-	
-	pPrt = &pAC->GIni.GP[0];
-	
-	if (pAC->GIni.GIGenesis) {
-		if (pPrt->PhyType == SK_PHY_BCOM) {
-			if (pAC->GIni.GIMacsFound == 1) {
-				pAC->I2c.MaxSens += 1;
-			}
-			else {
-				pAC->I2c.MaxSens += 3;
-			}
-		}
-	}
-	else {
-		pAC->I2c.MaxSens += 3;
-	}
-	
-	for (i = 0; i < pAC->I2c.MaxSens; i++) {
-		switch (i) {
-		case 0:
-			pAC->I2c.SenTable[i].SenDesc = "Temperature";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN;
-			break;
-		case 1:
-			pAC->I2c.SenTable[i].SenDesc = "Voltage PCI";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN;
-			break;
-		case 2:
-			pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN;
-			pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO;
-			break;
-		case 3:
-			pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC";
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN;
-			break;
-		case 4:
-			if (pAC->GIni.GIGenesis) {
-				if (pPrt->PhyType == SK_PHY_BCOM) {
-					pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL";
-					pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
-					pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
-				}
-				else {
-					pAC->I2c.SenTable[i].SenDesc = "Voltage PMA";
-					pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
-					pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
-				}
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX";
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN;
-				if (pAC->GIni.GIVauxAvail) {
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
-				}
-				else {
-					pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR;
-					pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR;
-				}
-			}
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN;
-			break;
-		case 5:
-			if (pAC->GIni.GIGenesis) {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5";
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
-			}
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN;
-			break;
-		case 6:
-			if (pAC->GIni.GIGenesis) {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL";
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3";
-			}
-			pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-			pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
-			pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
-			pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
-			pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
-			pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN;
-			break;
-		case 7:
-			if (pAC->GIni.GIGenesis) {
-				pAC->I2c.SenTable[i].SenDesc = "Speed Fan";
-				pAC->I2c.SenTable[i].SenType = SK_SEN_FAN;
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR;
-				pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
-			}
-			else {
-				pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
-				pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
-				pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
-				pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
-				pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
-				pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
-				pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN;
-			}
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
-				SKERR_I2C_E001, SKERR_I2C_E001MSG);
-			break;
-		}
-
-		pAC->I2c.SenTable[i].SenValue = 0;
-		pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
-		pAC->I2c.SenTable[i].SenErrCts = 0;
-		pAC->I2c.SenTable[i].SenBegErrTS = 0;
-		pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
-		pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor;
-		pAC->I2c.SenTable[i].SenDev = LM80_ADDR;
-	}
-
-#ifndef SK_DIAG
-	pAC->I2c.DummyReads = pAC->I2c.MaxSens;
-#endif /* !SK_DIAG */
-	
-	/* Clear I2C IRQ */
-	SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-	
-	/* Now we are I/O initialized */
-	pAC->I2c.InitLevel = SK_INIT_IO;
-	return(0);
-}	/* SkI2cInit1 */
-
-
-/*
- * Init level 2: Start first sensor read.
- */
-static int SkI2cInit2(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-	int		ReadComplete;
-	SK_SENSOR	*pSen;
-
-	if (pAC->I2c.InitLevel != SK_INIT_IO) {
-		/* ReInit not needed in I2C module */
-		/* Init0 and Init2 not permitted */
-		return(0);
-	}
-
-	pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-	ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
-	if (ReadComplete) {
-		SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
-	}
-
-	/* Now we are correctly initialized */
-	pAC->I2c.InitLevel = SK_INIT_RUN;
-
-	return(0);
-}	/* SkI2cInit2*/
-
-
-/*
- * Initialize I2C devices
- *
- * Get the first voltage value and discard it.
- * Go into temperature read mode. A default pointer is not set.
- *
- * The things to be done depend on the init level in the parameter list:
- * Level 0:
- *	Initialize only the data structures. Do NOT access hardware.
- * Level 1:
- *	Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
- * Level 2:
- *	Everything is possible. Interrupts may be used from now on.
- *
- * return:
- *	0 = success
- *	other = error.
- */
-int	SkI2cInit(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context needed in levels 1 and 2 */
-int		Level)	/* Init Level */
-{
-
-	switch (Level) {
-	case SK_INIT_DATA:
-		return(SkI2cInit0(pAC));
-	case SK_INIT_IO:
-		return(SkI2cInit1(pAC, IoC));
-	case SK_INIT_RUN:
-		return(SkI2cInit2(pAC, IoC));
-	default:
-		break;
-	}
-
-	return(0);
-}	/* SkI2cInit */
-
-
-#ifndef SK_DIAG
-
-/*
- * Interrupt service function for the I2C Interface
- *
- * Clears the Interrupt source
- *
- * Reads the register and check it for sending a trap.
- *
- * Starts the timer if necessary.
- */
-void SkI2cIsr(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC)	/* I/O Context */
-{
-	SK_EVPARA	Para;
-
-	/* Clear I2C IRQ */
-	SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-
-	Para.Para64 = 0;
-	SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
-}	/* SkI2cIsr */
-
-
-/*
- * Check this sensors Value against the threshold and send events.
- */
-static void SkI2cCheckSensor(
-SK_AC		*pAC,	/* Adapter Context */
-SK_SENSOR	*pSen)
-{
-	SK_EVPARA	ParaLocal;
-	SK_BOOL		TooHigh;	/* Is sensor too high? */
-	SK_BOOL		TooLow;		/* Is sensor too low? */
-	SK_U64		CurrTime;	/* Current Time */
-	SK_BOOL		DoTrapSend;	/* We need to send a trap */
-	SK_BOOL		DoErrLog;	/* We need to log the error */
-	SK_BOOL		IsError;	/* We need to log the error */
-
-	/* Check Dummy Reads first */
-	if (pAC->I2c.DummyReads > 0) {
-		pAC->I2c.DummyReads--;
-		return;
-	}
-
-	/* Get the current time */
-	CurrTime = SkOsGetTime(pAC);
-
-	/* Set para to the most useful setting: The current sensor. */
-	ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
-
-	/* Check the Value against the thresholds. First: Error Thresholds */
-	TooHigh = (pSen->SenValue > pSen->SenThreErrHigh);
-	TooLow = (pSen->SenValue < pSen->SenThreErrLow);
-		
-	IsError = SK_FALSE;
-	if (TooHigh || TooLow) {
-		/* Error condition is satisfied */
-		DoTrapSend = SK_TRUE;
-		DoErrLog = SK_TRUE;
-
-		/* Now error condition is satisfied */
-		IsError = SK_TRUE;
-
-		if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
-			/* This state is the former one */
-
-			/* So check first whether we have to send a trap */
-			if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD >
-			    CurrTime) {
-				/*
-				 * Do NOT send the Trap. The hold back time
-				 * has to run out first.
-				 */
-				DoTrapSend = SK_FALSE;
-			}
-
-			/* Check now whether we have to log an Error */
-			if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD >
-			    CurrTime) {
-				/*
-				 * Do NOT log the error. The hold back time
-				 * has to run out first.
-				 */
-				DoErrLog = SK_FALSE;
-			}
-		}
-		else {
-			/* We came from a different state -> Set Begin Time Stamp */
-			pSen->SenBegErrTS = CurrTime;
-			pSen->SenErrFlag = SK_SEN_ERR_ERR;
-		}
-
-		if (DoTrapSend) {
-			/* Set current Time */
-			pSen->SenLastErrTrapTS = CurrTime;
-			pSen->SenErrCts++;
-
-			/* Queue PNMI Event */
-			SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
-				SK_PNMI_EVT_SEN_ERR_UPP :
-				SK_PNMI_EVT_SEN_ERR_LOW),
-				ParaLocal);
-		}
-
-		if (DoErrLog) {
-			/* Set current Time */
-			pSen->SenLastErrLogTS = CurrTime;
-
-			if (pSen->SenType == SK_SEN_TEMP) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG);
-			}
-			else if (pSen->SenType == SK_SEN_VOLT) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG);
-			}
-			else {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG);
-			}
-		}
-	}
-
-	/* Check the Value against the thresholds */
-	/* 2nd: Warning thresholds */
-	TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh);
-	TooLow = (pSen->SenValue < pSen->SenThreWarnLow);
-		
-	if (!IsError && (TooHigh || TooLow)) {
-		/* Error condition is satisfied */
-		DoTrapSend = SK_TRUE;
-		DoErrLog = SK_TRUE;
-
-		if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
-			/* This state is the former one */
-
-			/* So check first whether we have to send a trap */
-			if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) {
-				/*
-				 * Do NOT send the Trap. The hold back time
-				 * has to run out first.
-				 */
-				DoTrapSend = SK_FALSE;
-			}
-
-			/* Check now whether we have to log an Error */
-			if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) {
-				/*
-				 * Do NOT log the error. The hold back time
-				 * has to run out first.
-				 */
-				DoErrLog = SK_FALSE;
-			}
-		}
-		else {
-			/* We came from a different state -> Set Begin Time Stamp */
-			pSen->SenBegWarnTS = CurrTime;
-			pSen->SenErrFlag = SK_SEN_ERR_WARN;
-		}
-
-		if (DoTrapSend) {
-			/* Set current Time */
-			pSen->SenLastWarnTrapTS = CurrTime;
-			pSen->SenWarnCts++;
-
-			/* Queue PNMI Event */
-			SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
-				SK_PNMI_EVT_SEN_WAR_UPP :
-				SK_PNMI_EVT_SEN_WAR_LOW),
-				ParaLocal);
-		}
-
-		if (DoErrLog) {
-			/* Set current Time */
-			pSen->SenLastWarnLogTS = CurrTime;
-
-			if (pSen->SenType == SK_SEN_TEMP) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG);
-			}
-			else if (pSen->SenType == SK_SEN_VOLT) {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG);
-			}
-			else {
-				SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG);
-			}
-		}
-	}
-
-	/* Check for NO error at all */
-	if (!IsError && !TooHigh && !TooLow) {
-		/* Set o.k. Status if no error and no warning condition */
-		pSen->SenErrFlag = SK_SEN_ERR_OK;
-	}
-
-	/* End of check against the thresholds */
-
-	/* Bug fix AF: 16.Aug.2001: Correct the init base
-	 * of LM80 sensor.
-	 */
-	if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
-
-        pSen->SenInit = SK_SEN_DYN_INIT_NONE;
-
-		if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) {
-			/* 5V PCI-IO Voltage */
-			pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN;
-			pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR;
-		}
-		else {
-			/* 3.3V PCI-IO Voltage */
-			pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN;
-			pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR;
-		}
-	}
-	
-#ifdef TEST_ONLY
-    /* Dynamic thresholds also for VAUX of LM80 sensor */
-	if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
-
-        pSen->SenInit = SK_SEN_DYN_INIT_NONE;
-
-		/* 3.3V VAUX Voltage */
-		if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) {
-			pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
-			pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
-		}
-		/* 0V VAUX Voltage */
-		else {
-			pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
-			pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
-		}
-	}
-
-	/*
-	 * Check initialization state:
-	 * The VIO Thresholds need adaption
-	 */
-	if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
-	     pSen->SenValue > SK_SEN_WARNLOW2C &&
-	     pSen->SenValue < SK_SEN_WARNHIGH2) {
-		pSen->SenThreErrLow = SK_SEN_ERRLOW2C;
-		pSen->SenThreWarnLow = SK_SEN_WARNLOW2C;
-		pSen->SenInit = SK_TRUE;
-	}
-
-	if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
-	     pSen->SenValue > SK_SEN_WARNLOW2 &&
-	     pSen->SenValue < SK_SEN_WARNHIGH2C) {
-		pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C;
-		pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C;
-		pSen->SenInit = SK_TRUE;
-	}
-#endif
-
-	if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
-	}
-}	/* SkI2cCheckSensor */
-
-
-/*
- * The only Event to be served is the timeout event
- *
- */
-int	SkI2cEvent(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_U32		Event,	/* Module specific Event */
-SK_EVPARA	Para)	/* Event specific Parameter */
-{
-	int			ReadComplete;
-	SK_SENSOR	*pSen;
-	SK_U32		Time;
-	SK_EVPARA	ParaLocal;
-	int			i;
-
-	/* New case: no sensors */
-	if (pAC->I2c.MaxSens == 0) {
-		return(0);
-	}
-
-	switch (Event) {
-	case SK_I2CEV_IRQ:
-		pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-		ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
-		if (ReadComplete) {
-			/* Check sensor against defined thresholds */
-			SkI2cCheckSensor(pAC, pSen);
-
-			/* Increment Current sensor and set appropriate Timeout */
-			pAC->I2c.CurrSens++;
-			if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) {
-				pAC->I2c.CurrSens = 0;
-				Time = SK_I2C_TIM_LONG;
-			}
-			else {
-				Time = SK_I2C_TIM_SHORT;
-			}
-
-			/* Start Timer */
-			ParaLocal.Para64 = (SK_U64)0;
-
-			pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-			
-			SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-		}
-        else {
-			/* Start Timer */
-			ParaLocal.Para64 = (SK_U64)0;
-
-			pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
-
-            SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-		}
-		break;
-	case SK_I2CEV_TIM:
-		if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
-
-			ParaLocal.Para64 = (SK_U64)0;
-			SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
-
-			pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-			ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
-			if (ReadComplete) {
-				/* Check sensor against defined thresholds */
-				SkI2cCheckSensor(pAC, pSen);
-
-				/* Increment Current sensor and set appropriate Timeout */
-				pAC->I2c.CurrSens++;
-				if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
-					pAC->I2c.CurrSens = 0;
-					Time = SK_I2C_TIM_LONG;
-				}
-				else {
-					Time = SK_I2C_TIM_SHORT;
-				}
-
-				/* Start Timer */
-				ParaLocal.Para64 = (SK_U64)0;
-
-				pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
-				SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
-					SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-			}
-		}
-		else {
-			pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-			pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
-			SK_I2C_STOP(IoC);
-
-			/* Increment Current sensor and set appropriate Timeout */
-			pAC->I2c.CurrSens++;
-			if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
-				pAC->I2c.CurrSens = 0;
-				Time = SK_I2C_TIM_LONG;
-			}
-			else {
-				Time = SK_I2C_TIM_SHORT;
-			}
-
-			/* Start Timer */
-			ParaLocal.Para64 = (SK_U64)0;
-
-			pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
-			SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
-				SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
-		}
-		break;
-	case SK_I2CEV_CLEAR:
-		for (i = 0; i < SK_MAX_SENSORS; i++) {
-			pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
-			pAC->I2c.SenTable[i].SenErrCts = 0;
-			pAC->I2c.SenTable[i].SenWarnCts = 0;
-			pAC->I2c.SenTable[i].SenBegErrTS = 0;
-			pAC->I2c.SenTable[i].SenBegWarnTS = 0;
-			pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0;
-			pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0;
-			pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0;
-			pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0;
-		}
-		break;
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
-	}
-
-	return(0);
-}	/* SkI2cEvent*/
-
-#endif /* !SK_DIAG */
diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c
deleted file mode 100644
index a204f5b..0000000
--- a/drivers/net/sk98lin/sklm80.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/******************************************************************************
- *
- * Name:	sklm80.c
- * Project:	Gigabit Ethernet Adapters, TWSI-Module
- * Version:	$Revision: 1.22 $
- * Date:	$Date: 2003/10/20 09:08:21 $
- * Purpose:	Functions to access Voltage and Temperature Sensor (LM80)
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-	LM80 functions
-*/
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. ";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/lm80.h"
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#define	BREAK_OR_WAIT(pAC,IoC,Event)	break
-
-/*
- * read a sensors value (LM80 specific)
- *
- * This function reads a sensors value from the I2C sensor chip LM80.
- * The sensor is defined by its index into the sensors database in the struct
- * pAC points to.
- *
- * Returns	1 if the read is completed
- *		0 if the read must be continued (I2C Bus still allocated)
- */
-int SkLm80ReadSensor(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context needed in level 1 and 2 */
-SK_SENSOR	*pSen)	/* Sensor to be read */
-{
-	SK_I32		Value;
-
-	switch (pSen->SenState) {
-	case SK_SEN_IDLE:
-		/* Send address to ADDR register */
-		SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0);
-
-		pSen->SenState = SK_SEN_VALUE ;
-		BREAK_OR_WAIT(pAC, IoC, I2C_READ);
-	
-	case SK_SEN_VALUE:
-		/* Read value from data register */
-		SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
-		
-		Value &= 0xff; /* only least significant byte is valid */
-
-		/* Do NOT check the Value against the thresholds */
-		/* Checking is done in the calling instance */
-
-		if (pSen->SenType == SK_SEN_VOLT) {
-			/* Voltage sensor */
-			pSen->SenValue = Value * SK_LM80_VT_LSB;
-			pSen->SenState = SK_SEN_IDLE ;
-			return(1);
-		}
-
-		if (pSen->SenType == SK_SEN_FAN) {
-			if (Value != 0 && Value != 0xff) {
-				/* Fan speed counter */
-				pSen->SenValue = SK_LM80_FAN_FAKTOR/Value;
-			}
-			else {
-				/* Indicate Fan error */
-				pSen->SenValue = 0;
-			}
-			pSen->SenState = SK_SEN_IDLE ;
-			return(1);
-		}
-
-		/* First: correct the value: it might be negative */
-		if ((Value & 0x80) != 0) {
-			/* Value is negative */
-			Value = Value - 256;
-		}
-
-		/* We have a temperature sensor and need to get the signed extension.
-		 * For now we get the extension from the last reading, so in the normal
-		 * case we won't see flickering temperatures.
-		 */
-		pSen->SenValue = (Value * SK_LM80_TEMP_LSB) +
-			(pSen->SenValue % SK_LM80_TEMP_LSB);
-
-		/* Send address to ADDR register */
-		SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
-
-		pSen->SenState = SK_SEN_VALEXT ;
-		BREAK_OR_WAIT(pAC, IoC, I2C_READ);
-	
-	case SK_SEN_VALEXT:
-		/* Read value from data register */
-		SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
-		Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */
-
-		/* cut the LSB bit */
-		pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) *
-			SK_LM80_TEMP_LSB);
-
-		if (pSen->SenValue < 0) {
-			/* Value negative: The bit value must be subtracted */
-			pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
-		}
-		else {
-			/* Value positive: The bit value must be added */
-			pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
-		}
-
-		pSen->SenState = SK_SEN_IDLE ;
-		return(1);
-	
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG);
-		return(1);
-	}
-
-	/* Not completed */
-	return(0);
-}
-
diff --git a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c
deleted file mode 100644
index 0275b4f..0000000
--- a/drivers/net/sk98lin/skqueue.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/******************************************************************************
- *
- * Name:	skqueue.c
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.20 $
- * Date:	$Date: 2003/09/16 13:44:00 $
- * Purpose:	Management of an event queue.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-/*
- *	Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skqueue.c,v 1.20 2003/09/16 13:44:00 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/skqueue.h"		/* Queue Definitions */
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
-	Event queue management.
-
-	General Description:
-
- */
-intro()
-{}
-#endif
-
-#define PRINTF(a,b,c)
-
-/*
- * init event queue management
- *
- * Must be called during init level 0.
- */
-void	SkEventInit(
-SK_AC	*pAC,	/* Adapter context */
-SK_IOC	Ioc,	/* IO context */
-int		Level)	/* Init level */
-{
-	switch (Level) {
-	case SK_INIT_DATA:
-		pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue;
-		break;
-	default:
-		break;
-	}
-}
-
-/*
- * add event to queue
- */
-void	SkEventQueue(
-SK_AC		*pAC,	/* Adapters context */
-SK_U32		Class,	/* Event Class */
-SK_U32		Event,	/* Event to be queued */
-SK_EVPARA	Para)	/* Event parameter */
-{
-	pAC->Event.EvPut->Class = Class;
-	pAC->Event.EvPut->Event = Event;
-	pAC->Event.EvPut->Para = Para;
-	
-	if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT])
-		pAC->Event.EvPut = pAC->Event.EvQueue;
-
-	if (pAC->Event.EvPut == pAC->Event.EvGet) {
-		SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG);
-	}
-}
-
-/*
- * event dispatcher
- *	while event queue is not empty
- *		get event from queue
- *		send command to state machine
- *	end
- *	return error reported by individual Event function
- *		0 if no error occured.
- */
-int	SkEventDispatcher(
-SK_AC	*pAC,	/* Adapters Context */
-SK_IOC	Ioc)	/* Io context */
-{
-	SK_EVENTELEM	*pEv;	/* pointer into queue */
-	SK_U32			Class;
-	int			Rtv;
-
-	pEv = pAC->Event.EvGet;
-	
-	PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put);
-	
-	while (pEv != pAC->Event.EvPut) {
-		PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event);
-
-		switch (Class = pEv->Class) {
-#ifndef SK_USE_LAC_EV
-#ifndef SK_SLIM
-		case SKGE_RLMT:		/* RLMT Event */
-			Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_I2C:		/* I2C Event */
-			Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_PNMI:		/* PNMI Event */
-			Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif	/* not SK_SLIM */
-#endif	/* not SK_USE_LAC_EV */
-		case SKGE_DRV:		/* Driver Event */
-			Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#ifndef SK_USE_SW_TIMER
-		case SKGE_HWAC:
-			Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#else /* !SK_USE_SW_TIMER */
-        case SKGE_SWT :
-			Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif /* !SK_USE_SW_TIMER */
-#ifdef SK_USE_LAC_EV
-		case SKGE_LACP :
-			Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_RSF :
-			Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_MARKER :
-			Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-		case SKGE_FD :
-			Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif /* SK_USE_LAC_EV */
-#ifdef	SK_USE_CSUM
-		case SKGE_CSUM :
-			Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para);
-			break;
-#endif	/* SK_USE_CSUM */
-		default :
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG);
-			Rtv = 0;
-		}
-
-		if (Rtv != 0) {
-			return(Rtv);
-		}
-
-		if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT])
-			pEv = pAC->Event.EvQueue;
-
-		/* Renew get: it is used in queue_events to detect overruns */
-		pAC->Event.EvGet = pEv;
-	}
-
-	return(0);
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c
deleted file mode 100644
index be8d1cc..0000000
--- a/drivers/net/sk98lin/skrlmt.c
+++ /dev/null
@@ -1,3257 +0,0 @@
-/******************************************************************************
- *
- * Name:	skrlmt.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.69 $
- * Date:	$Date: 2003/04/15 09:39:22 $
- * Purpose:	Manage links on SK-NET Adapters, esp. redundant ones.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters.
- * It is mainly intended for adapters with more than one link.
- * For such adapters, this module realizes Redundant Link ManagemenT (RLMT).
- *
- * Include File Hierarchy:
- *
- *	"skdrv1st.h"
- *	"skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef	lint
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skrlmt.c,v 1.69 2003/04/15 09:39:22 tschilli Exp $ (C) Marvell.";
-#endif	/* !defined(lint) */
-
-#define __SKRLMT_C
-
-#ifdef __cplusplus
-extern "C" {
-#endif	/* cplusplus */
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* defines ********************************************************************/
-
-#ifndef SK_HWAC_LINK_LED
-#define SK_HWAC_LINK_LED(a,b,c,d)
-#endif	/* !defined(SK_HWAC_LINK_LED) */
-
-#ifndef DEBUG
-#define RLMT_STATIC	static
-#else	/* DEBUG */
-#define RLMT_STATIC
-
-#ifndef SK_LITTLE_ENDIAN
-/* First 32 bits */
-#define OFFS_LO32	1
-
-/* Second 32 bits */
-#define OFFS_HI32	0
-#else	/* SK_LITTLE_ENDIAN */
-/* First 32 bits */
-#define OFFS_LO32	0
-
-/* Second 32 bits */
-#define OFFS_HI32	1
-#endif	/* SK_LITTLE_ENDIAN */
-
-#endif	/* DEBUG */
-
-/* ----- Private timeout values ----- */
-
-#define SK_RLMT_MIN_TO_VAL			   125000	/* 1/8 sec. */
-#define SK_RLMT_DEF_TO_VAL			  1000000	/* 1 sec. */
-#define SK_RLMT_PORTDOWN_TIM_VAL	   900000	/* another 0.9 sec. */
-#define SK_RLMT_PORTSTART_TIM_VAL	   100000	/* 0.1 sec. */
-#define SK_RLMT_PORTUP_TIM_VAL		  2500000	/* 2.5 sec. */
-#define SK_RLMT_SEG_TO_VAL			900000000	/* 15 min. */
-
-/* Assume tick counter increment is 1 - may be set OS-dependent. */
-#ifndef SK_TICK_INCR
-#define SK_TICK_INCR	SK_CONSTU64(1)
-#endif	/* !defined(SK_TICK_INCR) */
-
-/*
- * Amount that a time stamp must be later to be recognized as "substantially
- * later". This is about 1/128 sec, but above 1 tick counter increment.
- */
-#define SK_RLMT_BC_DELTA		(1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \
-									(SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR))
-
-/* ----- Private RLMT defaults ----- */
-
-#define SK_RLMT_DEF_PREF_PORT	0					/* "Lower" port. */
-#define SK_RLMT_DEF_MODE 		SK_RLMT_CHECK_LINK	/* Default RLMT Mode. */
-
-/* ----- Private RLMT checking states ----- */
-
-#define SK_RLMT_RCS_SEG			1		/* RLMT Check State: check seg. */
-#define SK_RLMT_RCS_START_SEG	2		/* RLMT Check State: start check seg. */
-#define SK_RLMT_RCS_SEND_SEG	4		/* RLMT Check State: send BPDU packet */
-#define SK_RLMT_RCS_REPORT_SEG	8		/* RLMT Check State: report seg. */
-
-/* ----- Private PORT checking states ----- */
-
-#define SK_RLMT_PCS_TX			1		/* Port Check State: check tx. */
-#define SK_RLMT_PCS_RX			2		/* Port Check State: check rx. */
-
-/* ----- Private PORT events ----- */
-
-/* Note: Update simulation when changing these. */
-#define SK_RLMT_PORTSTART_TIM	1100	/* Port start timeout. */
-#define SK_RLMT_PORTUP_TIM		1101	/* Port can now go up. */
-#define SK_RLMT_PORTDOWN_RX_TIM	1102	/* Port did not receive once ... */
-#define SK_RLMT_PORTDOWN		1103	/* Port went down. */
-#define SK_RLMT_PORTDOWN_TX_TIM	1104	/* Partner did not receive ... */
-
-/* ----- Private RLMT events ----- */
-
-/* Note: Update simulation when changing these. */
-#define SK_RLMT_TIM				2100	/* RLMT timeout. */
-#define SK_RLMT_SEG_TIM			2101	/* RLMT segmentation check timeout. */
-
-#define TO_SHORTEN(tim)	((tim) / 2)
-
-/* Error numbers and messages. */
-#define SKERR_RLMT_E001		(SK_ERRBASE_RLMT + 0)
-#define SKERR_RLMT_E001_MSG	"No Packet."
-#define SKERR_RLMT_E002		(SKERR_RLMT_E001 + 1)
-#define SKERR_RLMT_E002_MSG	"Short Packet."
-#define SKERR_RLMT_E003		(SKERR_RLMT_E002 + 1)
-#define SKERR_RLMT_E003_MSG	"Unknown RLMT event."
-#define SKERR_RLMT_E004		(SKERR_RLMT_E003 + 1)
-#define SKERR_RLMT_E004_MSG	"PortsUp incorrect."
-#define SKERR_RLMT_E005		(SKERR_RLMT_E004 + 1)
-#define SKERR_RLMT_E005_MSG	\
- "Net seems to be segmented (different root bridges are reported on the ports)."
-#define SKERR_RLMT_E006		(SKERR_RLMT_E005 + 1)
-#define SKERR_RLMT_E006_MSG	"Duplicate MAC Address detected."
-#define SKERR_RLMT_E007		(SKERR_RLMT_E006 + 1)
-#define SKERR_RLMT_E007_MSG	"LinksUp incorrect."
-#define SKERR_RLMT_E008		(SKERR_RLMT_E007 + 1)
-#define SKERR_RLMT_E008_MSG	"Port not started but link came up."
-#define SKERR_RLMT_E009		(SKERR_RLMT_E008 + 1)
-#define SKERR_RLMT_E009_MSG	"Corrected illegal setting of Preferred Port."
-#define SKERR_RLMT_E010		(SKERR_RLMT_E009 + 1)
-#define SKERR_RLMT_E010_MSG	"Ignored illegal Preferred Port."
-
-/* LLC field values. */
-#define LLC_COMMAND_RESPONSE_BIT		1
-#define LLC_TEST_COMMAND				0xE3
-#define LLC_UI							0x03
-
-/* RLMT Packet fields. */
-#define	SK_RLMT_DSAP					0
-#define	SK_RLMT_SSAP					0
-#define SK_RLMT_CTRL					(LLC_TEST_COMMAND)
-#define SK_RLMT_INDICATOR0				0x53	/* S */
-#define SK_RLMT_INDICATOR1				0x4B	/* K */
-#define SK_RLMT_INDICATOR2				0x2D	/* - */
-#define SK_RLMT_INDICATOR3				0x52	/* R */
-#define SK_RLMT_INDICATOR4				0x4C	/* L */
-#define SK_RLMT_INDICATOR5				0x4D	/* M */
-#define SK_RLMT_INDICATOR6				0x54	/* T */
-#define SK_RLMT_PACKET_VERSION			0
-
-/* RLMT SPT Flag values. */
-#define	SK_RLMT_SPT_FLAG_CHANGE			0x01
-#define	SK_RLMT_SPT_FLAG_CHANGE_ACK		0x80
-
-/* RLMT SPT Packet fields. */
-#define	SK_RLMT_SPT_DSAP				0x42
-#define	SK_RLMT_SPT_SSAP				0x42
-#define SK_RLMT_SPT_CTRL				(LLC_UI)
-#define	SK_RLMT_SPT_PROTOCOL_ID0		0x00
-#define	SK_RLMT_SPT_PROTOCOL_ID1		0x00
-#define	SK_RLMT_SPT_PROTOCOL_VERSION_ID	0x00
-#define	SK_RLMT_SPT_BPDU_TYPE			0x00
-#define	SK_RLMT_SPT_FLAGS				0x00	/* ?? */
-#define	SK_RLMT_SPT_ROOT_ID0			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_ROOT_ID1			0xFF	/* Lowest possible priority. */
-
-/* Remaining 6 bytes will be the current port address. */
-#define	SK_RLMT_SPT_ROOT_PATH_COST0		0x00
-#define	SK_RLMT_SPT_ROOT_PATH_COST1		0x00
-#define	SK_RLMT_SPT_ROOT_PATH_COST2		0x00
-#define	SK_RLMT_SPT_ROOT_PATH_COST3		0x00
-#define	SK_RLMT_SPT_BRIDGE_ID0			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_BRIDGE_ID1			0xFF	/* Lowest possible priority. */
-
-/* Remaining 6 bytes will be the current port address. */
-#define	SK_RLMT_SPT_PORT_ID0			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_PORT_ID1			0xFF	/* Lowest possible priority. */
-#define	SK_RLMT_SPT_MSG_AGE0			0x00
-#define	SK_RLMT_SPT_MSG_AGE1			0x00
-#define	SK_RLMT_SPT_MAX_AGE0			0x00
-#define	SK_RLMT_SPT_MAX_AGE1			0xFF
-#define	SK_RLMT_SPT_HELLO_TIME0			0x00
-#define	SK_RLMT_SPT_HELLO_TIME1			0xFF
-#define	SK_RLMT_SPT_FWD_DELAY0			0x00
-#define	SK_RLMT_SPT_FWD_DELAY1			0x40
-
-/* Size defines. */
-#define SK_RLMT_MIN_PACKET_SIZE			34
-#define SK_RLMT_MAX_PACKET_SIZE			(SK_RLMT_MAX_TX_BUF_SIZE)
-#define SK_PACKET_DATA_LEN				(SK_RLMT_MAX_PACKET_SIZE - \
-										SK_RLMT_MIN_PACKET_SIZE)
-
-/* ----- RLMT packet types ----- */
-#define SK_PACKET_ANNOUNCE				1	/* Port announcement. */
-#define SK_PACKET_ALIVE					2	/* Alive packet to port. */
-#define SK_PACKET_ADDR_CHANGED			3	/* Port address changed. */
-#define SK_PACKET_CHECK_TX				4	/* Check your tx line. */
-
-#ifdef SK_LITTLE_ENDIAN
-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \
-	SK_U8	*_Addr = (SK_U8*)(Addr); \
-	SK_U16	_Val = (SK_U16)(Val); \
-	*_Addr++ = (SK_U8)(_Val >> 8); \
-	*_Addr = (SK_U8)(_Val & 0xFF); \
-}
-#endif	/* SK_LITTLE_ENDIAN */
-
-#ifdef SK_BIG_ENDIAN
-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))
-#endif	/* SK_BIG_ENDIAN */
-
-#define AUTONEG_FAILED	SK_FALSE
-#define AUTONEG_SUCCESS	SK_TRUE
-
-
-/* typedefs *******************************************************************/
-
-/* RLMT packet.  Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */
-typedef struct s_RlmtPacket {
-	SK_U8	DstAddr[SK_MAC_ADDR_LEN];
-	SK_U8	SrcAddr[SK_MAC_ADDR_LEN];
-	SK_U8	TypeLen[2];
-	SK_U8	DSap;
-	SK_U8	SSap;
-	SK_U8	Ctrl;
-	SK_U8	Indicator[7];
-	SK_U8	RlmtPacketType[2];
-	SK_U8	Align1[2];
-	SK_U8	Random[4];				/* Random value of requesting(!) station. */
-	SK_U8	RlmtPacketVersion[2];	/* RLMT Packet version. */
-	SK_U8	Data[SK_PACKET_DATA_LEN];
-} SK_RLMT_PACKET;
-
-typedef struct s_SpTreeRlmtPacket {
-	SK_U8	DstAddr[SK_MAC_ADDR_LEN];
-	SK_U8	SrcAddr[SK_MAC_ADDR_LEN];
-	SK_U8	TypeLen[2];
-	SK_U8	DSap;
-	SK_U8	SSap;
-	SK_U8	Ctrl;
-	SK_U8	ProtocolId[2];
-	SK_U8	ProtocolVersionId;
-	SK_U8	BpduType;
-	SK_U8	Flags;
-	SK_U8	RootId[8];
-	SK_U8	RootPathCost[4];
-	SK_U8	BridgeId[8];
-	SK_U8	PortId[2];
-	SK_U8	MessageAge[2];
-	SK_U8	MaxAge[2];
-	SK_U8	HelloTime[2];
-	SK_U8	ForwardDelay[2];
-} SK_SPTREE_PACKET;
-
-/* global variables ***********************************************************/
-
-SK_MAC_ADDR	SkRlmtMcAddr =	{{0x01,  0x00,  0x5A,  0x52,  0x4C,  0x4D}};
-SK_MAC_ADDR	BridgeMcAddr =	{{0x01,  0x80,  0xC2,  0x00,  0x00,  0x00}};
-
-/* local variables ************************************************************/
-
-/* None. */
-
-/* functions ******************************************************************/
-
-RLMT_STATIC void	SkRlmtCheckSwitch(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	NetIdx);
-RLMT_STATIC void	SkRlmtCheckSeg(
-	SK_AC	*pAC,
-	SK_IOC	IoC,
-	SK_U32	NetIdx);
-RLMT_STATIC void	SkRlmtEvtSetNets(
-	SK_AC		*pAC,
-	SK_IOC		IoC,
-	SK_EVPARA	Para);
-
-/******************************************************************************
- *
- *	SkRlmtInit - initialize data, set state to init
- *
- * Description:
- *
- *	SK_INIT_DATA
- *	============
- *
- *	This routine initializes all RLMT-related variables to a known state.
- *	The initial state is SK_RLMT_RS_INIT.
- *	All ports are initialized to SK_RLMT_PS_INIT.
- *
- *
- *	SK_INIT_IO
- *	==========
- *
- *	Nothing.
- *
- *
- *	SK_INIT_RUN
- *	===========
- *
- *	Determine the adapter's random value.
- *	Set the hw registers, the "logical MAC address", the
- *	RLMT multicast address, and eventually the BPDU multicast address.
- *
- * Context:
- *	init, pageable
- *
- * Returns:
- *	Nothing.
- */
-void	SkRlmtInit(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-int		Level)	/* Initialization Level */
-{
-	SK_U32		i, j;
-	SK_U64		Random;
-	SK_EVPARA	Para;
-    SK_MAC_ADDR		VirtualMacAddress;
-    SK_MAC_ADDR		PhysicalAMacAddress;
-    SK_BOOL		VirtualMacAddressSet;
-    SK_BOOL		PhysicalAMacAddressSet;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
-		("RLMT Init level %d.\n", Level))
-
-	switch (Level) {
-	case SK_INIT_DATA:	/* Initialize data structures. */
-		SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT));
-
-		for (i = 0; i < SK_MAX_MACS; i++) {
-			pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT;
-			pAC->Rlmt.Port[i].LinkDown = SK_TRUE;
-			pAC->Rlmt.Port[i].PortDown = SK_TRUE;
-			pAC->Rlmt.Port[i].PortStarted = SK_FALSE;
-			pAC->Rlmt.Port[i].PortNoRx = SK_FALSE;
-			pAC->Rlmt.Port[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Port[i].PortNumber = i;
-			pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0];
-			pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i];
-		}
-
-		pAC->Rlmt.NumNets = 1;
-		for (i = 0; i < SK_MAX_NETS; i++) {
-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* Automatic. */
-			/* Just assuming. */
-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
-			pAC->Rlmt.Net[i].NetNumber = i;
-		}
-
-		pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0];
-		pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1];
-#if SK_MAX_NETS > 1
-		pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1];
-#endif	/* SK_MAX_NETS > 1 */
-		break;
-
-	case SK_INIT_IO:	/* GIMacsFound first available here. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
-			("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound))
-
-		pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
-
-		/* Initialize HW registers? */
-		if (pAC->GIni.GIMacsFound == 1) {
-			Para.Para32[0] = SK_RLMT_MODE_CLS;
-			Para.Para32[1] = 0;
-			(void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para);
-		}
-		break;
-
-	case SK_INIT_RUN:
-		/* Ensure RLMT is set to one net. */
-		if (pAC->Rlmt.NumNets > 1) {
-			Para.Para32[0] = 1;
-			Para.Para32[1] = -1;
-			SkRlmtEvtSetNets(pAC, IoC, Para);
-		}
-
-		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-			Random = SkOsGetTime(pAC);
-			*(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random;
-
-			for (j = 0; j < 4; j++) {
-				pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort->
-					CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j];
-			}
-
-			(void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
-			
-			/* Add RLMT MC address. */
-			(void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT);
-
-			if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) {
-				/* Add BPDU MC address. */
-				(void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT);
-			}
-
-			(void)SkAddrMcUpdate(pAC, IoC, i);
-		}
-
-    	VirtualMacAddressSet = SK_FALSE;
-		/* Read virtual MAC address from Control Register File. */
-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-			
-            SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]);
-            VirtualMacAddressSet |= VirtualMacAddress.a[j];
-		}
-    	
-        PhysicalAMacAddressSet = SK_FALSE;
-		/* Read physical MAC address for MAC A from Control Register File. */
-		for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-			
-            SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]);
-            PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j];
-		}
-
-        /* check if the two mac addresses contain reasonable values */
-        if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) {
-
-            pAC->Rlmt.RlmtOff = SK_TRUE;
-        }
-
-        /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD
-           and the RLMT_LOOKAHEAD macros */
-        else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) {
-
-            pAC->Rlmt.RlmtOff = SK_TRUE;
-        }
-		else {
-			pAC->Rlmt.RlmtOff = SK_FALSE;
-		}
-		break;
-
-	default:	/* error */
-		break;
-	}
-	return;
-}	/* SkRlmtInit */
-
-
-/******************************************************************************
- *
- *	SkRlmtBuildCheckChain - build the check chain
- *
- * Description:
- *	This routine builds the local check chain:
- *	- Each port that is up checks the next port.
- *	- The last port that is up checks the first port that is up.
- *
- * Notes:
- *	- Currently only local ports are considered when building the chain.
- *	- Currently the SuspectState is just reset;
- *	  it would be better to save it ...
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtBuildCheckChain(
-SK_AC	*pAC,	/* Adapter Context */
-SK_U32	NetIdx)	/* Net Number */
-{
-	SK_U32			i;
-	SK_U32			NumMacsUp;
-	SK_RLMT_PORT *	FirstMacUp;
-	SK_RLMT_PORT *	PrevMacUp;
-
-	FirstMacUp	= NULL;
-	PrevMacUp	= NULL;
-	
-	if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
-		for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) {
-			pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
-		}
-		return;	/* Done. */
-	}
-			
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SkRlmtBuildCheckChain.\n"))
-
-	NumMacsUp = 0;
-
-	for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
-		pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
-		pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0;
-		pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &=
-			~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX);
-
-		/*
-		 * If more than two links are detected we should consider
-		 * checking at least two other ports:
-		 * 1. the next port that is not LinkDown and
-		 * 2. the next port that is not PortDown.
-		 */
-		if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
-			if (NumMacsUp == 0) {
-				FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
-			}
-			else {
-				PrevMacUp->PortCheck[
-					pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr =
-					pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress;
-				PrevMacUp->PortCheck[
-					PrevMacUp->PortsChecked].SuspectTx = SK_FALSE;
-				PrevMacUp->PortsChecked++;
-			}
-			PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
-			NumMacsUp++;
-		}
-	}
-
-	if (NumMacsUp > 1) {
-		PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr =
-			FirstMacUp->AddrPort->CurrentMacAddress;
-		PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx =
-			SK_FALSE;
-		PrevMacUp->PortsChecked++;
-	}
-
-#ifdef DEBUG
-	for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Port %d checks %d other ports: %2X.\n", i,
-				pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked,
-				pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5]))
-	}
-#endif	/* DEBUG */
-
-	return;
-}	/* SkRlmtBuildCheckChain */
-
-
-/******************************************************************************
- *
- *	SkRlmtBuildPacket - build an RLMT packet
- *
- * Description:
- *	This routine sets up an RLMT packet.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	NULL or pointer to RLMT mbuf
- */
-RLMT_STATIC SK_MBUF	*SkRlmtBuildPacket(
-SK_AC		*pAC,		/* Adapter Context */
-SK_IOC		IoC,		/* I/O Context */
-SK_U32		PortNumber,	/* Sending port */
-SK_U16		PacketType,	/* RLMT packet type */
-SK_MAC_ADDR	*SrcAddr,	/* Source address */
-SK_MAC_ADDR	*DestAddr)	/* Destination address */
-{
-	int		i;
-	SK_U16		Length;
-	SK_MBUF		*pMb;
-	SK_RLMT_PACKET	*pPacket;
-
-#ifdef DEBUG
-	SK_U8	CheckSrc  = 0;
-	SK_U8	CheckDest = 0;
-	
-	for (i = 0; i < SK_MAC_ADDR_LEN; ++i) {
-		CheckSrc  |= SrcAddr->a[i];
-		CheckDest |= DestAddr->a[i];
-	}
-
-	if ((CheckSrc == 0) || (CheckDest == 0)) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR,
-			("SkRlmtBuildPacket: Invalid %s%saddr.\n",
-			 (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : "")))
-	}
-#endif
-
-	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) {
-		pPacket = (SK_RLMT_PACKET*)pMb->pData;
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-			pPacket->DstAddr[i] = DestAddr->a[i];
-			pPacket->SrcAddr[i] = SrcAddr->a[i];
-		}
-		pPacket->DSap = SK_RLMT_DSAP;
-		pPacket->SSap = SK_RLMT_SSAP;
-		pPacket->Ctrl = SK_RLMT_CTRL;
-		pPacket->Indicator[0] = SK_RLMT_INDICATOR0;
-		pPacket->Indicator[1] = SK_RLMT_INDICATOR1;
-		pPacket->Indicator[2] = SK_RLMT_INDICATOR2;
-		pPacket->Indicator[3] = SK_RLMT_INDICATOR3;
-		pPacket->Indicator[4] = SK_RLMT_INDICATOR4;
-		pPacket->Indicator[5] = SK_RLMT_INDICATOR5;
-		pPacket->Indicator[6] = SK_RLMT_INDICATOR6;
-
-		SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]);
-
-		for (i = 0; i < 4; i++) {
-			pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i];
-		}
-		
-		SK_U16_TO_NETWORK_ORDER(
-			SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]);
-
-		for (i = 0; i < SK_PACKET_DATA_LEN; i++) {
-			pPacket->Data[i] = 0x00;
-		}
-
-		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */
-		pMb->Length = Length;
-		pMb->PortIdx = PortNumber;
-		Length -= 14;
-		SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]);
-
-		if (PacketType == SK_PACKET_ALIVE) {
-			pAC->Rlmt.Port[PortNumber].TxHelloCts++;
-		}
-	}
-
-	return (pMb);
-}	/* SkRlmtBuildPacket */
-
-
-/******************************************************************************
- *
- *	SkRlmtBuildSpanningTreePacket - build spanning tree check packet
- *
- * Description:
- *	This routine sets up a BPDU packet for spanning tree check.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	NULL or pointer to RLMT mbuf
- */
-RLMT_STATIC SK_MBUF	*SkRlmtBuildSpanningTreePacket(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Sending port */
-{
-	unsigned			i;
-	SK_U16				Length;
-	SK_MBUF				*pMb;
-	SK_SPTREE_PACKET	*pSPacket;
-
-	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) !=
-		NULL) {
-		pSPacket = (SK_SPTREE_PACKET*)pMb->pData;
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-			pSPacket->DstAddr[i] = BridgeMcAddr.a[i];
-			pSPacket->SrcAddr[i] =
-				pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
-		}
-		pSPacket->DSap = SK_RLMT_SPT_DSAP;
-		pSPacket->SSap = SK_RLMT_SPT_SSAP;
-		pSPacket->Ctrl = SK_RLMT_SPT_CTRL;
-
-		pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0;
-		pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1;
-		pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID;
-		pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE;
-		pSPacket->Flags = SK_RLMT_SPT_FLAGS;
-		pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0;
-		pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1;
-		pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0;
-		pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1;
-		pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2;
-		pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3;
-		pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0;
-		pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1;
-
-		/*
-		 * Use logical MAC address as bridge ID and filter these packets
-		 * on receive.
-		 */
-		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-			pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] =
-				pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber].
-					CurrentMacAddress.a[i];
-		}
-		pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0;
-		pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1;
-		pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0;
-		pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1;
-		pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0;
-		pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1;
-		pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0;
-		pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1;
-		pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0;
-		pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1;
-
-		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */
-		pMb->Length = Length;
-		pMb->PortIdx = PortNumber;
-		Length -= 14;
-		SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]);
-
-		pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++;
-	}
-
-	return (pMb);
-}	/* SkRlmtBuildSpanningTreePacket */
-
-
-/******************************************************************************
- *
- *	SkRlmtSend - build and send check packets
- *
- * Description:
- *	Depending on the RLMT state and the checking state, several packets
- *	are sent through the indicated port.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtSend(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Sending port */
-{
-	unsigned	j;
-	SK_EVPARA	Para;
-	SK_RLMT_PORT	*pRPort;
-
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-	if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
-		if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) {
-			/* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */
-			if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
-				SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
-				&SkRlmtMcAddr)) != NULL) {
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-		}
-		else {
-			/*
-			 * Send a directed RLMT packet to all ports that are
-			 * checked by the indicated port.
-			 */
-			for (j = 0; j < pRPort->PortsChecked; j++) {
-				if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
-					SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
-					&pRPort->PortCheck[j].CheckAddr)) != NULL) {
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-				}
-			}
-		}
-	}
-
-	if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
-		(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) {
-		/*
-		 * Send a BPDU packet to make a connected switch tell us
-		 * the correct root bridge.
-		 */
-		if ((Para.pParaPtr =
-			SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) {
-			pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG;
-			pRPort->RootIdSet = SK_FALSE;
-
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX,
-				("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber))
-		}
-	}
-	return;
-}	/* SkRlmtSend */
-
-
-/******************************************************************************
- *
- *	SkRlmtPortReceives - check if port is (going) down and bring it up
- *
- * Description:
- *	This routine checks if a port who received a non-BPDU packet
- *	needs to go up or needs to be stopped going down.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtPortReceives(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	PortNumber)		/* Port to check */
-{
-	SK_RLMT_PORT	*pRPort;
-	SK_EVPARA		Para;
-
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-	pRPort->PortNoRx = SK_FALSE;
-
-	if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
-		!(pRPort->CheckingState & SK_RLMT_PCS_TX)) {
-		/*
-		 * Port is marked down (rx), but received a non-BPDU packet.
-		 * Bring it up.
-		 */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Received on PortDown.\n"))
-
-		pRPort->PortState = SK_RLMT_PS_GOING_UP;
-		pRPort->GuTimeStamp = SkOsGetTime(pAC);
-		Para.Para32[0] = PortNumber;
-		Para.Para32[1] = (SK_U32)-1;
-		SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
-			SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para);
-		pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
-		/* pAC->Rlmt.CheckSwitch = SK_TRUE; */
-		SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-	}	/* PortDown && !SuspectTx */
-	else if (pRPort->CheckingState & SK_RLMT_PCS_RX) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Stop bringing port down.\n"))
-		SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
-		pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
-		/* pAC->Rlmt.CheckSwitch = SK_TRUE; */
-		SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-	}	/* PortGoingDown */
-
-	return;
-}	/* SkRlmtPortReceives */
-
-
-/******************************************************************************
- *
- *	SkRlmtPacketReceive - receive a packet for closer examination
- *
- * Description:
- *	This routine examines a packet more closely than SK_RLMT_LOOKAHEAD.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtPacketReceive(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-SK_MBUF	*pMb)	/* Received packet */
-{
-#ifdef xDEBUG
-	extern	void DumpData(char *p, int size);
-#endif	/* DEBUG */
-	int					i;
-	unsigned			j;
-	SK_U16				PacketType;
-	SK_U32				PortNumber;
-	SK_ADDR_PORT		*pAPort;
-	SK_RLMT_PORT		*pRPort;
-	SK_RLMT_PACKET		*pRPacket;
-	SK_SPTREE_PACKET	*pSPacket;
-	SK_EVPARA			Para;
-
-	PortNumber	= pMb->PortIdx;
-	pAPort = &pAC->Addr.Port[PortNumber];
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-		("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber))
-
-	pRPacket = (SK_RLMT_PACKET*)pMb->pData;
-	pSPacket = (SK_SPTREE_PACKET*)pRPacket;
-
-#ifdef xDEBUG
-	DumpData((char *)pRPacket, 32);
-#endif	/* DEBUG */
-
-	if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) {
-		SkRlmtPortReceives(pAC, IoC, PortNumber);
-	}
-	
-	/* Check destination address. */
-
-	if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) &&
-		!SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) &&
-		!SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) {
-
-		/* Not sent to current MAC or registered MC address => Trash it. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Not for me.\n"))
-
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		return;
-	}
-	else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) {
-
-		/*
-		 * Was sent by same port (may happen during port switching
-		 * or in case of duplicate MAC addresses).
-		 */
-
-		/*
-		 * Check for duplicate address here:
-		 * If Packet.Random != My.Random => DupAddr.
-		 */
-		for (i = 3; i >= 0; i--) {
-			if (pRPort->Random[i] != pRPacket->Random[i]) {
-				break;
-			}
-		}
-
-		/*
-		 * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply
-		 * packets (they have the LLC_COMMAND_RESPONSE_BIT set in
-		 * pRPacket->SSap).
-		 */
-		if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP &&
-			pRPacket->Ctrl == SK_RLMT_CTRL &&
-			pRPacket->SSap == SK_RLMT_SSAP &&
-			pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
-			pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
-			pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
-			pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
-			pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
-			pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
-			pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Duplicate MAC Address.\n"))
-
-			/* Error Log entry. */
-			SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG);
-		}
-		else {
-			/* Simply trash it. */
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Sent by me.\n"))
-		}
-
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		return;
-	}
-
-	/* Check SuspectTx entries. */
-	if (pRPort->PortsSuspect > 0) {
-		for (j = 0; j < pRPort->PortsChecked; j++) {
-			if (pRPort->PortCheck[j].SuspectTx &&
-				SK_ADDR_EQUAL(
-					pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) {
-				pRPort->PortCheck[j].SuspectTx = SK_FALSE;
-				pRPort->PortsSuspect--;
-				break;
-			}
-		}
-	}
-
-	/* Determine type of packet. */
-	if (pRPacket->DSap == SK_RLMT_DSAP &&
-		pRPacket->Ctrl == SK_RLMT_CTRL &&
-		(pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP &&
-		pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
-		pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
-		pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
-		pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
-		pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
-		pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
-		pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
-
-		/* It's an RLMT packet. */
-		PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) |
-			pRPacket->RlmtPacketType[1]);
-
-		switch (PacketType) {
-		case SK_PACKET_ANNOUNCE:	/* Not yet used. */
-#if 0
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC);
-#endif	/* 0 */
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Announce.\n"))
-
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-			break;
-
-		case SK_PACKET_ALIVE:
-			if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-					("SkRlmtPacketReceive: Alive Reply.\n"))
-
-				if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) ||
-					SK_ADDR_EQUAL(
-						pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) {
-					/* Obviously we could send something. */
-					if (pRPort->CheckingState & SK_RLMT_PCS_TX) {
-						pRPort->CheckingState &=  ~SK_RLMT_PCS_TX;
-						SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-					}
-
-					if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
-						!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
-						pRPort->PortState = SK_RLMT_PS_GOING_UP;
-						pRPort->GuTimeStamp = SkOsGetTime(pAC);
-
-						SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
-						Para.Para32[0] = PortNumber;
-						Para.Para32[1] = (SK_U32)-1;
-						SkTimerStart(pAC, IoC, &pRPort->UpTimer,
-							SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT,
-							SK_RLMT_PORTUP_TIM, Para);
-					}
-				}
-
-				/* Mark sending port as alive? */
-				SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-			}
-			else {	/* Alive Request Packet. */
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-					("SkRlmtPacketReceive: Alive Request.\n"))
-
-				pRPort->RxHelloCts++;
-
-				/* Answer. */
-				for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
-					pRPacket->DstAddr[i] = pRPacket->SrcAddr[i];
-					pRPacket->SrcAddr[i] =
-						pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
-				}
-				pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT;
-
-				Para.pParaPtr = pMb;
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-			break;
-
-		case SK_PACKET_CHECK_TX:
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Check your tx line.\n"))
-
-			/* A port checking us requests us to check our tx line. */
-			pRPort->CheckingState |= SK_RLMT_PCS_TX;
-
-			/* Start PortDownTx timer. */
-			Para.Para32[0] = PortNumber;
-			Para.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pRPort->DownTxTimer,
-				SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
-				SK_RLMT_PORTDOWN_TX_TIM, Para);
-
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-
-			if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
-				SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
-				&SkRlmtMcAddr)) != NULL) {
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-			break;
-
-		case SK_PACKET_ADDR_CHANGED:
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Address Change.\n"))
-
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-			break;
-
-		default:
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-				("SkRlmtPacketReceive: Unknown RLMT packet.\n"))
-
-			/* RA;:;: ??? */
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		}
-	}
-	else if (pSPacket->DSap == SK_RLMT_SPT_DSAP &&
-		pSPacket->Ctrl == SK_RLMT_SPT_CTRL &&
-		(pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: BPDU Packet.\n"))
-
-		/* Spanning Tree packet. */
-		pRPort->RxSpHelloCts++;
-
-		if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt.
-			Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) {
-			/*
-			 * Check segmentation if a new root bridge is set and
-			 * the segmentation check is not currently running.
-			 */
-			if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) &&
-				(pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
-				(pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG)
-				!= 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState &
-				SK_RLMT_RCS_SEG) == 0) {
-				pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
-					SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
-			}
-
-			/* Store tree view of this port. */
-			for (i = 0; i < 8; i++) {
-				pRPort->Root.Id[i] = pSPacket->RootId[i];
-			}
-			pRPort->RootIdSet = SK_TRUE;
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
-				("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
-					PortNumber,
-					pRPort->Root.Id[0], pRPort->Root.Id[1],
-					pRPort->Root.Id[2], pRPort->Root.Id[3],
-					pRPort->Root.Id[4], pRPort->Root.Id[5],
-					pRPort->Root.Id[6], pRPort->Root.Id[7]))
-		}
-
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState &
-			SK_RLMT_RCS_REPORT_SEG) != 0) {
-			SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber);
-		}
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
-			("SkRlmtPacketReceive: Unknown Packet Type.\n"))
-
-		/* Unknown packet. */
-		SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-	}
-	return;
-}	/* SkRlmtPacketReceive */
-
-
-/******************************************************************************
- *
- *	SkRlmtCheckPort - check if a port works
- *
- * Description:
- *	This routine checks if a port whose link is up received something
- *	and if it seems to transmit successfully.
- *
- *	# PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp
- *	# PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg
- *	# RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg
- *
- *	if (Rx - RxBpdu == 0) {	# No rx.
- *		if (state == PsUp) {
- *			PortCheckingState |= ChkRx
- *		}
- *		if (ModeCheckSeg && (Timeout ==
- *			TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) {
- *			RlmtCheckingState |= ChkSeg)
- *			PortCheckingState |= ChkSeg
- *		}
- *		NewTimeout = TO_SHORTEN(Timeout)
- *		if (NewTimeout < RLMT_MIN_TIMEOUT) {
- *			NewTimeout = RLMT_MIN_TIMEOUT
- *			PortState = PsDown
- *			...
- *		}
- *	}
- *	else {	# something was received
- *		# Set counter to 0 at LinkDown?
- *		#   No - rx may be reported after LinkDown ???
- *		PortCheckingState &= ~ChkRx
- *		NewTimeout = RLMT_DEFAULT_TIMEOUT
- *		if (RxAck == 0) {
- *			possible reasons:
- *			is my tx line bad? --
- *				send RLMT multicast and report
- *				back internally? (only possible
- *				between ports on same adapter)
- *		}
- *		if (RxChk == 0) {
- *			possible reasons:
- *			- tx line of port set to check me
- *			  maybe bad
- *			- no other port/adapter available or set
- *			  to check me
- *			- adapter checking me has a longer
- *			  timeout
- *			??? anything that can be done here?
- *		}
- *	}
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	New timeout value.
- */
-RLMT_STATIC SK_U32	SkRlmtCheckPort(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Port to check */
-{
-	unsigned		i;
-	SK_U32			NewTimeout;
-	SK_RLMT_PORT	*pRPort;
-	SK_EVPARA		Para;
-
-	pRPort = &pAC->Rlmt.Port[PortNumber];
-
-	if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n",
-				PortNumber, pRPort->PacketsPerTimeSlot))
-
-		/*
-		 * Check segmentation if there was no receive at least twice
-		 * in a row (PortNoRx is already set) and the segmentation
-		 * check is not currently running.
-		 */
-
-		if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
-			(pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
-			!(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) {
-			pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
-				SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
-		}
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n",
-				pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX))
-
-		if (pRPort->PortState != SK_RLMT_PS_DOWN) {
-			NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue);
-			if (NewTimeout < SK_RLMT_MIN_TO_VAL) {
-				NewTimeout = SK_RLMT_MIN_TO_VAL;
-			}
-
-			if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
-				Para.Para32[0] = PortNumber;
-				pRPort->CheckingState |= SK_RLMT_PCS_RX;
-
-				/*
-				 * What shall we do if the port checked by this one receives
-				 * our request frames?  What's bad - our rx line or his tx line?
-				 */
-				Para.Para32[1] = (SK_U32)-1;
-				SkTimerStart(pAC, IoC, &pRPort->DownRxTimer,
-					SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
-					SK_RLMT_PORTDOWN_RX_TIM, Para);
-
-				for (i = 0; i < pRPort->PortsChecked; i++) {
-					if (pRPort->PortCheck[i].SuspectTx) {
-						continue;
-					}
-					pRPort->PortCheck[i].SuspectTx = SK_TRUE;
-					pRPort->PortsSuspect++;
-					if ((Para.pParaPtr =
-						SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX,
-							&pAC->Addr.Port[PortNumber].CurrentMacAddress,
-							&pRPort->PortCheck[i].CheckAddr)) != NULL) {
-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-					}
-				}
-			}
-		}
-		else {	/* PortDown -- or all partners suspect. */
-			NewTimeout = SK_RLMT_DEF_TO_VAL;
-		}
-		pRPort->PortNoRx = SK_TRUE;
-	}
-	else {	/* A non-BPDU packet was received. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n",
-				PortNumber,
-				pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot,
-				pRPort->PacketsPerTimeSlot))
-		
-		SkRlmtPortReceives(pAC, IoC, PortNumber);
-		if (pAC->Rlmt.CheckSwitch) {
-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-		}
-
-		NewTimeout = SK_RLMT_DEF_TO_VAL;
-	}
-
-	return (NewTimeout);
-}	/* SkRlmtCheckPort */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectBcRx - select new active port, criteria 1 (CLP)
- *
- * Description:
- *	This routine selects the port that received a broadcast frame
- *	substantially later than all other ports.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectBcRx(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	Active,		/* Active port */
-SK_U32	PrefPort,	/* Preferred port */
-SK_U32	*pSelect)	/* New active port */
-{
-	SK_U64		BcTimeStamp;
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	BcTimeStamp = 0;	/* Not totally necessary, but feeling better. */
-	PortFound = SK_FALSE;
-	
-	/* Select port with the latest TimeStamp. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n",
-				i,
-   				pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx,
-				*((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32),
-				*((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32)))
-
-		if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) {
-			if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) {
-				BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp;
-				*pSelect = i;
-				PortFound = SK_TRUE;
-			}
-		}
-	}
-
-	if (PortFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Port %d received the last broadcast.\n", *pSelect))
-
-		/* Look if another port's time stamp is similar. */
-		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-			if (i == *pSelect) {
-				continue;
-			}
-			if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx &&
-				(pAC->Rlmt.Port[i].BcTimeStamp >
-				 BcTimeStamp - SK_RLMT_BC_DELTA ||
-				pAC->Rlmt.Port[i].BcTimeStamp +
-				 SK_RLMT_BC_DELTA > BcTimeStamp)) {
-				PortFound = SK_FALSE;
-				
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-					("Port %d received a broadcast at a similar time.\n", i))
-				break;
-			}
-		}
-	}
-
-#ifdef DEBUG
-	if (PortFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially "
-			 "latest broadcast (%u).\n",
-				*pSelect,
-				BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp))
-	}
-#endif	/* DEBUG */
-
-	return (PortFound);
-}	/* SkRlmtSelectBcRx */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP)
- *
- * Description:
- *	This routine selects a good port (it is PortUp && !SuspectRx).
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectNotSuspect(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	Active,		/* Active port */
-SK_U32	PrefPort,	/* Preferred port */
-SK_U32	*pSelect)	/* New active port */
-{
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	PortFound = SK_FALSE;
-
-	/* Select first port that is PortUp && !SuspectRx. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (!pAC->Rlmt.Port[i].PortDown &&
-			!(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) {
-			*pSelect = i;
-			if (!pAC->Rlmt.Port[Active].PortDown &&
-				!(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) {
-				*pSelect = Active;
-			}
-			if (!pAC->Rlmt.Port[PrefPort].PortDown &&
-				!(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) {
-				*pSelect = PrefPort;
-			}
-			PortFound = SK_TRUE;
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n",
-					*pSelect))
-			break;
-		}
-	}
-	return (PortFound);
-}	/* SkRlmtSelectNotSuspect */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP)
- *
- * Description:
- *	This routine selects a port that is up.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectUp(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	Active,			/* Active port */
-SK_U32	PrefPort,		/* Preferred port */
-SK_U32	*pSelect,		/* New active port */
-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
-{
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	PortFound = SK_FALSE;
-
-	/* Select first port that is PortUp. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			*pSelect = i;
-			if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP &&
-				pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
-				*pSelect = Active;
-			}
-			if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP &&
-				pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
-				*pSelect = PrefPort;
-			}
-			PortFound = SK_TRUE;
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect))
-			break;
-		}
-	}
-	return (PortFound);
-}	/* SkRlmtSelectUp */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP)
- *
- * Description:
- *	This routine selects the port that is going up for the longest time.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectGoingUp(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	Active,			/* Active port */
-SK_U32	PrefPort,		/* Preferred port */
-SK_U32	*pSelect,		/* New active port */
-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
-{
-	SK_U64		GuTimeStamp;
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	GuTimeStamp = 0;
-	PortFound = SK_FALSE;
-
-	/* Select port that is PortGoingUp for the longest time. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
-			*pSelect = i;
-			PortFound = SK_TRUE;
-			break;
-		}
-	}
-
-	if (!PortFound) {
-		return (SK_FALSE);
-	}
-
-	for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
-			pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
-			*pSelect = i;
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect))
-	return (SK_TRUE);
-}	/* SkRlmtSelectGoingUp */
-
-
-/******************************************************************************
- *
- *	SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP)
- *
- * Description:
- *	This routine selects a port that is down.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	SK_BOOL
- */
-RLMT_STATIC SK_BOOL	SkRlmtSelectDown(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-SK_U32	Active,			/* Active port */
-SK_U32	PrefPort,		/* Preferred port */
-SK_U32	*pSelect,		/* New active port */
-SK_BOOL	AutoNegDone)	/* Successfully auto-negotiated? */
-{
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	PortFound = SK_FALSE;
-
-	/* Select first port that is PortDown. */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN &&
-			pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
-			*pSelect = i;
-			if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN &&
-				pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
-				*pSelect = Active;
-			}
-			if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN &&
-				pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
-				*pSelect = PrefPort;
-			}
-			PortFound = SK_TRUE;
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect))
-			break;
-		}
-	}
-	return (PortFound);
-}	/* SkRlmtSelectDown */
-
-
-/******************************************************************************
- *
- *	SkRlmtCheckSwitch - select new active port and switch to it
- *
- * Description:
- *	This routine decides which port should be the active one and queues
- *	port switching if necessary.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtCheckSwitch(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-SK_U32	NetIdx)	/* Net index */
-{
-	SK_EVPARA	Para;
-	SK_U32		Active;
-	SK_U32		PrefPort;
-	SK_U32		i;
-	SK_BOOL		PortFound;
-
-	Active = pAC->Rlmt.Net[NetIdx].ActivePort;	/* Index of active port. */
-	PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort;	/* Index of preferred port. */
-	PortFound = SK_FALSE;
-	pAC->Rlmt.CheckSwitch = SK_FALSE;
-
-#if 0	/* RW 2001/10/18 - active port becomes always prefered one */
-	if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */
-		/* disable auto-fail back */
-		PrefPort = Active;
-	}
-#endif
-
-	if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) {
-		/* Last link went down - shut down the net. */
-		pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN;
-		Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP;
-		Para.Para32[1] = NetIdx;
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para);
-
-		Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
-			Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
-		Para.Para32[1] = NetIdx;
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
-		return;
-	}	/* pAC->Rlmt.LinksUp == 0 */
-	else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 &&
-		pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) {
-		/* First link came up - get the net up. */
-		pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP;
-
-		/*
-		 * If pAC->Rlmt.ActivePort != Para.Para32[0],
-		 * the DRV switches to the port that came up.
-		 */
-		for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
-			if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
-				if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) {
-					i = Active;
-				}
-				if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) {
-					i = PrefPort;
-				}
-				PortFound = SK_TRUE;
-				break;
-			}
-		}
-
-		if (PortFound) {
-			Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
-			Para.Para32[1] = NetIdx;
-			SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
-
-			pAC->Rlmt.Net[NetIdx].ActivePort = i;
-			Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
-			Para.Para32[1] = NetIdx;
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para);
-
-			if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
-				(Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC,
-				pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber,
-				SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].
-				CurrentMacAddress, &SkRlmtMcAddr)) != NULL) {
-				/*
-				 * Send announce packet to RLMT multicast address to force
-				 * switches to learn the new location of the logical MAC address.
-				 */
-				SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-			}
-		}
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG);
-		}
-
-		return;
-	}	/* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */
-	else {	/* Cannot be reached in dual-net mode. */
-		Para.Para32[0] = Active;
-
-		/*
-		 * Preselection:
-		 *	If RLMT Mode != CheckLinkState
-		 *		select port that received a broadcast frame substantially later
-		 *		than all other ports
-		 *	else select first port that is not SuspectRx
-		 *	else select first port that is PortUp
-		 *	else select port that is PortGoingUp for the longest time
-		 *	else select first port that is PortDown
-		 *	else stop.
-		 *
-		 * For the preselected port:
-		 *	If ActivePort is equal in quality, select ActivePort.
-		 *
-		 *	If PrefPort is equal in quality, select PrefPort.
-		 *
-		 *	If ActivePort != SelectedPort,
-		 *		If old ActivePort is LinkDown,
-		 *			SwitchHard
-		 *		else
-		 *			SwitchSoft
-		 */
-		/* check of ChgBcPrio flag added */
-		if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
-			(!pAC->Rlmt.Net[0].ChgBcPrio)) {
-			
-			if (!PortFound) {
-				PortFound = SkRlmtSelectBcRx(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-
-			if (!PortFound) {
-				PortFound = SkRlmtSelectNotSuspect(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
-		/* with changed priority for last broadcast received */
-		if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
-			(pAC->Rlmt.Net[0].ChgBcPrio)) {
-			if (!PortFound) {
-				PortFound = SkRlmtSelectNotSuspect(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-
-			if (!PortFound) {
-				PortFound = SkRlmtSelectBcRx(
-					pAC, IoC, Active, PrefPort, &Para.Para32[1]);
-			}
-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
-		}
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
-		}
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectGoingUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
-		}
-
-		if (!PortFound) {
-			PortFound = SkRlmtSelectGoingUp(
-				pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
-		}
-
-		if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) {
-			if (!PortFound) {
-				PortFound = SkRlmtSelectDown(pAC, IoC,
-					Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
-			}
-
-			if (!PortFound) {
-				PortFound = SkRlmtSelectDown(pAC, IoC,
-					Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
-			}
-		}	/* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
-		if (PortFound) {
-
-			if (Para.Para32[1] != Active) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-					("Active: %d, Para1: %d.\n", Active, Para.Para32[1]))
-				pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1];
-				Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
-					Port[Para.Para32[0]]->PortNumber;
-				Para.Para32[1] = pAC->Rlmt.Net[NetIdx].
-					Port[Para.Para32[1]]->PortNumber;
-				SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE);
-				if (pAC->Rlmt.Port[Active].LinkDown) {
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para);
-				}
-				else {
-					SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para);
-				}
-				Para.Para32[1] = NetIdx;
-				Para.Para32[0] =
-					pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber;
-				SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
-				Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
-					Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
-				SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
-				if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
-					(Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0],
-					SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress,
-					&SkRlmtMcAddr)) != NULL) {
-					/*
-					 * Send announce packet to RLMT multicast address to force
-					 * switches to learn the new location of the logical
-					 * MAC address.
-					 */
-					SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
-				}	/* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */
-			}	/* Para.Para32[1] != Active */
-		}	/* PortFound */
-		else {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG);
-		}
-	}	/* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */
-	return;
-}	/* SkRlmtCheckSwitch */
-
-
-/******************************************************************************
- *
- *	SkRlmtCheckSeg - Report if segmentation is detected
- *
- * Description:
- *	This routine checks if the ports see different root bridges and reports
- *	segmentation in such a case.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing.
- */
-RLMT_STATIC void	SkRlmtCheckSeg(
-SK_AC	*pAC,	/* Adapter Context */
-SK_IOC	IoC,	/* I/O Context */
-SK_U32	NetIdx)	/* Net number */
-{
-	SK_EVPARA	Para;
-	SK_RLMT_NET	*pNet;
-	SK_U32		i, j;
-	SK_BOOL		Equal;
-
-	pNet = &pAC->Rlmt.Net[NetIdx];
-	pNet->RootIdSet = SK_FALSE;
-	Equal = SK_TRUE;
-
-	for (i = 0; i < pNet->NumPorts; i++) {
-		if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) {
-			continue;
-		}
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
-			("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i,
-				pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1],
-				pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3],
-				pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5],
-				pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7]))
-
-		if (!pNet->RootIdSet) {
-			pNet->Root = pNet->Port[i]->Root;
-			pNet->RootIdSet = SK_TRUE;
-			continue;
-		}
-
-		for (j = 0; j < 8; j ++) {
-			Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j];
-			if (!Equal) {
-				break;
-			}
-		}
-		
-		if (!Equal) {
-			SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG);
-			Para.Para32[0] = NetIdx;
-			Para.Para32[1] = (SK_U32)-1;
-			SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para);
-
-			pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG;
-
-			/* 2000-03-06 RA: New. */
-			Para.Para32[0] = NetIdx;
-			Para.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL,
-				SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
-			break;
-		}
-	}	/* for (i = 0; i < pNet->NumPorts; i++) */
-
-	/* 2000-03-06 RA: Moved here. */
-	/* Segmentation check not running anymore. */
-	pNet->CheckingState &= ~SK_RLMT_RCS_SEG;
-
-}	/* SkRlmtCheckSeg */
-
-
-/******************************************************************************
- *
- *	SkRlmtPortStart - initialize port variables and start port
- *
- * Description:
- *	This routine initializes a port's variables and issues a PORT_START
- *	to the HWAC module.  This handles retries if the start fails or the
- *	link eventually goes down.
- *
- * Context:
- *	runtime, pageable?
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtPortStart(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-SK_U32	PortNumber)	/* Port number */
-{
-	SK_EVPARA	Para;
-
-	pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN;
-	pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE;
-	pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE;
-	pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE;
-	pAC->Rlmt.Port[PortNumber].CheckingState = 0;
-	pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
-	Para.Para32[0] = PortNumber;
-	Para.Para32[1] = (SK_U32)-1;
-	SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-}	/* SkRlmtPortStart */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortStartTim - PORT_START_TIM
- *
- * Description:
- *	This routine handles PORT_START_TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortStartTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_U32			i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0]))
-
-		if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"))
-		return;
-	}
-
-	/*
-	 * Used to start non-preferred ports if the preferred one
-	 * does not come up.
-	 * This timeout needs only be set when starting the first
-	 * (preferred) port.
-	 */
-	if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
-		/* PORT_START failed. */
-		for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) {
-			if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) {
-				SkRlmtPortStart(pAC, IoC,
-					pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber);
-			}
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"))
-}	/* SkRlmtEvtPortStartTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtLinkUp - LINK_UP
- *
- * Description:
- *	This routine handles LLINK_UP events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtLinkUp(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 Undefined */
-{
-	SK_U32			i;
-	SK_RLMT_PORT	*pRPort;
-	SK_EVPARA		Para2;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	if (!pRPort->PortStarted) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_LINK_UP Event EMPTY.\n"))
-		return;
-	}
-
-	if (!pRPort->LinkDown) {
-		/* RA;:;: Any better solution? */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_LINK_UP Event EMPTY.\n"))
-		return;
-	}
-
-	SkTimerStop(pAC, IoC, &pRPort->UpTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
-	/* Do something if timer already fired? */
-
-	pRPort->LinkDown = SK_FALSE;
-	pRPort->PortState = SK_RLMT_PS_GOING_UP;
-	pRPort->GuTimeStamp = SkOsGetTime(pAC);
-	pRPort->BcTimeStamp = 0;
-	pRPort->Net->LinksUp++;
-	if (pRPort->Net->LinksUp == 1) {
-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE);
-	}
-	else {
-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
-	}
-
-	for (i = 0; i < pRPort->Net->NumPorts; i++) {
-		if (!pRPort->Net->Port[i]->PortStarted) {
-			SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber);
-		}
-	}
-
-	SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-
-	if (pRPort->Net->LinksUp >= 2) {
-		if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
-		}
-	}
-
-	/* If the first link comes up, start the periodical RLMT timeout. */
-	if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 &&
-		(pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) {
-		Para2.Para32[0] = pRPort->Net->NetNumber;
-		Para2.Para32[1] = (SK_U32)-1;
-		SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer,
-			pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2);
-	}
-
-	Para2 = Para;
-	Para2.Para32[1] = (SK_U32)-1;
-	SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
-		SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2);
-	
-	/* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */
-	if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
-		(pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 &&
-		(Para2.pParaPtr =
-			SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE,
-			&pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr)
-		) != NULL) {
-		/* Send "new" packet to RLMT multicast address. */
-		SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
-	}
-
-	if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) {
-		if ((Para2.pParaPtr =
-			SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) {
-			pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE;
-			pRPort->Net->CheckingState |=
-				SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
-
-			SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
-
-			Para.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer,
-				SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_UP Event END.\n"))
-}	/* SkRlmtEvtLinkUp */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortUpTim - PORT_UP_TIM
- *
- * Description:
- *	This routine handles PORT_UP_TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortUpTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_RLMT_PORT	*pRPort;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTUP_TIM Event EMPTY.\n"))
-		return;
-	}
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0]))
-		return;
-	}
-
-	pRPort->PortDown = SK_FALSE;
-	pRPort->PortState = SK_RLMT_PS_UP;
-	pRPort->Net->PortsUp++;
-	if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
-		if (pAC->Rlmt.NumNets <= 1) {
-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-		}
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTUP_TIM Event END.\n"))
-}	/* SkRlmtEvtPortUpTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortDownTim - PORT_DOWN_*
- *
- * Description:
- *	This routine handles PORT_DOWN_* events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortDownX(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_U32		Event,	/* Event code */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_RLMT_PORT	*pRPort;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n",
-			Para.Para32[0], Event))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTDOWN* Event EMPTY.\n"))
-		return;
-	}
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM &&
-		!(pRPort->CheckingState & SK_RLMT_PCS_TX))) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event))
-		return;
-	}
-	
-	/* Stop port's timers. */
-	SkTimerStop(pAC, IoC, &pRPort->UpTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
-	SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
-	if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) {
-		pRPort->PortState = SK_RLMT_PS_DOWN;
-	}
-
-	if (!pRPort->PortDown) {
-		pRPort->Net->PortsUp--;
-		pRPort->PortDown = SK_TRUE;
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para);
-	}
-
-	pRPort->PacketsPerTimeSlot = 0;
-	/* pRPort->DataPacketsPerTimeSlot = 0; */
-	pRPort->BpduPacketsPerTimeSlot = 0;
-	pRPort->BcTimeStamp = 0;
-
-	/*
-	 * RA;:;: To be checked:
-	 * - actions at RLMT_STOP: We should not switch anymore.
-	 */
-	if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
-		if (Para.Para32[0] ==
-			pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) {
-			/* Active Port went down. */
-			SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event))
-}	/* SkRlmtEvtPortDownX */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtLinkDown - LINK_DOWN
- *
- * Description:
- *	This routine handles LINK_DOWN events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtLinkDown(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 Undefined */
-{
-	SK_RLMT_PORT	*pRPort;
-
-	pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
-		pRPort->Net->LinksUp--;
-		pRPort->LinkDown = SK_TRUE;
-		pRPort->PortState = SK_RLMT_PS_LINK_DOWN;
-		SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF);
-
-		if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) {
-			/* Build the check chain. */
-			SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
-		}
-
-		/* Ensure that port is marked down. */
-		Para.Para32[1] = -1;
-		(void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_LINK_DOWN Event END.\n"))
-}	/* SkRlmtEvtLinkDown */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPortAddr - PORT_ADDR
- *
- * Description:
- *	This routine handles PORT_ADDR events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPortAddr(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortNumber; SK_U32 -1 */
-{
-	SK_U32			i, j;
-	SK_RLMT_PORT	*pRPort;
-	SK_MAC_ADDR		*pOldMacAddr;
-	SK_MAC_ADDR		*pNewMacAddr;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORT_ADDR Event EMPTY.\n"))
-		return;
-	}
-
-	/* Port's physical MAC address changed. */
-	pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress;
-	pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress;
-
-	/*
-	 * NOTE: This is not scalable for solutions where ports are
-	 *	 checked remotely.  There, we need to send an RLMT
-	 *	 address change packet - and how do we ensure delivery?
-	 */
-	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-		pRPort = &pAC->Rlmt.Port[i];
-		for (j = 0; j < pRPort->PortsChecked; j++) {
-			if (SK_ADDR_EQUAL(
-				pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) {
-				pRPort->PortCheck[j].CheckAddr = *pNewMacAddr;
-			}
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PORT_ADDR Event END.\n"))
-}	/* SkRlmtEvtPortAddr */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStart - START
- *
- * Description:
- *	This routine handles START events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStart(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_EVPARA	Para2;
-	SK_U32		PortIdx;
-	SK_U32		PortNumber;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("All nets should have been started.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >=
-		pAC->Rlmt.Net[Para.Para32[0]].NumPorts) {
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG);
-
-		/* Change PrefPort to internal default. */
-		Para2.Para32[0] = 0xFFFFFFFF;
-		Para2.Para32[1] = Para.Para32[0];
-		(void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2);
-	}
-
-	PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort;
-	PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber;
-
-	pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0;
-	pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0;
-	pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0;
-	pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN;
-
-	/* Start preferred port. */
-	SkRlmtPortStart(pAC, IoC, PortNumber);
-
-	/* Start Timer (for first port only). */
-	Para2.Para32[0] = PortNumber;
-	Para2.Para32[1] = (SK_U32)-1;
-	SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer,
-		SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2);
-
-	pAC->Rlmt.NetsStarted++;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_START Event END.\n"))
-}	/* SkRlmtEvtStart */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStop - STOP
- *
- * Description:
- *	This routine handles STOP events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStop(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_EVPARA	Para2;
-	SK_U32		PortNumber;
-	SK_U32		i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	if (pAC->Rlmt.NetsStarted == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("All nets are stopped.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STOP Event EMPTY.\n"))
-		return;
-	}
-
-	/* Stop RLMT timers. */
-	SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer);
-	SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer);
-
-	/* Stop net. */
-	pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT;
-	pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE;
-	Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL;
-	Para2.Para32[1] = Para.Para32[0];			/* Net# */
-	SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2);
-
-	/* Stop ports. */
-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-		PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
-		if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) {
-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer);
-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer);
-			SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer);
-
-			pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT;
-			pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE;
-			Para2.Para32[0] = PortNumber;
-			Para2.Para32[1] = (SK_U32)-1;
-			SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2);
-		}
-	}
-
-	pAC->Rlmt.NetsStarted--;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STOP Event END.\n"))
-}	/* SkRlmtEvtStop */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtTim - TIM
- *
- * Description:
- *	This routine handles TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_RLMT_PORT	*pRPort;
-	SK_U32			Timeout;
-	SK_U32			NewTimeout;
-	SK_U32			PortNumber;
-	SK_U32			i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_TIM Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_TIM Event EMPTY.\n"))
-		return;
-	}
-
-	if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 ||
-		pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) {
-		/* Mode changed or all links down: No more link checking. */
-		return;
-	}
-
-#if 0
-	pAC->Rlmt.SwitchCheckCounter--;
-	if (pAC->Rlmt.SwitchCheckCounter == 0) {
-		pAC->Rlmt.SwitchCheckCounter;
-	}
-#endif	/* 0 */
-
-	NewTimeout = SK_RLMT_DEF_TO_VAL;
-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-		PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
-		pRPort = &pAC->Rlmt.Port[PortNumber];
-		if (!pRPort->LinkDown) {
-			Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber);
-			if (Timeout < NewTimeout) {
-				NewTimeout = Timeout;
-			}
-
-			/*
-			 * These counters should be set to 0 for all ports before the
-			 * first frame is sent in the next loop.
-			 */
-			pRPort->PacketsPerTimeSlot = 0;
-			/* pRPort->DataPacketsPerTimeSlot = 0; */
-			pRPort->BpduPacketsPerTimeSlot = 0;
-		}
-	}
-	pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout;
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) {
-		/*
-		 * If checking remote ports, also send packets if
-		 *   (LinksUp == 1) &&
-		 *   this port checks at least one (remote) port.
-		 */
-
-		/*
-		 * Must be new loop, as SkRlmtCheckPort can request to
-		 * check segmentation when e.g. checking the last port.
-		 */
-		for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-			if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) {
-				SkRlmtSend(pAC, IoC,
-					pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber);
-			}
-		}
-	}
-
-	SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer,
-		pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM,
-		Para);
-
-	if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 &&
-		(pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) &&
-		(pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) {
-		SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer,
-			SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
-		pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG;
-		pAC->Rlmt.Net[Para.Para32[0]].CheckingState |=
-			SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_TIM Event END.\n"))
-}	/* SkRlmtEvtTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtSegTim - SEG_TIM
- *
- * Description:
- *	This routine handles SEG_TIM events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtSegTim(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-#ifdef xDEBUG
-	int j;
-#endif	/* DEBUG */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SEG_TIM Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SEG_TIM Event EMPTY.\n"))
-		return;
-	}
-
-#ifdef xDEBUG
-	for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) {
-		SK_ADDR_PORT	*pAPort;
-		SK_U32			k;
-		SK_U16			*InAddr;
-		SK_U8			InAddr8[6];
-
-		InAddr = (SK_U16 *)&InAddr8[0];
-		pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort;
-		for (k = 0; k < pAPort->NextExactMatchRlmt; k++) {
-			/* Get exact match address k from port j. */
-			XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
-				XM_EXM(k), InAddr);
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x --  %02x %02x %02x %02x %02x %02x.\n",
-					k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
-					InAddr8[0], InAddr8[1], InAddr8[2],
-					InAddr8[3], InAddr8[4], InAddr8[5],
-					pAPort->Exact[k].a[0], pAPort->Exact[k].a[1],
-					pAPort->Exact[k].a[2], pAPort->Exact[k].a[3],
-					pAPort->Exact[k].a[4], pAPort->Exact[k].a[5]))
-		}
-	}
-#endif	/* xDEBUG */
-				
-	SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]);
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SEG_TIM Event END.\n"))
-}	/* SkRlmtEvtSegTim */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPacketRx - PACKET_RECEIVED
- *
- * Description:
- *	This routine handles PACKET_RECEIVED events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPacketRx(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_MBUF *pMb */
-{
-	SK_MBUF	*pMb;
-	SK_MBUF	*pNextMb;
-	SK_U32	NetNumber;
-
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"))
-
-	/* Should we ignore frames during port switching? */
-
-#ifdef DEBUG
-	pMb = Para.pParaPtr;
-	if (pMb == NULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n"))
-	}
-	else if (pMb->pNext != NULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("More than one mbuf or pMb->pNext not set.\n"))
-	}
-#endif	/* DEBUG */
-
-	for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) {
-		pNextMb = pMb->pNext;
-		pMb->pNext = NULL;
-
-		NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber;
-		if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) {
-			SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-		}
-		else {
-			SkRlmtPacketReceive(pAC, IoC, pMb);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PACKET_RECEIVED Event END.\n"))
-}	/* SkRlmtEvtPacketRx */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStatsClear - STATS_CLEAR
- *
- * Description:
- *	This routine handles STATS_CLEAR events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStatsClear(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_U32			i;
-	SK_RLMT_PORT	*pRPort;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_CLEAR Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
-		return;
-	}
-
-	/* Clear statistics for logical and physical ports. */
-	for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
-		pRPort =
-			&pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber];
-		pRPort->TxHelloCts = 0;
-		pRPort->RxHelloCts = 0;
-		pRPort->TxSpHelloReqCts = 0;
-		pRPort->RxSpHelloCts = 0;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_CLEAR Event END.\n"))
-}	/* SkRlmtEvtStatsClear */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtStatsUpdate - STATS_UPDATE
- *
- * Description:
- *	This routine handles STATS_UPDATE events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtStatsUpdate(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NetNumber; SK_U32 -1 */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_UPDATE Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
-		return;
-	}
-
-	/* Update statistics - currently always up-to-date. */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_STATS_UPDATE Event END.\n"))
-}	/* SkRlmtEvtStatsUpdate */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtPrefportChange - PREFPORT_CHANGE
- *
- * Description:
- *	This routine handles PREFPORT_CHANGE events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtPrefportChange(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 PortIndex; SK_U32 NetNumber */
-{
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0]))
-
-	if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[1]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
-		return;
-	}
-
-	/* 0xFFFFFFFF == auto-mode. */
-	if (Para.Para32[0] == 0xFFFFFFFF) {
-		pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT;
-	}
-	else {
-		if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) {
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG);
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-				("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
-			return;
-		}
-
-		pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0];
-	}
-
-	pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0];
-
-	if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
-		SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_PREFPORT_CHANGE Event END.\n"))
-}	/* SkRlmtEvtPrefportChange */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtSetNets - SET_NETS
- *
- * Description:
- *	This routine handles SET_NETS events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtSetNets(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NumNets; SK_U32 -1 */
-{
-	int i;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SET_NETS Event BEGIN.\n"))
-
-	if (Para.Para32[1] != (SK_U32)-1) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad Parameter.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS ||
-		Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad number of nets: %d.\n", Para.Para32[0]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] == pAC->Rlmt.NumNets) {	/* No change. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	/* Entering and leaving dual mode only allowed while nets are stopped. */
-	if (pAC->Rlmt.NetsStarted > 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Changing dual mode only allowed while all nets are stopped.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	if (Para.Para32[0] == 1) {
-		if (pAC->Rlmt.NumNets > 1) {
-			/* Clear logical MAC addr from second net's active port. */
-			(void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
-				Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL);
-			pAC->Rlmt.Net[1].NumPorts = 0;
-		}
-
-		pAC->Rlmt.NumNets = Para.Para32[0];
-		for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* "Automatic" */
-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
-			/* Just assuming. */
-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
-			pAC->Rlmt.Net[i].NetNumber = i;
-		}
-
-		pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0];
-		pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
-
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("RLMT: Changed to one net with two ports.\n"))
-	}
-	else if (Para.Para32[0] == 2) {
-		pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1];
-		pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1;
-		pAC->Rlmt.Net[0].NumPorts =
-			pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts;
-		
-		pAC->Rlmt.NumNets = Para.Para32[0];
-		for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
-			pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
-			pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
-			pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF;	  /* "Automatic" */
-			pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
-			/* Just assuming. */
-			pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
-			pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
-			pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
-
-			pAC->Rlmt.Net[i].NetNumber = i;
-		}
-
-		/* Set logical MAC addr on second net's active port. */
-		(void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
-			Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL);
-
-		SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("RLMT: Changed to two nets with one port each.\n"))
-	}
-	else {
-		/* Not implemented for more than two nets. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SetNets not implemented for more than two nets.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_SET_NETS Event EMPTY.\n"))
-		return;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_SET_NETS Event END.\n"))
-}	/* SkRlmtSetNets */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvtModeChange - MODE_CHANGE
- *
- * Description:
- *	This routine handles MODE_CHANGE events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	Nothing
- */
-RLMT_STATIC void	SkRlmtEvtModeChange(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_EVPARA	Para)	/* SK_U32 NewMode; SK_U32 NetNumber */
-{
-	SK_EVPARA	Para2;
-	SK_U32		i;
-	SK_U32		PrevRlmtMode;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-		("SK_RLMT_MODE_CHANGE Event BEGIN.\n"))
-
-	if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Bad NetNumber %d.\n", Para.Para32[1]))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
-		return;
-	}
-
-	Para.Para32[0] |= SK_RLMT_CHECK_LINK;
-
-	if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) &&
-		Para.Para32[0] != SK_RLMT_MODE_CLS) {
-		pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS;
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Forced RLMT mode to CLS on single port net.\n"))
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
-		return;
-	}
-
-	/* Update RLMT mode. */
-	PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode;
-	pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0];
-
-	if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) !=
-		(pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
-		/* SK_RLMT_CHECK_LOC_LINK bit changed. */
-		if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 &&
-			pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 &&
-			pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) {
-			/* 20001207 RA: Was "PortsUp == 1". */
-			Para2.Para32[0] = Para.Para32[1];
-			Para2.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer,
-				pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue,
-				SKGE_RLMT, SK_RLMT_TIM, Para2);
-		}
-	}
-
-	if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) !=
-		(pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) {
-		/* SK_RLMT_CHECK_SEG bit changed. */
-		for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) {
-			(void)SkAddrMcClear(pAC, IoC,
-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
-				SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
-
-			/* Add RLMT MC address. */
-			(void)SkAddrMcAdd(pAC, IoC,
-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
-				&SkRlmtMcAddr, SK_ADDR_PERMANENT);
-
-			if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode &
-				SK_RLMT_CHECK_SEG) != 0) {
-				/* Add BPDU MC address. */
-				(void)SkAddrMcAdd(pAC, IoC,
-					pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
-					&BridgeMcAddr, SK_ADDR_PERMANENT);
-
-				if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
-					if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown &&
-						(Para2.pParaPtr = SkRlmtBuildSpanningTreePacket(
-						pAC, IoC, i)) != NULL) {
-						pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet =
-							SK_FALSE;
-						SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
-					}
-				}
-			}
-			(void)SkAddrMcUpdate(pAC, IoC,
-				pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber);
-		}	/* for ... */
-
-		if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) {
-			Para2.Para32[0] = Para.Para32[1];
-			Para2.Para32[1] = (SK_U32)-1;
-			SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer,
-				SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2);
-		}
-	}	/* SK_RLMT_CHECK_SEG bit changed. */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("SK_RLMT_MODE_CHANGE Event END.\n"))
-}	/* SkRlmtEvtModeChange */
-
-
-/******************************************************************************
- *
- *	SkRlmtEvent - a PORT- or an RLMT-specific event happened
- *
- * Description:
- *	This routine calls subroutines to handle PORT- and RLMT-specific events.
- *
- * Context:
- *	runtime, pageable?
- *	may be called after SK_INIT_IO
- *
- * Returns:
- *	0
- */
-int	SkRlmtEvent(
-SK_AC		*pAC,	/* Adapter Context */
-SK_IOC		IoC,	/* I/O Context */
-SK_U32		Event,	/* Event code */
-SK_EVPARA	Para)	/* Event-specific parameter */
-{
-	switch (Event) {
-	
-	/* ----- PORT events ----- */
-
-	case SK_RLMT_PORTSTART_TIM:	/* From RLMT via TIME. */
-		SkRlmtEvtPortStartTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_LINK_UP:		/* From SIRQ. */
-		SkRlmtEvtLinkUp(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PORTUP_TIM:	/* From RLMT via TIME. */
-		SkRlmtEvtPortUpTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PORTDOWN:			/* From RLMT. */
-	case SK_RLMT_PORTDOWN_RX_TIM:	/* From RLMT via TIME. */
-	case SK_RLMT_PORTDOWN_TX_TIM:	/* From RLMT via TIME. */
-		SkRlmtEvtPortDownX(pAC, IoC, Event, Para);
-		break;
-	case SK_RLMT_LINK_DOWN:		/* From SIRQ. */
-		SkRlmtEvtLinkDown(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PORT_ADDR:		/* From ADDR. */
-		SkRlmtEvtPortAddr(pAC, IoC, Para);
-		break;
-
-	/* ----- RLMT events ----- */
-
-	case SK_RLMT_START:		/* From DRV. */
-		SkRlmtEvtStart(pAC, IoC, Para);
-		break;
-	case SK_RLMT_STOP:		/* From DRV. */
-		SkRlmtEvtStop(pAC, IoC, Para);
-		break;
-	case SK_RLMT_TIM:		/* From RLMT via TIME. */
-		SkRlmtEvtTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_SEG_TIM:
-		SkRlmtEvtSegTim(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PACKET_RECEIVED:	/* From DRV. */
-		SkRlmtEvtPacketRx(pAC, IoC, Para);
-		break;
-	case SK_RLMT_STATS_CLEAR:	/* From PNMI. */
-		SkRlmtEvtStatsClear(pAC, IoC, Para);
-		break;
-	case SK_RLMT_STATS_UPDATE:	/* From PNMI. */
-		SkRlmtEvtStatsUpdate(pAC, IoC, Para);
-		break;
-	case SK_RLMT_PREFPORT_CHANGE:	/* From PNMI. */
-		SkRlmtEvtPrefportChange(pAC, IoC, Para);
-		break;
-	case SK_RLMT_MODE_CHANGE:	/* From PNMI. */
-		SkRlmtEvtModeChange(pAC, IoC, Para);
-		break;
-	case SK_RLMT_SET_NETS:	/* From DRV. */
-		SkRlmtEvtSetNets(pAC, IoC, Para);
-		break;
-
-	/* ----- Unknown events ----- */
-
-	default:	/* Create error log entry. */
-		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
-			("Unknown RLMT Event %d.\n", Event))
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG);
-		break;
-	}	/* switch() */
-
-	return (0);
-}	/* SkRlmtEvent */
-
-#ifdef __cplusplus
-}
-#endif	/* __cplusplus */
diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c
deleted file mode 100644
index 4e46295..0000000
--- a/drivers/net/sk98lin/sktimer.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/******************************************************************************
- *
- * Name:	sktimer.c
- * Project:	Gigabit Ethernet Adapters, Event Scheduler Module
- * Version:	$Revision: 1.14 $
- * Date:	$Date: 2003/09/16 13:46:51 $
- * Purpose:	High level timer functions.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect GmbH.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-/*
- *	Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h"		/* Driver Specific Definitions */
-#include "h/skdrv2nd.h"		/* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
-	Event queue management.
-
-	General Description:
-
- */
-intro()
-{}
-#endif
-
-
-/* Forward declaration */
-static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
-
-
-/*
- * Inits the software timer
- *
- * needs to be called during Init level 1.
- */
-void	SkTimerInit(
-SK_AC	*pAC,		/* Adapters context */
-SK_IOC	Ioc,		/* IoContext */
-int		Level)		/* Init Level */
-{
-	switch (Level) {
-	case SK_INIT_DATA:
-		pAC->Tim.StQueue = NULL;
-		break;
-	case SK_INIT_IO:
-		SkHwtInit(pAC, Ioc);
-		SkTimerDone(pAC, Ioc);
-		break;
-	default:
-		break;
-	}
-}
-
-/*
- * Stops a high level timer
- * - If a timer is not in the queue the function returns normally, too.
- */
-void	SkTimerStop(
-SK_AC		*pAC,		/* Adapters context */
-SK_IOC		Ioc,		/* IoContext */
-SK_TIMER	*pTimer)	/* Timer Pointer to be started */
-{
-	SK_TIMER	**ppTimPrev;
-	SK_TIMER	*pTm;
-
-	/*
-	 * remove timer from queue
-	 */
-	pTimer->TmActive = SK_FALSE;
-	
-	if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
-		SkHwtStop(pAC, Ioc);
-	}
-	
-	for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
-		ppTimPrev = &pTm->TmNext ) {
-		
-		if (pTm == pTimer) {
-			/*
-			 * Timer found in queue
-			 * - dequeue it and
-			 * - correct delta of the next timer
-			 */
-			*ppTimPrev = pTm->TmNext;
-
-			if (pTm->TmNext) {
-				/* correct delta of next timer in queue */
-				pTm->TmNext->TmDelta += pTm->TmDelta;
-			}
-			return;
-		}
-	}
-}
-
-/*
- * Start a high level software timer
- */
-void	SkTimerStart(
-SK_AC		*pAC,		/* Adapters context */
-SK_IOC		Ioc,		/* IoContext */
-SK_TIMER	*pTimer,	/* Timer Pointer to be started */
-SK_U32		Time,		/* Time value */
-SK_U32		Class,		/* Event Class for this timer */
-SK_U32		Event,		/* Event Value for this timer */
-SK_EVPARA	Para)		/* Event Parameter for this timer */
-{
-	SK_TIMER	**ppTimPrev;
-	SK_TIMER	*pTm;
-	SK_U32		Delta;
-
-	Time /= 16;		/* input is uS, clock ticks are 16uS */
-	
-	if (!Time)
-		Time = 1;
-
-	SkTimerStop(pAC, Ioc, pTimer);
-
-	pTimer->TmClass = Class;
-	pTimer->TmEvent = Event;
-	pTimer->TmPara = Para;
-	pTimer->TmActive = SK_TRUE;
-
-	if (!pAC->Tim.StQueue) {
-		/* First Timer to be started */
-		pAC->Tim.StQueue = pTimer;
-		pTimer->TmNext = NULL;
-		pTimer->TmDelta = Time;
-		
-		SkHwtStart(pAC, Ioc, Time);
-		
-		return;
-	}
-
-	/*
-	 * timer correction
-	 */
-	timer_done(pAC, Ioc, 0);
-
-	/*
-	 * find position in queue
-	 */
-	Delta = 0;
-	for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
-		ppTimPrev = &pTm->TmNext ) {
-		
-		if (Delta + pTm->TmDelta > Time) {
-			/* Position found */
-			/* Here the timer needs to be inserted. */
-			break;
-		}
-		Delta += pTm->TmDelta;
-	}
-
-	/* insert in queue */
-	*ppTimPrev = pTimer;
-	pTimer->TmNext = pTm;
-	pTimer->TmDelta = Time - Delta;
-
-	if (pTm) {
-		/* There is a next timer
-		 * -> correct its Delta value.
-		 */
-		pTm->TmDelta -= pTimer->TmDelta;
-	}
-
-	/* restart with first */
-	SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
-}
-
-
-void	SkTimerDone(
-SK_AC	*pAC,		/* Adapters context */
-SK_IOC	Ioc)		/* IoContext */
-{
-	timer_done(pAC, Ioc, 1);
-}
-
-
-static void	timer_done(
-SK_AC	*pAC,		/* Adapters context */
-SK_IOC	Ioc,		/* IoContext */
-int		Restart)	/* Do we need to restart the Hardware timer ? */
-{
-	SK_U32		Delta;
-	SK_TIMER	*pTm;
-	SK_TIMER	*pTComp;	/* Timer completed now now */
-	SK_TIMER	**ppLast;	/* Next field of Last timer to be deq */
-	int		Done = 0;
-
-	Delta = SkHwtRead(pAC, Ioc);
-	
-	ppLast = &pAC->Tim.StQueue;
-	pTm = pAC->Tim.StQueue;
-	while (pTm && !Done) {
-		if (Delta >= pTm->TmDelta) {
-			/* Timer ran out */
-			pTm->TmActive = SK_FALSE;
-			Delta -= pTm->TmDelta;
-			ppLast = &pTm->TmNext;
-			pTm = pTm->TmNext;
-		}
-		else {
-			/* We found the first timer that did not run out */
-			pTm->TmDelta -= Delta;
-			Delta = 0;
-			Done = 1;
-		}
-	}
-	*ppLast = NULL;
-	/*
-	 * pTm points to the first Timer that did not run out.
-	 * StQueue points to the first Timer that run out.
-	 */
-
-	for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
-		SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara);
-	}
-
-	/* Set head of timer queue to the first timer that did not run out */
-	pAC->Tim.StQueue = pTm;
-
-	if (Restart && pAC->Tim.StQueue) {
-		/* Restart HW timer */
-		SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
-	}
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c
deleted file mode 100644
index 1e662aa..0000000
--- a/drivers/net/sk98lin/skvpd.c
+++ /dev/null
@@ -1,1091 +0,0 @@
-/******************************************************************************
- *
- * Name:	skvpd.c
- * Project:	GEnesis, PCI Gigabit Ethernet Adapter
- * Version:	$Revision: 1.37 $
- * Date:	$Date: 2003/01/13 10:42:45 $
- * Purpose:	Shared software to read and write VPD data
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2003 SysKonnect GmbH.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-	Please refer skvpd.txt for information how to include this module
- */
-static const char SysKonnectFileId[] =
-	"@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK";
-
-#include "h/skdrv1st.h"
-#include "h/sktypes.h"
-#include "h/skdebug.h"
-#include "h/skdrv2nd.h"
-
-/*
- * Static functions
- */
-#ifndef SK_KR_PROTO
-static SK_VPD_PARA	*vpd_find_para(
-	SK_AC	*pAC,
-	const char	*key,
-	SK_VPD_PARA *p);
-#else	/* SK_KR_PROTO */
-static SK_VPD_PARA	*vpd_find_para();
-#endif	/* SK_KR_PROTO */
-
-/*
- * waits for a completion of a VPD transfer
- * The VPD transfer must complete within SK_TICKS_PER_SEC/16
- *
- * returns	0:	success, transfer completes
- *		error	exit(9) with a error message
- */
-static int VpdWait(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-int		event)	/* event to wait for (VPD_READ / VPD_write) completion*/
-{
-	SK_U64	start_time;
-	SK_U16	state;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD wait for %s\n", event?"Write":"Read"));
-	start_time = SkOsGetTime(pAC);
-	do {
-		if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) {
-
-			/* Bug fix AF: Thu Mar 28 2002
-			 * Do not call: VPD_STOP(pAC, IoC);
-			 * A pending VPD read cycle can not be aborted by writing
-			 * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register).
-			 * Although the write threshold in the OUR-register protects
-			 * VPD read only space from being overwritten this does not
-			 * protect a VPD read from being `converted` into a VPD write
-			 * operation (on the fly). As a consequence the VPD_STOP would
-			 * delete VPD read only data. In case of any problems with the
-			 * I2C bus we exit the loop here. The I2C read operation can
-			 * not be aborted except by a reset (->LR).
-			 */
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR,
-				("ERROR:VPD wait timeout\n"));
-			return(1);
-		}
-		
-		VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-			("state = %x, event %x\n",state,event));
-	} while((int)(state & PCI_VPD_FLAG) == event);
-
-	return(0);
-}
-
-#ifdef SKDIAG
-
-/*
- * Read the dword at address 'addr' from the VPD EEPROM.
- *
- * Needed Time:	MIN 1,3 ms	MAX 2,6 ms
- *
- * Note: The DWord is returned in the endianess of the machine the routine
- *       is running on.
- *
- * Returns the data read.
- */
-SK_U32 VpdReadDWord(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-int		addr)	/* VPD address */
-{
-	SK_U32	Rtv;
-
-	/* start VPD read */
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD read dword at 0x%x\n",addr));
-	addr &= ~VPD_WRITE;		/* ensure the R/W bit is set to read */
-
-	VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr);
-
-	/* ignore return code here */
-	(void)VpdWait(pAC, IoC, VPD_READ);
-
-	/* Don't swap here, it's a data stream of bytes */
-	Rtv = 0;
-
-	VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD read dword data = 0x%x\n",Rtv));
-	return(Rtv);
-}
-
-#endif	/* SKDIAG */
-
-/*
- *	Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
- *	or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdWriteStream(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* data buffer */
-int		Addr,	/* VPD start address */
-int		Len)	/* number of bytes to read / to write */
-{
-	int		i;
-	int		j;
-	SK_U16	AdrReg;
-	int		Rtv;
-	SK_U8	* pComp;	/* Compare pointer */
-	SK_U8	Data;		/* Input Data for Compare */
-
-	/* Init Compare Pointer */
-	pComp = (SK_U8 *) buf;
-
-	for (i = 0; i < Len; i++, buf++) {
-		if ((i%sizeof(SK_U32)) == 0) {
-			/*
-			 * At the begin of each cycle read the Data Reg
-			 * So it is initialized even if only a few bytes
-			 * are written.
-			 */
-			AdrReg = (SK_U16) Addr;
-			AdrReg &= ~VPD_WRITE;	/* READ operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_READ);
-			if (Rtv != 0) {
-				return(i);
-			}
-		}
-
-		/* Write current Byte */
-		VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
-				*(SK_U8*)buf);
-
-		if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
-			/* New Address needs to be written to VPD_ADDR reg */
-			AdrReg = (SK_U16) Addr;
-			Addr += sizeof(SK_U32);
-			AdrReg |= VPD_WRITE;	/* WRITE operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_WRITE);
-			if (Rtv != 0) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-					("Write Timed Out\n"));
-				return(i - (i%sizeof(SK_U32)));
-			}
-
-			/*
-			 * Now re-read to verify
-			 */
-			AdrReg &= ~VPD_WRITE;	/* READ operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_READ);
-			if (Rtv != 0) {
-				SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-					("Verify Timed Out\n"));
-				return(i - (i%sizeof(SK_U32)));
-			}
-
-			for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) {
-				
-				VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data);
-				
-				if (Data != *pComp) {
-					/* Verify Error */
-					SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-						("WriteStream Verify Error\n"));
-					return(i - (i%sizeof(SK_U32)) + j);
-				}
-			}
-		}
-	}
-
-	return(Len);
-}
-	
-
-/*
- *	Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
- *	or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdReadStream(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* data buffer */
-int		Addr,	/* VPD start address */
-int		Len)	/* number of bytes to read / to write */
-{
-	int		i;
-	SK_U16	AdrReg;
-	int		Rtv;
-
-	for (i = 0; i < Len; i++, buf++) {
-		if ((i%sizeof(SK_U32)) == 0) {
-			/* New Address needs to be written to VPD_ADDR reg */
-			AdrReg = (SK_U16) Addr;
-			Addr += sizeof(SK_U32);
-			AdrReg &= ~VPD_WRITE;	/* READ operation */
-
-			VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
-			/* Wait for termination */
-			Rtv = VpdWait(pAC, IoC, VPD_READ);
-			if (Rtv != 0) {
-				return(i);
-			}
-		}
-		VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
-			(SK_U8 *)buf);
-	}
-
-	return(Len);
-}
-
-/*
- *	Read ore writes 'len' bytes of VPD data, starting at 'addr' from
- *	or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdTransferBlock(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* data buffer */
-int		addr,	/* VPD start address */
-int		len,	/* number of bytes to read / to write */
-int		dir)	/* transfer direction may be VPD_READ or VPD_WRITE */
-{
-	int		Rtv;	/* Return value */
-	int		vpd_rom_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD %s block, addr = 0x%x, len = %d\n",
-		dir ? "write" : "read", addr, len));
-
-	if (len == 0)
-		return(0);
-
-	vpd_rom_size = pAC->vpd.rom_size;
-	
-	if (addr > vpd_rom_size - 4) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Address error: 0x%x, exp. < 0x%x\n",
-			addr, vpd_rom_size - 4));
-		return(0);
-	}
-	
-	if (addr + len > vpd_rom_size) {
-		len = vpd_rom_size - addr;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("Warning: len was cut to %d\n", len));
-	}
-
-	if (dir == VPD_READ) {
-		Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
-	}
-	else {
-		Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
-	}
-
-	return(Rtv);
-}
-
-#ifdef SKDIAG
-
-/*
- *	Read 'len' bytes of VPD data, starting at 'addr'.
- *
- * Returns number of bytes read.
- */
-int VpdReadBlock(
-SK_AC	*pAC,	/* pAC pointer */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* buffer were the data should be stored */
-int		addr,	/* start reading at the VPD address */
-int		len)	/* number of bytes to read */
-{
-	return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ));
-}
-
-/*
- *	Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
- *
- * Returns number of bytes writes.
- */
-int VpdWriteBlock(
-SK_AC	*pAC,	/* pAC pointer */
-SK_IOC	IoC,	/* IO Context */
-char	*buf,	/* buffer, holds the data to write */
-int		addr,	/* start writing at the VPD address */
-int		len)	/* number of bytes to write */
-{
-	return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE));
-}
-#endif	/* SKDIAG */
-
-/*
- * (re)initialize the VPD buffer
- *
- * Reads the VPD data from the EEPROM into the VPD buffer.
- * Get the remaining read only and read / write space.
- *
- * return	0:	success
- *		1:	fatal VPD error
- */
-static int VpdInit(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC)	/* IO Context */
-{
-	SK_VPD_PARA *r, rp;	/* RW or RV */
-	int		i;
-	unsigned char	x;
-	int		vpd_size;
-	SK_U16	dev_id;
-	SK_U32	our_reg2;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. "));
-	
-	VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id);
-	
-	VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
-	
-	pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
-	
-	/*
-	 * this function might get used before the hardware is initialized
-	 * therefore we cannot always trust in GIChipId
-	 */
-	if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 &&
-		dev_id != VPD_DEV_ID_GENESIS) ||
-		((pAC->vpd.v.vpd_status & VPD_VALID) != 0 &&
-		!pAC->GIni.GIGenesis)) {
-
-		/* for Yukon the VPD size is always 256 */
-		vpd_size = VPD_SIZE_YUKON;
-	}
-	else {
-		/* Genesis uses the maximum ROM size up to 512 for VPD */
-		if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) {
-			vpd_size = VPD_SIZE_GENESIS;
-		}
-		else {
-			vpd_size = pAC->vpd.rom_size;
-		}
-	}
-
-	/* read the VPD data into the VPD buffer */
-	if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ)
-		!= vpd_size) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("Block Read Error\n"));
-		return(1);
-	}
-	
-	pAC->vpd.vpd_size = vpd_size;
-
-	/* Asus K8V Se Deluxe bugfix. Correct VPD content */
-	/* MBo April 2004 */
-	if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) &&
-	    ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) &&
-	    ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) {
-		printk("sk98lin: Asus mainboard with buggy VPD? "
-				"Correcting data.\n");
-		pAC->vpd.vpd_buf[0x40] = 0x38;
-	}
-
-
-	/* find the end tag of the RO area */
-	if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: RV Tag not found\n"));
-		return(1);
-	}
-	
-	if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) {
-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: Invalid VPD struct size\n"));
-		return(1);
-	}
-	pAC->vpd.v.vpd_free_ro = r->p_len - 1;
-
-	/* test the checksum */
-	for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) {
-		x += pAC->vpd.vpd_buf[i];
-	}
-	
-	if (x != 0) {
-		/* checksum error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("VPD Checksum Error\n"));
-		return(1);
-	}
-
-	/* find and check the end tag of the RW area */
-	if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: RV Tag not found\n"));
-		return(1);
-	}
-	
-	if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: Invalid VPD struct size\n"));
-		return(1);
-	}
-	pAC->vpd.v.vpd_free_rw = r->p_len;
-
-	/* everything seems to be ok */
-	if (pAC->GIni.GIChipId != 0) {
-		pAC->vpd.v.vpd_status |= VPD_VALID;
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT,
-		("done. Free RO = %d, Free RW = %d\n",
-		pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
-
-	return(0);
-}
-
-/*
- *	find the Keyword 'key' in the VPD buffer and fills the
- *	parameter struct 'p' with it's values
- *
- * returns	*p	success
- *		0:	parameter was not found or VPD encoding error
- */
-static SK_VPD_PARA *vpd_find_para(
-SK_AC		*pAC,	/* common data base */
-const char	*key,	/* keyword to find (e.g. "MN") */
-SK_VPD_PARA *p)		/* parameter description struct */
-{
-	char *v	;	/* points to VPD buffer */
-	int max;	/* Maximum Number of Iterations */
-
-	v = pAC->vpd.vpd_buf;
-	max = 128;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD find para %s .. ",key));
-
-	/* check mandatory resource type ID string (Product Name) */
-	if (*v != (char)RES_ID) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Error: 0x%x missing\n", RES_ID));
-		return NULL;
-	}
-
-	if (strcmp(key, VPD_NAME) == 0) {
-		p->p_len = VPD_GET_RES_LEN(v);
-		p->p_val = VPD_GET_VAL(v);
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-			("found, len = %d\n", p->p_len));
-		return(p);
-	}
-
-	v += 3 + VPD_GET_RES_LEN(v) + 3;
-	for (;; ) {
-		if (SK_MEMCMP(key,v,2) == 0) {
-			p->p_len = VPD_GET_VPD_LEN(v);
-			p->p_val = VPD_GET_VAL(v);
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-				("found, len = %d\n",p->p_len));
-			return(p);
-		}
-
-		/* exit when reaching the "RW" Tag or the maximum of itera. */
-		max--;
-		if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
-			break;
-		}
-
-		if (SK_MEMCMP(VPD_RV,v,2) == 0) {
-			v += 3 + VPD_GET_VPD_LEN(v) + 3;	/* skip VPD-W */
-		}
-		else {
-			v += 3 + VPD_GET_VPD_LEN(v);
-		}
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-			("scanning '%c%c' len = %d\n",v[0],v[1],v[2]));
-	}
-
-#ifdef DEBUG
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n"));
-	if (max == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Key/Len Encoding error\n"));
-	}
-#endif /* DEBUG */
-	return NULL;
-}
-
-/*
- *	Move 'n' bytes. Begin with the last byte if 'n' is > 0,
- *	Start with the last byte if n is < 0.
- *
- * returns nothing
- */
-static void vpd_move_para(
-char	*start,		/* start of memory block */
-char	*end,		/* end of memory block to move */
-int		n)			/* number of bytes the memory block has to be moved */
-{
-	char *p;
-	int i;		/* number of byte copied */
-
-	if (n == 0)
-		return;
-
-	i = (int) (end - start + 1);
-	if (n < 0) {
-		p = start + n;
-		while (i != 0) {
-			*p++ = *start++;
-			i--;
-		}
-	}
-	else {
-		p = end + n;
-		while (i != 0) {
-			*p-- = *end--;
-			i--;
-		}
-	}
-}
-
-/*
- *	setup the VPD keyword 'key' at 'ip'.
- *
- * returns nothing
- */
-static void vpd_insert_key(
-const char	*key,	/* keyword to insert */
-const char	*buf,	/* buffer with the keyword value */
-int		len,		/* length of the value string */
-char	*ip)		/* inseration point */
-{
-	SK_VPD_KEY *p;
-
-	p = (SK_VPD_KEY *) ip;
-	p->p_key[0] = key[0];
-	p->p_key[1] = key[1];
-	p->p_len = (unsigned char) len;
-	SK_MEMCPY(&p->p_val,buf,len);
-}
-
-/*
- *	Setup the VPD end tag "RV" / "RW".
- *	Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
- *
- * returns	0:	success
- *		1:	encoding error
- */
-static int vpd_mod_endtag(
-SK_AC	*pAC,		/* common data base */
-char	*etp)		/* end pointer input position */
-{
-	SK_VPD_KEY *p;
-	unsigned char	x;
-	int	i;
-	int	vpd_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1]));
-
-	vpd_size = pAC->vpd.vpd_size;
-
-	p = (SK_VPD_KEY *) etp;
-
-	if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
-		/* something wrong here, encoding error */
-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
-			("Encoding Error: invalid end tag\n"));
-		return(1);
-	}
-	if (etp > pAC->vpd.vpd_buf + vpd_size/2) {
-		/* create "RW" tag */
-		p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1);
-		pAC->vpd.v.vpd_free_rw = (int) p->p_len;
-		i = pAC->vpd.v.vpd_free_rw;
-		etp += 3;
-	}
-	else {
-		/* create "RV" tag */
-		p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3);
-		pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1;
-
-		/* setup checksum */
-		for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) {
-			x += pAC->vpd.vpd_buf[i];
-		}
-		p->p_val = (char) 0 - x;
-		i = pAC->vpd.v.vpd_free_ro;
-		etp += 4;
-	}
-	while (i) {
-		*etp++ = 0x00;
-		i--;
-	}
-
-	return(0);
-}
-
-/*
- *	Insert a VPD keyword into the VPD buffer.
- *
- *	The keyword 'key' is inserted at the position 'ip' in the
- *	VPD buffer.
- *	The keywords behind the input position will
- *	be moved. The VPD end tag "RV" or "RW" is generated again.
- *
- * returns	0:	success
- *		2:	value string was cut
- *		4:	VPD full, keyword was not written
- *		6:	fatal VPD error
- *
- */
-static int	VpdSetupPara(
-SK_AC	*pAC,		/* common data base */
-const char	*key,	/* keyword to insert */
-const char	*buf,	/* buffer with the keyword value */
-int		len,		/* length of the keyword value */
-int		type,		/* VPD_RO_KEY or VPD_RW_KEY */
-int		op)			/* operation to do: ADD_KEY or OWR_KEY */
-{
-	SK_VPD_PARA vp;
-	char	*etp;		/* end tag position */
-	int	free;		/* remaining space in selected area */
-	char	*ip;		/* input position inside the VPD buffer */
-	int	rtv;		/* return code */
-	int	head;		/* additional haeder bytes to move */
-	int	found;		/* additinoal bytes if the keyword was found */
-	int vpd_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("VPD setup para key = %s, val = %s\n",key,buf));
-	
-	vpd_size = pAC->vpd.vpd_size;
-
-	rtv = 0;
-	ip = NULL;
-	if (type == VPD_RW_KEY) {
-		/* end tag is "RW" */
-		free = pAC->vpd.v.vpd_free_rw;
-		etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3);
-	}
-	else {
-		/* end tag is "RV" */
-		free = pAC->vpd.v.vpd_free_ro;
-		etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4);
-	}
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-		("Free RO = %d, Free RW = %d\n",
-		pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
-
-	head = 0;
-	found = 0;
-	if (op == OWR_KEY) {
-		if (vpd_find_para(pAC, key, &vp)) {
-			found = 3;
-			ip = vp.p_val - 3;
-			free += vp.p_len + 3;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-				("Overwrite Key\n"));
-		}
-		else {
-			op = ADD_KEY;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
-				("Add Key\n"));
-		}
-	}
-	if (op == ADD_KEY) {
-		ip = etp;
-		vp.p_len = 0;
-		head = 3;
-	}
-
-	if (len + 3 > free) {
-		if (free < 7) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD Buffer Overflow, keyword not written\n"));
-			return(4);
-		}
-		/* cut it again */
-		len = free - 3;
-		rtv = 2;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("VPD Buffer Full, Keyword was cut\n"));
-	}
-
-	vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head);
-	vpd_insert_key(key, buf, len, ip);
-	if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
-		pAC->vpd.v.vpd_status &= ~VPD_VALID;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("VPD Encoding Error\n"));
-		return(6);
-	}
-
-	return(rtv);
-}
-
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the
- *	VPD buffer if not already done.
- *
- * return:	A pointer to the vpd_status structure. The structure contains
- *		this fields.
- */
-SK_VPD_STATUS *VpdStat(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC)	/* IO Context */
-{
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		(void)VpdInit(pAC, IoC);
-	}
-	return(&pAC->vpd.v);
-}
-
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the VPD
- *	buffer if not already done.
- *	Scan the VPD buffer for VPD keywords and create the VPD
- *	keyword list by copying the keywords to 'buf', all after
- *	each other and terminated with a '\0'.
- *
- * Exceptions:	o The Resource Type ID String (product name) is called "Name"
- *		o The VPD end tags 'RV' and 'RW' are not listed
- *
- *	The number of copied keywords is counted in 'elements'.
- *
- * returns	0:	success
- *		2:	buffer overfull, one or more keywords are missing
- *		6:	fatal VPD error
- *
- *	example values after returning:
- *
- *		buf =	"Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0"
- *		*len =		30
- *		*elements =	 9
- */
-int VpdKeys(
-SK_AC	*pAC,		/* common data base */
-SK_IOC	IoC,		/* IO Context */
-char	*buf,		/* buffer where to copy the keywords */
-int		*len,		/* buffer length */
-int		*elements)	/* number of keywords returned */
-{
-	char *v;
-	int n;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. "));
-	*elements = 0;
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			*len = 0;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD Init Error, terminated\n"));
-			return(6);
-		}
-	}
-
-	if ((signed)strlen(VPD_NAME) + 1 <= *len) {
-		v = pAC->vpd.vpd_buf;
-		strcpy(buf,VPD_NAME);
-		n = strlen(VPD_NAME) + 1;
-		buf += n;
-		*elements = 1;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
-			("'%c%c' ",v[0],v[1]));
-	}
-	else {
-		*len = 0;
-		SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
-			("buffer overflow\n"));
-		return(2);
-	}
-
-	v += 3 + VPD_GET_RES_LEN(v) + 3;
-	for (;; ) {
-		/* exit when reaching the "RW" Tag */
-		if (SK_MEMCMP(VPD_RW,v,2) == 0) {
-			break;
-		}
-
-		if (SK_MEMCMP(VPD_RV,v,2) == 0) {
-			v += 3 + VPD_GET_VPD_LEN(v) + 3;	/* skip VPD-W */
-			continue;
-		}
-
-		if (n+3 <= *len) {
-			SK_MEMCPY(buf,v,2);
-			buf += 2;
-			*buf++ = '\0';
-			n += 3;
-			v += 3 + VPD_GET_VPD_LEN(v);
-			*elements += 1;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
-				("'%c%c' ",v[0],v[1]));
-		}
-		else {
-			*len = n;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("buffer overflow\n"));
-			return(2);
-		}
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n"));
-	*len = n;
-	return(0);
-}
-
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the
- *	VPD buffer if not already done. Search for the VPD keyword
- *	'key' and copy its value to 'buf'. Add a terminating '\0'.
- *	If the value does not fit into the buffer cut it after
- *	'len' - 1 bytes.
- *
- * returns	0:	success
- *		1:	keyword not found
- *		2:	value string was cut
- *		3:	VPD transfer timeout
- *		6:	fatal VPD error
- */
-int VpdRead(
-SK_AC		*pAC,	/* common data base */
-SK_IOC		IoC,	/* IO Context */
-const char	*key,	/* keyword to read (e.g. "MN") */
-char		*buf,	/* buffer where to copy the keyword value */
-int			*len)	/* buffer length */
-{
-	SK_VPD_PARA *p, vp;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key));
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			*len = 0;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD init error\n"));
-			return(6);
-		}
-	}
-
-	if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
-		if (p->p_len > (*(unsigned *)len)-1) {
-			p->p_len = *len - 1;
-		}
-		SK_MEMCPY(buf, p->p_val, p->p_len);
-		buf[p->p_len] = '\0';
-		*len = p->p_len;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
-			("%c%c%c%c.., len = %d\n",
-			buf[0],buf[1],buf[2],buf[3],*len));
-	}
-	else {
-		*len = 0;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n"));
-		return(1);
-	}
-	return(0);
-}
-
-
-/*
- *	Check whether a given key may be written
- *
- * returns
- *	SK_TRUE		Yes it may be written
- *	SK_FALSE	No it may be written
- */
-SK_BOOL VpdMayWrite(
-char	*key)	/* keyword to write (allowed values "Yx", "Vx") */
-{
-	if ((*key != 'Y' && *key != 'V') ||
-		key[1] < '0' || key[1] > 'Z' ||
-		(key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
-
-		return(SK_FALSE);
-	}
-	return(SK_TRUE);
-}
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the VPD
- *	buffer if not already done. Insert/overwrite the keyword 'key'
- *	in the VPD buffer. Cut the keyword value if it does not fit
- *	into the VPD read / write area.
- *
- * returns	0:	success
- *		2:	value string was cut
- *		3:	VPD transfer timeout
- *		4:	VPD full, keyword was not written
- *		5:	keyword cannot be written
- *		6:	fatal VPD error
- */
-int VpdWrite(
-SK_AC		*pAC,	/* common data base */
-SK_IOC		IoC,	/* IO Context */
-const char	*key,	/* keyword to write (allowed values "Yx", "Vx") */
-const char	*buf)	/* buffer where the keyword value can be read from */
-{
-	int len;		/* length of the keyword to write */
-	int rtv;		/* return code */
-	int rtv2;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
-		("VPD write %s = %s\n",key,buf));
-
-	if ((*key != 'Y' && *key != 'V') ||
-		key[1] < '0' || key[1] > 'Z' ||
-		(key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("illegal key tag, keyword not written\n"));
-		return(5);
-	}
-
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD init error\n"));
-			return(6);
-		}
-	}
-
-	rtv = 0;
-	len = strlen(buf);
-	if (len > VPD_MAX_LEN) {
-		/* cut it */
-		len = VPD_MAX_LEN;
-		rtv = 2;
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("keyword too long, cut after %d bytes\n",VPD_MAX_LEN));
-	}
-	if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("VPD write error\n"));
-		return(rtv2);
-	}
-
-	return(rtv);
-}
-
-/*
- *	Read the contents of the VPD EEPROM and copy it to the
- *	VPD buffer if not already done. Remove the VPD keyword
- *	'key' from the VPD buffer.
- *	Only the keywords in the read/write area can be deleted.
- *	Keywords in the read only area cannot be deleted.
- *
- * returns	0:	success, keyword was removed
- *		1:	keyword not found
- *		5:	keyword cannot be deleted
- *		6:	fatal VPD error
- */
-int VpdDelete(
-SK_AC	*pAC,	/* common data base */
-SK_IOC	IoC,	/* IO Context */
-char	*key)	/* keyword to read (e.g. "MN") */
-{
-	SK_VPD_PARA *p, vp;
-	char *etp;
-	int	vpd_size;
-
-	vpd_size = pAC->vpd.vpd_size;
-
-	SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key));
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
-		if (VpdInit(pAC, IoC) != 0) {
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD init error\n"));
-			return(6);
-		}
-	}
-
-	if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
-		if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
-			/* try to delete read only keyword */
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("cannot delete RO keyword\n"));
-			return(5);
-		}
-
-		etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3);
-
-		vpd_move_para(vp.p_val+vp.p_len, etp+2,
-			- ((int)(vp.p_len + 3)));
-		if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
-			pAC->vpd.v.vpd_status &= ~VPD_VALID;
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("VPD encoding error\n"));
-			return(6);
-		}
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-			("keyword not found\n"));
-		return(1);
-	}
-
-	return(0);
-}
-
-/*
- *	If the VPD buffer contains valid data write the VPD
- *	read/write area back to the VPD EEPROM.
- *
- * returns	0:	success
- *		3:	VPD transfer timeout
- */
-int VpdUpdate(
-SK_AC	*pAC,	/* Adapters context */
-SK_IOC	IoC)	/* IO Context */
-{
-	int vpd_size;
-
-	vpd_size = pAC->vpd.vpd_size;
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. "));
-	if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) {
-		if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2,
-			vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) {
-
-			SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
-				("transfer timed out\n"));
-			return(3);
-		}
-	}
-	SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n"));
-	return(0);
-}
-
diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c
deleted file mode 100644
index b4e7502..0000000
--- a/drivers/net/sk98lin/skxmac2.c
+++ /dev/null
@@ -1,4160 +0,0 @@
-/******************************************************************************
- *
- * Name:	skxmac2.c
- * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.102 $
- * Date:	$Date: 2003/10/02 16:53:58 $
- * Purpose:	Contains functions to initialize the MACs and PHYs
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *	(C)Copyright 1998-2002 SysKonnect.
- *	(C)Copyright 2002-2003 Marvell.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* typedefs *******************************************************************/
-
-/* BCOM PHY magic pattern list */
-typedef struct s_PhyHack {
-	int		PhyReg;		/* Phy register */
-	SK_U16	PhyVal;		/* Value to write */
-} BCOM_HACK;
-
-/* local variables ************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
-	"@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#ifdef GENESIS
-static BCOM_HACK BcomRegA1Hack[] = {
- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
- { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
- { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
- { 0, 0 }
-};
-static BCOM_HACK BcomRegC0Hack[] = {
- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
- { 0x15, 0x0A04 }, { 0x18, 0x0420 },
- { 0, 0 }
-};
-#endif
-
-/* function prototypes ********************************************************/
-#ifdef GENESIS
-static void	SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
-static int	SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
-#endif /* GENESIS */
-#ifdef YUKON
-static void	SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
-#endif /* YUKON */
-#ifdef OTHER_PHY
-static void	SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
-static void	SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
-static int	SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
-static int	SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
-#endif /* OTHER_PHY */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmPhyRead() - Read from XMAC PHY register
- *
- * Description:	reads a 16-bit word from XMAC PHY or ext. PHY
- *
- * Returns:
- *	nothing
- */
-void SkXmPhyRead(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-int		Port,			/* Port Index (MAC_1 + n) */
-int		PhyReg,			/* Register Address (Offset) */
-SK_U16	SK_FAR *pVal)	/* Pointer to Value */
-{
-	SK_U16		Mmu;
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	/* write the PHY register's address */
-	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
-	
-	/* get the PHY register's value */
-	XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
-	
-	if (pPrt->PhyType != SK_PHY_XMAC) {
-		do {
-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
-			/* wait until 'Ready' is set */
-		} while ((Mmu & XM_MMU_PHY_RDY) == 0);
-
-		/* get the PHY register's value */
-		XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
-	}
-}	/* SkXmPhyRead */
-
-
-/******************************************************************************
- *
- *	SkXmPhyWrite() - Write to XMAC PHY register
- *
- * Description:	writes a 16-bit word to XMAC PHY or ext. PHY
- *
- * Returns:
- *	nothing
- */
-void SkXmPhyWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	Val)		/* Value */
-{
-	SK_U16		Mmu;
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	if (pPrt->PhyType != SK_PHY_XMAC) {
-		do {
-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
-			/* wait until 'Busy' is cleared */
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
-	}
-	
-	/* write the PHY register's address */
-	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
-	
-	/* write the PHY register's value */
-	XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
-	
-	if (pPrt->PhyType != SK_PHY_XMAC) {
-		do {
-			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
-			/* wait until 'Busy' is cleared */
-		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
-	}
-}	/* SkXmPhyWrite */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmPhyRead() - Read from GPHY register
- *
- * Description:	reads a 16-bit word from GPHY through MDIO
- *
- * Returns:
- *	nothing
- */
-void SkGmPhyRead(
-SK_AC	*pAC,			/* Adapter Context */
-SK_IOC	IoC,			/* I/O Context */
-int		Port,			/* Port Index (MAC_1 + n) */
-int		PhyReg,			/* Register Address (Offset) */
-SK_U16	SK_FAR *pVal)	/* Pointer to Value */
-{
-	SK_U16	Ctrl;
-	SK_GEPORT	*pPrt;
-#ifdef VCPU
-	u_long SimCyle;
-	u_long SimLowTime;
-	
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
-		PhyReg, SimCyle, SimLowTime);
-#endif /* VCPU */
-	
-	pPrt = &pAC->GIni.GP[Port];
-	
-	/* set PHY-Register offset and 'Read' OpCode (= 1) */
-	*pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
-		GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
-
-	GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
-
-	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-	
-	/* additional check for MDC/MDIO activity */
-	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
-		*pVal = 0;
-		return;
-	}
-
-	*pVal |= GM_SMI_CT_BUSY;
-	
-	do {
-#ifdef VCPU
-		VCPUwaitTime(1000);
-#endif /* VCPU */
-
-		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
-	/* wait until 'ReadValid' is set */
-	} while (Ctrl == *pVal);
-	
-	/* get the PHY register's value */
-	GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
-
-#ifdef VCPU
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
-		SimCyle, SimLowTime);
-#endif /* VCPU */
-
-}	/* SkGmPhyRead */
-
-
-/******************************************************************************
- *
- *	SkGmPhyWrite() - Write to GPHY register
- *
- * Description:	writes a 16-bit word to GPHY through MDIO
- *
- * Returns:
- *	nothing
- */
-void SkGmPhyWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	Val)		/* Value */
-{
-	SK_U16	Ctrl;
-	SK_GEPORT	*pPrt;
-#ifdef VCPU
-	SK_U32	DWord;
-	u_long	SimCyle;
-	u_long	SimLowTime;
-	
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
-		PhyReg, Val, SimCyle, SimLowTime);
-#endif /* VCPU */
-	
-	pPrt = &pAC->GIni.GP[Port];
-	
-	/* write the PHY register's value */
-	GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
-	
-	/* set PHY-Register offset and 'Write' OpCode (= 0) */
-	Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
-
-	GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
-
-	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-	
-	/* additional check for MDC/MDIO activity */
-	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
-		return;
-	}
-	
-	Val |= GM_SMI_CT_BUSY;
-
-	do {
-#ifdef VCPU
-		/* read Timer value */
-		SK_IN32(IoC, B2_TI_VAL, &DWord);
-
-		VCPUwaitTime(1000);
-#endif /* VCPU */
-
-		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
-	/* wait until 'Busy' is cleared */
-	} while (Ctrl == Val);
-	
-#ifdef VCPU
-	VCPUgetTime(&SimCyle, &SimLowTime);
-	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
-		SimCyle, SimLowTime);
-#endif /* VCPU */
-
-}	/* SkGmPhyWrite */
-#endif /* YUKON */
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- *	SkGePhyRead() - Read from PHY register
- *
- * Description:	calls a read PHY routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkGePhyRead(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	*pVal)		/* Pointer to Value */
-{
-	void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
-
-	if (pAC->GIni.GIGenesis) {
-		r_func = SkXmPhyRead;
-	}
-	else {
-		r_func = SkGmPhyRead;
-	}
-	
-	r_func(pAC, IoC, Port, PhyReg, pVal);
-}	/* SkGePhyRead */
-
-
-/******************************************************************************
- *
- *	SkGePhyWrite() - Write to PHY register
- *
- * Description:	calls a write PHY routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkGePhyWrite(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* I/O Context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		PhyReg,		/* Register Address (Offset) */
-SK_U16	Val)		/* Value */
-{
-	void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
-
-	if (pAC->GIni.GIGenesis) {
-		w_func = SkXmPhyWrite;
-	}
-	else {
-		w_func = SkGmPhyWrite;
-	}
-	
-	w_func(pAC, IoC, Port, PhyReg, Val);
-}	/* SkGePhyWrite */
-#endif /* SK_DIAG */
-
-
-/******************************************************************************
- *
- *	SkMacPromiscMode() - Enable / Disable Promiscuous Mode
- *
- * Description:
- *   enables / disables promiscuous mode by setting Mode Register (XMAC) or
- *   Receive Control Register (GMAC) dep. on board type   	
- *
- * Returns:
- *	nothing
- */
-void SkMacPromiscMode(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-#ifdef YUKON
-	SK_U16	RcReg;
-#endif
-#ifdef GENESIS
-	SK_U32	MdReg;
-#endif	
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-		/* enable or disable promiscuous mode */
-		if (Enable) {
-			MdReg |= XM_MD_ENA_PROM;
-		}
-		else {
-			MdReg &= ~XM_MD_ENA_PROM;
-		}
-		/* setup Mode Register */
-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
-		
-		/* enable or disable unicast and multicast filtering */
-		if (Enable) {
-			RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
-		}
-		else {
-			RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
-		}
-		/* setup Receive Control Register */
-		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
-	}
-#endif /* YUKON */
-
-}	/* SkMacPromiscMode*/
-
-
-/******************************************************************************
- *
- *	SkMacHashing() - Enable / Disable Hashing
- *
- * Description:
- *   enables / disables hashing by setting Mode Register (XMAC) or
- *   Receive Control Register (GMAC) dep. on board type		
- *
- * Returns:
- *	nothing
- */
-void SkMacHashing(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-#ifdef YUKON
-	SK_U16	RcReg;
-#endif	
-#ifdef GENESIS
-	SK_U32	MdReg;
-#endif
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-		/* enable or disable hashing */
-		if (Enable) {
-			MdReg |= XM_MD_ENA_HASH;
-		}
-		else {
-			MdReg &= ~XM_MD_ENA_HASH;
-		}
-		/* setup Mode Register */
-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
-		
-		/* enable or disable multicast filtering */
-		if (Enable) {
-			RcReg |= GM_RXCR_MCF_ENA;
-		}
-		else {
-			RcReg &= ~GM_RXCR_MCF_ENA;
-		}
-		/* setup Receive Control Register */
-		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
-	}
-#endif /* YUKON */
-
-}	/* SkMacHashing*/
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- *	SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
- *
- * Description:
- *	The features
- *	 - FCS stripping,					SK_STRIP_FCS_ON/OFF
- *	 - pad byte stripping,				SK_STRIP_PAD_ON/OFF
- *	 - don't set XMR_FS_ERR in status	SK_LENERR_OK_ON/OFF
- *	   for inrange length error frames
- *	 - don't set XMR_FS_ERR in status	SK_BIG_PK_OK_ON/OFF
- *	   for frames > 1514 bytes
- *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
- *
- *	for incoming packets may be enabled/disabled by this function.
- *	Additional modes may be added later.
- *	Multiple modes can be enabled/disabled at the same time.
- *	The new configuration is written to the Rx Command register immediately.
- *
- * Returns:
- *	nothing
- */
-static void SkXmSetRxCmd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
-					   SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
-{
-	SK_U16	OldRxCmd;
-	SK_U16	RxCmd;
-
-	XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
-
-	RxCmd = OldRxCmd;
-	
-	switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
-	case SK_STRIP_FCS_ON:
-		RxCmd |= XM_RX_STRIP_FCS;
-		break;
-	case SK_STRIP_FCS_OFF:
-		RxCmd &= ~XM_RX_STRIP_FCS;
-		break;
-	}
-
-	switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
-	case SK_STRIP_PAD_ON:
-		RxCmd |= XM_RX_STRIP_PAD;
-		break;
-	case SK_STRIP_PAD_OFF:
-		RxCmd &= ~XM_RX_STRIP_PAD;
-		break;
-	}
-
-	switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
-	case SK_LENERR_OK_ON:
-		RxCmd |= XM_RX_LENERR_OK;
-		break;
-	case SK_LENERR_OK_OFF:
-		RxCmd &= ~XM_RX_LENERR_OK;
-		break;
-	}
-
-	switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
-	case SK_BIG_PK_OK_ON:
-		RxCmd |= XM_RX_BIG_PK_OK;
-		break;
-	case SK_BIG_PK_OK_OFF:
-		RxCmd &= ~XM_RX_BIG_PK_OK;
-		break;
-	}
-
-	switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
-	case SK_SELF_RX_ON:
-		RxCmd |= XM_RX_SELF_RX;
-		break;
-	case SK_SELF_RX_OFF:
-		RxCmd &= ~XM_RX_SELF_RX;
-		break;
-	}
-
-	/* Write the new mode to the Rx command register if required */
-	if (OldRxCmd != RxCmd) {
-		XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
-	}
-}	/* SkXmSetRxCmd */
-
-
-/******************************************************************************
- *
- *	SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
- *
- * Description:
- *	The features
- *	 - FCS (CRC) stripping,				SK_STRIP_FCS_ON/OFF
- *	 - don't set GMR_FS_LONG_ERR		SK_BIG_PK_OK_ON/OFF
- *	   for frames > 1514 bytes
- *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
- *
- *	for incoming packets may be enabled/disabled by this function.
- *	Additional modes may be added later.
- *	Multiple modes can be enabled/disabled at the same time.
- *	The new configuration is written to the Rx Command register immediately.
- *
- * Returns:
- *	nothing
- */
-static void SkGmSetRxCmd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		Mode)		/* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
-					   SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
-{
-	SK_U16	OldRxCmd;
-	SK_U16	RxCmd;
-
-	if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
-		
-		GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
-
-		RxCmd = OldRxCmd;
-
-		if ((Mode & SK_STRIP_FCS_ON) != 0) {
-			RxCmd |= GM_RXCR_CRC_DIS;
-		}
-		else {
-			RxCmd &= ~GM_RXCR_CRC_DIS;
-		}
-		/* Write the new mode to the Rx control register if required */
-		if (OldRxCmd != RxCmd) {
-			GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
-		}
-	}
-
-	if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
-		
-		GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
-
-		RxCmd = OldRxCmd;
-
-		if ((Mode & SK_BIG_PK_OK_ON) != 0) {
-			RxCmd |= GM_SMOD_JUMBO_ENA;
-		}
-		else {
-			RxCmd &= ~GM_SMOD_JUMBO_ENA;
-		}
-		/* Write the new mode to the Rx control register if required */
-		if (OldRxCmd != RxCmd) {
-			GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
-		}
-	}
-}	/* SkGmSetRxCmd */
-
-
-/******************************************************************************
- *
- *	SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
- *
- * Description:	modifies the MAC's Rx Control reg. dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacSetRxCmd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		Mode)		/* Rx Mode */
-{
-	if (pAC->GIni.GIGenesis) {
-		
-		SkXmSetRxCmd(pAC, IoC, Port, Mode);
-	}
-	else {
-		
-		SkGmSetRxCmd(pAC, IoC, Port, Mode);
-	}
-
-}	/* SkMacSetRxCmd */
-
-
-/******************************************************************************
- *
- *	SkMacCrcGener() - Enable / Disable CRC Generation
- *
- * Description:	enables / disables CRC generation dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacCrcGener(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-	SK_U16	Word;
-
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN16(IoC, Port, XM_TX_CMD, &Word);
-
-		if (Enable) {
-			Word &= ~XM_TX_NO_CRC;
-		}
-		else {
-			Word |= XM_TX_NO_CRC;
-		}
-		/* setup Tx Command Register */
-		XM_OUT16(IoC, Port, XM_TX_CMD, Word);
-	}
-	else {
-		
-		GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
-		
-		if (Enable) {
-			Word &= ~GM_TXCR_CRC_DIS;
-		}
-		else {
-			Word |= GM_TXCR_CRC_DIS;
-		}
-		/* setup Tx Control Register */
-		GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
-	}
-
-}	/* SkMacCrcGener*/
-
-#endif /* SK_DIAG */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmClrExactAddr() - Clear Exact Match Address Registers
- *
- * Description:
- *	All Exact Match Address registers of the XMAC 'Port' will be
- *	cleared starting with 'StartNum' up to (and including) the
- *	Exact Match address number of 'StopNum'.
- *
- * Returns:
- *	nothing
- */
-void SkXmClrExactAddr(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-int		StartNum,	/* Begin with this Address Register Index (0..15) */
-int		StopNum)	/* Stop after finished with this Register Idx (0..15) */
-{
-	int		i;
-	SK_U16	ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
-
-	if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
-		StartNum > StopNum) {
-
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
-		return;
-	}
-
-	for (i = StartNum; i <= StopNum; i++) {
-		XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
-	}
-}	/* SkXmClrExactAddr */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
- *
- * Description:
- *	Flush the transmit FIFO of the MAC specified by the index 'Port'
- *
- * Returns:
- *	nothing
- */
-void SkMacFlushTxFifo(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
-	SK_U32	MdReg;
-
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* no way to flush the FIFO we have to issue a reset */
-		/* TBD */
-	}
-#endif /* YUKON */
-
-}	/* SkMacFlushTxFifo */
-
-
-/******************************************************************************
- *
- *	SkMacFlushRxFifo() - Flush the MAC's receive FIFO
- *
- * Description:
- *	Flush the receive FIFO of the MAC specified by the index 'Port'
- *
- * Returns:
- *	nothing
- */
-static void SkMacFlushRxFifo(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
-	SK_U32	MdReg;
-
-	if (pAC->GIni.GIGenesis) {
-
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* no way to flush the FIFO we have to issue a reset */
-		/* TBD */
-	}
-#endif /* YUKON */
-
-}	/* SkMacFlushRxFifo */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmSoftRst() - Do a XMAC software reset
- *
- * Description:
- *	The PHY registers should not be destroyed during this
- *	kind of software reset. Therefore the XMAC Software Reset
- *	(XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
- *
- *	The software reset is done by
- *		- disabling the Rx and Tx state machine,
- *		- resetting the statistics module,
- *		- clear all other significant XMAC Mode,
- *		  Command, and Control Registers
- *		- clearing the Hash Register and the
- *		  Exact Match Address registers, and
- *		- flushing the XMAC's Rx and Tx FIFOs.
- *
- * Note:
- *	Another requirement when stopping the XMAC is to
- *	avoid sending corrupted frames on the network.
- *	Disabling the Tx state machine will NOT interrupt
- *	the currently transmitted frame. But we must take care
- *	that the Tx FIFO is cleared AFTER the current frame
- *	is complete sent to the network.
- *
- *	It takes about 12ns to send a frame with 1538 bytes.
- *	One PCI clock goes at least 15ns (66MHz). Therefore
- *	after reading XM_GP_PORT back, we are sure that the
- *	transmitter is disabled AND idle. And this means
- *	we may flush the transmit FIFO now.
- *
- * Returns:
- *	nothing
- */
-static void SkXmSoftRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U16	ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
-	
-	/* reset the statistics module */
-	XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
-
-	/* disable all XMAC IRQs */
-	XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
-	
-	XM_OUT32(IoC, Port, XM_MODE, 0);		/* clear Mode Reg */
-	
-	XM_OUT16(IoC, Port, XM_TX_CMD, 0);		/* reset TX CMD Reg */
-	XM_OUT16(IoC, Port, XM_RX_CMD, 0);		/* reset RX CMD Reg */
-	
-	/* disable all PHY IRQs */
-	switch (pAC->GIni.GP[Port].PhyType) {
-	case SK_PHY_BCOM:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
-			break;
-		case SK_PHY_NAT:
-			/* todo: National
-			 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
-			break;
-#endif /* OTHER_PHY */
-	}
-
-	/* clear the Hash Register */
-	XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
-
-	/* clear the Exact Match Address registers */
-	SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
-	
-	/* clear the Source Check Address registers */
-	XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
-
-}	/* SkXmSoftRst */
-
-
-/******************************************************************************
- *
- *	SkXmHardRst() - Do a XMAC hardware reset
- *
- * Description:
- *	The XMAC of the specified 'Port' and all connected devices
- *	(PHY and SERDES) will receive a reset signal on its *Reset pins.
- *	External PHYs must be reset by clearing a bit in the GPIO register
- *  (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
- *
- * ATTENTION:
- * 	It is absolutely necessary to reset the SW_RST Bit first
- *	before calling this function.
- *
- * Returns:
- *	nothing
- */
-static void SkXmHardRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	Reg;
-	int		i;
-	int		TOut;
-	SK_U16	Word;
-
-	for (i = 0; i < 4; i++) {
-		/* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
-
-		TOut = 0;
-		do {
-			if (TOut++ > 10000) {
-				/*
-				 * Adapter seems to be in RESET state.
-				 * Registers cannot be written.
-				 */
-				return;
-			}
-
-			SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
-			
-			SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
-		
-		} while ((Word & MFF_SET_MAC_RST) == 0);
-	}
-
-	/* For external PHYs there must be special handling */
-	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
-		
-		SK_IN32(IoC, B2_GP_IO, &Reg);
-		
-		if (Port == 0) {
-			Reg |= GP_DIR_0; 	/* set to output */
-			Reg &= ~GP_IO_0;	/* set PHY reset (active low) */
-		}
-		else {
-			Reg |= GP_DIR_2;	/* set to output */
-			Reg &= ~GP_IO_2;	/* set PHY reset (active low) */
-		}
-		/* reset external PHY */
-		SK_OUT32(IoC, B2_GP_IO, Reg);
-
-		/* short delay */
-		SK_IN32(IoC, B2_GP_IO, &Reg);
-	}
-}	/* SkXmHardRst */
-
-
-/******************************************************************************
- *
- *	SkXmClearRst() - Release the PHY & XMAC reset
- *
- * Description:
- *
- * Returns:
- *	nothing
- */
-static void SkXmClearRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	DWord;
-	
-	/* clear HW reset */
-	SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
-
-	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
-
-		SK_IN32(IoC, B2_GP_IO, &DWord);
-
-		if (Port == 0) {
-			DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
-		}
-		else {
-			DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
-		}
-		/* Clear PHY reset */
-		SK_OUT32(IoC, B2_GP_IO, DWord);
-
-		/* Enable GMII interface */
-		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
-	}
-}	/* SkXmClearRst */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmSoftRst() - Do a GMAC software reset
- *
- * Description:
- *	The GPHY registers should not be destroyed during this
- *	kind of software reset.
- *
- * Returns:
- *	nothing
- */
-static void SkGmSoftRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U16	EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
-	SK_U16  RxCtrl;
-
-	/* reset the statistics module */
-
-	/* disable all GMAC IRQs */
-	SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
-	
-	/* disable all PHY IRQs */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
-	
-	/* clear the Hash Register */
-	GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
-
-	/* Enable Unicast and Multicast filtering */
-	GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
-	
-	GM_OUT16(IoC, Port, GM_RX_CTRL,
-		(SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
-
-}	/* SkGmSoftRst */
-
-
-/******************************************************************************
- *
- *	SkGmHardRst() - Do a GMAC hardware reset
- *
- * Description:
- *
- * Returns:
- *	nothing
- */
-static void SkGmHardRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	DWord;
-	
-	/* WA code for COMA mode */
-	if (pAC->GIni.GIYukonLite &&
-		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-		
-		SK_IN32(IoC, B2_GP_IO, &DWord);
-
-		DWord |= (GP_DIR_9 | GP_IO_9);
-
-		/* set PHY reset */
-		SK_OUT32(IoC, B2_GP_IO, DWord);
-	}
-
-	/* set GPHY Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
-
-	/* set GMAC Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-
-}	/* SkGmHardRst */
-
-
-/******************************************************************************
- *
- *	SkGmClearRst() - Release the GPHY & GMAC reset
- *
- * Description:
- *
- * Returns:
- *	nothing
- */
-static void SkGmClearRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U32	DWord;
-	
-#ifdef XXX
-		/* clear GMAC Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
-
-		/* set GMAC Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-#endif /* XXX */
-
-	/* WA code for COMA mode */
-	if (pAC->GIni.GIYukonLite &&
-		pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-		
-		SK_IN32(IoC, B2_GP_IO, &DWord);
-
-		DWord |= GP_DIR_9;		/* set to output */
-		DWord &= ~GP_IO_9;		/* clear PHY reset (active high) */
-
-		/* clear PHY reset */
-		SK_OUT32(IoC, B2_GP_IO, DWord);
-	}
-
-	/* set HWCFG_MODE */
-	DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
-		GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
-		(pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
-		GPC_HWCFG_GMII_FIB);
-
-	/* set GPHY Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
-
-	/* release GPHY Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
-
-#ifdef VCPU
-	VCpuWait(9000);
-#endif /* VCPU */
-
-	/* clear GMAC Control reset */
-	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
-
-#ifdef VCPU
-	VCpuWait(2000);
-	
-	SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
-			
-	SK_IN32(IoC, B0_ISRC, &DWord);
-#endif /* VCPU */
-
-}	/* SkGmClearRst */
-#endif /* YUKON */
-
-
-/******************************************************************************
- *
- *	SkMacSoftRst() - Do a MAC software reset
- *
- * Description:	calls a MAC software reset routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacSoftRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* disable receiver and transmitter */
-	SkMacRxTxDisable(pAC, IoC, Port);
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		SkXmSoftRst(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		SkGmSoftRst(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-
-	/* flush the MAC's Rx and Tx FIFOs */
-	SkMacFlushTxFifo(pAC, IoC, Port);
-	
-	SkMacFlushRxFifo(pAC, IoC, Port);
-
-	pPrt->PState = SK_PRT_STOP;
-
-}	/* SkMacSoftRst */
-
-
-/******************************************************************************
- *
- *	SkMacHardRst() - Do a MAC hardware reset
- *
- * Description:	calls a MAC hardware reset routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacHardRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* Port Index (MAC_1 + n) */
-{
-	
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		SkXmHardRst(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		SkGmHardRst(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-
-	pAC->GIni.GP[Port].PState = SK_PRT_RESET;
-
-}	/* SkMacHardRst */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmInitMac() - Initialize the XMAC II
- *
- * Description:
- *	Initialize the XMAC of the specified port.
- *	The XMAC must be reset or stopped before calling this function.
- *
- * Note:
- *	The XMAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- *	nothing
- */
-void SkXmInitMac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	int			i;
-	SK_U16		SWord;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PState == SK_PRT_STOP) {
-		/* Port State: SK_PRT_STOP */
-		/* Verify that the reset bit is cleared */
-		SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
-
-		if ((SWord & MFF_SET_MAC_RST) != 0) {
-			/* PState does not match HW state */
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
-			/* Correct it */
-			pPrt->PState = SK_PRT_RESET;
-		}
-	}
-
-	if (pPrt->PState == SK_PRT_RESET) {
-
-		SkXmClearRst(pAC, IoC, Port);
-
-		if (pPrt->PhyType != SK_PHY_XMAC) {
-			/* read Id from external PHY (all have the same address) */
-			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
-
-			/*
-			 * Optimize MDIO transfer by suppressing preamble.
-			 * Must be done AFTER first access to BCOM chip.
-			 */
-			XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
-			
-			XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
-
-			if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
-				/*
-				 * Workaround BCOM Errata for the C0 type.
-				 * Write magic patterns to reserved registers.
-				 */
-				i = 0;
-				while (BcomRegC0Hack[i].PhyReg != 0) {
-					SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
-						BcomRegC0Hack[i].PhyVal);
-					i++;
-				}
-			}
-			else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
-				/*
-				 * Workaround BCOM Errata for the A1 type.
-				 * Write magic patterns to reserved registers.
-				 */
-				i = 0;
-				while (BcomRegA1Hack[i].PhyReg != 0) {
-					SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
-						BcomRegA1Hack[i].PhyVal);
-					i++;
-				}
-			}
-
-			/*
-			 * Workaround BCOM Errata (#10523) for all BCom PHYs.
-			 * Disable Power Management after reset.
-			 */
-			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
-			
-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
-				(SK_U16)(SWord | PHY_B_AC_DIS_PM));
-
-			/* PHY LED initialization is done in SkGeXmitLED() */
-		}
-
-		/* Dummy read the Interrupt source register */
-		XM_IN16(IoC, Port, XM_ISRC, &SWord);
-		
-		/*
-		 * The auto-negotiation process starts immediately after
-		 * clearing the reset. The auto-negotiation process should be
-		 * started by the SIRQ, therefore stop it here immediately.
-		 */
-		SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
-
-#ifdef TEST_ONLY
-		/* temp. code: enable signal detect */
-		/* WARNING: do not override GMII setting above */
-		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
-#endif
-	}
-
-	/*
-	 * configure the XMACs Station Address
-	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
-	 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
-	 */
-	for (i = 0; i < 3; i++) {
-		/*
-		 * The following 2 statements are together endianess
-		 * independent. Remember this when changing.
-		 */
-		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
-		
-		XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
-	}
-
-	/* Tx Inter Packet Gap (XM_TX_IPG):	use default */
-	/* Tx High Water Mark (XM_TX_HI_WM):	use default */
-	/* Tx Low Water Mark (XM_TX_LO_WM):	use default */
-	/* Host Request Threshold (XM_HT_THR):	use default */
-	/* Rx Request Threshold (XM_RX_THR):	use default */
-	/* Rx Low Water Mark (XM_RX_LO_WM):	use default */
-
-	/* configure Rx High Water Mark (XM_RX_HI_WM) */
-	XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
-
-	/* Configure Tx Request Threshold */
-	SWord = SK_XM_THR_SL;				/* for single port */
-
-	if (pAC->GIni.GIMacsFound > 1) {
-		switch (pAC->GIni.GIPortUsage) {
-		case SK_RED_LINK:
-			SWord = SK_XM_THR_REDL;		/* redundant link */
-			break;
-		case SK_MUL_LINK:
-			SWord = SK_XM_THR_MULL;		/* load balancing */
-			break;
-		case SK_JUMBO_LINK:
-			SWord = SK_XM_THR_JUMBO;	/* jumbo frames */
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
-			break;
-		}
-	}
-	XM_OUT16(IoC, Port, XM_TX_THR, SWord);
-
-	/* setup register defaults for the Tx Command Register */
-	XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
-
-	/* setup register defaults for the Rx Command Register */
-	SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
-
-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-		SWord |= XM_RX_BIG_PK_OK;
-	}
-
-	if (pPrt->PLinkMode == SK_LMODE_HALF) {
-		/*
-		 * If in manual half duplex mode the other side might be in
-		 * full duplex mode, so ignore if a carrier extension is not seen
-		 * on frames received
-		 */
-		SWord |= XM_RX_DIS_CEXT;
-	}
-	
-	XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
-
-	/*
-	 * setup register defaults for the Mode Register
-	 *	- Don't strip error frames to avoid Store & Forward
-	 *	  on the Rx side.
-	 *	- Enable 'Check Station Address' bit
-	 *	- Enable 'Check Address Array' bit
-	 */
-	XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
-
-	/*
-	 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
-	 *	- Enable all bits excepting 'Octets Rx OK Low CntOv'
-	 *	  and 'Octets Rx OK Hi Cnt Ov'.
-	 */
-	XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
-
-	/*
-	 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
-	 *	- Enable all bits excepting 'Octets Tx OK Low CntOv'
-	 *	  and 'Octets Tx OK Hi Cnt Ov'.
-	 */
-	XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
-
-	/*
-	 * Do NOT init XMAC interrupt mask here.
-	 * All interrupts remain disable until link comes up!
-	 */
-
-	/*
-	 * Any additional configuration changes may be done now.
-	 * The last action is to enable the Rx and Tx state machine.
-	 * This should be done after the auto-negotiation process
-	 * has been completed successfully.
-	 */
-}	/* SkXmInitMac */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmInitMac() - Initialize the GMAC
- *
- * Description:
- *	Initialize the GMAC of the specified port.
- *	The GMAC must be reset or stopped before calling this function.
- *
- * Note:
- *	The GMAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- *	nothing
- */
-void SkGmInitMac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	int			i;
-	SK_U16		SWord;
-	SK_U32		DWord;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PState == SK_PRT_STOP) {
-		/* Port State: SK_PRT_STOP */
-		/* Verify that the reset bit is cleared */
-		SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
-		
-		if ((DWord & GMC_RST_SET) != 0) {
-			/* PState does not match HW state */
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
-			/* Correct it */
-			pPrt->PState = SK_PRT_RESET;
-		}
-	}
-
-	if (pPrt->PState == SK_PRT_RESET) {
-		
-		SkGmHardRst(pAC, IoC, Port);
-
-		SkGmClearRst(pAC, IoC, Port);
-		
-		/* Auto-negotiation ? */
-		if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-			/* Auto-negotiation disabled */
-
-			/* get General Purpose Control */
-			GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
-
-			/* disable auto-update for speed, duplex and flow-control */
-			SWord |= GM_GPCR_AU_ALL_DIS;
-			
-			/* setup General Purpose Control Register */
-			GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
-			
-			SWord = GM_GPCR_AU_ALL_DIS;
-		}
-		else {
-			SWord = 0;
-		}
-
-		/* speed settings */
-		switch (pPrt->PLinkSpeed) {
-		case SK_LSPEED_AUTO:
-		case SK_LSPEED_1000MBPS:
-			SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
-			break;
-		case SK_LSPEED_100MBPS:
-			SWord |= GM_GPCR_SPEED_100;
-			break;
-		case SK_LSPEED_10MBPS:
-			break;
-		}
-
-		/* duplex settings */
-		if (pPrt->PLinkMode != SK_LMODE_HALF) {
-			/* set full duplex */
-			SWord |= GM_GPCR_DUP_FULL;
-		}
-
-		/* flow-control settings */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			/* set Pause Off */
-			SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
-			/* disable Tx & Rx flow-control */
-			SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			/* disable Rx flow-control */
-			SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-		case SK_FLOW_MODE_SYM_OR_REM:
-			/* enable Tx & Rx flow-control */
-			break;
-		}
-
-		/* setup General Purpose Control Register */
-		GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
-
-		/* dummy read the Interrupt Source Register */
-		SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
-		
-#ifndef VCPU
-		/* read Id from PHY */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
-		
-		SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
-#endif /* VCPU */
-	}
-
-	(void)SkGmResetCounter(pAC, IoC, Port);
-
-	/* setup Transmit Control Register */
-	GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
-
-	/* setup Receive Control Register */
-	GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
-		GM_RXCR_CRC_DIS);
-
-	/* setup Transmit Flow Control Register */
-	GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
-
-	/* setup Transmit Parameter Register */
-#ifdef VCPU
-	GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
-#endif /* VCPU */
-
-    SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
-			TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
-			TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
-	
-	GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
-
-	/* configure the Serial Mode Register */
-#ifdef VCPU
-	GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
-#endif /* VCPU */
-	
-	SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
-
-	if (pPrt->PMacLimit4) {
-		/* reset of collision counter after 4 consecutive collisions */
-		SWord |= GM_SMOD_LIMIT_4;
-	}
-
-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-		/* enable jumbo mode (Max. Frame Length = 9018) */
-		SWord |= GM_SMOD_JUMBO_ENA;
-	}
-	
-	GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
-	
-	/*
-	 * configure the GMACs Station Addresses
-	 * in PROM you can find our addresses at:
-	 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
-	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
-	 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
-	 */
-
-	for (i = 0; i < 3; i++) {
-		/*
-		 * The following 2 statements are together endianess
-		 * independent. Remember this when changing.
-		 */
-		/* physical address: will be used for pause frames */
-		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
-
-#ifdef WA_DEV_16
-		/* WA for deviation #16 */
-		if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
-			/* swap the address bytes */
-			SWord = ((SWord & 0xff00) >> 8)	| ((SWord & 0x00ff) << 8);
-
-			/* write to register in reversed order */
-			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
-		}
-		else {
-			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
-		}
-#else		
-		GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
-#endif /* WA_DEV_16 */
-		
-		/* virtual address: will be used for data */
-		SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
-
-		GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
-		
-		/* reset Multicast filtering Hash registers 1-3 */
-		GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
-	}
-
-	/* reset Multicast filtering Hash register 4 */
-	GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
-
-	/* enable interrupt mask for counter overflows */
-	GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
-	GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
-	GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
-
-#if defined(SK_DIAG) || defined(DEBUG)
-	/* read General Purpose Status */
-	GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("MAC Stat Reg.=0x%04X\n", SWord));
-#endif /* SK_DIAG || DEBUG */
-
-#ifdef SK_DIAG
-	c_print("MAC Stat Reg=0x%04X\n", SWord);
-#endif /* SK_DIAG */
-
-}	/* SkGmInitMac */
-#endif /* YUKON */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmInitDupMd() - Initialize the XMACs Duplex Mode
- *
- * Description:
- *	This function initializes the XMACs Duplex Mode.
- *	It should be called after successfully finishing
- *	the Auto-negotiation Process
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitDupMd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	switch (pAC->GIni.GP[Port].PLinkModeStatus) {
-	case SK_LMODE_STAT_AUTOHALF:
-	case SK_LMODE_STAT_HALF:
-		/* Configuration Actions for Half Duplex Mode */
-		/*
-		 * XM_BURST = default value. We are probable not quick
-		 * 	enough at the 'XMAC' bus to burst 8kB.
-		 *	The XMAC stops bursting if no transmit frames
-		 *	are available or the burst limit is exceeded.
-		 */
-		/* XM_TX_RT_LIM = default value (15) */
-		/* XM_TX_STIME = default value (0xff = 4096 bit times) */
-		break;
-	case SK_LMODE_STAT_AUTOFULL:
-	case SK_LMODE_STAT_FULL:
-		/* Configuration Actions for Full Duplex Mode */
-		/*
-		 * The duplex mode is configured by the PHY,
-		 * therefore it seems to be that there is nothing
-		 * to do here.
-		 */
-		break;
-	case SK_LMODE_STAT_UNKNOWN:
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
-		break;
-	}
-}	/* SkXmInitDupMd */
-
-
-/******************************************************************************
- *
- *	SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
- *
- * Description:
- *	This function initializes the Pause Mode which should
- *	be used for this port.
- *	It should be called after successfully finishing
- *	the Auto-negotiation Process
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPauseMd(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U32		DWord;
-	SK_U16		Word;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-	
-	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
-		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
-
-		/* Disable Pause Frame Reception */
-		Word |= XM_MMU_IGN_PF;
-	}
-	else {
-		/*
-		 * enabling pause frame reception is required for 1000BT
-		 * because the XMAC is not reset if the link is going down
-		 */
-		/* Enable Pause Frame Reception */
-		Word &= ~XM_MMU_IGN_PF;
-	}	
-	
-	XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
-
-	XM_IN32(IoC, Port, XM_MODE, &DWord);
-
-	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
-		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
-
-		/*
-		 * Configure Pause Frame Generation
-		 * Use internal and external Pause Frame Generation.
-		 * Sending pause frames is edge triggered.
-		 * Send a Pause frame with the maximum pause time if
-		 * internal oder external FIFO full condition occurs.
-		 * Send a zero pause time frame to re-start transmission.
-		 */
-
-		/* XM_PAUSE_DA = '010000C28001' (default) */
-
-		/* XM_MAC_PTIME = 0xffff (maximum) */
-		/* remember this value is defined in big endian (!) */
-		XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
-
-		/* Set Pause Mode in Mode Register */
-		DWord |= XM_PAUSE_MODE;
-
-		/* Set Pause Mode in MAC Rx FIFO */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
-	}
-	else {
-		/*
-		 * disable pause frame generation is required for 1000BT
-		 * because the XMAC is not reset if the link is going down
-		 */
-		/* Disable Pause Mode in Mode Register */
-		DWord &= ~XM_PAUSE_MODE;
-
-		/* Disable Pause Mode in MAC Rx FIFO */
-		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
-	}
-	
-	XM_OUT32(IoC, Port, XM_MODE, DWord);
-}	/* SkXmInitPauseMd*/
-
-
-/******************************************************************************
- *
- *	SkXmInitPhyXmac() - Initialize the XMAC Phy registers
- *
- * Description:	initializes all the XMACs Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyXmac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Ctrl;
-
-	pPrt = &pAC->GIni.GP[Port];
-	Ctrl = 0;
-	
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyXmac: no auto-negotiation Port %d\n", Port));
-		/* Set DuplexMode in Config register */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			Ctrl |= PHY_CT_DUP_MD;
-		}
-
-		/*
-		 * Do NOT enable Auto-negotiation here. This would hold
-		 * the link down because no IDLEs are transmitted
-		 */
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyXmac: with auto-negotiation Port %d\n", Port));
-		/* Set Auto-negotiation advertisement */
-
-		/* Set Full/half duplex capabilities */
-		switch (pPrt->PLinkMode) {
-		case SK_LMODE_AUTOHALF:
-			Ctrl |= PHY_X_AN_HD;
-			break;
-		case SK_LMODE_AUTOFULL:
-			Ctrl |= PHY_X_AN_FD;
-			break;
-		case SK_LMODE_AUTOBOTH:
-			Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-				SKERR_HWI_E015MSG);
-		}
-
-		/* Set Flow-control capabilities */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			Ctrl |= PHY_X_P_NO_PAUSE;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			Ctrl |= PHY_X_P_ASYM_MD;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-			Ctrl |= PHY_X_P_SYM_MD;
-			break;
-		case SK_FLOW_MODE_SYM_OR_REM:
-			Ctrl |= PHY_X_P_BOTH_MD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-				SKERR_HWI_E016MSG);
-		}
-
-		/* Write AutoNeg Advertisement Register */
-		SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
-
-		/* Restart Auto-negotiation */
-		Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
-	}
-
-	if (DoLoop) {
-		/* Set the Phy Loopback bit, too */
-		Ctrl |= PHY_CT_LOOP;
-	}
-
-	/* Write to the Phy control register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
-}	/* SkXmInitPhyXmac */
-
-
-/******************************************************************************
- *
- *	SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
- *
- * Description:	initializes all the Broadcom Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyBcom(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Ctrl1;
-	SK_U16		Ctrl2;
-	SK_U16		Ctrl3;
-	SK_U16		Ctrl4;
-	SK_U16		Ctrl5;
-
-	Ctrl1 = PHY_CT_SP1000;
-	Ctrl2 = 0;
-	Ctrl3 = PHY_SEL_TYPE;
-	Ctrl4 = PHY_B_PEC_EN_LTR;
-	Ctrl5 = PHY_B_AC_TX_TST;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* manually Master/Slave ? */
-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
-		Ctrl2 |= PHY_B_1000C_MSE;
-		
-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
-			Ctrl2 |= PHY_B_1000C_MSC;
-		}
-	}
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyBcom: no auto-negotiation Port %d\n", Port));
-		/* Set DuplexMode in Config register */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			Ctrl1 |= PHY_CT_DUP_MD;
-		}
-
-		/* Determine Master/Slave manually if not already done */
-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
-			Ctrl2 |= PHY_B_1000C_MSE;	/* set it to Slave */
-		}
-
-		/*
-		 * Do NOT enable Auto-negotiation here. This would hold
-		 * the link down because no IDLES are transmitted
-		 */
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyBcom: with auto-negotiation Port %d\n", Port));
-		/* Set Auto-negotiation advertisement */
-
-		/*
-		 * Workaround BCOM Errata #1 for the C5 type.
-		 * 1000Base-T Link Acquisition Failure in Slave Mode
-		 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
-		 */
-		Ctrl2 |= PHY_B_1000C_RD;
-		
-		 /* Set Full/half duplex capabilities */
-		switch (pPrt->PLinkMode) {
-		case SK_LMODE_AUTOHALF:
-			Ctrl2 |= PHY_B_1000C_AHD;
-			break;
-		case SK_LMODE_AUTOFULL:
-			Ctrl2 |= PHY_B_1000C_AFD;
-			break;
-		case SK_LMODE_AUTOBOTH:
-			Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-				SKERR_HWI_E015MSG);
-		}
-
-		/* Set Flow-control capabilities */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			Ctrl3 |= PHY_B_P_NO_PAUSE;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			Ctrl3 |= PHY_B_P_ASYM_MD;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-			Ctrl3 |= PHY_B_P_SYM_MD;
-			break;
-		case SK_FLOW_MODE_SYM_OR_REM:
-			Ctrl3 |= PHY_B_P_BOTH_MD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-				SKERR_HWI_E016MSG);
-		}
-
-		/* Restart Auto-negotiation */
-		Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
-	}
-	
-	/* Initialize LED register here? */
-	/* No. Please do it in SkDgXmitLed() (if required) and swap
-	   init order of LEDs and XMAC. (MAl) */
-	
-	/* Write 1000Base-T Control Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
-	
-	/* Write AutoNeg Advertisement Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
-	
-	if (DoLoop) {
-		/* Set the Phy Loopback bit, too */
-		Ctrl1 |= PHY_CT_LOOP;
-	}
-
-	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
-		/* configure FIFO to high latency for transmission of ext. packets */
-		Ctrl4 |= PHY_B_PEC_HIGH_LA;
-
-		/* configure reception of extended packets */
-		Ctrl5 |= PHY_B_AC_LONG_PACK;
-
-		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
-	}
-
-	/* Configure LED Traffic Mode and Jumbo Frame usage if specified */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
-	
-	/* Write to the Phy control register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Control Reg=0x%04X\n", Ctrl1));
-}	/* SkXmInitPhyBcom */
-#endif /* GENESIS */
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmInitPhyMarv() - Initialize the Marvell Phy registers
- *
- * Description:	initializes all the Marvell Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkGmInitPhyMarv(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		PhyCtrl;
-	SK_U16		C1000BaseT;
-	SK_U16		AutoNegAdv;
-	SK_U16		ExtPhyCtrl;
-	SK_U16		LedCtrl;
-	SK_BOOL		AutoNeg;
-#if defined(SK_DIAG) || defined(DEBUG)
-	SK_U16		PhyStat;
-	SK_U16		PhyStat1;
-	SK_U16		PhySpecStat;
-#endif /* SK_DIAG || DEBUG */
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		AutoNeg = SK_FALSE;
-	}
-	else {
-		AutoNeg = SK_TRUE;
-	}
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("InitPhyMarv: Port %d, auto-negotiation %s\n",
-		 Port, AutoNeg ? "ON" : "OFF"));
-
-#ifdef VCPU
-	VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
-		Port, DoLoop);
-#else /* VCPU */
-	if (DoLoop) {
-		/* Set 'MAC Power up'-bit, set Manual MDI configuration */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
-			PHY_M_PC_MAC_POW_UP);
-	}
-	else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
-		/* Read Ext. PHY Specific Control */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
-		
-		ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
-			PHY_M_EC_MAC_S_MSK);
-		
-		ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
-			PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
-	
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
-	}
-
-	/* Read PHY Control */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
-
-	if (!AutoNeg) {
-		/* Disable Auto-negotiation */
-		PhyCtrl &= ~PHY_CT_ANE;
-	}
-
-	PhyCtrl |= PHY_CT_RESET;
-	/* Assert software reset */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
-#endif /* VCPU */
-
-	PhyCtrl = 0 /* PHY_CT_COL_TST */;
-	C1000BaseT = 0;
-	AutoNegAdv = PHY_SEL_TYPE;
-
-	/* manually Master/Slave ? */
-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
-		/* enable Manual Master/Slave */
-		C1000BaseT |= PHY_M_1000C_MSE;
-		
-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
-			C1000BaseT |= PHY_M_1000C_MSC;	/* set it to Master */
-		}
-	}
-	
-	/* Auto-negotiation ? */
-	if (!AutoNeg) {
-		
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			/* Set Full Duplex Mode */
-			PhyCtrl |= PHY_CT_DUP_MD;
-		}
-
-		/* Set Master/Slave manually if not already done */
-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
-			C1000BaseT |= PHY_M_1000C_MSE;	/* set it to Slave */
-		}
-
-		/* Set Speed */
-		switch (pPrt->PLinkSpeed) {
-		case SK_LSPEED_AUTO:
-		case SK_LSPEED_1000MBPS:
-			PhyCtrl |= PHY_CT_SP1000;
-			break;
-		case SK_LSPEED_100MBPS:
-			PhyCtrl |= PHY_CT_SP100;
-			break;
-		case SK_LSPEED_10MBPS:
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
-				SKERR_HWI_E019MSG);
-		}
-
-		if (!DoLoop) {
-			PhyCtrl |= PHY_CT_RESET;
-		}
-	}
-	else {
-		/* Set Auto-negotiation advertisement */
-		
-		if (pAC->GIni.GICopperType) {
-			/* Set Speed capabilities */
-			switch (pPrt->PLinkSpeed) {
-			case SK_LSPEED_AUTO:
-				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
-				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
-					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
-				break;
-			case SK_LSPEED_1000MBPS:
-				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
-				break;
-			case SK_LSPEED_100MBPS:
-				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
-					/* advertise 10Base-T also */
-					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
-				break;
-			case SK_LSPEED_10MBPS:
-				AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
-					SKERR_HWI_E019MSG);
-			}
-
-			/* Set Full/half duplex capabilities */
-			switch (pPrt->PLinkMode) {
-			case SK_LMODE_AUTOHALF:
-				C1000BaseT &= ~PHY_M_1000C_AFD;
-				AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
-				break;
-			case SK_LMODE_AUTOFULL:
-				C1000BaseT &= ~PHY_M_1000C_AHD;
-				AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
-				break;
-			case SK_LMODE_AUTOBOTH:
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-					SKERR_HWI_E015MSG);
-			}
-			
-			/* Set Flow-control capabilities */
-			switch (pPrt->PFlowCtrlMode) {
-			case SK_FLOW_MODE_NONE:
-				AutoNegAdv |= PHY_B_P_NO_PAUSE;
-				break;
-			case SK_FLOW_MODE_LOC_SEND:
-				AutoNegAdv |= PHY_B_P_ASYM_MD;
-				break;
-			case SK_FLOW_MODE_SYMMETRIC:
-				AutoNegAdv |= PHY_B_P_SYM_MD;
-				break;
-			case SK_FLOW_MODE_SYM_OR_REM:
-				AutoNegAdv |= PHY_B_P_BOTH_MD;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-					SKERR_HWI_E016MSG);
-			}
-		}
-		else {	/* special defines for FIBER (88E1011S only) */
-			
-			/* Set Full/half duplex capabilities */
-			switch (pPrt->PLinkMode) {
-			case SK_LMODE_AUTOHALF:
-				AutoNegAdv |= PHY_M_AN_1000X_AHD;
-				break;
-			case SK_LMODE_AUTOFULL:
-				AutoNegAdv |= PHY_M_AN_1000X_AFD;
-				break;
-			case SK_LMODE_AUTOBOTH:
-				AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-					SKERR_HWI_E015MSG);
-			}
-			
-			/* Set Flow-control capabilities */
-			switch (pPrt->PFlowCtrlMode) {
-			case SK_FLOW_MODE_NONE:
-				AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
-				break;
-			case SK_FLOW_MODE_LOC_SEND:
-				AutoNegAdv |= PHY_M_P_ASYM_MD_X;
-				break;
-			case SK_FLOW_MODE_SYMMETRIC:
-				AutoNegAdv |= PHY_M_P_SYM_MD_X;
-				break;
-			case SK_FLOW_MODE_SYM_OR_REM:
-				AutoNegAdv |= PHY_M_P_BOTH_MD_X;
-				break;
-			default:
-				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-					SKERR_HWI_E016MSG);
-			}
-		}
-
-		if (!DoLoop) {
-			/* Restart Auto-negotiation */
-			PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
-		}
-	}
-	
-#ifdef VCPU
-	/*
-	 * E-mail from Gu Lin (08-03-2002):
-	 */
-	
-	/* Program PHY register 30 as 16'h0708 for simulation speed up */
-	SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
-	
-	VCpuWait(2000);
-
-#else /* VCPU */
-	
-	/* Write 1000Base-T Control Register */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
-	
-	/* Write AutoNeg Advertisement Register */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
-#endif /* VCPU */
-	
-	if (DoLoop) {
-		/* Set the PHY Loopback bit */
-		PhyCtrl |= PHY_CT_LOOP;
-
-#ifdef XXX
-		/* Program PHY register 16 as 16'h0400 to force link good */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
-#endif /* XXX */
-
-#ifndef VCPU
-		if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
-			/* Write Ext. PHY Specific Control */
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
-				(SK_U16)((pPrt->PLinkSpeed + 2) << 4));
-		}
-#endif /* VCPU */
-	}
-#ifdef TEST_ONLY
-	else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
-			/* Write PHY Specific Control */
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
-				PHY_M_PC_EN_DET_MSK);
-	}
-#endif
-
-	/* Write to the PHY Control register */
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
-
-#ifdef VCPU
-	VCpuWait(2000);
-#else
-
-	LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
-
-	if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
-		LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
-	}
-
-	if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
-		LedCtrl |= PHY_M_LEDC_DP_CTRL;
-	}
-	
-	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
-
-	if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
-		/* only in forced 100 Mbps mode */
-		if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
-
-			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
-				PHY_M_LED_MO_100(MO_LED_ON));
-		}
-	}
-
-#ifdef SK_DIAG
-	c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
-	c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
-	c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
-	c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
-#endif /* SK_DIAG */
-
-#if defined(SK_DIAG) || defined(DEBUG)
-	/* Read PHY Control */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
-	
-	/* Read 1000Base-T Control Register */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("1000B-T Ctrl =0x%04X\n", C1000BaseT));
-	
-	/* Read AutoNeg Advertisement Register */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
-	
-	/* Read Ext. PHY Specific Control */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
-	
-	/* Read PHY Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Stat Reg.=0x%04X\n", PhyStat));
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Stat Reg.=0x%04X\n", PhyStat1));
-	
-	/* Read PHY Specific Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Spec Stat=0x%04X\n", PhySpecStat));
-#endif /* SK_DIAG || DEBUG */
-
-#ifdef SK_DIAG
-	c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
-	c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
-	c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
-	c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
-	c_print("PHY Stat Reg=0x%04X\n", PhyStat);
-	c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
-	c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
-#endif /* SK_DIAG */
-
-#endif /* VCPU */
-
-}	/* SkGmInitPhyMarv */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- *	SkXmInitPhyLone() - Initialize the Level One Phy registers
- *
- * Description:	initializes all the Level One Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyLone(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Ctrl1;
-	SK_U16		Ctrl2;
-	SK_U16		Ctrl3;
-
-	Ctrl1 = PHY_CT_SP1000;
-	Ctrl2 = 0;
-	Ctrl3 = PHY_SEL_TYPE;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* manually Master/Slave ? */
-	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
-		Ctrl2 |= PHY_L_1000C_MSE;
-		
-		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
-			Ctrl2 |= PHY_L_1000C_MSC;
-		}
-	}
-	/* Auto-negotiation ? */
-	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
-		/*
-		 * level one spec say: "1000 Mbps: manual mode not allowed"
-		 * but lets see what happens...
-		 */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyLone: no auto-negotiation Port %d\n", Port));
-		/* Set DuplexMode in Config register */
-		if (pPrt->PLinkMode == SK_LMODE_FULL) {
-			Ctrl1 |= PHY_CT_DUP_MD;
-		}
-
-		/* Determine Master/Slave manually if not already done */
-		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
-			Ctrl2 |= PHY_L_1000C_MSE;	/* set it to Slave */
-		}
-
-		/*
-		 * Do NOT enable Auto-negotiation here. This would hold
-		 * the link down because no IDLES are transmitted
-		 */
-	}
-	else {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("InitPhyLone: with auto-negotiation Port %d\n", Port));
-		/* Set Auto-negotiation advertisement */
-
-		/* Set Full/half duplex capabilities */
-		switch (pPrt->PLinkMode) {
-		case SK_LMODE_AUTOHALF:
-			Ctrl2 |= PHY_L_1000C_AHD;
-			break;
-		case SK_LMODE_AUTOFULL:
-			Ctrl2 |= PHY_L_1000C_AFD;
-			break;
-		case SK_LMODE_AUTOBOTH:
-			Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
-				SKERR_HWI_E015MSG);
-		}
-
-		/* Set Flow-control capabilities */
-		switch (pPrt->PFlowCtrlMode) {
-		case SK_FLOW_MODE_NONE:
-			Ctrl3 |= PHY_L_P_NO_PAUSE;
-			break;
-		case SK_FLOW_MODE_LOC_SEND:
-			Ctrl3 |= PHY_L_P_ASYM_MD;
-			break;
-		case SK_FLOW_MODE_SYMMETRIC:
-			Ctrl3 |= PHY_L_P_SYM_MD;
-			break;
-		case SK_FLOW_MODE_SYM_OR_REM:
-			Ctrl3 |= PHY_L_P_BOTH_MD;
-			break;
-		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-				SKERR_HWI_E016MSG);
-		}
-
-		/* Restart Auto-negotiation */
-		Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
-	}
-	
-	/* Write 1000Base-T Control Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
-	
-	/* Write AutoNeg Advertisement Register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
-
-	if (DoLoop) {
-		/* Set the Phy Loopback bit, too */
-		Ctrl1 |= PHY_CT_LOOP;
-	}
-
-	/* Write to the Phy control register */
-	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Control Reg=0x%04X\n", Ctrl1));
-}	/* SkXmInitPhyLone */
-
-
-/******************************************************************************
- *
- *	SkXmInitPhyNat() - Initialize the National Phy registers
- *
- * Description:	initializes all the National Phy registers
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkXmInitPhyNat(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-/* todo: National */
-}	/* SkXmInitPhyNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- *	SkMacInitPhy() - Initialize the PHY registers
- *
- * Description:	calls the Init PHY routines dep. on board type
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-void SkMacInitPhy(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		switch (pPrt->PhyType) {
-		case SK_PHY_XMAC:
-			SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
-			break;
-		case SK_PHY_BCOM:
-			SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
-			break;
-		case SK_PHY_NAT:
-			SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
-			break;
-#endif /* OTHER_PHY */
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
-	}
-#endif /* YUKON */
-
-}	/* SkMacInitPhy */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmAutoNegDoneXmac() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneXmac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		LPAb;		/* Link Partner Ability */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneXmac, Port %d\n", Port));
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
-	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
-
-	if ((LPAb & PHY_X_AN_RFB) != 0) {
-		/* At least one of the remote fault bit is set */
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	/* Check Duplex mismatch */
-	if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	else {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_DUP_CAP);
-	}
-
-	/* Check PAUSE mismatch */
-	/* We are NOT using chapter 4.23 of the Xaqti manual */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
-	     pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
-	    (LPAb & PHY_X_P_SYM_MD) != 0) {
-		/* Symmetric PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-	}
-	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
-		   (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
-		/* Enable PAUSE receive, disable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-	}
-	else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
-		   (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
-		/* Disable PAUSE receive, enable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-	}
-	else {
-		/* PAUSE mismatch -> no PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	}
-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneXmac */
-
-
-/******************************************************************************
- *
- *	SkXmAutoNegDoneBcom() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneBcom(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		LPAb;		/* Link Partner Ability */
-	SK_U16		AuxStat;	/* Auxiliary Status */
-
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
-	SK_U16		ResAb;		/* Resolved Ability */
-#endif	/* 0 */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneBcom, Port %d\n", Port));
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-#endif	/* 0 */
-	
-	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
-
-	if ((LPAb & PHY_B_AN_RF) != 0) {
-		/* Remote fault bit is set: Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	/* Check Duplex mismatch */
-	if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	else {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_DUP_CAP);
-	}
-	
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
-	/* Check Master/Slave resolution */
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		return(SK_AND_OTHER);
-	}
-	
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-#endif	/* 0 */
-
-	/* Check PAUSE mismatch ??? */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
-		/* Symmetric PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-	}
-	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
-		/* Enable PAUSE receive, disable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-	}
-	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
-		/* Disable PAUSE receive, enable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-	}
-	else {
-		/* PAUSE mismatch -> no PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	}
-	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmAutoNegDoneMarv() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkGmAutoNegDoneMarv(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		LPAb;		/* Link Partner Ability */
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		AuxStat;	/* Auxiliary Status */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneMarv, Port %d\n", Port));
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Link P.Abil.=0x%04X\n", LPAb));
-	
-	if ((LPAb & PHY_M_AN_RF) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
-	
-	/* Check Master/Slave resolution */
-	if ((ResAb & PHY_B_1000S_MSF) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		return(SK_AND_OTHER);
-	}
-	
-	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
-		(SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
-	
-	/* Read PHY Specific Status */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
-	
-	/* Check Speed & Duplex resolved */
-	if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-		return(SK_AND_DUP_CAP);
-	}
-	
-	if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	
-	/* Check PAUSE mismatch ??? */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
-		/* Symmetric PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-	}
-	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
-		/* Enable PAUSE receive, disable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-	}
-	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
-		/* Disable PAUSE receive, enable PAUSE transmit */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-	}
-	else {
-		/* PAUSE mismatch -> no PAUSE */
-		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	}
-	
-	/* set used link speed */
-	switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
-	case (unsigned)PHY_M_PS_SPEED_1000:
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-		break;
-	case PHY_M_PS_SPEED_100:
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
-		break;
-	default:
-		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
-	}
-
-	return(SK_AND_OK);
-}	/* SkGmAutoNegDoneMarv */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- *	SkXmAutoNegDoneLone() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneLone(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		ResAb;		/* Resolved Ability */
-	SK_U16		LPAb;		/* Link Partner Ability */
-	SK_U16		QuickStat;	/* Auxiliary Status */
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNegDoneLone, Port %d\n", Port));
-	pPrt = &pAC->GIni.GP[Port];
-
-	/* Get PHY parameters */
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
-	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
-
-	if ((LPAb & PHY_L_AN_RF) != 0) {
-		/* Remote fault bit is set */
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegFail: Remote fault bit set Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		return(SK_AND_OTHER);
-	}
-
-	/* Check Duplex mismatch */
-	if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
-	}
-	else {
-		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
-	}
-	
-	/* Check Master/Slave resolution */
-	if ((ResAb & PHY_L_1000S_MSF) != 0) {
-		/* Error */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault Port %d\n", Port));
-		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		return(SK_AND_OTHER);
-	}
-	else if (ResAb & PHY_L_1000S_MSR) {
-		pPrt->PMSStatus = SK_MS_STAT_MASTER;
-	}
-	else {
-		pPrt->PMSStatus = SK_MS_STAT_SLAVE;
-	}
-
-	/* Check PAUSE mismatch */
-	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
-	/* we must manually resolve the abilities here */
-	pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-	
-	switch (pPrt->PFlowCtrlMode) {
-	case SK_FLOW_MODE_NONE:
-		/* default */
-		break;
-	case SK_FLOW_MODE_LOC_SEND:
-		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
-			(PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
-			/* Disable PAUSE receive, enable PAUSE transmit */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
-		}
-		break;
-	case SK_FLOW_MODE_SYMMETRIC:
-		if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
-			/* Symmetric PAUSE */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-		}
-		break;
-	case SK_FLOW_MODE_SYM_OR_REM:
-		if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
-			PHY_L_QS_AS_PAUSE) {
-			/* Enable PAUSE receive, disable PAUSE transmit */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
-		}
-		else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
-			/* Symmetric PAUSE */
-			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
-		}
-		break;
-	default:
-		SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
-			SKERR_HWI_E016MSG);
-	}
-	
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneLone */
-
-
-/******************************************************************************
- *
- *	SkXmAutoNegDoneNat() - Auto-negotiation handling
- *
- * Description:
- *	This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-static int SkXmAutoNegDoneNat(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-/* todo: National */
-	return(SK_AND_OK);
-}	/* SkXmAutoNegDoneNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- *	SkMacAutoNegDone() - Auto-negotiation handling
- *
- * Description:	calls the auto-negotiation done routines dep. on board type
- *
- * Returns:
- *	SK_AND_OK	o.k.
- *	SK_AND_DUP_CAP 	Duplex capability error happened
- *	SK_AND_OTHER 	Other error happened
- */
-int	SkMacAutoNegDone(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	int	Rtv;
-
-	Rtv = SK_AND_OK;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		switch (pPrt->PhyType) {
-		
-		case SK_PHY_XMAC:
-			Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
-			break;
-		case SK_PHY_BCOM:
-			Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
-			break;
-		case SK_PHY_NAT:
-			Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
-			break;
-#endif /* OTHER_PHY */
-		default:
-			return(SK_AND_OTHER);
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-	
-	if (Rtv != SK_AND_OK) {
-		return(Rtv);
-	}
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("AutoNeg done Port %d\n", Port));
-	
-	/* We checked everything and may now enable the link */
-	pPrt->PAutoNegFail = SK_FALSE;
-
-	SkMacRxTxEnable(pAC, IoC, Port);
-	
-	return(SK_AND_OK);
-}	/* SkMacAutoNegDone */
-
-
-/******************************************************************************
- *
- *	SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
- *
- * Description:	enables Rx/Tx dep. on board type
- *
- * Returns:
- *	0	o.k.
- *	!= 0	Error happened
- */
-int SkMacRxTxEnable(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		Reg;		/* 16-bit register value */
-	SK_U16		IntMask;	/* MAC interrupt mask */
-#ifdef GENESIS
-	SK_U16		SWord;
-#endif
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (!pPrt->PHWLinkUp) {
-		/* The Hardware link is NOT up */
-		return(0);
-	}
-
-	if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
-	     pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
-	     pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
-	     pPrt->PAutoNegFail) {
-		/* Auto-negotiation is not done or failed */
-		return(0);
-	}
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* set Duplex Mode and Pause Mode */
-		SkXmInitDupMd(pAC, IoC, Port);
-		
-		SkXmInitPauseMd(pAC, IoC, Port);
-	
-		/*
-		 * Initialize the Interrupt Mask Register. Default IRQs are...
-		 *	- Link Asynchronous Event
-		 *	- Link Partner requests config
-		 *	- Auto Negotiation Done
-		 *	- Rx Counter Event Overflow
-		 *	- Tx Counter Event Overflow
-		 *	- Transmit FIFO Underrun
-		 */
-		IntMask = XM_DEF_MSK;
-
-#ifdef DEBUG
-		/* add IRQ for Receive FIFO Overflow */
-		IntMask &= ~XM_IS_RXF_OV;
-#endif /* DEBUG */
-		
-		if (pPrt->PhyType != SK_PHY_XMAC) {
-			/* disable GP0 interrupt bit */
-			IntMask |= XM_IS_INP_ASS;
-		}
-		XM_OUT16(IoC, Port, XM_IMSK, IntMask);
-	
-		/* get MMU Command Reg. */
-		XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
-		
-		if (pPrt->PhyType != SK_PHY_XMAC &&
-			(pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
-			 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
-			/* set to Full Duplex */
-			Reg |= XM_MMU_GMII_FD;
-		}
-		
-		switch (pPrt->PhyType) {
-		case SK_PHY_BCOM:
-			/*
-			 * Workaround BCOM Errata (#10523) for all BCom Phys
-			 * Enable Power Management after link up
-			 */
-			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
-			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
-				(SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
-            SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
-				(SK_U16)PHY_B_DEF_MSK);
-			break;
-#ifdef OTHER_PHY
-		case SK_PHY_LONE:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
-			break;
-		case SK_PHY_NAT:
-			/* todo National:
-			SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
-			/* no interrupts possible from National ??? */
-			break;
-#endif /* OTHER_PHY */
-		}
-		
-		/* enable Rx/Tx */
-		XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/*
-		 * Initialize the Interrupt Mask Register. Default IRQs are...
-		 *	- Rx Counter Event Overflow
-		 *	- Tx Counter Event Overflow
-		 *	- Transmit FIFO Underrun
-		 */
-		IntMask = GMAC_DEF_MSK;
-
-#ifdef DEBUG
-		/* add IRQ for Receive FIFO Overrun */
-		IntMask |= GM_IS_RX_FF_OR;
-#endif /* DEBUG */
-		
-		SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
-		
-		/* get General Purpose Control */
-		GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
-		
-		if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
-			pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
-			/* set to Full Duplex */
-			Reg |= GM_GPCR_DUP_FULL;
-		}
-		
-		/* enable Rx/Tx */
-        GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
-			GM_GPCR_TX_ENA));
-
-#ifndef VCPU
-		/* Enable all PHY interrupts */
-        SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
-			(SK_U16)PHY_M_DEF_MSK);
-#endif /* VCPU */
-	}
-#endif /* YUKON */
-					
-	return(0);
-
-}	/* SkMacRxTxEnable */
-
-
-/******************************************************************************
- *
- *	SkMacRxTxDisable() - Disable Receiver and Transmitter
- *
- * Description:	disables Rx/Tx dep. on board type
- *
- * Returns: N/A
- */
-void SkMacRxTxDisable(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_U16	Word;
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-		
-		XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
-	
-		/* dummy read to ensure writing */
-		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		
-		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
-
-        GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
-			GM_GPCR_TX_ENA)));
-
-		/* dummy read to ensure writing */
-		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
-	}
-#endif /* YUKON */
-
-}	/* SkMacRxTxDisable */
-
-
-/******************************************************************************
- *
- *	SkMacIrqDisable() - Disable IRQ from MAC
- *
- * Description:	sets the IRQ-mask to disable IRQ dep. on board type
- *
- * Returns: N/A
- */
-void SkMacIrqDisable(
-SK_AC	*pAC,		/* Adapter Context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-#ifdef GENESIS
-	SK_U16		Word;
-#endif
-
-	pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		
-		/* disable all XMAC IRQs */
-		XM_OUT16(IoC, Port, XM_IMSK, 0xffff);	
-		
-		/* Disable all PHY interrupts */
-		switch (pPrt->PhyType) {
-			case SK_PHY_BCOM:
-				/* Make sure that PHY is initialized */
-				if (pPrt->PState != SK_PRT_RESET) {
-					/* NOT allowed if BCOM is in RESET state */
-					/* Workaround BCOM Errata (#10523) all BCom */
-					/* Disable Power Management if link is down */
-					SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
-					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
-						(SK_U16)(Word | PHY_B_AC_DIS_PM));
-					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
-				}
-				break;
-#ifdef OTHER_PHY
-			case SK_PHY_LONE:
-				SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
-				break;
-			case SK_PHY_NAT:
-				/* todo: National
-				SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
-				break;
-#endif /* OTHER_PHY */
-		}
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* disable all GMAC IRQs */
-		SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
-		
-#ifndef VCPU
-		/* Disable all PHY interrupts */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
-#endif /* VCPU */
-	}
-#endif /* YUKON */
-
-}	/* SkMacIrqDisable */
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- *	SkXmSendCont() - Enable / Disable Send Continuous Mode
- *
- * Description:	enable / disable Send Continuous Mode on XMAC
- *
- * Returns:
- *	nothing
- */
-void SkXmSendCont(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-	SK_U32	MdReg;
-
-	XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-	if (Enable) {
-		MdReg |= XM_MD_TX_CONT;
-	}
-	else {
-		MdReg &= ~XM_MD_TX_CONT;
-	}
-	/* setup Mode Register */
-	XM_OUT32(IoC, Port, XM_MODE, MdReg);
-
-}	/* SkXmSendCont */
-
-
-/******************************************************************************
- *
- *	SkMacTimeStamp() - Enable / Disable Time Stamp
- *
- * Description:	enable / disable Time Stamp generation for Rx packets
- *
- * Returns:
- *	nothing
- */
-void SkMacTimeStamp(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port,	/* Port Index (MAC_1 + n) */
-SK_BOOL	Enable)	/* Enable / Disable */
-{
-	SK_U32	MdReg;
-	SK_U8	TimeCtrl;
-
-	if (pAC->GIni.GIGenesis) {
-
-		XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
-		if (Enable) {
-			MdReg |= XM_MD_ATS;
-		}
-		else {
-			MdReg &= ~XM_MD_ATS;
-		}
-		/* setup Mode Register */
-		XM_OUT32(IoC, Port, XM_MODE, MdReg);
-	}
-	else {
-		if (Enable) {
-			TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
-		}
-		else {
-			TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
-		}
-		/* Start/Stop Time Stamp Timer */
-		SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
-	}
-
-}	/* SkMacTimeStamp*/
-
-#else /* !SK_DIAG */
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
- *
- *	This function analyses the Interrupt status word. If any of the
- *	Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
- *	is set true.
- */
-void SkXmAutoNegLipaXmac(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U16	IStatus)	/* Interrupt Status word to analyse */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
-		(IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
-			Port, IStatus));
-		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
-	}
-}	/* SkXmAutoNegLipaXmac */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- *	SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
- *
- *	This function analyses the PHY status word.
- *  If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
- *	is set true.
- */
-void SkMacAutoNegLipaPhy(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_U16	PhyStat)	/* PHY Status word to analyse */
-{
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
-		(PhyStat & PHY_ST_AN_OVER) != 0) {
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
-			Port, PhyStat));
-		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
-	}
-}	/* SkMacAutoNegLipaPhy */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmIrq() - Interrupt Service Routine
- *
- * Description:	services an Interrupt Request of the XMAC
- *
- * Note:
- *	With an external PHY, some interrupt bits are not meaningfull any more:
- *	- LinkAsyncEvent (bit #14)              XM_IS_LNK_AE
- *	- LinkPartnerReqConfig (bit #10)	XM_IS_LIPA_RC
- *	- Page Received (bit #9)		XM_IS_RX_PAGE
- *	- NextPageLoadedForXmt (bit #8)		XM_IS_TX_PAGE
- *	- AutoNegDone (bit #7)			XM_IS_AND
- *	Also probably not valid any more is the GP0 input bit:
- *	- GPRegisterBit0set			XM_IS_INP_ASS
- *
- * Returns:
- *	nothing
- */
-static void SkXmIrq(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_EVPARA	Para;
-	SK_U16		IStatus;	/* Interrupt status read from the XMAC */
-	SK_U16		IStatus2;
-#ifdef SK_SLIM
-    SK_U64      OverflowStatus;
-#endif	
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	XM_IN16(IoC, Port, XM_ISRC, &IStatus);
-	
-	/* LinkPartner Auto-negable? */
-	if (pPrt->PhyType == SK_PHY_XMAC) {
-		SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
-	}
-	else {
-		/* mask bits that are not used with ext. PHY */
-		IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
-			XM_IS_RX_PAGE | XM_IS_TX_PAGE |
-			XM_IS_AND | XM_IS_INP_ASS);
-	}
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
-
-	if (!pPrt->PHWLinkUp) {
-		/* Spurious XMAC interrupt */
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("SkXmIrq: spurious interrupt on Port %d\n", Port));
-		return;
-	}
-
-	if ((IStatus & XM_IS_INP_ASS) != 0) {
-		/* Reread ISR Register if link is not in sync */
-		XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
-
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
-			 Port, IStatus, IStatus2));
-		IStatus &= ~XM_IS_INP_ASS;
-		IStatus |= IStatus2;
-	}
-
-	if ((IStatus & XM_IS_LNK_AE) != 0) {
-		/* not used, GP0 is used instead */
-	}
-
-	if ((IStatus & XM_IS_TX_ABORT) != 0) {
-		/* not used */
-	}
-
-	if ((IStatus & XM_IS_FRC_INT) != 0) {
-		/* not used, use ASIC IRQ instead if needed */
-	}
-
-	if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
-		SkHWLinkDown(pAC, IoC, Port);
-
-		/* Signal to RLMT */
-		Para.Para32[0] = (SK_U32)Port;
-		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
-		/* Start workaround Errata #2 timer */
-		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
-			SKGE_HWAC, SK_HWEV_WATIM, Para);
-	}
-
-	if ((IStatus & XM_IS_RX_PAGE) != 0) {
-		/* not used */
-	}
-
-	if ((IStatus & XM_IS_TX_PAGE) != 0) {
-		/* not used */
-	}
-
-	if ((IStatus & XM_IS_AND) != 0) {
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-			("SkXmIrq: AND on link that is up Port %d\n", Port));
-	}
-
-	if ((IStatus & XM_IS_TSC_OV) != 0) {
-		/* not used */
-	}
-
-	/* Combined Tx & Rx Counter Overflow SIRQ Event */
-	if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
-#ifdef SK_SLIM
-		SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
-#else
-		Para.Para32[0] = (SK_U32)Port;
-		Para.Para32[1] = (SK_U32)IStatus;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
-#endif /* SK_SLIM */
-	}
-
-	if ((IStatus & XM_IS_RXF_OV) != 0) {
-		/* normal situation -> no effect */
-#ifdef DEBUG
-		pPrt->PRxOverCnt++;
-#endif /* DEBUG */
-	}
-
-	if ((IStatus & XM_IS_TXF_UR) != 0) {
-		/* may NOT happen -> error log */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
-	}
-
-	if ((IStatus & XM_IS_TX_COMP) != 0) {
-		/* not served here */
-	}
-
-	if ((IStatus & XM_IS_RX_COMP) != 0) {
-		/* not served here */
-	}
-}	/* SkXmIrq */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmIrq() - Interrupt Service Routine
- *
- * Description:	services an Interrupt Request of the GMAC
- *
- * Note:
- *
- * Returns:
- *	nothing
- */
-static void SkGmIrq(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U8		IStatus;	/* Interrupt status */
-#ifdef SK_SLIM
-    SK_U64      OverflowStatus;
-#else
-	SK_EVPARA	Para;
-#endif	
-
-	pPrt = &pAC->GIni.GP[Port];
-	
-	SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
-	
-#ifdef XXX
-	/* LinkPartner Auto-negable? */
-	SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
-#endif /* XXX */
-	
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
-		("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
-
-	/* Combined Tx & Rx Counter Overflow SIRQ Event */
-	if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
-		/* these IRQs will be cleared by reading GMACs register */
-#ifdef SK_SLIM
-        SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
-#else
-		Para.Para32[0] = (SK_U32)Port;
-		Para.Para32[1] = (SK_U32)IStatus;
-		SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
-#endif		
-	}
-
-	if (IStatus & GM_IS_RX_FF_OR) {
-		/* clear GMAC Rx FIFO Overrun IRQ */
-		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
-#ifdef DEBUG
-		pPrt->PRxOverCnt++;
-#endif /* DEBUG */
-	}
-
-	if (IStatus & GM_IS_TX_FF_UR) {
-		/* clear GMAC Tx FIFO Underrun IRQ */
-		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
-		/* may NOT happen -> error log */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
-	}
-
-	if (IStatus & GM_IS_TX_COMPL) {
-		/* not served here */
-	}
-
-	if (IStatus & GM_IS_RX_COMPL) {
-		/* not served here */
-	}
-}	/* SkGmIrq */
-#endif /* YUKON */
-
-
-/******************************************************************************
- *
- *	SkMacIrq() - Interrupt Service Routine for MAC
- *
- * Description:	calls the Interrupt Service Routine dep. on board type
- *
- * Returns:
- *	nothing
- */
-void SkMacIrq(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-int		Port)		/* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
-	if (pAC->GIni.GIGenesis) {
-		/* IRQ from XMAC */
-		SkXmIrq(pAC, IoC, Port);
-	}
-#endif /* GENESIS */
-	
-#ifdef YUKON
-	if (pAC->GIni.GIYukon) {
-		/* IRQ from GMAC */
-		SkGmIrq(pAC, IoC, Port);
-	}
-#endif /* YUKON */
-
-}	/* SkMacIrq */
-
-#endif /* !SK_DIAG */
-
-#ifdef GENESIS
-/******************************************************************************
- *
- *	SkXmUpdateStats() - Force the XMAC to output the current statistic
- *
- * Description:
- *	The XMAC holds its statistic internally. To obtain the current
- *	values a command must be sent so that the statistic data will
- *	be written to a predefined memory area on the adapter.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmUpdateStats(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_GEPORT	*pPrt;
-	SK_U16		StatReg;
-	int			WaitIndex;
-
-	pPrt = &pAC->GIni.GP[Port];
-	WaitIndex = 0;
-
-	/* Send an update command to XMAC specified */
-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
-
-	/*
-	 * It is an auto-clearing register. If the command bits
-	 * went to zero again, the statistics are transferred.
-	 * Normally the command should be executed immediately.
-	 * But just to be sure we execute a loop.
-	 */
-	do {
-
-		XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
-		
-		if (++WaitIndex > 10) {
-
-			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
-
-			return(1);
-		}
-	} while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
-	
-	return(0);
-}	/* SkXmUpdateStats */
-
-
-/******************************************************************************
- *
- *	SkXmMacStatistic() - Get XMAC counter value
- *
- * Description:
- *	Gets the 32bit counter value. Except for the octet counters
- *	the lower 32bit are counted in hardware and the upper 32bit
- *	must be counted in software by monitoring counter overflow interrupts.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmMacStatistic(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* IO context */
-unsigned int Port,		/* Port Index (MAC_1 + n) */
-SK_U16	StatAddr,		/* MIB counter base address */
-SK_U32	SK_FAR *pVal)	/* ptr to return statistic value */
-{
-	if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
-		
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
-		
-		return(1);
-	}
-	
-	XM_IN32(IoC, Port, StatAddr, pVal);
-
-	return(0);
-}	/* SkXmMacStatistic */
-
-
-/******************************************************************************
- *
- *	SkXmResetCounter() - Clear MAC statistic counter
- *
- * Description:
- *	Force the XMAC to clear its statistic counter.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmResetCounter(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
-	/* Clear two times according to Errata #3 */
-	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
-
-	return(0);
-}	/* SkXmResetCounter */
-
-
-/******************************************************************************
- *
- *	SkXmOverflowStatus() - Gets the status of counter overflow interrupt
- *
- * Description:
- *	Checks the source causing an counter overflow interrupt. On success the
- *	resulting counter overflow status is written to <pStatus>, whereas the
- *	upper dword stores the XMAC ReceiveCounterEvent register and the lower
- *	dword the XMAC TransmitCounterEvent register.
- *
- * Note:
- *	For XMAC the interrupt source is a self-clearing register, so the source
- *	must be checked only once. SIRQ module does another check to be sure
- *	that no interrupt get lost during process time.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkXmOverflowStatus(
-SK_AC	*pAC,				/* adapter context */
-SK_IOC	IoC,				/* IO context */
-unsigned int Port,			/* Port Index (MAC_1 + n) */
-SK_U16	IStatus,			/* Interupt Status from MAC */
-SK_U64	SK_FAR *pStatus)	/* ptr for return overflow status value */
-{
-	SK_U64	Status;	/* Overflow status */
-	SK_U32	RegVal;
-
-	Status = 0;
-
-	if ((IStatus & XM_IS_RXC_OV) != 0) {
-
-		XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
-		Status |= (SK_U64)RegVal << 32;
-	}
-	
-	if ((IStatus & XM_IS_TXC_OV) != 0) {
-
-		XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
-		Status |= (SK_U64)RegVal;
-	}
-
-	*pStatus = Status;
-
-	return(0);
-}	/* SkXmOverflowStatus */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- *	SkGmUpdateStats() - Force the GMAC to output the current statistic
- *
- * Description:
- *	Empty function for GMAC. Statistic data is accessible in direct way.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmUpdateStats(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	return(0);
-}
-
-
-/******************************************************************************
- *
- *	SkGmMacStatistic() - Get GMAC counter value
- *
- * Description:
- *	Gets the 32bit counter value. Except for the octet counters
- *	the lower 32bit are counted in hardware and the upper 32bit
- *	must be counted in software by monitoring counter overflow interrupts.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmMacStatistic(
-SK_AC	*pAC,			/* adapter context */
-SK_IOC	IoC,			/* IO context */
-unsigned int Port,		/* Port Index (MAC_1 + n) */
-SK_U16	StatAddr,		/* MIB counter base address */
-SK_U32	SK_FAR *pVal)	/* ptr to return statistic value */
-{
-
-	if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
-		
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
-		
-		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
-		return(1);
-	}
-		
-	GM_IN32(IoC, Port, StatAddr, pVal);
-
-	return(0);
-}	/* SkGmMacStatistic */
-
-
-/******************************************************************************
- *
- *	SkGmResetCounter() - Clear MAC statistic counter
- *
- * Description:
- *	Force GMAC to clear its statistic counter.
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmResetCounter(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,		/* IO context */
-unsigned int Port)	/* Port Index (MAC_1 + n) */
-{
-	SK_U16	Reg;	/* Phy Address Register */
-	SK_U16	Word;
-	int		i;
-
-	GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
-
-	/* set MIB Clear Counter Mode */
-	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
-	
-	/* read all MIB Counters with Clear Mode set */
-	for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
-		/* the reset is performed only when the lower 16 bits are read */
-		GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
-	}
-	
-	/* clear MIB Clear Counter Mode */
-	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
-	
-	return(0);
-}	/* SkGmResetCounter */
-
-
-/******************************************************************************
- *
- *	SkGmOverflowStatus() - Gets the status of counter overflow interrupt
- *
- * Description:
- *	Checks the source causing an counter overflow interrupt. On success the
- *	resulting counter overflow status is written to <pStatus>, whereas the
- *	the following bit coding is used:
- *	63:56 - unused
- *	55:48 - TxRx interrupt register bit7:0
- *	32:47 - Rx interrupt register
- *	31:24 - unused
- *	23:16 - TxRx interrupt register bit15:8
- *	15:0  - Tx interrupt register
- *
- * Returns:
- *	0:  success
- *	1:  something went wrong
- */
-int SkGmOverflowStatus(
-SK_AC	*pAC,				/* adapter context */
-SK_IOC	IoC,				/* IO context */
-unsigned int Port,			/* Port Index (MAC_1 + n) */
-SK_U16	IStatus,			/* Interupt Status from MAC */
-SK_U64	SK_FAR *pStatus)	/* ptr for return overflow status value */
-{
-	SK_U64	Status;		/* Overflow status */
-	SK_U16	RegVal;
-
-	Status = 0;
-
-	if ((IStatus & GM_IS_RX_CO_OV) != 0) {
-		/* this register is self-clearing after read */
-		GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
-		Status |= (SK_U64)RegVal << 32;
-	}
-	
-	if ((IStatus & GM_IS_TX_CO_OV) != 0) {
-		/* this register is self-clearing after read */
-		GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
-		Status |= (SK_U64)RegVal;
-	}
-	
-	/* this register is self-clearing after read */
-	GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
-	/* Rx overflow interrupt register bits (LoByte)*/
-	Status |= (SK_U64)((SK_U8)RegVal) << 48;
-	/* Tx overflow interrupt register bits (HiByte)*/
-	Status |= (SK_U64)(RegVal >> 8) << 16;
-
-	*pStatus = Status;
-
-	return(0);
-}	/* SkGmOverflowStatus */
-
-
-#ifndef SK_SLIM
-/******************************************************************************
- *
- *	SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
- *
- * Description:
- *  starts the cable diagnostic test if 'StartTest' is true
- *  gets the results if 'StartTest' is true
- *
- * NOTE:	this test is meaningful only when link is down
- *	
- * Returns:
- *	0:  success
- *	1:	no YUKON copper
- *	2:	test in progress
- */
-int SkGmCableDiagStatus(
-SK_AC	*pAC,		/* adapter context */
-SK_IOC	IoC,   		/* IO context */
-int		Port,		/* Port Index (MAC_1 + n) */
-SK_BOOL	StartTest)	/* flag for start / get result */
-{
-	int		i;
-	SK_U16	RegVal;
-	SK_GEPORT	*pPrt;
-
-	pPrt = &pAC->GIni.GP[Port];
-
-	if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
-		
-		return(1);
-	}
-
-	if (StartTest) {
-		/* only start the cable test */
-		if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
-			/* apply TDR workaround from Marvell */
-			SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
-			
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
-			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
-		}
-
-		/* set address to 0 for MDI[0] */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
-
-		/* Read Cable Diagnostic Reg */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
-		/* start Cable Diagnostic Test */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
-			(SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
-	
-		return(0);
-	}
-	
-	/* Read Cable Diagnostic Reg */
-	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
-	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("PHY Cable Diag.=0x%04X\n", RegVal));
-
-	if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
-		/* test is running */
-		return(2);
-	}
-
-	/* get the test results */
-	for (i = 0; i < 4; i++)  {
-		/* set address to i for MDI[i] */
-		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
-
-		/* get Cable Diagnostic values */
-		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
-		pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
-
-		pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
-	}
-
-	return(0);
-}	/* SkGmCableDiagStatus */
-#endif /* !SK_SLIM */
-#endif /* YUKON */
-
-/* End of file */
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index fe01b96..a2f3215 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -39,6 +39,7 @@
 #include <linux/workqueue.h>
 #include <linux/if_vlan.h>
 #include <linux/prefetch.h>
+#include <linux/debugfs.h>
 #include <linux/mii.h>
 
 #include <asm/irq.h>
@@ -50,7 +51,7 @@
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
-#define DRV_VERSION		"1.14"
+#define DRV_VERSION		"1.16"
 #define PFX			DRV_NAME " "
 
 /*
@@ -64,7 +65,6 @@
 #define RX_MAX_PENDING		(RX_LE_SIZE/6 - 2)
 #define RX_DEF_PENDING		RX_MAX_PENDING
 #define RX_SKB_ALIGN		8
-#define RX_BUF_WRITE		16
 
 #define TX_RING_SIZE		512
 #define TX_DEF_PENDING		(TX_RING_SIZE - 1)
@@ -77,6 +77,9 @@
 #define NAPI_WEIGHT		64
 #define PHY_RETRIES		1000
 
+#define SKY2_EEPROM_MAGIC	0x9955aabb
+
+
 #define RING_NEXT(x,s)	(((x)+1) & ((s)-1))
 
 static const u32 default_msg =
@@ -96,7 +99,7 @@
 module_param(disable_msi, int, 0);
 MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
 
-static int idle_timeout = 0;
+static int idle_timeout = 100;
 module_param(idle_timeout, int, 0);
 MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)");
 
@@ -130,7 +133,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */
-//	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
 	{ 0 }
 };
 
@@ -217,13 +220,24 @@
 		sky2_write8(hw, B2_Y2_CLK_GATE, 0);
 
 	if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
-		u32 reg1;
+		u32 reg;
 
-		sky2_pci_write32(hw, PCI_DEV_REG3, 0);
-		reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
-		reg1 &= P_ASPM_CONTROL_MSK;
-		sky2_pci_write32(hw, PCI_DEV_REG4, reg1);
-		sky2_pci_write32(hw, PCI_DEV_REG5, 0);
+		reg = sky2_pci_read32(hw, PCI_DEV_REG4);
+		/* set all bits to 0 except bits 15..12 and 8 */
+		reg &= P_ASPM_CONTROL_MSK;
+		sky2_pci_write32(hw, PCI_DEV_REG4, reg);
+
+		reg = sky2_pci_read32(hw, PCI_DEV_REG5);
+		/* set all bits to 0 except bits 28 & 27 */
+		reg &= P_CTL_TIM_VMAIN_AV_MSK;
+		sky2_pci_write32(hw, PCI_DEV_REG5, reg);
+
+		sky2_pci_write32(hw, PCI_CFG_REG_1, 0);
+
+		/* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */
+		reg = sky2_read32(hw, B2_GP_IO);
+		reg |= GLB_GPIO_STAT_RACE_DIS;
+		sky2_write32(hw, B2_GP_IO, reg);
 	}
 }
 
@@ -650,6 +664,30 @@
 
 }
 
+static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
+{
+	if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) {
+		sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+			     TX_STFW_ENA |
+			     (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS);
+	} else {
+		if (hw->dev[port]->mtu > ETH_DATA_LEN) {
+			/* set Tx GMAC FIFO Almost Empty Threshold */
+			sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
+				     (ECU_JUMBO_WM << 16) | ECU_AE_THR);
+
+			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+				     TX_JUMBO_ENA | TX_STFW_DIS);
+
+			/* Can't do offload because of lack of store/forward */
+			hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG
+						     | NETIF_F_ALL_CSUM);
+		} else
+			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+				     TX_JUMBO_DIS | TX_STFW_ENA);
+	}
+}
+
 static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
 {
 	struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
@@ -730,8 +768,11 @@
 
 	/* Configure Rx MAC FIFO */
 	sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
-	sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
-		     GMF_OPER_ON | GMF_RX_F_FL_ON);
+	reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
+	if (hw->chip_id == CHIP_ID_YUKON_EX)
+		reg |= GMF_RX_OVER_ON;
+
+	sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
 
 	/* Flush Rx MAC FIFO on any flow control or error */
 	sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
@@ -747,16 +788,7 @@
 		sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
 		sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
 
-		/* set Tx GMAC FIFO Almost Empty Threshold */
-		sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
-			     (ECU_JUMBO_WM << 16) | ECU_AE_THR);
-
-		if (hw->dev[port]->mtu > ETH_DATA_LEN)
-			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-				     TX_JUMBO_ENA | TX_STFW_DIS);
-		else
-			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-				     TX_JUMBO_DIS | TX_STFW_ENA);
+		sky2_set_tx_stfwd(hw, port);
 	}
 
 }
@@ -861,24 +893,18 @@
 	return le;
 }
 
-/* Return high part of DMA address (could be 32 or 64 bit) */
-static inline u32 high32(dma_addr_t a)
-{
-	return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0;
-}
-
 /* Build description to hardware for one receive segment */
 static void sky2_rx_add(struct sky2_port *sky2,  u8 op,
 			dma_addr_t map, unsigned len)
 {
 	struct sky2_rx_le *le;
-	u32 hi = high32(map);
+	u32 hi = upper_32_bits(map);
 
 	if (sky2->rx_addr64 != hi) {
 		le = sky2_next_rx(sky2);
 		le->addr = cpu_to_le32(hi);
 		le->opcode = OP_ADDR64 | HW_OWNER;
-		sky2->rx_addr64 = high32(map + len);
+		sky2->rx_addr64 = upper_32_bits(map + len);
 	}
 
 	le = sky2_next_rx(sky2);
@@ -939,14 +965,16 @@
 {
 	struct sky2_rx_le *le;
 
-	le = sky2_next_rx(sky2);
-	le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
-	le->ctrl = 0;
-	le->opcode = OP_TCPSTART | HW_OWNER;
+	if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) {
+		le = sky2_next_rx(sky2);
+		le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
+		le->ctrl = 0;
+		le->opcode = OP_TCPSTART | HW_OWNER;
 
-	sky2_write32(sky2->hw,
-		     Q_ADDR(rxqaddr[sky2->port], Q_CSR),
-		     sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+		sky2_write32(sky2->hw,
+			     Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+			     sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+	}
 
 }
 
@@ -1106,6 +1134,11 @@
 	return NULL;
 }
 
+static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq)
+{
+	sky2_put_idx(sky2->hw, rxq, sky2->rx_put);
+}
+
 /*
  * Allocate and setup receiver buffer pool.
  * Normal case this ends up creating one list element for skb
@@ -1134,15 +1167,14 @@
 	if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
 	    (hw->chip_rev == CHIP_REV_YU_EC_U_A1
 	     || hw->chip_rev == CHIP_REV_YU_EC_U_B0))
-		sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS);
+		sky2_write32(hw, Q_ADDR(rxq, Q_TEST), F_M_RX_RAM_DIS);
 
 	sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
 
 	rx_set_checksum(sky2);
 
 	/* Space needed for frame data + headers rounded up */
-	size = ALIGN(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8)
-		+ 8;
+	size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
 
 	/* Stopping point for hardware truncation */
 	thresh = (size - 8) / sizeof(u32);
@@ -1197,7 +1229,7 @@
 	}
 
 	/* Tell chip about available buffers */
-	sky2_put_idx(hw, rxq, sky2->rx_put);
+	sky2_rx_update(sky2, rxq);
 	return 0;
 nomem:
 	sky2_rx_clean(sky2);
@@ -1234,6 +1266,8 @@
 	if (netif_msg_ifup(sky2))
 		printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
 
+	netif_carrier_off(dev);
+
 	/* must be power of 2 */
 	sky2->tx_le = pci_alloc_consistent(hw->pdev,
 					   TX_RING_SIZE *
@@ -1285,6 +1319,10 @@
 
 	sky2_qset(hw, txqaddr[port]);
 
+	/* This is copied from sk98lin 10.0.5.3; no one tells me about erratta's */
+	if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev == CHIP_REV_YU_EX_B0)
+		sky2_write32(hw, Q_ADDR(txqaddr[port], Q_TEST), F_TX_CHK_AUTO_OFF);
+
 	/* Set almost empty threshold */
 	if (hw->chip_id == CHIP_ID_YUKON_EC_U
 	    && hw->chip_rev == CHIP_REV_YU_EC_U_A0)
@@ -1380,27 +1418,30 @@
 
 	len = skb_headlen(skb);
 	mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
-	addr64 = high32(mapping);
+	addr64 = upper_32_bits(mapping);
 
 	/* Send high bits if changed or crosses boundary */
-	if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) {
+	if (addr64 != sky2->tx_addr64 ||
+	    upper_32_bits(mapping + len) != sky2->tx_addr64) {
 		le = get_tx_le(sky2);
 		le->addr = cpu_to_le32(addr64);
 		le->opcode = OP_ADDR64 | HW_OWNER;
-		sky2->tx_addr64 = high32(mapping + len);
+		sky2->tx_addr64 = upper_32_bits(mapping + len);
 	}
 
 	/* Check for TCP Segmentation Offload */
 	mss = skb_shinfo(skb)->gso_size;
 	if (mss != 0) {
-		mss += tcp_optlen(skb); /* TCP options */
-		mss += ip_hdrlen(skb) + sizeof(struct tcphdr);
-		mss += ETH_HLEN;
+		if (hw->chip_id != CHIP_ID_YUKON_EX)
+			mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
 
-		if (mss != sky2->tx_last_mss) {
-			le = get_tx_le(sky2);
-			le->addr = cpu_to_le32(mss);
-			le->opcode = OP_LRGLEN | HW_OWNER;
+  		if (mss != sky2->tx_last_mss) {
+  			le = get_tx_le(sky2);
+  			le->addr = cpu_to_le32(mss);
+ 			if (hw->chip_id == CHIP_ID_YUKON_EX)
+				le->opcode = OP_MSS | HW_OWNER;
+			else
+				le->opcode = OP_LRGLEN | HW_OWNER;
 			sky2->tx_last_mss = mss;
 		}
 	}
@@ -1422,24 +1463,30 @@
 
 	/* Handle TCP checksum offload */
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		const unsigned offset = skb_transport_offset(skb);
-		u32 tcpsum;
+		/* On Yukon EX (some versions) encoding change. */
+ 		if (hw->chip_id == CHIP_ID_YUKON_EX
+		    && hw->chip_rev != CHIP_REV_YU_EX_B0)
+ 			ctrl |= CALSUM;	/* auto checksum */
+		else {
+			const unsigned offset = skb_transport_offset(skb);
+			u32 tcpsum;
 
-		tcpsum = offset << 16;		/* sum start */
-		tcpsum |= offset + skb->csum_offset;	/* sum write */
+			tcpsum = offset << 16;			/* sum start */
+			tcpsum |= offset + skb->csum_offset;	/* sum write */
 
-		ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
-		if (ip_hdr(skb)->protocol == IPPROTO_UDP)
-			ctrl |= UDPTCP;
+			ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+			if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+				ctrl |= UDPTCP;
 
-		if (tcpsum != sky2->tx_tcpsum) {
-			sky2->tx_tcpsum = tcpsum;
+			if (tcpsum != sky2->tx_tcpsum) {
+				sky2->tx_tcpsum = tcpsum;
 
-			le = get_tx_le(sky2);
-			le->addr = cpu_to_le32(tcpsum);
-			le->length = 0;	/* initial checksum value */
-			le->ctrl = 1;	/* one packet */
-			le->opcode = OP_TCPLISW | HW_OWNER;
+				le = get_tx_le(sky2);
+				le->addr = cpu_to_le32(tcpsum);
+				le->length = 0;	/* initial checksum value */
+				le->ctrl = 1;	/* one packet */
+				le->opcode = OP_TCPLISW | HW_OWNER;
+			}
 		}
 	}
 
@@ -1459,7 +1506,7 @@
 
 		mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset,
 				       frag->size, PCI_DMA_TODEVICE);
-		addr64 = high32(mapping);
+		addr64 = upper_32_bits(mapping);
 		if (addr64 != sky2->tx_addr64) {
 			le = get_tx_le(sky2);
 			le->addr = cpu_to_le32(addr64);
@@ -1529,13 +1576,13 @@
 			if (unlikely(netif_msg_tx_done(sky2)))
 				printk(KERN_DEBUG "%s: tx done %u\n",
 				       dev->name, idx);
+
 			sky2->net_stats.tx_packets++;
 			sky2->net_stats.tx_bytes += re->skb->len;
 
 			dev_kfree_skb_any(re->skb);
+			sky2->tx_next = RING_NEXT(idx, TX_RING_SIZE);
 		}
-
-		le->opcode = 0;	/* paranoia */
 	}
 
 	sky2->tx_cons = idx;
@@ -1573,7 +1620,6 @@
 
 	/* Stop more packets from being queued */
 	netif_stop_queue(dev);
-	netif_carrier_off(dev);
 
 	/* Disable port IRQ */
 	imask = sky2_read32(hw, B0_IMSK);
@@ -1625,6 +1671,8 @@
 
 	sky2_phy_power(hw, port, 0);
 
+	netif_carrier_off(dev);
+
 	/* turn off LED's */
 	sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
 
@@ -1689,7 +1737,6 @@
 	gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
 
 	netif_carrier_on(sky2->netdev);
-	netif_wake_queue(sky2->netdev);
 
 	/* Turn on link LED */
 	sky2_write8(hw, SK_REG(port, LNK_LED_REG),
@@ -1741,7 +1788,6 @@
 	gma_write16(hw, port, GM_GP_CTRL, reg);
 
 	netif_carrier_off(sky2->netdev);
-	netif_stop_queue(sky2->netdev);
 
 	/* Turn on link LED */
 	sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
@@ -1913,15 +1959,8 @@
 
 	synchronize_irq(hw->pdev->irq);
 
-	if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
-		if (new_mtu > ETH_DATA_LEN) {
-			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-				     TX_JUMBO_ENA | TX_STFW_DIS);
-			dev->features &= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
-		} else
-			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-				     TX_JUMBO_DIS | TX_STFW_ENA);
-	}
+	if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+		sky2_set_tx_stfwd(hw, port);
 
 	ctl = gma_read16(hw, port, GM_GP_CTRL);
 	gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
@@ -2019,8 +2058,6 @@
 	struct sk_buff *skb, *nskb;
 	unsigned hdr_space = sky2->rx_data_size;
 
-	pr_debug(PFX "receive new length=%d\n", length);
-
 	/* Don't be tricky about reusing pages (yet) */
 	nskb = sky2_rx_alloc(sky2);
 	if (unlikely(!nskb))
@@ -2064,6 +2101,9 @@
 	if (!(status & GMR_FS_RX_OK))
 		goto resubmit;
 
+	if (status >> 16 != length)
+		goto len_mismatch;
+
 	if (length < copybreak)
 		skb = receive_copy(sky2, re, length);
 	else
@@ -2073,6 +2113,11 @@
 
 	return skb;
 
+len_mismatch:
+	/* Truncation of overlength packets
+	   causes PHY length to not match MAC length */
+	++sky2->net_stats.rx_length_errors;
+
 error:
 	++sky2->net_stats.rx_errors;
 	if (status & GMR_FS_RX_FF_OV) {
@@ -2109,15 +2154,16 @@
 /* Process status response ring */
 static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 {
-	struct sky2_port *sky2;
 	int work_done = 0;
-	unsigned buf_write[2] = { 0, 0 };
+	unsigned rx[2] = { 0, 0 };
 	u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
 
 	rmb();
 
 	while (hw->st_idx != hwidx) {
+		struct sky2_port *sky2;
 		struct sky2_status_le *le  = hw->st_le + hw->st_idx;
+		unsigned port = le->css & CSS_LINK_BIT;
 		struct net_device *dev;
 		struct sk_buff *skb;
 		u32 status;
@@ -2125,19 +2171,28 @@
 
 		hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
 
-		BUG_ON(le->link >= 2);
-		dev = hw->dev[le->link];
-
+		dev = hw->dev[port];
 		sky2 = netdev_priv(dev);
 		length = le16_to_cpu(le->length);
 		status = le32_to_cpu(le->status);
 
 		switch (le->opcode & ~HW_OWNER) {
 		case OP_RXSTAT:
+			++rx[port];
 			skb = sky2_receive(dev, length, status);
 			if (unlikely(!skb)) {
 				sky2->net_stats.rx_dropped++;
-				goto force_update;
+				break;
+			}
+
+			/* This chip reports checksum status differently */
+			if (hw->chip_id == CHIP_ID_YUKON_EX) {
+				if (sky2->rx_csum &&
+				    (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
+				    (le->css & CSS_TCPUDPCSOK))
+					skb->ip_summed = CHECKSUM_UNNECESSARY;
+				else
+					skb->ip_summed = CHECKSUM_NONE;
 			}
 
 			skb->protocol = eth_type_trans(skb, dev);
@@ -2154,13 +2209,6 @@
 #endif
 				netif_receive_skb(skb);
 
-			/* Update receiver after 16 frames */
-			if (++buf_write[le->link] == RX_BUF_WRITE) {
-force_update:
-				sky2_put_idx(hw, rxqaddr[le->link], sky2->rx_put);
-				buf_write[le->link] = 0;
-			}
-
 			/* Stop after net poll weight */
 			if (++work_done >= to_do)
 				goto exit_loop;
@@ -2179,6 +2227,9 @@
 			if (!sky2->rx_csum)
 				break;
 
+			if (hw->chip_id == CHIP_ID_YUKON_EX)
+				break;
+
 			/* Both checksum counters are programmed to start at
 			 * the same offset, so unless there is a problem they
 			 * should match. This failure is an early indication that
@@ -2194,7 +2245,7 @@
 				       dev->name, status);
 				sky2->rx_csum = 0;
 				sky2_write32(sky2->hw,
-					     Q_ADDR(rxqaddr[le->link], Q_CSR),
+					     Q_ADDR(rxqaddr[port], Q_CSR),
 					     BMU_DIS_RX_CHKSUM);
 			}
 			break;
@@ -2213,24 +2264,18 @@
 			if (net_ratelimit())
 				printk(KERN_WARNING PFX
 				       "unknown status opcode 0x%x\n", le->opcode);
-			goto exit_loop;
 		}
 	}
 
 	/* Fully processed status ring so clear irq */
 	sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
-	mmiowb();
 
 exit_loop:
-	if (buf_write[0]) {
-		sky2 = netdev_priv(hw->dev[0]);
-		sky2_put_idx(hw, Q_R1, sky2->rx_put);
-	}
+	if (rx[0])
+		sky2_rx_update(netdev_priv(hw->dev[0]), Q_R1);
 
-	if (buf_write[1]) {
-		sky2 = netdev_priv(hw->dev[1]);
-		sky2_put_idx(hw, Q_R2, sky2->rx_put);
-	}
+	if (rx[1])
+		sky2_rx_update(netdev_priv(hw->dev[1]), Q_R2);
 
 	return work_done;
 }
@@ -2427,8 +2472,7 @@
 static int sky2_poll(struct net_device *dev0, int *budget)
 {
 	struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
-	int work_limit = min(dev0->quota, *budget);
-	int work_done = 0;
+	int work_done;
 	u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
 
 	if (unlikely(status & Y2_IS_ERROR))
@@ -2440,18 +2484,25 @@
 	if (status & Y2_IS_IRQ_PHY2)
 		sky2_phy_intr(hw, 1);
 
-	work_done = sky2_status_intr(hw, work_limit);
-	if (work_done < work_limit) {
-		netif_rx_complete(dev0);
+	work_done = sky2_status_intr(hw, min(dev0->quota, *budget));
+	*budget -= work_done;
+	dev0->quota -= work_done;
 
-		/* end of interrupt, re-enables also acts as I/O synchronization */
-		sky2_read32(hw, B0_Y2_SP_LISR);
-		return 0;
-	} else {
-		*budget -= work_done;
-		dev0->quota -= work_done;
+	/* More work? */
+ 	if (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX))
 		return 1;
+
+	/* Bug/Errata workaround?
+	 * Need to kick the TX irq moderation timer.
+	 */
+	if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
+		sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+		sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
 	}
+	netif_rx_complete(dev0);
+
+	sky2_read32(hw, B0_Y2_SP_LISR);
+	return 0;
 }
 
 static irqreturn_t sky2_intr(int irq, void *dev_id)
@@ -2513,6 +2564,9 @@
 {
 	u8 t8;
 
+	/* Enable all clocks */
+	sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
 	sky2_write8(hw, B0_CTST, CS_RST_CLR);
 
 	hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
@@ -2522,14 +2576,6 @@
 		return -EOPNOTSUPP;
 	}
 
-	if (hw->chip_id == CHIP_ID_YUKON_EX)
-		dev_warn(&hw->pdev->dev, "this driver not yet tested on this chip type\n"
-			 "Please report success or failure to <netdev@vger.kernel.org>\n");
-
-	/* Make sure and enable all clocks */
-	if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U)
-		sky2_pci_write32(hw, PCI_DEV_REG3, 0);
-
 	hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
 
 	/* This rev is really old, and requires untested workarounds */
@@ -2589,6 +2635,11 @@
 	for (i = 0; i < hw->ports; i++) {
 		sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
 		sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+
+		if (hw->chip_id == CHIP_ID_YUKON_EX)
+			sky2_write16(hw, SK_REG(i, GMAC_CTRL),
+				     GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON
+				     | GMC_BYP_RETR_ON);
 	}
 
 	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
@@ -2675,8 +2726,6 @@
 	struct net_device *dev;
 	int i, err;
 
-	dev_dbg(&hw->pdev->dev, "restarting\n");
-
 	del_timer_sync(&hw->idle_timer);
 
 	rtnl_lock();
@@ -2735,7 +2784,7 @@
 
 	sky2->wol = wol->wolopts;
 
-	if (hw->chip_id == CHIP_ID_YUKON_EC_U)
+	if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
 		sky2_write32(hw, B0_CTST, sky2->wol
 			     ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
 
@@ -3330,7 +3379,7 @@
 
 /*
  * Returns copy of control register region
- * Note: access to the RAM address register set will cause timeouts.
+ * Note: ethtool_get_regs always provides full size (16k) buffer
  */
 static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 			  void *p)
@@ -3338,15 +3387,19 @@
 	const struct sky2_port *sky2 = netdev_priv(dev);
 	const void __iomem *io = sky2->hw->regs;
 
-	BUG_ON(regs->len < B3_RI_WTO_R1);
 	regs->version = 1;
 	memset(p, 0, regs->len);
 
 	memcpy_fromio(p, io, B3_RAM_ADDR);
 
-	memcpy_fromio(p + B3_RI_WTO_R1,
-		      io + B3_RI_WTO_R1,
-		      regs->len - B3_RI_WTO_R1);
+	/* skip diagnostic ram region */
+	memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, 0x2000 - B3_RI_WTO_R1);
+
+	/* copy GMAC registers */
+	memcpy_fromio(p + BASE_GMAC_1, io + BASE_GMAC_1, 0x1000);
+	if (sky2->hw->ports > 1)
+		memcpy_fromio(p + BASE_GMAC_2, io + BASE_GMAC_2, 0x1000);
+
 }
 
 /* In order to do Jumbo packets on these chips, need to turn off the
@@ -3357,9 +3410,7 @@
 	const struct sky2_port *sky2 = netdev_priv(dev);
 	const struct sky2_hw *hw = sky2->hw;
 
-	return dev->mtu > ETH_DATA_LEN &&
-		(hw->chip_id == CHIP_ID_YUKON_EX
-		 || hw->chip_id == CHIP_ID_YUKON_EC_U);
+	return dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U;
 }
 
 static int sky2_set_tx_csum(struct net_device *dev, u32 data)
@@ -3379,39 +3430,315 @@
 	return ethtool_op_set_tso(dev, data);
 }
 
+static int sky2_get_eeprom_len(struct net_device *dev)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	u16 reg2;
+
+	reg2 = sky2_pci_read32(sky2->hw, PCI_DEV_REG2);
+	return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
+}
+
+static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset)
+{
+	sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset);
+
+	while (!(sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F))
+			cpu_relax();
+	return sky2_pci_read32(hw, cap + PCI_VPD_DATA);
+}
+
+static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val)
+{
+	sky2_pci_write32(hw, cap + PCI_VPD_DATA, val);
+	sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F);
+	do {
+		cpu_relax();
+	} while (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F);
+}
+
+static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+			   u8 *data)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
+	int length = eeprom->len;
+	u16 offset = eeprom->offset;
+
+	if (!cap)
+		return -EINVAL;
+
+	eeprom->magic = SKY2_EEPROM_MAGIC;
+
+	while (length > 0) {
+		u32 val = sky2_vpd_read(sky2->hw, cap, offset);
+		int n = min_t(int, length, sizeof(val));
+
+		memcpy(data, &val, n);
+		length -= n;
+		data += n;
+		offset += n;
+	}
+	return 0;
+}
+
+static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+			   u8 *data)
+{
+	struct sky2_port *sky2 = netdev_priv(dev);
+	int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
+	int length = eeprom->len;
+	u16 offset = eeprom->offset;
+
+	if (!cap)
+		return -EINVAL;
+
+	if (eeprom->magic != SKY2_EEPROM_MAGIC)
+		return -EINVAL;
+
+	while (length > 0) {
+		u32 val;
+		int n = min_t(int, length, sizeof(val));
+
+		if (n < sizeof(val))
+			val = sky2_vpd_read(sky2->hw, cap, offset);
+		memcpy(&val, data, n);
+
+		sky2_vpd_write(sky2->hw, cap, offset, val);
+
+		length -= n;
+		data += n;
+		offset += n;
+	}
+	return 0;
+}
+
+
 static const struct ethtool_ops sky2_ethtool_ops = {
-	.get_settings = sky2_get_settings,
-	.set_settings = sky2_set_settings,
-	.get_drvinfo  = sky2_get_drvinfo,
-	.get_wol      = sky2_get_wol,
-	.set_wol      = sky2_set_wol,
-	.get_msglevel = sky2_get_msglevel,
-	.set_msglevel = sky2_set_msglevel,
-	.nway_reset   = sky2_nway_reset,
-	.get_regs_len = sky2_get_regs_len,
-	.get_regs = sky2_get_regs,
-	.get_link = ethtool_op_get_link,
-	.get_sg = ethtool_op_get_sg,
-	.set_sg = ethtool_op_set_sg,
-	.get_tx_csum = ethtool_op_get_tx_csum,
-	.set_tx_csum = sky2_set_tx_csum,
-	.get_tso = ethtool_op_get_tso,
-	.set_tso = sky2_set_tso,
-	.get_rx_csum = sky2_get_rx_csum,
-	.set_rx_csum = sky2_set_rx_csum,
-	.get_strings = sky2_get_strings,
-	.get_coalesce = sky2_get_coalesce,
-	.set_coalesce = sky2_set_coalesce,
-	.get_ringparam = sky2_get_ringparam,
-	.set_ringparam = sky2_set_ringparam,
+	.get_settings	= sky2_get_settings,
+	.set_settings	= sky2_set_settings,
+	.get_drvinfo	= sky2_get_drvinfo,
+	.get_wol	= sky2_get_wol,
+	.set_wol	= sky2_set_wol,
+	.get_msglevel	= sky2_get_msglevel,
+	.set_msglevel	= sky2_set_msglevel,
+	.nway_reset	= sky2_nway_reset,
+	.get_regs_len	= sky2_get_regs_len,
+	.get_regs	= sky2_get_regs,
+	.get_link	= ethtool_op_get_link,
+	.get_eeprom_len	= sky2_get_eeprom_len,
+	.get_eeprom	= sky2_get_eeprom,
+	.set_eeprom	= sky2_set_eeprom,
+	.get_sg 	= ethtool_op_get_sg,
+	.set_sg 	= ethtool_op_set_sg,
+	.get_tx_csum	= ethtool_op_get_tx_csum,
+	.set_tx_csum	= sky2_set_tx_csum,
+	.get_tso	= ethtool_op_get_tso,
+	.set_tso	= sky2_set_tso,
+	.get_rx_csum	= sky2_get_rx_csum,
+	.set_rx_csum	= sky2_set_rx_csum,
+	.get_strings	= sky2_get_strings,
+	.get_coalesce	= sky2_get_coalesce,
+	.set_coalesce	= sky2_set_coalesce,
+	.get_ringparam	= sky2_get_ringparam,
+	.set_ringparam	= sky2_set_ringparam,
 	.get_pauseparam = sky2_get_pauseparam,
 	.set_pauseparam = sky2_set_pauseparam,
-	.phys_id = sky2_phys_id,
+	.phys_id	= sky2_phys_id,
 	.get_stats_count = sky2_get_stats_count,
 	.get_ethtool_stats = sky2_get_ethtool_stats,
 	.get_perm_addr	= ethtool_op_get_perm_addr,
 };
 
+#ifdef CONFIG_SKY2_DEBUG
+
+static struct dentry *sky2_debug;
+
+static int sky2_debug_show(struct seq_file *seq, void *v)
+{
+	struct net_device *dev = seq->private;
+	const struct sky2_port *sky2 = netdev_priv(dev);
+	const struct sky2_hw *hw = sky2->hw;
+	unsigned port = sky2->port;
+	unsigned idx, last;
+	int sop;
+
+	if (!netif_running(dev))
+		return -ENETDOWN;
+
+	seq_printf(seq, "IRQ src=%x mask=%x control=%x\n",
+		   sky2_read32(hw, B0_ISRC),
+		   sky2_read32(hw, B0_IMSK),
+		   sky2_read32(hw, B0_Y2_SP_ICR));
+
+	netif_poll_disable(hw->dev[0]);
+	last = sky2_read16(hw, STAT_PUT_IDX);
+
+	if (hw->st_idx == last)
+		seq_puts(seq, "Status ring (empty)\n");
+	else {
+		seq_puts(seq, "Status ring\n");
+		for (idx = hw->st_idx; idx != last && idx < STATUS_RING_SIZE;
+		     idx = RING_NEXT(idx, STATUS_RING_SIZE)) {
+			const struct sky2_status_le *le = hw->st_le + idx;
+			seq_printf(seq, "[%d] %#x %d %#x\n",
+				   idx, le->opcode, le->length, le->status);
+		}
+		seq_puts(seq, "\n");
+	}
+
+	seq_printf(seq, "Tx ring pending=%u...%u report=%d done=%d\n",
+		   sky2->tx_cons, sky2->tx_prod,
+		   sky2_read16(hw, port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
+		   sky2_read16(hw, Q_ADDR(txqaddr[port], Q_DONE)));
+
+	/* Dump contents of tx ring */
+	sop = 1;
+	for (idx = sky2->tx_next; idx != sky2->tx_prod && idx < TX_RING_SIZE;
+	     idx = RING_NEXT(idx, TX_RING_SIZE)) {
+		const struct sky2_tx_le *le = sky2->tx_le + idx;
+		u32 a = le32_to_cpu(le->addr);
+
+		if (sop)
+			seq_printf(seq, "%u:", idx);
+		sop = 0;
+
+		switch(le->opcode & ~HW_OWNER) {
+		case OP_ADDR64:
+			seq_printf(seq, " %#x:", a);
+			break;
+		case OP_LRGLEN:
+			seq_printf(seq, " mtu=%d", a);
+			break;
+		case OP_VLAN:
+			seq_printf(seq, " vlan=%d", be16_to_cpu(le->length));
+			break;
+		case OP_TCPLISW:
+			seq_printf(seq, " csum=%#x", a);
+			break;
+		case OP_LARGESEND:
+			seq_printf(seq, " tso=%#x(%d)", a, le16_to_cpu(le->length));
+			break;
+		case OP_PACKET:
+			seq_printf(seq, " %#x(%d)", a, le16_to_cpu(le->length));
+			break;
+		case OP_BUFFER:
+			seq_printf(seq, " frag=%#x(%d)", a, le16_to_cpu(le->length));
+			break;
+		default:
+			seq_printf(seq, " op=%#x,%#x(%d)", le->opcode,
+				   a, le16_to_cpu(le->length));
+		}
+
+		if (le->ctrl & EOP) {
+			seq_putc(seq, '\n');
+			sop = 1;
+		}
+	}
+
+	seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n",
+		   sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)),
+		   last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
+		   sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX)));
+
+	netif_poll_enable(hw->dev[0]);
+	return 0;
+}
+
+static int sky2_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, sky2_debug_show, inode->i_private);
+}
+
+static const struct file_operations sky2_debug_fops = {
+	.owner		= THIS_MODULE,
+	.open		= sky2_debug_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+/*
+ * Use network device events to create/remove/rename
+ * debugfs file entries
+ */
+static int sky2_device_event(struct notifier_block *unused,
+			     unsigned long event, void *ptr)
+{
+	struct net_device *dev = ptr;
+
+	if (dev->open == sky2_up) {
+		struct sky2_port *sky2 = netdev_priv(dev);
+
+		switch(event) {
+		case NETDEV_CHANGENAME:
+			if (!netif_running(dev))
+				break;
+			/* fallthrough */
+		case NETDEV_DOWN:
+		case NETDEV_GOING_DOWN:
+			if (sky2->debugfs) {
+				printk(KERN_DEBUG PFX "%s: remove debugfs\n",
+				       dev->name);
+				debugfs_remove(sky2->debugfs);
+				sky2->debugfs = NULL;
+			}
+
+			if (event != NETDEV_CHANGENAME)
+				break;
+			/* fallthrough for changename */
+		case NETDEV_UP:
+			if (sky2_debug) {
+				struct dentry *d;
+				d = debugfs_create_file(dev->name, S_IRUGO,
+							sky2_debug, dev,
+							&sky2_debug_fops);
+				if (d == NULL || IS_ERR(d))
+					printk(KERN_INFO PFX
+					       "%s: debugfs create failed\n",
+					       dev->name);
+				else
+					sky2->debugfs = d;
+			}
+			break;
+		}
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block sky2_notifier = {
+	.notifier_call = sky2_device_event,
+};
+
+
+static __init void sky2_debug_init(void)
+{
+	struct dentry *ent;
+
+	ent = debugfs_create_dir("sky2", NULL);
+	if (!ent || IS_ERR(ent))
+		return;
+
+	sky2_debug = ent;
+	register_netdevice_notifier(&sky2_notifier);
+}
+
+static __exit void sky2_debug_cleanup(void)
+{
+	if (sky2_debug) {
+		unregister_netdevice_notifier(&sky2_notifier);
+		debugfs_remove(sky2_debug);
+		sky2_debug = NULL;
+	}
+}
+
+#else
+#define sky2_debug_init()
+#define sky2_debug_cleanup()
+#endif
+
+
 /* Initialize network device */
 static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
 						     unsigned port,
@@ -3486,10 +3813,6 @@
 	memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
-	/* device is off until link detection */
-	netif_carrier_off(dev);
-	netif_stop_queue(dev);
-
 	return dev;
 }
 
@@ -3906,12 +4229,14 @@
 
 static int __init sky2_init_module(void)
 {
+	sky2_debug_init();
 	return pci_register_driver(&sky2_driver);
 }
 
 static void __exit sky2_cleanup_module(void)
 {
 	pci_unregister_driver(&sky2_driver);
+	sky2_debug_cleanup();
 }
 
 module_init(sky2_init_module);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index b8c4a3b..dce4d27 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -14,6 +14,8 @@
 	PCI_DEV_REG3	= 0x80,
 	PCI_DEV_REG4	= 0x84,
 	PCI_DEV_REG5    = 0x88,
+	PCI_CFG_REG_0	= 0x90,
+	PCI_CFG_REG_1	= 0x94,
 };
 
 enum {
@@ -28,6 +30,7 @@
 enum pci_dev_reg_1 {
 	PCI_Y2_PIG_ENA	 = 1<<31, /* Enable Plug-in-Go (YUKON-2) */
 	PCI_Y2_DLL_DIS	 = 1<<30, /* Disable PCI DLL (YUKON-2) */
+	PCI_SW_PWR_ON_RST= 1<<30, /* SW Power on Reset (Yukon-EX) */
 	PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */
 	PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */
 	PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */
@@ -67,6 +70,80 @@
 				  | P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY,
 };
 
+/*	PCI_OUR_REG_5		32 bit	Our Register 5 (Yukon-ECU only) */
+enum pci_dev_reg_5 {
+					/* Bit 31..27:	for A3 & later */
+	P_CTL_DIV_CORE_CLK_ENA	= 1<<31, /* Divide Core Clock Enable */
+	P_CTL_SRESET_VMAIN_AV	= 1<<30, /* Soft Reset for Vmain_av De-Glitch */
+	P_CTL_BYPASS_VMAIN_AV	= 1<<29, /* Bypass En. for Vmain_av De-Glitch */
+	P_CTL_TIM_VMAIN_AV_MSK	= 3<<27, /* Bit 28..27: Timer Vmain_av Mask */
+					 /* Bit 26..16: Release Clock on Event */
+	P_REL_PCIE_RST_DE_ASS	= 1<<26, /* PCIe Reset De-Asserted */
+	P_REL_GPHY_REC_PACKET	= 1<<25, /* GPHY Received Packet */
+	P_REL_INT_FIFO_N_EMPTY	= 1<<24, /* Internal FIFO Not Empty */
+	P_REL_MAIN_PWR_AVAIL	= 1<<23, /* Main Power Available */
+	P_REL_CLKRUN_REQ_REL	= 1<<22, /* CLKRUN Request Release */
+	P_REL_PCIE_RESET_ASS	= 1<<21, /* PCIe Reset Asserted */
+	P_REL_PME_ASSERTED	= 1<<20, /* PME Asserted */
+	P_REL_PCIE_EXIT_L1_ST	= 1<<19, /* PCIe Exit L1 State */
+	P_REL_LOADER_NOT_FIN	= 1<<18, /* EPROM Loader Not Finished */
+	P_REL_PCIE_RX_EX_IDLE	= 1<<17, /* PCIe Rx Exit Electrical Idle State */
+	P_REL_GPHY_LINK_UP	= 1<<16, /* GPHY Link Up */
+
+					/* Bit 10.. 0: Mask for Gate Clock */
+	P_GAT_PCIE_RST_ASSERTED	= 1<<10,/* PCIe Reset Asserted */
+	P_GAT_GPHY_N_REC_PACKET	= 1<<9, /* GPHY Not Received Packet */
+	P_GAT_INT_FIFO_EMPTY	= 1<<8, /* Internal FIFO Empty */
+	P_GAT_MAIN_PWR_N_AVAIL	= 1<<7, /* Main Power Not Available */
+	P_GAT_CLKRUN_REQ_REL	= 1<<6, /* CLKRUN Not Requested */
+	P_GAT_PCIE_RESET_ASS	= 1<<5, /* PCIe Reset Asserted */
+	P_GAT_PME_DE_ASSERTED	= 1<<4, /* PME De-Asserted */
+	P_GAT_PCIE_ENTER_L1_ST	= 1<<3, /* PCIe Enter L1 State */
+	P_GAT_LOADER_FINISHED	= 1<<2, /* EPROM Loader Finished */
+	P_GAT_PCIE_RX_EL_IDLE	= 1<<1, /* PCIe Rx Electrical Idle State */
+	P_GAT_GPHY_LINK_DOWN	= 1<<0,	/* GPHY Link Down */
+
+	PCIE_OUR5_EVENT_CLK_D3_SET = P_REL_GPHY_REC_PACKET |
+				     P_REL_INT_FIFO_N_EMPTY |
+				     P_REL_PCIE_EXIT_L1_ST |
+				     P_REL_PCIE_RX_EX_IDLE |
+				     P_GAT_GPHY_N_REC_PACKET |
+				     P_GAT_INT_FIFO_EMPTY |
+				     P_GAT_PCIE_ENTER_L1_ST |
+				     P_GAT_PCIE_RX_EL_IDLE,
+};
+
+#/*	PCI_CFG_REG_1			32 bit	Config Register 1 (Yukon-Ext only) */
+enum pci_cfg_reg1 {
+	P_CF1_DIS_REL_EVT_RST	= 1<<24, /* Dis. Rel. Event during PCIE reset */
+										/* Bit 23..21: Release Clock on Event */
+	P_CF1_REL_LDR_NOT_FIN	= 1<<23, /* EEPROM Loader Not Finished */
+	P_CF1_REL_VMAIN_AVLBL	= 1<<22, /* Vmain available */
+	P_CF1_REL_PCIE_RESET	= 1<<21, /* PCI-E reset */
+										/* Bit 20..18: Gate Clock on Event */
+	P_CF1_GAT_LDR_NOT_FIN	= 1<<20, /* EEPROM Loader Finished */
+	P_CF1_GAT_PCIE_RX_IDLE	= 1<<19, /* PCI-E Rx Electrical idle */
+	P_CF1_GAT_PCIE_RESET	= 1<<18, /* PCI-E Reset */
+	P_CF1_PRST_PHY_CLKREQ	= 1<<17, /* Enable PCI-E rst & PM2PHY gen. CLKREQ */
+	P_CF1_PCIE_RST_CLKREQ	= 1<<16, /* Enable PCI-E rst generate CLKREQ */
+
+	P_CF1_ENA_CFG_LDR_DONE	= 1<<8, /* Enable core level Config loader done */
+
+	P_CF1_ENA_TXBMU_RD_IDLE	= 1<<1, /* Enable TX BMU Read  IDLE for ASPM */
+	P_CF1_ENA_TXBMU_WR_IDLE	= 1<<0, /* Enable TX BMU Write IDLE for ASPM */
+
+	PCIE_CFG1_EVENT_CLK_D3_SET = P_CF1_DIS_REL_EVT_RST |
+					P_CF1_REL_LDR_NOT_FIN |
+					P_CF1_REL_VMAIN_AVLBL |
+					P_CF1_REL_PCIE_RESET |
+					P_CF1_GAT_LDR_NOT_FIN |
+					P_CF1_GAT_PCIE_RESET |
+					P_CF1_PRST_PHY_CLKREQ |
+					P_CF1_ENA_CFG_LDR_DONE |
+					P_CF1_ENA_TXBMU_RD_IDLE |
+					P_CF1_ENA_TXBMU_WR_IDLE,
+};
+
 
 #define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
 			       PCI_STATUS_SIG_SYSTEM_ERROR | \
@@ -364,6 +441,20 @@
 	TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
 };
 
+/* 	B2_GPIO */
+enum {
+	GLB_GPIO_CLK_DEB_ENA = 1<<31,	/* Clock Debug Enable */
+	GLB_GPIO_CLK_DBG_MSK = 0xf<<26, /* Clock Debug */
+
+	GLB_GPIO_INT_RST_D3_DIS = 1<<15, /* Disable Internal Reset After D3 to D0 */
+	GLB_GPIO_LED_PAD_SPEED_UP = 1<<14, /* LED PAD Speed Up */
+	GLB_GPIO_STAT_RACE_DIS	= 1<<13, /* Status Race Disable */
+	GLB_GPIO_TEST_SEL_MSK	= 3<<11, /* Testmode Select */
+	GLB_GPIO_TEST_SEL_BASE	= 1<<11,
+	GLB_GPIO_RAND_ENA	= 1<<10, /* Random Enable */
+	GLB_GPIO_RAND_BIT_1	= 1<<9,  /* Random Bit 1 */
+};
+
 /*	B2_MAC_CFG		 8 bit	MAC Configuration / Chip Revision */
 enum {
 	CFG_CHIP_R_MSK	  = 0xf<<4,	/* Bit 7.. 4: Chip Revision */
@@ -392,6 +483,11 @@
 	CHIP_REV_YU_FE_A2    = 2,
 
 };
+enum yukon_ex_rev {
+	CHIP_REV_YU_EX_A0    = 1,
+	CHIP_REV_YU_EX_B0    = 2,
+};
+
 
 /*	B2_Y2_CLK_GATE	 8 bit	Clock Gating (Yukon-2 only) */
 enum {
@@ -515,23 +611,15 @@
 enum {
 	B8_Q_REGS = 0x0400, /* base of Queue registers */
 	Q_D	= 0x00,	/* 8*32	bit	Current Descriptor */
-	Q_DA_L	= 0x20,	/* 32 bit	Current Descriptor Address Low dWord */
-	Q_DA_H	= 0x24,	/* 32 bit	Current Descriptor Address High dWord */
+	Q_VLAN  = 0x20, /* 16 bit	Current VLAN Tag */
+	Q_DONE	= 0x24,	/* 16 bit	Done Index */
 	Q_AC_L	= 0x28,	/* 32 bit	Current Address Counter Low dWord */
 	Q_AC_H	= 0x2c,	/* 32 bit	Current Address Counter High dWord */
 	Q_BC	= 0x30,	/* 32 bit	Current Byte Counter */
 	Q_CSR	= 0x34,	/* 32 bit	BMU Control/Status Register */
-	Q_F	= 0x38,	/* 32 bit	Flag Register */
-	Q_T1	= 0x3c,	/* 32 bit	Test Register 1 */
-	Q_T1_TR	= 0x3c,	/*  8 bit	Test Register 1 Transfer SM */
-	Q_T1_WR	= 0x3d,	/*  8 bit	Test Register 1 Write Descriptor SM */
-	Q_T1_RD	= 0x3e,	/*  8 bit	Test Register 1 Read Descriptor SM */
-	Q_T1_SV	= 0x3f,	/*  8 bit	Test Register 1 Supervisor SM */
-	Q_T2	= 0x40,	/* 32 bit	Test Register 2	*/
-	Q_T3	= 0x44,	/* 32 bit	Test Register 3	*/
+	Q_TEST	= 0x38,	/* 32 bit	Test/Control Register */
 
 /* Yukon-2 */
-	Q_DONE	= 0x24,	/* 16 bit	Done Index 		(Yukon-2 only) */
 	Q_WM	= 0x40,	/* 16 bit	FIFO Watermark */
 	Q_AL	= 0x42,	/*  8 bit	FIFO Alignment */
 	Q_RSP	= 0x44,	/* 16 bit	FIFO Read Shadow Pointer */
@@ -545,15 +633,16 @@
 };
 #define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
 
-/*	Q_F				32 bit	Flag Register */
+/*	Q_TEST				32 bit	Test Register */
 enum {
-	F_ALM_FULL	= 1<<27, /* Rx FIFO: almost full */
-	F_EMPTY		= 1<<27, /* Tx FIFO: empty flag */
-	F_FIFO_EOF	= 1<<26, /* Tag (EOF Flag) bit in FIFO */
-	F_WM_REACHED	= 1<<25, /* Watermark reached */
+	/* Transmit */
+	F_TX_CHK_AUTO_OFF = 1<<31, /* Tx checksum auto calc off (Yukon EX) */
+	F_TX_CHK_AUTO_ON  = 1<<30, /* Tx checksum auto calc off (Yukon EX) */
+
+	/* Receive */
 	F_M_RX_RAM_DIS	= 1<<24, /* MAC Rx RAM Read Port disable */
-	F_FIFO_LEVEL	= 0x1fL<<16, /* Bit 23..16:	# of Qwords in FIFO */
-	F_WATER_MARK	= 0x0007ffL, /* Bit 10.. 0:	Watermark */
+
+	/* Hardware testbits not used */
 };
 
 /* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
@@ -1608,6 +1697,16 @@
 	RX_VLAN_STRIP_ON = 1<<25,	/* enable  VLAN stripping */
 	RX_VLAN_STRIP_OFF = 1<<24,	/* disable VLAN stripping */
 
+	RX_MACSEC_FLUSH_ON  = 1<<23,
+	RX_MACSEC_FLUSH_OFF = 1<<22,
+	RX_MACSEC_ASF_FLUSH_ON = 1<<21,
+	RX_MACSEC_ASF_FLUSH_OFF = 1<<20,
+
+	GMF_RX_OVER_ON      = 1<<19,	/* enable flushing on receive overrun */
+	GMF_RX_OVER_OFF     = 1<<18,	/* disable flushing on receive overrun */
+	GMF_ASF_RX_OVER_ON  = 1<<17,	/* enable flushing of ASF when overrun */
+	GMF_ASF_RX_OVER_OFF = 1<<16,	/* disable flushing of ASF when overrun */
+
 	GMF_WP_TST_ON	= 1<<14,	/* Write Pointer Test On */
 	GMF_WP_TST_OFF	= 1<<13,	/* Write Pointer Test Off */
 	GMF_WP_STEP	= 1<<12,	/* Write Pointer Step/Increment */
@@ -1720,6 +1819,15 @@
 
 /*	GMAC_CTRL		32 bit	GMAC Control Reg (YUKON only) */
 enum {
+	GMC_SET_RST	    = 1<<15,/* MAC SEC RST */
+	GMC_SEC_RST_OFF     = 1<<14,/* MAC SEC RSt OFF */
+	GMC_BYP_MACSECRX_ON = 1<<13,/* Bypass macsec RX */
+	GMC_BYP_MACSECRX_OFF= 1<<12,/* Bypass macsec RX off */
+	GMC_BYP_MACSECTX_ON = 1<<11,/* Bypass macsec TX */
+	GMC_BYP_MACSECTX_OFF= 1<<10,/* Bypass macsec TX  off*/
+	GMC_BYP_RETR_ON	= 1<<9, /* Bypass retransmit FIFO On */
+	GMC_BYP_RETR_OFF= 1<<8, /* Bypass retransmit FIFO Off */
+
 	GMC_H_BURST_ON	= 1<<7,	/* Half Duplex Burst Mode On */
 	GMC_H_BURST_OFF	= 1<<6,	/* Half Duplex Burst Mode Off */
 	GMC_F_LOOPB_ON	= 1<<5,	/* FIFO Loopback On */
@@ -1805,9 +1913,13 @@
 	OP_ADDR64VLAN	= OP_ADDR64 | OP_VLAN,
 	OP_LRGLEN	= 0x24,
 	OP_LRGLENVLAN	= OP_LRGLEN | OP_VLAN,
+	OP_MSS		= 0x28,
+	OP_MSSVLAN	= OP_MSS | OP_VLAN,
+
 	OP_BUFFER	= 0x40,
 	OP_PACKET	= 0x41,
 	OP_LARGESEND	= 0x43,
+	OP_LSOV2	= 0x45,
 
 /* YUKON-2 STATUS opcodes defines */
 	OP_RXSTAT	= 0x60,
@@ -1818,6 +1930,19 @@
 	OP_RXTIMEVLAN	= OP_RXTIMESTAMP | OP_RXVLAN,
 	OP_RSS_HASH	= 0x65,
 	OP_TXINDEXLE	= 0x68,
+	OP_MACSEC	= 0x6c,
+	OP_PUTIDX	= 0x70,
+};
+
+enum status_css {
+	CSS_TCPUDPCSOK	= 1<<7,	/* TCP / UDP checksum is ok */
+	CSS_ISUDP	= 1<<6, /* packet is a UDP packet */
+	CSS_ISTCP	= 1<<5, /* packet is a TCP packet */
+	CSS_ISIPFRAG	= 1<<4, /* packet is a TCP/UDP frag, CS calc not done */
+	CSS_ISIPV6	= 1<<3, /* packet is a IPv6 packet */
+	CSS_IPV4CSUMOK	= 1<<2, /* IP v4: TCP header checksum is ok */
+	CSS_ISIPV4	= 1<<1, /* packet is a IPv4 packet */
+	CSS_LINK_BIT	= 1<<0, /* port number (legacy) */
 };
 
 /* Yukon 2 hardware interface */
@@ -1838,7 +1963,7 @@
 struct sky2_status_le {
 	__le32	status;	/* also checksum */
 	__le16	length;	/* also vlan tag */
-	u8	link;
+	u8	css;
 	u8	opcode;
 } __attribute((packed));
 
@@ -1873,6 +1998,7 @@
 	struct sky2_tx_le    *tx_le;
 	u16		     tx_cons;		/* next le to check */
 	u16		     tx_prod;		/* next le to use */
+	u16		     tx_next;		/* debug only */
 	u32		     tx_addr64;
 	u16		     tx_pending;
 	u16		     tx_last_mss;
@@ -1903,6 +2029,9 @@
  	enum flow_control    flow_mode;
  	enum flow_control    flow_status;
 
+#ifdef CONFIG_SKY2_DEBUG
+	struct dentry	     *debugfs;
+#endif
 	struct net_device_stats net_stats;
 
 };
diff --git a/drivers/net/sni_82596.c b/drivers/net/sni_82596.c
new file mode 100644
index 0000000..2cf6794
--- /dev/null
+++ b/drivers/net/sni_82596.c
@@ -0,0 +1,185 @@
+/*
+ * sni_82596.c -- driver for intel 82596 ethernet controller, as
+ *  		  used in older SNI RM machines
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#define SNI_82596_DRIVER_VERSION "SNI RM 82596 driver - Revision: 0.01"
+
+static const char sni_82596_string[] = "snirm_82596";
+
+#define DMA_ALLOC                      dma_alloc_coherent
+#define DMA_FREE                       dma_free_coherent
+#define DMA_WBACK(priv, addr, len)     do { } while (0)
+#define DMA_INV(priv, addr, len)       do { } while (0)
+#define DMA_WBACK_INV(priv, addr, len) do { } while (0)
+
+#define SYSBUS      0x00004400
+
+/* big endian CPU, 82596 little endian */
+#define SWAP32(x)   cpu_to_le32((u32)(x))
+#define SWAP16(x)   cpu_to_le16((u16)(x))
+
+#define OPT_MPU_16BIT    0x01
+
+#include "lib82596.c"
+
+MODULE_AUTHOR("Thomas Bogendoerfer");
+MODULE_DESCRIPTION("i82596 driver");
+MODULE_LICENSE("GPL");
+module_param(i596_debug, int, 0);
+MODULE_PARM_DESC(i596_debug, "82596 debug mask");
+
+static inline void ca(struct net_device *dev)
+{
+	struct i596_private *lp = netdev_priv(dev);
+
+	writel(0, lp->ca);
+}
+
+
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
+{
+	struct i596_private *lp = netdev_priv(dev);
+
+	u32 v = (u32) (c) | (u32) (x);
+
+	if (lp->options & OPT_MPU_16BIT) {
+		writew(v & 0xffff, lp->mpu_port);
+		wmb();  /* order writes to MPU port */
+		udelay(1);
+		writew(v >> 16, lp->mpu_port);
+	} else {
+		writel(v, lp->mpu_port);
+		wmb();  /* order writes to MPU port */
+		udelay(1);
+		writel(v, lp->mpu_port);
+	}
+}
+
+
+static int __devinit sni_82596_probe(struct platform_device *dev)
+{
+	struct	net_device *netdevice;
+	struct i596_private *lp;
+	struct  resource *res, *ca, *idprom, *options;
+	int	retval = -ENOMEM;
+	void __iomem *mpu_addr;
+	void __iomem *ca_addr;
+	u8 __iomem *eth_addr;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	ca = platform_get_resource(dev, IORESOURCE_MEM, 1);
+	options = platform_get_resource(dev, 0, 0);
+	idprom = platform_get_resource(dev, IORESOURCE_MEM, 2);
+	if (!res || !ca || !options || !idprom)
+		return -ENODEV;
+	mpu_addr = ioremap_nocache(res->start, 4);
+	if (!mpu_addr)
+		return -ENOMEM;
+	ca_addr = ioremap_nocache(ca->start, 4);
+	if (!ca_addr)
+		goto probe_failed_free_mpu;
+
+	printk(KERN_INFO "Found i82596 at 0x%x\n", res->start);
+
+	netdevice = alloc_etherdev(sizeof(struct i596_private));
+	if (!netdevice)
+		goto probe_failed_free_ca;
+
+	SET_NETDEV_DEV(netdevice, &dev->dev);
+	platform_set_drvdata (dev, netdevice);
+
+	netdevice->base_addr = res->start;
+	netdevice->irq = platform_get_irq(dev, 0);
+
+	eth_addr = ioremap_nocache(idprom->start, 0x10);
+	if (!eth_addr)
+		goto probe_failed;
+
+	/* someone seems to like messed up stuff */
+	netdevice->dev_addr[0] = readb(eth_addr + 0x0b);
+	netdevice->dev_addr[1] = readb(eth_addr + 0x0a);
+	netdevice->dev_addr[2] = readb(eth_addr + 0x09);
+	netdevice->dev_addr[3] = readb(eth_addr + 0x08);
+	netdevice->dev_addr[4] = readb(eth_addr + 0x07);
+	netdevice->dev_addr[5] = readb(eth_addr + 0x06);
+	iounmap(eth_addr);
+
+	if (!netdevice->irq) {
+		printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
+			__FILE__, netdevice->base_addr);
+		goto probe_failed;
+	}
+
+	lp = netdev_priv(netdevice);
+	lp->options = options->flags & IORESOURCE_BITS;
+	lp->ca = ca_addr;
+	lp->mpu_port = mpu_addr;
+
+	retval = i82596_probe(netdevice);
+	if (retval == 0)
+		return 0;
+
+probe_failed:
+	free_netdev(netdevice);
+probe_failed_free_ca:
+	iounmap(ca_addr);
+probe_failed_free_mpu:
+	iounmap(mpu_addr);
+	return retval;
+}
+
+static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct i596_private *lp = netdev_priv(dev);
+
+	unregister_netdev(dev);
+	DMA_FREE(dev->dev.parent, sizeof(struct i596_private),
+		 lp->dma, lp->dma_addr);
+	iounmap(lp->ca);
+	iounmap(lp->mpu_port);
+	free_netdev (dev);
+	return 0;
+}
+
+static struct platform_driver sni_82596_driver = {
+	.probe	= sni_82596_probe,
+	.remove	= __devexit_p(sni_82596_driver_remove),
+	.driver	= {
+		.name	= sni_82596_string,
+	},
+};
+
+static int __devinit sni_82596_init(void)
+{
+	printk(KERN_INFO SNI_82596_DRIVER_VERSION "\n");
+	return platform_driver_register(&sni_82596_driver);
+}
+
+
+static void __exit sni_82596_exit(void)
+{
+	platform_driver_unregister(&sni_82596_driver);
+}
+
+module_init(sni_82596_init);
+module_exit(sni_82596_exit);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 7a4aa6a..590b12c 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -434,7 +434,8 @@
 				      bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
 	if (!descr->skb) {
 		if (netif_msg_rx_err(card) && net_ratelimit())
-			pr_err("Not enough memory to allocate rx buffer\n");
+			dev_err(&card->netdev->dev,
+			        "Not enough memory to allocate rx buffer\n");
 		card->spider_stats.alloc_rx_skb_error++;
 		return -ENOMEM;
 	}
@@ -455,7 +456,7 @@
 		dev_kfree_skb_any(descr->skb);
 		descr->skb = NULL;
 		if (netif_msg_rx_err(card) && net_ratelimit())
-			pr_err("Could not iommu-map rx buffer\n");
+			dev_err(&card->netdev->dev, "Could not iommu-map rx buffer\n");
 		card->spider_stats.rx_iommu_map_error++;
 		hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
 	} else {
@@ -500,6 +501,20 @@
 }
 
 /**
+ * spider_net_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * spider_net_disable_rxdmac terminates processing on the DMA controller
+ * by turing off the DMA controller, with the force-end flag set.
+ */
+static inline void
+spider_net_disable_rxdmac(struct spider_net_card *card)
+{
+	spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
+			     SPIDER_NET_DMA_RX_FEND_VALUE);
+}
+
+/**
  * spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains
  * @card: card structure
  *
@@ -655,20 +670,6 @@
 }
 
 /**
- * spider_net_disable_rxdmac - disables the receive DMA controller
- * @card: card structure
- *
- * spider_net_disable_rxdmac terminates processing on the DMA controller by
- * turing off DMA and issueing a force end
- */
-static void
-spider_net_disable_rxdmac(struct spider_net_card *card)
-{
-	spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
-			     SPIDER_NET_DMA_RX_FEND_VALUE);
-}
-
-/**
  * spider_net_prepare_tx_descr - fill tx descriptor with skb data
  * @card: card structure
  * @descr: descriptor structure to fill out
@@ -692,7 +693,7 @@
 	buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
 	if (pci_dma_mapping_error(buf)) {
 		if (netif_msg_tx_err(card) && net_ratelimit())
-			pr_err("could not iommu-map packet (%p, %i). "
+			dev_err(&card->netdev->dev, "could not iommu-map packet (%p, %i). "
 				  "Dropping packet\n", skb->data, skb->len);
 		card->spider_stats.tx_iommu_map_error++;
 		return -ENOMEM;
@@ -715,7 +716,7 @@
 	hwdescr->data_status = 0;
 
 	hwdescr->dmac_cmd_status =
-			SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
+			SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_TXFRMTL;
 	spin_unlock_irqrestore(&chain->lock, flags);
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -832,9 +833,8 @@
 		case SPIDER_NET_DESCR_PROTECTION_ERROR:
 		case SPIDER_NET_DESCR_FORCE_END:
 			if (netif_msg_tx_err(card))
-				pr_err("%s: forcing end of tx descriptor "
-				       "with status x%02x\n",
-				       card->netdev->name, status);
+				dev_err(&card->netdev->dev, "forcing end of tx descriptor "
+				       "with status x%02x\n", status);
 			card->netdev_stats.tx_errors++;
 			break;
 
@@ -1022,34 +1022,94 @@
 	netif_receive_skb(skb);
 }
 
-#ifdef DEBUG
 static void show_rx_chain(struct spider_net_card *card)
 {
 	struct spider_net_descr_chain *chain = &card->rx_chain;
 	struct spider_net_descr *start= chain->tail;
 	struct spider_net_descr *descr= start;
+	struct spider_net_hw_descr *hwd = start->hwdescr;
+	struct device *dev = &card->netdev->dev;
+	u32 curr_desc, next_desc;
 	int status;
 
+	int tot = 0;
 	int cnt = 0;
-	int cstat = spider_net_get_descr_status(descr);
-	printk(KERN_INFO "RX chain tail at descr=%ld\n",
-	     (start - card->descr) - card->tx_chain.num_desc);
+	int off = start - chain->ring;
+	int cstat = hwd->dmac_cmd_status;
+
+	dev_info(dev, "Total number of descrs=%d\n",
+		chain->num_desc);
+	dev_info(dev, "Chain tail located at descr=%d, status=0x%x\n",
+		off, cstat);
+
+	curr_desc = spider_net_read_reg(card, SPIDER_NET_GDACTDPA);
+	next_desc = spider_net_read_reg(card, SPIDER_NET_GDACNEXTDA);
+
 	status = cstat;
 	do
 	{
-		status = spider_net_get_descr_status(descr);
+		hwd = descr->hwdescr;
+		off = descr - chain->ring;
+		status = hwd->dmac_cmd_status;
+
+		if (descr == chain->head)
+			dev_info(dev, "Chain head is at %d, head status=0x%x\n",
+			         off, status);
+
+		if (curr_desc == descr->bus_addr)
+			dev_info(dev, "HW curr desc (GDACTDPA) is at %d, status=0x%x\n",
+			         off, status);
+
+		if (next_desc == descr->bus_addr)
+			dev_info(dev, "HW next desc (GDACNEXTDA) is at %d, status=0x%x\n",
+			         off, status);
+
+		if (hwd->next_descr_addr == 0)
+			dev_info(dev, "chain is cut at %d\n", off);
+
 		if (cstat != status) {
-			printk(KERN_INFO "Have %d descrs with stat=x%08x\n", cnt, cstat);
+			int from = (chain->num_desc + off - cnt) % chain->num_desc;
+			int to = (chain->num_desc + off - 1) % chain->num_desc;
+			dev_info(dev, "Have %d (from %d to %d) descrs "
+			         "with stat=0x%08x\n", cnt, from, to, cstat);
 			cstat = status;
 			cnt = 0;
 		}
+
 		cnt ++;
+		tot ++;
 		descr = descr->next;
 	} while (descr != start);
-	printk(KERN_INFO "Last %d descrs with stat=x%08x\n", cnt, cstat);
-}
+
+	dev_info(dev, "Last %d descrs with stat=0x%08x "
+	         "for a total of %d descrs\n", cnt, cstat, tot);
+
+#ifdef DEBUG
+	/* Now dump the whole ring */
+	descr = start;
+	do
+	{
+		struct spider_net_hw_descr *hwd = descr->hwdescr;
+		status = spider_net_get_descr_status(hwd);
+		cnt = descr - chain->ring;
+		dev_info(dev, "Descr %d stat=0x%08x skb=%p\n",
+		         cnt, status, descr->skb);
+		dev_info(dev, "bus addr=%08x buf addr=%08x sz=%d\n",
+		         descr->bus_addr, hwd->buf_addr, hwd->buf_size);
+		dev_info(dev, "next=%08x result sz=%d valid sz=%d\n",
+		         hwd->next_descr_addr, hwd->result_size,
+		         hwd->valid_size);
+		dev_info(dev, "dmac=%08x data stat=%08x data err=%08x\n",
+		         hwd->dmac_cmd_status, hwd->data_status,
+		         hwd->data_error);
+		dev_info(dev, "\n");
+
+		descr = descr->next;
+	} while (descr != start);
 #endif
 
+}
+
 /**
  * spider_net_resync_head_ptr - Advance head ptr past empty descrs
  *
@@ -1127,6 +1187,7 @@
 	struct spider_net_descr_chain *chain = &card->rx_chain;
 	struct spider_net_descr *descr = chain->tail;
 	struct spider_net_hw_descr *hwdescr = descr->hwdescr;
+	u32 hw_buf_addr;
 	int status;
 
 	status = spider_net_get_descr_status(hwdescr);
@@ -1140,15 +1201,17 @@
 	chain->tail = descr->next;
 
 	/* unmap descriptor */
-	pci_unmap_single(card->pdev, hwdescr->buf_addr,
+	hw_buf_addr = hwdescr->buf_addr;
+	hwdescr->buf_addr = 0xffffffff;
+	pci_unmap_single(card->pdev, hw_buf_addr,
 			SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
 
 	if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) ||
 	     (status == SPIDER_NET_DESCR_PROTECTION_ERROR) ||
 	     (status == SPIDER_NET_DESCR_FORCE_END) ) {
 		if (netif_msg_rx_err(card))
-			pr_err("%s: dropping RX descriptor with state %d\n",
-			       card->netdev->name, status);
+			dev_err(&card->netdev->dev,
+			       "dropping RX descriptor with state %d\n", status);
 		card->netdev_stats.rx_dropped++;
 		goto bad_desc;
 	}
@@ -1156,8 +1219,8 @@
 	if ( (status != SPIDER_NET_DESCR_COMPLETE) &&
 	     (status != SPIDER_NET_DESCR_FRAME_END) ) {
 		if (netif_msg_rx_err(card))
-			pr_err("%s: RX descriptor with unknown state %d\n",
-			       card->netdev->name, status);
+			dev_err(&card->netdev->dev,
+			       "RX descriptor with unknown state %d\n", status);
 		card->spider_stats.rx_desc_unk_state++;
 		goto bad_desc;
 	}
@@ -1165,18 +1228,17 @@
 	/* The cases we'll throw away the packet immediately */
 	if (hwdescr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
 		if (netif_msg_rx_err(card))
-			pr_err("%s: error in received descriptor found, "
+			dev_err(&card->netdev->dev,
+			       "error in received descriptor found, "
 			       "data_status=x%08x, data_error=x%08x\n",
-			       card->netdev->name,
 			       hwdescr->data_status, hwdescr->data_error);
 		goto bad_desc;
 	}
 
-	if (hwdescr->dmac_cmd_status & 0xfcf4) {
-		pr_err("%s: bad status, cmd_status=x%08x\n",
-			       card->netdev->name,
+	if (hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_BAD_STATUS) {
+		dev_err(&card->netdev->dev, "bad status, cmd_status=x%08x\n",
 			       hwdescr->dmac_cmd_status);
-		pr_err("buf_addr=x%08x\n", hwdescr->buf_addr);
+		pr_err("buf_addr=x%08x\n", hw_buf_addr);
 		pr_err("buf_size=x%08x\n", hwdescr->buf_size);
 		pr_err("next_descr_addr=x%08x\n", hwdescr->next_descr_addr);
 		pr_err("result_size=x%08x\n", hwdescr->result_size);
@@ -1196,6 +1258,8 @@
 	return 1;
 
 bad_desc:
+	if (netif_msg_rx_err(card))
+		show_rx_chain(card);
 	dev_kfree_skb_irq(descr->skb);
 	descr->skb = NULL;
 	hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
@@ -1221,7 +1285,6 @@
 	int packets_to_do, packets_done = 0;
 	int no_more_packets = 0;
 
-	spider_net_cleanup_tx_ring(card);
 	packets_to_do = min(*budget, netdev->quota);
 
 	while (packets_to_do) {
@@ -1246,6 +1309,8 @@
 	spider_net_refill_rx_chain(card);
 	spider_net_enable_rxdmac(card);
 
+	spider_net_cleanup_tx_ring(card);
+
 	/* if all packets are in the stack, enable interrupts and return 0 */
 	/* if not, return 1 */
 	if (no_more_packets) {
@@ -1376,11 +1441,17 @@
 spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
 {
 	u32 error_reg1, error_reg2;
+	u32 mask_reg1, mask_reg2;
 	u32 i;
 	int show_error = 1;
 
 	error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
 	error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
+	mask_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1MSK);
+	mask_reg2 = spider_net_read_reg(card,SPIDER_NET_GHIINT2MSK);
+
+	error_reg1 &= mask_reg1;
+	error_reg2 &= mask_reg2;
 
 	/* check GHIINT0STS ************************************/
 	if (status_reg)
@@ -1415,7 +1486,7 @@
 	case SPIDER_NET_GPWFFINT:
 		/* PHY command queue full */
 		if (netif_msg_intr(card))
-			pr_err("PHY write queue full\n");
+			dev_err(&card->netdev->dev, "PHY write queue full\n");
 		show_error = 0;
 		break;
 
@@ -1582,9 +1653,8 @@
 	}
 
 	if ((show_error) && (netif_msg_intr(card)) && net_ratelimit())
-		pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, "
+		dev_err(&card->netdev->dev, "Error interrupt, GHIINT0STS = 0x%08x, "
 		       "GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n",
-		       card->netdev->name,
 		       status_reg, error_reg1, error_reg2);
 
 	/* clear interrupt sources */
@@ -1609,9 +1679,11 @@
 {
 	struct net_device *netdev = ptr;
 	struct spider_net_card *card = netdev_priv(netdev);
-	u32 status_reg;
+	u32 status_reg, mask_reg;
 
 	status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS);
+	mask_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+	status_reg &= mask_reg;
 
 	if (!status_reg)
 		return IRQ_NONE;
@@ -1653,6 +1725,38 @@
 #endif /* CONFIG_NET_POLL_CONTROLLER */
 
 /**
+ * spider_net_enable_interrupts - enable interrupts
+ * @card: card structure
+ *
+ * spider_net_enable_interrupt enables several interrupts
+ */
+static void 
+spider_net_enable_interrupts(struct spider_net_card *card)
+{
+	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
+			     SPIDER_NET_INT0_MASK_VALUE);
+	spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
+			     SPIDER_NET_INT1_MASK_VALUE);
+	spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
+			     SPIDER_NET_INT2_MASK_VALUE);
+}
+
+/**
+ * spider_net_disable_interrupts - disable interrupts
+ * @card: card structure
+ *
+ * spider_net_disable_interrupts disables all the interrupts
+ */
+static void 
+spider_net_disable_interrupts(struct spider_net_card *card)
+{
+	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
+	spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
+	spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
+	spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
+}
+
+/**
  * spider_net_init_card - initializes the card
  * @card: card structure
  *
@@ -1672,6 +1776,7 @@
 	spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
 		spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4);
 
+	spider_net_disable_interrupts(card);
 }
 
 /**
@@ -1759,14 +1864,6 @@
 	spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
 			     SPIDER_NET_OPMODE_VALUE);
 
-	/* set interrupt mask registers */
-	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
-			     SPIDER_NET_INT0_MASK_VALUE);
-	spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
-			     SPIDER_NET_INT1_MASK_VALUE);
-	spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
-			     SPIDER_NET_INT2_MASK_VALUE);
-
 	spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
 			     SPIDER_NET_GDTBSTA);
 }
@@ -1849,7 +1946,8 @@
 			     SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
 		if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
 		     netif_msg_probe(card) ) {
-			pr_err("Incorrect size of spidernet firmware in " \
+			dev_err(&card->netdev->dev,
+			       "Incorrect size of spidernet firmware in " \
 			       "filesystem. Looking in host firmware...\n");
 			goto try_host_fw;
 		}
@@ -1873,8 +1971,8 @@
 
 	if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
 	     netif_msg_probe(card) ) {
-		pr_err("Incorrect size of spidernet firmware in " \
-		       "host firmware\n");
+		dev_err(&card->netdev->dev,
+		       "Incorrect size of spidernet firmware in host firmware\n");
 		goto done;
 	}
 
@@ -1884,7 +1982,8 @@
 	return err;
 out_err:
 	if (netif_msg_probe(card))
-		pr_err("Couldn't find spidernet firmware in filesystem " \
+		dev_err(&card->netdev->dev,
+		       "Couldn't find spidernet firmware in filesystem " \
 		       "or host firmware\n");
 	return err;
 }
@@ -1941,6 +2040,8 @@
 	netif_carrier_on(netdev);
 	netif_poll_enable(netdev);
 
+	spider_net_enable_interrupts(card);
+
 	return 0;
 
 register_int_failed:
@@ -2113,11 +2214,7 @@
 	del_timer_sync(&card->tx_timer);
 	del_timer_sync(&card->aneg_timer);
 
-	/* disable/mask all interrupts */
-	spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
-	spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
-	spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
-	spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
+	spider_net_disable_interrupts(card);
 
 	free_irq(netdev->irq, netdev);
 
@@ -2279,13 +2376,14 @@
 
 	result = spider_net_set_mac(netdev, &addr);
 	if ((result) && (netif_msg_probe(card)))
-		pr_err("Failed to set MAC address: %i\n", result);
+		dev_err(&card->netdev->dev,
+		        "Failed to set MAC address: %i\n", result);
 
 	result = register_netdev(netdev);
 	if (result) {
 		if (netif_msg_probe(card))
-			pr_err("Couldn't register net_device: %i\n",
-				  result);
+			dev_err(&card->netdev->dev,
+			        "Couldn't register net_device: %i\n", result);
 		return result;
 	}
 
@@ -2363,17 +2461,19 @@
 	unsigned long mmio_start, mmio_len;
 
 	if (pci_enable_device(pdev)) {
-		pr_err("Couldn't enable PCI device\n");
+		dev_err(&pdev->dev, "Couldn't enable PCI device\n");
 		return NULL;
 	}
 
 	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-		pr_err("Couldn't find proper PCI device base address.\n");
+		dev_err(&pdev->dev,
+		        "Couldn't find proper PCI device base address.\n");
 		goto out_disable_dev;
 	}
 
 	if (pci_request_regions(pdev, spider_net_driver_name)) {
-		pr_err("Couldn't obtain PCI resources, aborting.\n");
+		dev_err(&pdev->dev,
+		        "Couldn't obtain PCI resources, aborting.\n");
 		goto out_disable_dev;
 	}
 
@@ -2381,8 +2481,8 @@
 
 	card = spider_net_alloc_card();
 	if (!card) {
-		pr_err("Couldn't allocate net_device structure, "
-			  "aborting.\n");
+		dev_err(&pdev->dev,
+		        "Couldn't allocate net_device structure, aborting.\n");
 		goto out_release_regions;
 	}
 	card->pdev = pdev;
@@ -2396,7 +2496,8 @@
 	card->regs = ioremap(mmio_start, mmio_len);
 
 	if (!card->regs) {
-		pr_err("Couldn't obtain PCI resources, aborting.\n");
+		dev_err(&pdev->dev,
+		        "Couldn't obtain PCI resources, aborting.\n");
 		goto out_release_regions;
 	}
 
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 1d054aa..dbbdb8c 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -349,11 +349,23 @@
 #define SPIDER_NET_GPRDAT_MASK			0x0000ffff
 
 #define SPIDER_NET_DMAC_NOINTR_COMPLETE		0x00800000
-#define SPIDER_NET_DMAC_NOCS			0x00040000
+#define SPIDER_NET_DMAC_TXFRMTL		0x00040000
 #define SPIDER_NET_DMAC_TCP			0x00020000
 #define SPIDER_NET_DMAC_UDP			0x00030000
 #define SPIDER_NET_TXDCEST			0x08000000
 
+#define SPIDER_NET_DESCR_RXFDIS        0x00000001
+#define SPIDER_NET_DESCR_RXDCEIS       0x00000002
+#define SPIDER_NET_DESCR_RXDEN0IS      0x00000004
+#define SPIDER_NET_DESCR_RXINVDIS      0x00000008
+#define SPIDER_NET_DESCR_RXRERRIS      0x00000010
+#define SPIDER_NET_DESCR_RXFDCIMS      0x00000100
+#define SPIDER_NET_DESCR_RXDCEIMS      0x00000200
+#define SPIDER_NET_DESCR_RXDEN0IMS     0x00000400
+#define SPIDER_NET_DESCR_RXINVDIMS     0x00000800
+#define SPIDER_NET_DESCR_RXRERRMIS     0x00001000
+#define SPIDER_NET_DESCR_UNUSED        0x077fe0e0
+
 #define SPIDER_NET_DESCR_IND_PROC_MASK		0xF0000000
 #define SPIDER_NET_DESCR_COMPLETE		0x00000000 /* used in rx and tx */
 #define SPIDER_NET_DESCR_RESPONSE_ERROR		0x10000000 /* used in rx and tx */
@@ -364,6 +376,13 @@
 #define SPIDER_NET_DESCR_NOT_IN_USE		0xF0000000
 #define SPIDER_NET_DESCR_TXDESFLG		0x00800000
 
+#define SPIDER_NET_DESCR_BAD_STATUS   (SPIDER_NET_DESCR_RXDEN0IS | \
+                                       SPIDER_NET_DESCR_RXRERRIS | \
+                                       SPIDER_NET_DESCR_RXDEN0IMS | \
+                                       SPIDER_NET_DESCR_RXINVDIMS | \
+                                       SPIDER_NET_DESCR_RXRERRMIS | \
+                                       SPIDER_NET_DESCR_UNUSED)
+
 /* Descriptor, as defined by the hardware */
 struct spider_net_hw_descr {
 	u32 buf_addr;
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 786d4b9..f2e1019 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -1456,7 +1456,7 @@
 			pci_dma_sync_single_for_cpu(np->pci_dev,
 						    np->rx_info[entry].mapping,
 						    pkt_len, PCI_DMA_FROMDEVICE);
-			eth_copy_and_sum(skb, np->rx_info[entry].skb->data, pkt_len, 0);
+			skb_copy_to_linear_data(skb, np->rx_info[entry].skb->data, pkt_len);
 			pci_dma_sync_single_for_device(np->pci_dev,
 						       np->rx_info[entry].mapping,
 						       pkt_len, PCI_DMA_FROMDEVICE);
diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c
index a123ea8..b77ab6e 100644
--- a/drivers/net/sun3_82586.c
+++ b/drivers/net/sun3_82586.c
@@ -777,7 +777,7 @@
 					{
 						skb_reserve(skb,2);
 						skb_put(skb,totlen);
-						eth_copy_and_sum(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen,0);
+						skb_copy_to_linear_data(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen);
 						skb->protocol=eth_type_trans(skb,dev);
 						netif_rx(skb);
 						p->stats.rx_packets++;
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 791e081..f1548c0 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -853,10 +853,9 @@
 
 				skb_reserve( skb, 2 );	/* 16 byte align */
 				skb_put( skb, pkt_len );	/* Make room */
-//			        skb_copy_to_linear_data(skb, PKTBUF_ADDR(head), pkt_len);
-				eth_copy_and_sum(skb,
+				skb_copy_to_linear_data(skb,
 						 PKTBUF_ADDR(head),
-						 pkt_len, 0);
+						 pkt_len);
 
 				skb->protocol = eth_type_trans( skb, dev );
 				netif_rx( skb );
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 2ad8d58..b3e0158 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -860,7 +860,7 @@
 			sbus_dma_sync_single_for_cpu(bp->bigmac_sdev,
 						     this->rx_addr, len,
 						     SBUS_DMA_FROMDEVICE);
-			eth_copy_and_sum(copy_skb, (unsigned char *)skb->data, len, 0);
+			skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len);
 			sbus_dma_sync_single_for_device(bp->bigmac_sdev,
 							this->rx_addr, len,
 							SBUS_DMA_FROMDEVICE);
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index e1f912d..c8ba534 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -1313,7 +1313,7 @@
 							    np->rx_buf_sz,
 							    PCI_DMA_FROMDEVICE);
 
-				eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
 				pci_dma_sync_single_for_device(np->pci_dev,
 							       desc->frag[0].addr,
 							       np->rx_buf_sz,
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 51c3fe2..15146a1 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2625,7 +2625,7 @@
 #endif /* CONFIG_SBUS */
 
 #ifdef CONFIG_PCI
-static struct quattro * __init quattro_pci_find(struct pci_dev *pdev)
+static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev)
 {
 	struct pci_dev *bdev = pdev->bus->self;
 	struct quattro *qp;
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 4272253..053b7cb 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -549,9 +549,9 @@
 
 			skb_reserve(skb, 2);		/* 16 byte align */
 			skb_put(skb, len);		/* make room */
-			eth_copy_and_sum(skb,
+			skb_copy_to_linear_data(skb,
 					 (unsigned char *)&(ib->rx_buf [entry][0]),
-					 len, 0);
+					 len);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
 			dev->last_rx = jiffies;
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index fa70e0b..1b65ae8 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -439,8 +439,8 @@
 			} else {
 				skb_reserve(skb, 2);
 				skb_put(skb, len);
-				eth_copy_and_sum(skb, (unsigned char *) this_qbuf,
-						 len, 0);
+				skb_copy_to_linear_data(skb, (unsigned char *) this_qbuf,
+						 len);
 				skb->protocol = eth_type_trans(skb, qep->dev);
 				netif_rx(skb);
 				qep->dev->last_rx = jiffies;
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 463d600..75655ad 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -23,9 +23,9 @@
  */
 
 #ifdef TC35815_NAPI
-#define DRV_VERSION	"1.35-NAPI"
+#define DRV_VERSION	"1.36-NAPI"
 #else
-#define DRV_VERSION	"1.35"
+#define DRV_VERSION	"1.36"
 #endif
 static const char *version = "tc35815.c:v" DRV_VERSION "\n";
 #define MODNAME			"tc35815"
@@ -49,6 +49,7 @@
 #include <linux/pci.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
@@ -597,13 +598,46 @@
 static void tc_mdio_write(struct net_device *dev, int phy_id, int location,
 			  int val);
 
-static void __devinit tc35815_init_dev_addr (struct net_device *dev)
+#ifdef CONFIG_CPU_TX49XX
+/*
+ * Find a platform_device providing a MAC address.  The platform code
+ * should provide a "tc35815-mac" device with a MAC address in its
+ * platform_data.
+ */
+static int __devinit tc35815_mac_match(struct device *dev, void *data)
+{
+	struct platform_device *plat_dev = to_platform_device(dev);
+	struct pci_dev *pci_dev = data;
+	unsigned int id = (pci_dev->bus->number << 8) | pci_dev->devfn;
+	return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id;
+}
+
+static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+{
+	struct tc35815_local *lp = dev->priv;
+	struct device *pd = bus_find_device(&platform_bus_type, NULL,
+					    lp->pci_dev, tc35815_mac_match);
+	if (pd) {
+		if (pd->platform_data)
+			memcpy(dev->dev_addr, pd->platform_data, ETH_ALEN);
+		put_device(pd);
+		return is_valid_ether_addr(dev->dev_addr) ? 0 : -ENODEV;
+	}
+	return -ENODEV;
+}
+#else
+static int __devinit tc35815_read_plat_dev_addr(struct device *dev)
+{
+	return -ENODEV;
+}
+#endif
+
+static int __devinit tc35815_init_dev_addr (struct net_device *dev)
 {
 	struct tc35815_regs __iomem *tr =
 		(struct tc35815_regs __iomem *)dev->base_addr;
 	int i;
 
-	/* dev_addr will be overwritten on NETDEV_REGISTER event */
 	while (tc_readl(&tr->PROM_Ctl) & PROM_Busy)
 		;
 	for (i = 0; i < 6; i += 2) {
@@ -615,6 +649,9 @@
 		dev->dev_addr[i] = data & 0xff;
 		dev->dev_addr[i+1] = data >> 8;
 	}
+	if (!is_valid_ether_addr(dev->dev_addr))
+		return tc35815_read_plat_dev_addr(dev);
+	return 0;
 }
 
 static int __devinit tc35815_init_one (struct pci_dev *pdev,
@@ -724,7 +761,10 @@
 	tc35815_chip_reset(dev);
 
 	/* Retrieve the ethernet address. */
-	tc35815_init_dev_addr(dev);
+	if (tc35815_init_dev_addr(dev)) {
+		dev_warn(&pdev->dev, "not valid ether addr\n");
+		random_ether_addr(dev->dev_addr);
+	}
 
 	rc = register_netdev (dev);
 	if (rc)
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 2f31841..3a43426 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -11944,12 +11944,11 @@
 	 * checksumming.
 	 */
 	if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
+		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
-			dev->features |= NETIF_F_HW_CSUM;
-		else
-			dev->features |= NETIF_F_IP_CSUM;
-		dev->features |= NETIF_F_SG;
+			dev->features |= NETIF_F_IPV6_CSUM;
+
 		tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
 	} else
 		tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index e22a3f5..9f1b6ab 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -363,7 +363,7 @@
 }
 
 
-static int __init xl_init(struct net_device *dev) 
+static int __devinit xl_init(struct net_device *dev) 
 {
     	struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
 
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 8c9634a..1c537d5 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -2,17 +2,17 @@
 # Tulip family network device configuration
 #
 
-menu "Tulip family network device support"
-	depends on NET_ETHERNET && (PCI || EISA || CARDBUS)
-
-config NET_TULIP
+menuconfig NET_TULIP
 	bool "\"Tulip\" family network device support"
+	depends on PCI || EISA || CARDBUS
 	help
 	  This selects the "Tulip" family of EISA/PCI network cards.
 
+if NET_TULIP
+
 config DE2104X
 	tristate "Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)"
-	depends on NET_TULIP && PCI && EXPERIMENTAL
+	depends on PCI && EXPERIMENTAL
 	select CRC32
 	---help---
 	  This driver is developed for the SMC EtherPower series Ethernet
@@ -30,7 +30,7 @@
 
 config TULIP
 	tristate "DECchip Tulip (dc2114x) PCI support"
-	depends on NET_TULIP && PCI
+	depends on PCI
 	select CRC32
 	---help---
 	  This driver is developed for the SMC EtherPower series Ethernet
@@ -95,7 +95,7 @@
 
 config DE4X5
 	tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
-	depends on NET_TULIP && (PCI || EISA)
+	depends on PCI || EISA
 	select CRC32
 	---help---
 	  This is support for the DIGITAL series of PCI/EISA Ethernet cards.
@@ -112,7 +112,7 @@
 
 config WINBOND_840
 	tristate "Winbond W89c840 Ethernet support"
-	depends on NET_TULIP && PCI
+	depends on PCI
 	select CRC32
 	select MII
 	help
@@ -123,7 +123,7 @@
 
 config DM9102
 	tristate "Davicom DM910x/DM980x support"
-	depends on NET_TULIP && PCI
+	depends on PCI
 	select CRC32
 	---help---
 	  This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
@@ -137,7 +137,7 @@
 
 config ULI526X
 	tristate "ULi M526x controller support"
-	depends on NET_TULIP && PCI
+	depends on PCI
 	select CRC32
 	---help---
 	  This driver is for ULi M5261/M5263 10/100M Ethernet Controller
@@ -149,7 +149,7 @@
 	  
 config PCMCIA_XIRCOM
 	tristate "Xircom CardBus support (new driver)"
-	depends on NET_TULIP && CARDBUS
+	depends on CARDBUS
 	---help---
 	  This driver is for the Digital "Tulip" Ethernet CardBus adapters.
 	  It should work with most DEC 21*4*-based chips/ethercards, as well
@@ -162,7 +162,7 @@
 
 config PCMCIA_XIRTULIP
 	tristate "Xircom Tulip-like CardBus support (old driver)"
-	depends on NET_TULIP && CARDBUS && BROKEN_ON_SMP
+	depends on CARDBUS && BROKEN_ON_SMP
 	select CRC32
 	---help---
 	  This driver is for the Digital "Tulip" Ethernet CardBus adapters.
@@ -174,5 +174,4 @@
 	  <file:Documentation/networking/net-modules.txt>.  The module will
 	  be called xircom_tulip_cb.  If unsure, say N.
 
-endmenu
-
+endif # NET_TULIP
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index 8617298..d380e0b 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -785,7 +785,6 @@
 
 	de->tx_head = NEXT_TX(entry);
 
-	BUG_ON(TX_BUFFS_AVAIL(de) < 0);
 	if (TX_BUFFS_AVAIL(de) == 0)
 		netif_stop_queue(dev);
 
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 62143f9..42fca26 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -597,7 +597,7 @@
 #endif
 
 struct parameters {
-    int fdx;
+    bool fdx;
     int autosense;
 };
 
@@ -809,10 +809,10 @@
     s32  irq_en;                            /* Summary interrupt bits       */
     int  media;                             /* Media (eg TP), mode (eg 100B)*/
     int  c_media;                           /* Remember the last media conn */
-    int  fdx;                               /* media full duplex flag       */
+    bool fdx;                               /* media full duplex flag       */
     int  linkOK;                            /* Link is OK                   */
     int  autosense;                         /* Allow/disallow autosensing   */
-    int  tx_enable;                         /* Enable descriptor polling    */
+    bool tx_enable;                         /* Enable descriptor polling    */
     int  setup_f;                           /* Setup frame filtering type   */
     int  local_state;                       /* State within a 'media' state */
     struct mii_phy phy[DE4X5_MAX_PHY];      /* List of attached PHY devices */
@@ -838,8 +838,8 @@
     struct de4x5_srom srom;                 /* A copy of the SROM           */
     int cfrv;				    /* Card CFRV copy */
     int rx_ovf;                             /* Check for 'RX overflow' tag  */
-    int useSROM;                            /* For non-DEC card use SROM    */
-    int useMII;                             /* Infoblock using the MII      */
+    bool useSROM;                           /* For non-DEC card use SROM    */
+    bool useMII;                            /* Infoblock using the MII      */
     int asBitValid;                         /* Autosense bits in GEP?       */
     int asPolarity;                         /* 0 => asserted high           */
     int asBit;                              /* Autosense bit number in GEP  */
@@ -928,7 +928,7 @@
 static int     test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec);
 static int     test_for_100Mb(struct net_device *dev, int msec);
 static int     wait_for_link(struct net_device *dev);
-static int     test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec);
+static int     test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec);
 static int     is_spd_100(struct net_device *dev);
 static int     is_100_up(struct net_device *dev);
 static int     is_10_up(struct net_device *dev);
@@ -1109,7 +1109,7 @@
     /*
     ** Now find out what kind of DC21040/DC21041/DC21140 board we have.
     */
-    lp->useSROM = FALSE;
+    lp->useSROM = false;
     if (lp->bus == PCI) {
 	PCI_signature(name, lp);
     } else {
@@ -1137,7 +1137,7 @@
 	lp->cache.gepc = GEP_INIT;
 	lp->asBit = GEP_SLNK;
 	lp->asPolarity = GEP_SLNK;
-	lp->asBitValid = TRUE;
+	lp->asBitValid = ~0;
 	lp->timeout = -1;
 	lp->gendev = gendev;
 	spin_lock_init(&lp->lock);
@@ -1463,7 +1463,7 @@
     u_long flags = 0;
 
     netif_stop_queue(dev);
-    if (lp->tx_enable == NO) {                   /* Cannot send for now */
+    if (!lp->tx_enable) {                   /* Cannot send for now */
 	return -1;
     }
 
@@ -2424,7 +2424,7 @@
     switch (lp->media) {
     case INIT:
 	DISABLE_IRQs;
-	lp->tx_enable = NO;
+	lp->tx_enable = false;
 	lp->timeout = -1;
 	de4x5_save_skbs(dev);
 	if ((lp->autosense == AUTO) || (lp->autosense == TP)) {
@@ -2477,7 +2477,7 @@
 	    lp->c_media = lp->media;
 	}
 	lp->media = INIT;
-	lp->tx_enable = NO;
+	lp->tx_enable = false;
 	break;
     }
 
@@ -2578,7 +2578,7 @@
     switch (lp->media) {
     case INIT:
 	DISABLE_IRQs;
-	lp->tx_enable = NO;
+	lp->tx_enable = false;
 	lp->timeout = -1;
 	de4x5_save_skbs(dev);          /* Save non transmitted skb's */
 	if ((lp->autosense == AUTO) || (lp->autosense == TP_NW)) {
@@ -2757,7 +2757,7 @@
 	    lp->c_media = lp->media;
 	}
 	lp->media = INIT;
-	lp->tx_enable = NO;
+	lp->tx_enable = false;
 	break;
     }
 
@@ -2781,7 +2781,7 @@
     case INIT:
         if (lp->timeout < 0) {
 	    DISABLE_IRQs;
-	    lp->tx_enable = FALSE;
+	    lp->tx_enable = false;
 	    lp->linkOK = 0;
 	    de4x5_save_skbs(dev);          /* Save non transmitted skb's */
 	}
@@ -2830,7 +2830,7 @@
 	    if (lp->timeout < 0) {
 		mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
 	    }
-	    cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
+	    cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
 	    if (cr < 0) {
 		next_tick = cr & ~TIMER_CB;
 	    } else {
@@ -2845,7 +2845,7 @@
 	    break;
 
 	case 1:
-	    if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
+	    if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000)) < 0) {
 		next_tick = sr & ~TIMER_CB;
 	    } else {
 		lp->media = SPD_DET;
@@ -2857,10 +2857,10 @@
 		    if (!(anlpa & MII_ANLPA_RF) &&
 			 (cap = anlpa & MII_ANLPA_TAF & ana)) {
 			if (cap & MII_ANA_100M) {
-			    lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
+			    lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
 			    lp->media = _100Mb;
 			} else if (cap & MII_ANA_10M) {
-			    lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
+			    lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
 
 			    lp->media = _10Mb;
 			}
@@ -2932,7 +2932,7 @@
 	    lp->c_media = lp->media;
 	}
 	lp->media = INIT;
-	lp->tx_enable = FALSE;
+	lp->tx_enable = false;
 	break;
     }
 
@@ -2965,7 +2965,7 @@
     case INIT:
         if (lp->timeout < 0) {
 	    DISABLE_IRQs;
-	    lp->tx_enable = FALSE;
+	    lp->tx_enable = false;
 	    lp->linkOK = 0;
             lp->timeout = -1;
 	    de4x5_save_skbs(dev);            /* Save non transmitted skb's */
@@ -3013,7 +3013,7 @@
 	    if (lp->timeout < 0) {
 		mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
 	    }
-	    cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
+	    cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
 	    if (cr < 0) {
 		next_tick = cr & ~TIMER_CB;
 	    } else {
@@ -3028,7 +3028,8 @@
 	    break;
 
 	case 1:
-	    if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
+	    sr = test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000);
+	    if (sr < 0) {
 		next_tick = sr & ~TIMER_CB;
 	    } else {
 		lp->media = SPD_DET;
@@ -3040,10 +3041,10 @@
 		    if (!(anlpa & MII_ANLPA_RF) &&
 			 (cap = anlpa & MII_ANLPA_TAF & ana)) {
 			if (cap & MII_ANA_100M) {
-			    lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
+			    lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
 			    lp->media = _100Mb;
 			} else if (cap & MII_ANA_10M) {
-			    lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
+			    lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
 			    lp->media = _10Mb;
 			}
 		    }
@@ -3222,14 +3223,14 @@
 {
     struct de4x5_private *lp = netdev_priv(dev);
 
-    lp->fdx = 0;
+    lp->fdx = false;
     if (lp->infoblock_media == lp->media)
       return 0;
 
     switch(lp->infoblock_media) {
       case SROM_10BASETF:
 	if (!lp->params.fdx) return -1;
-	lp->fdx = TRUE;
+	lp->fdx = true;
       case SROM_10BASET:
 	if (lp->params.fdx && !lp->fdx) return -1;
 	if ((lp->chipset == DC21140) || ((lp->chipset & ~0x00ff) == DC2114x)) {
@@ -3249,7 +3250,7 @@
 
       case SROM_100BASETF:
         if (!lp->params.fdx) return -1;
-	lp->fdx = TRUE;
+	lp->fdx = true;
       case SROM_100BASET:
 	if (lp->params.fdx && !lp->fdx) return -1;
 	lp->media = _100Mb;
@@ -3261,7 +3262,7 @@
 
       case SROM_100BASEFF:
 	if (!lp->params.fdx) return -1;
-	lp->fdx = TRUE;
+	lp->fdx = true;
       case SROM_100BASEF:
 	if (lp->params.fdx && !lp->fdx) return -1;
 	lp->media = _100Mb;
@@ -3297,7 +3298,7 @@
     spin_lock_irqsave(&lp->lock, flags);
     de4x5_rst_desc_ring(dev);
     de4x5_setup_intr(dev);
-    lp->tx_enable = YES;
+    lp->tx_enable = true;
     spin_unlock_irqrestore(&lp->lock, flags);
     outl(POLL_DEMAND, DE4X5_TPD);
 
@@ -3336,7 +3337,7 @@
             }
         }
 	if (lp->useMII) {
-	    next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, FALSE, 500);
+	    next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, false, 500);
 	}
     } else if (lp->chipset == DC21140) {
 	PHY_HARD_RESET;
@@ -3466,7 +3467,7 @@
 **
 */
 static int
-test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
+test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec)
 {
     struct de4x5_private *lp = netdev_priv(dev);
     int test;
@@ -3476,9 +3477,8 @@
 	lp->timeout = msec/100;
     }
 
-    if (pol) pol = ~0;
     reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask;
-    test = (reg ^ pol) & mask;
+    test = (reg ^ (pol ? ~0 : 0)) & mask;
 
     if (test && --lp->timeout) {
 	reg = 100 | TIMER_CB;
@@ -3992,10 +3992,10 @@
 			     )))))));
 	}
 	if (lp->chipset != DC21041) {
-	    lp->useSROM = TRUE;             /* card is not recognisably DEC */
+	    lp->useSROM = true;             /* card is not recognisably DEC */
 	}
     } else if ((lp->chipset & ~0x00ff) == DC2114x) {
-	lp->useSROM = TRUE;
+	lp->useSROM = true;
     }
 
     return status;
@@ -4216,7 +4216,7 @@
 	memset((char *)&lp->srom, 0, sizeof(struct de4x5_srom));
 	memcpy(lp->srom.ieee_addr, (char *)dev->dev_addr, ETH_ALEN);
 	memcpy(lp->srom.info, (char *)&srom_repair_info[SMC-1], 100);
-	lp->useSROM = TRUE;
+	lp->useSROM = true;
 	break;
     }
 
@@ -4392,7 +4392,7 @@
 	if (lp->chipset == infoleaf_array[i].chipset) break;
     }
     if (i == INFOLEAF_SIZE) {
-	lp->useSROM = FALSE;
+	lp->useSROM = false;
 	printk("%s: Cannot find correct chipset for SROM decoding!\n",
 	                                                          dev->name);
 	return -ENXIO;
@@ -4409,7 +4409,7 @@
 	    if (lp->device == *p) break;
 	}
 	if (i == 0) {
-	    lp->useSROM = FALSE;
+	    lp->useSROM = false;
 	    printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n",
 	                                               dev->name, lp->device);
 	    return -ENXIO;
@@ -4542,7 +4542,7 @@
 	}
 	lp->media = INIT;
 	lp->tcount = 0;
-	lp->tx_enable = FALSE;
+	lp->tx_enable = false;
     }
 
     return next_tick & ~TIMER_CB;
@@ -4577,7 +4577,7 @@
 	}
 	lp->media = INIT;
 	lp->tcount = 0;
-	lp->tx_enable = FALSE;
+	lp->tx_enable = false;
     }
 
     return next_tick & ~TIMER_CB;
@@ -4611,7 +4611,7 @@
 	}
 	lp->media = INIT;
 	lp->tcount = 0;
-	lp->tx_enable = FALSE;
+	lp->tx_enable = false;
     }
 
     return next_tick & ~TIMER_CB;
@@ -4650,7 +4650,7 @@
 	lp->asBit = 1 << ((csr6 >> 1) & 0x07);
 	lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
 	lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
-	lp->useMII = FALSE;
+	lp->useMII = false;
 
 	de4x5_switch_mac_port(dev);
     }
@@ -4691,7 +4691,7 @@
 	lp->asBit = 1 << ((csr6 >> 1) & 0x07);
 	lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
 	lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
-	lp->useMII = FALSE;
+	lp->useMII = false;
 
 	de4x5_switch_mac_port(dev);
     }
@@ -4731,7 +4731,7 @@
         lp->ibn = 1;
         lp->active = *p;
 	lp->infoblock_csr6 = OMR_MII_100;
-	lp->useMII = TRUE;
+	lp->useMII = true;
 	lp->infoblock_media = ANS;
 
 	de4x5_switch_mac_port(dev);
@@ -4773,7 +4773,7 @@
         lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
         lp->cache.gep  = ((s32)(TWIDDLE(p)) << 16);
 	lp->infoblock_csr6 = OMR_SIA;
-	lp->useMII = FALSE;
+	lp->useMII = false;
 
 	de4x5_switch_mac_port(dev);
     }
@@ -4814,7 +4814,7 @@
 	lp->active = *p;
 	if (MOTO_SROM_BUG) lp->active = 0;
 	lp->infoblock_csr6 = OMR_MII_100;
-	lp->useMII = TRUE;
+	lp->useMII = true;
 	lp->infoblock_media = ANS;
 
 	de4x5_switch_mac_port(dev);
@@ -4856,7 +4856,7 @@
 	lp->asBit = 1 << ((csr6 >> 1) & 0x07);
 	lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
 	lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
-	lp->useMII = FALSE;
+	lp->useMII = false;
 
 	de4x5_switch_mac_port(dev);
     }
@@ -5077,7 +5077,7 @@
     int id;
 
     lp->active = 0;
-    lp->useMII = TRUE;
+    lp->useMII = true;
 
     /* Search the MII address space for possible PHY devices */
     for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) {
@@ -5127,7 +5127,7 @@
 	    de4x5_dbg_mii(dev, k);
 	}
     }
-    if (!lp->mii_cnt) lp->useMII = FALSE;
+    if (!lp->mii_cnt) lp->useMII = false;
 
     return lp->mii_cnt;
 }
diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h
index 57226e5..12af0cc 100644
--- a/drivers/net/tulip/de4x5.h
+++ b/drivers/net/tulip/de4x5.h
@@ -893,15 +893,6 @@
 #define PHYS_ADDR_ONLY       1     /* Update the physical address only */
 
 /*
-** Booleans
-*/
-#define NO                   0
-#define FALSE                0
-
-#define YES                  ~0
-#define TRUE                 ~0
-
-/*
 ** Adapter state
 */
 #define INITIALISED          0     /* After h/w initialised and mem alloc'd */
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index ea89677..53efd66 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -197,8 +197,8 @@
 								   tp->rx_buffers[entry].mapping,
 								   pkt_len, PCI_DMA_FROMDEVICE);
 #if ! defined(__alpha__)
-                                       eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
-                                                        pkt_len, 0);
+                                       skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
+                                                        pkt_len);
                                        skb_put(skb, pkt_len);
 #else
                                        memcpy(skb_put(skb, pkt_len),
@@ -420,8 +420,8 @@
 							    tp->rx_buffers[entry].mapping,
 							    pkt_len, PCI_DMA_FROMDEVICE);
 #if ! defined(__alpha__)
-				eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
-						 pkt_len, 0);
+				skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
+						 pkt_len);
 				skb_put(skb, pkt_len);
 #else
 				memcpy(skb_put(skb, pkt_len),
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 38f3b99..5824f6a 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -1232,7 +1232,7 @@
 				pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry],
 							    np->rx_skbuff[entry]->len,
 							    PCI_DMA_FROMDEVICE);
-				eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
 				skb_put(skb, pkt_len);
 				pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry],
 							       np->rx_skbuff[entry]->len,
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 2470b1e..37e35cd 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -1208,7 +1208,7 @@
 				goto out;
 			}
 			skb_reserve(skb, 2);
-			eth_copy_and_sum(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len, 0);
+			skb_copy_to_linear_data(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len);
 			skb_put(skb, pkt_len);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
index f641729..f984fbd 100644
--- a/drivers/net/tulip/xircom_tulip_cb.c
+++ b/drivers/net/tulip/xircom_tulip_cb.c
@@ -1242,8 +1242,8 @@
 				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
 				skb_reserve(skb, 2);	/* 16 byte align the IP header */
 #if ! defined(__alpha__)
-				eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
-								 pkt_len, 0);
+				skb_copy_to_linear_data(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
+								 pkt_len);
 				skb_put(skb, pkt_len);
 #else
 				memcpy(skb_put(skb, pkt_len),
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a2c6caa..62b2b30 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -432,6 +432,7 @@
 	init_waitqueue_head(&tun->read_wait);
 
 	tun->owner = -1;
+	tun->group = -1;
 
 	SET_MODULE_OWNER(dev);
 	dev->open = tun_net_open;
@@ -467,8 +468,11 @@
 			return -EBUSY;
 
 		/* Check permissions */
-		if (tun->owner != -1 &&
-		    current->euid != tun->owner && !capable(CAP_NET_ADMIN))
+		if (((tun->owner != -1 &&
+		      current->euid != tun->owner) ||
+		     (tun->group != -1 &&
+		      current->egid != tun->group)) &&
+		     !capable(CAP_NET_ADMIN))
 			return -EPERM;
 	}
 	else if (__dev_get_by_name(ifr->ifr_name))
@@ -610,6 +614,13 @@
 		DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
 		break;
 
+	case TUNSETGROUP:
+		/* Set group of the device */
+		tun->group= (gid_t) arg;
+
+		DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group);
+		break;
+
 	case TUNSETLINK:
 		/* Only allow setting the type when the interface is down */
 		if (tun->dev->flags & IFF_UP) {
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 15b2fb8..df52454 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -1703,7 +1703,7 @@
 			pci_dma_sync_single_for_cpu(tp->pdev, dma_addr,
 						    PKT_BUF_SZ,
 						    PCI_DMA_FROMDEVICE);
-			eth_copy_and_sum(new_skb, skb->data, pkt_len, 0);
+			skb_copy_to_linear_data(new_skb, skb->data, pkt_len);
 			pci_dma_sync_single_for_device(tp->pdev, dma_addr,
 						       PKT_BUF_SZ,
 						       PCI_DMA_FROMDEVICE);
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 18b731b..e4736a3 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -2276,7 +2276,7 @@
 	phy_stop(phydev);
 
 	/* Mask all interrupts */
-	out_be32(ugeth->uccf->p_ucce, 0x00000000);
+	out_be32(ugeth->uccf->p_uccm, 0x00000000);
 
 	/* Clear all interrupts */
 	out_be32(ugeth->uccf->p_ucce, 0xffffffff);
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 86e90c5..76752d84 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -255,7 +255,7 @@
 		if (!(skb = dev_alloc_skb(pkt_len)))
 			return;
 
-		eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
+		skb_copy_to_linear_data(skb, pkt_start + pkt_offset, pkt_len);
 		skb_put(skb, pkt_len);
 
 		skb->protocol = eth_type_trans(skb, catc->netdev);
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index 60d2944..524dc5f 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -635,7 +635,7 @@
 
 		skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
 
-		eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0);
+		skb_copy_to_linear_data(skb, kaweth->rx_buf + 2, pkt_len);
 
 		skb_put(skb, pkt_len);
 
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index a12f576..37bf4f2 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -192,7 +192,7 @@
 				usb_pipeendpoint(pipe), maxp, period);
 		}
 	}
-	return  0;
+	return 0;
 }
 
 /* Passes this packet up the stack, updating its accounting.
@@ -326,7 +326,7 @@
 	if (netif_running (dev->net)
 			&& netif_device_present (dev->net)
 			&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
-		switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
+		switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
 		case -EPIPE:
 			usbnet_defer_kevent (dev, EVENT_RX_HALT);
 			break;
@@ -393,8 +393,8 @@
 	entry->urb = NULL;
 
 	switch (urb_status) {
-	    // success
-	    case 0:
+	/* success */
+	case 0:
 		if (skb->len < dev->net->hard_header_len) {
 			entry->state = rx_cleanup;
 			dev->stats.rx_errors++;
@@ -404,28 +404,30 @@
 		}
 		break;
 
-	    // stalls need manual reset. this is rare ... except that
-	    // when going through USB 2.0 TTs, unplug appears this way.
-	    // we avoid the highspeed version of the ETIMEOUT/EILSEQ
-	    // storm, recovering as needed.
-	    case -EPIPE:
+	/* stalls need manual reset. this is rare ... except that
+	 * when going through USB 2.0 TTs, unplug appears this way.
+	 * we avoid the highspeed version of the ETIMEOUT/EILSEQ
+	 * storm, recovering as needed.
+	 */
+	case -EPIPE:
 		dev->stats.rx_errors++;
 		usbnet_defer_kevent (dev, EVENT_RX_HALT);
 		// FALLTHROUGH
 
-	    // software-driven interface shutdown
-	    case -ECONNRESET:		// async unlink
-	    case -ESHUTDOWN:		// hardware gone
+	/* software-driven interface shutdown */
+	case -ECONNRESET:		/* async unlink */
+	case -ESHUTDOWN:		/* hardware gone */
 		if (netif_msg_ifdown (dev))
 			devdbg (dev, "rx shutdown, code %d", urb_status);
 		goto block;
 
-	    // we get controller i/o faults during khubd disconnect() delays.
-	    // throttle down resubmits, to avoid log floods; just temporarily,
-	    // so we still recover when the fault isn't a khubd delay.
-	    case -EPROTO:
-	    case -ETIME:
-	    case -EILSEQ:
+	/* we get controller i/o faults during khubd disconnect() delays.
+	 * throttle down resubmits, to avoid log floods; just temporarily,
+	 * so we still recover when the fault isn't a khubd delay.
+	 */
+	case -EPROTO:
+	case -ETIME:
+	case -EILSEQ:
 		dev->stats.rx_errors++;
 		if (!timer_pending (&dev->delay)) {
 			mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
@@ -438,12 +440,12 @@
 		urb = NULL;
 		break;
 
-	    // data overrun ... flush fifo?
-	    case -EOVERFLOW:
+	/* data overrun ... flush fifo? */
+	case -EOVERFLOW:
 		dev->stats.rx_over_errors++;
 		// FALLTHROUGH
 
-	    default:
+	default:
 		entry->state = rx_cleanup;
 		dev->stats.rx_errors++;
 		if (netif_msg_rx_err (dev))
@@ -471,22 +473,22 @@
 	int		status = urb->status;
 
 	switch (status) {
-	    /* success */
-	    case 0:
+	/* success */
+	case 0:
 		dev->driver_info->status(dev, urb);
 		break;
 
-	    /* software-driven interface shutdown */
-	    case -ENOENT:		// urb killed
-	    case -ESHUTDOWN:		// hardware gone
+	/* software-driven interface shutdown */
+	case -ENOENT:		/* urb killed */
+	case -ESHUTDOWN:	/* hardware gone */
 		if (netif_msg_ifdown (dev))
 			devdbg (dev, "intr shutdown, code %d", status);
 		return;
 
-	    /* NOTE:  not throttling like RX/TX, since this endpoint
-	     * already polls infrequently
-	     */
-	    default:
+	/* NOTE:  not throttling like RX/TX, since this endpoint
+	 * already polls infrequently
+	 */
+	default:
 		devdbg (dev, "intr status %d", status);
 		break;
 	}
@@ -569,9 +571,9 @@
 	temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq);
 
 	// maybe wait for deletions to finish.
-	while (!skb_queue_empty(&dev->rxq) &&
-	       !skb_queue_empty(&dev->txq) &&
-	       !skb_queue_empty(&dev->done)) {
+	while (!skb_queue_empty(&dev->rxq)
+			&& !skb_queue_empty(&dev->txq)
+			&& !skb_queue_empty(&dev->done)) {
 		msleep(UNLINK_TIMEOUT_MS);
 		if (netif_msg_ifdown (dev))
 			devdbg (dev, "waited for %d urb completions", temp);
@@ -1011,16 +1013,16 @@
 	while ((skb = skb_dequeue (&dev->done))) {
 		entry = (struct skb_data *) skb->cb;
 		switch (entry->state) {
-		    case rx_done:
+		case rx_done:
 			entry->state = rx_cleanup;
 			rx_process (dev, skb);
 			continue;
-		    case tx_done:
-		    case rx_cleanup:
+		case tx_done:
+		case rx_cleanup:
 			usb_free_urb (entry->urb);
 			dev_kfree_skb (skb);
 			continue;
-		    default:
+		default:
 			devdbg (dev, "bogus skb state %d", entry->state);
 		}
 	}
@@ -1211,7 +1213,7 @@
 			status = 0;
 
 	}
-	if (status == 0 && dev->status)
+	if (status >= 0 && dev->status)
 		status = init_status (dev, udev);
 	if (status < 0)
 		goto out3;
diff --git a/drivers/net/usb/usbnet.h b/drivers/net/usb/usbnet.h
index a3f8b9e..a6c5820 100644
--- a/drivers/net/usb/usbnet.h
+++ b/drivers/net/usb/usbnet.h
@@ -47,7 +47,7 @@
 	unsigned long		data [5];
 	u32			xid;
 	u32			hard_mtu;	/* count any extra framing */
-	size_t		        rx_urb_size;    /* size for rx urbs  */
+	size_t			rx_urb_size;	/* size for rx urbs */
 	struct mii_if_info	mii;
 
 	/* various kinds of pending driver work */
@@ -85,7 +85,7 @@
 #define FLAG_NO_SETINT	0x0010		/* device can't set_interface() */
 #define FLAG_ETHER	0x0020		/* maybe use "eth%d" names */
 
-#define FLAG_FRAMING_AX 0x0040          /* AX88772/178 packets */
+#define FLAG_FRAMING_AX 0x0040		/* AX88772/178 packets */
 
 	/* init device ... can sleep, or cause probe() failure */
 	int	(*bind)(struct usbnet *, struct usb_interface *);
@@ -146,9 +146,9 @@
 
 /* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
 #define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
- 			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
- 			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
- 			|USB_CDC_PACKET_TYPE_DIRECTED)
+			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
+			|USB_CDC_PACKET_TYPE_DIRECTED)
 
 
 /* we record the state for each of our queued skbs */
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index adea290a9..565f6cc 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -1492,9 +1492,9 @@
 							    rp->rx_buf_sz,
 							    PCI_DMA_FROMDEVICE);
 
-				eth_copy_and_sum(skb,
+				skb_copy_to_linear_data(skb,
 						 rp->rx_skbuff[entry]->data,
-						 pkt_len, 0);
+						 pkt_len);
 				skb_put(skb, pkt_len);
 				pci_dma_sync_single_for_device(rp->pdev,
 							       rp->rx_skbuff_dma[entry],
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index fa2399c..ae27af0 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -546,6 +546,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called zd1201.
 
+config RTL8187
+	tristate "Realtek 8187 USB support"
+	depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
+	select EEPROM_93CX6
+	---help---
+	  This is a driver for RTL8187 based cards.
+	  These are USB based chips found in cards such as:
+
+	  Netgear WG111v2
+
+	  Thanks to Realtek for their support!
+
 source "drivers/net/wireless/hostap/Kconfig"
 source "drivers/net/wireless/bcm43xx/Kconfig"
 source "drivers/net/wireless/zd1211rw/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index d212460..ef35bc6 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -44,3 +44,6 @@
 
 obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
 obj-$(CONFIG_LIBERTAS_USB)     += libertas/
+
+rtl8187-objs		:= rtl8187_dev.o rtl8187_rtl8225.o
+obj-$(CONFIG_RTL8187)	+= rtl8187.o
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index b37f1e3..d779199 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -1638,7 +1638,7 @@
 		return;
 	}
 
-	if (phy->analog > 1) {
+	if (phy->analog == 1) {
 		value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
 		value |= (baseband_attenuation << 2) & 0x003C;
 	} else {
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 5b3abd5..9090052 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -326,7 +326,6 @@
 	char *p = page;
 	struct ap_data *ap = (struct ap_data *) data;
 	char *policy_txt;
-	struct list_head *ptr;
 	struct mac_entry *entry;
 
 	if (off != 0) {
@@ -352,14 +351,12 @@
 	p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries);
 	p += sprintf(p, "MAC list:\n");
 	spin_lock_bh(&ap->mac_restrictions.lock);
-	for (ptr = ap->mac_restrictions.mac_list.next;
-	     ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) {
+	list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) {
 		if (p - page > PAGE_SIZE - 80) {
 			p += sprintf(p, "All entries did not fit one page.\n");
 			break;
 		}
 
-		entry = list_entry(ptr, struct mac_entry, list);
 		p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr));
 	}
 	spin_unlock_bh(&ap->mac_restrictions.lock);
@@ -413,7 +410,6 @@
 static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
 			       u8 *mac)
 {
-	struct list_head *ptr;
 	struct mac_entry *entry;
 	int found = 0;
 
@@ -421,10 +417,7 @@
 		return 0;
 
 	spin_lock_bh(&mac_restrictions->lock);
-	for (ptr = mac_restrictions->mac_list.next;
-	     ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
-		entry = list_entry(ptr, struct mac_entry, list);
-
+	list_for_each_entry(entry, &mac_restrictions->mac_list, list) {
 		if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
 			found = 1;
 			break;
@@ -519,7 +512,7 @@
 {
 	char *p = page;
 	struct ap_data *ap = (struct ap_data *) data;
-	struct list_head *ptr;
+	struct sta_info *sta;
 	int i;
 
 	if (off > PROC_LIMIT) {
@@ -529,9 +522,7 @@
 
 	p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
 	spin_lock_bh(&ap->sta_table_lock);
-	for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
-		struct sta_info *sta = (struct sta_info *) ptr;
-
+	list_for_each_entry(sta, &ap->sta_list, list) {
 		if (!sta->ap)
 			continue;
 
@@ -861,7 +852,7 @@
 
 void hostap_free_data(struct ap_data *ap)
 {
-	struct list_head *n, *ptr;
+	struct sta_info *n, *sta;
 
 	if (ap == NULL || !ap->initialized) {
 		printk(KERN_DEBUG "hostap_free_data: ap has not yet been "
@@ -875,8 +866,7 @@
 	ap->crypt = ap->crypt_priv = NULL;
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
 
-	list_for_each_safe(ptr, n, &ap->sta_list) {
-		struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+	list_for_each_entry_safe(sta, n, &ap->sta_list, list) {
 		ap_sta_hash_del(ap, sta);
 		list_del(&sta->list);
 		if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
@@ -2704,6 +2694,8 @@
 
 	if (hdr->addr1[0] & 0x01) {
 		/* broadcast/multicast frame - no AP related processing */
+		if (local->ap->num_sta <= 0)
+			ret = AP_TX_DROP;
 		goto out;
 	}
 
@@ -3198,15 +3190,14 @@
 
 void hostap_update_rates(local_info_t *local)
 {
-	struct list_head *ptr;
+	struct sta_info *sta;
 	struct ap_data *ap = local->ap;
 
 	if (!ap)
 		return;
 
 	spin_lock_bh(&ap->sta_table_lock);
-	for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
-		struct sta_info *sta = (struct sta_info *) ptr;
+	list_for_each_entry(sta, &ap->sta_list, list) {
 		prism2_check_tx_rates(sta);
 	}
 	spin_unlock_bh(&ap->sta_table_lock);
@@ -3242,11 +3233,10 @@
 void hostap_add_wds_links(local_info_t *local)
 {
 	struct ap_data *ap = local->ap;
-	struct list_head *ptr;
+	struct sta_info *sta;
 
 	spin_lock_bh(&ap->sta_table_lock);
-	list_for_each(ptr, &ap->sta_list) {
-		struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+	list_for_each_entry(sta, &ap->sta_list, list) {
 		if (sta->ap)
 			hostap_wds_link_oper(local, sta->addr, WDS_ADD);
 	}
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index c090a5a..30acd39 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -1,8 +1,6 @@
 #ifndef HOSTAP_CONFIG_H
 #define HOSTAP_CONFIG_H
 
-#define PRISM2_VERSION "0.4.4-kernel"
-
 /* In the previous versions of Host AP driver, support for user space version
  * of IEEE 802.11 management (hostapd) used to be disabled in the default
  * configuration. From now on, support for hostapd is always included and it is
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index ee1532b..30e723f 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -22,7 +22,6 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static dev_info_t dev_info = "hostap_cs";
 
 MODULE_AUTHOR("Jouni Malinen");
@@ -30,7 +29,6 @@
 		   "cards (PC Card).");
 MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 
 static int ignore_cis_vcc;
@@ -910,14 +908,12 @@
 
 static int __init init_prism2_pccard(void)
 {
-	printk(KERN_INFO "%s: %s\n", dev_info, version);
 	return pcmcia_register_driver(&hostap_driver);
 }
 
 static void __exit exit_prism2_pccard(void)
 {
 	pcmcia_unregister_driver(&hostap_driver);
-	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
 }
 
 
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index cdea7f7..8c71077 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -3893,8 +3893,6 @@
 	local = iface->local;
 
 	strncpy(info->driver, "hostap", sizeof(info->driver) - 1);
-	strncpy(info->version, PRISM2_VERSION,
-		sizeof(info->version) - 1);
 	snprintf(info->fw_version, sizeof(info->fw_version) - 1,
 		 "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
 		 (local->sta_fw_ver >> 8) & 0xff,
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 4743426..446de51 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -37,7 +37,6 @@
 MODULE_AUTHOR("Jouni Malinen");
 MODULE_DESCRIPTION("Host AP common routines");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 #define TX_TIMEOUT (2 * HZ)
 
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index db4899e..0cd48d1 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -20,7 +20,6 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static char *dev_info = "hostap_pci";
 
 
@@ -29,7 +28,6 @@
 		   "PCI cards.");
 MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 
 /* struct local_info::hw_priv */
@@ -462,8 +460,6 @@
 
 static int __init init_prism2_pci(void)
 {
-	printk(KERN_INFO "%s: %s\n", dev_info, version);
-
 	return pci_register_driver(&prism2_pci_drv_id);
 }
 
@@ -471,7 +467,6 @@
 static void __exit exit_prism2_pci(void)
 {
 	pci_unregister_driver(&prism2_pci_drv_id);
-	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
 }
 
 
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index f0fd5ec..0183df7 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -23,7 +23,6 @@
 #include "hostap_wlan.h"
 
 
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
 static char *dev_info = "hostap_plx";
 
 
@@ -32,7 +31,6 @@
 		   "cards (PLX).");
 MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
 
 
 static int ignore_cis;
@@ -623,8 +621,6 @@
 
 static int __init init_prism2_plx(void)
 {
-	printk(KERN_INFO "%s: %s\n", dev_info, version);
-
 	return pci_register_driver(&prism2_plx_drv_id);
 }
 
@@ -632,7 +628,6 @@
 static void __exit exit_prism2_plx(void)
 {
 	pci_unregister_driver(&prism2_plx_drv_id);
-	printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
 }
 
 
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
new file mode 100644
index 0000000..6124e46
--- /dev/null
+++ b/drivers/net/wireless/rtl8187.h
@@ -0,0 +1,145 @@
+/*
+ * Definitions for RTL8187 hardware
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RTL8187_H
+#define RTL8187_H
+
+#include "rtl818x.h"
+
+#define RTL8187_EEPROM_TXPWR_BASE	0x05
+#define RTL8187_EEPROM_MAC_ADDR		0x07
+#define RTL8187_EEPROM_TXPWR_CHAN_1	0x16	/* 3 channels */
+#define RTL8187_EEPROM_TXPWR_CHAN_6	0x1B	/* 2 channels */
+#define RTL8187_EEPROM_TXPWR_CHAN_4	0x3D	/* 2 channels */
+
+#define RTL8187_REQT_READ	0xC0
+#define RTL8187_REQT_WRITE	0x40
+#define RTL8187_REQ_GET_REG	0x05
+#define RTL8187_REQ_SET_REG	0x05
+
+#define RTL8187_MAX_RX		0x9C4
+
+struct rtl8187_rx_info {
+	struct urb *urb;
+	struct ieee80211_hw *dev;
+};
+
+struct rtl8187_rx_hdr {
+	__le16 len;
+	__le16 rate;
+	u8 noise;
+	u8 signal;
+	u8 agc;
+	u8 reserved;
+	__le64 mac_time;
+} __attribute__((packed));
+
+struct rtl8187_tx_info {
+	struct ieee80211_tx_control *control;
+	struct urb *urb;
+	struct ieee80211_hw *dev;
+};
+
+struct rtl8187_tx_hdr {
+	__le32 flags;
+#define RTL8187_TX_FLAG_NO_ENCRYPT	(1 << 15)
+#define RTL8187_TX_FLAG_MORE_FRAG	(1 << 17)
+#define RTL8187_TX_FLAG_CTS		(1 << 18)
+#define RTL8187_TX_FLAG_RTS		(1 << 23)
+	__le16 rts_duration;
+	__le16 len;
+	__le32 retry;
+} __attribute__((packed));
+
+struct rtl8187_priv {
+	/* common between rtl818x drivers */
+	struct rtl818x_csr *map;
+	void (*rf_init)(struct ieee80211_hw *);
+	int mode;
+
+	/* rtl8187 specific */
+	struct ieee80211_channel channels[14];
+	struct ieee80211_rate rates[12];
+	struct ieee80211_hw_mode modes[2];
+	struct usb_device *udev;
+	u8 *hwaddr;
+	u16 txpwr_base;
+	u8 asic_rev;
+	struct sk_buff_head rx_queue;
+};
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
+
+static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
+{
+	u8 val;
+
+	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+	return val;
+}
+
+static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
+{
+	__le16 val;
+
+	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+	return le16_to_cpu(val);
+}
+
+static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
+{
+	__le32 val;
+
+	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+	return le32_to_cpu(val);
+}
+
+static inline void rtl818x_iowrite8(struct rtl8187_priv *priv,
+				    u8 *addr, u8 val)
+{
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+}
+
+static inline void rtl818x_iowrite16(struct rtl8187_priv *priv,
+				     __le16 *addr, u16 val)
+{
+	__le16 buf = cpu_to_le16(val);
+
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+static inline void rtl818x_iowrite32(struct rtl8187_priv *priv,
+				     __le32 *addr, u32 val)
+{
+	__le32 buf = cpu_to_le32(val);
+
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+#endif /* RTL8187_H */
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
new file mode 100644
index 0000000..cea8589
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -0,0 +1,731 @@
+/*
+ * Linux device driver for RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Magic delays and register offsets below are taken from the original
+ * r8187 driver sources.  Thanks to Realtek for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/eeprom_93cx6.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
+MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
+MODULE_DESCRIPTION("RTL8187 USB wireless driver");
+MODULE_LICENSE("GPL");
+
+static struct usb_device_id rtl8187_table[] __devinitdata = {
+	/* Realtek */
+	{USB_DEVICE(0x0bda, 0x8187)},
+	/* Netgear */
+	{USB_DEVICE(0x0846, 0x6100)},
+	{USB_DEVICE(0x0846, 0x6a00)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, rtl8187_table);
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	data <<= 8;
+	data |= addr | 0x80;
+
+	rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF);
+	rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
+	rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
+	rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
+
+	msleep(1);
+}
+
+static void rtl8187_tx_cb(struct urb *urb)
+{
+	struct ieee80211_tx_status status = { {0} };
+	struct sk_buff *skb = (struct sk_buff *)urb->context;
+	struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb;
+
+	usb_free_urb(info->urb);
+	if (info->control)
+		memcpy(&status.control, info->control, sizeof(status.control));
+	kfree(info->control);
+	skb_pull(skb, sizeof(struct rtl8187_tx_hdr));
+	status.flags |= IEEE80211_TX_STATUS_ACK;
+	ieee80211_tx_status_irqsafe(info->dev, skb, &status);
+}
+
+static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+		      struct ieee80211_tx_control *control)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	struct rtl8187_tx_hdr *hdr;
+	struct rtl8187_tx_info *info;
+	struct urb *urb;
+	u32 tmp;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		kfree_skb(skb);
+		return 0;
+	}
+
+	hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
+	tmp = skb->len - sizeof(*hdr);
+	tmp |= RTL8187_TX_FLAG_NO_ENCRYPT;
+	tmp |= control->rts_cts_rate << 19;
+	tmp |= control->tx_rate << 24;
+	if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb))
+		tmp |= RTL8187_TX_FLAG_MORE_FRAG;
+	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
+		tmp |= RTL8187_TX_FLAG_RTS;
+		hdr->rts_duration =
+			ieee80211_rts_duration(dev, skb->len, control);
+	}
+	if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+		tmp |= RTL8187_TX_FLAG_CTS;
+	hdr->flags = cpu_to_le32(tmp);
+	hdr->len = 0;
+	tmp = control->retry_limit << 8;
+	hdr->retry = cpu_to_le32(tmp);
+
+	info = (struct rtl8187_tx_info *)skb->cb;
+	info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC);
+	info->urb = urb;
+	info->dev = dev;
+	usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2),
+			  hdr, skb->len, rtl8187_tx_cb, skb);
+	usb_submit_urb(urb, GFP_ATOMIC);
+
+	return 0;
+}
+
+static void rtl8187_rx_cb(struct urb *urb)
+{
+	struct sk_buff *skb = (struct sk_buff *)urb->context;
+	struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb;
+	struct ieee80211_hw *dev = info->dev;
+	struct rtl8187_priv *priv = dev->priv;
+	struct rtl8187_rx_hdr *hdr;
+	struct ieee80211_rx_status rx_status = { 0 };
+	int rate, signal;
+
+	spin_lock(&priv->rx_queue.lock);
+	if (skb->next)
+		__skb_unlink(skb, &priv->rx_queue);
+	else {
+		spin_unlock(&priv->rx_queue.lock);
+		return;
+	}
+	spin_unlock(&priv->rx_queue.lock);
+
+	if (unlikely(urb->status)) {
+		usb_free_urb(urb);
+		dev_kfree_skb_irq(skb);
+		return;
+	}
+
+	skb_put(skb, urb->actual_length);
+	hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr));
+	skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF);
+
+	signal = hdr->agc >> 1;
+	rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF;
+	if (rate > 3) {	/* OFDM rate */
+		if (signal > 90)
+			signal = 90;
+		else if (signal < 25)
+			signal = 25;
+		signal = 90 - signal;
+	} else {	/* CCK rate */
+		if (signal > 95)
+			signal = 95;
+		else if (signal < 30)
+			signal = 30;
+		signal = 95 - signal;
+	}
+
+	rx_status.antenna = (hdr->signal >> 7) & 1;
+	rx_status.signal = 64 - min(hdr->noise, (u8)64);
+	rx_status.ssi = signal;
+	rx_status.rate = rate;
+	rx_status.freq = dev->conf.freq;
+	rx_status.channel = dev->conf.channel;
+	rx_status.phymode = dev->conf.phymode;
+	rx_status.mactime = le64_to_cpu(hdr->mac_time);
+	ieee80211_rx_irqsafe(dev, skb, &rx_status);
+
+	skb = dev_alloc_skb(RTL8187_MAX_RX);
+	if (unlikely(!skb)) {
+		usb_free_urb(urb);
+		/* TODO check rx queue length and refill *somewhere* */
+		return;
+	}
+
+	info = (struct rtl8187_rx_info *)skb->cb;
+	info->urb = urb;
+	info->dev = dev;
+	urb->transfer_buffer = skb_tail_pointer(skb);
+	urb->context = skb;
+	skb_queue_tail(&priv->rx_queue, skb);
+
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int rtl8187_init_urbs(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	struct urb *entry;
+	struct sk_buff *skb;
+	struct rtl8187_rx_info *info;
+
+	while (skb_queue_len(&priv->rx_queue) < 8) {
+		skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
+		if (!skb)
+			break;
+		entry = usb_alloc_urb(0, GFP_KERNEL);
+		if (!entry) {
+			kfree_skb(skb);
+			break;
+		}
+		usb_fill_bulk_urb(entry, priv->udev,
+				  usb_rcvbulkpipe(priv->udev, 1),
+				  skb_tail_pointer(skb),
+				  RTL8187_MAX_RX, rtl8187_rx_cb, skb);
+		info = (struct rtl8187_rx_info *)skb->cb;
+		info->urb = entry;
+		info->dev = dev;
+		skb_queue_tail(&priv->rx_queue, skb);
+		usb_submit_urb(entry, GFP_KERNEL);
+	}
+
+	return 0;
+}
+
+static int rtl8187_init_hw(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u8 reg;
+	int i;
+
+	/* reset */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+	msleep(200);
+	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10);
+	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11);
+	rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00);
+	msleep(200);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CMD);
+	reg &= (1 << 1);
+	reg |= RTL818X_CMD_RESET;
+	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+	i = 10;
+	do {
+		msleep(2);
+		if (!(rtl818x_ioread8(priv, &priv->map->CMD) &
+		      RTL818X_CMD_RESET))
+			break;
+	} while (--i);
+
+	if (!i) {
+		printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy));
+		return -ETIMEDOUT;
+	}
+
+	/* reload registers from eeprom */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
+
+	i = 10;
+	do {
+		msleep(4);
+		if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) &
+		      RTL818X_EEPROM_CMD_CONFIG))
+			break;
+	} while (--i);
+
+	if (!i) {
+		printk(KERN_ERR "%s: eeprom reset timeout!\n",
+		       wiphy_name(dev->wiphy));
+		return -ETIMEDOUT;
+	}
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	/* setup card */
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 1);
+	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	for (i = 0; i < ETH_ALEN; i++)
+		rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]);
+
+	rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG1);
+	reg &= 0x3F;
+	reg |= 0x80;
+	rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
+	rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
+	rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+
+	// TODO: set RESP_RATE and BRSR properly
+	rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
+	rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+
+	/* host_usb_init */
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+	reg = rtl818x_ioread8(priv, (u8 *)0xFE53);
+	rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7));
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
+	rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20);
+	rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80);
+	msleep(100);
+
+	rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
+	rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
+	rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7);
+	msleep(100);
+
+	priv->rf_init(dev);
+
+	rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+	reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & 0xfffe;
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 0x1);
+	rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10);
+	rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80);
+	rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60);
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+
+	return 0;
+}
+
+static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
+{
+	u32 reg;
+	struct rtl8187_priv *priv = dev->priv;
+
+	reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+	/* Enable TX loopback on MAC level to avoid TX during channel
+	 * changes, as this has be seen to causes problems and the
+	 * card will stop work until next reset
+	 */
+	rtl818x_iowrite32(priv, &priv->map->TX_CONF,
+			  reg | RTL818X_TX_CONF_LOOPBACK_MAC);
+	msleep(10);
+	rtl8225_rf_set_channel(dev, channel);
+	msleep(10);
+	rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+}
+
+static int rtl8187_open(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u32 reg;
+	int ret;
+
+	ret = rtl8187_init_hw(dev);
+	if (ret)
+		return ret;
+
+	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
+
+	rtl8187_init_urbs(dev);
+
+	reg = RTL818X_RX_CONF_ONLYERLPKT |
+	      RTL818X_RX_CONF_RX_AUTORESETPHY |
+	      RTL818X_RX_CONF_BSSID |
+	      RTL818X_RX_CONF_MGMT |
+	      RTL818X_RX_CONF_CTRL |
+	      RTL818X_RX_CONF_DATA |
+	      (7 << 13 /* RX FIFO threshold NONE */) |
+	      (7 << 10 /* MAX RX DMA */) |
+	      RTL818X_RX_CONF_BROADCAST |
+	      RTL818X_RX_CONF_MULTICAST |
+	      RTL818X_RX_CONF_NICMAC;
+	if (priv->mode == IEEE80211_IF_TYPE_MNTR)
+		reg |= RTL818X_RX_CONF_MONITOR;
+
+	rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
+	reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
+	reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
+	rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
+
+	reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
+	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
+	reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
+	reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
+	rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
+
+	reg  = RTL818X_TX_CONF_CW_MIN |
+	       (7 << 21 /* MAX TX DMA */) |
+	       RTL818X_TX_CONF_NO_ICV;
+	rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CMD);
+	reg |= RTL818X_CMD_TX_ENABLE;
+	reg |= RTL818X_CMD_RX_ENABLE;
+	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+	return 0;
+}
+
+static int rtl8187_stop(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	struct rtl8187_rx_info *info;
+	struct sk_buff *skb;
+	u32 reg;
+
+	rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+	reg = rtl818x_ioread8(priv, &priv->map->CMD);
+	reg &= ~RTL818X_CMD_TX_ENABLE;
+	reg &= ~RTL818X_CMD_RX_ENABLE;
+	rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+	rtl8225_rf_stop(dev);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	while ((skb = skb_dequeue(&priv->rx_queue))) {
+		info = (struct rtl8187_rx_info *)skb->cb;
+		usb_kill_urb(info->urb);
+		kfree_skb(skb);
+	}
+	return 0;
+}
+
+static int rtl8187_add_interface(struct ieee80211_hw *dev,
+				 struct ieee80211_if_init_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	/* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */
+	if (priv->mode != IEEE80211_IF_TYPE_MGMT)
+		return -1;
+
+	switch (conf->type) {
+	case IEEE80211_IF_TYPE_STA:
+	case IEEE80211_IF_TYPE_MNTR:
+		priv->mode = conf->type;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	priv->hwaddr = conf->mac_addr;
+
+	return 0;
+}
+
+static void rtl8187_remove_interface(struct ieee80211_hw *dev,
+				     struct ieee80211_if_init_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	priv->mode = IEEE80211_IF_TYPE_MGMT;
+}
+
+static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	rtl8187_set_channel(dev, conf->channel);
+
+	rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+
+	if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+		rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+		rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+		rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
+		rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
+	} else {
+		rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+		rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+		rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
+		rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
+	rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
+	rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
+	rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
+	return 0;
+}
+
+static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
+				    struct ieee80211_if_conf *conf)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
+
+	if (is_valid_ether_addr(conf->bssid))
+		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
+	else
+		rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
+
+	return 0;
+}
+
+static const struct ieee80211_ops rtl8187_ops = {
+	.tx			= rtl8187_tx,
+	.open			= rtl8187_open,
+	.stop			= rtl8187_stop,
+	.add_interface		= rtl8187_add_interface,
+	.remove_interface	= rtl8187_remove_interface,
+	.config			= rtl8187_config,
+	.config_interface	= rtl8187_config_interface,
+};
+
+static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+{
+	struct ieee80211_hw *dev = eeprom->data;
+	struct rtl8187_priv *priv = dev->priv;
+	u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+
+	eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
+	eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
+	eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
+	eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
+}
+
+static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+{
+	struct ieee80211_hw *dev = eeprom->data;
+	struct rtl8187_priv *priv = dev->priv;
+	u8 reg = RTL818X_EEPROM_CMD_PROGRAM;
+
+	if (eeprom->reg_data_in)
+		reg |= RTL818X_EEPROM_CMD_WRITE;
+	if (eeprom->reg_data_out)
+		reg |= RTL818X_EEPROM_CMD_READ;
+	if (eeprom->reg_data_clock)
+		reg |= RTL818X_EEPROM_CMD_CK;
+	if (eeprom->reg_chip_select)
+		reg |= RTL818X_EEPROM_CMD_CS;
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
+	udelay(10);
+}
+
+static int __devinit rtl8187_probe(struct usb_interface *intf,
+				   const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct ieee80211_hw *dev;
+	struct rtl8187_priv *priv;
+	struct eeprom_93cx6 eeprom;
+	struct ieee80211_channel *channel;
+	u16 txpwr, reg;
+	int err, i;
+
+	dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
+	if (!dev) {
+		printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n");
+		return -ENOMEM;
+	}
+
+	priv = dev->priv;
+
+	SET_IEEE80211_DEV(dev, &intf->dev);
+	usb_set_intfdata(intf, dev);
+	priv->udev = udev;
+
+	usb_get_dev(udev);
+
+	skb_queue_head_init(&priv->rx_queue);
+	memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
+	memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
+	priv->map = (struct rtl818x_csr *)0xFF00;
+	priv->modes[0].mode = MODE_IEEE80211G;
+	priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
+	priv->modes[0].rates = priv->rates;
+	priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
+	priv->modes[0].channels = priv->channels;
+	priv->modes[1].mode = MODE_IEEE80211B;
+	priv->modes[1].num_rates = 4;
+	priv->modes[1].rates = priv->rates;
+	priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
+	priv->modes[1].channels = priv->channels;
+	priv->mode = IEEE80211_IF_TYPE_MGMT;
+	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+		     IEEE80211_HW_RX_INCLUDES_FCS |
+		     IEEE80211_HW_WEP_INCLUDE_IV |
+		     IEEE80211_HW_DATA_NULLFUNC_ACK;
+	dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
+	dev->queues = 1;
+	dev->max_rssi = 65;
+	dev->max_signal = 64;
+
+	for (i = 0; i < 2; i++)
+		if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
+			goto err_free_dev;
+
+	eeprom.data = dev;
+	eeprom.register_read = rtl8187_eeprom_register_read;
+	eeprom.register_write = rtl8187_eeprom_register_write;
+	if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
+		eeprom.width = PCI_EEPROM_WIDTH_93C66;
+	else
+		eeprom.width = PCI_EEPROM_WIDTH_93C46;
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	udelay(10);
+
+	eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR,
+			       (__le16 __force *)dev->wiphy->perm_addr, 3);
+	if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
+		printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly "
+		       "generated MAC address\n");
+		random_ether_addr(dev->wiphy->perm_addr);
+	}
+
+	channel = priv->channels;
+	for (i = 0; i < 3; i++) {
+		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
+				  &txpwr);
+		(*channel++).val = txpwr & 0xFF;
+		(*channel++).val = txpwr >> 8;
+	}
+	for (i = 0; i < 2; i++) {
+		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
+				  &txpwr);
+		(*channel++).val = txpwr & 0xFF;
+		(*channel++).val = txpwr >> 8;
+	}
+	for (i = 0; i < 2; i++) {
+		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
+				  &txpwr);
+		(*channel++).val = txpwr & 0xFF;
+		(*channel++).val = txpwr >> 8;
+	}
+
+	eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
+			  &priv->txpwr_base);
+
+	reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1;
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1);
+	/* 0 means asic B-cut, we should use SW 3 wire
+	 * bit-by-bit banging for radio. 1 means we can use
+	 * USB specific request to write radio registers */
+	priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3;
+	rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl8225_write(dev, 0, 0x1B7);
+
+	if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700)
+		priv->rf_init = rtl8225_rf_init;
+	else
+		priv->rf_init = rtl8225z2_rf_init;
+
+	rtl8225_write(dev, 0, 0x0B7);
+
+	err = ieee80211_register_hw(dev);
+	if (err) {
+		printk(KERN_ERR "rtl8187: Cannot register device\n");
+		goto err_free_dev;
+	}
+
+	printk(KERN_INFO "%s: hwaddr " MAC_FMT ", rtl8187 V%d + %s\n",
+	       wiphy_name(dev->wiphy), MAC_ARG(dev->wiphy->perm_addr),
+	       priv->asic_rev, priv->rf_init == rtl8225_rf_init ?
+	       "rtl8225" : "rtl8225z2");
+
+	return 0;
+
+ err_free_dev:
+	ieee80211_free_hw(dev);
+	usb_set_intfdata(intf, NULL);
+	usb_put_dev(udev);
+	return err;
+}
+
+static void __devexit rtl8187_disconnect(struct usb_interface *intf)
+{
+	struct ieee80211_hw *dev = usb_get_intfdata(intf);
+	struct rtl8187_priv *priv;
+
+	if (!dev)
+		return;
+
+	ieee80211_unregister_hw(dev);
+
+	priv = dev->priv;
+	usb_put_dev(interface_to_usbdev(intf));
+	ieee80211_free_hw(dev);
+}
+
+static struct usb_driver rtl8187_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= rtl8187_table,
+	.probe		= rtl8187_probe,
+	.disconnect	= rtl8187_disconnect,
+};
+
+static int __init rtl8187_init(void)
+{
+	return usb_register(&rtl8187_driver);
+}
+
+static void __exit rtl8187_exit(void)
+{
+	usb_deregister(&rtl8187_driver);
+}
+
+module_init(rtl8187_init);
+module_exit(rtl8187_exit);
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
new file mode 100644
index 0000000..e25a09f
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -0,0 +1,745 @@
+/*
+ * Radio tuning for RTL8225 on RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Magic delays, register offsets, and phy value tables below are
+ * taken from the original r8187 driver sources.  Thanks to Realtek
+ * for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u16 reg80, reg84, reg82;
+	u32 bangdata;
+	int i;
+
+	bangdata = (data << 4) | (addr & 0xf);
+
+	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
+	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
+
+	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(2);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+	udelay(10);
+
+	for (i = 15; i >= 0; i--) {
+		u16 reg = reg80 | (bangdata & (1 << i)) >> i;
+
+		if (i & 1)
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+
+		if (!(i & 1))
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+	msleep(2);
+}
+
+static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u16 reg80, reg82, reg84;
+
+	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+	reg80 &= ~(0x3 << 2);
+	reg84 &= ~0xF;
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(2);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+	udelay(10);
+
+	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+			addr, 0x8225, &data, sizeof(data), HZ / 2);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(10);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+	msleep(2);
+}
+
+void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	if (priv->asic_rev)
+		rtl8225_write_8051(dev, addr, data);
+	else
+		rtl8225_write_bitbang(dev, addr, data);
+}
+
+u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u16 reg80, reg82, reg84, out;
+	int i;
+
+	reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+	reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+	reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+	reg80 &= ~0xF;
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+	udelay(4);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+	udelay(5);
+
+	for (i = 4; i >= 0; i--) {
+		u16 reg = reg80 | ((addr >> i) & 1);
+
+		if (!(i & 1)) {
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+			udelay(1);
+		}
+
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg | (1 << 1));
+		udelay(2);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg | (1 << 1));
+		udelay(2);
+
+		if (i & 1) {
+			rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+			udelay(1);
+		}
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3) | (1 << 1));
+	udelay(2);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3));
+	udelay(2);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3));
+	udelay(2);
+
+	out = 0;
+	for (i = 11; i >= 0; i--) {
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3));
+		udelay(1);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3) | (1 << 1));
+		udelay(2);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3) | (1 << 1));
+		udelay(2);
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3) | (1 << 1));
+		udelay(2);
+
+		if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
+			out |= 1 << i;
+
+		rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+				  reg80 | (1 << 3));
+		udelay(2);
+	}
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+			  reg80 | (1 << 3) | (1 << 2));
+	udelay(2);
+
+	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
+
+	return out;
+}
+
+static const u16 rtl8225bcd_rxgain[] = {
+	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+	0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
+	0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
+};
+
+static const u8 rtl8225_agc[] = {
+	0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
+	0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
+	0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
+	0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
+	0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
+	0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
+	0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
+	0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
+	0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
+	0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
+	0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
+	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
+	0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+};
+
+static const u8 rtl8225_gain[] = {
+	0x23, 0x88, 0x7c, 0xa5,	/* -82dBm */
+	0x23, 0x88, 0x7c, 0xb5,	/* -82dBm */
+	0x23, 0x88, 0x7c, 0xc5,	/* -82dBm */
+	0x33, 0x80, 0x79, 0xc5,	/* -78dBm */
+	0x43, 0x78, 0x76, 0xc5,	/* -74dBm */
+	0x53, 0x60, 0x73, 0xc5,	/* -70dBm */
+	0x63, 0x58, 0x70, 0xc5,	/* -66dBm */
+};
+
+static const u8 rtl8225_threshold[] = {
+	0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
+};
+
+static const u8 rtl8225_tx_gain_cck_ofdm[] = {
+	0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
+};
+
+static const u8 rtl8225_tx_power_cck[] = {
+	0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
+	0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
+	0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
+	0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
+	0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
+	0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
+};
+
+static const u8 rtl8225_tx_power_cck_ch14[] = {
+	0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
+	0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
+	0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
+	0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
+	0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
+	0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225_tx_power_ofdm[] = {
+	0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
+};
+
+static const u32 rtl8225_chan[] = {
+	0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
+	0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
+};
+
+static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u8 cck_power, ofdm_power;
+	const u8 *tmp;
+	u32 reg;
+	int i;
+
+	cck_power = priv->channels[channel - 1].val & 0xF;
+	ofdm_power = priv->channels[channel - 1].val >> 4;
+
+	cck_power = min(cck_power, (u8)11);
+	ofdm_power = min(ofdm_power, (u8)35);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+			 rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
+
+	if (channel == 14)
+		tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
+	else
+		tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
+
+	for (i = 0; i < 8; i++)
+		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+	msleep(1); // FIXME: optional?
+
+	/* anaparam2 on */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl8225_write_phy_ofdm(dev, 2, 0x42);
+	rtl8225_write_phy_ofdm(dev, 6, 0x00);
+	rtl8225_write_phy_ofdm(dev, 8, 0x00);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+			 rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
+
+	tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
+
+	rtl8225_write_phy_ofdm(dev, 5, *tmp);
+	rtl8225_write_phy_ofdm(dev, 7, *tmp);
+
+	msleep(1);
+}
+
+void rtl8225_rf_init(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	int i;
+
+	rtl8225_write(dev, 0x0, 0x067); msleep(1);
+	rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
+	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
+	rtl8225_write(dev, 0x3, 0x441); msleep(1);
+	rtl8225_write(dev, 0x4, 0x486); msleep(1);
+	rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
+	rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
+	rtl8225_write(dev, 0x7, 0x82A); msleep(1);
+	rtl8225_write(dev, 0x8, 0x01F); msleep(1);
+	rtl8225_write(dev, 0x9, 0x334); msleep(1);
+	rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
+	rtl8225_write(dev, 0xB, 0x391); msleep(1);
+	rtl8225_write(dev, 0xC, 0x050); msleep(1);
+	rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
+	rtl8225_write(dev, 0xE, 0x029); msleep(1);
+	rtl8225_write(dev, 0xF, 0x914); msleep(100);
+
+	rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
+	rtl8225_write(dev, 0x2, 0x44D); msleep(200);
+
+	if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+		rtl8225_write(dev, 0x02, 0x0c4d);
+		msleep(200);
+		rtl8225_write(dev, 0x02, 0x044d);
+		msleep(100);
+		if (!(rtl8225_read(dev, 6) & (1 << 7)))
+			printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+			       wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+	}
+
+	rtl8225_write(dev, 0x0, 0x127);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
+		rtl8225_write(dev, 0x1, i + 1);
+		rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
+	}
+
+	rtl8225_write(dev, 0x0, 0x027);
+	rtl8225_write(dev, 0x0, 0x22F);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+		msleep(1);
+		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+		msleep(1);
+	}
+
+	msleep(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+	rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+
+	rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+	rtl8225_write_phy_cck(dev, 0x19, 0x00);
+	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+	rtl8225_write_phy_cck(dev, 0x40, 0x86);
+	rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+	rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
+
+	rtl8225_rf_set_tx_power(dev, 1);
+
+	/* RX antenna default to A */
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);	/* B: 0xDB */
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);	/* B: 0x10 */
+
+	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
+	msleep(1);
+	rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+
+	/* set sensitivity */
+	rtl8225_write(dev, 0x0c, 0x50);
+	rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+	rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+	rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
+}
+
+static const u8 rtl8225z2_tx_power_cck_ch14[] = {
+	0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225z2_tx_power_cck[] = {
+	0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
+};
+
+static const u8 rtl8225z2_tx_power_ofdm[] = {
+	0x42, 0x00, 0x40, 0x00, 0x40
+};
+
+static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+	0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+	0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+	0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
+};
+
+static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	u8 cck_power, ofdm_power;
+	const u8 *tmp;
+	u32 reg;
+	int i;
+
+	cck_power = priv->channels[channel - 1].val & 0xF;
+	ofdm_power = priv->channels[channel - 1].val >> 4;
+
+	cck_power = min(cck_power, (u8)15);
+	cck_power += priv->txpwr_base & 0xF;
+	cck_power = min(cck_power, (u8)35);
+
+	ofdm_power = min(ofdm_power, (u8)15);
+	ofdm_power += priv->txpwr_base >> 4;
+	ofdm_power = min(ofdm_power, (u8)35);
+
+	if (channel == 14)
+		tmp = rtl8225z2_tx_power_cck_ch14;
+	else
+		tmp = rtl8225z2_tx_power_cck;
+
+	for (i = 0; i < 8; i++)
+		rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+			 rtl8225z2_tx_gain_cck_ofdm[cck_power]);
+	msleep(1);
+
+	/* anaparam2 on */
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+	rtl8225_write_phy_ofdm(dev, 2, 0x42);
+	rtl8225_write_phy_ofdm(dev, 5, 0x00);
+	rtl8225_write_phy_ofdm(dev, 6, 0x40);
+	rtl8225_write_phy_ofdm(dev, 7, 0x00);
+	rtl8225_write_phy_ofdm(dev, 8, 0x40);
+
+	rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+			 rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
+	msleep(1);
+}
+
+static const u16 rtl8225z2_rxgain[] = {
+	0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+	0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+	0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+	0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+	0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+	0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+	0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+	0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+	0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+	0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+	0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
+	0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
+};
+
+static const u8 rtl8225z2_gain_bg[] = {
+	0x23, 0x15, 0xa5, /* -82-1dBm */
+	0x23, 0x15, 0xb5, /* -82-2dBm */
+	0x23, 0x15, 0xc5, /* -82-3dBm */
+	0x33, 0x15, 0xc5, /* -78dBm */
+	0x43, 0x15, 0xc5, /* -74dBm */
+	0x53, 0x15, 0xc5, /* -70dBm */
+	0x63, 0x15, 0xc5  /* -66dBm */
+};
+
+void rtl8225z2_rf_init(struct ieee80211_hw *dev)
+{
+	struct rtl8187_priv *priv = dev->priv;
+	int i;
+
+	rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
+	rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
+	rtl8225_write(dev, 0x2, 0x44D); msleep(1);
+	rtl8225_write(dev, 0x3, 0x441); msleep(1);
+	rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
+	rtl8225_write(dev, 0x5, 0xC72); msleep(1);
+	rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
+	rtl8225_write(dev, 0x7, 0x82A); msleep(1);
+	rtl8225_write(dev, 0x8, 0x03F); msleep(1);
+	rtl8225_write(dev, 0x9, 0x335); msleep(1);
+	rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
+	rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
+	rtl8225_write(dev, 0xc, 0x850); msleep(1);
+	rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
+	rtl8225_write(dev, 0xe, 0x02B); msleep(1);
+	rtl8225_write(dev, 0xf, 0x114); msleep(100);
+
+	rtl8225_write(dev, 0x0, 0x1B7);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
+		rtl8225_write(dev, 0x1, i + 1);
+		rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
+	}
+
+	rtl8225_write(dev, 0x3, 0x080);
+	rtl8225_write(dev, 0x5, 0x004);
+	rtl8225_write(dev, 0x0, 0x0B7);
+	rtl8225_write(dev, 0x2, 0xc4D);
+
+	msleep(200);
+	rtl8225_write(dev, 0x2, 0x44D);
+	msleep(100);
+
+	if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+		rtl8225_write(dev, 0x02, 0x0C4D);
+		msleep(200);
+		rtl8225_write(dev, 0x02, 0x044D);
+		msleep(100);
+		if (!(rtl8225_read(dev, 6) & (1 << 7)))
+			printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+			       wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+	}
+
+	msleep(200);
+
+	rtl8225_write(dev, 0x0, 0x2BF);
+
+	for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+		rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+		msleep(1);
+		rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+		msleep(1);
+	}
+
+	msleep(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
+	rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
+	rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+	rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+	rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
+	rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
+	rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
+	rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
+
+	rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+	rtl8225_write_phy_cck(dev, 0x19, 0x00);
+	rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+	rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+	rtl8225_write_phy_cck(dev, 0x40, 0x86);
+	rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
+	rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+	rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
+
+	rtl8225z2_rf_set_tx_power(dev, 1);
+
+	/* RX antenna default to A */
+	rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);	/* B: 0xDB */
+	rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);	/* B: 0x10 */
+
+	rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);	/* B: 0x00 */
+	msleep(1);
+	rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+}
+
+void rtl8225_rf_stop(struct ieee80211_hw *dev)
+{
+	u8 reg;
+	struct rtl8187_priv *priv = dev->priv;
+
+	rtl8225_write(dev, 0x4, 0x1f); msleep(1);
+
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+	reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
+	rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
+	rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+}
+
+void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
+{
+	struct rtl8187_priv *priv = dev->priv;
+
+	if (priv->rf_init == rtl8225_rf_init)
+		rtl8225_rf_set_tx_power(dev, channel);
+	else
+		rtl8225z2_rf_set_tx_power(dev, channel);
+
+	rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
+	msleep(10);
+}
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h
new file mode 100644
index 0000000..798ba4a
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.h
@@ -0,0 +1,44 @@
+/*
+ * Radio tuning definitions for RTL8225 on RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RTL8187_RTL8225_H
+#define RTL8187_RTL8225_H
+
+#define RTL8225_ANAPARAM_ON	0xa0000a59
+#define RTL8225_ANAPARAM2_ON	0x860c7312
+#define RTL8225_ANAPARAM_OFF	0xa00beb59
+#define RTL8225_ANAPARAM2_OFF	0x840dec11
+
+void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
+u16  rtl8225_read(struct ieee80211_hw *, u8 addr);
+
+void rtl8225_rf_init(struct ieee80211_hw *);
+void rtl8225z2_rf_init(struct ieee80211_hw *);
+void rtl8225_rf_stop(struct ieee80211_hw *);
+void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
+
+
+static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
+					  u8 addr, u32 data)
+{
+	rtl8187_write_phy(dev, addr, data);
+}
+
+static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
+					 u8 addr, u32 data)
+{
+	rtl8187_write_phy(dev, addr, data | 0x10000);
+}
+
+#endif /* RTL8187_RTL8225_H */
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
new file mode 100644
index 0000000..283de30
--- /dev/null
+++ b/drivers/net/wireless/rtl818x.h
@@ -0,0 +1,226 @@
+/*
+ * Definitions for RTL818x hardware
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RTL818X_H
+#define RTL818X_H
+
+struct rtl818x_csr {
+	u8	MAC[6];
+	u8	reserved_0[2];
+	__le32	MAR[2];
+	u8	RX_FIFO_COUNT;
+	u8	reserved_1;
+	u8	TX_FIFO_COUNT;
+	u8	BQREQ;
+	u8	reserved_2[4];
+	__le32	TSFT[2];
+	__le32	TLPDA;
+	__le32	TNPDA;
+	__le32	THPDA;
+	__le16	BRSR;
+	u8	BSSID[6];
+	u8	RESP_RATE;
+	u8	EIFS;
+	u8	reserved_3[1];
+	u8	CMD;
+#define RTL818X_CMD_TX_ENABLE		(1 << 2)
+#define RTL818X_CMD_RX_ENABLE		(1 << 3)
+#define RTL818X_CMD_RESET		(1 << 4)
+	u8	reserved_4[4];
+	__le16	INT_MASK;
+	__le16	INT_STATUS;
+#define RTL818X_INT_RX_OK		(1 <<  0)
+#define RTL818X_INT_RX_ERR		(1 <<  1)
+#define RTL818X_INT_TXL_OK		(1 <<  2)
+#define RTL818X_INT_TXL_ERR		(1 <<  3)
+#define RTL818X_INT_RX_DU		(1 <<  4)
+#define RTL818X_INT_RX_FO		(1 <<  5)
+#define RTL818X_INT_TXN_OK		(1 <<  6)
+#define RTL818X_INT_TXN_ERR		(1 <<  7)
+#define RTL818X_INT_TXH_OK		(1 <<  8)
+#define RTL818X_INT_TXH_ERR		(1 <<  9)
+#define RTL818X_INT_TXB_OK		(1 << 10)
+#define RTL818X_INT_TXB_ERR		(1 << 11)
+#define RTL818X_INT_ATIM		(1 << 12)
+#define RTL818X_INT_BEACON		(1 << 13)
+#define RTL818X_INT_TIME_OUT		(1 << 14)
+#define RTL818X_INT_TX_FO		(1 << 15)
+	__le32	TX_CONF;
+#define RTL818X_TX_CONF_LOOPBACK_MAC	(1 << 17)
+#define RTL818X_TX_CONF_NO_ICV		(1 << 19)
+#define RTL818X_TX_CONF_DISCW		(1 << 20)
+#define RTL818X_TX_CONF_R8180_ABCD	(2 << 25)
+#define RTL818X_TX_CONF_R8180_F		(3 << 25)
+#define RTL818X_TX_CONF_R8185_ABC	(4 << 25)
+#define RTL818X_TX_CONF_R8185_D		(5 << 25)
+#define RTL818X_TX_CONF_HWVER_MASK	(7 << 25)
+#define RTL818X_TX_CONF_CW_MIN		(1 << 31)
+	__le32	RX_CONF;
+#define RTL818X_RX_CONF_MONITOR		(1 <<  0)
+#define RTL818X_RX_CONF_NICMAC		(1 <<  1)
+#define RTL818X_RX_CONF_MULTICAST	(1 <<  2)
+#define RTL818X_RX_CONF_BROADCAST	(1 <<  3)
+#define RTL818X_RX_CONF_DATA		(1 << 18)
+#define RTL818X_RX_CONF_CTRL		(1 << 19)
+#define RTL818X_RX_CONF_MGMT		(1 << 20)
+#define RTL818X_RX_CONF_BSSID		(1 << 23)
+#define RTL818X_RX_CONF_RX_AUTORESETPHY	(1 << 28)
+#define RTL818X_RX_CONF_ONLYERLPKT	(1 << 31)
+	__le32	INT_TIMEOUT;
+	__le32	TBDA;
+	u8	EEPROM_CMD;
+#define RTL818X_EEPROM_CMD_READ		(1 << 0)
+#define RTL818X_EEPROM_CMD_WRITE	(1 << 1)
+#define RTL818X_EEPROM_CMD_CK		(1 << 2)
+#define RTL818X_EEPROM_CMD_CS		(1 << 3)
+#define RTL818X_EEPROM_CMD_NORMAL	(0 << 6)
+#define RTL818X_EEPROM_CMD_LOAD		(1 << 6)
+#define RTL818X_EEPROM_CMD_PROGRAM	(2 << 6)
+#define RTL818X_EEPROM_CMD_CONFIG	(3 << 6)
+	u8	CONFIG0;
+	u8	CONFIG1;
+	u8	CONFIG2;
+	__le32	ANAPARAM;
+	u8	MSR;
+#define RTL818X_MSR_NO_LINK		(0 << 2)
+#define RTL818X_MSR_ADHOC		(1 << 2)
+#define RTL818X_MSR_INFRA		(2 << 2)
+	u8	CONFIG3;
+#define RTL818X_CONFIG3_ANAPARAM_WRITE	(1 << 6)
+	u8	CONFIG4;
+#define RTL818X_CONFIG4_POWEROFF	(1 << 6)
+#define RTL818X_CONFIG4_VCOOFF		(1 << 7)
+	u8	TESTR;
+	u8	reserved_9[2];
+	__le16	PGSELECT;
+	__le32	ANAPARAM2;
+	u8	reserved_10[12];
+	__le16	BEACON_INTERVAL;
+	__le16	ATIM_WND;
+	__le16	BEACON_INTERVAL_TIME;
+	__le16	ATIMTR_INTERVAL;
+	u8	reserved_11[4];
+	u8	PHY[4];
+	__le16	RFPinsOutput;
+	__le16	RFPinsEnable;
+	__le16	RFPinsSelect;
+	__le16	RFPinsInput;
+	__le32	RF_PARA;
+	__le32	RF_TIMING;
+	u8	GP_ENABLE;
+	u8	GPIO;
+	u8	reserved_12[10];
+	u8	TX_AGC_CTL;
+#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT		(1 << 0)
+#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT	(1 << 1)
+#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT			(1 << 2)
+	u8	TX_GAIN_CCK;
+	u8	TX_GAIN_OFDM;
+	u8	TX_ANTENNA;
+	u8	reserved_13[16];
+	u8	WPA_CONF;
+	u8	reserved_14[3];
+	u8	SIFS;
+	u8	DIFS;
+	u8	SLOT;
+	u8	reserved_15[5];
+	u8	CW_CONF;
+#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT	(1 << 0)
+#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT	(1 << 1)
+	u8	CW_VAL;
+	u8	RATE_FALLBACK;
+	u8	reserved_16[25];
+	u8	CONFIG5;
+	u8	TX_DMA_POLLING;
+	u8	reserved_17[2];
+	__le16	CWR;
+	u8	RETRY_CTR;
+	u8	reserved_18[5];
+	__le32	RDSAR;
+	u8	reserved_19[18];
+	u16	TALLY_CNT;
+	u8	TALLY_SEL;
+} __attribute__((packed));
+
+static const struct ieee80211_rate rtl818x_rates[] = {
+	{ .rate = 10,
+	  .val = 0,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 20,
+	  .val = 1,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 55,
+	  .val = 2,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 110,
+	  .val = 3,
+	  .flags = IEEE80211_RATE_CCK },
+	{ .rate = 60,
+	  .val = 4,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 90,
+	  .val = 5,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 120,
+	  .val = 6,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 180,
+	  .val = 7,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 240,
+	  .val = 8,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 360,
+	  .val = 9,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 480,
+	  .val = 10,
+	  .flags = IEEE80211_RATE_OFDM },
+	{ .rate = 540,
+	  .val = 11,
+	  .flags = IEEE80211_RATE_OFDM },
+};
+
+static const struct ieee80211_channel rtl818x_channels[] = {
+	{ .chan = 1,
+	  .freq = 2412},
+	{ .chan = 2,
+	  .freq = 2417},
+	{ .chan = 3,
+	  .freq = 2422},
+	{ .chan = 4,
+	  .freq = 2427},
+	{ .chan = 5,
+	  .freq = 2432},
+	{ .chan = 6,
+	  .freq = 2437},
+	{ .chan = 7,
+	  .freq = 2442},
+	{ .chan = 8,
+	  .freq = 2447},
+	{ .chan = 9,
+	  .freq = 2452},
+	{ .chan = 10,
+	  .freq = 2457},
+	{ .chan = 11,
+	  .freq = 2462},
+	{ .chan = 12,
+	  .freq = 2467},
+	{ .chan = 13,
+	  .freq = 2472},
+	{ .chan = 14,
+	  .freq = 2484}
+};
+
+#endif /* RTL818X_H */
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index ce9230b..c8b5c22 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1011,7 +1011,7 @@
 	} else {
 		skb->dev = dev;
 		skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */
-		eth_copy_and_sum(skb, (unsigned char *)&sig.daddr, 12, 0);
+		skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12);
 		wl3501_receive(this, skb->data, pkt_len);
 		skb_put(skb, pkt_len);
 		skb->protocol	= eth_type_trans(skb, dev);
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index 6603ad5..4d50590 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -3,7 +3,7 @@
 zd1211rw-objs := zd_chip.o zd_ieee80211.o \
 		zd_mac.o zd_netdev.o \
 		zd_rf_al2230.o zd_rf_rf2959.o \
-		zd_rf_al7230b.o \
+		zd_rf_al7230b.o zd_rf_uw2453.o \
 		zd_rf.o zd_usb.o zd_util.o
 
 ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 95b4a2a..5b624bf 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1253,6 +1253,9 @@
 {
 	int r;
 
+	if (!zd_rf_should_update_pwr_int(&chip->rf))
+		return 0;
+
 	r = update_pwr_int(chip, channel);
 	if (r)
 		return r;
@@ -1283,7 +1286,7 @@
 	int r;
 	u32 value;
 
-	if (!chip->patch_cck_gain)
+	if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf))
 		return 0;
 
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ce0a5f6..79d0288 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -608,6 +608,9 @@
 #define CR_ZD1211B_TXOP			CTL_REG(0x0b20)
 #define CR_ZD1211B_RETRY_MAX		CTL_REG(0x0b28)
 
+/* Used to detect PLL lock */
+#define UW2453_INTR_REG			((zd_addr_t)0x85c1)
+
 #define CWIN_SIZE			0x007f043f
 
 
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index 549c23b..7407409 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -52,34 +52,38 @@
 void zd_rf_init(struct zd_rf *rf)
 {
 	memset(rf, 0, sizeof(*rf));
+
+	/* default to update channel integration, as almost all RF's do want
+	 * this */
+	rf->update_channel_int = 1;
 }
 
 void zd_rf_clear(struct zd_rf *rf)
 {
+	if (rf->clear)
+		rf->clear(rf);
 	ZD_MEMCLEAR(rf, sizeof(*rf));
 }
 
 int zd_rf_init_hw(struct zd_rf *rf, u8 type)
 {
-	int r, t;
+	int r = 0;
+	int t;
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
 	switch (type) {
 	case RF2959_RF:
 		r = zd_rf_init_rf2959(rf);
-		if (r)
-			return r;
 		break;
 	case AL2230_RF:
 		r = zd_rf_init_al2230(rf);
-		if (r)
-			return r;
 		break;
 	case AL7230B_RF:
 		r = zd_rf_init_al7230b(rf);
-		if (r)
-			return r;
+		break;
+	case UW2453_RF:
+		r = zd_rf_init_uw2453(rf);
 		break;
 	default:
 		dev_err(zd_chip_dev(chip),
@@ -88,6 +92,9 @@
 		return -ENODEV;
 	}
 
+	if (r)
+		return r;
+
 	rf->type = type;
 
 	r = zd_chip_lock_phy_regs(chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index aa9cc10..c6dfd82 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -48,12 +48,26 @@
 
 	u8 channel;
 
+	/* whether channel integration and calibration should be updated
+	 * defaults to 1 (yes) */
+	u8 update_channel_int:1;
+
+	/* whether CR47 should be patched from the EEPROM, if the appropriate
+	 * flag is set in the POD. The vendor driver suggests that this should
+	 * be done for all RF's, but a bug in their code prevents but their
+	 * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */
+	u8 patch_cck_gain:1;
+
+	/* private RF driver data */
+	void *priv;
+
 	/* RF-specific functions */
 	int (*init_hw)(struct zd_rf *rf);
 	int (*set_channel)(struct zd_rf *rf, u8 channel);
 	int (*switch_radio_on)(struct zd_rf *rf);
 	int (*switch_radio_off)(struct zd_rf *rf);
 	int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel);
+	void (*clear)(struct zd_rf *rf);
 };
 
 const char *zd_rf_name(u8 type);
@@ -71,10 +85,24 @@
 int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
 int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
 
+static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf)
+{
+	return rf->update_channel_int;
+}
+
+static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf)
+{
+	return rf->patch_cck_gain;
+}
+
+int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
+int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
+
 /* Functions for individual RF chips */
 
 int zd_rf_init_rf2959(struct zd_rf *rf);
 int zd_rf_init_al2230(struct zd_rf *rf);
 int zd_rf_init_al7230b(struct zd_rf *rf);
+int zd_rf_init_uw2453(struct zd_rf *rf);
 
 #endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 511392a..e7a4ecf 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -432,5 +432,6 @@
 		rf->switch_radio_on = zd1211_al2230_switch_radio_on;
 	}
 	rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+	rf->patch_cck_gain = 1;
 	return 0;
 }
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
index 5e5e9dd..f4e8b6a 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -483,6 +483,7 @@
 		rf->switch_radio_on = zd1211_al7230b_switch_radio_on;
 		rf->set_channel = zd1211_al7230b_set_channel;
 		rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+		rf->patch_cck_gain = 1;
 	}
 
 	rf->switch_radio_off = al7230b_switch_radio_off;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
new file mode 100644
index 0000000..414e40d
--- /dev/null
+++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
@@ -0,0 +1,534 @@
+/* zd_rf_uw2453.c: Functions for the UW2453 RF controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+/* This RF programming code is based upon the code found in v2.16.0.0 of the
+ * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs
+ * for this RF on their website, so we're able to understand more than
+ * usual as to what is going on. Thumbs up for Ubec for doing that. */
+
+/* The 3-wire serial interface provides access to 8 write-only registers.
+ * The data format is a 4 bit register address followed by a 20 bit value. */
+#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff))
+
+/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth
+ * fractional divide ratio) and 3 (VCO config).
+ *
+ * We configure the RF to produce an interrupt when the PLL is locked onto
+ * the configured frequency. During initialization, we run through a variety
+ * of different VCO configurations on channel 1 until we detect a PLL lock.
+ * When this happens, we remember which VCO configuration produced the lock
+ * and use it later. Actually, we use the configuration *after* the one that
+ * produced the lock, which seems odd, but it works.
+ *
+ * If we do not see a PLL lock on any standard VCO config, we fall back on an
+ * autocal configuration, which has a fixed (as opposed to per-channel) VCO
+ * config and different synth values from the standard set (divide ratio
+ * is still shared with the standard set). */
+
+/* The per-channel synth values for all standard VCO configurations. These get
+ * written to register 1. */
+static const u8 uw2453_std_synth[] = {
+	RF_CHANNEL( 1) = 0x47,
+	RF_CHANNEL( 2) = 0x47,
+	RF_CHANNEL( 3) = 0x67,
+	RF_CHANNEL( 4) = 0x67,
+	RF_CHANNEL( 5) = 0x67,
+	RF_CHANNEL( 6) = 0x67,
+	RF_CHANNEL( 7) = 0x57,
+	RF_CHANNEL( 8) = 0x57,
+	RF_CHANNEL( 9) = 0x57,
+	RF_CHANNEL(10) = 0x57,
+	RF_CHANNEL(11) = 0x77,
+	RF_CHANNEL(12) = 0x77,
+	RF_CHANNEL(13) = 0x77,
+	RF_CHANNEL(14) = 0x4f,
+};
+
+/* This table stores the synthesizer fractional divide ratio for *all* VCO
+ * configurations (both standard and autocal). These get written to register 2.
+ */
+static const u16 uw2453_synth_divide[] = {
+	RF_CHANNEL( 1) = 0x999,
+	RF_CHANNEL( 2) = 0x99b,
+	RF_CHANNEL( 3) = 0x998,
+	RF_CHANNEL( 4) = 0x99a,
+	RF_CHANNEL( 5) = 0x999,
+	RF_CHANNEL( 6) = 0x99b,
+	RF_CHANNEL( 7) = 0x998,
+	RF_CHANNEL( 8) = 0x99a,
+	RF_CHANNEL( 9) = 0x999,
+	RF_CHANNEL(10) = 0x99b,
+	RF_CHANNEL(11) = 0x998,
+	RF_CHANNEL(12) = 0x99a,
+	RF_CHANNEL(13) = 0x999,
+	RF_CHANNEL(14) = 0xccc,
+};
+
+/* Here is the data for all the standard VCO configurations. We shrink our
+ * table a little by observing that both channels in a consecutive pair share
+ * the same value. We also observe that the high 4 bits ([0:3] in the specs)
+ * are all 'Reserved' and are always set to 0x4 - we chop them off in the data
+ * below. */
+#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2)
+#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)]
+static const u16 uw2453_std_vco_cfg[][7] = {
+	{ /* table 1 */
+		RF_CHANPAIR( 1,  2) = 0x664d,
+		RF_CHANPAIR( 3,  4) = 0x604d,
+		RF_CHANPAIR( 5,  6) = 0x6675,
+		RF_CHANPAIR( 7,  8) = 0x6475,
+		RF_CHANPAIR( 9, 10) = 0x6655,
+		RF_CHANPAIR(11, 12) = 0x6455,
+		RF_CHANPAIR(13, 14) = 0x6665,
+	},
+	{ /* table 2 */
+		RF_CHANPAIR( 1,  2) = 0x666d,
+		RF_CHANPAIR( 3,  4) = 0x606d,
+		RF_CHANPAIR( 5,  6) = 0x664d,
+		RF_CHANPAIR( 7,  8) = 0x644d,
+		RF_CHANPAIR( 9, 10) = 0x6675,
+		RF_CHANPAIR(11, 12) = 0x6475,
+		RF_CHANPAIR(13, 14) = 0x6655,
+	},
+	{ /* table 3 */
+		RF_CHANPAIR( 1,  2) = 0x665d,
+		RF_CHANPAIR( 3,  4) = 0x605d,
+		RF_CHANPAIR( 5,  6) = 0x666d,
+		RF_CHANPAIR( 7,  8) = 0x646d,
+		RF_CHANPAIR( 9, 10) = 0x664d,
+		RF_CHANPAIR(11, 12) = 0x644d,
+		RF_CHANPAIR(13, 14) = 0x6675,
+	},
+	{ /* table 4 */
+		RF_CHANPAIR( 1,  2) = 0x667d,
+		RF_CHANPAIR( 3,  4) = 0x607d,
+		RF_CHANPAIR( 5,  6) = 0x665d,
+		RF_CHANPAIR( 7,  8) = 0x645d,
+		RF_CHANPAIR( 9, 10) = 0x666d,
+		RF_CHANPAIR(11, 12) = 0x646d,
+		RF_CHANPAIR(13, 14) = 0x664d,
+	},
+	{ /* table 5 */
+		RF_CHANPAIR( 1,  2) = 0x6643,
+		RF_CHANPAIR( 3,  4) = 0x6043,
+		RF_CHANPAIR( 5,  6) = 0x667d,
+		RF_CHANPAIR( 7,  8) = 0x647d,
+		RF_CHANPAIR( 9, 10) = 0x665d,
+		RF_CHANPAIR(11, 12) = 0x645d,
+		RF_CHANPAIR(13, 14) = 0x666d,
+	},
+	{ /* table 6 */
+		RF_CHANPAIR( 1,  2) = 0x6663,
+		RF_CHANPAIR( 3,  4) = 0x6063,
+		RF_CHANPAIR( 5,  6) = 0x6643,
+		RF_CHANPAIR( 7,  8) = 0x6443,
+		RF_CHANPAIR( 9, 10) = 0x667d,
+		RF_CHANPAIR(11, 12) = 0x647d,
+		RF_CHANPAIR(13, 14) = 0x665d,
+	},
+	{ /* table 7 */
+		RF_CHANPAIR( 1,  2) = 0x6653,
+		RF_CHANPAIR( 3,  4) = 0x6053,
+		RF_CHANPAIR( 5,  6) = 0x6663,
+		RF_CHANPAIR( 7,  8) = 0x6463,
+		RF_CHANPAIR( 9, 10) = 0x6643,
+		RF_CHANPAIR(11, 12) = 0x6443,
+		RF_CHANPAIR(13, 14) = 0x667d,
+	},
+	{ /* table 8 */
+		RF_CHANPAIR( 1,  2) = 0x6673,
+		RF_CHANPAIR( 3,  4) = 0x6073,
+		RF_CHANPAIR( 5,  6) = 0x6653,
+		RF_CHANPAIR( 7,  8) = 0x6453,
+		RF_CHANPAIR( 9, 10) = 0x6663,
+		RF_CHANPAIR(11, 12) = 0x6463,
+		RF_CHANPAIR(13, 14) = 0x6643,
+	},
+	{ /* table 9 */
+		RF_CHANPAIR( 1,  2) = 0x664b,
+		RF_CHANPAIR( 3,  4) = 0x604b,
+		RF_CHANPAIR( 5,  6) = 0x6673,
+		RF_CHANPAIR( 7,  8) = 0x6473,
+		RF_CHANPAIR( 9, 10) = 0x6653,
+		RF_CHANPAIR(11, 12) = 0x6453,
+		RF_CHANPAIR(13, 14) = 0x6663,
+	},
+	{ /* table 10 */
+		RF_CHANPAIR( 1,  2) = 0x666b,
+		RF_CHANPAIR( 3,  4) = 0x606b,
+		RF_CHANPAIR( 5,  6) = 0x664b,
+		RF_CHANPAIR( 7,  8) = 0x644b,
+		RF_CHANPAIR( 9, 10) = 0x6673,
+		RF_CHANPAIR(11, 12) = 0x6473,
+		RF_CHANPAIR(13, 14) = 0x6653,
+	},
+	{ /* table 11 */
+		RF_CHANPAIR( 1,  2) = 0x665b,
+		RF_CHANPAIR( 3,  4) = 0x605b,
+		RF_CHANPAIR( 5,  6) = 0x666b,
+		RF_CHANPAIR( 7,  8) = 0x646b,
+		RF_CHANPAIR( 9, 10) = 0x664b,
+		RF_CHANPAIR(11, 12) = 0x644b,
+		RF_CHANPAIR(13, 14) = 0x6673,
+	},
+
+};
+
+/* The per-channel synth values for autocal. These get written to register 1. */
+static const u16 uw2453_autocal_synth[] = {
+	RF_CHANNEL( 1) = 0x6847,
+	RF_CHANNEL( 2) = 0x6847,
+	RF_CHANNEL( 3) = 0x6867,
+	RF_CHANNEL( 4) = 0x6867,
+	RF_CHANNEL( 5) = 0x6867,
+	RF_CHANNEL( 6) = 0x6867,
+	RF_CHANNEL( 7) = 0x6857,
+	RF_CHANNEL( 8) = 0x6857,
+	RF_CHANNEL( 9) = 0x6857,
+	RF_CHANNEL(10) = 0x6857,
+	RF_CHANNEL(11) = 0x6877,
+	RF_CHANNEL(12) = 0x6877,
+	RF_CHANNEL(13) = 0x6877,
+	RF_CHANNEL(14) = 0x684f,
+};
+
+/* The VCO configuration for autocal (all channels) */
+static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662;
+
+/* TX gain settings. The array index corresponds to the TX power integration
+ * values found in the EEPROM. The values get written to register 7. */
+static u32 uw2453_txgain[] = {
+	[0x00] = 0x0e313,
+	[0x01] = 0x0fb13,
+	[0x02] = 0x0e093,
+	[0x03] = 0x0f893,
+	[0x04] = 0x0ea93,
+	[0x05] = 0x1f093,
+	[0x06] = 0x1f493,
+	[0x07] = 0x1f693,
+	[0x08] = 0x1f393,
+	[0x09] = 0x1f35b,
+	[0x0a] = 0x1e6db,
+	[0x0b] = 0x1ff3f,
+	[0x0c] = 0x1ffff,
+	[0x0d] = 0x361d7,
+	[0x0e] = 0x37fbf,
+	[0x0f] = 0x3ff8b,
+	[0x10] = 0x3ff33,
+	[0x11] = 0x3fb3f,
+	[0x12] = 0x3ffff,
+};
+
+/* RF-specific structure */
+struct uw2453_priv {
+	/* index into synth/VCO config tables where PLL lock was found
+	 * -1 means autocal */
+	int config;
+};
+
+#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv)
+
+static int uw2453_synth_set_channel(struct zd_chip *chip, int channel,
+	bool autocal)
+{
+	int r;
+	int idx = channel - 1;
+	u32 val;
+
+	if (autocal)
+		val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]);
+	else
+		val = UW2453_REGWRITE(1, uw2453_std_synth[idx]);
+
+	r = zd_rfwrite_locked(chip, val, RF_RV_BITS);
+	if (r)
+		return r;
+
+	return zd_rfwrite_locked(chip,
+		UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS);
+}
+
+static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value)
+{
+	/* vendor driver always sets these upper bits even though the specs say
+	 * they are reserved */
+	u32 val = 0x40000 | value;
+	return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS);
+}
+
+static int uw2453_init_mode(struct zd_chip *chip)
+{
+	static const u32 rv[] = {
+		UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */
+		UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */
+		UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */
+		UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */
+	};
+
+	return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+}
+
+static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel)
+{
+	u8 int_value = chip->pwr_int_values[channel - 1];
+
+	if (int_value >= ARRAY_SIZE(uw2453_txgain)) {
+		dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for "
+			  "int value %x on channel %d\n", int_value, channel);
+		return 0;
+	}
+
+	return zd_rfwrite_locked(chip,
+		UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS);
+}
+
+static int uw2453_init_hw(struct zd_rf *rf)
+{
+	int i, r;
+	int found_config = -1;
+	u16 intr_status;
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR10,  0x89 }, { CR15,  0x20 },
+		{ CR17,  0x28 }, /* 6112 no change */
+		{ CR23,  0x38 }, { CR24,  0x20 }, { CR26,  0x93 },
+		{ CR27,  0x15 }, { CR28,  0x3e }, { CR29,  0x00 },
+		{ CR33,  0x28 }, { CR34,  0x30 },
+		{ CR35,  0x43 }, /* 6112 3e->43 */
+		{ CR41,  0x24 }, { CR44,  0x32 },
+		{ CR46,  0x92 }, /* 6112 96->92 */
+		{ CR47,  0x1e },
+		{ CR48,  0x04 }, /* 5602 Roger */
+		{ CR49,  0xfa }, { CR79,  0x58 }, { CR80,  0x30 },
+		{ CR81,  0x30 }, { CR87,  0x0a }, { CR89,  0x04 },
+		{ CR91,  0x00 }, { CR92,  0x0a }, { CR98,  0x8d },
+		{ CR99,  0x28 }, { CR100, 0x02 },
+		{ CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */
+		{ CR102, 0x27 },
+		{ CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */
+		{ CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */
+		{ CR109, 0x13 },
+		{ CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */
+		{ CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 },
+		{ CR114, 0x23 }, /* 6221 27->23 */
+		{ CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */
+		{ CR116, 0x24 }, /* 6220 1c->24 */
+		{ CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */
+		{ CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */
+		{ CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */
+		{ CR120, 0x4f },
+		{ CR121, 0x1f }, /* 6220 4f->1f */
+		{ CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad },
+		{ CR126, 0x6c }, { CR127, 0x03 },
+		{ CR128, 0x14 }, /* 6302 12->11 */
+		{ CR129, 0x12 }, /* 6301 10->0f */
+		{ CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 },
+		{ CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff },
+		{ CR253, 0xff },
+	};
+
+	static const u32 rv[] = {
+		UW2453_REGWRITE(4, 0x2b),    /* configure reciever gain */
+		UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
+		UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
+		UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
+
+		/* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins,
+		 * RSSI circuit powered down, reduced RSSI range */
+		UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */
+
+		/* synthesizer configuration for channel 1 */
+		UW2453_REGWRITE(1, 0x47),
+		UW2453_REGWRITE(2, 0x999),
+
+		/* disable manual VCO band selection */
+		UW2453_REGWRITE(3, 0x7602),
+
+		/* enable manual VCO band selection, configure current level */
+		UW2453_REGWRITE(3, 0x46063),
+	};
+
+	r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+	if (r)
+		return r;
+
+	r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+	if (r)
+		return r;
+
+	r = uw2453_init_mode(chip);
+	if (r)
+		return r;
+
+	/* Try all standard VCO configuration settings on channel 1 */
+	for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) {
+		/* Configure synthesizer for channel 1 */
+		r = uw2453_synth_set_channel(chip, 1, false);
+		if (r)
+			return r;
+
+		/* Write VCO config */
+		r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]);
+		if (r)
+			return r;
+
+		/* ack interrupt event */
+		r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG);
+		if (r)
+			return r;
+
+		/* check interrupt status */
+		r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG);
+		if (r)
+			return r;
+
+		if (!intr_status & 0xf) {
+			dev_dbg_f(zd_chip_dev(chip),
+				"PLL locked on configuration %d\n", i);
+			found_config = i;
+			break;
+		}
+	}
+
+	if (found_config == -1) {
+		/* autocal */
+		dev_dbg_f(zd_chip_dev(chip),
+			"PLL did not lock, using autocal\n");
+
+		r = uw2453_synth_set_channel(chip, 1, true);
+		if (r)
+			return r;
+
+		r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG);
+		if (r)
+			return r;
+	}
+
+	/* To match the vendor driver behaviour, we use the configuration after
+	 * the one that produced a lock. */
+	UW2453_PRIV(rf)->config = found_config + 1;
+
+	return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_set_channel(struct zd_rf *rf, u8 channel)
+{
+	int r;
+	u16 vco_cfg;
+	int config = UW2453_PRIV(rf)->config;
+	bool autocal = (config == -1);
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR80,  0x30 }, { CR81,  0x30 }, { CR79,  0x58 },
+		{ CR12,  0xf0 }, { CR77,  0x1b }, { CR78,  0x58 },
+	};
+
+	r = uw2453_synth_set_channel(chip, channel, autocal);
+	if (r)
+		return r;
+
+	if (autocal)
+		vco_cfg = UW2453_AUTOCAL_VCO_CFG;
+	else
+		vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)];
+
+	r = uw2453_write_vco_cfg(chip, vco_cfg);
+	if (r)
+		return r;
+
+	r = uw2453_init_mode(chip);
+	if (r)
+		return r;
+
+	r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+	if (r)
+		return r;
+
+	r = uw2453_set_tx_gain_level(chip, channel);
+	if (r)
+		return r;
+
+	return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_switch_radio_on(struct zd_rf *rf)
+{
+	int r;
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+	struct zd_ioreq16 ioreqs[] = {
+		{ CR11,  0x00 }, { CR251, 0x3f },
+	};
+
+	/* enter RXTX mode */
+	r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS);
+	if (r)
+		return r;
+
+	if (chip->is_zd1211b)
+		ioreqs[1].value = 0x7f;
+
+	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int uw2453_switch_radio_off(struct zd_rf *rf)
+{
+	int r;
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR11,  0x04 }, { CR251, 0x2f },
+	};
+
+	/* enter IDLE mode */
+	/* FIXME: shouldn't we go to SLEEP? sent email to zydas */
+	r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS);
+	if (r)
+		return r;
+
+	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static void uw2453_clear(struct zd_rf *rf)
+{
+	kfree(rf->priv);
+}
+
+int zd_rf_init_uw2453(struct zd_rf *rf)
+{
+	rf->init_hw = uw2453_init_hw;
+	rf->set_channel = uw2453_set_channel;
+	rf->switch_radio_on = uw2453_switch_radio_on;
+	rf->switch_radio_off = uw2453_switch_radio_off;
+	rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+	rf->clear = uw2453_clear;
+	/* we have our own TX integration code */
+	rf->update_channel_int = 0;
+
+	rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL);
+	if (rf->priv == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 8459549..740a219 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -54,6 +54,7 @@
 	{ USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
 	/* ZD1211B */
 	{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index f2a90a7..870c539 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -1137,7 +1137,7 @@
 				if (skb == NULL)
 					break;
 				skb_reserve(skb, 2);	/* 16 byte align the IP header */
-				eth_copy_and_sum(skb, rx_skb->data, pkt_len, 0);
+				skb_copy_to_linear_data(skb, rx_skb->data, pkt_len);
 				skb_put(skb, pkt_len);
 				pci_dma_sync_single_for_device(yp->pci_dev, desc->addr,
 											   yp->rx_buf_sz,
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
new file mode 100644
index 0000000..ab9c3e5
--- /dev/null
+++ b/drivers/power/Kconfig
@@ -0,0 +1,51 @@
+menuconfig POWER_SUPPLY
+	tristate "Power supply class support"
+	help
+	  Say Y here to enable power supply class support. This allows
+	  power supply (batteries, AC, USB) monitoring by userspace
+	  via sysfs and uevent (if available) and/or APM kernel interface
+	  (if selected below).
+
+if POWER_SUPPLY
+
+config POWER_SUPPLY_DEBUG
+	bool "Power supply debug"
+	help
+	  Say Y here to enable debugging messages for power supply class
+	  and drivers.
+
+config PDA_POWER
+	tristate "Generic PDA/phone power driver"
+	help
+	  Say Y here to enable generic power driver for PDAs and phones with
+	  one or two external power supplies (AC/USB) connected to main and
+	  backup batteries, and optional builtin charger.
+
+config APM_POWER
+	tristate "APM emulation for class batteries"
+	depends on APM_EMULATION
+	help
+	  Say Y here to enable support APM status emulation using
+	  battery class devices.
+
+config BATTERY_DS2760
+	tristate "DS2760 battery driver (HP iPAQ & others)"
+	select W1
+	select W1_SLAVE_DS2760
+	help
+	  Say Y here to enable support for batteries with ds2760 chip.
+
+config BATTERY_PMU
+	tristate "Apple PMU battery"
+	depends on ADB_PMU
+	help
+	  Say Y here to expose battery information on Apple machines
+	  through the generic battery class.
+
+config BATTERY_OLPC
+	tristate "One Laptop Per Child battery"
+	depends on X86_32 && OLPC
+	help
+	  Say Y to enable support for the battery on the OLPC laptop.
+
+endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
new file mode 100644
index 0000000..6413ded
--- /dev/null
+++ b/drivers/power/Makefile
@@ -0,0 +1,22 @@
+power_supply-objs := power_supply_core.o
+
+ifeq ($(CONFIG_SYSFS),y)
+power_supply-objs += power_supply_sysfs.o
+endif
+
+ifeq ($(CONFIG_LEDS_TRIGGERS),y)
+power_supply-objs += power_supply_leds.o
+endif
+
+ifeq ($(CONFIG_POWER_SUPPLY_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_POWER_SUPPLY)	+= power_supply.o
+
+obj-$(CONFIG_PDA_POWER)		+= pda_power.o
+obj-$(CONFIG_APM_POWER)		+= apm_power.o
+
+obj-$(CONFIG_BATTERY_DS2760)	+= ds2760_battery.o
+obj-$(CONFIG_BATTERY_PMU)	+= pmu_battery.o
+obj-$(CONFIG_BATTERY_OLPC)	+= olpc_battery.o
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c
new file mode 100644
index 0000000..042bd95
--- /dev/null
+++ b/drivers/power/apm_power.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2007 Eugeny Boger <eugenyboger@dgap.mipt.ru>
+ *
+ * Author: Eugeny Boger <eugenyboger@dgap.mipt.ru>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ */
+
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/apm-emulation.h>
+
+#define PSY_PROP(psy, prop, val) psy->get_property(psy, \
+			 POWER_SUPPLY_PROP_##prop, val)
+
+#define _MPSY_PROP(prop, val) main_battery->get_property(main_battery, \
+							 prop, val)
+
+#define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val)
+
+static struct power_supply *main_battery;
+
+static void find_main_battery(void)
+{
+	struct device *dev;
+	struct power_supply *bat, *batm;
+	union power_supply_propval full;
+	int max_charge = 0;
+
+	main_battery = NULL;
+	batm = NULL;
+	list_for_each_entry(dev, &power_supply_class->devices, node) {
+		bat = dev_get_drvdata(dev);
+		/* If none of battery devices cantains 'use_for_apm' flag,
+		   choice one with maximum design charge */
+		if (!PSY_PROP(bat, CHARGE_FULL_DESIGN, &full)) {
+			if (full.intval > max_charge) {
+				batm = bat;
+				max_charge = full.intval;
+			}
+		}
+
+		if (bat->use_for_apm)
+			main_battery = bat;
+	}
+	if (!main_battery)
+		main_battery = batm;
+
+	return;
+}
+
+static int calculate_time(int status)
+{
+	union power_supply_propval charge_full, charge_empty;
+	union power_supply_propval charge, I;
+
+	if (MPSY_PROP(CHARGE_FULL, &charge_full)) {
+		/* if battery can't report this property, use design value */
+		if (MPSY_PROP(CHARGE_FULL_DESIGN, &charge_full))
+			return -1;
+	}
+
+	if (MPSY_PROP(CHARGE_EMPTY, &charge_empty)) {
+		/* if battery can't report this property, use design value */
+		if (MPSY_PROP(CHARGE_EMPTY_DESIGN, &charge_empty))
+			charge_empty.intval = 0;
+	}
+
+	if (MPSY_PROP(CHARGE_AVG, &charge)) {
+		/* if battery can't report average value, use momentary */
+		if (MPSY_PROP(CHARGE_NOW, &charge))
+			return -1;
+	}
+
+	if (MPSY_PROP(CURRENT_AVG, &I)) {
+		/* if battery can't report average value, use momentary */
+		if (MPSY_PROP(CURRENT_NOW, &I))
+			return -1;
+	}
+
+	if (status == POWER_SUPPLY_STATUS_CHARGING)
+		return ((charge.intval - charge_full.intval) * 60L) /
+		       I.intval;
+	else
+		return -((charge.intval - charge_empty.intval) * 60L) /
+			I.intval;
+}
+
+static int calculate_capacity(int using_charge)
+{
+	enum power_supply_property full_prop, empty_prop;
+	enum power_supply_property full_design_prop, empty_design_prop;
+	enum power_supply_property now_prop, avg_prop;
+	union power_supply_propval empty, full, cur;
+	int ret;
+
+	if (using_charge) {
+		full_prop = POWER_SUPPLY_PROP_CHARGE_FULL;
+		empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
+		full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
+		empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN;
+		now_prop = POWER_SUPPLY_PROP_CHARGE_NOW;
+		avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG;
+	} else {
+		full_prop = POWER_SUPPLY_PROP_ENERGY_FULL;
+		empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
+		full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
+		empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
+		now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
+		avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
+	}
+
+	if (_MPSY_PROP(full_prop, &full)) {
+		/* if battery can't report this property, use design value */
+		if (_MPSY_PROP(full_design_prop, &full))
+			return -1;
+	}
+
+	if (_MPSY_PROP(avg_prop, &cur)) {
+		/* if battery can't report average value, use momentary */
+		if (_MPSY_PROP(now_prop, &cur))
+			return -1;
+	}
+
+	if (_MPSY_PROP(empty_prop, &empty)) {
+		/* if battery can't report this property, use design value */
+		if (_MPSY_PROP(empty_design_prop, &empty))
+			empty.intval = 0;
+	}
+
+	if (full.intval - empty.intval)
+		ret =  ((cur.intval - empty.intval) * 100L) /
+		       (full.intval - empty.intval);
+	else
+		return -1;
+
+	if (ret > 100)
+		return 100;
+	else if (ret < 0)
+		return 0;
+
+	return ret;
+}
+
+static void apm_battery_apm_get_power_status(struct apm_power_info *info)
+{
+	union power_supply_propval status;
+	union power_supply_propval capacity, time_to_full, time_to_empty;
+
+	down(&power_supply_class->sem);
+	find_main_battery();
+	if (!main_battery) {
+		up(&power_supply_class->sem);
+		return;
+	}
+
+	/* status */
+
+	if (MPSY_PROP(STATUS, &status))
+		status.intval = POWER_SUPPLY_STATUS_UNKNOWN;
+
+	/* ac line status */
+
+	if ((status.intval == POWER_SUPPLY_STATUS_CHARGING) ||
+	    (status.intval == POWER_SUPPLY_STATUS_NOT_CHARGING) ||
+	    (status.intval == POWER_SUPPLY_STATUS_FULL))
+		info->ac_line_status = APM_AC_ONLINE;
+	else
+		info->ac_line_status = APM_AC_OFFLINE;
+
+	/* battery life (i.e. capacity, in percents) */
+
+	if (MPSY_PROP(CAPACITY, &capacity) == 0) {
+		info->battery_life = capacity.intval;
+	} else {
+		/* try calculate using energy */
+		info->battery_life = calculate_capacity(0);
+		/* if failed try calculate using charge instead */
+		if (info->battery_life == -1)
+			info->battery_life = calculate_capacity(1);
+	}
+
+	/* charging status */
+
+	if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
+		info->battery_status = APM_BATTERY_STATUS_CHARGING;
+	} else {
+		if (info->battery_life > 50)
+			info->battery_status = APM_BATTERY_STATUS_HIGH;
+		else if (info->battery_life > 5)
+			info->battery_status = APM_BATTERY_STATUS_LOW;
+		else
+			info->battery_status = APM_BATTERY_STATUS_CRITICAL;
+	}
+	info->battery_flag = info->battery_status;
+
+	/* time */
+
+	info->units = APM_UNITS_MINS;
+
+	if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
+		if (MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full)) {
+			if (MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full))
+				info->time = calculate_time(status.intval);
+			else
+				info->time = time_to_full.intval / 60;
+		}
+	} else {
+		if (MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty)) {
+			if (MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty))
+				info->time = calculate_time(status.intval);
+			else
+				info->time = time_to_empty.intval / 60;
+		}
+	}
+
+	up(&power_supply_class->sem);
+	return;
+}
+
+static int __init apm_battery_init(void)
+{
+	printk(KERN_INFO "APM Battery Driver\n");
+
+	apm_get_power_status = apm_battery_apm_get_power_status;
+	return 0;
+}
+
+static void __exit apm_battery_exit(void)
+{
+	apm_get_power_status = NULL;
+	return;
+}
+
+module_init(apm_battery_init);
+module_exit(apm_battery_exit);
+
+MODULE_AUTHOR("Eugeny Boger <eugenyboger@dgap.mipt.ru>");
+MODULE_DESCRIPTION("APM emulation driver for battery monitoring class");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
new file mode 100644
index 0000000..00e1ea6
--- /dev/null
+++ b/drivers/power/ds2760_battery.c
@@ -0,0 +1,470 @@
+/*
+ * Driver for batteries with DS2760 chips inside.
+ *
+ * Copyright © 2007 Anton Vorontsov
+ *	       2004-2007 Matt Reimer
+ *	       2004 Szabolcs Gyurko
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * Author:  Anton Vorontsov <cbou@mail.ru>
+ *	    February 2007
+ *
+ *	    Matt Reimer <mreimer@vpop.net>
+ *	    April 2004, 2005, 2007
+ *
+ *	    Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *	    September 2004
+ */
+
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+
+#include "../w1/w1.h"
+#include "../w1/slaves/w1_ds2760.h"
+
+struct ds2760_device_info {
+	struct device *dev;
+
+	/* DS2760 data, valid after calling ds2760_battery_read_status() */
+	unsigned long update_time;	/* jiffies when data read */
+	char raw[DS2760_DATA_SIZE];	/* raw DS2760 data */
+	int voltage_raw;		/* units of 4.88 mV */
+	int voltage_uV;			/* units of µV */
+	int current_raw;		/* units of 0.625 mA */
+	int current_uA;			/* units of µA */
+	int accum_current_raw;		/* units of 0.25 mAh */
+	int accum_current_uAh;		/* units of µAh */
+	int temp_raw;			/* units of 0.125 °C */
+	int temp_C;			/* units of 0.1 °C */
+	int rated_capacity;		/* units of µAh */
+	int rem_capacity;		/* percentage */
+	int full_active_uAh;		/* units of µAh */
+	int empty_uAh;			/* units of µAh */
+	int life_sec;			/* units of seconds */
+	int charge_status;		/* POWER_SUPPLY_STATUS_* */
+
+	int full_counter;
+	struct power_supply bat;
+	struct device *w1_dev;
+	struct workqueue_struct *monitor_wqueue;
+	struct delayed_work monitor_work;
+};
+
+static unsigned int cache_time = 1000;
+module_param(cache_time, uint, 0644);
+MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+
+/* Some batteries have their rated capacity stored a N * 10 mAh, while
+ * others use an index into this table. */
+static int rated_capacities[] = {
+	0,
+	920,	/* Samsung */
+	920,	/* BYD */
+	920,	/* Lishen */
+	920,	/* NEC */
+	1440,	/* Samsung */
+	1440,	/* BYD */
+	1440,	/* Lishen */
+	1440,	/* NEC */
+	2880,	/* Samsung */
+	2880,	/* BYD */
+	2880,	/* Lishen */
+	2880	/* NEC */
+};
+
+/* array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C
+ * temp is in Celsius */
+static int battery_interpolate(int array[], int temp)
+{
+	int index, dt;
+
+	if (temp <= 0)
+		return array[0];
+	if (temp >= 40)
+		return array[4];
+
+	index = temp / 10;
+	dt    = temp % 10;
+
+	return array[index] + (((array[index + 1] - array[index]) * dt) / 10);
+}
+
+static int ds2760_battery_read_status(struct ds2760_device_info *di)
+{
+	int ret, i, start, count, scale[5];
+
+	if (di->update_time && time_before(jiffies, di->update_time +
+					   msecs_to_jiffies(cache_time)))
+		return 0;
+
+	/* The first time we read the entire contents of SRAM/EEPROM,
+	 * but after that we just read the interesting bits that change. */
+	if (di->update_time == 0) {
+		start = 0;
+		count = DS2760_DATA_SIZE;
+	} else {
+		start = DS2760_VOLTAGE_MSB;
+		count = DS2760_TEMP_LSB - start + 1;
+	}
+
+	ret = w1_ds2760_read(di->w1_dev, di->raw + start, start, count);
+	if (ret != count) {
+		dev_warn(di->dev, "call to w1_ds2760_read failed (0x%p)\n",
+			 di->w1_dev);
+		return 1;
+	}
+
+	di->update_time = jiffies;
+
+	/* DS2760 reports voltage in units of 4.88mV, but the battery class
+	 * reports in units of uV, so convert by multiplying by 4880. */
+	di->voltage_raw = (di->raw[DS2760_VOLTAGE_MSB] << 3) |
+			  (di->raw[DS2760_VOLTAGE_LSB] >> 5);
+	di->voltage_uV = di->voltage_raw * 4880;
+
+	/* DS2760 reports current in signed units of 0.625mA, but the battery
+	 * class reports in units of µA, so convert by multiplying by 625. */
+	di->current_raw =
+	    (((signed char)di->raw[DS2760_CURRENT_MSB]) << 5) |
+			  (di->raw[DS2760_CURRENT_LSB] >> 3);
+	di->current_uA = di->current_raw * 625;
+
+	/* DS2760 reports accumulated current in signed units of 0.25mAh. */
+	di->accum_current_raw =
+	    (((signed char)di->raw[DS2760_CURRENT_ACCUM_MSB]) << 8) |
+			   di->raw[DS2760_CURRENT_ACCUM_LSB];
+	di->accum_current_uAh = di->accum_current_raw * 250;
+
+	/* DS2760 reports temperature in signed units of 0.125°C, but the
+	 * battery class reports in units of 1/10 °C, so we convert by
+	 * multiplying by .125 * 10 = 1.25. */
+	di->temp_raw = (((signed char)di->raw[DS2760_TEMP_MSB]) << 3) |
+				     (di->raw[DS2760_TEMP_LSB] >> 5);
+	di->temp_C = di->temp_raw + (di->temp_raw / 4);
+
+	/* At least some battery monitors (e.g. HP iPAQ) store the battery's
+	 * maximum rated capacity. */
+	if (di->raw[DS2760_RATED_CAPACITY] < ARRAY_SIZE(rated_capacities))
+		di->rated_capacity = rated_capacities[
+			(unsigned int)di->raw[DS2760_RATED_CAPACITY]];
+	else
+		di->rated_capacity = di->raw[DS2760_RATED_CAPACITY] * 10;
+
+	di->rated_capacity *= 1000; /* convert to µAh */
+
+	/* Calculate the full level at the present temperature. */
+	di->full_active_uAh = di->raw[DS2760_ACTIVE_FULL] << 8 |
+			      di->raw[DS2760_ACTIVE_FULL + 1];
+
+	scale[0] = di->raw[DS2760_ACTIVE_FULL] << 8 |
+		   di->raw[DS2760_ACTIVE_FULL + 1];
+	for (i = 1; i < 5; i++)
+		scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i];
+
+	di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10);
+	di->full_active_uAh *= 1000; /* convert to µAh */
+
+	/* Calculate the empty level at the present temperature. */
+	scale[4] = di->raw[DS2760_ACTIVE_EMPTY + 4];
+	for (i = 3; i >= 0; i--)
+		scale[i] = scale[i + 1] + di->raw[DS2760_ACTIVE_EMPTY + i];
+
+	di->empty_uAh = battery_interpolate(scale, di->temp_C / 10);
+	di->empty_uAh *= 1000; /* convert to µAh */
+
+	/* From Maxim Application Note 131: remaining capacity =
+	 * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */
+	di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) /
+			    (di->full_active_uAh - di->empty_uAh);
+
+	if (di->rem_capacity < 0)
+		di->rem_capacity = 0;
+	if (di->rem_capacity > 100)
+		di->rem_capacity = 100;
+
+	if (di->current_uA)
+		di->life_sec = -((di->accum_current_uAh - di->empty_uAh) *
+				 3600L) / di->current_uA;
+	else
+		di->life_sec = 0;
+
+	return 0;
+}
+
+static void ds2760_battery_update_status(struct ds2760_device_info *di)
+{
+	int old_charge_status = di->charge_status;
+
+	ds2760_battery_read_status(di);
+
+	if (di->charge_status == POWER_SUPPLY_STATUS_UNKNOWN)
+		di->full_counter = 0;
+
+	if (power_supply_am_i_supplied(&di->bat)) {
+		if (di->current_uA > 10000) {
+			di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
+			di->full_counter = 0;
+		} else if (di->current_uA < -5000) {
+			if (di->charge_status != POWER_SUPPLY_STATUS_NOT_CHARGING)
+				dev_notice(di->dev, "not enough power to "
+					   "charge\n");
+			di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+			di->full_counter = 0;
+		} else if (di->current_uA < 10000 &&
+			    di->charge_status != POWER_SUPPLY_STATUS_FULL) {
+
+			/* Don't consider the battery to be full unless
+			 * we've seen the current < 10 mA at least two
+			 * consecutive times. */
+
+			di->full_counter++;
+
+			if (di->full_counter < 2) {
+				di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
+			} else {
+				unsigned char acr[2];
+				int acr_val;
+
+				/* acr is in units of 0.25 mAh */
+				acr_val = di->full_active_uAh * 4L / 1000;
+
+				acr[0] = acr_val >> 8;
+				acr[1] = acr_val & 0xff;
+
+				if (w1_ds2760_write(di->w1_dev, acr,
+				    DS2760_CURRENT_ACCUM_MSB, 2) < 2)
+					dev_warn(di->dev,
+						 "ACR reset failed\n");
+
+				di->charge_status = POWER_SUPPLY_STATUS_FULL;
+			}
+		}
+	} else {
+		di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
+		di->full_counter = 0;
+	}
+
+	if (di->charge_status != old_charge_status)
+		power_supply_changed(&di->bat);
+
+	return;
+}
+
+static void ds2760_battery_work(struct work_struct *work)
+{
+	struct ds2760_device_info *di = container_of(work,
+		struct ds2760_device_info, monitor_work.work);
+	const int interval = HZ * 60;
+
+	dev_dbg(di->dev, "%s\n", __FUNCTION__);
+
+	ds2760_battery_update_status(di);
+	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, interval);
+
+	return;
+}
+
+#define to_ds2760_device_info(x) container_of((x), struct ds2760_device_info, \
+					      bat);
+
+static void ds2760_battery_external_power_changed(struct power_supply *psy)
+{
+	struct ds2760_device_info *di = to_ds2760_device_info(psy);
+
+	dev_dbg(di->dev, "%s\n", __FUNCTION__);
+
+	cancel_delayed_work(&di->monitor_work);
+	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);
+
+	return;
+}
+
+static int ds2760_battery_get_property(struct power_supply *psy,
+				       enum power_supply_property psp,
+				       union power_supply_propval *val)
+{
+	struct ds2760_device_info *di = to_ds2760_device_info(psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		val->intval = di->charge_status;
+		return 0;
+	default:
+		break;
+	}
+
+	ds2760_battery_read_status(di);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		val->intval = di->voltage_uV;
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		val->intval = di->current_uA;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+		val->intval = di->rated_capacity;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		val->intval = di->full_active_uAh;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_EMPTY:
+		val->intval = di->empty_uAh;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		val->intval = di->accum_current_uAh;
+		break;
+	case POWER_SUPPLY_PROP_TEMP:
+		val->intval = di->temp_C;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static enum power_supply_property ds2760_battery_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_EMPTY,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_TEMP,
+};
+
+static int ds2760_battery_probe(struct platform_device *pdev)
+{
+	int retval = 0;
+	struct ds2760_device_info *di;
+	struct ds2760_platform_data *pdata;
+
+	di = kzalloc(sizeof(*di), GFP_KERNEL);
+	if (!di) {
+		retval = -ENOMEM;
+		goto di_alloc_failed;
+	}
+
+	platform_set_drvdata(pdev, di);
+
+	pdata = pdev->dev.platform_data;
+	di->dev		= &pdev->dev;
+	di->w1_dev	     = pdev->dev.parent;
+	di->bat.name	   = pdev->dev.bus_id;
+	di->bat.type	   = POWER_SUPPLY_TYPE_BATTERY;
+	di->bat.properties     = ds2760_battery_props;
+	di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props);
+	di->bat.get_property   = ds2760_battery_get_property;
+	di->bat.external_power_changed =
+				  ds2760_battery_external_power_changed;
+
+	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+	retval = power_supply_register(&pdev->dev, &di->bat);
+	if (retval) {
+		dev_err(di->dev, "failed to register battery");
+		goto batt_failed;
+	}
+
+	INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
+	di->monitor_wqueue = create_singlethread_workqueue(pdev->dev.bus_id);
+	if (!di->monitor_wqueue) {
+		retval = -ESRCH;
+		goto workqueue_failed;
+	}
+	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 1);
+
+	goto success;
+
+workqueue_failed:
+	power_supply_unregister(&di->bat);
+batt_failed:
+	kfree(di);
+di_alloc_failed:
+success:
+	return retval;
+}
+
+static int ds2760_battery_remove(struct platform_device *pdev)
+{
+	struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+	cancel_rearming_delayed_workqueue(di->monitor_wqueue,
+					  &di->monitor_work);
+	destroy_workqueue(di->monitor_wqueue);
+	power_supply_unregister(&di->bat);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int ds2760_battery_suspend(struct platform_device *pdev,
+				  pm_message_t state)
+{
+	struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+	return 0;
+}
+
+static int ds2760_battery_resume(struct platform_device *pdev)
+{
+	struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+	power_supply_changed(&di->bat);
+
+	cancel_delayed_work(&di->monitor_work);
+	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);
+
+	return 0;
+}
+
+#else
+
+#define ds2760_battery_suspend NULL
+#define ds2760_battery_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct platform_driver ds2760_battery_driver = {
+	.driver = {
+		.name = "ds2760-battery",
+	},
+	.probe	  = ds2760_battery_probe,
+	.remove   = ds2760_battery_remove,
+	.suspend  = ds2760_battery_suspend,
+	.resume	  = ds2760_battery_resume,
+};
+
+static int __init ds2760_battery_init(void)
+{
+	return platform_driver_register(&ds2760_battery_driver);
+}
+
+static void __exit ds2760_battery_exit(void)
+{
+	platform_driver_unregister(&ds2760_battery_driver);
+	return;
+}
+
+module_init(ds2760_battery_init);
+module_exit(ds2760_battery_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
+	      "Matt Reimer <mreimer@vpop.net>, "
+	      "Anton Vorontsov <cbou@mail.ru>");
+MODULE_DESCRIPTION("ds2760 battery driver");
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
new file mode 100644
index 0000000..878684d
--- /dev/null
+++ b/drivers/power/olpc_battery.c
@@ -0,0 +1,352 @@
+/*
+ * Battery driver for One Laptop Per Child board.
+ *
+ *	Copyright © 2006  David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <asm/olpc.h>
+
+
+#define EC_BAT_VOLTAGE	0x10	/* uint16_t,	*9.76/32,    mV   */
+#define EC_BAT_CURRENT	0x11	/* int16_t,	*15.625/120, mA   */
+#define EC_BAT_ACR	0x12
+#define EC_BAT_TEMP	0x13	/* uint16_t,	*100/256,   °C  */
+#define EC_AMB_TEMP	0x14	/* uint16_t,	*100/256,   °C  */
+#define EC_BAT_STATUS	0x15	/* uint8_t,	bitmask */
+#define EC_BAT_SOC	0x16	/* uint8_t,	percentage */
+#define EC_BAT_SERIAL	0x17	/* uint8_t[6] */
+#define EC_BAT_EEPROM	0x18	/* uint8_t adr as input, uint8_t output */
+#define EC_BAT_ERRCODE	0x1f	/* uint8_t,	bitmask */
+
+#define BAT_STAT_PRESENT	0x01
+#define BAT_STAT_FULL		0x02
+#define BAT_STAT_LOW		0x04
+#define BAT_STAT_DESTROY	0x08
+#define BAT_STAT_AC		0x10
+#define BAT_STAT_CHARGING	0x20
+#define BAT_STAT_DISCHARGING	0x40
+
+#define BAT_ERR_INFOFAIL	0x02
+#define BAT_ERR_OVERVOLTAGE	0x04
+#define BAT_ERR_OVERTEMP	0x05
+#define BAT_ERR_GAUGESTOP	0x06
+#define BAT_ERR_OUT_OF_CONTROL	0x07
+#define BAT_ERR_ID_FAIL		0x09
+#define BAT_ERR_ACR_FAIL	0x10
+
+#define BAT_ADDR_MFR_TYPE	0x5F
+
+/*********************************************************************
+ *		Power
+ *********************************************************************/
+
+static int olpc_ac_get_prop(struct power_supply *psy,
+			    enum power_supply_property psp,
+			    union power_supply_propval *val)
+{
+	int ret = 0;
+	uint8_t status;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
+		if (ret)
+			return ret;
+
+		val->intval = !!(status & BAT_STAT_AC);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static enum power_supply_property olpc_ac_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply olpc_ac = {
+	.name = "olpc-ac",
+	.type = POWER_SUPPLY_TYPE_MAINS,
+	.properties = olpc_ac_props,
+	.num_properties = ARRAY_SIZE(olpc_ac_props),
+	.get_property = olpc_ac_get_prop,
+};
+
+/*********************************************************************
+ *		Battery properties
+ *********************************************************************/
+static int olpc_bat_get_property(struct power_supply *psy,
+				 enum power_supply_property psp,
+				 union power_supply_propval *val)
+{
+	int ret = 0;
+	int16_t ec_word;
+	uint8_t ec_byte;
+
+	ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1);
+	if (ret)
+		return ret;
+
+	/* Theoretically there's a race here -- the battery could be
+	   removed immediately after we check whether it's present, and
+	   then we query for some other property of the now-absent battery.
+	   It doesn't matter though -- the EC will return the last-known
+	   information, and it's as if we just ran that _little_ bit faster
+	   and managed to read it out before the battery went away. */
+	if (!(ec_byte & BAT_STAT_PRESENT) && psp != POWER_SUPPLY_PROP_PRESENT)
+		return -ENODEV;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		if (olpc_platform_info.ecver > 0x44) {
+			if (ec_byte & BAT_STAT_CHARGING)
+				val->intval = POWER_SUPPLY_STATUS_CHARGING;
+			else if (ec_byte & BAT_STAT_DISCHARGING)
+				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+			else if (ec_byte & BAT_STAT_FULL)
+				val->intval = POWER_SUPPLY_STATUS_FULL;
+			else /* er,... */
+				val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+		} else {
+			/* Older EC didn't report charge/discharge bits */
+			if (!(ec_byte & BAT_STAT_AC)) /* No AC means discharging */
+				val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+			else if (ec_byte & BAT_STAT_FULL)
+				val->intval = POWER_SUPPLY_STATUS_FULL;
+			else /* Not _necessarily_ true but EC doesn't tell all yet */
+				val->intval = POWER_SUPPLY_STATUS_CHARGING;
+			break;
+		}
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = !!(ec_byte & BAT_STAT_PRESENT);
+		break;
+
+	case POWER_SUPPLY_PROP_HEALTH:
+		if (ec_byte & BAT_STAT_DESTROY)
+			val->intval = POWER_SUPPLY_HEALTH_DEAD;
+		else {
+			ret = olpc_ec_cmd(EC_BAT_ERRCODE, NULL, 0, &ec_byte, 1);
+			if (ret)
+				return ret;
+
+			switch (ec_byte) {
+			case 0:
+				val->intval = POWER_SUPPLY_HEALTH_GOOD;
+				break;
+
+			case BAT_ERR_OVERTEMP:
+				val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+				break;
+
+			case BAT_ERR_OVERVOLTAGE:
+				val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+				break;
+
+			case BAT_ERR_INFOFAIL:
+			case BAT_ERR_OUT_OF_CONTROL:
+			case BAT_ERR_ID_FAIL:
+			case BAT_ERR_ACR_FAIL:
+				val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+				break;
+
+			default:
+				/* Eep. We don't know this failure code */
+				return -EIO;
+			}
+		}
+		break;
+
+	case POWER_SUPPLY_PROP_MANUFACTURER:
+		ec_byte = BAT_ADDR_MFR_TYPE;
+		ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
+		if (ret)
+			return ret;
+
+		switch (ec_byte >> 4) {
+		case 1:
+			val->strval = "Gold Peak";
+			break;
+		case 2:
+			val->strval = "BYD";
+			break;
+		default:
+			val->strval = "Unknown";
+			break;
+		}
+		break;
+	case POWER_SUPPLY_PROP_TECHNOLOGY:
+		ec_byte = BAT_ADDR_MFR_TYPE;
+		ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
+		if (ret)
+			return ret;
+
+		switch (ec_byte & 0xf) {
+		case 1:
+			val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH;
+			break;
+		case 2:
+			val->intval = POWER_SUPPLY_TECHNOLOGY_LiFe;
+			break;
+		default:
+			val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
+			break;
+		}
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+		ret = olpc_ec_cmd(EC_BAT_VOLTAGE, NULL, 0, (void *)&ec_word, 2);
+		if (ret)
+			return ret;
+
+		ec_word = be16_to_cpu(ec_word);
+		val->intval = ec_word * 9760L / 32;
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_AVG:
+		ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2);
+		if (ret)
+			return ret;
+
+		ec_word = be16_to_cpu(ec_word);
+		val->intval = ec_word * 15625L / 120;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY:
+		ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
+		if (ret)
+			return ret;
+		val->intval = ec_byte;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+		if (ec_byte & BAT_STAT_FULL)
+			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+		else if (ec_byte & BAT_STAT_LOW)
+			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+		else
+			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+		break;
+	case POWER_SUPPLY_PROP_TEMP:
+		ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2);
+		if (ret)
+			return ret;
+		ec_word = be16_to_cpu(ec_word);
+		val->intval = ec_word * 100 / 256;
+		break;
+	case POWER_SUPPLY_PROP_TEMP_AMBIENT:
+		ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
+		if (ret)
+			return ret;
+
+		ec_word = be16_to_cpu(ec_word);
+		val->intval = ec_word * 100 / 256;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static enum power_supply_property olpc_bat_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_AVG,
+	POWER_SUPPLY_PROP_CURRENT_AVG,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_TEMP_AMBIENT,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+/*********************************************************************
+ *		Initialisation
+ *********************************************************************/
+
+static struct platform_device *bat_pdev;
+
+static struct power_supply olpc_bat = {
+	.properties = olpc_bat_props,
+	.num_properties = ARRAY_SIZE(olpc_bat_props),
+	.get_property = olpc_bat_get_property,
+	.use_for_apm = 1,
+};
+
+void olpc_battery_trigger_uevent(unsigned long cause)
+{
+	if (cause & EC_SCI_SRC_ACPWR)
+		kobject_uevent(&olpc_ac.dev->kobj, KOBJ_CHANGE);
+	if (cause & (EC_SCI_SRC_BATERR|EC_SCI_SRC_BATSOC|EC_SCI_SRC_BATTERY))
+		kobject_uevent(&olpc_bat.dev->kobj, KOBJ_CHANGE);
+}
+
+static int __init olpc_bat_init(void)
+{
+	int ret = 0;
+	uint8_t status;
+
+	if (!olpc_platform_info.ecver)
+		return -ENXIO;
+	if (olpc_platform_info.ecver < 0x43) {
+		printk(KERN_NOTICE "OLPC EC version 0x%02x too old for battery driver.\n", olpc_platform_info.ecver);
+		return -ENXIO;
+	}
+
+	ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
+	if (ret)
+		return ret;
+
+	/* Ignore the status. It doesn't actually matter */
+
+	bat_pdev = platform_device_register_simple("olpc-battery", 0, NULL, 0);
+	if (IS_ERR(bat_pdev))
+		return PTR_ERR(bat_pdev);
+
+	ret = power_supply_register(&bat_pdev->dev, &olpc_ac);
+	if (ret)
+		goto ac_failed;
+
+	olpc_bat.name = bat_pdev->name;
+
+	ret = power_supply_register(&bat_pdev->dev, &olpc_bat);
+	if (ret)
+		goto battery_failed;
+
+	olpc_register_battery_callback(&olpc_battery_trigger_uevent);
+	goto success;
+
+battery_failed:
+	power_supply_unregister(&olpc_ac);
+ac_failed:
+	platform_device_unregister(bat_pdev);
+success:
+	return ret;
+}
+
+static void __exit olpc_bat_exit(void)
+{
+	olpc_deregister_battery_callback();
+	power_supply_unregister(&olpc_bat);
+	power_supply_unregister(&olpc_ac);
+	platform_device_unregister(bat_pdev);
+	return;
+}
+
+module_init(olpc_bat_init);
+module_exit(olpc_bat_exit);
+
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Battery driver for One Laptop Per Child 'XO' machine");
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
new file mode 100644
index 0000000..4e1eb04
--- /dev/null
+++ b/drivers/power/pda_power.c
@@ -0,0 +1,261 @@
+/*
+ * Common power driver for PDAs and phones with one or two external
+ * power supplies (AC/USB) connected to main and backup batteries,
+ * and optional builtin charger.
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/power_supply.h>
+#include <linux/pda_power.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+
+static inline unsigned int get_irq_flags(struct resource *res)
+{
+	unsigned int flags = IRQF_DISABLED | IRQF_SHARED;
+
+	flags |= res->flags & IRQF_TRIGGER_MASK;
+
+	return flags;
+}
+
+static struct device *dev;
+static struct pda_power_pdata *pdata;
+static struct resource *ac_irq, *usb_irq;
+static struct timer_list charger_timer;
+static struct timer_list supply_timer;
+
+static int pda_power_get_property(struct power_supply *psy,
+				  enum power_supply_property psp,
+				  union power_supply_propval *val)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		if (psy->type == POWER_SUPPLY_TYPE_MAINS)
+			val->intval = pdata->is_ac_online ?
+				      pdata->is_ac_online() : 0;
+		else
+			val->intval = pdata->is_usb_online ?
+				      pdata->is_usb_online() : 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static enum power_supply_property pda_power_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static char *pda_power_supplied_to[] = {
+	"main-battery",
+	"backup-battery",
+};
+
+static struct power_supply pda_power_supplies[] = {
+	{
+		.name = "ac",
+		.type = POWER_SUPPLY_TYPE_MAINS,
+		.supplied_to = pda_power_supplied_to,
+		.num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
+		.properties = pda_power_props,
+		.num_properties = ARRAY_SIZE(pda_power_props),
+		.get_property = pda_power_get_property,
+	},
+	{
+		.name = "usb",
+		.type = POWER_SUPPLY_TYPE_USB,
+		.supplied_to = pda_power_supplied_to,
+		.num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
+		.properties = pda_power_props,
+		.num_properties = ARRAY_SIZE(pda_power_props),
+		.get_property = pda_power_get_property,
+	},
+};
+
+static void update_charger(void)
+{
+	if (!pdata->set_charge)
+		return;
+
+	if (pdata->is_ac_online && pdata->is_ac_online()) {
+		dev_dbg(dev, "charger on (AC)\n");
+		pdata->set_charge(PDA_POWER_CHARGE_AC);
+	} else if (pdata->is_usb_online && pdata->is_usb_online()) {
+		dev_dbg(dev, "charger on (USB)\n");
+		pdata->set_charge(PDA_POWER_CHARGE_USB);
+	} else {
+		dev_dbg(dev, "charger off\n");
+		pdata->set_charge(0);
+	}
+
+	return;
+}
+
+static void supply_timer_func(unsigned long irq)
+{
+	if (ac_irq && irq == ac_irq->start)
+		power_supply_changed(&pda_power_supplies[0]);
+	else if (usb_irq && irq == usb_irq->start)
+		power_supply_changed(&pda_power_supplies[1]);
+	return;
+}
+
+static void charger_timer_func(unsigned long irq)
+{
+	update_charger();
+
+	/* Okay, charger set. Now wait a bit before notifying supplicants,
+	 * charge power should stabilize. */
+	supply_timer.data = irq;
+	mod_timer(&supply_timer,
+		  jiffies + msecs_to_jiffies(pdata->wait_for_charger));
+	return;
+}
+
+static irqreturn_t power_changed_isr(int irq, void *unused)
+{
+	/* Wait a bit before reading ac/usb line status and setting charger,
+	 * because ac/usb status readings may lag from irq. */
+	charger_timer.data = irq;
+	mod_timer(&charger_timer,
+		  jiffies + msecs_to_jiffies(pdata->wait_for_status));
+	return IRQ_HANDLED;
+}
+
+static int pda_power_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	dev = &pdev->dev;
+
+	if (pdev->id != -1) {
+		dev_err(dev, "it's meaningless to register several "
+			"pda_powers; use id = -1\n");
+		ret = -EINVAL;
+		goto wrongid;
+	}
+
+	pdata = pdev->dev.platform_data;
+
+	update_charger();
+
+	if (!pdata->wait_for_status)
+		pdata->wait_for_status = 500;
+
+	if (!pdata->wait_for_charger)
+		pdata->wait_for_charger = 500;
+
+	setup_timer(&charger_timer, charger_timer_func, 0);
+	setup_timer(&supply_timer, supply_timer_func, 0);
+
+	ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
+	usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
+	if (!ac_irq && !usb_irq) {
+		dev_err(dev, "no ac/usb irq specified\n");
+		ret = -ENODEV;
+		goto noirqs;
+	}
+
+	if (pdata->supplied_to) {
+		pda_power_supplies[0].supplied_to = pdata->supplied_to;
+		pda_power_supplies[1].supplied_to = pdata->supplied_to;
+		pda_power_supplies[0].num_supplicants = pdata->num_supplicants;
+		pda_power_supplies[1].num_supplicants = pdata->num_supplicants;
+	}
+
+	ret = power_supply_register(&pdev->dev, &pda_power_supplies[0]);
+	if (ret) {
+		dev_err(dev, "failed to register %s power supply\n",
+			pda_power_supplies[0].name);
+		goto supply0_failed;
+	}
+
+	ret = power_supply_register(&pdev->dev, &pda_power_supplies[1]);
+	if (ret) {
+		dev_err(dev, "failed to register %s power supply\n",
+			pda_power_supplies[1].name);
+		goto supply1_failed;
+	}
+
+	if (ac_irq) {
+		ret = request_irq(ac_irq->start, power_changed_isr,
+				  get_irq_flags(ac_irq), ac_irq->name,
+				  &pda_power_supplies[0]);
+		if (ret) {
+			dev_err(dev, "request ac irq failed\n");
+			goto ac_irq_failed;
+		}
+	}
+
+	if (usb_irq) {
+		ret = request_irq(usb_irq->start, power_changed_isr,
+				  get_irq_flags(usb_irq), usb_irq->name,
+				  &pda_power_supplies[1]);
+		if (ret) {
+			dev_err(dev, "request usb irq failed\n");
+			goto usb_irq_failed;
+		}
+	}
+
+	goto success;
+
+usb_irq_failed:
+	if (ac_irq)
+		free_irq(ac_irq->start, &pda_power_supplies[0]);
+ac_irq_failed:
+	power_supply_unregister(&pda_power_supplies[1]);
+supply1_failed:
+	power_supply_unregister(&pda_power_supplies[0]);
+supply0_failed:
+noirqs:
+wrongid:
+success:
+	return ret;
+}
+
+static int pda_power_remove(struct platform_device *pdev)
+{
+	if (usb_irq)
+		free_irq(usb_irq->start, &pda_power_supplies[1]);
+	if (ac_irq)
+		free_irq(ac_irq->start, &pda_power_supplies[0]);
+	del_timer_sync(&charger_timer);
+	del_timer_sync(&supply_timer);
+	power_supply_unregister(&pda_power_supplies[1]);
+	power_supply_unregister(&pda_power_supplies[0]);
+	return 0;
+}
+
+static struct platform_driver pda_power_pdrv = {
+	.driver = {
+		.name = "pda-power",
+	},
+	.probe = pda_power_probe,
+	.remove = pda_power_remove,
+};
+
+static int __init pda_power_init(void)
+{
+	return platform_driver_register(&pda_power_pdrv);
+}
+
+static void __exit pda_power_exit(void)
+{
+	platform_driver_unregister(&pda_power_pdrv);
+	return;
+}
+
+module_init(pda_power_init);
+module_exit(pda_power_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
diff --git a/drivers/power/pmu_battery.c b/drivers/power/pmu_battery.c
new file mode 100644
index 0000000..2fea4af
--- /dev/null
+++ b/drivers/power/pmu_battery.c
@@ -0,0 +1,215 @@
+/*
+ * Battery class driver for Apple PMU
+ *
+ *	Copyright © 2006  David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+static struct pmu_battery_dev {
+	struct power_supply bat;
+	struct pmu_battery_info *pbi;
+	char name[16];
+	int propval;
+} *pbats[PMU_MAX_BATTERIES];
+
+#define to_pmu_battery_dev(x) container_of(x, struct pmu_battery_dev, bat)
+
+/*********************************************************************
+ *		Power
+ *********************************************************************/
+
+static int pmu_get_ac_prop(struct power_supply *psy,
+			   enum power_supply_property psp,
+			   union power_supply_propval *val)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = (!!(pmu_power_flags & PMU_PWR_AC_PRESENT)) ||
+			      (pmu_battery_count == 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static enum power_supply_property pmu_ac_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply pmu_ac = {
+	.name = "pmu-ac",
+	.type = POWER_SUPPLY_TYPE_MAINS,
+	.properties = pmu_ac_props,
+	.num_properties = ARRAY_SIZE(pmu_ac_props),
+	.get_property = pmu_get_ac_prop,
+};
+
+/*********************************************************************
+ *		Battery properties
+ *********************************************************************/
+
+static char *pmu_batt_types[] = {
+	"Smart", "Comet", "Hooper", "Unknown"
+};
+
+static char *pmu_bat_get_model_name(struct pmu_battery_info *pbi)
+{
+	switch (pbi->flags & PMU_BATT_TYPE_MASK) {
+	case PMU_BATT_TYPE_SMART:
+		return pmu_batt_types[0];
+	case PMU_BATT_TYPE_COMET:
+		return pmu_batt_types[1];
+	case PMU_BATT_TYPE_HOOPER:
+		return pmu_batt_types[2];
+	default: break;
+	}
+	return pmu_batt_types[3];
+}
+
+static int pmu_bat_get_property(struct power_supply *psy,
+				enum power_supply_property psp,
+				union power_supply_propval *val)
+{
+	struct pmu_battery_dev *pbat = to_pmu_battery_dev(psy);
+	struct pmu_battery_info *pbi = pbat->pbi;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		if (pbi->flags & PMU_BATT_CHARGING)
+			val->intval = POWER_SUPPLY_STATUS_CHARGING;
+		else
+			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+		break;
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = !!(pbi->flags & PMU_BATT_PRESENT);
+		break;
+	case POWER_SUPPLY_PROP_MODEL_NAME:
+		val->strval = pmu_bat_get_model_name(pbi);
+		break;
+	case POWER_SUPPLY_PROP_ENERGY_AVG:
+		val->intval = pbi->charge     * 1000; /* mWh -> µWh */
+		break;
+	case POWER_SUPPLY_PROP_ENERGY_FULL:
+		val->intval = pbi->max_charge * 1000; /* mWh -> µWh */
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_AVG:
+		val->intval = pbi->amperage   * 1000; /* mA -> µA */
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+		val->intval = pbi->voltage    * 1000; /* mV -> µV */
+		break;
+	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+		val->intval = pbi->time_remaining;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static enum power_supply_property pmu_bat_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_ENERGY_AVG,
+	POWER_SUPPLY_PROP_ENERGY_FULL,
+	POWER_SUPPLY_PROP_CURRENT_AVG,
+	POWER_SUPPLY_PROP_VOLTAGE_AVG,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+};
+
+/*********************************************************************
+ *		Initialisation
+ *********************************************************************/
+
+static struct platform_device *bat_pdev;
+
+static int __init pmu_bat_init(void)
+{
+	int ret;
+	int i;
+
+	bat_pdev = platform_device_register_simple("pmu-battery",
+						   0, NULL, 0);
+	if (IS_ERR(bat_pdev)) {
+		ret = PTR_ERR(bat_pdev);
+		goto pdev_register_failed;
+	}
+
+	ret = power_supply_register(&bat_pdev->dev, &pmu_ac);
+	if (ret)
+		goto ac_register_failed;
+
+	for (i = 0; i < pmu_battery_count; i++) {
+		struct pmu_battery_dev *pbat = kzalloc(sizeof(*pbat),
+						       GFP_KERNEL);
+		if (!pbat)
+			break;
+
+		sprintf(pbat->name, "PMU battery %d", i);
+		pbat->bat.name = pbat->name;
+		pbat->bat.properties = pmu_bat_props;
+		pbat->bat.num_properties = ARRAY_SIZE(pmu_bat_props);
+		pbat->bat.get_property = pmu_bat_get_property;
+		pbat->pbi = &pmu_batteries[i];
+
+		ret = power_supply_register(&bat_pdev->dev, &pbat->bat);
+		if (ret) {
+			kfree(pbat);
+			goto battery_register_failed;
+		}
+		pbats[i] = pbat;
+	}
+
+	goto success;
+
+battery_register_failed:
+	while (i--) {
+		if (!pbats[i])
+			continue;
+		power_supply_unregister(&pbats[i]->bat);
+		kfree(pbats[i]);
+	}
+	power_supply_unregister(&pmu_ac);
+ac_register_failed:
+	platform_device_unregister(bat_pdev);
+pdev_register_failed:
+success:
+	return ret;
+}
+
+static void __exit pmu_bat_exit(void)
+{
+	int i;
+
+	for (i = 0; i < PMU_MAX_BATTERIES; i++) {
+		if (!pbats[i])
+			continue;
+		power_supply_unregister(&pbats[i]->bat);
+		kfree(pbats[i]);
+	}
+	power_supply_unregister(&pmu_ac);
+	platform_device_unregister(bat_pdev);
+
+	return;
+}
+
+module_init(pmu_bat_init);
+module_exit(pmu_bat_exit);
+
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PMU battery driver");
diff --git a/drivers/power/power_supply.h b/drivers/power/power_supply.h
new file mode 100644
index 0000000..a9880d4
--- /dev/null
+++ b/drivers/power/power_supply.h
@@ -0,0 +1,42 @@
+/*
+ *  Functions private to power supply class
+ *
+ *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright © 2004  Szabolcs Gyurko
+ *  Copyright © 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#ifdef CONFIG_SYSFS
+
+extern int power_supply_create_attrs(struct power_supply *psy);
+extern void power_supply_remove_attrs(struct power_supply *psy);
+extern int power_supply_uevent(struct device *dev, char **envp, int num_envp,
+			       char *buffer, int buffer_size);
+
+#else
+
+static inline int power_supply_create_attrs(struct power_supply *psy)
+{ return 0; }
+static inline void power_supply_remove_attrs(struct power_supply *psy) {}
+#define power_supply_uevent NULL
+
+#endif /* CONFIG_SYSFS */
+
+#ifdef CONFIG_LEDS_TRIGGERS
+
+extern void power_supply_update_leds(struct power_supply *psy);
+extern int power_supply_create_triggers(struct power_supply *psy);
+extern void power_supply_remove_triggers(struct power_supply *psy);
+
+#else
+
+static inline void power_supply_update_leds(struct power_supply *psy) {}
+static inline int power_supply_create_triggers(struct power_supply *psy)
+{ return 0; }
+static inline void power_supply_remove_triggers(struct power_supply *psy) {}
+
+#endif /* CONFIG_LEDS_TRIGGERS */
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
new file mode 100644
index 0000000..e87ea51
--- /dev/null
+++ b/drivers/power/power_supply_core.c
@@ -0,0 +1,168 @@
+/*
+ *  Universal power supply monitor class
+ *
+ *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright © 2004  Szabolcs Gyurko
+ *  Copyright © 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include "power_supply.h"
+
+struct class *power_supply_class;
+
+static void power_supply_changed_work(struct work_struct *work)
+{
+	struct power_supply *psy = container_of(work, struct power_supply,
+						changed_work);
+	int i;
+
+	dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+
+	for (i = 0; i < psy->num_supplicants; i++) {
+		struct device *dev;
+
+		down(&power_supply_class->sem);
+		list_for_each_entry(dev, &power_supply_class->devices, node) {
+			struct power_supply *pst = dev_get_drvdata(dev);
+
+			if (!strcmp(psy->supplied_to[i], pst->name)) {
+				if (pst->external_power_changed)
+					pst->external_power_changed(pst);
+			}
+		}
+		up(&power_supply_class->sem);
+	}
+
+	power_supply_update_leds(psy);
+
+	kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
+
+	return;
+}
+
+void power_supply_changed(struct power_supply *psy)
+{
+	dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+
+	schedule_work(&psy->changed_work);
+
+	return;
+}
+
+int power_supply_am_i_supplied(struct power_supply *psy)
+{
+	union power_supply_propval ret = {0,};
+	struct device *dev;
+
+	down(&power_supply_class->sem);
+	list_for_each_entry(dev, &power_supply_class->devices, node) {
+		struct power_supply *epsy = dev_get_drvdata(dev);
+		int i;
+
+		for (i = 0; i < epsy->num_supplicants; i++) {
+			if (!strcmp(epsy->supplied_to[i], psy->name)) {
+				if (epsy->get_property(epsy,
+					  POWER_SUPPLY_PROP_ONLINE, &ret))
+					continue;
+				if (ret.intval)
+					goto out;
+			}
+		}
+	}
+out:
+	up(&power_supply_class->sem);
+
+	dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, ret.intval);
+
+	return ret.intval;
+}
+
+int power_supply_register(struct device *parent, struct power_supply *psy)
+{
+	int rc = 0;
+
+	psy->dev = device_create(power_supply_class, parent, 0,
+				 "%s", psy->name);
+	if (IS_ERR(psy->dev)) {
+		rc = PTR_ERR(psy->dev);
+		goto dev_create_failed;
+	}
+
+	dev_set_drvdata(psy->dev, psy);
+
+	INIT_WORK(&psy->changed_work, power_supply_changed_work);
+
+	rc = power_supply_create_attrs(psy);
+	if (rc)
+		goto create_attrs_failed;
+
+	rc = power_supply_create_triggers(psy);
+	if (rc)
+		goto create_triggers_failed;
+
+	power_supply_changed(psy);
+
+	goto success;
+
+create_triggers_failed:
+	power_supply_remove_attrs(psy);
+create_attrs_failed:
+	device_unregister(psy->dev);
+dev_create_failed:
+success:
+	return rc;
+}
+
+void power_supply_unregister(struct power_supply *psy)
+{
+	flush_scheduled_work();
+	power_supply_remove_triggers(psy);
+	power_supply_remove_attrs(psy);
+	device_unregister(psy->dev);
+	return;
+}
+
+static int __init power_supply_class_init(void)
+{
+	power_supply_class = class_create(THIS_MODULE, "power_supply");
+
+	if (IS_ERR(power_supply_class))
+		return PTR_ERR(power_supply_class);
+
+	power_supply_class->dev_uevent = power_supply_uevent;
+
+	return 0;
+}
+
+static void __exit power_supply_class_exit(void)
+{
+	class_destroy(power_supply_class);
+	return;
+}
+
+EXPORT_SYMBOL_GPL(power_supply_changed);
+EXPORT_SYMBOL_GPL(power_supply_am_i_supplied);
+EXPORT_SYMBOL_GPL(power_supply_register);
+EXPORT_SYMBOL_GPL(power_supply_unregister);
+
+/* exported for the APM Power driver, APM emulation */
+EXPORT_SYMBOL_GPL(power_supply_class);
+
+subsys_initcall(power_supply_class_init);
+module_exit(power_supply_class_exit);
+
+MODULE_DESCRIPTION("Universal power supply monitor class");
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>, "
+	      "Szabolcs Gyurko, "
+	      "Anton Vorontsov <cbou@mail.ru>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/power_supply_leds.c b/drivers/power/power_supply_leds.c
new file mode 100644
index 0000000..7232490
--- /dev/null
+++ b/drivers/power/power_supply_leds.c
@@ -0,0 +1,176 @@
+/*
+ *  LEDs triggers for power supply class
+ *
+ *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright © 2004  Szabolcs Gyurko
+ *  Copyright © 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#include <linux/power_supply.h>
+
+/* Battery specific LEDs triggers. */
+
+static void power_supply_update_bat_leds(struct power_supply *psy)
+{
+	union power_supply_propval status;
+
+	if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
+		return;
+
+	dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, status.intval);
+
+	switch (status.intval) {
+	case POWER_SUPPLY_STATUS_FULL:
+		led_trigger_event(psy->charging_full_trig, LED_FULL);
+		led_trigger_event(psy->charging_trig, LED_OFF);
+		led_trigger_event(psy->full_trig, LED_FULL);
+		break;
+	case POWER_SUPPLY_STATUS_CHARGING:
+		led_trigger_event(psy->charging_full_trig, LED_FULL);
+		led_trigger_event(psy->charging_trig, LED_FULL);
+		led_trigger_event(psy->full_trig, LED_OFF);
+		break;
+	default:
+		led_trigger_event(psy->charging_full_trig, LED_OFF);
+		led_trigger_event(psy->charging_trig, LED_OFF);
+		led_trigger_event(psy->full_trig, LED_OFF);
+		break;
+	}
+
+	return;
+}
+
+static int power_supply_create_bat_triggers(struct power_supply *psy)
+{
+	int rc = 0;
+
+	psy->charging_full_trig_name = kmalloc(strlen(psy->name) +
+				  sizeof("-charging-or-full"), GFP_KERNEL);
+	if (!psy->charging_full_trig_name)
+		goto charging_full_failed;
+
+	psy->charging_trig_name = kmalloc(strlen(psy->name) +
+					  sizeof("-charging"), GFP_KERNEL);
+	if (!psy->charging_trig_name)
+		goto charging_failed;
+
+	psy->full_trig_name = kmalloc(strlen(psy->name) +
+				      sizeof("-full"), GFP_KERNEL);
+	if (!psy->full_trig_name)
+		goto full_failed;
+
+	strcpy(psy->charging_full_trig_name, psy->name);
+	strcat(psy->charging_full_trig_name, "-charging-or-full");
+	strcpy(psy->charging_trig_name, psy->name);
+	strcat(psy->charging_trig_name, "-charging");
+	strcpy(psy->full_trig_name, psy->name);
+	strcat(psy->full_trig_name, "-full");
+
+	led_trigger_register_simple(psy->charging_full_trig_name,
+				    &psy->charging_full_trig);
+	led_trigger_register_simple(psy->charging_trig_name,
+				    &psy->charging_trig);
+	led_trigger_register_simple(psy->full_trig_name,
+				    &psy->full_trig);
+
+	goto success;
+
+full_failed:
+	kfree(psy->charging_trig_name);
+charging_failed:
+	kfree(psy->charging_full_trig_name);
+charging_full_failed:
+	rc = -ENOMEM;
+success:
+	return rc;
+}
+
+static void power_supply_remove_bat_triggers(struct power_supply *psy)
+{
+	led_trigger_unregister_simple(psy->charging_full_trig);
+	led_trigger_unregister_simple(psy->charging_trig);
+	led_trigger_unregister_simple(psy->full_trig);
+	kfree(psy->full_trig_name);
+	kfree(psy->charging_trig_name);
+	kfree(psy->charging_full_trig_name);
+	return;
+}
+
+/* Generated power specific LEDs triggers. */
+
+static void power_supply_update_gen_leds(struct power_supply *psy)
+{
+	union power_supply_propval online;
+
+	if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
+		return;
+
+	dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, online.intval);
+
+	if (online.intval)
+		led_trigger_event(psy->online_trig, LED_FULL);
+	else
+		led_trigger_event(psy->online_trig, LED_OFF);
+
+	return;
+}
+
+static int power_supply_create_gen_triggers(struct power_supply *psy)
+{
+	int rc = 0;
+
+	psy->online_trig_name = kmalloc(strlen(psy->name) + sizeof("-online"),
+					GFP_KERNEL);
+	if (!psy->online_trig_name)
+		goto online_failed;
+
+	strcpy(psy->online_trig_name, psy->name);
+	strcat(psy->online_trig_name, "-online");
+
+	led_trigger_register_simple(psy->online_trig_name, &psy->online_trig);
+
+	goto success;
+
+online_failed:
+	rc = -ENOMEM;
+success:
+	return rc;
+}
+
+static void power_supply_remove_gen_triggers(struct power_supply *psy)
+{
+	led_trigger_unregister_simple(psy->online_trig);
+	kfree(psy->online_trig_name);
+	return;
+}
+
+/* Choice what triggers to create&update. */
+
+void power_supply_update_leds(struct power_supply *psy)
+{
+	if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+		power_supply_update_bat_leds(psy);
+	else
+		power_supply_update_gen_leds(psy);
+	return;
+}
+
+int power_supply_create_triggers(struct power_supply *psy)
+{
+	if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+		return power_supply_create_bat_triggers(psy);
+	return power_supply_create_gen_triggers(psy);
+}
+
+void power_supply_remove_triggers(struct power_supply *psy)
+{
+	if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+		power_supply_remove_bat_triggers(psy);
+	else
+		power_supply_remove_gen_triggers(psy);
+	return;
+}
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
new file mode 100644
index 0000000..c07d425
--- /dev/null
+++ b/drivers/power/power_supply_sysfs.c
@@ -0,0 +1,299 @@
+/*
+ *  Sysfs interface for the universal power supply monitor class
+ *
+ *  Copyright © 2007  David Woodhouse <dwmw2@infradead.org>
+ *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright © 2004  Szabolcs Gyurko
+ *  Copyright © 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#include <linux/ctype.h>
+#include <linux/power_supply.h>
+
+/*
+ * This is because the name "current" breaks the device attr macro.
+ * The "current" word resolves to "(get_current())" so instead of
+ * "current" "(get_current())" appears in the sysfs.
+ *
+ * The source of this definition is the device.h which calls __ATTR
+ * macro in sysfs.h which calls the __stringify macro.
+ *
+ * Only modification that the name is not tried to be resolved
+ * (as a macro let's say).
+ */
+
+#define POWER_SUPPLY_ATTR(_name)					\
+{									\
+	.attr = { .name = #_name, .mode = 0444, .owner = THIS_MODULE },	\
+	.show = power_supply_show_property,				\
+	.store = NULL,							\
+}
+
+static struct device_attribute power_supply_attrs[];
+
+static ssize_t power_supply_show_property(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf) {
+	static char *status_text[] = {
+		"Unknown", "Charging", "Discharging", "Not charging", "Full"
+	};
+	static char *health_text[] = {
+		"Unknown", "Good", "Overheat", "Dead", "Over voltage",
+		"Unspecified failure"
+	};
+	static char *technology_text[] = {
+		"Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd"
+	};
+	static char *capacity_level_text[] = {
+		"Unknown", "Critical", "Low", "Normal", "High", "Full"
+	};
+	ssize_t ret;
+	struct power_supply *psy = dev_get_drvdata(dev);
+	const ptrdiff_t off = attr - power_supply_attrs;
+	union power_supply_propval value;
+
+	ret = psy->get_property(psy, off, &value);
+
+	if (ret < 0) {
+		if (ret != -ENODEV)
+			dev_err(dev, "driver failed to report `%s' property\n",
+				attr->attr.name);
+		return ret;
+	}
+
+	if (off == POWER_SUPPLY_PROP_STATUS)
+		return sprintf(buf, "%s\n", status_text[value.intval]);
+	else if (off == POWER_SUPPLY_PROP_HEALTH)
+		return sprintf(buf, "%s\n", health_text[value.intval]);
+	else if (off == POWER_SUPPLY_PROP_TECHNOLOGY)
+		return sprintf(buf, "%s\n", technology_text[value.intval]);
+	else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL)
+		return sprintf(buf, "%s\n",
+			       capacity_level_text[value.intval]);
+	else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)
+		return sprintf(buf, "%s\n", value.strval);
+
+	return sprintf(buf, "%d\n", value.intval);
+}
+
+/* Must be in the same order as POWER_SUPPLY_PROP_* */
+static struct device_attribute power_supply_attrs[] = {
+	/* Properties of type `int' */
+	POWER_SUPPLY_ATTR(status),
+	POWER_SUPPLY_ATTR(health),
+	POWER_SUPPLY_ATTR(present),
+	POWER_SUPPLY_ATTR(online),
+	POWER_SUPPLY_ATTR(technology),
+	POWER_SUPPLY_ATTR(voltage_max_design),
+	POWER_SUPPLY_ATTR(voltage_min_design),
+	POWER_SUPPLY_ATTR(voltage_now),
+	POWER_SUPPLY_ATTR(voltage_avg),
+	POWER_SUPPLY_ATTR(current_now),
+	POWER_SUPPLY_ATTR(current_avg),
+	POWER_SUPPLY_ATTR(charge_full_design),
+	POWER_SUPPLY_ATTR(charge_empty_design),
+	POWER_SUPPLY_ATTR(charge_full),
+	POWER_SUPPLY_ATTR(charge_empty),
+	POWER_SUPPLY_ATTR(charge_now),
+	POWER_SUPPLY_ATTR(charge_avg),
+	POWER_SUPPLY_ATTR(energy_full_design),
+	POWER_SUPPLY_ATTR(energy_empty_design),
+	POWER_SUPPLY_ATTR(energy_full),
+	POWER_SUPPLY_ATTR(energy_empty),
+	POWER_SUPPLY_ATTR(energy_now),
+	POWER_SUPPLY_ATTR(energy_avg),
+	POWER_SUPPLY_ATTR(capacity),
+	POWER_SUPPLY_ATTR(capacity_level),
+	POWER_SUPPLY_ATTR(temp),
+	POWER_SUPPLY_ATTR(temp_ambient),
+	POWER_SUPPLY_ATTR(time_to_empty_now),
+	POWER_SUPPLY_ATTR(time_to_empty_avg),
+	POWER_SUPPLY_ATTR(time_to_full_now),
+	POWER_SUPPLY_ATTR(time_to_full_avg),
+	/* Properties of type `const char *' */
+	POWER_SUPPLY_ATTR(model_name),
+	POWER_SUPPLY_ATTR(manufacturer),
+};
+
+static ssize_t power_supply_show_static_attrs(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf) {
+	static char *type_text[] = { "Battery", "UPS", "Mains", "USB" };
+	struct power_supply *psy = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", type_text[psy->type]);
+}
+
+static struct device_attribute power_supply_static_attrs[] = {
+	__ATTR(type, 0444, power_supply_show_static_attrs, NULL),
+};
+
+int power_supply_create_attrs(struct power_supply *psy)
+{
+	int rc = 0;
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++) {
+		rc = device_create_file(psy->dev,
+			    &power_supply_static_attrs[i]);
+		if (rc)
+			goto statics_failed;
+	}
+
+	for (j = 0; j < psy->num_properties; j++) {
+		rc = device_create_file(psy->dev,
+			    &power_supply_attrs[psy->properties[j]]);
+		if (rc)
+			goto dynamics_failed;
+	}
+
+	goto succeed;
+
+dynamics_failed:
+	while (j--)
+		device_remove_file(psy->dev,
+			   &power_supply_attrs[psy->properties[j]]);
+statics_failed:
+	while (i--)
+		device_remove_file(psy->dev,
+			   &power_supply_static_attrs[psy->properties[i]]);
+succeed:
+	return rc;
+}
+
+void power_supply_remove_attrs(struct power_supply *psy)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++)
+		device_remove_file(psy->dev,
+			    &power_supply_static_attrs[i]);
+
+	for (i = 0; i < psy->num_properties; i++)
+		device_remove_file(psy->dev,
+			    &power_supply_attrs[psy->properties[i]]);
+
+	return;
+}
+
+static char *kstruprdup(const char *str, gfp_t gfp)
+{
+	char *ret, *ustr;
+
+	ustr = ret = kmalloc(strlen(str) + 1, gfp);
+
+	if (!ret)
+		return NULL;
+
+	while (*str)
+		*ustr++ = toupper(*str++);
+
+	*ustr = 0;
+
+	return ret;
+}
+
+int power_supply_uevent(struct device *dev, char **envp, int num_envp,
+			char *buffer, int buffer_size)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	int i = 0, length = 0, ret = 0, j;
+	char *prop_buf;
+	char *attrname;
+
+	dev_dbg(dev, "uevent\n");
+
+	if (!psy) {
+		dev_dbg(dev, "No power supply yet\n");
+		return ret;
+	}
+
+	dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
+
+	ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+			     &length, "POWER_SUPPLY_NAME=%s", psy->name);
+	if (ret)
+		return ret;
+
+	prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
+	if (!prop_buf)
+		return -ENOMEM;
+
+	for (j = 0; j < ARRAY_SIZE(power_supply_static_attrs); j++) {
+		struct device_attribute *attr;
+		char *line;
+
+		attr = &power_supply_static_attrs[j];
+
+		ret = power_supply_show_static_attrs(dev, attr, prop_buf);
+		if (ret < 0)
+			goto out;
+
+		line = strchr(prop_buf, '\n');
+		if (line)
+			*line = 0;
+
+		attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
+		if (!attrname) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf);
+
+		ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+				     &length, "POWER_SUPPLY_%s=%s",
+				     attrname, prop_buf);
+		kfree(attrname);
+		if (ret)
+			goto out;
+	}
+
+	dev_dbg(dev, "%zd dynamic props\n", psy->num_properties);
+
+	for (j = 0; j < psy->num_properties; j++) {
+		struct device_attribute *attr;
+		char *line;
+
+		attr = &power_supply_attrs[psy->properties[j]];
+
+		ret = power_supply_show_property(dev, attr, prop_buf);
+		if (ret == -ENODEV) {
+			/* When a battery is absent, we expect -ENODEV. Don't abort;
+			   send the uevent with at least the the PRESENT=0 property */
+			ret = 0;
+			continue;
+		}
+
+		if (ret < 0)
+			goto out;
+
+		line = strchr(prop_buf, '\n');
+		if (line)
+			*line = 0;
+
+		attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
+		if (!attrname) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf);
+
+		ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+				     &length, "POWER_SUPPLY_%s=%s",
+				     attrname, prop_buf);
+		kfree(attrname);
+		if (ret)
+			goto out;
+	}
+
+out:
+	free_page((unsigned long)prop_buf);
+
+	return ret;
+}
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 8b3b0f4..ac7e8ef 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -28,6 +28,7 @@
 static struct proc_dir_entry *dasd_devices_entry = NULL;
 static struct proc_dir_entry *dasd_statistics_entry = NULL;
 
+#ifdef CONFIG_DASD_PROFILE
 static char *
 dasd_get_user_string(const char __user *user_buf, size_t user_len)
 {
@@ -47,6 +48,7 @@
 		buffer[user_len] = 0;
 	return buffer;
 }
+#endif /* CONFIG_DASD_PROFILE */
 
 static int
 dasd_devices_show(struct seq_file *m, void *v)
@@ -167,6 +169,7 @@
 	return len;
 }
 
+#ifdef CONFIG_DASD_PROFILE
 static char *
 dasd_statistics_array(char *str, unsigned int *array, int shift)
 {
@@ -180,6 +183,7 @@
 	str += sprintf(str,"\n");
 	return str;
 }
+#endif /* CONFIG_DASD_PROFILE */
 
 static int
 dasd_statistics_read(char *page, char **start, off_t off,
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index dbb99d1..c7318a1 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -72,6 +72,18 @@
 
 typedef u32 sccb_mask_t;	/* ATTENTION: assumes 32bit mask !!! */
 
+struct sccb_header {
+	u16	length;
+	u8	function_code;
+	u8	control_mask[3];
+	u16	response_code;
+} __attribute__((packed));
+
+extern u64 sclp_facilities;
+
+#define SCLP_HAS_CHP_INFO	(sclp_facilities & 0x8000000000000000ULL)
+#define SCLP_HAS_CHP_RECONFIG	(sclp_facilities & 0x2000000000000000ULL)
+
 struct gds_subvector {
 	u8	length;
 	u8	key;
diff --git a/drivers/s390/char/sclp_chp.c b/drivers/s390/char/sclp_chp.c
index a66b914..c68f5e7 100644
--- a/drivers/s390/char/sclp_chp.c
+++ b/drivers/s390/char/sclp_chp.c
@@ -55,6 +55,8 @@
 	struct chp_cfg_data *data;
 	int rc;
 
+	if (!SCLP_HAS_CHP_RECONFIG)
+		return -EOPNOTSUPP;
 	/* Prepare sccb. */
 	data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!data)
@@ -152,6 +154,8 @@
 	struct chp_info_data *data;
 	int rc;
 
+	if (!SCLP_HAS_CHP_INFO)
+		return -EOPNOTSUPP;
 	/* Prepare sccb. */
 	data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
 	if (!data)
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
index 7bcbe64..a1136e0 100644
--- a/drivers/s390/char/sclp_info.c
+++ b/drivers/s390/char/sclp_info.c
@@ -11,47 +11,106 @@
 #include <asm/sclp.h>
 #include "sclp.h"
 
-struct sclp_readinfo_sccb s390_readinfo_sccb;
+struct sclp_readinfo_sccb {
+	struct	sccb_header header;	/* 0-7 */
+	u16	rnmax;			/* 8-9 */
+	u8	rnsize;			/* 10 */
+	u8	_reserved0[24 - 11];	/* 11-23 */
+	u8	loadparm[8];		/* 24-31 */
+	u8	_reserved1[48 - 32];	/* 32-47 */
+	u64	facilities;		/* 48-55 */
+	u8	_reserved2[91 - 56];	/* 56-90 */
+	u8	flags;			/* 91 */
+	u8	_reserved3[100 - 92];	/* 92-99 */
+	u32	rnsize2;		/* 100-103 */
+	u64	rnmax2;			/* 104-111 */
+	u8	_reserved4[4096 - 112];	/* 112-4095 */
+} __attribute__((packed, aligned(4096)));
+
+static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
+static int __initdata early_readinfo_sccb_valid;
+
+u64 sclp_facilities;
 
 void __init sclp_readinfo_early(void)
 {
-	sclp_cmdw_t command;
-	struct sccb_header *sccb;
 	int ret;
+	int i;
+	struct sclp_readinfo_sccb *sccb;
+	sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
+				  SCLP_CMDW_READ_SCP_INFO};
 
-	__ctl_set_bit(0, 9); /* enable service signal subclass mask */
+	/* Enable service signal subclass mask. */
+	__ctl_set_bit(0, 9);
+	sccb = &early_readinfo_sccb;
+	for (i = 0; i < ARRAY_SIZE(commands); i++) {
+		do {
+			memset(sccb, 0, sizeof(*sccb));
+			sccb->header.length = sizeof(*sccb);
+			sccb->header.control_mask[2] = 0x80;
+			ret = sclp_service_call(commands[i], sccb);
+		} while (ret == -EBUSY);
 
-	sccb = &s390_readinfo_sccb.header;
-	command = SCLP_CMDW_READ_SCP_INFO_FORCED;
-	while (1) {
-		u16 response;
-
-		memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb));
-		sccb->length = sizeof(s390_readinfo_sccb);
-		sccb->control_mask[2] = 0x80;
-
-		ret = sclp_service_call(command, &s390_readinfo_sccb);
-
-		if (ret == -EIO)
-			goto out;
-		if (ret == -EBUSY)
-			continue;
-
+		if (ret)
+			break;
 		__load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
 				PSW_MASK_WAIT | PSW_DEFAULT_KEY);
 		local_irq_disable();
+		/*
+		 * Contents of the sccb might have changed
+		 * therefore a barrier is needed.
+		 */
 		barrier();
-
-		response = sccb->response_code;
-
-		if (response == 0x10)
+		if (sccb->header.response_code == 0x10) {
+			early_readinfo_sccb_valid = 1;
 			break;
-
-		if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO)
+		}
+		if (sccb->header.response_code != 0x1f0)
 			break;
-
-		command = SCLP_CMDW_READ_SCP_INFO;
 	}
-out:
-	__ctl_clear_bit(0, 9); /* disable service signal subclass mask */
+	/* Disable service signal subclass mask again. */
+	__ctl_clear_bit(0, 9);
+}
+
+void __init sclp_facilities_detect(void)
+{
+	if (!early_readinfo_sccb_valid)
+		return;
+	sclp_facilities = early_readinfo_sccb.facilities;
+}
+
+unsigned long long __init sclp_memory_detect(void)
+{
+	unsigned long long memsize;
+	struct sclp_readinfo_sccb *sccb;
+
+	if (!early_readinfo_sccb_valid)
+		return 0;
+	sccb = &early_readinfo_sccb;
+	if (sccb->rnsize)
+		memsize = sccb->rnsize << 20;
+	else
+		memsize = sccb->rnsize2 << 20;
+	if (sccb->rnmax)
+		memsize *= sccb->rnmax;
+	else
+		memsize *= sccb->rnmax2;
+	return memsize;
+}
+
+/*
+ * This function will be called after sclp_memory_detect(), which gets called
+ * early from early.c code. Therefore the sccb should have valid contents.
+ */
+void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
+{
+	struct sclp_readinfo_sccb *sccb;
+
+	if (!early_readinfo_sccb_valid)
+		return;
+	sccb = &early_readinfo_sccb;
+	info->is_valid = 1;
+	if (sccb->flags & 0x2)
+		info->has_dump = 1;
+	memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
 }
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index fce3dac..82e6a6b 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -175,13 +175,12 @@
 
 static const struct file_operations vmcp_fops = {
 	.owner		= THIS_MODULE,
-	.open		= &vmcp_open,
-	.release	= &vmcp_release,
-	.read		= &vmcp_read,
-	.llseek		= &no_llseek,
-	.write		= &vmcp_write,
-	.unlocked_ioctl	= &vmcp_ioctl,
-	.compat_ioctl	= &vmcp_ioctl
+	.open		= vmcp_open,
+	.release	= vmcp_release,
+	.read		= vmcp_read,
+	.write		= vmcp_write,
+	.unlocked_ioctl	= vmcp_ioctl,
+	.compat_ioctl	= vmcp_ioctl
 };
 
 static struct miscdevice vmcp_dev = {
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index a5a00e9..12f7a4c 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -835,7 +835,7 @@
 }
 
 
-static int vmlogrdr_init(void)
+static int __init vmlogrdr_init(void)
 {
 	int rc;
 	int i;
@@ -885,7 +885,7 @@
 }
 
 
-static void vmlogrdr_exit(void)
+static void __exit vmlogrdr_exit(void)
 {
 	vmlogrdr_cleanup();
 	printk (KERN_INFO "vmlogrdr: driver unloaded\n");
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 4e711a9..3712ede 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -156,7 +156,7 @@
 	return rc;
 }
 
-static int memcpy_real_user(__user void *dest, unsigned long src, size_t count)
+static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
 {
 	static char buf[4096];
 	int offs = 0, size;
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 997f468..60b9347 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -27,7 +27,6 @@
 /*
  * diag210 is used under VM to get information about a virtual device
  */
-#ifdef CONFIG_64BIT
 int
 diag210(struct diag210 * addr)
 {
@@ -43,6 +42,7 @@
 	spin_lock_irqsave(&diag210_lock, flags);
 	diag210_tmp = *addr;
 
+#ifdef CONFIG_64BIT
 	asm volatile(
 		"	lhi	%0,-1\n"
 		"	sam31\n"
@@ -51,19 +51,8 @@
 		"	srl	%0,28\n"
 		"1:	sam64\n"
 		EX_TABLE(0b,1b)
-		: "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory");
-
-	*addr = diag210_tmp;
-	spin_unlock_irqrestore(&diag210_lock, flags);
-
-	return ccode;
-}
+		: "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
 #else
-int
-diag210(struct diag210 * addr)
-{
-	int ccode;
-
 	asm volatile(
 		"	lhi	%0,-1\n"
 		"	diag	%1,0,0x210\n"
@@ -71,11 +60,14 @@
 		"	srl	%0,28\n"
 		"1:\n"
 		EX_TABLE(0b,1b)
-		: "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory");
+		: "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
+#endif
+
+	*addr = diag210_tmp;
+	spin_unlock_irqrestore(&diag210_lock, flags);
 
 	return ccode;
 }
-#endif
 
 /*
  * Input :
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 5aac0ec..90bd220 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -43,6 +43,7 @@
 static void ap_poll_timeout(unsigned long);
 static int ap_poll_thread_start(void);
 static void ap_poll_thread_stop(void);
+static void ap_request_timeout(unsigned long);
 
 /**
  * Module description.
@@ -189,6 +190,7 @@
 	case AP_RESPONSE_NORMAL:
 		return 0;
 	case AP_RESPONSE_Q_FULL:
+	case AP_RESPONSE_RESET_IN_PROGRESS:
 		return -EBUSY;
 	default:	/* Device is gone. */
 		return -ENODEV;
@@ -252,6 +254,8 @@
 		if (status.queue_empty)
 			return -ENOENT;
 		return -EBUSY;
+	case AP_RESPONSE_RESET_IN_PROGRESS:
+		return -EBUSY;
 	default:
 		return -ENODEV;
 	}
@@ -326,11 +330,12 @@
 			i = AP_MAX_RESET;	/* return with -ENODEV */
 			break;
 		case AP_RESPONSE_RESET_IN_PROGRESS:
+			rc = -EBUSY;
 		case AP_RESPONSE_BUSY:
 		default:
 			break;
 		}
-		if (rc != -ENODEV)
+		if (rc != -ENODEV && rc != -EBUSY)
 			break;
 		if (i < AP_MAX_RESET - 1) {
 			udelay(5);
@@ -341,6 +346,40 @@
 }
 
 /**
+ * Arm request timeout if a AP device was idle and a new request is submitted.
+ */
+static void ap_increase_queue_count(struct ap_device *ap_dev)
+{
+	int timeout = ap_dev->drv->request_timeout;
+
+	ap_dev->queue_count++;
+	if (ap_dev->queue_count == 1) {
+		mod_timer(&ap_dev->timeout, jiffies + timeout);
+		ap_dev->reset = AP_RESET_ARMED;
+	}
+}
+
+/**
+ * AP device is still alive, re-schedule request timeout if there are still
+ * pending requests.
+ */
+static void ap_decrease_queue_count(struct ap_device *ap_dev)
+{
+	int timeout = ap_dev->drv->request_timeout;
+
+	ap_dev->queue_count--;
+	if (ap_dev->queue_count > 0)
+		mod_timer(&ap_dev->timeout, jiffies + timeout);
+	else
+		/**
+		 * The timeout timer should to be disabled now - since
+		 * del_timer_sync() is very expensive, we just tell via the
+		 * reset flag to ignore the pending timeout timer.
+		 */
+		ap_dev->reset = AP_RESET_IGNORE;
+}
+
+/**
  * AP device related attributes.
  */
 static ssize_t ap_hwtype_show(struct device *dev,
@@ -498,6 +537,7 @@
 	struct ap_driver *ap_drv = ap_dev->drv;
 
 	ap_flush_queue(ap_dev);
+	del_timer_sync(&ap_dev->timeout);
 	if (ap_drv->remove)
 		ap_drv->remove(ap_dev);
 	spin_lock_bh(&ap_device_lock);
@@ -759,17 +799,21 @@
 				      __ap_scan_bus);
 		rc = ap_query_queue(qid, &queue_depth, &device_type);
 		if (dev) {
+			if (rc == -EBUSY) {
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout(AP_RESET_TIMEOUT);
+				rc = ap_query_queue(qid, &queue_depth,
+						    &device_type);
+			}
 			ap_dev = to_ap_dev(dev);
 			spin_lock_bh(&ap_dev->lock);
 			if (rc || ap_dev->unregistered) {
 				spin_unlock_bh(&ap_dev->lock);
-				put_device(dev);
 				device_unregister(dev);
+				put_device(dev);
 				continue;
-			} else
-				spin_unlock_bh(&ap_dev->lock);
-		}
-		if (dev) {
+			}
+			spin_unlock_bh(&ap_dev->lock);
 			put_device(dev);
 			continue;
 		}
@@ -788,6 +832,8 @@
 		INIT_LIST_HEAD(&ap_dev->pendingq);
 		INIT_LIST_HEAD(&ap_dev->requestq);
 		INIT_LIST_HEAD(&ap_dev->list);
+		setup_timer(&ap_dev->timeout, ap_request_timeout,
+			    (unsigned long) ap_dev);
 		if (device_type == 0)
 			ap_probe_device_type(ap_dev);
 		else
@@ -853,7 +899,7 @@
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
 		atomic_dec(&ap_poll_requests);
-		ap_dev->queue_count--;
+		ap_decrease_queue_count(ap_dev);
 		list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
 			if (ap_msg->psmid != ap_dev->reply->psmid)
 				continue;
@@ -904,7 +950,7 @@
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
 		atomic_inc(&ap_poll_requests);
-		ap_dev->queue_count++;
+		ap_increase_queue_count(ap_dev);
 		list_move_tail(&ap_msg->list, &ap_dev->pendingq);
 		ap_dev->requestq_count--;
 		ap_dev->pendingq_count++;
@@ -914,6 +960,7 @@
 		*flags |= 2;
 		break;
 	case AP_RESPONSE_Q_FULL:
+	case AP_RESPONSE_RESET_IN_PROGRESS:
 		*flags |= 2;
 		break;
 	case AP_RESPONSE_MESSAGE_TOO_BIG:
@@ -960,10 +1007,11 @@
 			list_add_tail(&ap_msg->list, &ap_dev->pendingq);
 			atomic_inc(&ap_poll_requests);
 			ap_dev->pendingq_count++;
-			ap_dev->queue_count++;
+			ap_increase_queue_count(ap_dev);
 			ap_dev->total_request_count++;
 			break;
 		case AP_RESPONSE_Q_FULL:
+		case AP_RESPONSE_RESET_IN_PROGRESS:
 			list_add_tail(&ap_msg->list, &ap_dev->requestq);
 			ap_dev->requestq_count++;
 			ap_dev->total_request_count++;
@@ -1046,6 +1094,25 @@
 }
 
 /**
+ * Reset a not responding AP device and move all requests from the
+ * pending queue to the request queue.
+ */
+static void ap_reset(struct ap_device *ap_dev)
+{
+	int rc;
+
+	ap_dev->reset = AP_RESET_IGNORE;
+	atomic_sub(ap_dev->queue_count, &ap_poll_requests);
+	ap_dev->queue_count = 0;
+	list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
+	ap_dev->requestq_count += ap_dev->pendingq_count;
+	ap_dev->pendingq_count = 0;
+	rc = ap_init_queue(ap_dev->qid);
+	if (rc == -ENODEV)
+		ap_dev->unregistered = 1;
+}
+
+/**
  * Poll all AP devices on the bus in a round robin fashion. Continue
  * polling until bit 2^0 of the control flags is not set. If bit 2^1
  * of the control flags has been set arm the poll timer.
@@ -1056,6 +1123,8 @@
 	if (!ap_dev->unregistered) {
 		if (ap_poll_queue(ap_dev, flags))
 			ap_dev->unregistered = 1;
+		if (ap_dev->reset == AP_RESET_DO)
+			ap_reset(ap_dev);
 	}
 	spin_unlock(&ap_dev->lock);
 	return 0;
@@ -1147,6 +1216,17 @@
 	mutex_unlock(&ap_poll_thread_mutex);
 }
 
+/**
+ * Handling of request timeouts
+ */
+static void ap_request_timeout(unsigned long data)
+{
+	struct ap_device *ap_dev = (struct ap_device *) data;
+
+	if (ap_dev->reset == AP_RESET_ARMED)
+		ap_dev->reset = AP_RESET_DO;
+}
+
 static void ap_reset_domain(void)
 {
 	int i;
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 008559e..87c2d64 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -33,6 +33,7 @@
 #define AP_DEVICES 64		/* Number of AP devices. */
 #define AP_DOMAINS 16		/* Number of AP domains. */
 #define AP_MAX_RESET 90		/* Maximum number of resets. */
+#define AP_RESET_TIMEOUT (HZ/2)	/* Time in ticks for reset timeouts. */
 #define AP_CONFIG_TIME 30	/* Time in seconds between AP bus rescans. */
 #define AP_POLL_TIME 1		/* Time in ticks between receive polls. */
 
@@ -83,6 +84,13 @@
 #define AP_DEVICE_TYPE_CEX2A	6
 #define AP_DEVICE_TYPE_CEX2C	7
 
+/**
+ * AP reset flag states
+ */
+#define AP_RESET_IGNORE	0	/* request timeout will be ignored */
+#define AP_RESET_ARMED	1	/* request timeout timer is active */
+#define AP_RESET_DO	2	/* AP reset required */
+
 struct ap_device;
 struct ap_message;
 
@@ -95,6 +103,7 @@
 	/* receive is called from tasklet context */
 	void (*receive)(struct ap_device *, struct ap_message *,
 			struct ap_message *);
+	int request_timeout;		/* request timeout in jiffies */
 };
 
 #define to_ap_drv(x) container_of((x), struct ap_driver, driver)
@@ -112,6 +121,8 @@
 	int queue_depth;		/* AP queue depth.*/
 	int device_type;		/* AP device type. */
 	int unregistered;		/* marks AP device as unregistered */
+	struct timer_list timeout;	/* Timer for request timeouts. */
+	int reset;			/* Reset required after req. timeout. */
 
 	int queue_count;		/* # messages currently on AP queue. */
 
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 5bb13a9..08657f6 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -70,6 +70,7 @@
 	.remove = zcrypt_cex2a_remove,
 	.receive = zcrypt_cex2a_receive,
 	.ids = zcrypt_cex2a_ids,
+	.request_timeout = CEX2A_CLEANUP_TIME,
 };
 
 /**
@@ -306,18 +307,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, CEX2A_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, mex->outputdata,
 				      mex->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	kfree(ap_msg.message);
 	return rc;
@@ -348,18 +344,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, CEX2A_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, crt->outputdata,
 				      crt->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	kfree(ap_msg.message);
 	return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 818ffe0..6e93b47 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -70,6 +70,7 @@
 	.remove = zcrypt_pcica_remove,
 	.receive = zcrypt_pcica_receive,
 	.ids = zcrypt_pcica_ids,
+	.request_timeout = PCICA_CLEANUP_TIME,
 };
 
 /**
@@ -290,18 +291,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, PCICA_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, mex->outputdata,
 				      mex->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	kfree(ap_msg.message);
 	return rc;
@@ -332,18 +328,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, PCICA_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, crt->outputdata,
 				      crt->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	kfree(ap_msg.message);
 	return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index f295a40..d6d59bf 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -82,6 +82,7 @@
 	.remove = zcrypt_pcicc_remove,
 	.receive = zcrypt_pcicc_receive,
 	.ids = zcrypt_pcicc_ids,
+	.request_timeout = PCICC_CLEANUP_TIME,
 };
 
 /**
@@ -501,18 +502,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, PCICC_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, mex->outputdata,
 				      mex->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	free_page((unsigned long) ap_msg.message);
 	return rc;
@@ -544,18 +540,13 @@
 		goto out_free;
 	init_completion(&work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&work, PCICC_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&work);
+	if (rc == 0)
 		rc = convert_response(zdev, &ap_msg, crt->outputdata,
 				      crt->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	free_page((unsigned long) ap_msg.message);
 	return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 252443b..6494878 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -93,6 +93,7 @@
 	.remove = zcrypt_pcixcc_remove,
 	.receive = zcrypt_pcixcc_receive,
 	.ids = zcrypt_pcixcc_ids,
+	.request_timeout = PCIXCC_CLEANUP_TIME,
 };
 
 /**
@@ -641,18 +642,13 @@
 		goto out_free;
 	init_completion(&resp_type.work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&resp_type.work, PCIXCC_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&resp_type.work);
+	if (rc == 0)
 		rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
 					  mex->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	free_page((unsigned long) ap_msg.message);
 	return rc;
@@ -685,18 +681,13 @@
 		goto out_free;
 	init_completion(&resp_type.work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&resp_type.work, PCIXCC_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&resp_type.work);
+	if (rc == 0)
 		rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
 					  crt->outputdatalength);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	free_page((unsigned long) ap_msg.message);
 	return rc;
@@ -729,17 +720,12 @@
 		goto out_free;
 	init_completion(&resp_type.work);
 	ap_queue_message(zdev->ap_dev, &ap_msg);
-	rc = wait_for_completion_interruptible_timeout(
-				&resp_type.work, PCIXCC_CLEANUP_TIME);
-	if (rc > 0)
+	rc = wait_for_completion_interruptible(&resp_type.work);
+	if (rc == 0)
 		rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
-	else {
-		/* Signal pending or message timed out. */
+	else
+		/* Signal pending. */
 		ap_cancel_message(zdev->ap_dev, &ap_msg);
-		if (rc == 0)
-			/* Message timed out. */
-			rc = -ETIME;
-	}
 out_free:
 	memset(ap_msg.message, 0x0, ap_msg.length);
 	kfree(ap_msg.message);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 6b76bab..a0ea435 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -842,12 +842,16 @@
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
+	PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
+	PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
 	PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
+	PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
+	PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
 	PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
 	PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
 	PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 61de78a..4fff61b 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -143,7 +143,7 @@
 static unsigned long break_pressed; /* break, really ... */
 #endif
 
-static unsigned char zs_init_regs[16] __initdata = {
+static unsigned char zs_init_regs[16] = {
 	0,				/* write 0 */
 	0,				/* write 1 */
 	0,				/* write 2 */
@@ -1581,7 +1581,7 @@
 /*  Initialize Z8530s zs_channels
  */
 
-static void __init probe_sccs(void)
+static void probe_sccs(void)
 {
 	struct dec_serial **pp;
 	int i, n, n_chips = 0, n_channels, chip, channel;
@@ -1923,7 +1923,7 @@
  *	- initialize the serial port
  *	Return non-zero if we didn't find a serial port.
  */
-static int __init serial_console_setup(struct console *co, char *options)
+static int serial_console_setup(struct console *co, char *options)
 {
 	struct dec_serial *info;
 	int baud = 9600;
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 904e5ae..df95d6c 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -35,4 +35,17 @@
 	  Each block has 30 bytes of data and a two byte CRC16.
 	  Full block writes are only allowed if the CRC is valid.
 
+config W1_SLAVE_DS2760
+	tristate "Dallas 2760 battery monitor chip (HP iPAQ & others)"
+	depends on W1
+	help
+	  If you enable this you will have the DS2760 battery monitor
+	  chip support.
+
+	  The battery monitor chip is used in many batteries/devices
+	  as the one who is responsible for charging/discharging/monitoring
+	  Li+ batteries.
+
+	  If you are unsure, say N.
+
 endmenu
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index 725dcfd..a8eb752 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -5,4 +5,5 @@
 obj-$(CONFIG_W1_SLAVE_THERM)	+= w1_therm.o
 obj-$(CONFIG_W1_SLAVE_SMEM)	+= w1_smem.o
 obj-$(CONFIG_W1_SLAVE_DS2433)	+= w1_ds2433.o
+obj-$(CONFIG_W1_SLAVE_DS2760)	+= w1_ds2760.o
 
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c
new file mode 100644
index 0000000..88a37fb
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2760.c
@@ -0,0 +1,213 @@
+/*
+ * 1-Wire implementation for the ds2760 chip
+ *
+ * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/idr.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+#include "../w1_family.h"
+#include "w1_ds2760.h"
+
+static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
+			int io)
+{
+	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+	if (!dev)
+		return 0;
+
+	mutex_lock(&sl->master->mutex);
+
+	if (addr > DS2760_DATA_SIZE || addr < 0) {
+		count = 0;
+		goto out;
+	}
+	if (addr + count > DS2760_DATA_SIZE)
+		count = DS2760_DATA_SIZE - addr;
+
+	if (!w1_reset_select_slave(sl)) {
+		if (!io) {
+			w1_write_8(sl->master, W1_DS2760_READ_DATA);
+			w1_write_8(sl->master, addr);
+			count = w1_read_block(sl->master, buf, count);
+		} else {
+			w1_write_8(sl->master, W1_DS2760_WRITE_DATA);
+			w1_write_8(sl->master, addr);
+			w1_write_block(sl->master, buf, count);
+			/* XXX w1_write_block returns void, not n_written */
+		}
+	}
+
+out:
+	mutex_unlock(&sl->master->mutex);
+
+	return count;
+}
+
+int w1_ds2760_read(struct device *dev, char *buf, int addr, size_t count)
+{
+	return w1_ds2760_io(dev, buf, addr, count, 0);
+}
+
+int w1_ds2760_write(struct device *dev, char *buf, int addr, size_t count)
+{
+	return w1_ds2760_io(dev, buf, addr, count, 1);
+}
+
+static ssize_t w1_ds2760_read_bin(struct kobject *kobj, char *buf, loff_t off,
+				  size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	return w1_ds2760_read(dev, buf, off, count);
+}
+
+static struct bin_attribute w1_ds2760_bin_attr = {
+	.attr = {
+		.name = "w1_slave",
+		.mode = S_IRUGO,
+		.owner = THIS_MODULE,
+	},
+	.size = DS2760_DATA_SIZE,
+	.read = w1_ds2760_read_bin,
+};
+
+static DEFINE_IDR(bat_idr);
+static DEFINE_MUTEX(bat_idr_lock);
+
+static int new_bat_id(void)
+{
+	int ret;
+
+	while (1) {
+		int id;
+
+		ret = idr_pre_get(&bat_idr, GFP_KERNEL);
+		if (ret == 0)
+			return -ENOMEM;
+
+		mutex_lock(&bat_idr_lock);
+		ret = idr_get_new(&bat_idr, NULL, &id);
+		mutex_unlock(&bat_idr_lock);
+
+		if (ret == 0) {
+			ret = id & MAX_ID_MASK;
+			break;
+		} else if (ret == -EAGAIN) {
+			continue;
+		} else {
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static void release_bat_id(int id)
+{
+	mutex_lock(&bat_idr_lock);
+	idr_remove(&bat_idr, id);
+	mutex_unlock(&bat_idr_lock);
+
+	return;
+}
+
+static int w1_ds2760_add_slave(struct w1_slave *sl)
+{
+	int ret;
+	int id;
+	struct platform_device *pdev;
+
+	id = new_bat_id();
+	if (id < 0) {
+		ret = id;
+		goto noid;
+	}
+
+	pdev = platform_device_alloc("ds2760-battery", id);
+	if (!pdev) {
+		ret = -ENOMEM;
+		goto pdev_alloc_failed;
+	}
+	pdev->dev.parent = &sl->dev;
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto pdev_add_failed;
+
+	ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
+	if (ret)
+		goto bin_attr_failed;
+
+	dev_set_drvdata(&sl->dev, pdev);
+
+	goto success;
+
+bin_attr_failed:
+pdev_add_failed:
+	platform_device_unregister(pdev);
+pdev_alloc_failed:
+	release_bat_id(id);
+noid:
+success:
+	return ret;
+}
+
+static void w1_ds2760_remove_slave(struct w1_slave *sl)
+{
+	struct platform_device *pdev = dev_get_drvdata(&sl->dev);
+	int id = pdev->id;
+
+	platform_device_unregister(pdev);
+	release_bat_id(id);
+	sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
+
+	return;
+}
+
+static struct w1_family_ops w1_ds2760_fops = {
+	.add_slave    = w1_ds2760_add_slave,
+	.remove_slave = w1_ds2760_remove_slave,
+};
+
+static struct w1_family w1_ds2760_family = {
+	.fid = W1_FAMILY_DS2760,
+	.fops = &w1_ds2760_fops,
+};
+
+static int __init w1_ds2760_init(void)
+{
+	printk(KERN_INFO "1-Wire driver for the DS2760 battery monitor "
+	       " chip  - (c) 2004-2005, Szabolcs Gyurko\n");
+	idr_init(&bat_idr);
+	return w1_register_family(&w1_ds2760_family);
+}
+
+static void __exit w1_ds2760_exit(void)
+{
+	w1_unregister_family(&w1_ds2760_family);
+	idr_destroy(&bat_idr);
+}
+
+EXPORT_SYMBOL(w1_ds2760_read);
+EXPORT_SYMBOL(w1_ds2760_write);
+
+module_init(w1_ds2760_init);
+module_exit(w1_ds2760_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>");
+MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip");
diff --git a/drivers/w1/slaves/w1_ds2760.h b/drivers/w1/slaves/w1_ds2760.h
new file mode 100644
index 0000000..f130242
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2760.h
@@ -0,0 +1,50 @@
+/*
+ * 1-Wire implementation for the ds2760 chip
+ *
+ * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ */
+
+#ifndef __w1_ds2760_h__
+#define __w1_ds2760_h__
+
+/* Known commands to the DS2760 chip */
+#define W1_DS2760_SWAP			0xAA
+#define W1_DS2760_READ_DATA		0x69
+#define W1_DS2760_WRITE_DATA		0x6C
+#define W1_DS2760_COPY_DATA		0x48
+#define W1_DS2760_RECALL_DATA		0xB8
+#define W1_DS2760_LOCK			0x6A
+
+/* Number of valid register addresses */
+#define DS2760_DATA_SIZE		0x40
+
+#define DS2760_PROTECTION_REG		0x00
+#define DS2760_STATUS_REG		0x01
+#define DS2760_EEPROM_REG		0x07
+#define DS2760_SPECIAL_FEATURE_REG	0x08
+#define DS2760_VOLTAGE_MSB		0x0c
+#define DS2760_VOLTAGE_LSB		0x0d
+#define DS2760_CURRENT_MSB		0x0e
+#define DS2760_CURRENT_LSB		0x0f
+#define DS2760_CURRENT_ACCUM_MSB	0x10
+#define DS2760_CURRENT_ACCUM_LSB	0x11
+#define DS2760_TEMP_MSB			0x18
+#define DS2760_TEMP_LSB			0x19
+#define DS2760_EEPROM_BLOCK0		0x20
+#define DS2760_ACTIVE_FULL		0x20
+#define DS2760_EEPROM_BLOCK1		0x30
+#define DS2760_RATED_CAPACITY		0x32
+#define DS2760_CURRENT_OFFSET_BIAS	0x33
+#define DS2760_ACTIVE_EMPTY		0x3b
+
+extern int w1_ds2760_read(struct device *dev, char *buf, int addr,
+			  size_t count);
+extern int w1_ds2760_write(struct device *dev, char *buf, int addr,
+			   size_t count);
+
+#endif /* !__w1_ds2760_h__ */
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 1e2ac40..ef1e1da 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -33,6 +33,7 @@
 #define W1_THERM_DS1822  	0x22
 #define W1_EEPROM_DS2433  	0x23
 #define W1_THERM_DS18B20 	0x28
+#define W1_FAMILY_DS2760	0x30
 
 #define MAXNAMELEN		32
 
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index f544a28..36e381c 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -33,7 +33,7 @@
 	.fsync		= file_fsync,
 	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 const struct inode_operations adfs_file_inode_operations = {
diff --git a/fs/affs/file.c b/fs/affs/file.c
index c879690..c314a35 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -35,7 +35,7 @@
 	.open		= affs_file_open,
 	.release	= affs_file_release,
 	.fsync		= file_fsync,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 const struct inode_operations affs_file_inode_operations = {
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 9c0e721..aede7eb 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -32,7 +32,7 @@
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= afs_file_write,
 	.mmap		= generic_file_readonly_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 	.fsync		= afs_fsync,
 };
 
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 329ee47..521ff7c 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -114,12 +114,6 @@
 	return -EIO;
 }
 
-static ssize_t bad_file_sendfile(struct file *in_file, loff_t *ppos,
-			size_t count, read_actor_t actor, void *target)
-{
-	return -EIO;
-}
-
 static ssize_t bad_file_sendpage(struct file *file, struct page *page,
 			int off, size_t len, loff_t *pos, int more)
 {
@@ -182,7 +176,6 @@
 	.aio_fsync	= bad_file_aio_fsync,
 	.fasync		= bad_file_fasync,
 	.lock		= bad_file_lock,
-	.sendfile	= bad_file_sendfile,
 	.sendpage	= bad_file_sendpage,
 	.get_unmapped_area = bad_file_get_unmapped_area,
 	.check_flags	= bad_file_check_flags,
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index ef4d1fa..24310e9 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -24,7 +24,7 @@
 	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb)
diff --git a/fs/bio.c b/fs/bio.c
index 093345f..33e4634 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1223,8 +1223,6 @@
 EXPORT_SYMBOL(bio_add_page);
 EXPORT_SYMBOL(bio_add_pc_page);
 EXPORT_SYMBOL(bio_get_nr_vecs);
-EXPORT_SYMBOL(bio_map_user);
-EXPORT_SYMBOL(bio_unmap_user);
 EXPORT_SYMBOL(bio_map_kern);
 EXPORT_SYMBOL(bio_pair_release);
 EXPORT_SYMBOL(bio_split);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index ea1480a..b3e9bfa 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1346,7 +1346,6 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= compat_blkdev_ioctl,
 #endif
-	.sendfile	= generic_file_sendfile,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 };
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 7c04752..8b0cbf4 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -616,7 +616,7 @@
 	.fsync = cifs_fsync,
 	.flush = cifs_flush,
 	.mmap  = cifs_file_mmap,
-	.sendfile = generic_file_sendfile,
+	.splice_read = generic_file_splice_read,
 	.llseek = cifs_llseek,
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl	= cifs_ioctl,
@@ -637,7 +637,7 @@
 	.lock = cifs_lock,
 	.fsync = cifs_fsync,
 	.flush = cifs_flush,
-	.sendfile = generic_file_sendfile, /* BB removeme BB */
+	.splice_read = generic_file_splice_read,
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl  = cifs_ioctl,
 #endif /* CONFIG_CIFS_POSIX */
@@ -656,7 +656,7 @@
 	.fsync = cifs_fsync,
 	.flush = cifs_flush,
 	.mmap  = cifs_file_mmap,
-	.sendfile = generic_file_sendfile,
+	.splice_read = generic_file_splice_read,
 	.llseek = cifs_llseek,
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl	= cifs_ioctl,
@@ -676,7 +676,7 @@
 	.release = cifs_close,
 	.fsync = cifs_fsync,
 	.flush = cifs_flush,
-	.sendfile = generic_file_sendfile, /* BB removeme BB */
+	.splice_read = generic_file_splice_read,
 #ifdef CONFIG_CIFS_POSIX
 	.ioctl  = cifs_ioctl,
 #endif /* CONFIG_CIFS_POSIX */
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 5ef2b60..99dbe86 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -47,8 +47,9 @@
 }
 
 static ssize_t
-coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
-		   read_actor_t actor, void *target)
+coda_file_splice_read(struct file *coda_file, loff_t *ppos,
+		      struct pipe_inode_info *pipe, size_t count,
+		      unsigned int flags)
 {
 	struct coda_file_info *cfi;
 	struct file *host_file;
@@ -57,10 +58,10 @@
 	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
 	host_file = cfi->cfi_container;
 
-	if (!host_file->f_op || !host_file->f_op->sendfile)
+	if (!host_file->f_op || !host_file->f_op->splice_read)
 		return -EINVAL;
 
-	return host_file->f_op->sendfile(host_file, ppos, count, actor, target);
+	return host_file->f_op->splice_read(host_file, ppos, pipe, count,flags);
 }
 
 static ssize_t
@@ -295,6 +296,6 @@
 	.flush		= coda_flush,
 	.release	= coda_release,
 	.fsync		= coda_fsync,
-	.sendfile	= coda_file_sendfile,
+	.splice_read	= coda_file_splice_read,
 };
 
diff --git a/fs/dlm/Makefile b/fs/dlm/Makefile
index 604cf7d..d248e60 100644
--- a/fs/dlm/Makefile
+++ b/fs/dlm/Makefile
@@ -8,6 +8,7 @@
 				member.o \
 				memory.o \
 				midcomms.o \
+				netlink.o \
 				lowcomms.o \
 				rcom.o \
 				recover.o \
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 822abdc..5069b2c 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -90,6 +90,7 @@
 	unsigned int cl_scan_secs;
 	unsigned int cl_log_debug;
 	unsigned int cl_protocol;
+	unsigned int cl_timewarn_cs;
 };
 
 enum {
@@ -103,6 +104,7 @@
 	CLUSTER_ATTR_SCAN_SECS,
 	CLUSTER_ATTR_LOG_DEBUG,
 	CLUSTER_ATTR_PROTOCOL,
+	CLUSTER_ATTR_TIMEWARN_CS,
 };
 
 struct cluster_attribute {
@@ -162,6 +164,7 @@
 CLUSTER_ATTR(scan_secs, 1);
 CLUSTER_ATTR(log_debug, 0);
 CLUSTER_ATTR(protocol, 0);
+CLUSTER_ATTR(timewarn_cs, 1);
 
 static struct configfs_attribute *cluster_attrs[] = {
 	[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
@@ -174,6 +177,7 @@
 	[CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr,
 	[CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr,
 	[CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
+	[CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
 	NULL,
 };
 
@@ -429,6 +433,8 @@
 	cl->cl_toss_secs = dlm_config.ci_toss_secs;
 	cl->cl_scan_secs = dlm_config.ci_scan_secs;
 	cl->cl_log_debug = dlm_config.ci_log_debug;
+	cl->cl_protocol = dlm_config.ci_protocol;
+	cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
 
 	space_list = &sps->ss_group;
 	comm_list = &cms->cs_group;
@@ -748,9 +754,16 @@
 
 static struct space *get_space(char *name)
 {
+	struct config_item *i;
+
 	if (!space_list)
 		return NULL;
-	return to_space(config_group_find_obj(space_list, name));
+
+	down(&space_list->cg_subsys->su_sem);
+	i = config_group_find_obj(space_list, name);
+	up(&space_list->cg_subsys->su_sem);
+
+	return to_space(i);
 }
 
 static void put_space(struct space *sp)
@@ -776,20 +789,20 @@
 			if (cm->nodeid != nodeid)
 				continue;
 			found = 1;
+			config_item_get(i);
 			break;
 		} else {
 			if (!cm->addr_count ||
 			    memcmp(cm->addr[0], addr, sizeof(*addr)))
 				continue;
 			found = 1;
+			config_item_get(i);
 			break;
 		}
 	}
 	up(&clusters_root.subsys.su_sem);
 
-	if (found)
-		config_item_get(i);
-	else
+	if (!found)
 		cm = NULL;
 	return cm;
 }
@@ -909,6 +922,7 @@
 #define DEFAULT_SCAN_SECS          5
 #define DEFAULT_LOG_DEBUG          0
 #define DEFAULT_PROTOCOL           0
+#define DEFAULT_TIMEWARN_CS      500 /* 5 sec = 500 centiseconds */
 
 struct dlm_config_info dlm_config = {
 	.ci_tcp_port = DEFAULT_TCP_PORT,
@@ -920,6 +934,7 @@
 	.ci_toss_secs = DEFAULT_TOSS_SECS,
 	.ci_scan_secs = DEFAULT_SCAN_SECS,
 	.ci_log_debug = DEFAULT_LOG_DEBUG,
-	.ci_protocol = DEFAULT_PROTOCOL
+	.ci_protocol = DEFAULT_PROTOCOL,
+	.ci_timewarn_cs = DEFAULT_TIMEWARN_CS
 };
 
diff --git a/fs/dlm/config.h b/fs/dlm/config.h
index 967cc3d..a3170fe 100644
--- a/fs/dlm/config.h
+++ b/fs/dlm/config.h
@@ -27,6 +27,7 @@
 	int ci_scan_secs;
 	int ci_log_debug;
 	int ci_protocol;
+	int ci_timewarn_cs;
 };
 
 extern struct dlm_config_info dlm_config;
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 61ba670..12c3bfd 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -17,6 +17,7 @@
 #include <linux/debugfs.h>
 
 #include "dlm_internal.h"
+#include "lock.h"
 
 #define DLM_DEBUG_BUF_LEN 4096
 static char debug_buf[DLM_DEBUG_BUF_LEN];
@@ -26,6 +27,8 @@
 
 struct rsb_iter {
 	int entry;
+	int locks;
+	int header;
 	struct dlm_ls *ls;
 	struct list_head *next;
 	struct dlm_rsb *rsb;
@@ -57,8 +60,8 @@
 	}
 }
 
-static void print_lock(struct seq_file *s, struct dlm_lkb *lkb,
-		       struct dlm_rsb *res)
+static void print_resource_lock(struct seq_file *s, struct dlm_lkb *lkb,
+				struct dlm_rsb *res)
 {
 	seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
 
@@ -85,6 +88,8 @@
 	struct dlm_lkb *lkb;
 	int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
 
+	lock_rsb(res);
+
 	seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
 	for (i = 0; i < res->res_length; i++) {
 		if (isprint(res->res_name[i]))
@@ -129,15 +134,15 @@
 	/* Print the locks attached to this resource */
 	seq_printf(s, "Granted Queue\n");
 	list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
-		print_lock(s, lkb, res);
+		print_resource_lock(s, lkb, res);
 
 	seq_printf(s, "Conversion Queue\n");
 	list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
-		print_lock(s, lkb, res);
+		print_resource_lock(s, lkb, res);
 
 	seq_printf(s, "Waiting Queue\n");
 	list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
-		print_lock(s, lkb, res);
+		print_resource_lock(s, lkb, res);
 
 	if (list_empty(&res->res_lookup))
 		goto out;
@@ -151,6 +156,61 @@
 		seq_printf(s, "\n");
 	}
  out:
+	unlock_rsb(res);
+	return 0;
+}
+
+static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r)
+{
+	struct dlm_user_args *ua;
+	unsigned int waiting = 0;
+	uint64_t xid = 0;
+
+	if (lkb->lkb_flags & DLM_IFL_USER) {
+		ua = (struct dlm_user_args *) lkb->lkb_astparam;
+		if (ua)
+			xid = ua->xid;
+	}
+
+	if (lkb->lkb_timestamp)
+		waiting = jiffies_to_msecs(jiffies - lkb->lkb_timestamp);
+
+	/* id nodeid remid pid xid exflags flags sts grmode rqmode time_ms
+	   r_nodeid r_len r_name */
+
+	seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %u %u %d \"%s\"\n",
+		   lkb->lkb_id,
+		   lkb->lkb_nodeid,
+		   lkb->lkb_remid,
+		   lkb->lkb_ownpid,
+		   (unsigned long long)xid,
+		   lkb->lkb_exflags,
+		   lkb->lkb_flags,
+		   lkb->lkb_status,
+		   lkb->lkb_grmode,
+		   lkb->lkb_rqmode,
+		   waiting,
+		   r->res_nodeid,
+		   r->res_length,
+		   r->res_name);
+}
+
+static int print_locks(struct dlm_rsb *r, struct seq_file *s)
+{
+	struct dlm_lkb *lkb;
+
+	lock_rsb(r);
+
+	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
+		print_lock(s, lkb, r);
+
+	list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
+		print_lock(s, lkb, r);
+
+	list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
+		print_lock(s, lkb, r);
+
+	unlock_rsb(r);
 	return 0;
 }
 
@@ -166,6 +226,9 @@
 			read_lock(&ls->ls_rsbtbl[i].lock);
 			if (!list_empty(&ls->ls_rsbtbl[i].list)) {
 				ri->next = ls->ls_rsbtbl[i].list.next;
+				ri->rsb = list_entry(ri->next, struct dlm_rsb,
+							res_hashchain);
+				dlm_hold_rsb(ri->rsb);
 				read_unlock(&ls->ls_rsbtbl[i].lock);
 				break;
 			}
@@ -176,6 +239,7 @@
 		if (ri->entry >= ls->ls_rsbtbl_size)
 			return 1;
 	} else {
+		struct dlm_rsb *old = ri->rsb;
 		i = ri->entry;
 		read_lock(&ls->ls_rsbtbl[i].lock);
 		ri->next = ri->next->next;
@@ -184,11 +248,14 @@
 			ri->next = NULL;
 			ri->entry++;
 			read_unlock(&ls->ls_rsbtbl[i].lock);
+			dlm_put_rsb(old);
 			goto top;
                 }
+		ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
+		dlm_hold_rsb(ri->rsb);
 		read_unlock(&ls->ls_rsbtbl[i].lock);
+		dlm_put_rsb(old);
 	}
-	ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
 
 	return 0;
 }
@@ -202,7 +269,7 @@
 {
 	struct rsb_iter *ri;
 
-	ri = kmalloc(sizeof *ri, GFP_KERNEL);
+	ri = kzalloc(sizeof *ri, GFP_KERNEL);
 	if (!ri)
 		return NULL;
 
@@ -260,7 +327,17 @@
 {
 	struct rsb_iter *ri = iter_ptr;
 
-	print_resource(ri->rsb, file);
+	if (ri->locks) {
+		if (ri->header) {
+			seq_printf(file, "id nodeid remid pid xid exflags flags "
+					 "sts grmode rqmode time_ms r_nodeid "
+					 "r_len r_name\n");
+			ri->header = 0;
+		}
+		print_locks(ri->rsb, file);
+	} else {
+		print_resource(ri->rsb, file);
+	}
 
 	return 0;
 }
@@ -296,6 +373,83 @@
 };
 
 /*
+ * Dump state in compact per-lock listing
+ */
+
+static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos)
+{
+	struct rsb_iter *ri;
+
+	ri = kzalloc(sizeof *ri, GFP_KERNEL);
+	if (!ri)
+		return NULL;
+
+	ri->ls = ls;
+	ri->entry = 0;
+	ri->next = NULL;
+	ri->locks = 1;
+
+	if (*pos == 0)
+		ri->header = 1;
+
+	if (rsb_iter_next(ri)) {
+		rsb_iter_free(ri);
+		return NULL;
+	}
+
+	return ri;
+}
+
+static void *locks_seq_start(struct seq_file *file, loff_t *pos)
+{
+	struct rsb_iter *ri;
+	loff_t n = *pos;
+
+	ri = locks_iter_init(file->private, pos);
+	if (!ri)
+		return NULL;
+
+	while (n--) {
+		if (rsb_iter_next(ri)) {
+			rsb_iter_free(ri);
+			return NULL;
+		}
+	}
+
+	return ri;
+}
+
+static struct seq_operations locks_seq_ops = {
+	.start = locks_seq_start,
+	.next  = rsb_seq_next,
+	.stop  = rsb_seq_stop,
+	.show  = rsb_seq_show,
+};
+
+static int locks_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	int ret;
+
+	ret = seq_open(file, &locks_seq_ops);
+	if (ret)
+		return ret;
+
+	seq = file->private_data;
+	seq->private = inode->i_private;
+
+	return 0;
+}
+
+static const struct file_operations locks_fops = {
+	.owner   = THIS_MODULE,
+	.open    = locks_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
+
+/*
  * dump lkb's on the ls_waiters list
  */
 
@@ -362,6 +516,20 @@
 		return -ENOMEM;
 	}
 
+	memset(name, 0, sizeof(name));
+	snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name);
+
+	ls->ls_debug_locks_dentry = debugfs_create_file(name,
+							S_IFREG | S_IRUGO,
+							dlm_root,
+							ls,
+							&locks_fops);
+	if (!ls->ls_debug_locks_dentry) {
+		debugfs_remove(ls->ls_debug_waiters_dentry);
+		debugfs_remove(ls->ls_debug_rsb_dentry);
+		return -ENOMEM;
+	}
+
 	return 0;
 }
 
@@ -371,6 +539,8 @@
 		debugfs_remove(ls->ls_debug_rsb_dentry);
 	if (ls->ls_debug_waiters_dentry)
 		debugfs_remove(ls->ls_debug_waiters_dentry);
+	if (ls->ls_debug_locks_dentry)
+		debugfs_remove(ls->ls_debug_locks_dentry);
 }
 
 int dlm_register_debugfs(void)
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 30994d6..74901e9 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -151,6 +151,7 @@
 	void			*bastaddr;
 	int			mode;
 	struct dlm_lksb		*lksb;
+	unsigned long		timeout;
 };
 
 
@@ -213,6 +214,9 @@
 #define DLM_IFL_OVERLAP_UNLOCK  0x00080000
 #define DLM_IFL_OVERLAP_CANCEL  0x00100000
 #define DLM_IFL_ENDOFLIFE	0x00200000
+#define DLM_IFL_WATCH_TIMEWARN	0x00400000
+#define DLM_IFL_TIMEOUT_CANCEL	0x00800000
+#define DLM_IFL_DEADLOCK_CANCEL	0x01000000
 #define DLM_IFL_USER		0x00000001
 #define DLM_IFL_ORPHAN		0x00000002
 
@@ -243,6 +247,9 @@
 	struct list_head	lkb_wait_reply;	/* waiting for remote reply */
 	struct list_head	lkb_astqueue;	/* need ast to be sent */
 	struct list_head	lkb_ownqueue;	/* list of locks for a process */
+	struct list_head	lkb_time_list;
+	unsigned long		lkb_timestamp;
+	unsigned long		lkb_timeout_cs;
 
 	char			*lkb_lvbptr;
 	struct dlm_lksb		*lkb_lksb;      /* caller's status block */
@@ -447,12 +454,16 @@
 	struct mutex		ls_orphans_mutex;
 	struct list_head	ls_orphans;
 
+	struct mutex		ls_timeout_mutex;
+	struct list_head	ls_timeout;
+
 	struct list_head	ls_nodes;	/* current nodes in ls */
 	struct list_head	ls_nodes_gone;	/* dead node list, recovery */
 	int			ls_num_nodes;	/* number of nodes in ls */
 	int			ls_low_nodeid;
 	int			ls_total_weight;
 	int			*ls_node_array;
+	gfp_t			ls_allocation;
 
 	struct dlm_rsb		ls_stub_rsb;	/* for returning errors */
 	struct dlm_lkb		ls_stub_lkb;	/* for returning errors */
@@ -460,9 +471,12 @@
 
 	struct dentry		*ls_debug_rsb_dentry; /* debugfs */
 	struct dentry		*ls_debug_waiters_dentry; /* debugfs */
+	struct dentry		*ls_debug_locks_dentry; /* debugfs */
 
 	wait_queue_head_t	ls_uevent_wait;	/* user part of join/leave */
 	int			ls_uevent_result;
+	struct completion	ls_members_done;
+	int			ls_members_result;
 
 	struct miscdevice       ls_device;
 
@@ -472,6 +486,7 @@
 	struct task_struct	*ls_recoverd_task;
 	struct mutex		ls_recoverd_active;
 	spinlock_t		ls_recover_lock;
+	unsigned long		ls_recover_begin; /* jiffies timestamp */
 	uint32_t		ls_recover_status; /* DLM_RS_ */
 	uint64_t		ls_recover_seq;
 	struct dlm_recover	*ls_recover_args;
@@ -501,6 +516,7 @@
 #define LSFL_RCOM_READY		3
 #define LSFL_RCOM_WAIT		4
 #define LSFL_UEVENT_WAIT	5
+#define LSFL_TIMEWARN		6
 
 /* much of this is just saving user space pointers associated with the
    lock that we pass back to the user lib with an ast */
@@ -518,6 +534,7 @@
 	void __user		*castaddr;
 	void __user		*bastparam;
 	void __user		*bastaddr;
+	uint64_t		xid;
 };
 
 #define DLM_PROC_FLAGS_CLOSING 1
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index d8d6e72..b455919 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -82,10 +82,13 @@
 static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb);
 static int send_remove(struct dlm_rsb *r);
 static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
+static int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
 static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
 				    struct dlm_message *ms);
 static int receive_extralen(struct dlm_message *ms);
 static void do_purge(struct dlm_ls *ls, int nodeid, int pid);
+static void del_timeout(struct dlm_lkb *lkb);
+void dlm_timeout_warn(struct dlm_lkb *lkb);
 
 /*
  * Lock compatibilty matrix - thanks Steve
@@ -194,17 +197,17 @@
 
 /* Threads cannot use the lockspace while it's being recovered */
 
-static inline void lock_recovery(struct dlm_ls *ls)
+static inline void dlm_lock_recovery(struct dlm_ls *ls)
 {
 	down_read(&ls->ls_in_recovery);
 }
 
-static inline void unlock_recovery(struct dlm_ls *ls)
+void dlm_unlock_recovery(struct dlm_ls *ls)
 {
 	up_read(&ls->ls_in_recovery);
 }
 
-static inline int lock_recovery_try(struct dlm_ls *ls)
+int dlm_lock_recovery_try(struct dlm_ls *ls)
 {
 	return down_read_trylock(&ls->ls_in_recovery);
 }
@@ -286,8 +289,22 @@
 	if (is_master_copy(lkb))
 		return;
 
+	del_timeout(lkb);
+
 	DLM_ASSERT(lkb->lkb_lksb, dlm_print_lkb(lkb););
 
+	/* if the operation was a cancel, then return -DLM_ECANCEL, if a
+	   timeout caused the cancel then return -ETIMEDOUT */
+	if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_TIMEOUT_CANCEL)) {
+		lkb->lkb_flags &= ~DLM_IFL_TIMEOUT_CANCEL;
+		rv = -ETIMEDOUT;
+	}
+
+	if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_DEADLOCK_CANCEL)) {
+		lkb->lkb_flags &= ~DLM_IFL_DEADLOCK_CANCEL;
+		rv = -EDEADLK;
+	}
+
 	lkb->lkb_lksb->sb_status = rv;
 	lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags;
 
@@ -581,6 +598,7 @@
 	kref_init(&lkb->lkb_ref);
 	INIT_LIST_HEAD(&lkb->lkb_ownqueue);
 	INIT_LIST_HEAD(&lkb->lkb_rsb_lookup);
+	INIT_LIST_HEAD(&lkb->lkb_time_list);
 
 	get_random_bytes(&bucket, sizeof(bucket));
 	bucket &= (ls->ls_lkbtbl_size - 1);
@@ -985,15 +1003,136 @@
 {
 	int i;
 
-	if (dlm_locking_stopped(ls))
-		return;
-
 	for (i = 0; i < ls->ls_rsbtbl_size; i++) {
 		shrink_bucket(ls, i);
+		if (dlm_locking_stopped(ls))
+			break;
 		cond_resched();
 	}
 }
 
+static void add_timeout(struct dlm_lkb *lkb)
+{
+	struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+
+	if (is_master_copy(lkb)) {
+		lkb->lkb_timestamp = jiffies;
+		return;
+	}
+
+	if (test_bit(LSFL_TIMEWARN, &ls->ls_flags) &&
+	    !(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
+		lkb->lkb_flags |= DLM_IFL_WATCH_TIMEWARN;
+		goto add_it;
+	}
+	if (lkb->lkb_exflags & DLM_LKF_TIMEOUT)
+		goto add_it;
+	return;
+
+ add_it:
+	DLM_ASSERT(list_empty(&lkb->lkb_time_list), dlm_print_lkb(lkb););
+	mutex_lock(&ls->ls_timeout_mutex);
+	hold_lkb(lkb);
+	lkb->lkb_timestamp = jiffies;
+	list_add_tail(&lkb->lkb_time_list, &ls->ls_timeout);
+	mutex_unlock(&ls->ls_timeout_mutex);
+}
+
+static void del_timeout(struct dlm_lkb *lkb)
+{
+	struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+
+	mutex_lock(&ls->ls_timeout_mutex);
+	if (!list_empty(&lkb->lkb_time_list)) {
+		list_del_init(&lkb->lkb_time_list);
+		unhold_lkb(lkb);
+	}
+	mutex_unlock(&ls->ls_timeout_mutex);
+}
+
+/* FIXME: is it safe to look at lkb_exflags, lkb_flags, lkb_timestamp, and
+   lkb_lksb_timeout without lock_rsb?  Note: we can't lock timeout_mutex
+   and then lock rsb because of lock ordering in add_timeout.  We may need
+   to specify some special timeout-related bits in the lkb that are just to
+   be accessed under the timeout_mutex. */
+
+void dlm_scan_timeout(struct dlm_ls *ls)
+{
+	struct dlm_rsb *r;
+	struct dlm_lkb *lkb;
+	int do_cancel, do_warn;
+
+	for (;;) {
+		if (dlm_locking_stopped(ls))
+			break;
+
+		do_cancel = 0;
+		do_warn = 0;
+		mutex_lock(&ls->ls_timeout_mutex);
+		list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) {
+
+			if ((lkb->lkb_exflags & DLM_LKF_TIMEOUT) &&
+			    time_after_eq(jiffies, lkb->lkb_timestamp +
+					  lkb->lkb_timeout_cs * HZ/100))
+				do_cancel = 1;
+
+			if ((lkb->lkb_flags & DLM_IFL_WATCH_TIMEWARN) &&
+			    time_after_eq(jiffies, lkb->lkb_timestamp +
+				   	   dlm_config.ci_timewarn_cs * HZ/100))
+				do_warn = 1;
+
+			if (!do_cancel && !do_warn)
+				continue;
+			hold_lkb(lkb);
+			break;
+		}
+		mutex_unlock(&ls->ls_timeout_mutex);
+
+		if (!do_cancel && !do_warn)
+			break;
+
+		r = lkb->lkb_resource;
+		hold_rsb(r);
+		lock_rsb(r);
+
+		if (do_warn) {
+			/* clear flag so we only warn once */
+			lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
+			if (!(lkb->lkb_exflags & DLM_LKF_TIMEOUT))
+				del_timeout(lkb);
+			dlm_timeout_warn(lkb);
+		}
+
+		if (do_cancel) {
+			log_debug(ls, "timeout cancel %x node %d %s",
+				  lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+			lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
+			lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL;
+			del_timeout(lkb);
+			_cancel_lock(r, lkb);
+		}
+
+		unlock_rsb(r);
+		unhold_rsb(r);
+		dlm_put_lkb(lkb);
+	}
+}
+
+/* This is only called by dlm_recoverd, and we rely on dlm_ls_stop() stopping
+   dlm_recoverd before checking/setting ls_recover_begin. */
+
+void dlm_adjust_timeouts(struct dlm_ls *ls)
+{
+	struct dlm_lkb *lkb;
+	long adj = jiffies - ls->ls_recover_begin;
+
+	ls->ls_recover_begin = 0;
+	mutex_lock(&ls->ls_timeout_mutex);
+	list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list)
+		lkb->lkb_timestamp += adj;
+	mutex_unlock(&ls->ls_timeout_mutex);
+}
+
 /* lkb is master or local copy */
 
 static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -1275,10 +1414,8 @@
  * queue for one resource.  The granted mode of each lock blocks the requested
  * mode of the other lock."
  *
- * Part 2: if the granted mode of lkb is preventing the first lkb in the
- * convert queue from being granted, then demote lkb (set grmode to NL).
- * This second form requires that we check for conv-deadlk even when
- * now == 0 in _can_be_granted().
+ * Part 2: if the granted mode of lkb is preventing an earlier lkb in the
+ * convert queue from being granted, then deadlk/demote lkb.
  *
  * Example:
  * Granted Queue: empty
@@ -1287,41 +1424,52 @@
  *
  * The first lock can't be granted because of the granted mode of the second
  * lock and the second lock can't be granted because it's not first in the
- * list.  We demote the granted mode of the second lock (the lkb passed to this
- * function).
+ * list.  We either cancel lkb's conversion (PR->EX) and return EDEADLK, or we
+ * demote the granted mode of lkb (from PR to NL) if it has the CONVDEADLK
+ * flag set and return DEMOTED in the lksb flags.
  *
- * After the resolution, the "grant pending" function needs to go back and try
- * to grant locks on the convert queue again since the first lock can now be
- * granted.
+ * Originally, this function detected conv-deadlk in a more limited scope:
+ * - if !modes_compat(lkb1, lkb2) && !modes_compat(lkb2, lkb1), or
+ * - if lkb1 was the first entry in the queue (not just earlier), and was
+ *   blocked by the granted mode of lkb2, and there was nothing on the
+ *   granted queue preventing lkb1 from being granted immediately, i.e.
+ *   lkb2 was the only thing preventing lkb1 from being granted.
+ *
+ * That second condition meant we'd only say there was conv-deadlk if
+ * resolving it (by demotion) would lead to the first lock on the convert
+ * queue being granted right away.  It allowed conversion deadlocks to exist
+ * between locks on the convert queue while they couldn't be granted anyway.
+ *
+ * Now, we detect and take action on conversion deadlocks immediately when
+ * they're created, even if they may not be immediately consequential.  If
+ * lkb1 exists anywhere in the convert queue and lkb2 comes in with a granted
+ * mode that would prevent lkb1's conversion from being granted, we do a
+ * deadlk/demote on lkb2 right away and don't let it onto the convert queue.
+ * I think this means that the lkb_is_ahead condition below should always
+ * be zero, i.e. there will never be conv-deadlk between two locks that are
+ * both already on the convert queue.
  */
 
-static int conversion_deadlock_detect(struct dlm_rsb *rsb, struct dlm_lkb *lkb)
+static int conversion_deadlock_detect(struct dlm_rsb *r, struct dlm_lkb *lkb2)
 {
-	struct dlm_lkb *this, *first = NULL, *self = NULL;
+	struct dlm_lkb *lkb1;
+	int lkb_is_ahead = 0;
 
-	list_for_each_entry(this, &rsb->res_convertqueue, lkb_statequeue) {
-		if (!first)
-			first = this;
-		if (this == lkb) {
-			self = lkb;
+	list_for_each_entry(lkb1, &r->res_convertqueue, lkb_statequeue) {
+		if (lkb1 == lkb2) {
+			lkb_is_ahead = 1;
 			continue;
 		}
 
-		if (!modes_compat(this, lkb) && !modes_compat(lkb, this))
-			return 1;
+		if (!lkb_is_ahead) {
+			if (!modes_compat(lkb2, lkb1))
+				return 1;
+		} else {
+			if (!modes_compat(lkb2, lkb1) &&
+			    !modes_compat(lkb1, lkb2))
+				return 1;
+		}
 	}
-
-	/* if lkb is on the convert queue and is preventing the first
-	   from being granted, then there's deadlock and we demote lkb.
-	   multiple converting locks may need to do this before the first
-	   converting lock can be granted. */
-
-	if (self && self != first) {
-		if (!modes_compat(lkb, first) &&
-		    !queue_conflict(&rsb->res_grantqueue, first))
-			return 1;
-	}
-
 	return 0;
 }
 
@@ -1450,42 +1598,57 @@
 	if (!now && !conv && list_empty(&r->res_convertqueue) &&
 	    first_in_list(lkb, &r->res_waitqueue))
 		return 1;
-
  out:
-	/*
-	 * The following, enabled by CONVDEADLK, departs from VMS.
-	 */
-
-	if (conv && (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) &&
-	    conversion_deadlock_detect(r, lkb)) {
-		lkb->lkb_grmode = DLM_LOCK_NL;
-		lkb->lkb_sbflags |= DLM_SBF_DEMOTED;
-	}
-
 	return 0;
 }
 
-/*
- * The ALTPR and ALTCW flags aren't traditional lock manager flags, but are a
- * simple way to provide a big optimization to applications that can use them.
- */
-
-static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
+static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
+			  int *err)
 {
-	uint32_t flags = lkb->lkb_exflags;
 	int rv;
 	int8_t alt = 0, rqmode = lkb->lkb_rqmode;
+	int8_t is_convert = (lkb->lkb_grmode != DLM_LOCK_IV);
+
+	if (err)
+		*err = 0;
 
 	rv = _can_be_granted(r, lkb, now);
 	if (rv)
 		goto out;
 
-	if (lkb->lkb_sbflags & DLM_SBF_DEMOTED)
-		goto out;
+	/*
+	 * The CONVDEADLK flag is non-standard and tells the dlm to resolve
+	 * conversion deadlocks by demoting grmode to NL, otherwise the dlm
+	 * cancels one of the locks.
+	 */
 
-	if (rqmode != DLM_LOCK_PR && flags & DLM_LKF_ALTPR)
+	if (is_convert && can_be_queued(lkb) &&
+	    conversion_deadlock_detect(r, lkb)) {
+		if (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) {
+			lkb->lkb_grmode = DLM_LOCK_NL;
+			lkb->lkb_sbflags |= DLM_SBF_DEMOTED;
+		} else if (!(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
+			if (err)
+				*err = -EDEADLK;
+			else {
+				log_print("can_be_granted deadlock %x now %d",
+					  lkb->lkb_id, now);
+				dlm_dump_rsb(r);
+			}
+		}
+		goto out;
+	}
+
+	/*
+	 * The ALTPR and ALTCW flags are non-standard and tell the dlm to try
+	 * to grant a request in a mode other than the normal rqmode.  It's a
+	 * simple way to provide a big optimization to applications that can
+	 * use them.
+	 */
+
+	if (rqmode != DLM_LOCK_PR && (lkb->lkb_exflags & DLM_LKF_ALTPR))
 		alt = DLM_LOCK_PR;
-	else if (rqmode != DLM_LOCK_CW && flags & DLM_LKF_ALTCW)
+	else if (rqmode != DLM_LOCK_CW && (lkb->lkb_exflags & DLM_LKF_ALTCW))
 		alt = DLM_LOCK_CW;
 
 	if (alt) {
@@ -1500,10 +1663,20 @@
 	return rv;
 }
 
+/* FIXME: I don't think that can_be_granted() can/will demote or find deadlock
+   for locks pending on the convert list.  Once verified (watch for these
+   log_prints), we should be able to just call _can_be_granted() and not
+   bother with the demote/deadlk cases here (and there's no easy way to deal
+   with a deadlk here, we'd have to generate something like grant_lock with
+   the deadlk error.) */
+
+/* returns the highest requested mode of all blocked conversions */
+
 static int grant_pending_convert(struct dlm_rsb *r, int high)
 {
 	struct dlm_lkb *lkb, *s;
 	int hi, demoted, quit, grant_restart, demote_restart;
+	int deadlk;
 
 	quit = 0;
  restart:
@@ -1513,14 +1686,29 @@
 
 	list_for_each_entry_safe(lkb, s, &r->res_convertqueue, lkb_statequeue) {
 		demoted = is_demoted(lkb);
-		if (can_be_granted(r, lkb, 0)) {
+		deadlk = 0;
+
+		if (can_be_granted(r, lkb, 0, &deadlk)) {
 			grant_lock_pending(r, lkb);
 			grant_restart = 1;
-		} else {
-			hi = max_t(int, lkb->lkb_rqmode, hi);
-			if (!demoted && is_demoted(lkb))
-				demote_restart = 1;
+			continue;
 		}
+
+		if (!demoted && is_demoted(lkb)) {
+			log_print("WARN: pending demoted %x node %d %s",
+				  lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+			demote_restart = 1;
+			continue;
+		}
+
+		if (deadlk) {
+			log_print("WARN: pending deadlock %x node %d %s",
+				  lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+			dlm_dump_rsb(r);
+			continue;
+		}
+
+		hi = max_t(int, lkb->lkb_rqmode, hi);
 	}
 
 	if (grant_restart)
@@ -1538,7 +1726,7 @@
 	struct dlm_lkb *lkb, *s;
 
 	list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) {
-		if (can_be_granted(r, lkb, 0))
+		if (can_be_granted(r, lkb, 0, NULL))
 			grant_lock_pending(r, lkb);
                 else
 			high = max_t(int, lkb->lkb_rqmode, high);
@@ -1733,7 +1921,7 @@
 }
 
 static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
-			 int namelen, uint32_t parent_lkid, void *ast,
+			 int namelen, unsigned long timeout_cs, void *ast,
 			 void *astarg, void *bast, struct dlm_args *args)
 {
 	int rv = -EINVAL;
@@ -1776,10 +1964,6 @@
 	if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr)
 		goto out;
 
-	/* parent/child locks not yet supported */
-	if (parent_lkid)
-		goto out;
-
 	if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid)
 		goto out;
 
@@ -1791,6 +1975,7 @@
 	args->astaddr = ast;
 	args->astparam = (long) astarg;
 	args->bastaddr = bast;
+	args->timeout = timeout_cs;
 	args->mode = mode;
 	args->lksb = lksb;
 	rv = 0;
@@ -1845,6 +2030,7 @@
 	lkb->lkb_lksb = args->lksb;
 	lkb->lkb_lvbptr = args->lksb->sb_lvbptr;
 	lkb->lkb_ownpid = (int) current->pid;
+	lkb->lkb_timeout_cs = args->timeout;
 	rv = 0;
  out:
 	return rv;
@@ -1903,6 +2089,9 @@
 		if (is_overlap(lkb))
 			goto out;
 
+		/* don't let scand try to do a cancel */
+		del_timeout(lkb);
+
 		if (lkb->lkb_flags & DLM_IFL_RESEND) {
 			lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
 			rv = -EBUSY;
@@ -1934,6 +2123,9 @@
 		if (is_overlap_unlock(lkb))
 			goto out;
 
+		/* don't let scand try to do a cancel */
+		del_timeout(lkb);
+
 		if (lkb->lkb_flags & DLM_IFL_RESEND) {
 			lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
 			rv = -EBUSY;
@@ -1984,7 +2176,7 @@
 {
 	int error = 0;
 
-	if (can_be_granted(r, lkb, 1)) {
+	if (can_be_granted(r, lkb, 1, NULL)) {
 		grant_lock(r, lkb);
 		queue_cast(r, lkb, 0);
 		goto out;
@@ -1994,6 +2186,7 @@
 		error = -EINPROGRESS;
 		add_lkb(r, lkb, DLM_LKSTS_WAITING);
 		send_blocking_asts(r, lkb);
+		add_timeout(lkb);
 		goto out;
 	}
 
@@ -2009,16 +2202,32 @@
 static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
 	int error = 0;
+	int deadlk = 0;
 
 	/* changing an existing lock may allow others to be granted */
 
-	if (can_be_granted(r, lkb, 1)) {
+	if (can_be_granted(r, lkb, 1, &deadlk)) {
 		grant_lock(r, lkb);
 		queue_cast(r, lkb, 0);
 		grant_pending_locks(r);
 		goto out;
 	}
 
+	/* can_be_granted() detected that this lock would block in a conversion
+	   deadlock, so we leave it on the granted queue and return EDEADLK in
+	   the ast for the convert. */
+
+	if (deadlk) {
+		/* it's left on the granted queue */
+		log_debug(r->res_ls, "deadlock %x node %d sts%d g%d r%d %s",
+			  lkb->lkb_id, lkb->lkb_nodeid, lkb->lkb_status,
+			  lkb->lkb_grmode, lkb->lkb_rqmode, r->res_name);
+		revert_lock(r, lkb);
+		queue_cast(r, lkb, -EDEADLK);
+		error = -EDEADLK;
+		goto out;
+	}
+
 	/* is_demoted() means the can_be_granted() above set the grmode
 	   to NL, and left us on the granted queue.  This auto-demotion
 	   (due to CONVDEADLK) might mean other locks, and/or this lock, are
@@ -2041,6 +2250,7 @@
 		del_lkb(r, lkb);
 		add_lkb(r, lkb, DLM_LKSTS_CONVERT);
 		send_blocking_asts(r, lkb);
+		add_timeout(lkb);
 		goto out;
 	}
 
@@ -2274,7 +2484,7 @@
 	if (!ls)
 		return -EINVAL;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	if (convert)
 		error = find_lkb(ls, lksb->sb_lkid, &lkb);
@@ -2284,7 +2494,7 @@
 	if (error)
 		goto out;
 
-	error = set_lock_args(mode, lksb, flags, namelen, parent_lkid, ast,
+	error = set_lock_args(mode, lksb, flags, namelen, 0, ast,
 			      astarg, bast, &args);
 	if (error)
 		goto out_put;
@@ -2299,10 +2509,10 @@
  out_put:
 	if (convert || error)
 		__put_lkb(ls, lkb);
-	if (error == -EAGAIN)
+	if (error == -EAGAIN || error == -EDEADLK)
 		error = 0;
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	dlm_put_lockspace(ls);
 	return error;
 }
@@ -2322,7 +2532,7 @@
 	if (!ls)
 		return -EINVAL;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	error = find_lkb(ls, lkid, &lkb);
 	if (error)
@@ -2344,7 +2554,7 @@
  out_put:
 	dlm_put_lkb(lkb);
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	dlm_put_lockspace(ls);
 	return error;
 }
@@ -2384,7 +2594,7 @@
 	   pass into lowcomms_commit and a message buffer (mb) that we
 	   write our data into */
 
-	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb);
+	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb);
 	if (!mh)
 		return -ENOBUFS;
 
@@ -3111,9 +3321,10 @@
 		lkb->lkb_remid = ms->m_lkid;
 		if (is_altmode(lkb))
 			munge_altmode(lkb, ms);
-		if (result)
+		if (result) {
 			add_lkb(r, lkb, DLM_LKSTS_WAITING);
-		else {
+			add_timeout(lkb);
+		} else {
 			grant_lock_pc(r, lkb, ms);
 			queue_cast(r, lkb, 0);
 		}
@@ -3172,6 +3383,12 @@
 		queue_cast(r, lkb, -EAGAIN);
 		break;
 
+	case -EDEADLK:
+		receive_flags_reply(lkb, ms);
+		revert_lock_pc(r, lkb);
+		queue_cast(r, lkb, -EDEADLK);
+		break;
+
 	case -EINPROGRESS:
 		/* convert was queued on remote master */
 		receive_flags_reply(lkb, ms);
@@ -3179,6 +3396,7 @@
 			munge_demoted(lkb, ms);
 		del_lkb(r, lkb);
 		add_lkb(r, lkb, DLM_LKSTS_CONVERT);
+		add_timeout(lkb);
 		break;
 
 	case 0:
@@ -3298,8 +3516,7 @@
 	case -DLM_ECANCEL:
 		receive_flags_reply(lkb, ms);
 		revert_lock_pc(r, lkb);
-		if (ms->m_result)
-			queue_cast(r, lkb, -DLM_ECANCEL);
+		queue_cast(r, lkb, -DLM_ECANCEL);
 		break;
 	case 0:
 		break;
@@ -3424,7 +3641,7 @@
 			}
 		}
 
-		if (lock_recovery_try(ls))
+		if (dlm_lock_recovery_try(ls))
 			break;
 		schedule();
 	}
@@ -3503,7 +3720,7 @@
 		log_error(ls, "unknown message type %d", ms->m_type);
 	}
 
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
  out:
 	dlm_put_lockspace(ls);
 	dlm_astd_wake();
@@ -4034,13 +4251,13 @@
 
 int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
 		     int mode, uint32_t flags, void *name, unsigned int namelen,
-		     uint32_t parent_lkid)
+		     unsigned long timeout_cs)
 {
 	struct dlm_lkb *lkb;
 	struct dlm_args args;
 	int error;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	error = create_lkb(ls, &lkb);
 	if (error) {
@@ -4062,7 +4279,7 @@
 	   When DLM_IFL_USER is set, the dlm knows that this is a userspace
 	   lock and that lkb_astparam is the dlm_user_args structure. */
 
-	error = set_lock_args(mode, &ua->lksb, flags, namelen, parent_lkid,
+	error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs,
 			      DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
 	lkb->lkb_flags |= DLM_IFL_USER;
 	ua->old_mode = DLM_LOCK_IV;
@@ -4094,19 +4311,20 @@
 	list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks);
 	spin_unlock(&ua->proc->locks_spin);
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	return error;
 }
 
 int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
-		     int mode, uint32_t flags, uint32_t lkid, char *lvb_in)
+		     int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
+		     unsigned long timeout_cs)
 {
 	struct dlm_lkb *lkb;
 	struct dlm_args args;
 	struct dlm_user_args *ua;
 	int error;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	error = find_lkb(ls, lkid, &lkb);
 	if (error)
@@ -4127,6 +4345,7 @@
 	if (lvb_in && ua->lksb.sb_lvbptr)
 		memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN);
 
+	ua->xid = ua_tmp->xid;
 	ua->castparam = ua_tmp->castparam;
 	ua->castaddr = ua_tmp->castaddr;
 	ua->bastparam = ua_tmp->bastparam;
@@ -4134,19 +4353,19 @@
 	ua->user_lksb = ua_tmp->user_lksb;
 	ua->old_mode = lkb->lkb_grmode;
 
-	error = set_lock_args(mode, &ua->lksb, flags, 0, 0, DLM_FAKE_USER_AST,
-			      ua, DLM_FAKE_USER_AST, &args);
+	error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs,
+			      DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
 	if (error)
 		goto out_put;
 
 	error = convert_lock(ls, lkb, &args);
 
-	if (error == -EINPROGRESS || error == -EAGAIN)
+	if (error == -EINPROGRESS || error == -EAGAIN || error == -EDEADLK)
 		error = 0;
  out_put:
 	dlm_put_lkb(lkb);
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	kfree(ua_tmp);
 	return error;
 }
@@ -4159,7 +4378,7 @@
 	struct dlm_user_args *ua;
 	int error;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	error = find_lkb(ls, lkid, &lkb);
 	if (error)
@@ -4194,7 +4413,7 @@
  out_put:
 	dlm_put_lkb(lkb);
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	kfree(ua_tmp);
 	return error;
 }
@@ -4207,7 +4426,7 @@
 	struct dlm_user_args *ua;
 	int error;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	error = find_lkb(ls, lkid, &lkb);
 	if (error)
@@ -4231,11 +4450,59 @@
  out_put:
 	dlm_put_lkb(lkb);
  out:
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 	kfree(ua_tmp);
 	return error;
 }
 
+int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid)
+{
+	struct dlm_lkb *lkb;
+	struct dlm_args args;
+	struct dlm_user_args *ua;
+	struct dlm_rsb *r;
+	int error;
+
+	dlm_lock_recovery(ls);
+
+	error = find_lkb(ls, lkid, &lkb);
+	if (error)
+		goto out;
+
+	ua = (struct dlm_user_args *)lkb->lkb_astparam;
+
+	error = set_unlock_args(flags, ua, &args);
+	if (error)
+		goto out_put;
+
+	/* same as cancel_lock(), but set DEADLOCK_CANCEL after lock_rsb */
+
+	r = lkb->lkb_resource;
+	hold_rsb(r);
+	lock_rsb(r);
+
+	error = validate_unlock_args(lkb, &args);
+	if (error)
+		goto out_r;
+	lkb->lkb_flags |= DLM_IFL_DEADLOCK_CANCEL;
+
+	error = _cancel_lock(r, lkb);
+ out_r:
+	unlock_rsb(r);
+	put_rsb(r);
+
+	if (error == -DLM_ECANCEL)
+		error = 0;
+	/* from validate_unlock_args() */
+	if (error == -EBUSY)
+		error = 0;
+ out_put:
+	dlm_put_lkb(lkb);
+ out:
+	dlm_unlock_recovery(ls);
+	return error;
+}
+
 /* lkb's that are removed from the waiters list by revert are just left on the
    orphans list with the granted orphan locks, to be freed by purge */
 
@@ -4314,12 +4581,13 @@
 {
 	struct dlm_lkb *lkb, *safe;
 
-	lock_recovery(ls);
+	dlm_lock_recovery(ls);
 
 	while (1) {
 		lkb = del_proc_lock(ls, proc);
 		if (!lkb)
 			break;
+		del_timeout(lkb);
 		if (lkb->lkb_exflags & DLM_LKF_PERSISTENT)
 			orphan_proc_lock(ls, lkb);
 		else
@@ -4347,7 +4615,7 @@
 	}
 
 	mutex_unlock(&ls->ls_clear_proc_locks);
-	unlock_recovery(ls);
+	dlm_unlock_recovery(ls);
 }
 
 static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
@@ -4429,12 +4697,12 @@
 	if (nodeid != dlm_our_nodeid()) {
 		error = send_purge(ls, nodeid, pid);
 	} else {
-		lock_recovery(ls);
+		dlm_lock_recovery(ls);
 		if (pid == current->pid)
 			purge_proc_locks(ls, proc);
 		else
 			do_purge(ls, nodeid, pid);
-		unlock_recovery(ls);
+		dlm_unlock_recovery(ls);
 	}
 	return error;
 }
diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h
index 64fc4ec..1720313 100644
--- a/fs/dlm/lock.h
+++ b/fs/dlm/lock.h
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -24,6 +24,10 @@
 void dlm_hold_rsb(struct dlm_rsb *r);
 int dlm_put_lkb(struct dlm_lkb *lkb);
 void dlm_scan_rsbs(struct dlm_ls *ls);
+int dlm_lock_recovery_try(struct dlm_ls *ls);
+void dlm_unlock_recovery(struct dlm_ls *ls);
+void dlm_scan_timeout(struct dlm_ls *ls);
+void dlm_adjust_timeouts(struct dlm_ls *ls);
 
 int dlm_purge_locks(struct dlm_ls *ls);
 void dlm_purge_mstcpy_locks(struct dlm_rsb *r);
@@ -34,15 +38,18 @@
 int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
 
 int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode,
-	uint32_t flags, void *name, unsigned int namelen, uint32_t parent_lkid);
+	uint32_t flags, void *name, unsigned int namelen,
+	unsigned long timeout_cs);
 int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
-	int mode, uint32_t flags, uint32_t lkid, char *lvb_in);
+	int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
+	unsigned long timeout_cs);
 int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
 	uint32_t flags, uint32_t lkid, char *lvb_in);
 int dlm_user_cancel(struct dlm_ls *ls,  struct dlm_user_args *ua_tmp,
 	uint32_t flags, uint32_t lkid);
 int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
 	int nodeid, int pid);
+int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid);
 void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc);
 
 static inline int is_master(struct dlm_rsb *r)
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index a677b2a..1dc7210 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -197,13 +197,24 @@
 	else
 		kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
 
+	log_debug(ls, "%s the lockspace group...", in ? "joining" : "leaving");
+
+	/* dlm_controld will see the uevent, do the necessary group management
+	   and then write to sysfs to wake us */
+
 	error = wait_event_interruptible(ls->ls_uevent_wait,
 			test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
+
+	log_debug(ls, "group event done %d %d", error, ls->ls_uevent_result);
+
 	if (error)
 		goto out;
 
 	error = ls->ls_uevent_result;
  out:
+	if (error)
+		log_error(ls, "group %s failed %d %d", in ? "join" : "leave",
+			  error, ls->ls_uevent_result);
 	return error;
 }
 
@@ -234,8 +245,13 @@
 	struct dlm_ls *ls;
 
 	while (!kthread_should_stop()) {
-		list_for_each_entry(ls, &lslist, ls_list)
-			dlm_scan_rsbs(ls);
+		list_for_each_entry(ls, &lslist, ls_list) {
+			if (dlm_lock_recovery_try(ls)) {
+				dlm_scan_rsbs(ls);
+				dlm_scan_timeout(ls);
+				dlm_unlock_recovery(ls);
+			}
+		}
 		schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
 	}
 	return 0;
@@ -395,6 +411,7 @@
 {
 	struct dlm_ls *ls;
 	int i, size, error = -ENOMEM;
+	int do_unreg = 0;
 
 	if (namelen > DLM_LOCKSPACE_LEN)
 		return -EINVAL;
@@ -417,11 +434,22 @@
 		goto out;
 	memcpy(ls->ls_name, name, namelen);
 	ls->ls_namelen = namelen;
-	ls->ls_exflags = flags;
 	ls->ls_lvblen = lvblen;
 	ls->ls_count = 0;
 	ls->ls_flags = 0;
 
+	if (flags & DLM_LSFL_TIMEWARN)
+		set_bit(LSFL_TIMEWARN, &ls->ls_flags);
+
+	if (flags & DLM_LSFL_FS)
+		ls->ls_allocation = GFP_NOFS;
+	else
+		ls->ls_allocation = GFP_KERNEL;
+
+	/* ls_exflags are forced to match among nodes, and we don't
+	   need to require all nodes to have TIMEWARN or FS set */
+	ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS));
+
 	size = dlm_config.ci_rsbtbl_size;
 	ls->ls_rsbtbl_size = size;
 
@@ -461,6 +489,8 @@
 	mutex_init(&ls->ls_waiters_mutex);
 	INIT_LIST_HEAD(&ls->ls_orphans);
 	mutex_init(&ls->ls_orphans_mutex);
+	INIT_LIST_HEAD(&ls->ls_timeout);
+	mutex_init(&ls->ls_timeout_mutex);
 
 	INIT_LIST_HEAD(&ls->ls_nodes);
 	INIT_LIST_HEAD(&ls->ls_nodes_gone);
@@ -477,6 +507,8 @@
 
 	init_waitqueue_head(&ls->ls_uevent_wait);
 	ls->ls_uevent_result = 0;
+	init_completion(&ls->ls_members_done);
+	ls->ls_members_result = -1;
 
 	ls->ls_recoverd_task = NULL;
 	mutex_init(&ls->ls_recoverd_active);
@@ -513,32 +545,49 @@
 	error = dlm_recoverd_start(ls);
 	if (error) {
 		log_error(ls, "can't start dlm_recoverd %d", error);
-		goto out_rcomfree;
+		goto out_delist;
 	}
 
-	dlm_create_debug_file(ls);
-
 	error = kobject_setup(ls);
 	if (error)
-		goto out_del;
+		goto out_stop;
 
 	error = kobject_register(&ls->ls_kobj);
 	if (error)
-		goto out_del;
+		goto out_stop;
+
+	/* let kobject handle freeing of ls if there's an error */
+	do_unreg = 1;
+
+	/* This uevent triggers dlm_controld in userspace to add us to the
+	   group of nodes that are members of this lockspace (managed by the
+	   cluster infrastructure.)  Once it's done that, it tells us who the
+	   current lockspace members are (via configfs) and then tells the
+	   lockspace to start running (via sysfs) in dlm_ls_start(). */
 
 	error = do_uevent(ls, 1);
 	if (error)
-		goto out_unreg;
+		goto out_stop;
+
+	wait_for_completion(&ls->ls_members_done);
+	error = ls->ls_members_result;
+	if (error)
+		goto out_members;
+
+	dlm_create_debug_file(ls);
+
+	log_debug(ls, "join complete");
 
 	*lockspace = ls;
 	return 0;
 
- out_unreg:
-	kobject_unregister(&ls->ls_kobj);
- out_del:
-	dlm_delete_debug_file(ls);
+ out_members:
+	do_uevent(ls, 0);
+	dlm_clear_members(ls);
+	kfree(ls->ls_node_array);
+ out_stop:
 	dlm_recoverd_stop(ls);
- out_rcomfree:
+ out_delist:
 	spin_lock(&lslist_lock);
 	list_del(&ls->ls_list);
 	spin_unlock(&lslist_lock);
@@ -550,7 +599,10 @@
  out_rsbfree:
 	kfree(ls->ls_rsbtbl);
  out_lsfree:
-	kfree(ls);
+	if (do_unreg)
+		kobject_unregister(&ls->ls_kobj);
+	else
+		kfree(ls);
  out:
 	module_put(THIS_MODULE);
 	return error;
@@ -570,6 +622,8 @@
 	error = new_lockspace(name, namelen, lockspace, flags, lvblen);
 	if (!error)
 		ls_count++;
+	else if (!ls_count)
+		threads_stop();
  out:
 	mutex_unlock(&ls_lock);
 	return error;
@@ -696,7 +750,7 @@
 	dlm_clear_members_gone(ls);
 	kfree(ls->ls_node_array);
 	kobject_unregister(&ls->ls_kobj);
-        /* The ls structure will be freed when the kobject is done with */
+	/* The ls structure will be freed when the kobject is done with */
 
 	mutex_lock(&ls_lock);
 	ls_count--;
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 27970a5..0553a61 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -260,7 +260,7 @@
 static void lowcomms_data_ready(struct sock *sk, int count_unused)
 {
 	struct connection *con = sock2con(sk);
-	if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
+	if (con && !test_and_set_bit(CF_READ_PENDING, &con->flags))
 		queue_work(recv_workqueue, &con->rwork);
 }
 
@@ -268,7 +268,7 @@
 {
 	struct connection *con = sock2con(sk);
 
-	if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
+	if (con && !test_and_set_bit(CF_WRITE_PENDING, &con->flags))
 		queue_work(send_workqueue, &con->swork);
 }
 
@@ -720,11 +720,17 @@
 			INIT_WORK(&othercon->rwork, process_recv_sockets);
 			set_bit(CF_IS_OTHERCON, &othercon->flags);
 			newcon->othercon = othercon;
+			othercon->sock = newsock;
+			newsock->sk->sk_user_data = othercon;
+			add_sock(newsock, othercon);
+			addcon = othercon;
 		}
-		othercon->sock = newsock;
-		newsock->sk->sk_user_data = othercon;
-		add_sock(newsock, othercon);
-		addcon = othercon;
+		else {
+			printk("Extra connection from node %d attempted\n", nodeid);
+			result = -EAGAIN;
+			mutex_unlock(&newcon->sock_mutex);
+			goto accept_err;
+		}
 	}
 	else {
 		newsock->sk->sk_user_data = newcon;
@@ -1400,8 +1406,11 @@
 	down(&connections_lock);
 	for (i = 0; i <= max_nodeid; i++) {
 		con = __nodeid2con(i, 0);
-		if (con)
+		if (con) {
 			con->flags |= 0xFF;
+			if (con->sock)
+				con->sock->sk->sk_user_data = NULL;
+		}
 	}
 	up(&connections_lock);
 
diff --git a/fs/dlm/main.c b/fs/dlm/main.c
index 162fbae..eca2907 100644
--- a/fs/dlm/main.c
+++ b/fs/dlm/main.c
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -25,6 +25,8 @@
 static inline int dlm_register_debugfs(void) { return 0; }
 static inline void dlm_unregister_debugfs(void) { }
 #endif
+int dlm_netlink_init(void);
+void dlm_netlink_exit(void);
 
 static int __init init_dlm(void)
 {
@@ -50,10 +52,16 @@
 	if (error)
 		goto out_debug;
 
+	error = dlm_netlink_init();
+	if (error)
+		goto out_user;
+
 	printk("DLM (built %s %s) installed\n", __DATE__, __TIME__);
 
 	return 0;
 
+ out_user:
+	dlm_user_exit();
  out_debug:
 	dlm_unregister_debugfs();
  out_config:
@@ -68,6 +76,7 @@
 
 static void __exit exit_dlm(void)
 {
+	dlm_netlink_exit();
 	dlm_user_exit();
 	dlm_config_exit();
 	dlm_memory_exit();
diff --git a/fs/dlm/member.c b/fs/dlm/member.c
index 85e2897..073599d 100644
--- a/fs/dlm/member.c
+++ b/fs/dlm/member.c
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -233,6 +233,12 @@
 	*neg_out = neg;
 
 	error = ping_members(ls);
+	if (!error || error == -EPROTO) {
+		/* new_lockspace() may be waiting to know if the config
+		   is good or bad */
+		ls->ls_members_result = error;
+		complete(&ls->ls_members_done);
+	}
 	if (error)
 		goto out;
 
@@ -284,6 +290,9 @@
 	dlm_recoverd_suspend(ls);
 	ls->ls_recover_status = 0;
 	dlm_recoverd_resume(ls);
+
+	if (!ls->ls_recover_begin)
+		ls->ls_recover_begin = jiffies;
 	return 0;
 }
 
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c
new file mode 100644
index 0000000..863b87d
--- /dev/null
+++ b/fs/dlm/netlink.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007 Red Hat, Inc.  All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
+
+#include <net/genetlink.h>
+#include <linux/dlm.h>
+#include <linux/dlm_netlink.h>
+
+#include "dlm_internal.h"
+
+static uint32_t dlm_nl_seqnum;
+static uint32_t listener_nlpid;
+
+static struct genl_family family = {
+	.id		= GENL_ID_GENERATE,
+	.name		= DLM_GENL_NAME,
+	.version	= DLM_GENL_VERSION,
+};
+
+static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size)
+{
+	struct sk_buff *skb;
+	void *data;
+
+	skb = genlmsg_new(size, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	/* add the message headers */
+	data = genlmsg_put(skb, 0, dlm_nl_seqnum++, &family, 0, cmd);
+	if (!data) {
+		nlmsg_free(skb);
+		return -EINVAL;
+	}
+
+	*skbp = skb;
+	return 0;
+}
+
+static struct dlm_lock_data *mk_data(struct sk_buff *skb)
+{
+	struct nlattr *ret;
+
+	ret = nla_reserve(skb, DLM_TYPE_LOCK, sizeof(struct dlm_lock_data));
+	if (!ret)
+		return NULL;
+	return nla_data(ret);
+}
+
+static int send_data(struct sk_buff *skb)
+{
+	struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
+	void *data = genlmsg_data(genlhdr);
+	int rv;
+
+	rv = genlmsg_end(skb, data);
+	if (rv < 0) {
+		nlmsg_free(skb);
+		return rv;
+	}
+
+	return genlmsg_unicast(skb, listener_nlpid);
+}
+
+static int user_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+	listener_nlpid = info->snd_pid;
+	printk("user_cmd nlpid %u\n", listener_nlpid);
+	return 0;
+}
+
+static struct genl_ops dlm_nl_ops = {
+	.cmd		= DLM_CMD_HELLO,
+	.doit		= user_cmd,
+};
+
+int dlm_netlink_init(void)
+{
+	int rv;
+
+	rv = genl_register_family(&family);
+	if (rv)
+		return rv;
+
+	rv = genl_register_ops(&family, &dlm_nl_ops);
+	if (rv < 0)
+		goto err;
+	return 0;
+ err:
+	genl_unregister_family(&family);
+	return rv;
+}
+
+void dlm_netlink_exit(void)
+{
+	genl_unregister_ops(&family, &dlm_nl_ops);
+	genl_unregister_family(&family);
+}
+
+static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb)
+{
+	struct dlm_rsb *r = lkb->lkb_resource;
+	struct dlm_user_args *ua = (struct dlm_user_args *) lkb->lkb_astparam;
+
+	memset(data, 0, sizeof(struct dlm_lock_data));
+
+	data->version = DLM_LOCK_DATA_VERSION;
+	data->nodeid = lkb->lkb_nodeid;
+	data->ownpid = lkb->lkb_ownpid;
+	data->id = lkb->lkb_id;
+	data->remid = lkb->lkb_remid;
+	data->status = lkb->lkb_status;
+	data->grmode = lkb->lkb_grmode;
+	data->rqmode = lkb->lkb_rqmode;
+	data->timestamp = lkb->lkb_timestamp;
+	if (ua)
+		data->xid = ua->xid;
+	if (r) {
+		data->lockspace_id = r->res_ls->ls_global_id;
+		data->resource_namelen = r->res_length;
+		memcpy(data->resource_name, r->res_name, r->res_length);
+	}
+}
+
+void dlm_timeout_warn(struct dlm_lkb *lkb)
+{
+	struct dlm_lock_data *data;
+	struct sk_buff *send_skb;
+	size_t size;
+	int rv;
+
+	size = nla_total_size(sizeof(struct dlm_lock_data)) +
+	       nla_total_size(0); /* why this? */
+
+	rv = prepare_data(DLM_CMD_TIMEOUT, &send_skb, size);
+	if (rv < 0)
+		return;
+
+	data = mk_data(send_skb);
+	if (!data) {
+		nlmsg_free(send_skb);
+		return;
+	}
+
+	fill_data(data, lkb);
+
+	send_data(send_skb);
+}
+
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c
index 6bfbd61..e3a1527 100644
--- a/fs/dlm/rcom.c
+++ b/fs/dlm/rcom.c
@@ -38,7 +38,7 @@
 	char *mb;
 	int mb_len = sizeof(struct dlm_rcom) + len;
 
-	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb);
+	mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb);
 	if (!mh) {
 		log_print("create_rcom to %d type %d len %d ENOBUFS",
 			  to_nodeid, type, len);
@@ -90,7 +90,7 @@
 		log_error(ls, "version mismatch: %x nodeid %d: %x",
 			  DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid,
 			  rc->rc_header.h_version);
-		return -EINVAL;
+		return -EPROTO;
 	}
 
 	if (rf->rf_lvblen != ls->ls_lvblen ||
@@ -98,7 +98,7 @@
 		log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x",
 			  ls->ls_lvblen, ls->ls_exflags,
 			  nodeid, rf->rf_lvblen, rf->rf_lsflags);
-		return -EINVAL;
+		return -EPROTO;
 	}
 	return 0;
 }
@@ -386,7 +386,8 @@
 	dlm_recover_process_copy(ls, rc_in);
 }
 
-static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
+static int send_ls_not_ready(struct dlm_ls *ls, int nodeid,
+			     struct dlm_rcom *rc_in)
 {
 	struct dlm_rcom *rc;
 	struct rcom_config *rf;
@@ -394,7 +395,7 @@
 	char *mb;
 	int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config);
 
-	mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_KERNEL, &mb);
+	mh = dlm_lowcomms_get_buffer(nodeid, mb_len, ls->ls_allocation, &mb);
 	if (!mh)
 		return -ENOBUFS;
 	memset(mb, 0, mb_len);
@@ -464,7 +465,7 @@
 		log_print("lockspace %x from %d type %x not found",
 			  hd->h_lockspace, nodeid, rc->rc_type);
 		if (rc->rc_type == DLM_RCOM_STATUS)
-			send_ls_not_ready(nodeid, rc);
+			send_ls_not_ready(ls, nodeid, rc);
 		return;
 	}
 
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
index 3cb636d..6657599 100644
--- a/fs/dlm/recoverd.c
+++ b/fs/dlm/recoverd.c
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -190,6 +190,8 @@
 
 	dlm_clear_members_gone(ls);
 
+	dlm_adjust_timeouts(ls);
+
 	error = enable_locking(ls, rv->seq);
 	if (error) {
 		log_debug(ls, "enable_locking failed %d", error);
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index b0201ec..6438941 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -33,16 +33,17 @@
 struct dlm_lock_params32 {
 	__u8 mode;
 	__u8 namelen;
-	__u16 flags;
+	__u16 unused;
+	__u32 flags;
 	__u32 lkid;
 	__u32 parent;
-
+	__u64 xid;
+	__u64 timeout;
 	__u32 castparam;
 	__u32 castaddr;
 	__u32 bastparam;
 	__u32 bastaddr;
 	__u32 lksb;
-
 	char lvb[DLM_USER_LVB_LEN];
 	char name[0];
 };
@@ -68,6 +69,7 @@
 };
 
 struct dlm_lock_result32 {
+	__u32 version[3];
 	__u32 length;
 	__u32 user_astaddr;
 	__u32 user_astparam;
@@ -102,6 +104,8 @@
 		kb->i.lock.flags = kb32->i.lock.flags;
 		kb->i.lock.lkid = kb32->i.lock.lkid;
 		kb->i.lock.parent = kb32->i.lock.parent;
+		kb->i.lock.xid = kb32->i.lock.xid;
+		kb->i.lock.timeout = kb32->i.lock.timeout;
 		kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
 		kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
 		kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
@@ -115,6 +119,10 @@
 static void compat_output(struct dlm_lock_result *res,
 			  struct dlm_lock_result32 *res32)
 {
+	res32->version[0] = res->version[0];
+	res32->version[1] = res->version[1];
+	res32->version[2] = res->version[2];
+
 	res32->user_astaddr = (__u32)(long)res->user_astaddr;
 	res32->user_astparam = (__u32)(long)res->user_astparam;
 	res32->user_lksb = (__u32)(long)res->user_lksb;
@@ -130,6 +138,36 @@
 }
 #endif
 
+/* Figure out if this lock is at the end of its life and no longer
+   available for the application to use.  The lkb still exists until
+   the final ast is read.  A lock becomes EOL in three situations:
+     1. a noqueue request fails with EAGAIN
+     2. an unlock completes with EUNLOCK
+     3. a cancel of a waiting request completes with ECANCEL/EDEADLK
+   An EOL lock needs to be removed from the process's list of locks.
+   And we can't allow any new operation on an EOL lock.  This is
+   not related to the lifetime of the lkb struct which is managed
+   entirely by refcount. */
+
+static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
+{
+	switch (sb_status) {
+	case -DLM_EUNLOCK:
+		return 1;
+	case -DLM_ECANCEL:
+	case -ETIMEDOUT:
+	case -EDEADLK:
+		if (lkb->lkb_grmode == DLM_LOCK_IV)
+			return 1;
+		break;
+	case -EAGAIN:
+		if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV)
+			return 1;
+		break;
+	}
+	return 0;
+}
+
 /* we could possibly check if the cancel of an orphan has resulted in the lkb
    being removed and then remove that lkb from the orphans list and free it */
 
@@ -176,25 +214,7 @@
 		log_debug(ls, "ast overlap %x status %x %x",
 			  lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags);
 
-	/* Figure out if this lock is at the end of its life and no longer
-	   available for the application to use.  The lkb still exists until
-	   the final ast is read.  A lock becomes EOL in three situations:
-	     1. a noqueue request fails with EAGAIN
-	     2. an unlock completes with EUNLOCK
-	     3. a cancel of a waiting request completes with ECANCEL
-	   An EOL lock needs to be removed from the process's list of locks.
-	   And we can't allow any new operation on an EOL lock.  This is
-	   not related to the lifetime of the lkb struct which is managed
-	   entirely by refcount. */
-
-	if (type == AST_COMP &&
-	    lkb->lkb_grmode == DLM_LOCK_IV &&
-	    ua->lksb.sb_status == -EAGAIN)
-		eol = 1;
-	else if (ua->lksb.sb_status == -DLM_EUNLOCK ||
-	    (ua->lksb.sb_status == -DLM_ECANCEL &&
-	     lkb->lkb_grmode == DLM_LOCK_IV))
-		eol = 1;
+	eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type);
 	if (eol) {
 		lkb->lkb_ast_type &= ~AST_BAST;
 		lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
@@ -252,16 +272,18 @@
 	ua->castaddr = params->castaddr;
 	ua->bastparam = params->bastparam;
 	ua->bastaddr = params->bastaddr;
+	ua->xid = params->xid;
 
 	if (params->flags & DLM_LKF_CONVERT)
 		error = dlm_user_convert(ls, ua,
 				         params->mode, params->flags,
-				         params->lkid, params->lvb);
+				         params->lkid, params->lvb,
+					 (unsigned long) params->timeout);
 	else {
 		error = dlm_user_request(ls, ua,
 					 params->mode, params->flags,
 					 params->name, params->namelen,
-					 params->parent);
+					 (unsigned long) params->timeout);
 		if (!error)
 			error = ua->lksb.sb_lkid;
 	}
@@ -299,6 +321,22 @@
 	return error;
 }
 
+static int device_user_deadlock(struct dlm_user_proc *proc,
+				struct dlm_lock_params *params)
+{
+	struct dlm_ls *ls;
+	int error;
+
+	ls = dlm_find_lockspace_local(proc->lockspace);
+	if (!ls)
+		return -ENOENT;
+
+	error = dlm_user_deadlock(ls, params->flags, params->lkid);
+
+	dlm_put_lockspace(ls);
+	return error;
+}
+
 static int create_misc_device(struct dlm_ls *ls, char *name)
 {
 	int error, len;
@@ -348,7 +386,7 @@
 		return -EPERM;
 
 	error = dlm_new_lockspace(params->name, strlen(params->name),
-				  &lockspace, 0, DLM_USER_LVB_LEN);
+				  &lockspace, params->flags, DLM_USER_LVB_LEN);
 	if (error)
 		return error;
 
@@ -524,6 +562,14 @@
 		error = device_user_unlock(proc, &kbuf->i.lock);
 		break;
 
+	case DLM_USER_DEADLOCK:
+		if (!proc) {
+			log_print("no locking on control device");
+			goto out_sig;
+		}
+		error = device_user_deadlock(proc, &kbuf->i.lock);
+		break;
+
 	case DLM_USER_CREATE_LOCKSPACE:
 		if (proc) {
 			log_print("create/remove only on control device");
@@ -641,6 +687,9 @@
 	int struct_len;
 
 	memset(&result, 0, sizeof(struct dlm_lock_result));
+	result.version[0] = DLM_DEVICE_VERSION_MAJOR;
+	result.version[1] = DLM_DEVICE_VERSION_MINOR;
+	result.version[2] = DLM_DEVICE_VERSION_PATCH;
 	memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
 	result.user_lksb = ua->user_lksb;
 
@@ -699,6 +748,20 @@
 	return error;
 }
 
+static int copy_version_to_user(char __user *buf, size_t count)
+{
+	struct dlm_device_version ver;
+
+	memset(&ver, 0, sizeof(struct dlm_device_version));
+	ver.version[0] = DLM_DEVICE_VERSION_MAJOR;
+	ver.version[1] = DLM_DEVICE_VERSION_MINOR;
+	ver.version[2] = DLM_DEVICE_VERSION_PATCH;
+
+	if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version)))
+		return -EFAULT;
+	return sizeof(struct dlm_device_version);
+}
+
 /* a read returns a single ast described in a struct dlm_lock_result */
 
 static ssize_t device_read(struct file *file, char __user *buf, size_t count,
@@ -710,6 +773,16 @@
 	DECLARE_WAITQUEUE(wait, current);
 	int error, type=0, bmode=0, removed = 0;
 
+	if (count == sizeof(struct dlm_device_version)) {
+		error = copy_version_to_user(buf, count);
+		return error;
+	}
+
+	if (!proc) {
+		log_print("non-version read from control device %zu", count);
+		return -EINVAL;
+	}
+
 #ifdef CONFIG_COMPAT
 	if (count < sizeof(struct dlm_lock_result32))
 #else
@@ -747,11 +820,6 @@
 		}
 	}
 
-	if (list_empty(&proc->asts)) {
-		spin_unlock(&proc->asts_spin);
-		return -EAGAIN;
-	}
-
 	/* there may be both completion and blocking asts to return for
 	   the lkb, don't remove lkb from asts list unless no asts remain */
 
@@ -823,6 +891,7 @@
 static const struct file_operations ctl_device_fops = {
 	.open    = ctl_device_open,
 	.release = ctl_device_close,
+	.read    = device_read,
 	.write   = device_write,
 	.owner   = THIS_MODULE,
 };
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 59288d8..94f456f 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -338,16 +338,17 @@
 	return rc;
 }
 
-static ssize_t ecryptfs_sendfile(struct file *file, loff_t * ppos,
-				 size_t count, read_actor_t actor, void *target)
+static ssize_t ecryptfs_splice_read(struct file *file, loff_t * ppos,
+				    struct pipe_inode_info *pipe, size_t count,
+				    unsigned int flags)
 {
 	struct file *lower_file = NULL;
 	int rc = -EINVAL;
 
 	lower_file = ecryptfs_file_to_lower(file);
-	if (lower_file->f_op && lower_file->f_op->sendfile)
-		rc = lower_file->f_op->sendfile(lower_file, ppos, count,
-						actor, target);
+	if (lower_file->f_op && lower_file->f_op->splice_read)
+		rc = lower_file->f_op->splice_read(lower_file, ppos, pipe,
+						count, flags);
 
 	return rc;
 }
@@ -364,7 +365,7 @@
 	.release = ecryptfs_release,
 	.fsync = ecryptfs_fsync,
 	.fasync = ecryptfs_fasync,
-	.sendfile = ecryptfs_sendfile,
+	.splice_read = ecryptfs_splice_read,
 };
 
 const struct file_operations ecryptfs_main_fops = {
@@ -381,7 +382,7 @@
 	.release = ecryptfs_release,
 	.fsync = ecryptfs_fsync,
 	.fasync = ecryptfs_fasync,
-	.sendfile = ecryptfs_sendfile,
+	.splice_read = ecryptfs_splice_read,
 };
 
 static int
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 566d4e2..04afeec 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -53,7 +53,6 @@
 	.open		= generic_file_open,
 	.release	= ext2_release_file,
 	.fsync		= ext2_sync_file,
-	.sendfile	= generic_file_sendfile,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 };
@@ -71,7 +70,6 @@
 	.open		= generic_file_open,
 	.release	= ext2_release_file,
 	.fsync		= ext2_sync_file,
-	.sendfile	= xip_file_sendfile,
 };
 #endif
 
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 1e6f138..acc4913 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -120,7 +120,6 @@
 	.open		= generic_file_open,
 	.release	= ext3_release_file,
 	.fsync		= ext3_sync_file,
-	.sendfile	= generic_file_sendfile,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 };
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 3c6c1fd..d4c8186 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -120,7 +120,6 @@
 	.open		= generic_file_open,
 	.release	= ext4_release_file,
 	.fsync		= ext4_sync_file,
-	.sendfile	= generic_file_sendfile,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 };
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 55d3c74..69a83b5 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -134,7 +134,7 @@
 	.release	= fat_file_release,
 	.ioctl		= fat_generic_ioctl,
 	.fsync		= file_fsync,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 static int fat_cont_expand(struct inode *inode, loff_t size)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index adf7995..f79de7c 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -802,7 +802,7 @@
 	.release	= fuse_release,
 	.fsync		= fuse_fsync,
 	.lock		= fuse_file_lock,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 static const struct file_operations fuse_direct_io_file_operations = {
@@ -814,7 +814,7 @@
 	.release	= fuse_release,
 	.fsync		= fuse_fsync,
 	.lock		= fuse_file_lock,
-	/* no mmap and sendfile */
+	/* no mmap and splice_read */
 };
 
 static const struct address_space_operations fuse_file_aops  = {
diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile
index e3f1ada..04ad0ca 100644
--- a/fs/gfs2/Makefile
+++ b/fs/gfs2/Makefile
@@ -1,7 +1,7 @@
 obj-$(CONFIG_GFS2_FS) += gfs2.o
 gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \
 	glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \
-	mount.o ondisk.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
+	mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
 	ops_fstype.o ops_inode.o ops_super.o ops_vm.o quota.o \
 	recovery.o rgrp.o super.o sys.o trans.o util.o
 
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index c53a5d2..cd805a6 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -718,7 +718,7 @@
 	for (x = 0; x < rlist.rl_rgrps; x++) {
 		struct gfs2_rgrpd *rgd;
 		rgd = rlist.rl_ghs[x].gh_gl->gl_object;
-		rg_blocks += rgd->rd_ri.ri_length;
+		rg_blocks += rgd->rd_length;
 	}
 
 	error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
@@ -772,7 +772,7 @@
 			gfs2_free_data(ip, bstart, blen);
 	}
 
-	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
 	gfs2_dinode_out(ip, dibh->b_data);
 
@@ -824,7 +824,7 @@
 		goto out_gunlock_q;
 
 	error = gfs2_trans_begin(sdp,
-			sdp->sd_max_height + al->al_rgd->rd_ri.ri_length +
+			sdp->sd_max_height + al->al_rgd->rd_length +
 			RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0);
 	if (error)
 		goto out_ipres;
@@ -847,7 +847,7 @@
 	}
 
 	ip->i_di.di_size = size;
-	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
 	error = gfs2_meta_inode_buffer(ip, &dibh);
 	if (error)
@@ -885,7 +885,6 @@
 	unsigned blocksize, iblock, length, pos;
 	struct buffer_head *bh;
 	struct page *page;
-	void *kaddr;
 	int err;
 
 	page = grab_cache_page(mapping, index);
@@ -928,15 +927,13 @@
 		/* Uhhuh. Read error. Complain and punt. */
 		if (!buffer_uptodate(bh))
 			goto unlock;
+		err = 0;
 	}
 
 	if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
 		gfs2_trans_add_bh(ip->i_gl, bh, 0);
 
-	kaddr = kmap_atomic(page, KM_USER0);
-	memset(kaddr + offset, 0, length);
-	flush_dcache_page(page);
-	kunmap_atomic(kaddr, KM_USER0);
+	zero_user_page(page, offset, length, KM_USER0);
 
 unlock:
 	unlock_page(page);
@@ -962,7 +959,7 @@
 
 	if (gfs2_is_stuffed(ip)) {
 		ip->i_di.di_size = size;
-		ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+		ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size);
@@ -974,7 +971,7 @@
 
 		if (!error) {
 			ip->i_di.di_size = size;
-			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 			ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG;
 			gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 			gfs2_dinode_out(ip, dibh->b_data);
@@ -1044,10 +1041,10 @@
 		ip->i_di.di_height = 0;
 		ip->i_di.di_goal_meta =
 			ip->i_di.di_goal_data =
-			ip->i_num.no_addr;
+			ip->i_no_addr;
 		gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
 	}
-	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 	ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG;
 
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
diff --git a/fs/gfs2/daemon.c b/fs/gfs2/daemon.c
index 683cb5b..3548d9f 100644
--- a/fs/gfs2/daemon.c
+++ b/fs/gfs2/daemon.c
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/gfs2_ondisk.h>
 #include <linux/lm_interface.h>
+#include <linux/freezer.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -49,6 +50,8 @@
 	while (!kthread_should_stop()) {
 		gfs2_scand_internal(sdp);
 		t = gfs2_tune_get(sdp, gt_scand_secs) * HZ;
+		if (freezing(current))
+			refrigerator();
 		schedule_timeout_interruptible(t);
 	}
 
@@ -74,6 +77,8 @@
 		wait_event_interruptible(sdp->sd_reclaim_wq,
 					 (atomic_read(&sdp->sd_reclaim_count) ||
 					 kthread_should_stop()));
+		if (freezing(current))
+			refrigerator();
 	}
 
 	return 0;
@@ -93,6 +98,8 @@
 	while (!kthread_should_stop()) {
 		gfs2_check_journals(sdp);
 		t = gfs2_tune_get(sdp,  gt_recoverd_secs) * HZ;
+		if (freezing(current))
+			refrigerator();
 		schedule_timeout_interruptible(t);
 	}
 
@@ -141,6 +148,8 @@
 		}
 
 		t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
+		if (freezing(current))
+			refrigerator();
 		schedule_timeout_interruptible(t);
 	}
 
@@ -191,6 +200,8 @@
 		gfs2_quota_scan(sdp);
 
 		t = gfs2_tune_get(sdp, gt_quotad_secs) * HZ;
+		if (freezing(current))
+			refrigerator();
 		schedule_timeout_interruptible(t);
 	}
 
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index a96fa07..2beb2f4 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -130,7 +130,7 @@
 	memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
 	if (ip->i_di.di_size < offset + size)
 		ip->i_di.di_size = offset + size;
-	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 	gfs2_dinode_out(ip, dibh->b_data);
 
 	brelse(dibh);
@@ -228,7 +228,7 @@
 
 	if (ip->i_di.di_size < offset + copied)
 		ip->i_di.di_size = offset + copied;
-	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
@@ -1456,7 +1456,7 @@
 		if (dip->i_di.di_entries != g.offset) {
 			fs_warn(sdp, "Number of entries corrupt in dir %llu, "
 				"ip->i_di.di_entries (%u) != g.offset (%u)\n",
-				(unsigned long long)dip->i_num.no_addr,
+				(unsigned long long)dip->i_no_addr,
 				dip->i_di.di_entries,
 				g.offset);
 			error = -EIO;
@@ -1488,24 +1488,55 @@
  * Returns: errno
  */
 
-int gfs2_dir_search(struct inode *dir, const struct qstr *name,
-		    struct gfs2_inum_host *inum, unsigned int *type)
+struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name)
 {
 	struct buffer_head *bh;
 	struct gfs2_dirent *dent;
+	struct inode *inode;
+
+	dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
+	if (dent) {
+		if (IS_ERR(dent))
+			return ERR_PTR(PTR_ERR(dent));
+		inode = gfs2_inode_lookup(dir->i_sb, 
+				be16_to_cpu(dent->de_type),
+				be64_to_cpu(dent->de_inum.no_addr),
+				be64_to_cpu(dent->de_inum.no_formal_ino));
+		brelse(bh);
+		return inode;
+	}
+	return ERR_PTR(-ENOENT);
+}
+
+int gfs2_dir_check(struct inode *dir, const struct qstr *name,
+		   const struct gfs2_inode *ip)
+{
+	struct buffer_head *bh;
+	struct gfs2_dirent *dent;
+	int ret = -ENOENT;
 
 	dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
 	if (dent) {
 		if (IS_ERR(dent))
 			return PTR_ERR(dent);
-		if (inum)
-			gfs2_inum_in(inum, (char *)&dent->de_inum);
-		if (type)
-			*type = be16_to_cpu(dent->de_type);
+		if (ip) {
+			if (be64_to_cpu(dent->de_inum.no_addr) != ip->i_no_addr)
+				goto out;
+			if (be64_to_cpu(dent->de_inum.no_formal_ino) !=
+			    ip->i_no_formal_ino)
+				goto out;
+			if (unlikely(IF2DT(ip->i_inode.i_mode) !=
+			    be16_to_cpu(dent->de_type))) {
+				gfs2_consist_inode(GFS2_I(dir));
+				ret = -EIO;
+				goto out;
+			}
+		}
+		ret = 0;
+out:
 		brelse(bh);
-		return 0;
 	}
-	return -ENOENT;
+	return ret;
 }
 
 static int dir_new_leaf(struct inode *inode, const struct qstr *name)
@@ -1565,7 +1596,7 @@
  */
 
 int gfs2_dir_add(struct inode *inode, const struct qstr *name,
-		 const struct gfs2_inum_host *inum, unsigned type)
+		 const struct gfs2_inode *nip, unsigned type)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct buffer_head *bh;
@@ -1580,7 +1611,7 @@
 			if (IS_ERR(dent))
 				return PTR_ERR(dent);
 			dent = gfs2_init_dirent(inode, dent, name, bh);
-			gfs2_inum_out(inum, (char *)&dent->de_inum);
+			gfs2_inum_out(nip, dent);
 			dent->de_type = cpu_to_be16(type);
 			if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
 				leaf = (struct gfs2_leaf *)bh->b_data;
@@ -1592,7 +1623,7 @@
 				break;
 			gfs2_trans_add_bh(ip->i_gl, bh, 1);
 			ip->i_di.di_entries++;
-			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+			ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 			gfs2_dinode_out(ip, bh->b_data);
 			brelse(bh);
 			error = 0;
@@ -1678,7 +1709,7 @@
 		gfs2_consist_inode(dip);
 	gfs2_trans_add_bh(dip->i_gl, bh, 1);
 	dip->i_di.di_entries--;
-	dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
 	gfs2_dinode_out(dip, bh->b_data);
 	brelse(bh);
 	mark_inode_dirty(&dip->i_inode);
@@ -1700,7 +1731,7 @@
  */
 
 int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
-		   struct gfs2_inum_host *inum, unsigned int new_type)
+		   const struct gfs2_inode *nip, unsigned int new_type)
 {
 	struct buffer_head *bh;
 	struct gfs2_dirent *dent;
@@ -1715,7 +1746,7 @@
 		return PTR_ERR(dent);
 
 	gfs2_trans_add_bh(dip->i_gl, bh, 1);
-	gfs2_inum_out(inum, (char *)&dent->de_inum);
+	gfs2_inum_out(nip, dent);
 	dent->de_type = cpu_to_be16(new_type);
 
 	if (dip->i_di.di_flags & GFS2_DIF_EXHASH) {
@@ -1726,7 +1757,7 @@
 		gfs2_trans_add_bh(dip->i_gl, bh, 1);
 	}
 
-	dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
 	gfs2_dinode_out(dip, bh->b_data);
 	brelse(bh);
 	return 0;
@@ -1867,7 +1898,7 @@
 	for (x = 0; x < rlist.rl_rgrps; x++) {
 		struct gfs2_rgrpd *rgd;
 		rgd = rlist.rl_ghs[x].gh_gl->gl_object;
-		rg_blocks += rgd->rd_ri.ri_length;
+		rg_blocks += rgd->rd_length;
 	}
 
 	error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index 48fe890..8a468ca 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -16,15 +16,16 @@
 struct gfs2_inode;
 struct gfs2_inum;
 
-int gfs2_dir_search(struct inode *dir, const struct qstr *filename,
-		    struct gfs2_inum_host *inum, unsigned int *type);
+struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *filename);
+int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
+		   const struct gfs2_inode *ip);
 int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
-		 const struct gfs2_inum_host *inum, unsigned int type);
+		 const struct gfs2_inode *ip, unsigned int type);
 int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
 int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
 		  filldir_t filldir);
 int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
-		   struct gfs2_inum_host *new_inum, unsigned int new_type);
+		   const struct gfs2_inode *nip, unsigned int new_type);
 
 int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
 
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index 5b83ca6..2a7435b 100644
--- a/fs/gfs2/eattr.c
+++ b/fs/gfs2/eattr.c
@@ -254,7 +254,7 @@
 	if (error)
 		return error;
 
-	error = gfs2_trans_begin(sdp, rgd->rd_ri.ri_length + RES_DINODE +
+	error = gfs2_trans_begin(sdp, rgd->rd_length + RES_DINODE +
 				 RES_EATTR + RES_STATFS + RES_QUOTA, blks);
 	if (error)
 		goto out_gunlock;
@@ -300,7 +300,7 @@
 
 	error = gfs2_meta_inode_buffer(ip, &dibh);
 	if (!error) {
-		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+		ip->i_inode.i_ctime = CURRENT_TIME;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
@@ -700,7 +700,7 @@
 		goto out_gunlock_q;
 
 	error = gfs2_trans_begin(GFS2_SB(&ip->i_inode),
-				 blks + al->al_rgd->rd_ri.ri_length +
+				 blks + al->al_rgd->rd_length +
 				 RES_DINODE + RES_STATFS + RES_QUOTA, 0);
 	if (error)
 		goto out_ipres;
@@ -717,7 +717,7 @@
 					    (er->er_mode & S_IFMT));
 			ip->i_inode.i_mode = er->er_mode;
 		}
-		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+		ip->i_inode.i_ctime = CURRENT_TIME;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
@@ -852,7 +852,7 @@
 			(ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT));
 		ip->i_inode.i_mode = er->er_mode;
 	}
-	ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_ctime = CURRENT_TIME;
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
 	brelse(dibh);
@@ -1133,7 +1133,7 @@
 
 	error = gfs2_meta_inode_buffer(ip, &dibh);
 	if (!error) {
-		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+		ip->i_inode.i_ctime = CURRENT_TIME;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
@@ -1352,7 +1352,7 @@
 	for (x = 0; x < rlist.rl_rgrps; x++) {
 		struct gfs2_rgrpd *rgd;
 		rgd = rlist.rl_ghs[x].gh_gl->gl_object;
-		rg_blocks += rgd->rd_ri.ri_length;
+		rg_blocks += rgd->rd_length;
 	}
 
 	error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 1815429..3f0974e 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -422,11 +422,11 @@
 static void gfs2_holder_wake(struct gfs2_holder *gh)
 {
 	clear_bit(HIF_WAIT, &gh->gh_iflags);
-	smp_mb();
+	smp_mb__after_clear_bit();
 	wake_up_bit(&gh->gh_iflags, HIF_WAIT);
 }
 
-static int holder_wait(void *word)
+static int just_schedule(void *word)
 {
         schedule();
         return 0;
@@ -435,7 +435,20 @@
 static void wait_on_holder(struct gfs2_holder *gh)
 {
 	might_sleep();
-	wait_on_bit(&gh->gh_iflags, HIF_WAIT, holder_wait, TASK_UNINTERRUPTIBLE);
+	wait_on_bit(&gh->gh_iflags, HIF_WAIT, just_schedule, TASK_UNINTERRUPTIBLE);
+}
+
+static void gfs2_demote_wake(struct gfs2_glock *gl)
+{
+        clear_bit(GLF_DEMOTE, &gl->gl_flags);
+        smp_mb__after_clear_bit();
+        wake_up_bit(&gl->gl_flags, GLF_DEMOTE);
+}
+
+static void wait_on_demote(struct gfs2_glock *gl)
+{
+	might_sleep();
+	wait_on_bit(&gl->gl_flags, GLF_DEMOTE, just_schedule, TASK_UNINTERRUPTIBLE);
 }
 
 /**
@@ -528,7 +541,7 @@
 
 	if (gl->gl_state == gl->gl_demote_state ||
 	    gl->gl_state == LM_ST_UNLOCKED) {
-		clear_bit(GLF_DEMOTE, &gl->gl_flags);
+		gfs2_demote_wake(gl);
 		return 0;
 	}
 	set_bit(GLF_LOCK, &gl->gl_flags);
@@ -666,12 +679,22 @@
  * practise: LM_ST_SHARED and LM_ST_UNLOCKED
  */
 
-static void handle_callback(struct gfs2_glock *gl, unsigned int state)
+static void handle_callback(struct gfs2_glock *gl, unsigned int state, int remote)
 {
 	spin_lock(&gl->gl_spin);
 	if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) {
 		gl->gl_demote_state = state;
 		gl->gl_demote_time = jiffies;
+		if (remote && gl->gl_ops->go_type == LM_TYPE_IOPEN &&
+		    gl->gl_object) {
+			struct inode *inode = igrab(gl->gl_object);
+			spin_unlock(&gl->gl_spin);
+			if (inode) {
+				d_prune_aliases(inode);
+				iput(inode);
+			}
+			return;
+		}
 	} else if (gl->gl_demote_state != LM_ST_UNLOCKED) {
 		gl->gl_demote_state = state;
 	}
@@ -740,7 +763,7 @@
 		if (ret & LM_OUT_CANCELED)
 			op_done = 0;
 		else
-			clear_bit(GLF_DEMOTE, &gl->gl_flags);
+			gfs2_demote_wake(gl);
 	} else {
 		spin_lock(&gl->gl_spin);
 		list_del_init(&gh->gh_list);
@@ -848,7 +871,7 @@
 	gfs2_assert_warn(sdp, !ret);
 
 	state_change(gl, LM_ST_UNLOCKED);
-	clear_bit(GLF_DEMOTE, &gl->gl_flags);
+	gfs2_demote_wake(gl);
 
 	if (glops->go_inval)
 		glops->go_inval(gl, DIO_METADATA);
@@ -1174,7 +1197,7 @@
 	const struct gfs2_glock_operations *glops = gl->gl_ops;
 
 	if (gh->gh_flags & GL_NOCACHE)
-		handle_callback(gl, LM_ST_UNLOCKED);
+		handle_callback(gl, LM_ST_UNLOCKED, 0);
 
 	gfs2_glmutex_lock(gl);
 
@@ -1196,6 +1219,13 @@
 	spin_unlock(&gl->gl_spin);
 }
 
+void gfs2_glock_dq_wait(struct gfs2_holder *gh)
+{
+	struct gfs2_glock *gl = gh->gh_gl;
+	gfs2_glock_dq(gh);
+	wait_on_demote(gl);
+}
+
 /**
  * gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it
  * @gh: the holder structure
@@ -1297,10 +1327,6 @@
  * @num_gh: the number of structures
  * @ghs: an array of struct gfs2_holder structures
  *
- * Figure out how big an impact this function has.  Either:
- * 1) Replace this code with code that calls gfs2_glock_prefetch()
- * 2) Forget async stuff and just call nq_m_sync()
- * 3) Leave it like it is
  *
  * Returns: 0 on success (all glocks acquired),
  *          errno on failure (no glocks acquired)
@@ -1308,62 +1334,28 @@
 
 int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs)
 {
-	int *e;
-	unsigned int x;
-	int borked = 0, serious = 0;
+	struct gfs2_holder *tmp[4];
+	struct gfs2_holder **pph = tmp;
 	int error = 0;
 
-	if (!num_gh)
+	switch(num_gh) {
+	case 0:
 		return 0;
-
-	if (num_gh == 1) {
+	case 1:
 		ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
 		return gfs2_glock_nq(ghs);
-	}
-
-	e = kcalloc(num_gh, sizeof(struct gfs2_holder *), GFP_KERNEL);
-	if (!e)
-		return -ENOMEM;
-
-	for (x = 0; x < num_gh; x++) {
-		ghs[x].gh_flags |= LM_FLAG_TRY | GL_ASYNC;
-		error = gfs2_glock_nq(&ghs[x]);
-		if (error) {
-			borked = 1;
-			serious = error;
-			num_gh = x;
+	default:
+		if (num_gh <= 4)
 			break;
-		}
+		pph = kmalloc(num_gh * sizeof(struct gfs2_holder *), GFP_NOFS);
+		if (!pph)
+			return -ENOMEM;
 	}
 
-	for (x = 0; x < num_gh; x++) {
-		error = e[x] = glock_wait_internal(&ghs[x]);
-		if (error) {
-			borked = 1;
-			if (error != GLR_TRYFAILED && error != GLR_CANCELED)
-				serious = error;
-		}
-	}
+	error = nq_m_sync(num_gh, ghs, pph);
 
-	if (!borked) {
-		kfree(e);
-		return 0;
-	}
-
-	for (x = 0; x < num_gh; x++)
-		if (!e[x])
-			gfs2_glock_dq(&ghs[x]);
-
-	if (serious)
-		error = serious;
-	else {
-		for (x = 0; x < num_gh; x++)
-			gfs2_holder_reinit(ghs[x].gh_state, ghs[x].gh_flags,
-					  &ghs[x]);
-		error = nq_m_sync(num_gh, ghs, (struct gfs2_holder **)e);
-	}
-
-	kfree(e);
+	if (pph != tmp)
+		kfree(pph);
 
 	return error;
 }
@@ -1456,7 +1448,7 @@
 	if (!gl)
 		return;
 
-	handle_callback(gl, state);
+	handle_callback(gl, state, 1);
 
 	spin_lock(&gl->gl_spin);
 	run_queue(gl);
@@ -1596,7 +1588,7 @@
 	if (gfs2_glmutex_trylock(gl)) {
 		if (list_empty(&gl->gl_holders) &&
 		    gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl))
-			handle_callback(gl, LM_ST_UNLOCKED);
+			handle_callback(gl, LM_ST_UNLOCKED, 0);
 		gfs2_glmutex_unlock(gl);
 	}
 
@@ -1709,7 +1701,7 @@
 	if (gfs2_glmutex_trylock(gl)) {
 		if (list_empty(&gl->gl_holders) &&
 		    gl->gl_state != LM_ST_UNLOCKED)
-			handle_callback(gl, LM_ST_UNLOCKED);
+			handle_callback(gl, LM_ST_UNLOCKED, 0);
 		gfs2_glmutex_unlock(gl);
 	}
 }
@@ -1823,7 +1815,8 @@
 
 	print_dbg(gi, "  Inode:\n");
 	print_dbg(gi, "    num = %llu/%llu\n",
-		    ip->i_num.no_formal_ino, ip->i_num.no_addr);
+		  (unsigned long long)ip->i_no_formal_ino,
+		  (unsigned long long)ip->i_no_addr);
 	print_dbg(gi, "    type = %u\n", IF2DT(ip->i_inode.i_mode));
 	print_dbg(gi, "    i_flags =");
 	for (x = 0; x < 32; x++)
@@ -1909,8 +1902,8 @@
 	}
 	if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
 		print_dbg(gi, "  Demotion req to state %u (%llu uS ago)\n",
-			  gl->gl_demote_state,
-			  (u64)(jiffies - gl->gl_demote_time)*(1000000/HZ));
+			  gl->gl_demote_state, (unsigned long long)
+			  (jiffies - gl->gl_demote_time)*(1000000/HZ));
 	}
 	if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) {
 		if (!test_bit(GLF_LOCK, &gl->gl_flags) &&
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index b3e152d..7721ca3 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -87,6 +87,7 @@
 int gfs2_glock_poll(struct gfs2_holder *gh);
 int gfs2_glock_wait(struct gfs2_holder *gh);
 void gfs2_glock_dq(struct gfs2_holder *gh);
+void gfs2_glock_dq_wait(struct gfs2_holder *gh);
 
 void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
 int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 7b82657..777ca46 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -156,9 +156,9 @@
 		ip = NULL;
 
 	if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
-		gfs2_log_flush(gl->gl_sbd, gl);
 		if (ip)
 			filemap_fdatawrite(ip->i_inode.i_mapping);
+		gfs2_log_flush(gl->gl_sbd, gl);
 		gfs2_meta_sync(gl);
 		if (ip) {
 			struct address_space *mapping = ip->i_inode.i_mapping;
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index d995441..170ba93 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -28,6 +28,14 @@
 
 typedef void (*gfs2_glop_bh_t) (struct gfs2_glock *gl, unsigned int ret);
 
+struct gfs2_log_header_host {
+	u64 lh_sequence;	/* Sequence number of this transaction */
+	u32 lh_flags;		/* GFS2_LOG_HEAD_... */
+	u32 lh_tail;		/* Block number of log tail */
+	u32 lh_blkno;
+	u32 lh_hash;
+};
+
 /*
  * Structure of operations that are associated with each
  * type of element in the log.
@@ -60,12 +68,23 @@
 	u32 bi_len;
 };
 
+struct gfs2_rgrp_host {
+	u32 rg_flags;
+	u32 rg_free;
+	u32 rg_dinodes;
+	u64 rg_igeneration;
+};
+
 struct gfs2_rgrpd {
 	struct list_head rd_list;	/* Link with superblock */
 	struct list_head rd_list_mru;
 	struct list_head rd_recent;	/* Recently used rgrps */
 	struct gfs2_glock *rd_gl;	/* Glock for this rgrp */
-	struct gfs2_rindex_host rd_ri;
+	u64 rd_addr;			/* grp block disk address */
+	u64 rd_data0;			/* first data location */
+	u32 rd_length;			/* length of rgrp header in fs blocks */
+	u32 rd_data;			/* num of data blocks in rgrp */
+	u32 rd_bitbytes;		/* number of bytes in data bitmaps */
 	struct gfs2_rgrp_host rd_rg;
 	u64 rd_rg_vn;
 	struct gfs2_bitmap *rd_bits;
@@ -76,6 +95,8 @@
 	u32 rd_last_alloc_data;
 	u32 rd_last_alloc_meta;
 	struct gfs2_sbd *rd_sbd;
+	unsigned long rd_flags;
+#define GFS2_RDF_CHECK        0x0001          /* Need to check for unlinked inodes */
 };
 
 enum gfs2_state_bits {
@@ -211,10 +232,24 @@
 	GIF_SW_PAGED		= 3,
 };
 
+struct gfs2_dinode_host {
+	u64 di_size;		/* number of bytes in file */
+	u64 di_blocks;		/* number of blocks in file */
+	u64 di_goal_meta;	/* rgrp to alloc from next */
+	u64 di_goal_data;	/* data block goal */
+	u64 di_generation;	/* generation number for NFS */
+	u32 di_flags;		/* GFS2_DIF_... */
+	u16 di_height;		/* height of metadata */
+	/* These only apply to directories  */
+	u16 di_depth;		/* Number of bits in the table */
+	u32 di_entries;		/* The number of entries in the directory */
+	u64 di_eattr;		/* extended attribute block number */
+};
+
 struct gfs2_inode {
 	struct inode i_inode;
-	struct gfs2_inum_host i_num;
-
+	u64 i_no_addr;
+	u64 i_no_formal_ino;
 	unsigned long i_flags;		/* GIF_... */
 
 	struct gfs2_dinode_host i_di; /* To be replaced by ref to block */
@@ -275,14 +310,6 @@
 	QDF_LOCKED		= 2,
 };
 
-struct gfs2_quota_lvb {
-        __be32 qb_magic;
-        u32 __pad;
-        __be64 qb_limit;      /* Hard limit of # blocks to alloc */
-        __be64 qb_warn;       /* Warn user when alloc is above this # */
-        __be64 qb_value;       /* Current # blocks allocated */
-};
-
 struct gfs2_quota_data {
 	struct list_head qd_list;
 	unsigned int qd_count;
@@ -327,7 +354,9 @@
 
 	unsigned int tr_num_buf;
 	unsigned int tr_num_buf_new;
+	unsigned int tr_num_databuf_new;
 	unsigned int tr_num_buf_rm;
+	unsigned int tr_num_databuf_rm;
 	struct list_head tr_list_buf;
 
 	unsigned int tr_num_revoke;
@@ -354,6 +383,12 @@
 	unsigned int jd_blocks;
 };
 
+struct gfs2_statfs_change_host {
+	s64 sc_total;
+	s64 sc_free;
+	s64 sc_dinodes;
+};
+
 #define GFS2_GLOCKD_DEFAULT	1
 #define GFS2_GLOCKD_MAX		16
 
@@ -426,6 +461,28 @@
 
 #define GFS2_FSNAME_LEN		256
 
+struct gfs2_inum_host {
+	u64 no_formal_ino;
+	u64 no_addr;
+};
+
+struct gfs2_sb_host {
+	u32 sb_magic;
+	u32 sb_type;
+	u32 sb_format;
+
+	u32 sb_fs_format;
+	u32 sb_multihost_format;
+	u32 sb_bsize;
+	u32 sb_bsize_shift;
+
+	struct gfs2_inum_host sb_master_dir;
+	struct gfs2_inum_host sb_root_dir;
+
+	char sb_lockproto[GFS2_LOCKNAME_LEN];
+	char sb_locktable[GFS2_LOCKNAME_LEN];
+};
+
 struct gfs2_sbd {
 	struct super_block *sd_vfs;
 	struct super_block *sd_vfs_meta;
@@ -544,6 +601,7 @@
 
 	unsigned int sd_log_blks_reserved;
 	unsigned int sd_log_commited_buf;
+	unsigned int sd_log_commited_databuf;
 	unsigned int sd_log_commited_revoke;
 
 	unsigned int sd_log_num_gl;
@@ -552,7 +610,6 @@
 	unsigned int sd_log_num_rg;
 	unsigned int sd_log_num_databuf;
 	unsigned int sd_log_num_jdata;
-	unsigned int sd_log_num_hdrs;
 
 	struct list_head sd_log_le_gl;
 	struct list_head sd_log_le_buf;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index df0b8b3..34f7bcd 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -38,12 +38,17 @@
 #include "trans.h"
 #include "util.h"
 
+struct gfs2_inum_range_host {
+	u64 ir_start;
+	u64 ir_length;
+};
+
 static int iget_test(struct inode *inode, void *opaque)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
-	struct gfs2_inum_host *inum = opaque;
+	u64 *no_addr = opaque;
 
-	if (ip->i_num.no_addr == inum->no_addr &&
+	if (ip->i_no_addr == *no_addr &&
 	    inode->i_private != NULL)
 		return 1;
 
@@ -53,37 +58,70 @@
 static int iget_set(struct inode *inode, void *opaque)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
-	struct gfs2_inum_host *inum = opaque;
+	u64 *no_addr = opaque;
 
-	ip->i_num = *inum;
-	inode->i_ino = inum->no_addr;
+	inode->i_ino = (unsigned long)*no_addr;
+	ip->i_no_addr = *no_addr;
 	return 0;
 }
 
-struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum)
+struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr)
 {
-	return ilookup5(sb, (unsigned long)inum->no_addr,
-			iget_test, inum);
+	unsigned long hash = (unsigned long)no_addr;
+	return ilookup5(sb, hash, iget_test, &no_addr);
 }
 
-static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum_host *inum)
+static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr)
 {
-	return iget5_locked(sb, (unsigned long)inum->no_addr,
-		     iget_test, iget_set, inum);
+	unsigned long hash = (unsigned long)no_addr;
+	return iget5_locked(sb, hash, iget_test, iget_set, &no_addr);
+}
+
+/**
+ * GFS2 lookup code fills in vfs inode contents based on info obtained
+ * from directory entry inside gfs2_inode_lookup(). This has caused issues
+ * with NFS code path since its get_dentry routine doesn't have the relevant
+ * directory entry when gfs2_inode_lookup() is invoked. Part of the code
+ * segment inside gfs2_inode_lookup code needs to get moved around.
+ *
+ * Clean up I_LOCK and I_NEW as well.
+ **/
+
+void gfs2_set_iop(struct inode *inode)
+{
+	umode_t mode = inode->i_mode;
+
+	if (S_ISREG(mode)) {
+		inode->i_op = &gfs2_file_iops;
+		inode->i_fop = &gfs2_file_fops;
+		inode->i_mapping->a_ops = &gfs2_file_aops;
+	} else if (S_ISDIR(mode)) {
+		inode->i_op = &gfs2_dir_iops;
+		inode->i_fop = &gfs2_dir_fops;
+	} else if (S_ISLNK(mode)) {
+		inode->i_op = &gfs2_symlink_iops;
+	} else {
+		inode->i_op = &gfs2_dev_iops;
+	}
+
+	unlock_new_inode(inode);
 }
 
 /**
  * gfs2_inode_lookup - Lookup an inode
  * @sb: The super block
- * @inum: The inode number
+ * @no_addr: The inode number
  * @type: The type of the inode
  *
  * Returns: A VFS inode, or an error
  */
 
-struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned int type)
+struct inode *gfs2_inode_lookup(struct super_block *sb, 
+				unsigned int type,
+				u64 no_addr,
+				u64 no_formal_ino)
 {
-	struct inode *inode = gfs2_iget(sb, inum);
+	struct inode *inode = gfs2_iget(sb, no_addr);
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_glock *io_gl;
 	int error;
@@ -93,29 +131,15 @@
 
 	if (inode->i_state & I_NEW) {
 		struct gfs2_sbd *sdp = GFS2_SB(inode);
-		umode_t mode = DT2IF(type);
 		inode->i_private = ip;
-		inode->i_mode = mode;
+		ip->i_no_formal_ino = no_formal_ino;
 
-		if (S_ISREG(mode)) {
-			inode->i_op = &gfs2_file_iops;
-			inode->i_fop = &gfs2_file_fops;
-			inode->i_mapping->a_ops = &gfs2_file_aops;
-		} else if (S_ISDIR(mode)) {
-			inode->i_op = &gfs2_dir_iops;
-			inode->i_fop = &gfs2_dir_fops;
-		} else if (S_ISLNK(mode)) {
-			inode->i_op = &gfs2_symlink_iops;
-		} else {
-			inode->i_op = &gfs2_dev_iops;
-		}
-
-		error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
+		error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
 		if (unlikely(error))
 			goto fail;
 		ip->i_gl->gl_object = ip;
 
-		error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
+		error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
 		if (unlikely(error))
 			goto fail_put;
 
@@ -123,12 +147,38 @@
 		error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
 		if (unlikely(error))
 			goto fail_iopen;
+		ip->i_iopen_gh.gh_gl->gl_object = ip;
 
 		gfs2_glock_put(io_gl);
-		unlock_new_inode(inode);
+
+		if ((type == DT_UNKNOWN) && (no_formal_ino == 0))
+			goto gfs2_nfsbypass;
+
+		inode->i_mode = DT2IF(type);
+
+		/*
+		 * We must read the inode in order to work out its type in
+		 * this case. Note that this doesn't happen often as we normally
+		 * know the type beforehand. This code path only occurs during
+		 * unlinked inode recovery (where it is safe to do this glock,
+		 * which is not true in the general case).
+		 */
+		if (type == DT_UNKNOWN) {
+			struct gfs2_holder gh;
+			error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+			if (unlikely(error))
+				goto fail_glock;
+			/* Inode is now uptodate */
+			gfs2_glock_dq_uninit(&gh);
+		}
+
+		gfs2_set_iop(inode);
 	}
 
+gfs2_nfsbypass:
 	return inode;
+fail_glock:
+	gfs2_glock_dq(&ip->i_iopen_gh);
 fail_iopen:
 	gfs2_glock_put(io_gl);
 fail_put:
@@ -144,14 +194,12 @@
 	struct gfs2_dinode_host *di = &ip->i_di;
 	const struct gfs2_dinode *str = buf;
 
-	if (ip->i_num.no_addr != be64_to_cpu(str->di_num.no_addr)) {
+	if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) {
 		if (gfs2_consist_inode(ip))
 			gfs2_dinode_print(ip);
 		return -EIO;
 	}
-	if (ip->i_num.no_formal_ino != be64_to_cpu(str->di_num.no_formal_ino))
-		return -ESTALE;
-
+	ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino);
 	ip->i_inode.i_mode = be32_to_cpu(str->di_mode);
 	ip->i_inode.i_rdev = 0;
 	switch (ip->i_inode.i_mode & S_IFMT) {
@@ -175,11 +223,11 @@
 	di->di_blocks = be64_to_cpu(str->di_blocks);
 	gfs2_set_inode_blocks(&ip->i_inode);
 	ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
-	ip->i_inode.i_atime.tv_nsec = 0;
+	ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
 	ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
-	ip->i_inode.i_mtime.tv_nsec = 0;
+	ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
 	ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
-	ip->i_inode.i_ctime.tv_nsec = 0;
+	ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec);
 
 	di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
 	di->di_goal_data = be64_to_cpu(str->di_goal_data);
@@ -247,7 +295,7 @@
 	if (error)
 		goto out_qs;
 
-	rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+	rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
 	if (!rgd) {
 		gfs2_consist_inode(ip);
 		error = -EIO;
@@ -314,7 +362,7 @@
 	else
 		drop_nlink(&ip->i_inode);
 
-	ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+	ip->i_inode.i_ctime = CURRENT_TIME;
 
 	gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 	gfs2_dinode_out(ip, dibh->b_data);
@@ -366,9 +414,7 @@
 	struct super_block *sb = dir->i_sb;
 	struct gfs2_inode *dip = GFS2_I(dir);
 	struct gfs2_holder d_gh;
-	struct gfs2_inum_host inum;
-	unsigned int type;
-	int error;
+	int error = 0;
 	struct inode *inode = NULL;
 	int unlock = 0;
 
@@ -395,12 +441,9 @@
 			goto out;
 	}
 
-	error = gfs2_dir_search(dir, name, &inum, &type);
-	if (error)
-		goto out;
-
-	inode = gfs2_inode_lookup(sb, &inum, type);
-
+	inode = gfs2_dir_search(dir, name);
+	if (IS_ERR(inode))
+		error = PTR_ERR(inode);
 out:
 	if (unlock)
 		gfs2_glock_dq_uninit(&d_gh);
@@ -409,6 +452,22 @@
 	return inode ? inode : ERR_PTR(error);
 }
 
+static void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf)
+{
+	const struct gfs2_inum_range *str = buf;
+
+	ir->ir_start = be64_to_cpu(str->ir_start);
+	ir->ir_length = be64_to_cpu(str->ir_length);
+}
+
+static void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf)
+{
+	struct gfs2_inum_range *str = buf;
+
+	str->ir_start = cpu_to_be64(ir->ir_start);
+	str->ir_length = cpu_to_be64(ir->ir_length);
+}
+
 static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino)
 {
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode);
@@ -548,7 +607,7 @@
 	if (!dip->i_inode.i_nlink)
 		return -EPERM;
 
-	error = gfs2_dir_search(&dip->i_inode, name, NULL, NULL);
+	error = gfs2_dir_check(&dip->i_inode, name, NULL);
 	switch (error) {
 	case -ENOENT:
 		error = 0;
@@ -588,8 +647,7 @@
 		*gid = current->fsgid;
 }
 
-static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum,
-			u64 *generation)
+static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
 	int error;
@@ -605,7 +663,7 @@
 	if (error)
 		goto out_ipreserv;
 
-	inum->no_addr = gfs2_alloc_di(dip, generation);
+	*no_addr = gfs2_alloc_di(dip, generation);
 
 	gfs2_trans_end(sdp);
 
@@ -635,6 +693,7 @@
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
 	struct gfs2_dinode *di;
 	struct buffer_head *dibh;
+	struct timespec tv = CURRENT_TIME;
 
 	dibh = gfs2_meta_new(gl, inum->no_addr);
 	gfs2_trans_add_bh(gl, dibh, 1);
@@ -650,7 +709,7 @@
 	di->di_nlink = 0;
 	di->di_size = 0;
 	di->di_blocks = cpu_to_be64(1);
-	di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds());
+	di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);
 	di->di_major = cpu_to_be32(MAJOR(dev));
 	di->di_minor = cpu_to_be32(MINOR(dev));
 	di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
@@ -680,6 +739,9 @@
 	di->di_entries = 0;
 	memset(&di->__pad4, 0, sizeof(di->__pad4));
 	di->di_eattr = 0;
+	di->di_atime_nsec = cpu_to_be32(tv.tv_nsec);
+	di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec);
+	di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
 	memset(&di->di_reserved, 0, sizeof(di->di_reserved));
 
 	brelse(dibh);
@@ -749,7 +811,7 @@
 			goto fail_quota_locks;
 
 		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
-					 al->al_rgd->rd_ri.ri_length +
+					 al->al_rgd->rd_length +
 					 2 * RES_DINODE +
 					 RES_STATFS + RES_QUOTA, 0);
 		if (error)
@@ -760,7 +822,7 @@
 			goto fail_quota_locks;
 	}
 
-	error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_inode.i_mode));
+	error = gfs2_dir_add(&dip->i_inode, name, ip, IF2DT(ip->i_inode.i_mode));
 	if (error)
 		goto fail_end_trans;
 
@@ -840,11 +902,11 @@
 struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
 			   unsigned int mode, dev_t dev)
 {
-	struct inode *inode;
+	struct inode *inode = NULL;
 	struct gfs2_inode *dip = ghs->gh_gl->gl_object;
 	struct inode *dir = &dip->i_inode;
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-	struct gfs2_inum_host inum;
+	struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
 	int error;
 	u64 generation;
 
@@ -864,7 +926,7 @@
 	if (error)
 		goto fail_gunlock;
 
-	error = alloc_dinode(dip, &inum, &generation);
+	error = alloc_dinode(dip, &inum.no_addr, &generation);
 	if (error)
 		goto fail_gunlock;
 
@@ -877,34 +939,36 @@
 	if (error)
 		goto fail_gunlock2;
 
-	inode = gfs2_inode_lookup(dir->i_sb, &inum, IF2DT(mode));
+	inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode),
+					inum.no_addr,
+					inum.no_formal_ino);
 	if (IS_ERR(inode))
 		goto fail_gunlock2;
 
 	error = gfs2_inode_refresh(GFS2_I(inode));
 	if (error)
-		goto fail_iput;
+		goto fail_gunlock2;
 
 	error = gfs2_acl_create(dip, GFS2_I(inode));
 	if (error)
-		goto fail_iput;
+		goto fail_gunlock2;
 
 	error = gfs2_security_init(dip, GFS2_I(inode));
 	if (error)
-		goto fail_iput;
+		goto fail_gunlock2;
 
 	error = link_dinode(dip, name, GFS2_I(inode));
 	if (error)
-		goto fail_iput;
+		goto fail_gunlock2;
 
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
 	return inode;
 
-fail_iput:
-	iput(inode);
 fail_gunlock2:
 	gfs2_glock_dq_uninit(ghs + 1);
+	if (inode)
+		iput(inode);
 fail_gunlock:
 	gfs2_glock_dq(ghs);
 fail:
@@ -976,10 +1040,8 @@
  */
 
 int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
-		   struct gfs2_inode *ip)
+		   const struct gfs2_inode *ip)
 {
-	struct gfs2_inum_host inum;
-	unsigned int type;
 	int error;
 
 	if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode))
@@ -997,18 +1059,10 @@
 	if (error)
 		return error;
 
-	error = gfs2_dir_search(&dip->i_inode, name, &inum, &type);
+	error = gfs2_dir_check(&dip->i_inode, name, ip);
 	if (error)
 		return error;
 
-	if (!gfs2_inum_equal(&inum, &ip->i_num))
-		return -ENOENT;
-
-	if (IF2DT(ip->i_inode.i_mode) != type) {
-		gfs2_consist_inode(dip);
-		return -EIO;
-	}
-
 	return 0;
 }
 
@@ -1132,10 +1186,11 @@
 	struct gfs2_glock *gl = gh->gh_gl;
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	struct gfs2_inode *ip = gl->gl_object;
-	s64 curtime, quantum = gfs2_tune_get(sdp, gt_atime_quantum);
+	s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum);
 	unsigned int state;
 	int flags;
 	int error;
+	struct timespec tv = CURRENT_TIME;
 
 	if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||
 	    gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||
@@ -1153,8 +1208,7 @@
 	    (sdp->sd_vfs->s_flags & MS_RDONLY))
 		return 0;
 
-	curtime = get_seconds();
-	if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
+	if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
 		gfs2_glock_dq(gh);
 		gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,
 				   gh);
@@ -1165,8 +1219,8 @@
 		/* Verify that atime hasn't been updated while we were
 		   trying to get exclusive lock. */
 
-		curtime = get_seconds();
-		if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
+		tv = CURRENT_TIME;
+		if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
 			struct buffer_head *dibh;
 			struct gfs2_dinode *di;
 
@@ -1180,11 +1234,12 @@
 			if (error)
 				goto fail_end_trans;
 
-			ip->i_inode.i_atime.tv_sec = curtime;
+			ip->i_inode.i_atime = tv;
 
 			gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 			di = (struct gfs2_dinode *)dibh->b_data;
 			di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
+			di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
 			brelse(dibh);
 
 			gfs2_trans_end(sdp);
@@ -1252,3 +1307,66 @@
 	return error;
 }
 
+void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
+{
+	const struct gfs2_dinode_host *di = &ip->i_di;
+	struct gfs2_dinode *str = buf;
+
+	str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
+	str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);
+	str->di_header.__pad0 = 0;
+	str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
+	str->di_header.__pad1 = 0;
+	str->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
+	str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
+	str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
+	str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
+	str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
+	str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
+	str->di_size = cpu_to_be64(di->di_size);
+	str->di_blocks = cpu_to_be64(di->di_blocks);
+	str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
+	str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
+	str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
+
+	str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
+	str->di_goal_data = cpu_to_be64(di->di_goal_data);
+	str->di_generation = cpu_to_be64(di->di_generation);
+
+	str->di_flags = cpu_to_be32(di->di_flags);
+	str->di_height = cpu_to_be16(di->di_height);
+	str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
+					     !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
+					     GFS2_FORMAT_DE : 0);
+	str->di_depth = cpu_to_be16(di->di_depth);
+	str->di_entries = cpu_to_be32(di->di_entries);
+
+	str->di_eattr = cpu_to_be64(di->di_eattr);
+	str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
+	str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec);
+	str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec);
+}
+
+void gfs2_dinode_print(const struct gfs2_inode *ip)
+{
+	const struct gfs2_dinode_host *di = &ip->i_di;
+
+	printk(KERN_INFO "  no_formal_ino = %llu\n",
+	       (unsigned long long)ip->i_no_formal_ino);
+	printk(KERN_INFO "  no_addr = %llu\n",
+	       (unsigned long long)ip->i_no_addr);
+	printk(KERN_INFO "  di_size = %llu\n", (unsigned long long)di->di_size);
+	printk(KERN_INFO "  di_blocks = %llu\n",
+	       (unsigned long long)di->di_blocks);
+	printk(KERN_INFO "  di_goal_meta = %llu\n",
+	       (unsigned long long)di->di_goal_meta);
+	printk(KERN_INFO "  di_goal_data = %llu\n",
+	       (unsigned long long)di->di_goal_data);
+	printk(KERN_INFO "  di_flags = 0x%.8X\n", di->di_flags);
+	printk(KERN_INFO "  di_height = %u\n", di->di_height);
+	printk(KERN_INFO "  di_depth = %u\n", di->di_depth);
+	printk(KERN_INFO "  di_entries = %u\n", di->di_entries);
+	printk(KERN_INFO "  di_eattr = %llu\n",
+	       (unsigned long long)di->di_eattr);
+}
+
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index b57f448..4517ac8 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -10,17 +10,17 @@
 #ifndef __INODE_DOT_H__
 #define __INODE_DOT_H__
 
-static inline int gfs2_is_stuffed(struct gfs2_inode *ip)
+static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
 {
 	return !ip->i_di.di_height;
 }
 
-static inline int gfs2_is_jdata(struct gfs2_inode *ip)
+static inline int gfs2_is_jdata(const struct gfs2_inode *ip)
 {
 	return ip->i_di.di_flags & GFS2_DIF_JDATA;
 }
 
-static inline int gfs2_is_dir(struct gfs2_inode *ip)
+static inline int gfs2_is_dir(const struct gfs2_inode *ip)
 {
 	return S_ISDIR(ip->i_inode.i_mode);
 }
@@ -32,9 +32,25 @@
 		(GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
 }
 
+static inline int gfs2_check_inum(const struct gfs2_inode *ip, u64 no_addr,
+				  u64 no_formal_ino)
+{
+	return ip->i_no_addr == no_addr && ip->i_no_formal_ino == no_formal_ino;
+}
+
+static inline void gfs2_inum_out(const struct gfs2_inode *ip,
+				 struct gfs2_dirent *dent)
+{
+	dent->de_inum.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
+	dent->de_inum.no_addr = cpu_to_be64(ip->i_no_addr);
+}
+
+
 void gfs2_inode_attr_in(struct gfs2_inode *ip);
-struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned type);
-struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum);
+void gfs2_set_iop(struct inode *inode);
+struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, 
+				u64 no_addr, u64 no_formal_ino);
+struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
 
 int gfs2_inode_refresh(struct gfs2_inode *ip);
 
@@ -47,12 +63,14 @@
 int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
 		struct gfs2_inode *ip);
 int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
-		   struct gfs2_inode *ip);
+		   const struct gfs2_inode *ip);
 int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to);
 int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len);
 int gfs2_glock_nq_atime(struct gfs2_holder *gh);
 int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
 struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
+void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
+void gfs2_dinode_print(const struct gfs2_inode *ip);
 
 #endif /* __INODE_DOT_H__ */
 
diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c
index c305255..542a797 100644
--- a/fs/gfs2/locking/dlm/lock.c
+++ b/fs/gfs2/locking/dlm/lock.c
@@ -174,7 +174,6 @@
 	lp->cur = DLM_LOCK_IV;
 	lp->lvb = NULL;
 	lp->hold_null = NULL;
-	init_completion(&lp->ast_wait);
 	INIT_LIST_HEAD(&lp->clist);
 	INIT_LIST_HEAD(&lp->blist);
 	INIT_LIST_HEAD(&lp->delay_list);
@@ -399,6 +398,12 @@
 	lp->lksb.sb_lvbptr = NULL;
 }
 
+static int gdlm_ast_wait(void *word)
+{
+	schedule();
+	return 0;
+}
+
 /* This can do a synchronous dlm request (requiring a lock_dlm thread to get
    the completion) because gfs won't call hold_lvb() during a callback (from
    the context of a lock_dlm thread). */
@@ -424,10 +429,10 @@
 	lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE;
 	set_bit(LFL_NOBAST, &lpn->flags);
 	set_bit(LFL_INLOCK, &lpn->flags);
+	set_bit(LFL_AST_WAIT, &lpn->flags);
 
-	init_completion(&lpn->ast_wait);
 	gdlm_do_lock(lpn);
-	wait_for_completion(&lpn->ast_wait);
+	wait_on_bit(&lpn->flags, LFL_AST_WAIT, gdlm_ast_wait, TASK_UNINTERRUPTIBLE);
 	error = lpn->lksb.sb_status;
 	if (error) {
 		printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n",
diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h
index d074c6e..24d70f7 100644
--- a/fs/gfs2/locking/dlm/lock_dlm.h
+++ b/fs/gfs2/locking/dlm/lock_dlm.h
@@ -101,6 +101,7 @@
 	LFL_NOBAST		= 10,
 	LFL_HEADQUE		= 11,
 	LFL_UNLOCK_DELETE	= 12,
+	LFL_AST_WAIT		= 13,
 };
 
 struct gdlm_lock {
@@ -117,7 +118,6 @@
 	unsigned long		flags;		/* lock_dlm flags LFL_ */
 
 	int			bast_mode;	/* protected by async_lock */
-	struct completion	ast_wait;
 
 	struct list_head	clist;		/* complete */
 	struct list_head	blist;		/* blocking */
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
index 1d8faa3..41c5b04 100644
--- a/fs/gfs2/locking/dlm/mount.c
+++ b/fs/gfs2/locking/dlm/mount.c
@@ -147,7 +147,7 @@
 
 	error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
 				  &ls->dlm_lockspace,
-				  nodir ? DLM_LSFL_NODIR : 0,
+				  DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
 				  GDLM_LVB_SIZE);
 	if (error) {
 		log_error("dlm_new_lockspace error %d", error);
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
index f82495e..fba1f1d 100644
--- a/fs/gfs2/locking/dlm/plock.c
+++ b/fs/gfs2/locking/dlm/plock.c
@@ -242,7 +242,7 @@
 	op->info.number		= name->ln_number;
 	op->info.start		= fl->fl_start;
 	op->info.end		= fl->fl_end;
-
+	op->info.owner		= (__u64)(long) fl->fl_owner;
 
 	send_op(op);
 	wait_event(recv_wq, (op->done != 0));
@@ -254,16 +254,20 @@
 	}
 	spin_unlock(&ops_lock);
 
+	/* info.rv from userspace is 1 for conflict, 0 for no-conflict,
+	   -ENOENT if there are no locks on the file */
+
 	rv = op->info.rv;
 
 	fl->fl_type = F_UNLCK;
 	if (rv == -ENOENT)
 		rv = 0;
-	else if (rv == 0 && op->info.pid != fl->fl_pid) {
+	else if (rv > 0) {
 		fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
 		fl->fl_pid = op->info.pid;
 		fl->fl_start = op->info.start;
 		fl->fl_end = op->info.end;
+		rv = 0;
 	}
 
 	kfree(op);
diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c
index 9cf1f16..1aca51e 100644
--- a/fs/gfs2/locking/dlm/thread.c
+++ b/fs/gfs2/locking/dlm/thread.c
@@ -44,6 +44,13 @@
 	ls->fscb(ls->sdp, cb, &lp->lockname);
 }
 
+static void wake_up_ast(struct gdlm_lock *lp)
+{
+	clear_bit(LFL_AST_WAIT, &lp->flags);
+	smp_mb__after_clear_bit();
+	wake_up_bit(&lp->flags, LFL_AST_WAIT);
+}
+
 static void process_complete(struct gdlm_lock *lp)
 {
 	struct gdlm_ls *ls = lp->ls;
@@ -136,7 +143,7 @@
 	 */
 
 	if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) {
-		complete(&lp->ast_wait);
+		wake_up_ast(lp);
 		return;
 	}
 
@@ -214,7 +221,7 @@
 	if (test_bit(LFL_INLOCK, &lp->flags)) {
 		clear_bit(LFL_NOBLOCK, &lp->flags);
 		lp->cur = lp->req;
-		complete(&lp->ast_wait);
+		wake_up_ast(lp);
 		return;
 	}
 
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 291415d..f49a12e 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -83,6 +83,11 @@
 
 			gfs2_assert(sdp, bd->bd_ail == ai);
 
+			if (!bh){
+				list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
+                                continue;
+                        }
+
 			if (!buffer_busy(bh)) {
 				if (!buffer_uptodate(bh)) {
 					gfs2_log_unlock(sdp);
@@ -125,6 +130,11 @@
 					 bd_ail_st_list) {
 		bh = bd->bd_bh;
 
+		if (!bh){
+			list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
+			continue;
+		}
+
 		gfs2_assert(sdp, bd->bd_ail == ai);
 
 		if (buffer_busy(bh)) {
@@ -262,8 +272,8 @@
  * @sdp: The GFS2 superblock
  * @blks: The number of blocks to reserve
  *
- * Note that we never give out the last 6 blocks of the journal. Thats
- * due to the fact that there is are a small number of header blocks
+ * Note that we never give out the last few blocks of the journal. Thats
+ * due to the fact that there is a small number of header blocks
  * associated with each log flush. The exact number can't be known until
  * flush time, so we ensure that we have just enough free blocks at all
  * times to avoid running out during a log flush.
@@ -274,6 +284,7 @@
 int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
 {
 	unsigned int try = 0;
+	unsigned reserved_blks = 6 * (4096 / sdp->sd_vfs->s_blocksize);
 
 	if (gfs2_assert_warn(sdp, blks) ||
 	    gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks))
@@ -281,7 +292,7 @@
 
 	mutex_lock(&sdp->sd_log_reserve_mutex);
 	gfs2_log_lock(sdp);
-	while(sdp->sd_log_blks_free <= (blks + 6)) {
+	while(sdp->sd_log_blks_free <= (blks + reserved_blks)) {
 		gfs2_log_unlock(sdp);
 		gfs2_ail1_empty(sdp, 0);
 		gfs2_log_flush(sdp, NULL);
@@ -357,6 +368,58 @@
 	return dist;
 }
 
+/**
+ * calc_reserved - Calculate the number of blocks to reserve when
+ *                 refunding a transaction's unused buffers.
+ * @sdp: The GFS2 superblock
+ *
+ * This is complex.  We need to reserve room for all our currently used
+ * metadata buffers (e.g. normal file I/O rewriting file time stamps) and 
+ * all our journaled data buffers for journaled files (e.g. files in the 
+ * meta_fs like rindex, or files for which chattr +j was done.)
+ * If we don't reserve enough space, gfs2_log_refund and gfs2_log_flush
+ * will count it as free space (sd_log_blks_free) and corruption will follow.
+ *
+ * We can have metadata bufs and jdata bufs in the same journal.  So each
+ * type gets its own log header, for which we need to reserve a block.
+ * In fact, each type has the potential for needing more than one header 
+ * in cases where we have more buffers than will fit on a journal page.
+ * Metadata journal entries take up half the space of journaled buffer entries.
+ * Thus, metadata entries have buf_limit (502) and journaled buffers have
+ * databuf_limit (251) before they cause a wrap around.
+ *
+ * Also, we need to reserve blocks for revoke journal entries and one for an
+ * overall header for the lot.
+ *
+ * Returns: the number of blocks reserved
+ */
+static unsigned int calc_reserved(struct gfs2_sbd *sdp)
+{
+	unsigned int reserved = 0;
+	unsigned int mbuf_limit, metabufhdrs_needed;
+	unsigned int dbuf_limit, databufhdrs_needed;
+	unsigned int revokes = 0;
+
+	mbuf_limit = buf_limit(sdp);
+	metabufhdrs_needed = (sdp->sd_log_commited_buf +
+			      (mbuf_limit - 1)) / mbuf_limit;
+	dbuf_limit = databuf_limit(sdp);
+	databufhdrs_needed = (sdp->sd_log_commited_databuf +
+			      (dbuf_limit - 1)) / dbuf_limit;
+
+	if (sdp->sd_log_commited_revoke)
+		revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
+					  sizeof(u64));
+
+	reserved = sdp->sd_log_commited_buf + metabufhdrs_needed +
+		sdp->sd_log_commited_databuf + databufhdrs_needed +
+		revokes;
+	/* One for the overall header */
+	if (reserved)
+		reserved++;
+	return reserved;
+}
+
 static unsigned int current_tail(struct gfs2_sbd *sdp)
 {
 	struct gfs2_ail *ai;
@@ -447,14 +510,14 @@
 	return bh;
 }
 
-static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail, int pull)
+static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
 {
 	unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail);
 
 	ail2_empty(sdp, new_tail);
 
 	gfs2_log_lock(sdp);
-	sdp->sd_log_blks_free += dist - (pull ? 1 : 0);
+	sdp->sd_log_blks_free += dist;
 	gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks);
 	gfs2_log_unlock(sdp);
 
@@ -504,7 +567,7 @@
 	brelse(bh);
 
 	if (sdp->sd_log_tail != tail)
-		log_pull_tail(sdp, tail, pull);
+		log_pull_tail(sdp, tail);
 	else
 		gfs2_assert_withdraw(sdp, !pull);
 
@@ -517,6 +580,7 @@
 	struct list_head *head = &sdp->sd_log_flush_list;
 	struct gfs2_log_buf *lb;
 	struct buffer_head *bh;
+	int flushcount = 0;
 
 	while (!list_empty(head)) {
 		lb = list_entry(head->next, struct gfs2_log_buf, lb_list);
@@ -533,9 +597,20 @@
 		} else
 			brelse(bh);
 		kfree(lb);
+		flushcount++;
 	}
 
-	log_write_header(sdp, 0, 0);
+	/* If nothing was journaled, the header is unplanned and unwanted. */
+	if (flushcount) {
+		log_write_header(sdp, 0, 0);
+	} else {
+		unsigned int tail;
+		tail = current_tail(sdp);
+
+		gfs2_ail1_empty(sdp, 0);
+		if (sdp->sd_log_tail != tail)
+			log_pull_tail(sdp, tail);
+	}
 }
 
 /**
@@ -565,7 +640,10 @@
 	INIT_LIST_HEAD(&ai->ai_ail1_list);
 	INIT_LIST_HEAD(&ai->ai_ail2_list);
 
-	gfs2_assert_withdraw(sdp, sdp->sd_log_num_buf == sdp->sd_log_commited_buf);
+	gfs2_assert_withdraw(sdp,
+			     sdp->sd_log_num_buf + sdp->sd_log_num_jdata ==
+			     sdp->sd_log_commited_buf +
+			     sdp->sd_log_commited_databuf);
 	gfs2_assert_withdraw(sdp,
 			sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke);
 
@@ -576,16 +654,19 @@
 	lops_before_commit(sdp);
 	if (!list_empty(&sdp->sd_log_flush_list))
 		log_flush_commit(sdp);
-	else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle)
+	else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
+		gfs2_log_lock(sdp);
+		sdp->sd_log_blks_free--; /* Adjust for unreserved buffer */
+		gfs2_log_unlock(sdp);
 		log_write_header(sdp, 0, PULL);
+	}
 	lops_after_commit(sdp, ai);
 
 	gfs2_log_lock(sdp);
 	sdp->sd_log_head = sdp->sd_log_flush_head;
-	sdp->sd_log_blks_free -= sdp->sd_log_num_hdrs;
 	sdp->sd_log_blks_reserved = 0;
 	sdp->sd_log_commited_buf = 0;
-	sdp->sd_log_num_hdrs = 0;
+	sdp->sd_log_commited_databuf = 0;
 	sdp->sd_log_commited_revoke = 0;
 
 	if (!list_empty(&ai->ai_ail1_list)) {
@@ -602,32 +683,26 @@
 
 static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
 {
-	unsigned int reserved = 0;
+	unsigned int reserved;
 	unsigned int old;
 
 	gfs2_log_lock(sdp);
 
 	sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm;
-	gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_buf) >= 0);
+	sdp->sd_log_commited_databuf += tr->tr_num_databuf_new -
+		tr->tr_num_databuf_rm;
+	gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) ||
+			     (((int)sdp->sd_log_commited_databuf) >= 0));
 	sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
 	gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
-
-	if (sdp->sd_log_commited_buf)
-		reserved += sdp->sd_log_commited_buf;
-	if (sdp->sd_log_commited_revoke)
-		reserved += gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
-					    sizeof(u64));
-	if (reserved)
-		reserved++;
-
+	reserved = calc_reserved(sdp);
 	old = sdp->sd_log_blks_free;
 	sdp->sd_log_blks_free += tr->tr_reserved -
 				 (reserved - sdp->sd_log_blks_reserved);
 
 	gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old);
-	gfs2_assert_withdraw(sdp,
-			     sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks +
-			     sdp->sd_log_num_hdrs);
+	gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <=
+			     sdp->sd_jdesc->jd_blocks);
 
 	sdp->sd_log_blks_reserved = reserved;
 
@@ -673,13 +748,13 @@
 	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
 	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
 	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf);
-	gfs2_assert_withdraw(sdp, !sdp->sd_log_num_hdrs);
 	gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list));
 
 	sdp->sd_log_flush_head = sdp->sd_log_head;
 	sdp->sd_log_flush_wrapped = 0;
 
-	log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, 0);
+	log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
+			 (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL);
 
 	gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks);
 	gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index f82d84d..aff70f0 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -17,6 +17,7 @@
 
 #include "gfs2.h"
 #include "incore.h"
+#include "inode.h"
 #include "glock.h"
 #include "log.h"
 #include "lops.h"
@@ -117,15 +118,13 @@
 	struct gfs2_log_descriptor *ld;
 	struct gfs2_bufdata *bd1 = NULL, *bd2;
 	unsigned int total = sdp->sd_log_num_buf;
-	unsigned int offset = sizeof(struct gfs2_log_descriptor);
+	unsigned int offset = BUF_OFFSET;
 	unsigned int limit;
 	unsigned int num;
 	unsigned n;
 	__be64 *ptr;
 
-	offset += sizeof(__be64) - 1;
-	offset &= ~(sizeof(__be64) - 1);
-	limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
+	limit = buf_limit(sdp);
 	/* for 4k blocks, limit = 503 */
 
 	bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list);
@@ -134,7 +133,6 @@
 		if (total > limit)
 			num = limit;
 		bh = gfs2_log_get_buf(sdp);
-		sdp->sd_log_num_hdrs++;
 		ld = (struct gfs2_log_descriptor *)bh->b_data;
 		ptr = (__be64 *)(bh->b_data + offset);
 		ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
@@ -469,25 +467,28 @@
 	struct gfs2_inode *ip = GFS2_I(mapping->host);
 
 	gfs2_log_lock(sdp);
+	if (!list_empty(&bd->bd_list_tr)) {
+		gfs2_log_unlock(sdp);
+		return;
+	}
 	tr->tr_touched = 1;
-	if (list_empty(&bd->bd_list_tr) &&
-	    (ip->i_di.di_flags & GFS2_DIF_JDATA)) {
+	if (gfs2_is_jdata(ip)) {
 		tr->tr_num_buf++;
 		list_add(&bd->bd_list_tr, &tr->tr_list_buf);
-		gfs2_log_unlock(sdp);
-		gfs2_pin(sdp, bd->bd_bh);
-		tr->tr_num_buf_new++;
-	} else {
-		gfs2_log_unlock(sdp);
 	}
+	gfs2_log_unlock(sdp);
+	if (!list_empty(&le->le_list))
+		return;
+
 	gfs2_trans_add_gl(bd->bd_gl);
-	gfs2_log_lock(sdp);
-	if (list_empty(&le->le_list)) {
-		if (ip->i_di.di_flags & GFS2_DIF_JDATA)
-			sdp->sd_log_num_jdata++;
-		sdp->sd_log_num_databuf++;
-		list_add(&le->le_list, &sdp->sd_log_le_databuf);
+	if (gfs2_is_jdata(ip)) {
+		sdp->sd_log_num_jdata++;
+		gfs2_pin(sdp, bd->bd_bh);
+		tr->tr_num_databuf_new++;
 	}
+	sdp->sd_log_num_databuf++;
+	gfs2_log_lock(sdp);
+	list_add(&le->le_list, &sdp->sd_log_le_databuf);
 	gfs2_log_unlock(sdp);
 }
 
@@ -520,7 +521,6 @@
 	LIST_HEAD(started);
 	struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt;
 	struct buffer_head *bh = NULL,*bh1 = NULL;
-	unsigned int offset = sizeof(struct gfs2_log_descriptor);
 	struct gfs2_log_descriptor *ld;
 	unsigned int limit;
 	unsigned int total_dbuf = sdp->sd_log_num_databuf;
@@ -528,9 +528,7 @@
 	unsigned int num, n;
 	__be64 *ptr = NULL;
 
-	offset += 2*sizeof(__be64) - 1;
-	offset &= ~(2*sizeof(__be64) - 1);
-	limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
+	limit = databuf_limit(sdp);
 
 	/*
 	 * Start writing ordered buffers, write journaled buffers
@@ -581,10 +579,10 @@
 				gfs2_log_unlock(sdp);
 				if (!bh) {
 					bh = gfs2_log_get_buf(sdp);
-					sdp->sd_log_num_hdrs++;
 					ld = (struct gfs2_log_descriptor *)
 					     bh->b_data;
-					ptr = (__be64 *)(bh->b_data + offset);
+					ptr = (__be64 *)(bh->b_data +
+							 DATABUF_OFFSET);
 					ld->ld_header.mh_magic =
 						cpu_to_be32(GFS2_MAGIC);
 					ld->ld_header.mh_type =
@@ -605,7 +603,7 @@
 				if (unlikely(magic != 0))
 					set_buffer_escaped(bh1);
 				gfs2_log_lock(sdp);
-				if (n++ > num)
+				if (++n >= num)
 					break;
 			} else if (!bh1) {
 				total_dbuf--;
@@ -622,6 +620,7 @@
 		}
 		gfs2_log_unlock(sdp);
 		if (bh) {
+			set_buffer_mapped(bh);
 			set_buffer_dirty(bh);
 			ll_rw_block(WRITE, 1, &bh);
 			bh = NULL;
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
index 965bc65..41a00df 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -13,6 +13,13 @@
 #include <linux/list.h>
 #include "incore.h"
 
+#define BUF_OFFSET \
+	((sizeof(struct gfs2_log_descriptor) + sizeof(__be64) - 1) & \
+	 ~(sizeof(__be64) - 1))
+#define DATABUF_OFFSET \
+	((sizeof(struct gfs2_log_descriptor) + (2 * sizeof(__be64) - 1)) & \
+	 ~(2 * sizeof(__be64) - 1))
+
 extern const struct gfs2_log_operations gfs2_glock_lops;
 extern const struct gfs2_log_operations gfs2_buf_lops;
 extern const struct gfs2_log_operations gfs2_revoke_lops;
@@ -21,6 +28,22 @@
 
 extern const struct gfs2_log_operations *gfs2_log_ops[];
 
+static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
+{
+	unsigned int limit;
+
+	limit = (sdp->sd_sb.sb_bsize - BUF_OFFSET) / sizeof(__be64);
+	return limit;
+}
+
+static inline unsigned int databuf_limit(struct gfs2_sbd *sdp)
+{
+	unsigned int limit;
+
+	limit = (sdp->sd_sb.sb_bsize - DATABUF_OFFSET) / (2 * sizeof(__be64));
+	return limit;
+}
+
 static inline void lops_init_le(struct gfs2_log_element *le,
 				const struct gfs2_log_operations *lops)
 {
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index e62d4f6..8da343b 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -387,12 +387,18 @@
 
 			if (test_clear_buffer_pinned(bh)) {
 				struct gfs2_trans *tr = current->journal_info;
+				struct gfs2_inode *bh_ip =
+					GFS2_I(bh->b_page->mapping->host);
+
 				gfs2_log_lock(sdp);
 				list_del_init(&bd->bd_le.le_list);
 				gfs2_assert_warn(sdp, sdp->sd_log_num_buf);
 				sdp->sd_log_num_buf--;
 				gfs2_log_unlock(sdp);
-				tr->tr_num_buf_rm++;
+				if (bh_ip->i_inode.i_private != NULL)
+					tr->tr_num_databuf_rm++;
+				else
+					tr->tr_num_buf_rm++;
 				brelse(bh);
 			}
 			if (bd) {
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index e037425..527bf19 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -63,7 +63,7 @@
 static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip,
 					 struct buffer_head **bhp)
 {
-	return gfs2_meta_indirect_buffer(ip, 0, ip->i_num.no_addr, 0, bhp);
+	return gfs2_meta_indirect_buffer(ip, 0, ip->i_no_addr, 0, bhp);
 }
 
 struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen);
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c
index 4864659..6f006a80 100644
--- a/fs/gfs2/mount.c
+++ b/fs/gfs2/mount.c
@@ -82,20 +82,19 @@
 	char *options, *o, *v;
 	int error = 0;
 
-	if (!remount) {
-		/*  If someone preloaded options, use those instead  */
-		spin_lock(&gfs2_sys_margs_lock);
-		if (gfs2_sys_margs) {
-			data = gfs2_sys_margs;
-			gfs2_sys_margs = NULL;
-		}
-		spin_unlock(&gfs2_sys_margs_lock);
-
-		/*  Set some defaults  */
-		args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
-		args->ar_quota = GFS2_QUOTA_DEFAULT;
-		args->ar_data = GFS2_DATA_DEFAULT;
+	/*  If someone preloaded options, use those instead  */
+	spin_lock(&gfs2_sys_margs_lock);
+	if (!remount && gfs2_sys_margs) {
+		data = gfs2_sys_margs;
+		gfs2_sys_margs = NULL;
 	}
+	spin_unlock(&gfs2_sys_margs_lock);
+
+	/*  Set some defaults  */
+	memset(args, 0, sizeof(struct gfs2_args));
+	args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
+	args->ar_quota = GFS2_QUOTA_DEFAULT;
+	args->ar_data = GFS2_DATA_DEFAULT;
 
 	/* Split the options into tokens with the "," character and
 	   process them */
diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c
deleted file mode 100644
index d9ecfd2..0000000
--- a/fs/gfs2/ondisk.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs2.h"
-#include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
-#include "incore.h"
-
-#define pv(struct, member, fmt) printk(KERN_INFO "  "#member" = "fmt"\n", \
-				       struct->member);
-
-/*
- * gfs2_xxx_in - read in an xxx struct
- * first arg: the cpu-order structure
- * buf: the disk-order buffer
- *
- * gfs2_xxx_out - write out an xxx struct
- * first arg: the cpu-order structure
- * buf: the disk-order buffer
- *
- * gfs2_xxx_print - print out an xxx struct
- * first arg: the cpu-order structure
- */
-
-void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf)
-{
-	const struct gfs2_inum *str = buf;
-
-	no->no_formal_ino = be64_to_cpu(str->no_formal_ino);
-	no->no_addr = be64_to_cpu(str->no_addr);
-}
-
-void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf)
-{
-	struct gfs2_inum *str = buf;
-
-	str->no_formal_ino = cpu_to_be64(no->no_formal_ino);
-	str->no_addr = cpu_to_be64(no->no_addr);
-}
-
-static void gfs2_inum_print(const struct gfs2_inum_host *no)
-{
-	printk(KERN_INFO "  no_formal_ino = %llu\n", (unsigned long long)no->no_formal_ino);
-	printk(KERN_INFO "  no_addr = %llu\n", (unsigned long long)no->no_addr);
-}
-
-static void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf)
-{
-	const struct gfs2_meta_header *str = buf;
-
-	mh->mh_magic = be32_to_cpu(str->mh_magic);
-	mh->mh_type = be32_to_cpu(str->mh_type);
-	mh->mh_format = be32_to_cpu(str->mh_format);
-}
-
-void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf)
-{
-	const struct gfs2_sb *str = buf;
-
-	gfs2_meta_header_in(&sb->sb_header, buf);
-
-	sb->sb_fs_format = be32_to_cpu(str->sb_fs_format);
-	sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format);
-	sb->sb_bsize = be32_to_cpu(str->sb_bsize);
-	sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift);
-
-	gfs2_inum_in(&sb->sb_master_dir, (char *)&str->sb_master_dir);
-	gfs2_inum_in(&sb->sb_root_dir, (char *)&str->sb_root_dir);
-
-	memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
-	memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
-}
-
-void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf)
-{
-	const struct gfs2_rindex *str = buf;
-
-	ri->ri_addr = be64_to_cpu(str->ri_addr);
-	ri->ri_length = be32_to_cpu(str->ri_length);
-	ri->ri_data0 = be64_to_cpu(str->ri_data0);
-	ri->ri_data = be32_to_cpu(str->ri_data);
-	ri->ri_bitbytes = be32_to_cpu(str->ri_bitbytes);
-
-}
-
-void gfs2_rindex_print(const struct gfs2_rindex_host *ri)
-{
-	printk(KERN_INFO "  ri_addr = %llu\n", (unsigned long long)ri->ri_addr);
-	pv(ri, ri_length, "%u");
-
-	printk(KERN_INFO "  ri_data0 = %llu\n", (unsigned long long)ri->ri_data0);
-	pv(ri, ri_data, "%u");
-
-	pv(ri, ri_bitbytes, "%u");
-}
-
-void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
-{
-	const struct gfs2_rgrp *str = buf;
-
-	rg->rg_flags = be32_to_cpu(str->rg_flags);
-	rg->rg_free = be32_to_cpu(str->rg_free);
-	rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
-	rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
-}
-
-void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
-{
-	struct gfs2_rgrp *str = buf;
-
-	str->rg_flags = cpu_to_be32(rg->rg_flags);
-	str->rg_free = cpu_to_be32(rg->rg_free);
-	str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
-	str->__pad = cpu_to_be32(0);
-	str->rg_igeneration = cpu_to_be64(rg->rg_igeneration);
-	memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
-}
-
-void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf)
-{
-	const struct gfs2_quota *str = buf;
-
-	qu->qu_limit = be64_to_cpu(str->qu_limit);
-	qu->qu_warn = be64_to_cpu(str->qu_warn);
-	qu->qu_value = be64_to_cpu(str->qu_value);
-}
-
-void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
-{
-	const struct gfs2_dinode_host *di = &ip->i_di;
-	struct gfs2_dinode *str = buf;
-
-	str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
-	str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);
-	str->di_header.__pad0 = 0;
-	str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
-	str->di_header.__pad1 = 0;
-
-	gfs2_inum_out(&ip->i_num, &str->di_num);
-
-	str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
-	str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
-	str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
-	str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
-	str->di_size = cpu_to_be64(di->di_size);
-	str->di_blocks = cpu_to_be64(di->di_blocks);
-	str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
-	str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
-	str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
-
-	str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
-	str->di_goal_data = cpu_to_be64(di->di_goal_data);
-	str->di_generation = cpu_to_be64(di->di_generation);
-
-	str->di_flags = cpu_to_be32(di->di_flags);
-	str->di_height = cpu_to_be16(di->di_height);
-	str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
-					     !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
-					     GFS2_FORMAT_DE : 0);
-	str->di_depth = cpu_to_be16(di->di_depth);
-	str->di_entries = cpu_to_be32(di->di_entries);
-
-	str->di_eattr = cpu_to_be64(di->di_eattr);
-}
-
-void gfs2_dinode_print(const struct gfs2_inode *ip)
-{
-	const struct gfs2_dinode_host *di = &ip->i_di;
-
-	gfs2_inum_print(&ip->i_num);
-
-	printk(KERN_INFO "  di_size = %llu\n", (unsigned long long)di->di_size);
-	printk(KERN_INFO "  di_blocks = %llu\n", (unsigned long long)di->di_blocks);
-	printk(KERN_INFO "  di_goal_meta = %llu\n", (unsigned long long)di->di_goal_meta);
-	printk(KERN_INFO "  di_goal_data = %llu\n", (unsigned long long)di->di_goal_data);
-
-	pv(di, di_flags, "0x%.8X");
-	pv(di, di_height, "%u");
-
-	pv(di, di_depth, "%u");
-	pv(di, di_entries, "%u");
-
-	printk(KERN_INFO "  di_eattr = %llu\n", (unsigned long long)di->di_eattr);
-}
-
-void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
-{
-	const struct gfs2_log_header *str = buf;
-
-	gfs2_meta_header_in(&lh->lh_header, buf);
-	lh->lh_sequence = be64_to_cpu(str->lh_sequence);
-	lh->lh_flags = be32_to_cpu(str->lh_flags);
-	lh->lh_tail = be32_to_cpu(str->lh_tail);
-	lh->lh_blkno = be32_to_cpu(str->lh_blkno);
-	lh->lh_hash = be32_to_cpu(str->lh_hash);
-}
-
-void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf)
-{
-	const struct gfs2_inum_range *str = buf;
-
-	ir->ir_start = be64_to_cpu(str->ir_start);
-	ir->ir_length = be64_to_cpu(str->ir_length);
-}
-
-void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf)
-{
-	struct gfs2_inum_range *str = buf;
-
-	str->ir_start = cpu_to_be64(ir->ir_start);
-	str->ir_length = cpu_to_be64(ir->ir_length);
-}
-
-void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
-{
-	const struct gfs2_statfs_change *str = buf;
-
-	sc->sc_total = be64_to_cpu(str->sc_total);
-	sc->sc_free = be64_to_cpu(str->sc_free);
-	sc->sc_dinodes = be64_to_cpu(str->sc_dinodes);
-}
-
-void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf)
-{
-	struct gfs2_statfs_change *str = buf;
-
-	str->sc_total = cpu_to_be64(sc->sc_total);
-	str->sc_free = cpu_to_be64(sc->sc_free);
-	str->sc_dinodes = cpu_to_be64(sc->sc_dinodes);
-}
-
-void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf)
-{
-	const struct gfs2_quota_change *str = buf;
-
-	qc->qc_change = be64_to_cpu(str->qc_change);
-	qc->qc_flags = be32_to_cpu(str->qc_flags);
-	qc->qc_id = be32_to_cpu(str->qc_id);
-}
-
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 30c1562..26c8888 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
@@ -32,6 +32,7 @@
 #include "trans.h"
 #include "rgrp.h"
 #include "ops_file.h"
+#include "super.h"
 #include "util.h"
 #include "glops.h"
 
@@ -49,6 +50,8 @@
 		end = start + bsize;
 		if (end <= from || start >= to)
 			continue;
+		if (gfs2_is_jdata(ip))
+			set_buffer_uptodate(bh);
 		gfs2_trans_add_bh(ip->i_gl, bh, 0);
 	}
 }
@@ -134,7 +137,9 @@
 		return 0; /* don't care */
 	}
 
-	if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) {
+	if ((sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) &&
+	    PageChecked(page)) {
+		ClearPageChecked(page);
 		error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0);
 		if (error)
 			goto out_ignore;
@@ -203,11 +208,7 @@
 	 * so we need to supply one here. It doesn't happen often.
 	 */
 	if (unlikely(page->index)) {
-		kaddr = kmap_atomic(page, KM_USER0);
-		memset(kaddr, 0, PAGE_CACHE_SIZE);
-		kunmap_atomic(kaddr, KM_USER0);
-		flush_dcache_page(page);
-		SetPageUptodate(page);
+		zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
 		return 0;
 	}
 
@@ -450,6 +451,31 @@
 }
 
 /**
+ * adjust_fs_space - Adjusts the free space available due to gfs2_grow
+ * @inode: the rindex inode
+ */
+static void adjust_fs_space(struct inode *inode)
+{
+	struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
+	struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
+	struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+	u64 fs_total, new_free;
+
+	/* Total up the file system space, according to the latest rindex. */
+	fs_total = gfs2_ri_total(sdp);
+
+	spin_lock(&sdp->sd_statfs_spin);
+	if (fs_total > (m_sc->sc_total + l_sc->sc_total))
+		new_free = fs_total - (m_sc->sc_total + l_sc->sc_total);
+	else
+		new_free = 0;
+	spin_unlock(&sdp->sd_statfs_spin);
+	fs_warn(sdp, "File system extended by %llu blocks.\n",
+		(unsigned long long)new_free);
+	gfs2_statfs_change(sdp, new_free, new_free, 0);
+}
+
+/**
  * gfs2_commit_write - Commit write to a file
  * @file: The file to write to
  * @page: The page containing the data
@@ -511,6 +537,9 @@
 		di->di_size = cpu_to_be64(inode->i_size);
 	}
 
+	if (inode == sdp->sd_rindex)
+		adjust_fs_space(inode);
+
 	brelse(dibh);
 	gfs2_trans_end(sdp);
 	if (al->al_requested) {
@@ -543,6 +572,23 @@
 }
 
 /**
+ * gfs2_set_page_dirty - Page dirtying function
+ * @page: The page to dirty
+ *
+ * Returns: 1 if it dirtyed the page, or 0 otherwise
+ */
+ 
+static int gfs2_set_page_dirty(struct page *page)
+{
+	struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+	struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
+
+	if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
+		SetPageChecked(page);
+	return __set_page_dirty_buffers(page);
+}
+
+/**
  * gfs2_bmap - Block map function
  * @mapping: Address space info
  * @lblock: The block to map
@@ -578,6 +624,8 @@
 	if (bd) {
 		bd->bd_bh = NULL;
 		bh->b_private = NULL;
+		if (!bd->bd_ail && list_empty(&bd->bd_le.le_list))
+			kmem_cache_free(gfs2_bufdata_cachep, bd);
 	}
 	gfs2_log_unlock(sdp);
 
@@ -598,6 +646,8 @@
 	unsigned int curr_off = 0;
 
 	BUG_ON(!PageLocked(page));
+	if (offset == 0)
+		ClearPageChecked(page);
 	if (!page_has_buffers(page))
 		return;
 
@@ -728,8 +778,8 @@
 			return;
 
 		fs_warn(sdp, "ip = %llu %llu\n",
-			(unsigned long long)ip->i_num.no_formal_ino,
-			(unsigned long long)ip->i_num.no_addr);
+			(unsigned long long)ip->i_no_formal_ino,
+			(unsigned long long)ip->i_no_addr);
 
 		for (x = 0; x < GFS2_MAX_META_HEIGHT; x++)
 			fs_warn(sdp, "ip->i_cache[%u] = %s\n",
@@ -810,6 +860,7 @@
 	.sync_page = block_sync_page,
 	.prepare_write = gfs2_prepare_write,
 	.commit_write = gfs2_commit_write,
+	.set_page_dirty = gfs2_set_page_dirty,
 	.bmap = gfs2_bmap,
 	.invalidatepage = gfs2_invalidatepage,
 	.releasepage = gfs2_releasepage,
diff --git a/fs/gfs2/ops_address.h b/fs/gfs2/ops_address.h
index 35aaee4..fa1b5b3 100644
--- a/fs/gfs2/ops_address.h
+++ b/fs/gfs2/ops_address.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c
index a6fdc52..793e334 100644
--- a/fs/gfs2/ops_dentry.c
+++ b/fs/gfs2/ops_dentry.c
@@ -21,6 +21,7 @@
 #include "glock.h"
 #include "ops_dentry.h"
 #include "util.h"
+#include "inode.h"
 
 /**
  * gfs2_drevalidate - Check directory lookup consistency
@@ -40,14 +41,15 @@
 	struct gfs2_inode *dip = GFS2_I(parent->d_inode);
 	struct inode *inode = dentry->d_inode;
 	struct gfs2_holder d_gh;
-	struct gfs2_inode *ip;
-	struct gfs2_inum_host inum;
-	unsigned int type;
+	struct gfs2_inode *ip = NULL;
 	int error;
 	int had_lock=0;
 
-	if (inode && is_bad_inode(inode))
-		goto invalid;
+	if (inode) {
+		if (is_bad_inode(inode))
+			goto invalid;
+		ip = GFS2_I(inode);
+	}
 
 	if (sdp->sd_args.ar_localcaching)
 		goto valid;
@@ -59,7 +61,7 @@
 			goto fail;
 	} 
 
-	error = gfs2_dir_search(parent->d_inode, &dentry->d_name, &inum, &type);
+	error = gfs2_dir_check(parent->d_inode, &dentry->d_name, ip);
 	switch (error) {
 	case 0:
 		if (!inode)
@@ -73,16 +75,6 @@
 		goto fail_gunlock;
 	}
 
-	ip = GFS2_I(inode);
-
-	if (!gfs2_inum_equal(&ip->i_num, &inum))
-		goto invalid_gunlock;
-
-	if (IF2DT(ip->i_inode.i_mode) != type) {
-		gfs2_consist_inode(dip);
-		goto fail_gunlock;
-	}
-
 valid_gunlock:
 	if (!had_lock)
 		gfs2_glock_dq_uninit(&d_gh);
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index aad9183..99ea565 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -22,10 +22,14 @@
 #include "glops.h"
 #include "inode.h"
 #include "ops_dentry.h"
-#include "ops_export.h"
+#include "ops_fstype.h"
 #include "rgrp.h"
 #include "util.h"
 
+#define GFS2_SMALL_FH_SIZE 4
+#define GFS2_LARGE_FH_SIZE 8
+#define GFS2_OLD_FH_SIZE 10
+
 static struct dentry *gfs2_decode_fh(struct super_block *sb,
 				     __u32 *p,
 				     int fh_len,
@@ -35,31 +39,28 @@
 				     void *context)
 {
 	__be32 *fh = (__force __be32 *)p;
-	struct gfs2_fh_obj fh_obj;
-	struct gfs2_inum_host *this, parent;
+	struct gfs2_inum_host inum, parent;
 
-	this 		= &fh_obj.this;
-	fh_obj.imode 	= DT_UNKNOWN;
 	memset(&parent, 0, sizeof(struct gfs2_inum));
 
 	switch (fh_len) {
 	case GFS2_LARGE_FH_SIZE:
+	case GFS2_OLD_FH_SIZE:
 		parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
 		parent.no_formal_ino |= be32_to_cpu(fh[5]);
 		parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
 		parent.no_addr |= be32_to_cpu(fh[7]);
-		fh_obj.imode = be32_to_cpu(fh[8]);
 	case GFS2_SMALL_FH_SIZE:
-		this->no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
-		this->no_formal_ino |= be32_to_cpu(fh[1]);
-		this->no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
-		this->no_addr |= be32_to_cpu(fh[3]);
+		inum.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
+		inum.no_formal_ino |= be32_to_cpu(fh[1]);
+		inum.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
+		inum.no_addr |= be32_to_cpu(fh[3]);
 		break;
 	default:
 		return NULL;
 	}
 
-	return gfs2_export_ops.find_exported_dentry(sb, &fh_obj, &parent,
+	return gfs2_export_ops.find_exported_dentry(sb, &inum, &parent,
 						    acceptable, context);
 }
 
@@ -75,10 +76,10 @@
 	    (connectable && *len < GFS2_LARGE_FH_SIZE))
 		return 255;
 
-	fh[0] = cpu_to_be32(ip->i_num.no_formal_ino >> 32);
-	fh[1] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF);
-	fh[2] = cpu_to_be32(ip->i_num.no_addr >> 32);
-	fh[3] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF);
+	fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
+	fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
+	fh[2] = cpu_to_be32(ip->i_no_addr >> 32);
+	fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
 	*len = GFS2_SMALL_FH_SIZE;
 
 	if (!connectable || inode == sb->s_root->d_inode)
@@ -90,13 +91,10 @@
 	igrab(inode);
 	spin_unlock(&dentry->d_lock);
 
-	fh[4] = cpu_to_be32(ip->i_num.no_formal_ino >> 32);
-	fh[5] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF);
-	fh[6] = cpu_to_be32(ip->i_num.no_addr >> 32);
-	fh[7] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF);
-
-	fh[8]  = cpu_to_be32(inode->i_mode);
-	fh[9]  = 0;	/* pad to double word */
+	fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
+	fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
+	fh[6] = cpu_to_be32(ip->i_no_addr >> 32);
+	fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
 	*len = GFS2_LARGE_FH_SIZE;
 
 	iput(inode);
@@ -144,7 +142,8 @@
 	ip = GFS2_I(inode);
 
 	*name = 0;
-	gnfd.inum = ip->i_num;
+	gnfd.inum.no_addr = ip->i_no_addr;
+	gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
 	gnfd.name = name;
 
 	error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
@@ -192,8 +191,7 @@
 static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
 {
 	struct gfs2_sbd *sdp = sb->s_fs_info;
-	struct gfs2_fh_obj *fh_obj = (struct gfs2_fh_obj *)inum_obj;
-	struct gfs2_inum_host *inum = &fh_obj->this;
+	struct gfs2_inum_host *inum = inum_obj;
 	struct gfs2_holder i_gh, ri_gh, rgd_gh;
 	struct gfs2_rgrpd *rgd;
 	struct inode *inode;
@@ -202,9 +200,9 @@
 
 	/* System files? */
 
-	inode = gfs2_ilookup(sb, inum);
+	inode = gfs2_ilookup(sb, inum->no_addr);
 	if (inode) {
-		if (GFS2_I(inode)->i_num.no_formal_ino != inum->no_formal_ino) {
+		if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
 			iput(inode);
 			return ERR_PTR(-ESTALE);
 		}
@@ -236,7 +234,9 @@
 	gfs2_glock_dq_uninit(&rgd_gh);
 	gfs2_glock_dq_uninit(&ri_gh);
 
-	inode = gfs2_inode_lookup(sb, inum, fh_obj->imode);
+	inode = gfs2_inode_lookup(sb, DT_UNKNOWN,
+					inum->no_addr,
+					0);
 	if (!inode)
 		goto fail;
 	if (IS_ERR(inode)) {
@@ -250,6 +250,15 @@
 		goto fail;
 	}
 
+	/* Pick up the works we bypass in gfs2_inode_lookup */
+	if (inode->i_state & I_NEW) 
+		gfs2_set_iop(inode);
+
+	if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
+		iput(inode);
+		goto fail;
+	}
+
 	error = -EIO;
 	if (GFS2_I(inode)->i_di.di_flags & GFS2_DIF_SYSTEM) {
 		iput(inode);
diff --git a/fs/gfs2/ops_export.h b/fs/gfs2/ops_export.h
deleted file mode 100644
index f925a95..0000000
--- a/fs/gfs2/ops_export.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#ifndef __OPS_EXPORT_DOT_H__
-#define __OPS_EXPORT_DOT_H__
-
-#define GFS2_SMALL_FH_SIZE 4
-#define GFS2_LARGE_FH_SIZE 10
-
-extern struct export_operations gfs2_export_ops;
-struct gfs2_fh_obj {
-	struct gfs2_inum_host this;
-	__u32            imode;
-};
-
-#endif /* __OPS_EXPORT_DOT_H__ */
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 064df88..196d832 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -502,7 +502,7 @@
 	struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
 	struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
 	struct lm_lockname name =
-		{ .ln_number = ip->i_num.no_addr,
+		{ .ln_number = ip->i_no_addr,
 		  .ln_type = LM_TYPE_PLOCK };
 
 	if (!(fl->fl_flags & FL_POSIX))
@@ -557,7 +557,7 @@
 		gfs2_glock_dq_uninit(fl_gh);
 	} else {
 		error = gfs2_glock_get(GFS2_SB(&ip->i_inode),
-				      ip->i_num.no_addr, &gfs2_flock_glops,
+				      ip->i_no_addr, &gfs2_flock_glops,
 				      CREATE, &gl);
 		if (error)
 			goto out;
@@ -635,7 +635,6 @@
 	.release	= gfs2_close,
 	.fsync		= gfs2_fsync,
 	.lock		= gfs2_lock,
-	.sendfile	= generic_file_sendfile,
 	.flock		= gfs2_flock,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 2c5f8e7..cf5aa50 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -27,7 +27,6 @@
 #include "inode.h"
 #include "lm.h"
 #include "mount.h"
-#include "ops_export.h"
 #include "ops_fstype.h"
 #include "ops_super.h"
 #include "recovery.h"
@@ -105,6 +104,7 @@
 	sb->s_magic = GFS2_MAGIC;
 	sb->s_op = &gfs2_super_ops;
 	sb->s_export_op = &gfs2_export_ops;
+	sb->s_time_gran = 1;
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
 
 	if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME))
@@ -116,7 +116,6 @@
 
 static int init_names(struct gfs2_sbd *sdp, int silent)
 {
-	struct page *page;
 	char *proto, *table;
 	int error = 0;
 
@@ -126,14 +125,9 @@
 	/*  Try to autodetect  */
 
 	if (!proto[0] || !table[0]) {
-		struct gfs2_sb *sb;
-		page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
-		if (!page)
-			return -ENOBUFS;
-		sb = kmap(page);
-		gfs2_sb_in(&sdp->sd_sb, sb);
-		kunmap(page);
-		__free_page(page);
+		error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
+		if (error)
+			return error;
 
 		error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
 		if (error)
@@ -151,6 +145,9 @@
 	snprintf(sdp->sd_proto_name, GFS2_FSNAME_LEN, "%s", proto);
 	snprintf(sdp->sd_table_name, GFS2_FSNAME_LEN, "%s", table);
 
+	while ((table = strchr(sdp->sd_table_name, '/')))
+		*table = '_';
+
 out:
 	return error;
 }
@@ -236,17 +233,17 @@
 	return error;
 }
 
-static struct inode *gfs2_lookup_root(struct super_block *sb,
-				      struct gfs2_inum_host *inum)
+static inline struct inode *gfs2_lookup_root(struct super_block *sb,
+					     u64 no_addr)
 {
-	return gfs2_inode_lookup(sb, inum, DT_DIR);
+	return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0);
 }
 
 static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
 {
 	struct super_block *sb = sdp->sd_vfs;
 	struct gfs2_holder sb_gh;
-	struct gfs2_inum_host *inum;
+	u64 no_addr;
 	struct inode *inode;
 	int error = 0;
 
@@ -289,10 +286,10 @@
 	sb_set_blocksize(sb, sdp->sd_sb.sb_bsize);
 
 	/* Get the root inode */
-	inum = &sdp->sd_sb.sb_root_dir;
+	no_addr = sdp->sd_sb.sb_root_dir.no_addr;
 	if (sb->s_type == &gfs2meta_fs_type)
-		inum = &sdp->sd_sb.sb_master_dir;
-	inode = gfs2_lookup_root(sb, inum);
+		no_addr = sdp->sd_sb.sb_master_dir.no_addr;
+	inode = gfs2_lookup_root(sb, no_addr);
 	if (IS_ERR(inode)) {
 		error = PTR_ERR(inode);
 		fs_err(sdp, "can't read in root inode: %d\n", error);
@@ -449,7 +446,7 @@
 	if (undo)
 		goto fail_qinode;
 
-	inode = gfs2_lookup_root(sdp->sd_vfs, &sdp->sd_sb.sb_master_dir);
+	inode = gfs2_lookup_root(sdp->sd_vfs, sdp->sd_sb.sb_master_dir.no_addr);
 	if (IS_ERR(inode)) {
 		error = PTR_ERR(inode);
 		fs_err(sdp, "can't read in master directory: %d\n", error);
diff --git a/fs/gfs2/ops_fstype.h b/fs/gfs2/ops_fstype.h
index 7cc2c29..407029b 100644
--- a/fs/gfs2/ops_fstype.h
+++ b/fs/gfs2/ops_fstype.h
@@ -14,5 +14,6 @@
 
 extern struct file_system_type gfs2_fs_type;
 extern struct file_system_type gfs2meta_fs_type;
+extern struct export_operations gfs2_export_ops;
 
 #endif /* __OPS_FSTYPE_DOT_H__ */
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index d85f6e0..911c115 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -157,7 +157,7 @@
 	if (error)
 		goto out_gunlock;
 
-	error = gfs2_dir_search(dir, &dentry->d_name, NULL, NULL);
+	error = gfs2_dir_check(dir, &dentry->d_name, NULL);
 	switch (error) {
 	case -ENOENT:
 		break;
@@ -206,7 +206,7 @@
 			goto out_gunlock_q;
 
 		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
-					 al->al_rgd->rd_ri.ri_length +
+					 al->al_rgd->rd_length +
 					 2 * RES_DINODE + RES_STATFS +
 					 RES_QUOTA, 0);
 		if (error)
@@ -217,8 +217,7 @@
 			goto out_ipres;
 	}
 
-	error = gfs2_dir_add(dir, &dentry->d_name, &ip->i_num,
-			     IF2DT(inode->i_mode));
+	error = gfs2_dir_add(dir, &dentry->d_name, ip, IF2DT(inode->i_mode));
 	if (error)
 		goto out_end_trans;
 
@@ -275,7 +274,7 @@
 	gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
 	gfs2_holder_init(ip->i_gl,  LM_ST_EXCLUSIVE, 0, ghs + 1);
 
-	rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+	rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
 	gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
 
 
@@ -420,7 +419,7 @@
 		dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
 		gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
 
-		gfs2_inum_out(&dip->i_num, &dent->de_inum);
+		gfs2_inum_out(dip, dent);
 		dent->de_type = cpu_to_be16(DT_DIR);
 
 		gfs2_dinode_out(ip, di);
@@ -472,7 +471,7 @@
 	gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
 	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
 
-	rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+	rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
 	gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
 
 	error = gfs2_glock_nq_m(3, ghs);
@@ -614,7 +613,7 @@
 		 * this is the case of the target file already existing
 		 * so we unlink before doing the rename
 		 */
-		nrgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr);
+		nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr);
 		if (nrgd)
 			gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++);
 	}
@@ -653,7 +652,7 @@
 		if (error)
 			goto out_gunlock;
 
-		error = gfs2_dir_search(ndir, &ndentry->d_name, NULL, NULL);
+		error = gfs2_dir_check(ndir, &ndentry->d_name, NULL);
 		switch (error) {
 		case -ENOENT:
 			error = 0;
@@ -712,7 +711,7 @@
 			goto out_gunlock_q;
 
 		error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
-					 al->al_rgd->rd_ri.ri_length +
+					 al->al_rgd->rd_length +
 					 4 * RES_DINODE + 4 * RES_LEAF +
 					 RES_STATFS + RES_QUOTA + 4, 0);
 		if (error)
@@ -750,7 +749,7 @@
 		if (error)
 			goto out_end_trans;
 
-		error = gfs2_dir_mvino(ip, &name, &ndip->i_num, DT_DIR);
+		error = gfs2_dir_mvino(ip, &name, ndip, DT_DIR);
 		if (error)
 			goto out_end_trans;
 	} else {
@@ -758,7 +757,7 @@
 		error = gfs2_meta_inode_buffer(ip, &dibh);
 		if (error)
 			goto out_end_trans;
-		ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+		ip->i_inode.i_ctime = CURRENT_TIME;
 		gfs2_trans_add_bh(ip->i_gl, dibh, 1);
 		gfs2_dinode_out(ip, dibh->b_data);
 		brelse(dibh);
@@ -768,8 +767,7 @@
 	if (error)
 		goto out_end_trans;
 
-	error = gfs2_dir_add(ndir, &ndentry->d_name, &ip->i_num,
-			     IF2DT(ip->i_inode.i_mode));
+	error = gfs2_dir_add(ndir, &ndentry->d_name, ip, IF2DT(ip->i_inode.i_mode));
 	if (error)
 		goto out_end_trans;
 
@@ -905,8 +903,8 @@
 	}
 
 	error = gfs2_truncatei(ip, attr->ia_size);
-	if (error)
-		return error;
+	if (error && (inode->i_size != ip->i_di.di_size))
+		i_size_write(inode, ip->i_di.di_size);
 
 	return error;
 }
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 485ce3d..603d940 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -326,8 +326,10 @@
 		gfs2_glock_schedule_for_reclaim(ip->i_gl);
 		gfs2_glock_put(ip->i_gl);
 		ip->i_gl = NULL;
-		if (ip->i_iopen_gh.gh_gl)
+		if (ip->i_iopen_gh.gh_gl) {
+			ip->i_iopen_gh.gh_gl->gl_object = NULL;
 			gfs2_glock_dq_uninit(&ip->i_iopen_gh);
+		}
 	}
 }
 
@@ -422,13 +424,13 @@
 	if (!inode->i_private)
 		goto out;
 
-	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &gh);
+	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
 	if (unlikely(error)) {
 		gfs2_glock_dq_uninit(&ip->i_iopen_gh);
 		goto out;
 	}
 
-	gfs2_glock_dq(&ip->i_iopen_gh);
+	gfs2_glock_dq_wait(&ip->i_iopen_gh);
 	gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh);
 	error = gfs2_glock_nq(&ip->i_iopen_gh);
 	if (error)
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c
index aa0dbd2..404b7cc 100644
--- a/fs/gfs2/ops_vm.c
+++ b/fs/gfs2/ops_vm.c
@@ -66,7 +66,7 @@
 	if (error)
 		goto out_gunlock_q;
 
-	error = gfs2_trans_begin(sdp, al->al_rgd->rd_ri.ri_length +
+	error = gfs2_trans_begin(sdp, al->al_rgd->rd_length +
 				 ind_blocks + RES_DINODE +
 				 RES_STATFS + RES_QUOTA, 0);
 	if (error)
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index c186857..6e546ee 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -66,6 +66,18 @@
 #define QUOTA_USER 1
 #define QUOTA_GROUP 0
 
+struct gfs2_quota_host {
+	u64 qu_limit;
+	u64 qu_warn;
+	s64 qu_value;
+};
+
+struct gfs2_quota_change_host {
+	u64 qc_change;
+	u32 qc_flags; /* GFS2_QCF_... */
+	u32 qc_id;
+};
+
 static u64 qd2offset(struct gfs2_quota_data *qd)
 {
 	u64 offset;
@@ -561,6 +573,25 @@
 	mutex_unlock(&sdp->sd_quota_mutex);
 }
 
+static void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf)
+{
+	const struct gfs2_quota *str = buf;
+
+	qu->qu_limit = be64_to_cpu(str->qu_limit);
+	qu->qu_warn = be64_to_cpu(str->qu_warn);
+	qu->qu_value = be64_to_cpu(str->qu_value);
+}
+
+static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf)
+{
+	struct gfs2_quota *str = buf;
+
+	str->qu_limit = cpu_to_be64(qu->qu_limit);
+	str->qu_warn = cpu_to_be64(qu->qu_warn);
+	str->qu_value = cpu_to_be64(qu->qu_value);
+	memset(&str->qu_reserved, 0, sizeof(str->qu_reserved));
+}
+
 /**
  * gfs2_adjust_quota
  *
@@ -573,12 +604,13 @@
 	struct inode *inode = &ip->i_inode;
 	struct address_space *mapping = inode->i_mapping;
 	unsigned long index = loc >> PAGE_CACHE_SHIFT;
-	unsigned offset = loc & (PAGE_CACHE_SHIFT - 1);
+	unsigned offset = loc & (PAGE_CACHE_SIZE - 1);
 	unsigned blocksize, iblock, pos;
 	struct buffer_head *bh;
 	struct page *page;
 	void *kaddr;
-	__be64 *ptr;
+	char *ptr;
+	struct gfs2_quota_host qp;
 	s64 value;
 	int err = -EIO;
 
@@ -620,13 +652,17 @@
 
 	kaddr = kmap_atomic(page, KM_USER0);
 	ptr = kaddr + offset;
-	value = (s64)be64_to_cpu(*ptr) + change;
-	*ptr = cpu_to_be64(value);
+	gfs2_quota_in(&qp, ptr);
+	qp.qu_value += change;
+	value = qp.qu_value;
+	gfs2_quota_out(&qp, ptr);
 	flush_dcache_page(page);
 	kunmap_atomic(kaddr, KM_USER0);
 	err = 0;
 	qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC);
 	qd->qd_qb.qb_value = cpu_to_be64(value);
+	((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_magic = cpu_to_be32(GFS2_MAGIC);
+	((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_value = cpu_to_be64(value);
 unlock:
 	unlock_page(page);
 	page_cache_release(page);
@@ -689,7 +725,7 @@
 			goto out_alloc;
 
 		error = gfs2_trans_begin(sdp,
-					 al->al_rgd->rd_ri.ri_length +
+					 al->al_rgd->rd_length +
 					 num_qd * data_blocks +
 					 nalloc * ind_blocks +
 					 RES_DINODE + num_qd +
@@ -709,7 +745,7 @@
 		offset = qd2offset(qd);
 		error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync,
 					  (struct gfs2_quota_data *)
-					  qd->qd_gl->gl_lvb);
+					  qd);
 		if (error)
 			goto out_end_trans;
 
@@ -1050,6 +1086,15 @@
 	return error;
 }
 
+static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf)
+{
+	const struct gfs2_quota_change *str = buf;
+
+	qc->qc_change = be64_to_cpu(str->qc_change);
+	qc->qc_flags = be32_to_cpu(str->qc_flags);
+	qc->qc_id = be32_to_cpu(str->qc_id);
+}
+
 int gfs2_quota_init(struct gfs2_sbd *sdp)
 {
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 8bc182c..5ada38c 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -116,6 +116,22 @@
 	}
 }
 
+static int gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
+{
+	const struct gfs2_log_header *str = buf;
+
+	if (str->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) ||
+	    str->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH))
+		return 1;
+
+	lh->lh_sequence = be64_to_cpu(str->lh_sequence);
+	lh->lh_flags = be32_to_cpu(str->lh_flags);
+	lh->lh_tail = be32_to_cpu(str->lh_tail);
+	lh->lh_blkno = be32_to_cpu(str->lh_blkno);
+	lh->lh_hash = be32_to_cpu(str->lh_hash);
+	return 0;
+}
+
 /**
  * get_log_header - read the log header for a given segment
  * @jd: the journal
@@ -147,12 +163,10 @@
 					     sizeof(u32));
 	hash = crc32_le(hash, (unsigned char const *)&nothing, sizeof(nothing));
 	hash ^= (u32)~0;
-	gfs2_log_header_in(&lh, bh->b_data);
+	error = gfs2_log_header_in(&lh, bh->b_data);
 	brelse(bh);
 
-	if (lh.lh_header.mh_magic != GFS2_MAGIC ||
-	    lh.lh_header.mh_type != GFS2_METATYPE_LH ||
-	    lh.lh_blkno != blk || lh.lh_hash != hash)
+	if (error || lh.lh_blkno != blk || lh.lh_hash != hash)
 		return 1;
 
 	*head = lh;
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 1727f50..e4e0406 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
@@ -28,6 +28,7 @@
 #include "ops_file.h"
 #include "util.h"
 #include "log.h"
+#include "inode.h"
 
 #define BFITNOENT ((u32)~0)
 
@@ -50,6 +51,9 @@
 	        1, 0, 0, 0
 };
 
+static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+                        unsigned char old_state, unsigned char new_state);
+
 /**
  * gfs2_setbit - Set a bit in the bitmaps
  * @buffer: the buffer that holds the bitmaps
@@ -204,7 +208,7 @@
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
 	struct gfs2_bitmap *bi = NULL;
-	u32 length = rgd->rd_ri.ri_length;
+	u32 length = rgd->rd_length;
 	u32 count[4], tmp;
 	int buf, x;
 
@@ -227,7 +231,7 @@
 		return;
 	}
 
-	tmp = rgd->rd_ri.ri_data -
+	tmp = rgd->rd_data -
 		rgd->rd_rg.rg_free -
 		rgd->rd_rg.rg_dinodes;
 	if (count[1] + count[2] != tmp) {
@@ -253,10 +257,10 @@
 
 }
 
-static inline int rgrp_contains_block(struct gfs2_rindex_host *ri, u64 block)
+static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block)
 {
-	u64 first = ri->ri_data0;
-	u64 last = first + ri->ri_data;
+	u64 first = rgd->rd_data0;
+	u64 last = first + rgd->rd_data;
 	return first <= block && block < last;
 }
 
@@ -275,7 +279,7 @@
 	spin_lock(&sdp->sd_rindex_spin);
 
 	list_for_each_entry(rgd, &sdp->sd_rindex_mru_list, rd_list_mru) {
-		if (rgrp_contains_block(&rgd->rd_ri, blk)) {
+		if (rgrp_contains_block(rgd, blk)) {
 			list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
 			spin_unlock(&sdp->sd_rindex_spin);
 			return rgd;
@@ -354,6 +358,15 @@
 	mutex_unlock(&sdp->sd_rindex_mutex);
 }
 
+static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd)
+{
+	printk(KERN_INFO "  ri_addr = %llu\n", (unsigned long long)rgd->rd_addr);
+	printk(KERN_INFO "  ri_length = %u\n", rgd->rd_length);
+	printk(KERN_INFO "  ri_data0 = %llu\n", (unsigned long long)rgd->rd_data0);
+	printk(KERN_INFO "  ri_data = %u\n", rgd->rd_data);
+	printk(KERN_INFO "  ri_bitbytes = %u\n", rgd->rd_bitbytes);
+}
+
 /**
  * gfs2_compute_bitstructs - Compute the bitmap sizes
  * @rgd: The resource group descriptor
@@ -367,7 +380,7 @@
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
 	struct gfs2_bitmap *bi;
-	u32 length = rgd->rd_ri.ri_length; /* # blocks in hdr & bitmap */
+	u32 length = rgd->rd_length; /* # blocks in hdr & bitmap */
 	u32 bytes_left, bytes;
 	int x;
 
@@ -378,7 +391,7 @@
 	if (!rgd->rd_bits)
 		return -ENOMEM;
 
-	bytes_left = rgd->rd_ri.ri_bitbytes;
+	bytes_left = rgd->rd_bitbytes;
 
 	for (x = 0; x < length; x++) {
 		bi = rgd->rd_bits + x;
@@ -399,14 +412,14 @@
 		} else if (x + 1 == length) {
 			bytes = bytes_left;
 			bi->bi_offset = sizeof(struct gfs2_meta_header);
-			bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
+			bi->bi_start = rgd->rd_bitbytes - bytes_left;
 			bi->bi_len = bytes;
 		/* other blocks */
 		} else {
 			bytes = sdp->sd_sb.sb_bsize -
 				sizeof(struct gfs2_meta_header);
 			bi->bi_offset = sizeof(struct gfs2_meta_header);
-			bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
+			bi->bi_start = rgd->rd_bitbytes - bytes_left;
 			bi->bi_len = bytes;
 		}
 
@@ -418,9 +431,9 @@
 		return -EIO;
 	}
 	bi = rgd->rd_bits + (length - 1);
-	if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_ri.ri_data) {
+	if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_data) {
 		if (gfs2_consist_rgrpd(rgd)) {
-			gfs2_rindex_print(&rgd->rd_ri);
+			gfs2_rindex_print(rgd);
 			fs_err(sdp, "start=%u len=%u offset=%u\n",
 			       bi->bi_start, bi->bi_len, bi->bi_offset);
 		}
@@ -431,9 +444,104 @@
 }
 
 /**
- * gfs2_ri_update - Pull in a new resource index from the disk
+ * gfs2_ri_total - Total up the file system space, according to the rindex.
+ *
+ */
+u64 gfs2_ri_total(struct gfs2_sbd *sdp)
+{
+	u64 total_data = 0;	
+	struct inode *inode = sdp->sd_rindex;
+	struct gfs2_inode *ip = GFS2_I(inode);
+	char buf[sizeof(struct gfs2_rindex)];
+	struct file_ra_state ra_state;
+	int error, rgrps;
+
+	mutex_lock(&sdp->sd_rindex_mutex);
+	file_ra_state_init(&ra_state, inode->i_mapping);
+	for (rgrps = 0;; rgrps++) {
+		loff_t pos = rgrps * sizeof(struct gfs2_rindex);
+
+		if (pos + sizeof(struct gfs2_rindex) >= ip->i_di.di_size)
+			break;
+		error = gfs2_internal_read(ip, &ra_state, buf, &pos,
+					   sizeof(struct gfs2_rindex));
+		if (error != sizeof(struct gfs2_rindex))
+			break;
+		total_data += be32_to_cpu(((struct gfs2_rindex *)buf)->ri_data);
+	}
+	mutex_unlock(&sdp->sd_rindex_mutex);
+	return total_data;
+}
+
+static void gfs2_rindex_in(struct gfs2_rgrpd *rgd, const void *buf)
+{
+	const struct gfs2_rindex *str = buf;
+
+	rgd->rd_addr = be64_to_cpu(str->ri_addr);
+	rgd->rd_length = be32_to_cpu(str->ri_length);
+	rgd->rd_data0 = be64_to_cpu(str->ri_data0);
+	rgd->rd_data = be32_to_cpu(str->ri_data);
+	rgd->rd_bitbytes = be32_to_cpu(str->ri_bitbytes);
+}
+
+/**
+ * read_rindex_entry - Pull in a new resource index entry from the disk
  * @gl: The glock covering the rindex inode
  *
+ * Returns: 0 on success, error code otherwise
+ */
+
+static int read_rindex_entry(struct gfs2_inode *ip,
+			     struct file_ra_state *ra_state)
+{
+	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+	loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
+	char buf[sizeof(struct gfs2_rindex)];
+	int error;
+	struct gfs2_rgrpd *rgd;
+
+	error = gfs2_internal_read(ip, ra_state, buf, &pos,
+				   sizeof(struct gfs2_rindex));
+	if (!error)
+		return 0;
+	if (error != sizeof(struct gfs2_rindex)) {
+		if (error > 0)
+			error = -EIO;
+		return error;
+	}
+
+	rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
+	error = -ENOMEM;
+	if (!rgd)
+		return error;
+
+	mutex_init(&rgd->rd_mutex);
+	lops_init_le(&rgd->rd_le, &gfs2_rg_lops);
+	rgd->rd_sbd = sdp;
+
+	list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list);
+	list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
+
+	gfs2_rindex_in(rgd, buf);
+	error = compute_bitstructs(rgd);
+	if (error)
+		return error;
+
+	error = gfs2_glock_get(sdp, rgd->rd_addr,
+			       &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
+	if (error)
+		return error;
+
+	rgd->rd_gl->gl_object = rgd;
+	rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
+	rgd->rd_flags |= GFS2_RDF_CHECK;
+	return error;
+}
+
+/**
+ * gfs2_ri_update - Pull in a new resource index from the disk
+ * @ip: pointer to the rindex inode
+ *
  * Returns: 0 on successful update, error code otherwise
  */
 
@@ -441,13 +549,11 @@
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct inode *inode = &ip->i_inode;
-	struct gfs2_rgrpd *rgd;
-	char buf[sizeof(struct gfs2_rindex)];
 	struct file_ra_state ra_state;
-	u64 junk = ip->i_di.di_size;
+	u64 rgrp_count = ip->i_di.di_size;
 	int error;
 
-	if (do_div(junk, sizeof(struct gfs2_rindex))) {
+	if (do_div(rgrp_count, sizeof(struct gfs2_rindex))) {
 		gfs2_consist_inode(ip);
 		return -EIO;
 	}
@@ -455,50 +561,50 @@
 	clear_rgrpdi(sdp);
 
 	file_ra_state_init(&ra_state, inode->i_mapping);
-	for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
-		loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
-		error = gfs2_internal_read(ip, &ra_state, buf, &pos,
-					    sizeof(struct gfs2_rindex));
-		if (!error)
-			break;
-		if (error != sizeof(struct gfs2_rindex)) {
-			if (error > 0)
-				error = -EIO;
-			goto fail;
+	for (sdp->sd_rgrps = 0; sdp->sd_rgrps < rgrp_count; sdp->sd_rgrps++) {
+		error = read_rindex_entry(ip, &ra_state);
+		if (error) {
+			clear_rgrpdi(sdp);
+			return error;
 		}
-
-		rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
-		error = -ENOMEM;
-		if (!rgd)
-			goto fail;
-
-		mutex_init(&rgd->rd_mutex);
-		lops_init_le(&rgd->rd_le, &gfs2_rg_lops);
-		rgd->rd_sbd = sdp;
-
-		list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list);
-		list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
-
-		gfs2_rindex_in(&rgd->rd_ri, buf);
-		error = compute_bitstructs(rgd);
-		if (error)
-			goto fail;
-
-		error = gfs2_glock_get(sdp, rgd->rd_ri.ri_addr,
-				       &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
-		if (error)
-			goto fail;
-
-		rgd->rd_gl->gl_object = rgd;
-		rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
 	}
 
 	sdp->sd_rindex_vn = ip->i_gl->gl_vn;
 	return 0;
+}
 
-fail:
-	clear_rgrpdi(sdp);
-	return error;
+/**
+ * gfs2_ri_update_special - Pull in a new resource index from the disk
+ *
+ * This is a special version that's safe to call from gfs2_inplace_reserve_i.
+ * In this case we know that we don't have any resource groups in memory yet.
+ *
+ * @ip: pointer to the rindex inode
+ *
+ * Returns: 0 on successful update, error code otherwise
+ */
+static int gfs2_ri_update_special(struct gfs2_inode *ip)
+{
+	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+	struct inode *inode = &ip->i_inode;
+	struct file_ra_state ra_state;
+	int error;
+
+	file_ra_state_init(&ra_state, inode->i_mapping);
+	for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
+		/* Ignore partials */
+		if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
+		    ip->i_di.di_size)
+			break;
+		error = read_rindex_entry(ip, &ra_state);
+		if (error) {
+			clear_rgrpdi(sdp);
+			return error;
+		}
+	}
+
+	sdp->sd_rindex_vn = ip->i_gl->gl_vn;
+	return 0;
 }
 
 /**
@@ -543,6 +649,28 @@
 	return error;
 }
 
+static void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
+{
+	const struct gfs2_rgrp *str = buf;
+
+	rg->rg_flags = be32_to_cpu(str->rg_flags);
+	rg->rg_free = be32_to_cpu(str->rg_free);
+	rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
+	rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
+}
+
+static void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
+{
+	struct gfs2_rgrp *str = buf;
+
+	str->rg_flags = cpu_to_be32(rg->rg_flags);
+	str->rg_free = cpu_to_be32(rg->rg_free);
+	str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
+	str->__pad = cpu_to_be32(0);
+	str->rg_igeneration = cpu_to_be64(rg->rg_igeneration);
+	memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
+}
+
 /**
  * gfs2_rgrp_bh_get - Read in a RG's header and bitmaps
  * @rgd: the struct gfs2_rgrpd describing the RG to read in
@@ -557,7 +685,7 @@
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
 	struct gfs2_glock *gl = rgd->rd_gl;
-	unsigned int length = rgd->rd_ri.ri_length;
+	unsigned int length = rgd->rd_length;
 	struct gfs2_bitmap *bi;
 	unsigned int x, y;
 	int error;
@@ -575,7 +703,7 @@
 
 	for (x = 0; x < length; x++) {
 		bi = rgd->rd_bits + x;
-		error = gfs2_meta_read(gl, rgd->rd_ri.ri_addr + x, 0, &bi->bi_bh);
+		error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh);
 		if (error)
 			goto fail;
 	}
@@ -637,7 +765,7 @@
 void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd)
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
-	int x, length = rgd->rd_ri.ri_length;
+	int x, length = rgd->rd_length;
 
 	spin_lock(&sdp->sd_rindex_spin);
 	gfs2_assert_warn(rgd->rd_sbd, rgd->rd_bh_count);
@@ -660,7 +788,7 @@
 void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd)
 {
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
-	unsigned int length = rgd->rd_ri.ri_length;
+	unsigned int length = rgd->rd_length;
 	unsigned int x;
 
 	for (x = 0; x < length; x++) {
@@ -722,6 +850,38 @@
 }
 
 /**
+ * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes
+ * @rgd: The rgrp
+ *
+ * Returns: The inode, if one has been found
+ */
+
+static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
+{
+	struct inode *inode;
+	u32 goal = 0;
+	u64 no_addr;
+
+	for(;;) {
+		goal = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
+				    GFS2_BLKST_UNLINKED);
+		if (goal == 0)
+			return 0;
+		no_addr = goal + rgd->rd_data0;
+		if (no_addr <= *last_unlinked)
+			continue;
+		*last_unlinked = no_addr;
+		inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN,
+					no_addr, -1);
+		if (!IS_ERR(inode))
+			return inode;
+	}
+
+	rgd->rd_flags &= ~GFS2_RDF_CHECK;
+	return NULL;
+}
+
+/**
  * recent_rgrp_first - get first RG from "recent" list
  * @sdp: The GFS2 superblock
  * @rglast: address of the rgrp used last
@@ -743,7 +903,7 @@
 		goto first;
 
 	list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) {
-		if (rgd->rd_ri.ri_addr == rglast)
+		if (rgd->rd_addr == rglast)
 			goto out;
 	}
 
@@ -882,8 +1042,9 @@
  * Returns: errno
  */
 
-static int get_local_rgrp(struct gfs2_inode *ip)
+static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
 {
+	struct inode *inode = NULL;
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_rgrpd *rgd, *begin = NULL;
 	struct gfs2_alloc *al = &ip->i_alloc;
@@ -903,7 +1064,11 @@
 		case 0:
 			if (try_rgrp_fit(rgd, al))
 				goto out;
+			if (rgd->rd_flags & GFS2_RDF_CHECK)
+				inode = try_rgrp_unlink(rgd, last_unlinked);
 			gfs2_glock_dq_uninit(&al->al_rgd_gh);
+			if (inode)
+				return inode;
 			rgd = recent_rgrp_next(rgd, 1);
 			break;
 
@@ -912,7 +1077,7 @@
 			break;
 
 		default:
-			return error;
+			return ERR_PTR(error);
 		}
 	}
 
@@ -927,7 +1092,11 @@
 		case 0:
 			if (try_rgrp_fit(rgd, al))
 				goto out;
+			if (rgd->rd_flags & GFS2_RDF_CHECK)
+				inode = try_rgrp_unlink(rgd, last_unlinked);
 			gfs2_glock_dq_uninit(&al->al_rgd_gh);
+			if (inode)
+				return inode;
 			break;
 
 		case GLR_TRYFAILED:
@@ -935,7 +1104,7 @@
 			break;
 
 		default:
-			return error;
+			return ERR_PTR(error);
 		}
 
 		rgd = gfs2_rgrpd_get_next(rgd);
@@ -944,7 +1113,7 @@
 
 		if (rgd == begin) {
 			if (++loops >= 3)
-				return -ENOSPC;
+				return ERR_PTR(-ENOSPC);
 			if (!skipped)
 				loops++;
 			flags = 0;
@@ -954,7 +1123,7 @@
 	}
 
 out:
-	ip->i_last_rg_alloc = rgd->rd_ri.ri_addr;
+	ip->i_last_rg_alloc = rgd->rd_addr;
 
 	if (begin) {
 		recent_rgrp_add(rgd);
@@ -964,7 +1133,7 @@
 		forward_rgrp_set(sdp, rgd);
 	}
 
-	return 0;
+	return NULL;
 }
 
 /**
@@ -978,19 +1147,33 @@
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_alloc *al = &ip->i_alloc;
-	int error;
+	struct inode *inode;
+	int error = 0;
+	u64 last_unlinked = 0;
 
 	if (gfs2_assert_warn(sdp, al->al_requested))
 		return -EINVAL;
 
-	error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
+try_again:
+	/* We need to hold the rindex unless the inode we're using is
+	   the rindex itself, in which case it's already held. */
+	if (ip != GFS2_I(sdp->sd_rindex))
+		error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
+	else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */
+		error = gfs2_ri_update_special(ip);
+
 	if (error)
 		return error;
 
-	error = get_local_rgrp(ip);
-	if (error) {
-		gfs2_glock_dq_uninit(&al->al_ri_gh);
-		return error;
+	inode = get_local_rgrp(ip, &last_unlinked);
+	if (inode) {
+		if (ip != GFS2_I(sdp->sd_rindex))
+			gfs2_glock_dq_uninit(&al->al_ri_gh);
+		if (IS_ERR(inode))
+			return PTR_ERR(inode);
+		iput(inode);
+		gfs2_log_flush(sdp, NULL);
+		goto try_again;
 	}
 
 	al->al_file = file;
@@ -1019,7 +1202,8 @@
 
 	al->al_rgd = NULL;
 	gfs2_glock_dq_uninit(&al->al_rgd_gh);
-	gfs2_glock_dq_uninit(&al->al_ri_gh);
+	if (ip != GFS2_I(sdp->sd_rindex))
+		gfs2_glock_dq_uninit(&al->al_ri_gh);
 }
 
 /**
@@ -1037,8 +1221,8 @@
 	unsigned int buf;
 	unsigned char type;
 
-	length = rgd->rd_ri.ri_length;
-	rgrp_block = block - rgd->rd_ri.ri_data0;
+	length = rgd->rd_length;
+	rgrp_block = block - rgd->rd_data0;
 
 	for (buf = 0; buf < length; buf++) {
 		bi = rgd->rd_bits + buf;
@@ -1077,10 +1261,10 @@
  */
 
 static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
-			     unsigned char old_state, unsigned char new_state)
+			unsigned char old_state, unsigned char new_state)
 {
 	struct gfs2_bitmap *bi = NULL;
-	u32 length = rgd->rd_ri.ri_length;
+	u32 length = rgd->rd_length;
 	u32 blk = 0;
 	unsigned int buf, x;
 
@@ -1118,17 +1302,18 @@
 		goal = 0;
 	}
 
-	if (gfs2_assert_withdraw(rgd->rd_sbd, x <= length))
-		blk = 0;
+	if (old_state != new_state) {
+		gfs2_assert_withdraw(rgd->rd_sbd, blk != BFITNOENT);
 
-	gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
-	gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
-		    bi->bi_len, blk, new_state);
-	if (bi->bi_clone)
-		gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+		gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
+		gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
 			    bi->bi_len, blk, new_state);
+		if (bi->bi_clone)
+			gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+				    bi->bi_len, blk, new_state);
+	}
 
-	return bi->bi_start * GFS2_NBBY + blk;
+	return (blk == BFITNOENT) ? 0 : (bi->bi_start * GFS2_NBBY) + blk;
 }
 
 /**
@@ -1156,9 +1341,9 @@
 		return NULL;
 	}
 
-	length = rgd->rd_ri.ri_length;
+	length = rgd->rd_length;
 
-	rgrp_blk = bstart - rgd->rd_ri.ri_data0;
+	rgrp_blk = bstart - rgd->rd_data0;
 
 	while (blen--) {
 		for (buf = 0; buf < length; buf++) {
@@ -1202,15 +1387,15 @@
 	u32 goal, blk;
 	u64 block;
 
-	if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_data))
-		goal = ip->i_di.di_goal_data - rgd->rd_ri.ri_data0;
+	if (rgrp_contains_block(rgd, ip->i_di.di_goal_data))
+		goal = ip->i_di.di_goal_data - rgd->rd_data0;
 	else
 		goal = rgd->rd_last_alloc_data;
 
 	blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
 	rgd->rd_last_alloc_data = blk;
 
-	block = rgd->rd_ri.ri_data0 + blk;
+	block = rgd->rd_data0 + blk;
 	ip->i_di.di_goal_data = block;
 
 	gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
@@ -1246,15 +1431,15 @@
 	u32 goal, blk;
 	u64 block;
 
-	if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_meta))
-		goal = ip->i_di.di_goal_meta - rgd->rd_ri.ri_data0;
+	if (rgrp_contains_block(rgd, ip->i_di.di_goal_meta))
+		goal = ip->i_di.di_goal_meta - rgd->rd_data0;
 	else
 		goal = rgd->rd_last_alloc_meta;
 
 	blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
 	rgd->rd_last_alloc_meta = blk;
 
-	block = rgd->rd_ri.ri_data0 + blk;
+	block = rgd->rd_data0 + blk;
 	ip->i_di.di_goal_meta = block;
 
 	gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
@@ -1296,7 +1481,7 @@
 
 	rgd->rd_last_alloc_meta = blk;
 
-	block = rgd->rd_ri.ri_data0 + blk;
+	block = rgd->rd_data0 + blk;
 
 	gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
 	rgd->rd_rg.rg_free--;
@@ -1379,7 +1564,7 @@
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
 	struct gfs2_rgrpd *rgd;
-	u64 blkno = ip->i_num.no_addr;
+	u64 blkno = ip->i_no_addr;
 
 	rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED);
 	if (!rgd)
@@ -1414,9 +1599,9 @@
 
 void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip)
 {
-	gfs2_free_uninit_di(rgd, ip->i_num.no_addr);
+	gfs2_free_uninit_di(rgd, ip->i_no_addr);
 	gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid);
-	gfs2_meta_wipe(ip, ip->i_num.no_addr, 1);
+	gfs2_meta_wipe(ip, ip->i_no_addr, 1);
 }
 
 /**
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index b01e0cf..b4c6adf 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -65,5 +65,6 @@
 void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
 		      int flags);
 void gfs2_rlist_free(struct gfs2_rgrp_list *rlist);
+u64 gfs2_ri_total(struct gfs2_sbd *sdp);
 
 #endif /* __RGRP_DOT_H__ */
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 4fdda97..f916b97 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -95,8 +95,8 @@
 {
 	unsigned int x;
 
-	if (sb->sb_header.mh_magic != GFS2_MAGIC ||
-	    sb->sb_header.mh_type != GFS2_METATYPE_SB) {
+	if (sb->sb_magic != GFS2_MAGIC ||
+	    sb->sb_type != GFS2_METATYPE_SB) {
 		if (!silent)
 			printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n");
 		return -EINVAL;
@@ -174,10 +174,31 @@
 	return 0;
 }
 
+static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf)
+{
+	const struct gfs2_sb *str = buf;
+
+	sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic);
+	sb->sb_type = be32_to_cpu(str->sb_header.mh_type);
+	sb->sb_format = be32_to_cpu(str->sb_header.mh_format);
+	sb->sb_fs_format = be32_to_cpu(str->sb_fs_format);
+	sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format);
+	sb->sb_bsize = be32_to_cpu(str->sb_bsize);
+	sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift);
+	sb->sb_master_dir.no_addr = be64_to_cpu(str->sb_master_dir.no_addr);
+	sb->sb_master_dir.no_formal_ino = be64_to_cpu(str->sb_master_dir.no_formal_ino);
+	sb->sb_root_dir.no_addr = be64_to_cpu(str->sb_root_dir.no_addr);
+	sb->sb_root_dir.no_formal_ino = be64_to_cpu(str->sb_root_dir.no_formal_ino);
+
+	memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
+	memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
+}
+
 /**
  * gfs2_read_super - Read the gfs2 super block from disk
- * @sb: The VFS super block
+ * @sdp: The GFS2 super block
  * @sector: The location of the super block
+ * @error: The error code to return
  *
  * This uses the bio functions to read the super block from disk
  * because we want to be 100% sure that we never read cached data.
@@ -189,17 +210,19 @@
  * the master directory (contains pointers to journals etc) and the
  * root directory.
  *
- * Returns: A page containing the sb or NULL
+ * Returns: 0 on success or error
  */
 
-struct page *gfs2_read_super(struct super_block *sb, sector_t sector)
+int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
 {
+	struct super_block *sb = sdp->sd_vfs;
+	struct gfs2_sb *p;
 	struct page *page;
 	struct bio *bio;
 
 	page = alloc_page(GFP_KERNEL);
 	if (unlikely(!page))
-		return NULL;
+		return -ENOBUFS;
 
 	ClearPageUptodate(page);
 	ClearPageDirty(page);
@@ -208,7 +231,7 @@
 	bio = bio_alloc(GFP_KERNEL, 1);
 	if (unlikely(!bio)) {
 		__free_page(page);
-		return NULL;
+		return -ENOBUFS;
 	}
 
 	bio->bi_sector = sector * (sb->s_blocksize >> 9);
@@ -222,9 +245,13 @@
 	bio_put(bio);
 	if (!PageUptodate(page)) {
 		__free_page(page);
-		return NULL;
+		return -EIO;
 	}
-	return page;
+	p = kmap(page);
+	gfs2_sb_in(&sdp->sd_sb, p);
+	kunmap(page);
+	__free_page(page);
+	return 0;
 }
 
 /**
@@ -241,19 +268,13 @@
 	u32 tmp_blocks;
 	unsigned int x;
 	int error;
-	struct page *page;
-	char *sb;
 
-	page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
-	if (!page) {
+	error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
+	if (error) {
 		if (!silent)
 			fs_err(sdp, "can't read superblock\n");
-		return -EIO;
+		return error;
 	}
-	sb = kmap(page);
-	gfs2_sb_in(&sdp->sd_sb, sb);
-	kunmap(page);
-	__free_page(page);
 
 	error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
 	if (error)
@@ -360,7 +381,7 @@
 		name.len = sprintf(buf, "journal%u", sdp->sd_journals);
 		name.hash = gfs2_disk_hash(name.name, name.len);
 
-		error = gfs2_dir_search(sdp->sd_jindex, &name, NULL, NULL);
+		error = gfs2_dir_check(sdp->sd_jindex, &name, NULL);
 		if (error == -ENOENT) {
 			error = 0;
 			break;
@@ -593,6 +614,24 @@
 	return error;
 }
 
+static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
+{
+	const struct gfs2_statfs_change *str = buf;
+
+	sc->sc_total = be64_to_cpu(str->sc_total);
+	sc->sc_free = be64_to_cpu(str->sc_free);
+	sc->sc_dinodes = be64_to_cpu(str->sc_dinodes);
+}
+
+static void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf)
+{
+	struct gfs2_statfs_change *str = buf;
+
+	str->sc_total = cpu_to_be64(sc->sc_total);
+	str->sc_free = cpu_to_be64(sc->sc_free);
+	str->sc_dinodes = cpu_to_be64(sc->sc_dinodes);
+}
+
 int gfs2_statfs_init(struct gfs2_sbd *sdp)
 {
 	struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
@@ -772,7 +811,7 @@
 			    struct gfs2_statfs_change_host *sc)
 {
 	gfs2_rgrp_verify(rgd);
-	sc->sc_total += rgd->rd_ri.ri_data;
+	sc->sc_total += rgd->rd_data;
 	sc->sc_free += rgd->rd_rg.rg_free;
 	sc->sc_dinodes += rgd->rd_rg.rg_dinodes;
 	return 0;
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
index e590b2d..60a870e 100644
--- a/fs/gfs2/super.h
+++ b/fs/gfs2/super.h
@@ -16,7 +16,7 @@
 
 int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent);
 int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent);
-struct page *gfs2_read_super(struct super_block *sb, sector_t sector);
+int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector);
 
 static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
 {
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index 601eaa1..424a077 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -115,8 +115,8 @@
 		"GFS2: fsid=%s:   inode = %llu %llu\n"
 		"GFS2: fsid=%s:   function = %s, file = %s, line = %u\n",
 		sdp->sd_fsname,
-		sdp->sd_fsname, (unsigned long long)ip->i_num.no_formal_ino,
-		(unsigned long long)ip->i_num.no_addr,
+		sdp->sd_fsname, (unsigned long long)ip->i_no_formal_ino,
+		(unsigned long long)ip->i_no_addr,
 		sdp->sd_fsname, function, file, line);
 	return rv;
 }
@@ -137,7 +137,7 @@
 		"GFS2: fsid=%s:   RG = %llu\n"
 		"GFS2: fsid=%s:   function = %s, file = %s, line = %u\n",
 		sdp->sd_fsname,
-		sdp->sd_fsname, (unsigned long long)rgd->rd_ri.ri_addr,
+		sdp->sd_fsname, (unsigned long long)rgd->rd_addr,
 		sdp->sd_fsname, function, file, line);
 	return rv;
 }
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 9a934db..bc835f2 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -607,7 +607,7 @@
 	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 	.fsync		= file_fsync,
 	.open		= hfs_file_open,
 	.release	= hfs_file_release,
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 45dab5d..409ce54 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -288,7 +288,7 @@
 	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 	.fsync		= file_fsync,
 	.open		= hfsplus_file_open,
 	.release	= hfsplus_file_release,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 8286491..c778620 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -390,7 +390,7 @@
 static const struct file_operations hostfs_file_fops = {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= generic_file_aio_write,
 	.write		= do_sync_write,
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index b4eafc0..5b53e5c 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -129,7 +129,7 @@
 	.mmap		= generic_file_mmap,
 	.release	= hpfs_file_release,
 	.fsync		= hpfs_file_fsync,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 const struct inode_operations hpfs_file_iops =
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 9987127..c253019 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -47,7 +47,7 @@
 	.ioctl =	jffs2_ioctl,
 	.mmap =		generic_file_readonly_mmap,
 	.fsync =	jffs2_fsync,
-	.sendfile =	generic_file_sendfile
+	.splice_read =	generic_file_splice_read,
 };
 
 /* jffs2_file_inode_operations */
diff --git a/fs/jfs/endian24.h b/fs/jfs/endian24.h
index 79494c4..fa92f7f 100644
--- a/fs/jfs/endian24.h
+++ b/fs/jfs/endian24.h
@@ -29,7 +29,7 @@
 	__u32 __x = (x); \
 	((__u32)( \
 		((__x & (__u32)0x000000ffUL) << 16) | \
-		 (__x & (__u32)0x0000ff00UL)        | \
+		 (__x & (__u32)0x0000ff00UL)	    | \
 		((__x & (__u32)0x00ff0000UL) >> 16) )); \
 })
 
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index f7f8eff..87eb936 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -108,7 +108,6 @@
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
-	.sendfile	= generic_file_sendfile,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 	.fsync		= jfs_fsync,
diff --git a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c
index 9c5d596..887f575 100644
--- a/fs/jfs/jfs_debug.c
+++ b/fs/jfs/jfs_debug.c
@@ -26,34 +26,6 @@
 #include "jfs_filsys.h"
 #include "jfs_debug.h"
 
-#ifdef CONFIG_JFS_DEBUG
-void dump_mem(char *label, void *data, int length)
-{
-	int i, j;
-	int *intptr = data;
-	char *charptr = data;
-	char buf[10], line[80];
-
-	printk("%s: dump of %d bytes of data at 0x%p\n\n", label, length,
-	       data);
-	for (i = 0; i < length; i += 16) {
-		line[0] = 0;
-		for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
-			sprintf(buf, " %08x", intptr[i / 4 + j]);
-			strcat(line, buf);
-		}
-		buf[0] = ' ';
-		buf[2] = 0;
-		for (j = 0; (j < 16) && (i + j < length); j++) {
-			buf[1] =
-			    isprint(charptr[i + j]) ? charptr[i + j] : '.';
-			strcat(line, buf);
-		}
-		printk("%s\n", line);
-	}
-}
-#endif
-
 #ifdef PROC_FS_JFS /* see jfs_debug.h */
 
 static struct proc_dir_entry *base;
diff --git a/fs/jfs/jfs_debug.h b/fs/jfs/jfs_debug.h
index 7378798..044c1e6 100644
--- a/fs/jfs/jfs_debug.h
+++ b/fs/jfs/jfs_debug.h
@@ -62,7 +62,6 @@
 
 extern int jfsloglevel;
 
-extern void dump_mem(char *label, void *data, int length);
 extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *);
 
 /* information message: e.g., configuration, major event */
@@ -94,7 +93,6 @@
  *	---------
  */
 #else				/* CONFIG_JFS_DEBUG */
-#define dump_mem(label,data,length) do {} while (0)
 #define ASSERT(p) do {} while (0)
 #define jfs_info(fmt, arg...) do {} while (0)
 #define jfs_debug(fmt, arg...) do {} while (0)
diff --git a/fs/jfs/jfs_dinode.h b/fs/jfs/jfs_dinode.h
index 40b2011..c387540 100644
--- a/fs/jfs/jfs_dinode.h
+++ b/fs/jfs/jfs_dinode.h
@@ -19,23 +19,23 @@
 #define _H_JFS_DINODE
 
 /*
- *      jfs_dinode.h: on-disk inode manager
+ *	jfs_dinode.h: on-disk inode manager
  */
 
-#define INODESLOTSIZE           128
-#define L2INODESLOTSIZE         7
-#define log2INODESIZE           9	/* log2(bytes per dinode) */
+#define INODESLOTSIZE		128
+#define L2INODESLOTSIZE		7
+#define log2INODESIZE		9	/* log2(bytes per dinode) */
 
 
 /*
- *      on-disk inode : 512 bytes
+ *	on-disk inode : 512 bytes
  *
  * note: align 64-bit fields on 8-byte boundary.
  */
 struct dinode {
 	/*
-	 *      I. base area (128 bytes)
-	 *      ------------------------
+	 *	I. base area (128 bytes)
+	 *	------------------------
 	 *
 	 * define generic/POSIX attributes
 	 */
@@ -70,16 +70,16 @@
 	__le32 di_acltype;	/* 4: Type of ACL */
 
 	/*
-	 *      Extension Areas.
+	 *	Extension Areas.
 	 *
-	 *      Historically, the inode was partitioned into 4 128-byte areas,
-	 *      the last 3 being defined as unions which could have multiple
-	 *      uses.  The first 96 bytes had been completely unused until
-	 *      an index table was added to the directory.  It is now more
-	 *      useful to describe the last 3/4 of the inode as a single
-	 *      union.  We would probably be better off redesigning the
-	 *      entire structure from scratch, but we don't want to break
-	 *      commonality with OS/2's JFS at this time.
+	 *	Historically, the inode was partitioned into 4 128-byte areas,
+	 *	the last 3 being defined as unions which could have multiple
+	 *	uses.  The first 96 bytes had been completely unused until
+	 *	an index table was added to the directory.  It is now more
+	 *	useful to describe the last 3/4 of the inode as a single
+	 *	union.  We would probably be better off redesigning the
+	 *	entire structure from scratch, but we don't want to break
+	 *	commonality with OS/2's JFS at this time.
 	 */
 	union {
 		struct {
@@ -95,7 +95,7 @@
 		} _dir;					/* (384) */
 #define di_dirtable	u._dir._table
 #define di_dtroot	u._dir._dtroot
-#define di_parent       di_dtroot.header.idotdot
+#define di_parent	di_dtroot.header.idotdot
 #define di_DASD		di_dtroot.header.DASD
 
 		struct {
@@ -127,14 +127,14 @@
 #define di_inlinedata	u._file._u2._special._u
 #define di_rdev		u._file._u2._special._u._rdev
 #define di_fastsymlink	u._file._u2._special._u._fastsymlink
-#define di_inlineea     u._file._u2._special._inlineea
+#define di_inlineea	u._file._u2._special._inlineea
 	} u;
 };
 
 /* extended mode bits (on-disk inode di_mode) */
-#define IFJOURNAL       0x00010000	/* journalled file */
-#define ISPARSE         0x00020000	/* sparse file enabled */
-#define INLINEEA        0x00040000	/* inline EA area free */
+#define IFJOURNAL	0x00010000	/* journalled file */
+#define ISPARSE		0x00020000	/* sparse file enabled */
+#define INLINEEA	0x00040000	/* inline EA area free */
 #define ISWAPFILE	0x00800000	/* file open for pager swap space */
 
 /* more extended mode bits: attributes for OS/2 */
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index f3b1ebb..e198506 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -154,12 +154,12 @@
  *		the in-core descriptor is initialized from disk.
  *
  * PARAMETERS:
- *      ipbmap	-  pointer to in-core inode for the block map.
+ *	ipbmap	- pointer to in-core inode for the block map.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOMEM	- insufficient memory
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOMEM	- insufficient memory
+ *	-EIO	- i/o error
  */
 int dbMount(struct inode *ipbmap)
 {
@@ -232,11 +232,11 @@
  *		the memory for this descriptor is freed.
  *
  * PARAMETERS:
- *      ipbmap	-  pointer to in-core inode for the block map.
+ *	ipbmap	- pointer to in-core inode for the block map.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  */
 int dbUnmount(struct inode *ipbmap, int mounterror)
 {
@@ -320,13 +320,13 @@
  *		at a time.
  *
  * PARAMETERS:
- *      ip	-  pointer to in-core inode;
- *      blkno	-  starting block number to be freed.
- *      nblocks	-  number of blocks to be freed.
+ *	ip	- pointer to in-core inode;
+ *	blkno	- starting block number to be freed.
+ *	nblocks	- number of blocks to be freed.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  */
 int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
 {
@@ -395,23 +395,23 @@
 /*
  * NAME:	dbUpdatePMap()
  *
- * FUNCTION:    update the allocation state (free or allocate) of the
+ * FUNCTION:	update the allocation state (free or allocate) of the
  *		specified block range in the persistent block allocation map.
  *
  *		the blocks will be updated in the persistent map one
  *		dmap at a time.
  *
  * PARAMETERS:
- *      ipbmap	-  pointer to in-core inode for the block map.
- *      free	-  'true' if block range is to be freed from the persistent
- *		   map; 'false' if it is to   be allocated.
- *      blkno	-  starting block number of the range.
- *      nblocks	-  number of contiguous blocks in the range.
- *      tblk	-  transaction block;
+ *	ipbmap	- pointer to in-core inode for the block map.
+ *	free	- 'true' if block range is to be freed from the persistent
+ *		  map; 'false' if it is to be allocated.
+ *	blkno	- starting block number of the range.
+ *	nblocks	- number of contiguous blocks in the range.
+ *	tblk	- transaction block;
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  */
 int
 dbUpdatePMap(struct inode *ipbmap,
@@ -573,7 +573,7 @@
 /*
  * NAME:	dbNextAG()
  *
- * FUNCTION:    find the preferred allocation group for new allocations.
+ * FUNCTION:	find the preferred allocation group for new allocations.
  *
  *		Within the allocation groups, we maintain a preferred
  *		allocation group which consists of a group with at least
@@ -589,10 +589,10 @@
  *		empty ags around for large allocations.
  *
  * PARAMETERS:
- *      ipbmap	-  pointer to in-core inode for the block map.
+ *	ipbmap	- pointer to in-core inode for the block map.
  *
  * RETURN VALUES:
- *      the preferred allocation group number.
+ *	the preferred allocation group number.
  */
 int dbNextAG(struct inode *ipbmap)
 {
@@ -656,7 +656,7 @@
 /*
  * NAME:	dbAlloc()
  *
- * FUNCTION:    attempt to allocate a specified number of contiguous free
+ * FUNCTION:	attempt to allocate a specified number of contiguous free
  *		blocks from the working allocation block map.
  *
  *		the block allocation policy uses hints and a multi-step
@@ -680,16 +680,16 @@
  *		size or requests that specify no hint value.
  *
  * PARAMETERS:
- *      ip	-  pointer to in-core inode;
- *      hint	- allocation hint.
- *      nblocks	- number of contiguous blocks in the range.
- *      results	- on successful return, set to the starting block number
+ *	ip	- pointer to in-core inode;
+ *	hint	- allocation hint.
+ *	nblocks	- number of contiguous blocks in the range.
+ *	results	- on successful return, set to the starting block number
  *		  of the newly allocated contiguous range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  */
 int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
 {
@@ -706,12 +706,6 @@
 	/* assert that nblocks is valid */
 	assert(nblocks > 0);
 
-#ifdef _STILL_TO_PORT
-	/* DASD limit check                                     F226941 */
-	if (OVER_LIMIT(ip, nblocks))
-		return -ENOSPC;
-#endif				/* _STILL_TO_PORT */
-
 	/* get the log2 number of blocks to be allocated.
 	 * if the number of blocks is not a log2 multiple,
 	 * it will be rounded up to the next log2 multiple.
@@ -720,7 +714,6 @@
 
 	bmp = JFS_SBI(ip->i_sb)->bmap;
 
-//retry:        /* serialize w.r.t.extendfs() */
 	mapSize = bmp->db_mapsize;
 
 	/* the hint should be within the map */
@@ -879,17 +872,17 @@
 /*
  * NAME:	dbAllocExact()
  *
- * FUNCTION:    try to allocate the requested extent;
+ * FUNCTION:	try to allocate the requested extent;
  *
  * PARAMETERS:
- *      ip	- pointer to in-core inode;
- *      blkno	- extent address;
- *      nblocks	- extent length;
+ *	ip	- pointer to in-core inode;
+ *	blkno	- extent address;
+ *	nblocks	- extent length;
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  */
 int dbAllocExact(struct inode *ip, s64 blkno, int nblocks)
 {
@@ -946,7 +939,7 @@
 /*
  * NAME:	dbReAlloc()
  *
- * FUNCTION:    attempt to extend a current allocation by a specified
+ * FUNCTION:	attempt to extend a current allocation by a specified
  *		number of blocks.
  *
  *		this routine attempts to satisfy the allocation request
@@ -959,21 +952,21 @@
  *		number of blocks required.
  *
  * PARAMETERS:
- *      ip	    -  pointer to in-core inode requiring allocation.
- *      blkno	    -  starting block of the current allocation.
- *      nblocks	    -  number of contiguous blocks within the current
+ *	ip	    -  pointer to in-core inode requiring allocation.
+ *	blkno	    -  starting block of the current allocation.
+ *	nblocks	    -  number of contiguous blocks within the current
  *		       allocation.
- *      addnblocks  -  number of blocks to add to the allocation.
- *      results	-      on successful return, set to the starting block number
+ *	addnblocks  -  number of blocks to add to the allocation.
+ *	results	-      on successful return, set to the starting block number
  *		       of the existing allocation if the existing allocation
  *		       was extended in place or to a newly allocated contiguous
  *		       range if the existing allocation could not be extended
  *		       in place.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  */
 int
 dbReAlloc(struct inode *ip,
@@ -1004,7 +997,7 @@
 /*
  * NAME:	dbExtend()
  *
- * FUNCTION:    attempt to extend a current allocation by a specified
+ * FUNCTION:	attempt to extend a current allocation by a specified
  *		number of blocks.
  *
  *		this routine attempts to satisfy the allocation request
@@ -1013,16 +1006,16 @@
  *		immediately following the current allocation.
  *
  * PARAMETERS:
- *      ip	    -  pointer to in-core inode requiring allocation.
- *      blkno	    -  starting block of the current allocation.
- *      nblocks	    -  number of contiguous blocks within the current
+ *	ip	    -  pointer to in-core inode requiring allocation.
+ *	blkno	    -  starting block of the current allocation.
+ *	nblocks	    -  number of contiguous blocks within the current
  *		       allocation.
- *      addnblocks  -  number of blocks to add to the allocation.
+ *	addnblocks  -  number of blocks to add to the allocation.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  */
 static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks)
 {
@@ -1109,19 +1102,19 @@
 /*
  * NAME:	dbAllocNext()
  *
- * FUNCTION:    attempt to allocate the blocks of the specified block
+ * FUNCTION:	attempt to allocate the blocks of the specified block
  *		range within a dmap.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap.
- *      blkno	-  starting block number of the range.
- *      nblocks	-  number of contiguous free blocks of the range.
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap.
+ *	blkno	-  starting block number of the range.
+ *	nblocks	-  number of contiguous free blocks of the range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap) held on entry/exit;
  */
@@ -1233,7 +1226,7 @@
 /*
  * NAME:	dbAllocNear()
  *
- * FUNCTION:    attempt to allocate a number of contiguous free blocks near
+ * FUNCTION:	attempt to allocate a number of contiguous free blocks near
  *		a specified block (hint) within a dmap.
  *
  *		starting with the dmap leaf that covers the hint, we'll
@@ -1242,18 +1235,18 @@
  *		the desired free space.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap.
- *      blkno	-  block number to allocate near.
- *      nblocks	-  actual number of contiguous free blocks desired.
- *      l2nb	-  log2 number of contiguous free blocks desired.
- *      results	-  on successful return, set to the starting block number
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap.
+ *	blkno	-  block number to allocate near.
+ *	nblocks	-  actual number of contiguous free blocks desired.
+ *	l2nb	-  log2 number of contiguous free blocks desired.
+ *	results	-  on successful return, set to the starting block number
  *		   of the newly allocated range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap) held on entry/exit;
  */
@@ -1316,7 +1309,7 @@
 /*
  * NAME:	dbAllocAG()
  *
- * FUNCTION:    attempt to allocate the specified number of contiguous
+ * FUNCTION:	attempt to allocate the specified number of contiguous
  *		free blocks within the specified allocation group.
  *
  *		unless the allocation group size is equal to the number
@@ -1353,17 +1346,17 @@
  *		the allocation group.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
+ *	bmp	-  pointer to bmap descriptor
  *	agno	- allocation group number.
- *      nblocks	-  actual number of contiguous free blocks desired.
- *      l2nb	-  log2 number of contiguous free blocks desired.
- *      results	-  on successful return, set to the starting block number
+ *	nblocks	-  actual number of contiguous free blocks desired.
+ *	l2nb	-  log2 number of contiguous free blocks desired.
+ *	results	-  on successful return, set to the starting block number
  *		   of the newly allocated range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * note: IWRITE_LOCK(ipmap) held on entry/exit;
  */
@@ -1546,7 +1539,7 @@
 /*
  * NAME:	dbAllocAny()
  *
- * FUNCTION:    attempt to allocate the specified number of contiguous
+ * FUNCTION:	attempt to allocate the specified number of contiguous
  *		free blocks anywhere in the file system.
  *
  *		dbAllocAny() attempts to find the sufficient free space by
@@ -1556,16 +1549,16 @@
  *		desired free space is allocated.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      nblocks	 -  actual number of contiguous free blocks desired.
- *      l2nb	 -  log2 number of contiguous free blocks desired.
- *      results	-  on successful return, set to the starting block number
+ *	bmp	-  pointer to bmap descriptor
+ *	nblocks	 -  actual number of contiguous free blocks desired.
+ *	l2nb	 -  log2 number of contiguous free blocks desired.
+ *	results	-  on successful return, set to the starting block number
  *		   of the newly allocated range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -1598,9 +1591,9 @@
 /*
  * NAME:	dbFindCtl()
  *
- * FUNCTION:    starting at a specified dmap control page level and block
+ * FUNCTION:	starting at a specified dmap control page level and block
  *		number, search down the dmap control levels for a range of
- *	        contiguous free blocks large enough to satisfy an allocation
+ *		contiguous free blocks large enough to satisfy an allocation
  *		request for the specified number of free blocks.
  *
  *		if sufficient contiguous free blocks are found, this routine
@@ -1609,17 +1602,17 @@
  *		is sufficient in size.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      level	-  starting dmap control page level.
- *      l2nb	-  log2 number of contiguous free blocks desired.
- *      *blkno	-  on entry, starting block number for conducting the search.
+ *	bmp	-  pointer to bmap descriptor
+ *	level	-  starting dmap control page level.
+ *	l2nb	-  log2 number of contiguous free blocks desired.
+ *	*blkno	-  on entry, starting block number for conducting the search.
  *		   on successful return, the first block within a dmap page
  *		   that contains or starts a range of contiguous free blocks.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -1699,7 +1692,7 @@
 /*
  * NAME:	dbAllocCtl()
  *
- * FUNCTION:    attempt to allocate a specified number of contiguous
+ * FUNCTION:	attempt to allocate a specified number of contiguous
  *		blocks starting within a specific dmap.
  *
  *		this routine is called by higher level routines that search
@@ -1726,18 +1719,18 @@
  *		first dmap (i.e. blkno).
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      nblocks	 -  actual number of contiguous free blocks to allocate.
- *      l2nb	 -  log2 number of contiguous free blocks to allocate.
- *      blkno	 -  starting block number of the dmap to start the allocation
+ *	bmp	-  pointer to bmap descriptor
+ *	nblocks	 -  actual number of contiguous free blocks to allocate.
+ *	l2nb	 -  log2 number of contiguous free blocks to allocate.
+ *	blkno	 -  starting block number of the dmap to start the allocation
  *		    from.
- *      results	-  on successful return, set to the starting block number
+ *	results	-  on successful return, set to the starting block number
  *		   of the newly allocated range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -1870,7 +1863,7 @@
 /*
  * NAME:	dbAllocDmapLev()
  *
- * FUNCTION:    attempt to allocate a specified number of contiguous blocks
+ * FUNCTION:	attempt to allocate a specified number of contiguous blocks
  *		from a specified dmap.
  *
  *		this routine checks if the contiguous blocks are available.
@@ -1878,17 +1871,17 @@
  *		returned.
  *
  * PARAMETERS:
- *      mp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap to attempt to allocate blocks from.
- *      l2nb	-  log2 number of contiguous block desired.
- *      nblocks	-  actual number of contiguous block desired.
- *      results	-  on successful return, set to the starting block number
+ *	mp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap to attempt to allocate blocks from.
+ *	l2nb	-  log2 number of contiguous block desired.
+ *	nblocks	-  actual number of contiguous block desired.
+ *	results	-  on successful return, set to the starting block number
  *		   of the newly allocated range.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient disk resources
- *      -EIO	- i/o error
+ *	0	- success
+ *	-ENOSPC	- insufficient disk resources
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap), e.g., from dbAlloc(), or
  *	IWRITE_LOCK(ipbmap), e.g., dbAllocCtl(), held on entry/exit;
@@ -1933,7 +1926,7 @@
 /*
  * NAME:	dbAllocDmap()
  *
- * FUNCTION:    adjust the disk allocation map to reflect the allocation
+ * FUNCTION:	adjust the disk allocation map to reflect the allocation
  *		of a specified block range within a dmap.
  *
  *		this routine allocates the specified blocks from the dmap
@@ -1946,14 +1939,14 @@
  *		covers this dmap.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap to allocate the block range from.
- *      blkno	-  starting block number of the block to be allocated.
- *      nblocks	-  number of blocks to be allocated.
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap to allocate the block range from.
+ *	blkno	-  starting block number of the block to be allocated.
+ *	nblocks	-  number of blocks to be allocated.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -1989,7 +1982,7 @@
 /*
  * NAME:	dbFreeDmap()
  *
- * FUNCTION:    adjust the disk allocation map to reflect the allocation
+ * FUNCTION:	adjust the disk allocation map to reflect the allocation
  *		of a specified block range within a dmap.
  *
  *		this routine frees the specified blocks from the dmap through
@@ -1997,18 +1990,18 @@
  *		causes the maximum string of free blocks within the dmap to
  *		change (i.e. the value of the root of the dmap's dmtree), this
  *		routine will cause this change to be reflected up through the
- *	        appropriate levels of the dmap control pages by a call to
+ *		appropriate levels of the dmap control pages by a call to
  *		dbAdjCtl() for the L0 dmap control page that covers this dmap.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap to free the block range from.
- *      blkno	-  starting block number of the block to be freed.
- *      nblocks	-  number of blocks to be freed.
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap to free the block range from.
+ *	blkno	-  starting block number of the block to be freed.
+ *	nblocks	-  number of blocks to be freed.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -2055,7 +2048,7 @@
 /*
  * NAME:	dbAllocBits()
  *
- * FUNCTION:    allocate a specified block range from a dmap.
+ * FUNCTION:	allocate a specified block range from a dmap.
  *
  *		this routine updates the dmap to reflect the working
  *		state allocation of the specified block range. it directly
@@ -2065,10 +2058,10 @@
  *		dmap's dmtree, as a whole, to reflect the allocated range.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap to allocate bits from.
- *      blkno	-  starting block number of the bits to be allocated.
- *      nblocks	-  number of bits to be allocated.
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap to allocate bits from.
+ *	blkno	-  starting block number of the bits to be allocated.
+ *	nblocks	-  number of bits to be allocated.
  *
  * RETURN VALUES: none
  *
@@ -2149,7 +2142,7 @@
 			 * the allocated words.
 			 */
 			for (; nwords > 0; nwords -= nw) {
-			        if (leaf[word] < BUDMIN) {
+				if (leaf[word] < BUDMIN) {
 					jfs_error(bmp->db_ipbmap->i_sb,
 						  "dbAllocBits: leaf page "
 						  "corrupt");
@@ -2202,7 +2195,7 @@
 /*
  * NAME:	dbFreeBits()
  *
- * FUNCTION:    free a specified block range from a dmap.
+ * FUNCTION:	free a specified block range from a dmap.
  *
  *		this routine updates the dmap to reflect the working
  *		state allocation of the specified block range. it directly
@@ -2212,10 +2205,10 @@
  *		dmtree, as a whole, to reflect the deallocated range.
  *
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      dp	-  pointer to dmap to free bits from.
- *      blkno	-  starting block number of the bits to be freed.
- *      nblocks	-  number of bits to be freed.
+ *	bmp	-  pointer to bmap descriptor
+ *	dp	-  pointer to dmap to free bits from.
+ *	blkno	-  starting block number of the bits to be freed.
+ *	nblocks	-  number of bits to be freed.
  *
  * RETURN VALUES: 0 for success
  *
@@ -2388,19 +2381,19 @@
  *		the new root value and the next dmap control page level to
  *		be adjusted.
  * PARAMETERS:
- *      bmp	-  pointer to bmap descriptor
- *      blkno	-  the first block of a block range within a dmap.  it is
+ *	bmp	-  pointer to bmap descriptor
+ *	blkno	-  the first block of a block range within a dmap.  it is
  *		   the allocation or deallocation of this block range that
  *		   requires the dmap control page to be adjusted.
- *      newval	-  the new value of the lower level dmap or dmap control
+ *	newval	-  the new value of the lower level dmap or dmap control
  *		   page root.
- *      alloc	-  'true' if adjustment is due to an allocation.
- *      level	-  current level of dmap control page (i.e. L0, L1, L2) to
+ *	alloc	-  'true' if adjustment is due to an allocation.
+ *	level	-  current level of dmap control page (i.e. L0, L1, L2) to
  *		   be adjusted.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  *
  * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
  */
@@ -2544,16 +2537,16 @@
 /*
  * NAME:	dbSplit()
  *
- * FUNCTION:    update the leaf of a dmtree with a new value, splitting
+ * FUNCTION:	update the leaf of a dmtree with a new value, splitting
  *		the leaf from the binary buddy system of the dmtree's
  *		leaves, as required.
  *
  * PARAMETERS:
- *      tp	- pointer to the tree containing the leaf.
- *      leafno	- the number of the leaf to be updated.
- *      splitsz	- the size the binary buddy system starting at the leaf
+ *	tp	- pointer to the tree containing the leaf.
+ *	leafno	- the number of the leaf to be updated.
+ *	splitsz	- the size the binary buddy system starting at the leaf
  *		  must be split to, specified as the log2 number of blocks.
- *      newval	- the new value for the leaf.
+ *	newval	- the new value for the leaf.
  *
  * RETURN VALUES: none
  *
@@ -2600,7 +2593,7 @@
 /*
  * NAME:	dbBackSplit()
  *
- * FUNCTION:    back split the binary buddy system of dmtree leaves
+ * FUNCTION:	back split the binary buddy system of dmtree leaves
  *		that hold a specified leaf until the specified leaf
  *		starts its own binary buddy system.
  *
@@ -2617,8 +2610,8 @@
  *		in which a previous join operation must be backed out.
  *
  * PARAMETERS:
- *      tp	- pointer to the tree containing the leaf.
- *      leafno	- the number of the leaf to be updated.
+ *	tp	- pointer to the tree containing the leaf.
+ *	leafno	- the number of the leaf to be updated.
  *
  * RETURN VALUES: none
  *
@@ -2692,14 +2685,14 @@
 /*
  * NAME:	dbJoin()
  *
- * FUNCTION:    update the leaf of a dmtree with a new value, joining
+ * FUNCTION:	update the leaf of a dmtree with a new value, joining
  *		the leaf with other leaves of the dmtree into a multi-leaf
  *		binary buddy system, as required.
  *
  * PARAMETERS:
- *      tp	- pointer to the tree containing the leaf.
- *      leafno	- the number of the leaf to be updated.
- *      newval	- the new value for the leaf.
+ *	tp	- pointer to the tree containing the leaf.
+ *	leafno	- the number of the leaf to be updated.
+ *	newval	- the new value for the leaf.
  *
  * RETURN VALUES: none
  */
@@ -2785,15 +2778,15 @@
 /*
  * NAME:	dbAdjTree()
  *
- * FUNCTION:    update a leaf of a dmtree with a new value, adjusting
+ * FUNCTION:	update a leaf of a dmtree with a new value, adjusting
  *		the dmtree, as required, to reflect the new leaf value.
  *		the combination of any buddies must already be done before
  *		this is called.
  *
  * PARAMETERS:
- *      tp	- pointer to the tree to be adjusted.
- *      leafno	- the number of the leaf to be updated.
- *      newval	- the new value for the leaf.
+ *	tp	- pointer to the tree to be adjusted.
+ *	leafno	- the number of the leaf to be updated.
+ *	newval	- the new value for the leaf.
  *
  * RETURN VALUES: none
  */
@@ -2852,7 +2845,7 @@
 /*
  * NAME:	dbFindLeaf()
  *
- * FUNCTION:    search a dmtree_t for sufficient free blocks, returning
+ * FUNCTION:	search a dmtree_t for sufficient free blocks, returning
  *		the index of a leaf describing the free blocks if
  *		sufficient free blocks are found.
  *
@@ -2861,15 +2854,15 @@
  *		free space.
  *
  * PARAMETERS:
- *      tp	- pointer to the tree to be searched.
- *      l2nb	- log2 number of free blocks to search for.
+ *	tp	- pointer to the tree to be searched.
+ *	l2nb	- log2 number of free blocks to search for.
  *	leafidx	- return pointer to be set to the index of the leaf
  *		  describing at least l2nb free blocks if sufficient
  *		  free blocks are found.
  *
  * RETURN VALUES:
- *      0	- success
- *      -ENOSPC	- insufficient free blocks.
+ *	0	- success
+ *	-ENOSPC	- insufficient free blocks.
  */
 static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
 {
@@ -2916,18 +2909,18 @@
 /*
  * NAME:	dbFindBits()
  *
- * FUNCTION:    find a specified number of binary buddy free bits within a
+ * FUNCTION:	find a specified number of binary buddy free bits within a
  *		dmap bitmap word value.
  *
  *		this routine searches the bitmap value for (1 << l2nb) free
  *		bits at (1 << l2nb) alignments within the value.
  *
  * PARAMETERS:
- *      word	-  dmap bitmap word value.
- *      l2nb	-  number of free bits specified as a log2 number.
+ *	word	-  dmap bitmap word value.
+ *	l2nb	-  number of free bits specified as a log2 number.
  *
  * RETURN VALUES:
- *      starting bit number of free bits.
+ *	starting bit number of free bits.
  */
 static int dbFindBits(u32 word, int l2nb)
 {
@@ -2963,14 +2956,14 @@
 /*
  * NAME:	dbMaxBud(u8 *cp)
  *
- * FUNCTION:    determine the largest binary buddy string of free
+ * FUNCTION:	determine the largest binary buddy string of free
  *		bits within 32-bits of the map.
  *
  * PARAMETERS:
- *      cp	-  pointer to the 32-bit value.
+ *	cp	-  pointer to the 32-bit value.
  *
  * RETURN VALUES:
- *      largest binary buddy of free bits within a dmap word.
+ *	largest binary buddy of free bits within a dmap word.
  */
 static int dbMaxBud(u8 * cp)
 {
@@ -3000,14 +2993,14 @@
 /*
  * NAME:	cnttz(uint word)
  *
- * FUNCTION:    determine the number of trailing zeros within a 32-bit
+ * FUNCTION:	determine the number of trailing zeros within a 32-bit
  *		value.
  *
  * PARAMETERS:
- *      value	-  32-bit value to be examined.
+ *	value	-  32-bit value to be examined.
  *
  * RETURN VALUES:
- *      count of trailing zeros
+ *	count of trailing zeros
  */
 static int cnttz(u32 word)
 {
@@ -3025,14 +3018,14 @@
 /*
  * NAME:	cntlz(u32 value)
  *
- * FUNCTION:    determine the number of leading zeros within a 32-bit
+ * FUNCTION:	determine the number of leading zeros within a 32-bit
  *		value.
  *
  * PARAMETERS:
- *      value	-  32-bit value to be examined.
+ *	value	-  32-bit value to be examined.
  *
  * RETURN VALUES:
- *      count of leading zeros
+ *	count of leading zeros
  */
 static int cntlz(u32 value)
 {
@@ -3050,14 +3043,14 @@
  * NAME:	blkstol2(s64 nb)
  *
  * FUNCTION:	convert a block count to its log2 value. if the block
- *	        count is not a l2 multiple, it is rounded up to the next
+ *		count is not a l2 multiple, it is rounded up to the next
  *		larger l2 multiple.
  *
  * PARAMETERS:
- *      nb	-  number of blocks
+ *	nb	-  number of blocks
  *
  * RETURN VALUES:
- *      log2 number of blocks
+ *	log2 number of blocks
  */
 static int blkstol2(s64 nb)
 {
@@ -3099,13 +3092,13 @@
  *		at a time.
  *
  * PARAMETERS:
- *      ip	-  pointer to in-core inode;
- *      blkno	-  starting block number to be freed.
- *      nblocks	-  number of blocks to be freed.
+ *	ip	-  pointer to in-core inode;
+ *	blkno	-  starting block number to be freed.
+ *	nblocks	-  number of blocks to be freed.
  *
  * RETURN VALUES:
- *      0	- success
- *      -EIO	- i/o error
+ *	0	- success
+ *	-EIO	- i/o error
  */
 int dbAllocBottomUp(struct inode *ip, s64 blkno, s64 nblocks)
 {
@@ -3278,10 +3271,10 @@
  * L2
  *  |
  *   L1---------------------------------L1
- *    |                                  |
- *     L0---------L0---------L0           L0---------L0---------L0
- *      |          |          |            |          |          |
- *       d0,...,dn  d0,...,dn  d0,...,dn    d0,...,dn  d0,...,dn  d0,.,dm;
+ *    |					 |
+ *     L0---------L0---------L0		  L0---------L0---------L0
+ *      |	   |	      |		   |	      |		 |
+ *	 d0,...,dn  d0,...,dn  d0,...,dn    d0,...,dn  d0,...,dn  d0,.,dm;
  * L2L1L0d0,...,dnL0d0,...,dnL0d0,...,dnL1L0d0,...,dnL0d0,...,dnL0d0,..dm
  *
  * <---old---><----------------------------extend----------------------->
@@ -3307,7 +3300,7 @@
 		 (long long) blkno, (long long) nblocks, (long long) newsize);
 
 	/*
-	 *      initialize bmap control page.
+	 *	initialize bmap control page.
 	 *
 	 * all the data in bmap control page should exclude
 	 * the mkfs hidden dmap page.
@@ -3330,7 +3323,7 @@
 	bmp->db_numag += ((u32) newsize % (u32) bmp->db_agsize) ? 1 : 0;
 
 	/*
-	 *      reconfigure db_agfree[]
+	 *	reconfigure db_agfree[]
 	 * from old AG configuration to new AG configuration;
 	 *
 	 * coalesce contiguous k (newAGSize/oldAGSize) AGs;
@@ -3362,7 +3355,7 @@
 	bmp->db_maxag = bmp->db_maxag / k;
 
 	/*
-	 *      extend bmap
+	 *	extend bmap
 	 *
 	 * update bit maps and corresponding level control pages;
 	 * global control page db_nfree, db_agfree[agno], db_maxfreebud;
@@ -3410,7 +3403,7 @@
 			/* compute start L0 */
 			j = 0;
 			l1leaf = l1dcp->stree + CTLLEAFIND;
-			p += nbperpage;	/* 1st L0 of L1.k  */
+			p += nbperpage;	/* 1st L0 of L1.k */
 		}
 
 		/*
@@ -3548,7 +3541,7 @@
 	return -EIO;
 
 	/*
-	 *      finalize bmap control page
+	 *	finalize bmap control page
 	 */
 finalize:
 
@@ -3567,7 +3560,7 @@
 	int i, n;
 
 	/*
-	 *      finalize bmap control page
+	 *	finalize bmap control page
 	 */
 //finalize:
 	/*
@@ -3953,8 +3946,8 @@
  * convert number of map pages to the zero origin top dmapctl level
  */
 #define BMAPPGTOLEV(npages)	\
-	(((npages) <= 3 + MAXL0PAGES) ? 0 \
-       : ((npages) <= 2 + MAXL1PAGES) ? 1 : 2)
+	(((npages) <= 3 + MAXL0PAGES) ? 0 : \
+	 ((npages) <= 2 + MAXL1PAGES) ? 1 : 2)
 
 s64 dbMapFileSizeToMapSize(struct inode * ipbmap)
 {
@@ -3981,8 +3974,8 @@
 		factor =
 		    (i == 2) ? MAXL1PAGES : ((i == 1) ? MAXL0PAGES : 1);
 		complete = (u32) npages / factor;
-		ndmaps += complete * ((i == 2) ? LPERCTL * LPERCTL
-				      : ((i == 1) ? LPERCTL : 1));
+		ndmaps += complete * ((i == 2) ? LPERCTL * LPERCTL :
+				      ((i == 1) ? LPERCTL : 1));
 
 		/* pages in last/incomplete child */
 		npages = (u32) npages % factor;
diff --git a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h
index 45ea454..11e6d47 100644
--- a/fs/jfs/jfs_dmap.h
+++ b/fs/jfs/jfs_dmap.h
@@ -83,7 +83,7 @@
  *	- 1 is added to account for the control page of the map.
  */
 #define BLKTODMAP(b,s)    \
-        ((((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) << (s))
+	((((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) << (s))
 
 /*
  * convert disk block number to the logical block number of the LEVEL 0
@@ -98,7 +98,7 @@
  *	- 1 is added to account for the control page of the map.
  */
 #define BLKTOL0(b,s)      \
-        (((((b) >> 23) << 10) + ((b) >> 23) + ((b) >> 33) + 2 + 1) << (s))
+	(((((b) >> 23) << 10) + ((b) >> 23) + ((b) >> 33) + 2 + 1) << (s))
 
 /*
  * convert disk block number to the logical block number of the LEVEL 1
@@ -120,7 +120,7 @@
  * at the specified level which describes the disk block.
  */
 #define BLKTOCTL(b,s,l)   \
-        (((l) == 2) ? 1 : ((l) == 1) ? BLKTOL1((b),(s)) : BLKTOL0((b),(s)))
+	(((l) == 2) ? 1 : ((l) == 1) ? BLKTOL1((b),(s)) : BLKTOL0((b),(s)))
 
 /*
  * convert aggregate map size to the zero origin dmapctl level of the
@@ -145,27 +145,27 @@
  * dmaptree must be consistent with dmapctl.
  */
 struct dmaptree {
-	__le32 nleafs;		/* 4: number of tree leafs      */
-	__le32 l2nleafs;	/* 4: l2 number of tree leafs   */
-	__le32 leafidx;		/* 4: index of first tree leaf  */
-	__le32 height;		/* 4: height of the tree        */
+	__le32 nleafs;		/* 4: number of tree leafs	*/
+	__le32 l2nleafs;	/* 4: l2 number of tree leafs	*/
+	__le32 leafidx;		/* 4: index of first tree leaf	*/
+	__le32 height;		/* 4: height of the tree	*/
 	s8 budmin;		/* 1: min l2 tree leaf value to combine */
-	s8 stree[TREESIZE];	/* TREESIZE: tree               */
-	u8 pad[2];		/* 2: pad to word boundary      */
-};				/* - 360 -                      */
+	s8 stree[TREESIZE];	/* TREESIZE: tree		*/
+	u8 pad[2];		/* 2: pad to word boundary	*/
+};				/* - 360 -			*/
 
 /*
  *	dmap page per 8K blocks bitmap
  */
 struct dmap {
-	__le32 nblocks;		/* 4: num blks covered by this dmap     */
-	__le32 nfree;		/* 4: num of free blks in this dmap     */
-	__le64 start;		/* 8: starting blkno for this dmap      */
-	struct dmaptree tree;	/* 360: dmap tree                       */
-	u8 pad[1672];		/* 1672: pad to 2048 bytes              */
-	__le32 wmap[LPERDMAP];	/* 1024: bits of the working map        */
-	__le32 pmap[LPERDMAP];	/* 1024: bits of the persistent map     */
-};				/* - 4096 -                             */
+	__le32 nblocks;		/* 4: num blks covered by this dmap	*/
+	__le32 nfree;		/* 4: num of free blks in this dmap	*/
+	__le64 start;		/* 8: starting blkno for this dmap	*/
+	struct dmaptree tree;	/* 360: dmap tree			*/
+	u8 pad[1672];		/* 1672: pad to 2048 bytes		*/
+	__le32 wmap[LPERDMAP];	/* 1024: bits of the working map	*/
+	__le32 pmap[LPERDMAP];	/* 1024: bits of the persistent map	*/
+};				/* - 4096 -				*/
 
 /*
  *	disk map control page per level.
@@ -173,14 +173,14 @@
  * dmapctl must be consistent with dmaptree.
  */
 struct dmapctl {
-	__le32 nleafs;		/* 4: number of tree leafs      */
-	__le32 l2nleafs;	/* 4: l2 number of tree leafs   */
-	__le32 leafidx;		/* 4: index of the first tree leaf      */
-	__le32 height;		/* 4: height of tree            */
-	s8 budmin;		/* 1: minimum l2 tree leaf value        */
-	s8 stree[CTLTREESIZE];	/* CTLTREESIZE: dmapctl tree    */
-	u8 pad[2714];		/* 2714: pad to 4096            */
-};				/* - 4096 -                     */
+	__le32 nleafs;		/* 4: number of tree leafs	*/
+	__le32 l2nleafs;	/* 4: l2 number of tree leafs	*/
+	__le32 leafidx;		/* 4: index of the first tree leaf	*/
+	__le32 height;		/* 4: height of tree		*/
+	s8 budmin;		/* 1: minimum l2 tree leaf value	*/
+	s8 stree[CTLTREESIZE];	/* CTLTREESIZE: dmapctl tree	*/
+	u8 pad[2714];		/* 2714: pad to 4096		*/
+};				/* - 4096 -			*/
 
 /*
  *	common definition for dmaptree within dmap and dmapctl
@@ -202,41 +202,41 @@
  *	on-disk aggregate disk allocation map descriptor.
  */
 struct dbmap_disk {
-	__le64 dn_mapsize;	/* 8: number of blocks in aggregate     */
-	__le64 dn_nfree;	/* 8: num free blks in aggregate map    */
-	__le32 dn_l2nbperpage;	/* 4: number of blks per page           */
-	__le32 dn_numag;	/* 4: total number of ags               */
-	__le32 dn_maxlevel;	/* 4: number of active ags              */
-	__le32 dn_maxag;	/* 4: max active alloc group number     */
-	__le32 dn_agpref;	/* 4: preferred alloc group (hint)      */
-	__le32 dn_aglevel;	/* 4: dmapctl level holding the AG      */
-	__le32 dn_agheigth;	/* 4: height in dmapctl of the AG       */
-	__le32 dn_agwidth;	/* 4: width in dmapctl of the AG        */
-	__le32 dn_agstart;	/* 4: start tree index at AG height     */
-	__le32 dn_agl2size;	/* 4: l2 num of blks per alloc group    */
-	__le64 dn_agfree[MAXAG];/* 8*MAXAG: per AG free count           */
-	__le64 dn_agsize;	/* 8: num of blks per alloc group       */
-	s8 dn_maxfreebud;	/* 1: max free buddy system             */
-	u8 pad[3007];		/* 3007: pad to 4096                    */
-};				/* - 4096 -                             */
+	__le64 dn_mapsize;	/* 8: number of blocks in aggregate	*/
+	__le64 dn_nfree;	/* 8: num free blks in aggregate map	*/
+	__le32 dn_l2nbperpage;	/* 4: number of blks per page		*/
+	__le32 dn_numag;	/* 4: total number of ags		*/
+	__le32 dn_maxlevel;	/* 4: number of active ags		*/
+	__le32 dn_maxag;	/* 4: max active alloc group number	*/
+	__le32 dn_agpref;	/* 4: preferred alloc group (hint)	*/
+	__le32 dn_aglevel;	/* 4: dmapctl level holding the AG	*/
+	__le32 dn_agheigth;	/* 4: height in dmapctl of the AG	*/
+	__le32 dn_agwidth;	/* 4: width in dmapctl of the AG	*/
+	__le32 dn_agstart;	/* 4: start tree index at AG height	*/
+	__le32 dn_agl2size;	/* 4: l2 num of blks per alloc group	*/
+	__le64 dn_agfree[MAXAG];/* 8*MAXAG: per AG free count		*/
+	__le64 dn_agsize;	/* 8: num of blks per alloc group	*/
+	s8 dn_maxfreebud;	/* 1: max free buddy system		*/
+	u8 pad[3007];		/* 3007: pad to 4096			*/
+};				/* - 4096 -				*/
 
 struct dbmap {
-	s64 dn_mapsize;		/* number of blocks in aggregate     */
-	s64 dn_nfree;		/* num free blks in aggregate map    */
-	int dn_l2nbperpage;	/* number of blks per page           */
-	int dn_numag;		/* total number of ags               */
-	int dn_maxlevel;	/* number of active ags              */
-	int dn_maxag;		/* max active alloc group number     */
-	int dn_agpref;		/* preferred alloc group (hint)      */
-	int dn_aglevel;		/* dmapctl level holding the AG      */
-	int dn_agheigth;	/* height in dmapctl of the AG       */
-	int dn_agwidth;		/* width in dmapctl of the AG        */
-	int dn_agstart;		/* start tree index at AG height     */
-	int dn_agl2size;	/* l2 num of blks per alloc group    */
-	s64 dn_agfree[MAXAG];	/* per AG free count           */
-	s64 dn_agsize;		/* num of blks per alloc group       */
-	signed char dn_maxfreebud;	/* max free buddy system             */
-};				/* - 4096 -                             */
+	s64 dn_mapsize;		/* number of blocks in aggregate	*/
+	s64 dn_nfree;		/* num free blks in aggregate map	*/
+	int dn_l2nbperpage;	/* number of blks per page		*/
+	int dn_numag;		/* total number of ags			*/
+	int dn_maxlevel;	/* number of active ags			*/
+	int dn_maxag;		/* max active alloc group number	*/
+	int dn_agpref;		/* preferred alloc group (hint)		*/
+	int dn_aglevel;		/* dmapctl level holding the AG		*/
+	int dn_agheigth;	/* height in dmapctl of the AG		*/
+	int dn_agwidth;		/* width in dmapctl of the AG		*/
+	int dn_agstart;		/* start tree index at AG height	*/
+	int dn_agl2size;	/* l2 num of blks per alloc group	*/
+	s64 dn_agfree[MAXAG];	/* per AG free count			*/
+	s64 dn_agsize;		/* num of blks per alloc group		*/
+	signed char dn_maxfreebud;	/* max free buddy system	*/
+};				/* - 4096 -				*/
 /*
  *	in-memory aggregate disk allocation map descriptor.
  */
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 6d62f32..c14ba3c 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -315,8 +315,8 @@
 	lv = &llck->lv[llck->index];
 
 	/*
-	 *      Linelock slot size is twice the size of directory table
-	 *      slot size.  512 entries per page.
+	 *	Linelock slot size is twice the size of directory table
+	 *	slot size.  512 entries per page.
 	 */
 	lv->offset = ((index - 2) & 511) >> 1;
 	lv->length = 1;
@@ -615,7 +615,7 @@
 	btstack->nsplit = 1;
 
 	/*
-	 *      search down tree from root:
+	 *	search down tree from root:
 	 *
 	 * between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
 	 * internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -659,7 +659,7 @@
 			}
 			if (cmp == 0) {
 				/*
-				 *      search hit
+				 *	search hit
 				 */
 				/* search hit - leaf page:
 				 * return the entry found
@@ -723,7 +723,7 @@
 		}
 
 		/*
-		 *      search miss
+		 *	search miss
 		 *
 		 * base is the smallest index with key (Kj) greater than
 		 * search key (K) and may be zero or (maxindex + 1) index.
@@ -834,7 +834,7 @@
 	struct lv *lv;
 
 	/*
-	 *      retrieve search result
+	 *	retrieve search result
 	 *
 	 * dtSearch() returns (leaf page pinned, index at which to insert).
 	 * n.b. dtSearch() may return index of (maxindex + 1) of
@@ -843,7 +843,7 @@
 	DT_GETSEARCH(ip, btstack->top, bn, mp, p, index);
 
 	/*
-	 *      insert entry for new key
+	 *	insert entry for new key
 	 */
 	if (DO_INDEX(ip)) {
 		if (JFS_IP(ip)->next_index == DIREND) {
@@ -860,9 +860,9 @@
 	data.leaf.ino = *fsn;
 
 	/*
-	 *      leaf page does not have enough room for new entry:
+	 *	leaf page does not have enough room for new entry:
 	 *
-	 *      extend/split the leaf page;
+	 *	extend/split the leaf page;
 	 *
 	 * dtSplitUp() will insert the entry and unpin the leaf page.
 	 */
@@ -877,9 +877,9 @@
 	}
 
 	/*
-	 *      leaf page does have enough room for new entry:
+	 *	leaf page does have enough room for new entry:
 	 *
-	 *      insert the new data entry into the leaf page;
+	 *	insert the new data entry into the leaf page;
 	 */
 	BT_MARK_DIRTY(mp, ip);
 	/*
@@ -967,13 +967,13 @@
 	}
 
 	/*
-	 *      split leaf page
+	 *	split leaf page
 	 *
 	 * The split routines insert the new entry, and
 	 * acquire txLock as appropriate.
 	 */
 	/*
-	 *      split root leaf page:
+	 *	split root leaf page:
 	 */
 	if (sp->header.flag & BT_ROOT) {
 		/*
@@ -1012,7 +1012,7 @@
 	}
 
 	/*
-	 *      extend first leaf page
+	 *	extend first leaf page
 	 *
 	 * extend the 1st extent if less than buffer page size
 	 * (dtExtendPage() reurns leaf page unpinned)
@@ -1068,7 +1068,7 @@
 	}
 
 	/*
-	 *      split leaf page <sp> into <sp> and a new right page <rp>.
+	 *	split leaf page <sp> into <sp> and a new right page <rp>.
 	 *
 	 * return <rp> pinned and its extent descriptor <rpxd>
 	 */
@@ -1433,7 +1433,7 @@
 	rp->header.freecnt = rp->header.maxslot - fsi;
 
 	/*
-	 *      sequential append at tail: append without split
+	 *	sequential append at tail: append without split
 	 *
 	 * If splitting the last page on a level because of appending
 	 * a entry to it (skip is maxentry), it's likely that the access is
@@ -1467,7 +1467,7 @@
 	}
 
 	/*
-	 *      non-sequential insert (at possibly middle page)
+	 *	non-sequential insert (at possibly middle page)
 	 */
 
 	/*
@@ -1508,7 +1508,7 @@
 	left = 0;
 
 	/*
-	 *      compute fill factor for split pages
+	 *	compute fill factor for split pages
 	 *
 	 * <nxt> traces the next entry to move to rp
 	 * <off> traces the next entry to stay in sp
@@ -1551,7 +1551,7 @@
 	/* <nxt> poins to the 1st entry to move */
 
 	/*
-	 *      move entries to right page
+	 *	move entries to right page
 	 *
 	 * dtMoveEntry() initializes rp and reserves entry for insertion
 	 *
@@ -1677,7 +1677,7 @@
 		return (rc);
 
 	/*
-	 *      extend the extent
+	 *	extend the extent
 	 */
 	pxdlist = split->pxdlist;
 	pxd = &pxdlist->pxd[pxdlist->npxd];
@@ -1722,7 +1722,7 @@
 	}
 
 	/*
-	 *      extend the page
+	 *	extend the page
 	 */
 	sp->header.self = *pxd;
 
@@ -1739,9 +1739,6 @@
 	/* update buffer extent descriptor of extended page */
 	xlen = lengthPXD(pxd);
 	xsize = xlen << JFS_SBI(sb)->l2bsize;
-#ifdef _STILL_TO_PORT
-	bmSetXD(smp, xaddr, xsize);
-#endif				/*  _STILL_TO_PORT */
 
 	/*
 	 * copy old stbl to new stbl at start of extended area
@@ -1836,7 +1833,7 @@
 	}
 
 	/*
-	 *      update parent entry on the parent/root page
+	 *	update parent entry on the parent/root page
 	 */
 	/*
 	 * acquire a transaction lock on the parent/root page
@@ -1904,7 +1901,7 @@
 	sp = &JFS_IP(ip)->i_dtroot;
 
 	/*
-	 *      allocate/initialize a single (right) child page
+	 *	allocate/initialize a single (right) child page
 	 *
 	 * N.B. at first split, a one (or two) block to fit new entry
 	 * is allocated; at subsequent split, a full page is allocated;
@@ -1943,7 +1940,7 @@
 	rp->header.prev = 0;
 
 	/*
-	 *      move in-line root page into new right page extent
+	 *	move in-line root page into new right page extent
 	 */
 	/* linelock header + copied entries + new stbl (1st slot) in new page */
 	ASSERT(dtlck->index == 0);
@@ -2016,7 +2013,7 @@
 	dtInsertEntry(rp, split->index, split->key, split->data, &dtlck);
 
 	/*
-	 *      reset parent/root page
+	 *	reset parent/root page
 	 *
 	 * set the 1st entry offset to 0, which force the left-most key
 	 * at any level of the tree to be less than any search key.
@@ -2102,7 +2099,7 @@
 	dtpage_t *np;
 
 	/*
-	 *      search for the entry to delete:
+	 *	search for the entry to delete:
 	 *
 	 * dtSearch() returns (leaf page pinned, index at which to delete).
 	 */
@@ -2253,7 +2250,7 @@
 	int i;
 
 	/*
-	 *      keep the root leaf page which has become empty
+	 *	keep the root leaf page which has become empty
 	 */
 	if (BT_IS_ROOT(fmp)) {
 		/*
@@ -2269,7 +2266,7 @@
 	}
 
 	/*
-	 *      free the non-root leaf page
+	 *	free the non-root leaf page
 	 */
 	/*
 	 * acquire a transaction lock on the page
@@ -2299,7 +2296,7 @@
 	discard_metapage(fmp);
 
 	/*
-	 *      propagate page deletion up the directory tree
+	 *	propagate page deletion up the directory tree
 	 *
 	 * If the delete from the parent page makes it empty,
 	 * continue all the way up the tree.
@@ -2440,10 +2437,10 @@
 
 #ifdef _NOTYET
 /*
- * NAME:        dtRelocate()
+ * NAME:	dtRelocate()
  *
- * FUNCTION:    relocate dtpage (internal or leaf) of directory;
- *              This function is mainly used by defragfs utility.
+ * FUNCTION:	relocate dtpage (internal or leaf) of directory;
+ *		This function is mainly used by defragfs utility.
  */
 int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
 	       s64 nxaddr)
@@ -2471,8 +2468,8 @@
 		   xlen);
 
 	/*
-	 *      1. get the internal parent dtpage covering
-	 *      router entry for the tartget page to be relocated;
+	 *	1. get the internal parent dtpage covering
+	 *	router entry for the tartget page to be relocated;
 	 */
 	rc = dtSearchNode(ip, lmxaddr, opxd, &btstack);
 	if (rc)
@@ -2483,7 +2480,7 @@
 	jfs_info("dtRelocate: parent router entry validated.");
 
 	/*
-	 *      2. relocate the target dtpage
+	 *	2. relocate the target dtpage
 	 */
 	/* read in the target page from src extent */
 	DT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc);
@@ -2581,9 +2578,7 @@
 
 	/* update the buffer extent descriptor of the dtpage */
 	xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize;
-#ifdef _STILL_TO_PORT
-	bmSetXD(mp, nxaddr, xsize);
-#endif /* _STILL_TO_PORT */
+
 	/* unpin the relocated page */
 	DT_PUTPAGE(mp);
 	jfs_info("dtRelocate: target dtpage relocated.");
@@ -2594,7 +2589,7 @@
 	 */
 
 	/*
-	 *      3. acquire maplock for the source extent to be freed;
+	 *	3. acquire maplock for the source extent to be freed;
 	 */
 	/* for dtpage relocation, write a LOG_NOREDOPAGE record
 	 * for the source dtpage (logredo() will init NoRedoPage
@@ -2609,7 +2604,7 @@
 	pxdlock->index = 1;
 
 	/*
-	 *      4. update the parent router entry for relocation;
+	 *	4. update the parent router entry for relocation;
 	 *
 	 * acquire tlck for the parent entry covering the target dtpage;
 	 * write LOG_REDOPAGE to apply after image only;
@@ -2637,7 +2632,7 @@
  * NAME:	dtSearchNode()
  *
  * FUNCTION:	Search for an dtpage containing a specified address
- *              This function is mainly used by defragfs utility.
+ *		This function is mainly used by defragfs utility.
  *
  * NOTE:	Search result on stack, the found page is pinned at exit.
  *		The result page must be an internal dtpage.
@@ -2660,7 +2655,7 @@
 	BT_CLR(btstack);	/* reset stack */
 
 	/*
-	 *      descend tree to the level with specified leftmost page
+	 *	descend tree to the level with specified leftmost page
 	 *
 	 *  by convention, root bn = 0.
 	 */
@@ -2699,7 +2694,7 @@
 	}
 
 	/*
-	 *      search each page at the current levevl
+	 *	search each page at the current levevl
 	 */
       loop:
 	stbl = DT_GETSTBL(p);
@@ -3044,9 +3039,9 @@
 	if (DO_INDEX(ip)) {
 		/*
 		 * persistent index is stored in directory entries.
-		 * Special cases:        0 = .
-		 *                       1 = ..
-		 *                      -1 = End of directory
+		 * Special cases:	 0 = .
+		 *			 1 = ..
+		 *			-1 = End of directory
 		 */
 		do_index = 1;
 
@@ -3128,10 +3123,10 @@
 		/*
 		 * Legacy filesystem - OS/2 & Linux JFS < 0.3.6
 		 *
-		 * pn = index = 0:      First entry "."
-		 * pn = 0; index = 1:   Second entry ".."
-		 * pn > 0:              Real entries, pn=1 -> leftmost page
-		 * pn = index = -1:     No more entries
+		 * pn = index = 0:	First entry "."
+		 * pn = 0; index = 1:	Second entry ".."
+		 * pn > 0:		Real entries, pn=1 -> leftmost page
+		 * pn = index = -1:	No more entries
 		 */
 		dtpos = filp->f_pos;
 		if (dtpos == 0) {
@@ -3351,7 +3346,7 @@
 	BT_CLR(btstack);	/* reset stack */
 
 	/*
-	 *      descend leftmost path of the tree
+	 *	descend leftmost path of the tree
 	 *
 	 * by convention, root bn = 0.
 	 */
@@ -4531,7 +4526,7 @@
 	struct ldtentry *entry;
 
 	/*
-	 *      search for the entry to modify:
+	 *	search for the entry to modify:
 	 *
 	 * dtSearch() returns (leaf page pinned, index at which to modify).
 	 */
diff --git a/fs/jfs/jfs_dtree.h b/fs/jfs/jfs_dtree.h
index af8513f..8561c6e 100644
--- a/fs/jfs/jfs_dtree.h
+++ b/fs/jfs/jfs_dtree.h
@@ -35,7 +35,7 @@
 
 
 /*
- *      entry segment/slot
+ *	entry segment/slot
  *
  * an entry consists of type dependent head/only segment/slot and
  * additional segments/slots linked vi next field;
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index a35bdca..7ae1e32 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -34,8 +34,8 @@
 #endif
 static s64 extRoundDown(s64 nb);
 
-#define DPD(a)          (printk("(a): %d\n",(a)))
-#define DPC(a)          (printk("(a): %c\n",(a)))
+#define DPD(a)		(printk("(a): %d\n",(a)))
+#define DPC(a)		(printk("(a): %c\n",(a)))
 #define DPL1(a)					\
 {						\
 	if ((a) >> 32)				\
@@ -51,19 +51,19 @@
 		printk("(a): %x\n",(a) << 32);	\
 }
 
-#define DPD1(a)         (printk("(a): %d  ",(a)))
-#define DPX(a)          (printk("(a): %08x\n",(a)))
-#define DPX1(a)         (printk("(a): %08x  ",(a)))
-#define DPS(a)          (printk("%s\n",(a)))
-#define DPE(a)          (printk("\nENTERING: %s\n",(a)))
-#define DPE1(a)          (printk("\nENTERING: %s",(a)))
-#define DPS1(a)         (printk("  %s  ",(a)))
+#define DPD1(a)		(printk("(a): %d  ",(a)))
+#define DPX(a)		(printk("(a): %08x\n",(a)))
+#define DPX1(a)		(printk("(a): %08x  ",(a)))
+#define DPS(a)		(printk("%s\n",(a)))
+#define DPE(a)		(printk("\nENTERING: %s\n",(a)))
+#define DPE1(a)		(printk("\nENTERING: %s",(a)))
+#define DPS1(a)		(printk("  %s  ",(a)))
 
 
 /*
  * NAME:	extAlloc()
  *
- * FUNCTION:    allocate an extent for a specified page range within a
+ * FUNCTION:	allocate an extent for a specified page range within a
  *		file.
  *
  * PARAMETERS:
@@ -78,9 +78,9 @@
  *		  should be marked as allocated but not recorded.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 int
 extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
@@ -192,9 +192,9 @@
 
 #ifdef _NOTYET
 /*
- * NAME:        extRealloc()
+ * NAME:	extRealloc()
  *
- * FUNCTION:    extend the allocation of a file extent containing a
+ * FUNCTION:	extend the allocation of a file extent containing a
  *		partial back last page.
  *
  * PARAMETERS:
@@ -207,9 +207,9 @@
  *		  should be marked as allocated but not recorded.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr)
 {
@@ -345,9 +345,9 @@
 
 
 /*
- * NAME:        extHint()
+ * NAME:	extHint()
  *
- * FUNCTION:    produce an extent allocation hint for a file offset.
+ * FUNCTION:	produce an extent allocation hint for a file offset.
  *
  * PARAMETERS:
  *	ip	- the inode of the file.
@@ -356,8 +356,8 @@
  *		  the hint.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
+ *	0	- success
+ *	-EIO	- i/o error.
  */
 int extHint(struct inode *ip, s64 offset, xad_t * xp)
 {
@@ -387,7 +387,7 @@
 	lxdl.nlxd = 1;
 	lxdl.lxd = &lxd;
 	LXDoffset(&lxd, prev)
-	    LXDlength(&lxd, nbperpage);
+	LXDlength(&lxd, nbperpage);
 
 	xadl.maxnxad = 1;
 	xadl.nxad = 0;
@@ -397,11 +397,11 @@
 	if ((rc = xtLookupList(ip, &lxdl, &xadl, 0)))
 		return (rc);
 
-	/* check if not extent exists for the previous page.
+	/* check if no extent exists for the previous page.
 	 * this is possible for sparse files.
 	 */
 	if (xadl.nxad == 0) {
-//              assert(ISSPARSE(ip));
+//		assert(ISSPARSE(ip));
 		return (0);
 	}
 
@@ -410,28 +410,28 @@
 	 */
 	xp->flag &= XAD_NOTRECORDED;
 
-        if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) {
+	if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) {
 		jfs_error(ip->i_sb, "extHint: corrupt xtree");
 		return -EIO;
-        }
+	}
 
 	return (0);
 }
 
 
 /*
- * NAME:        extRecord()
+ * NAME:	extRecord()
  *
- * FUNCTION:    change a page with a file from not recorded to recorded.
+ * FUNCTION:	change a page with a file from not recorded to recorded.
  *
  * PARAMETERS:
  *	ip	- inode of the file.
  *	cp	- cbuf of the file page.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 int extRecord(struct inode *ip, xad_t * xp)
 {
@@ -451,9 +451,9 @@
 
 #ifdef _NOTYET
 /*
- * NAME:        extFill()
+ * NAME:	extFill()
  *
- * FUNCTION:    allocate disk space for a file page that represents
+ * FUNCTION:	allocate disk space for a file page that represents
  *		a file hole.
  *
  * PARAMETERS:
@@ -461,16 +461,16 @@
  *	cp	- cbuf of the file page represent the hole.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 int extFill(struct inode *ip, xad_t * xp)
 {
 	int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage;
 	s64 blkno = offsetXAD(xp) >> ip->i_blkbits;
 
-//      assert(ISSPARSE(ip));
+//	assert(ISSPARSE(ip));
 
 	/* initialize the extent allocation hint */
 	XADaddress(xp, 0);
@@ -489,7 +489,7 @@
 /*
  * NAME:	extBalloc()
  *
- * FUNCTION:    allocate disk blocks to form an extent.
+ * FUNCTION:	allocate disk blocks to form an extent.
  *
  *		initially, we will try to allocate disk blocks for the
  *		requested size (nblocks).  if this fails (nblocks
@@ -513,9 +513,9 @@
  *		   allocated block range.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 static int
 extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
@@ -580,7 +580,7 @@
 /*
  * NAME:	extBrealloc()
  *
- * FUNCTION:    attempt to extend an extent's allocation.
+ * FUNCTION:	attempt to extend an extent's allocation.
  *
  *		Initially, we will try to extend the extent's allocation
  *		in place.  If this fails, we'll try to move the extent
@@ -597,8 +597,8 @@
  *
  * PARAMETERS:
  *	ip	 - the inode of the file.
- *	blkno    - starting block number of the extents current allocation.
- *	nblks    - number of blocks within the extents current allocation.
+ *	blkno	 - starting block number of the extents current allocation.
+ *	nblks	 - number of blocks within the extents current allocation.
  *	newnblks - pointer to a s64 value.  on entry, this value is the
  *		   the new desired extent size (number of blocks).  on
  *		   successful exit, this value is set to the extent's actual
@@ -606,9 +606,9 @@
  *	newblkno - the starting block number of the extents new allocation.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOSPC	- insufficient disk resources.
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOSPC	- insufficient disk resources.
  */
 static int
 extBrealloc(struct inode *ip,
@@ -634,16 +634,16 @@
 
 
 /*
- * NAME:        extRoundDown()
+ * NAME:	extRoundDown()
  *
- * FUNCTION:    round down a specified number of blocks to the next
+ * FUNCTION:	round down a specified number of blocks to the next
  *		smallest power of 2 number.
  *
  * PARAMETERS:
  *	nb	- the inode of the file.
  *
  * RETURN VALUES:
- *      next smallest power of 2 number.
+ *	next smallest power of 2 number.
  */
 static s64 extRoundDown(s64 nb)
 {
diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h
index 38f70ac..b3f5463 100644
--- a/fs/jfs/jfs_filsys.h
+++ b/fs/jfs/jfs_filsys.h
@@ -34,9 +34,9 @@
 #define JFS_UNICODE	0x00000001	/* unicode name */
 
 /* mount time flags for error handling */
-#define JFS_ERR_REMOUNT_RO 0x00000002   /* remount read-only */
-#define JFS_ERR_CONTINUE   0x00000004   /* continue */
-#define JFS_ERR_PANIC      0x00000008   /* panic */
+#define JFS_ERR_REMOUNT_RO 0x00000002	/* remount read-only */
+#define JFS_ERR_CONTINUE   0x00000004	/* continue */
+#define JFS_ERR_PANIC      0x00000008	/* panic */
 
 /* Quota support */
 #define	JFS_USRQUOTA	0x00000010
@@ -83,7 +83,6 @@
 /*	case-insensitive name/directory support */
 
 #define JFS_AIX		0x80000000	/* AIX support */
-/*	POSIX name/directory  support - Never implemented*/
 
 /*
  *	buffer cache configuration
@@ -113,10 +112,10 @@
 #define IDATASIZE	256	/* inode inline data size */
 #define	IXATTRSIZE	128	/* inode inline extended attribute size */
 
-#define XTPAGE_SIZE     4096
-#define log2_PAGESIZE     12
+#define XTPAGE_SIZE	4096
+#define log2_PAGESIZE	12
 
-#define IAG_SIZE        4096
+#define IAG_SIZE	4096
 #define IAG_EXTENT_SIZE 4096
 #define	INOSPERIAG	4096	/* number of disk inodes per iag */
 #define	L2INOSPERIAG	12	/* l2 number of disk inodes per iag */
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index c653022..3870ba8 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -93,21 +93,21 @@
 static void copy_to_dinode(struct dinode *, struct inode *);
 
 /*
- * NAME:        diMount()
+ * NAME:	diMount()
  *
- * FUNCTION:    initialize the incore inode map control structures for
+ * FUNCTION:	initialize the incore inode map control structures for
  *		a fileset or aggregate init time.
  *
- *              the inode map's control structure (dinomap) is
- *              brought in from disk and placed in virtual memory.
+ *		the inode map's control structure (dinomap) is
+ *		brought in from disk and placed in virtual memory.
  *
  * PARAMETERS:
- *      ipimap  - pointer to inode map inode for the aggregate or fileset.
+ *	ipimap	- pointer to inode map inode for the aggregate or fileset.
  *
  * RETURN VALUES:
- *      0       - success
- *      -ENOMEM  - insufficient free virtual memory.
- *      -EIO	- i/o error.
+ *	0	- success
+ *	-ENOMEM	- insufficient free virtual memory.
+ *	-EIO	- i/o error.
  */
 int diMount(struct inode *ipimap)
 {
@@ -180,18 +180,18 @@
 
 
 /*
- * NAME:        diUnmount()
+ * NAME:	diUnmount()
  *
- * FUNCTION:    write to disk the incore inode map control structures for
+ * FUNCTION:	write to disk the incore inode map control structures for
  *		a fileset or aggregate at unmount time.
  *
  * PARAMETERS:
- *      ipimap  - pointer to inode map inode for the aggregate or fileset.
+ *	ipimap	- pointer to inode map inode for the aggregate or fileset.
  *
  * RETURN VALUES:
- *      0       - success
- *      -ENOMEM  - insufficient free virtual memory.
- *      -EIO	- i/o error.
+ *	0	- success
+ *	-ENOMEM	- insufficient free virtual memory.
+ *	-EIO	- i/o error.
  */
 int diUnmount(struct inode *ipimap, int mounterror)
 {
@@ -274,9 +274,9 @@
 
 
 /*
- * NAME:        diRead()
+ * NAME:	diRead()
  *
- * FUNCTION:    initialize an incore inode from disk.
+ * FUNCTION:	initialize an incore inode from disk.
  *
  *		on entry, the specifed incore inode should itself
  *		specify the disk inode number corresponding to the
@@ -285,7 +285,7 @@
  *		this routine handles incore inode initialization for
  *		both "special" and "regular" inodes.  special inodes
  *		are those required early in the mount process and
- *	        require special handling since much of the file system
+ *		require special handling since much of the file system
  *		is not yet initialized.  these "special" inodes are
  *		identified by a NULL inode map inode pointer and are
  *		actually initialized by a call to diReadSpecial().
@@ -298,12 +298,12 @@
  *		incore inode.
  *
  * PARAMETERS:
- *      ip  -  pointer to incore inode to be initialized from disk.
+ *	ip	-  pointer to incore inode to be initialized from disk.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
- *      -ENOMEM	- insufficient memory
+ *	0	- success
+ *	-EIO	- i/o error.
+ *	-ENOMEM	- insufficient memory
  *
  */
 int diRead(struct inode *ip)
@@ -410,26 +410,26 @@
 
 
 /*
- * NAME:        diReadSpecial()
+ * NAME:	diReadSpecial()
  *
- * FUNCTION:    initialize a 'special' inode from disk.
+ * FUNCTION:	initialize a 'special' inode from disk.
  *
  *		this routines handles aggregate level inodes.  The
  *		inode cache cannot differentiate between the
  *		aggregate inodes and the filesystem inodes, so we
  *		handle these here.  We don't actually use the aggregate
- *	        inode map, since these inodes are at a fixed location
+ *		inode map, since these inodes are at a fixed location
  *		and in some cases the aggregate inode map isn't initialized
  *		yet.
  *
  * PARAMETERS:
- *      sb - filesystem superblock
+ *	sb - filesystem superblock
  *	inum - aggregate inode number
  *	secondary - 1 if secondary aggregate inode table
  *
  * RETURN VALUES:
- *      new inode	- success
- *      NULL		- i/o error.
+ *	new inode	- success
+ *	NULL		- i/o error.
  */
 struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
 {
@@ -502,12 +502,12 @@
 }
 
 /*
- * NAME:        diWriteSpecial()
+ * NAME:	diWriteSpecial()
  *
- * FUNCTION:    Write the special inode to disk
+ * FUNCTION:	Write the special inode to disk
  *
  * PARAMETERS:
- *      ip - special inode
+ *	ip - special inode
  *	secondary - 1 if secondary aggregate inode table
  *
  * RETURN VALUES: none
@@ -554,9 +554,9 @@
 }
 
 /*
- * NAME:        diFreeSpecial()
+ * NAME:	diFreeSpecial()
  *
- * FUNCTION:    Free allocated space for special inode
+ * FUNCTION:	Free allocated space for special inode
  */
 void diFreeSpecial(struct inode *ip)
 {
@@ -572,9 +572,9 @@
 
 
 /*
- * NAME:        diWrite()
+ * NAME:	diWrite()
  *
- * FUNCTION:    write the on-disk inode portion of the in-memory inode
+ * FUNCTION:	write the on-disk inode portion of the in-memory inode
  *		to its corresponding on-disk inode.
  *
  *		on entry, the specifed incore inode should itself
@@ -589,11 +589,11 @@
  *
  * PARAMETERS:
  *	tid -  transacation id
- *      ip  -  pointer to incore inode to be written to the inode extent.
+ *	ip  -  pointer to incore inode to be written to the inode extent.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
+ *	0	- success
+ *	-EIO	- i/o error.
  */
 int diWrite(tid_t tid, struct inode *ip)
 {
@@ -730,7 +730,7 @@
 	ilinelock = (struct linelock *) & tlck->lock;
 
 	/*
-	 *      regular file: 16 byte (XAD slot) granularity
+	 *	regular file: 16 byte (XAD slot) granularity
 	 */
 	if (type & tlckXTREE) {
 		xtpage_t *p, *xp;
@@ -755,7 +755,7 @@
 				xad->flag &= ~(XAD_NEW | XAD_EXTENDED);
 	}
 	/*
-	 *      directory: 32 byte (directory entry slot) granularity
+	 *	directory: 32 byte (directory entry slot) granularity
 	 */
 	else if (type & tlckDTREE) {
 		dtpage_t *p, *xp;
@@ -800,9 +800,8 @@
 	}
 
 	/*
-	 *      lock/copy inode base: 128 byte slot granularity
+	 *	lock/copy inode base: 128 byte slot granularity
 	 */
-// baseDinode:
 	lv = & dilinelock->lv[dilinelock->index];
 	lv->offset = dioffset >> L2INODESLOTSIZE;
 	copy_to_dinode(dp, ip);
@@ -813,17 +812,6 @@
 		lv->length = 1;
 	dilinelock->index++;
 
-#ifdef _JFS_FASTDASD
-	/*
-	 * We aren't logging changes to the DASD used in directory inodes,
-	 * but we need to write them to disk.  If we don't unmount cleanly,
-	 * mount will recalculate the DASD used.
-	 */
-	if (S_ISDIR(ip->i_mode)
-	    && (ip->i_ipmnt->i_mntflag & JFS_DASD_ENABLED))
-		memcpy(&dp->di_DASD, &ip->i_DASD, sizeof(struct dasd));
-#endif				/*  _JFS_FASTDASD */
-
 	/* release the buffer holding the updated on-disk inode.
 	 * the buffer will be later written by commit processing.
 	 */
@@ -834,9 +822,9 @@
 
 
 /*
- * NAME:        diFree(ip)
+ * NAME:	diFree(ip)
  *
- * FUNCTION:    free a specified inode from the inode working map
+ * FUNCTION:	free a specified inode from the inode working map
  *		for a fileset or aggregate.
  *
  *		if the inode to be freed represents the first (only)
@@ -865,11 +853,11 @@
  *		any updates and are held until all updates are complete.
  *
  * PARAMETERS:
- *      ip	- inode to be freed.
+ *	ip	- inode to be freed.
  *
  * RETURN VALUES:
- *      0       - success
- *      -EIO	- i/o error.
+ *	0	- success
+ *	-EIO	- i/o error.
  */
 int diFree(struct inode *ip)
 {
@@ -902,7 +890,8 @@
 	 * the map.
 	 */
 	if (iagno >= imap->im_nextiag) {
-		dump_mem("imap", imap, 32);
+		print_hex_dump(KERN_ERR, "imap: ", DUMP_PREFIX_ADDRESS, 16, 4,
+			       imap, 32, 0);
 		jfs_error(ip->i_sb,
 			  "diFree: inum = %d, iagno = %d, nextiag = %d",
 			  (uint) inum, iagno, imap->im_nextiag);
@@ -964,8 +953,8 @@
 		return -EIO;
 	}
 	/*
-	 *      inode extent still has some inodes or below low water mark:
-	 *      keep the inode extent;
+	 *	inode extent still has some inodes or below low water mark:
+	 *	keep the inode extent;
 	 */
 	if (bitmap ||
 	    imap->im_agctl[agno].numfree < 96 ||
@@ -1047,12 +1036,12 @@
 
 
 	/*
-	 *      inode extent has become free and above low water mark:
-	 *      free the inode extent;
+	 *	inode extent has become free and above low water mark:
+	 *	free the inode extent;
 	 */
 
 	/*
-	 *      prepare to update iag list(s) (careful update step 1)
+	 *	prepare to update iag list(s) (careful update step 1)
 	 */
 	amp = bmp = cmp = dmp = NULL;
 	fwd = back = -1;
@@ -1152,7 +1141,7 @@
 	invalidate_pxd_metapages(ip, freepxd);
 
 	/*
-	 *      update iag list(s) (careful update step 2)
+	 *	update iag list(s) (careful update step 2)
 	 */
 	/* add the iag to the ag extent free list if this is the
 	 * first free extent for the iag.
@@ -1338,20 +1327,20 @@
 
 
 /*
- * NAME:        diAlloc(pip,dir,ip)
+ * NAME:	diAlloc(pip,dir,ip)
  *
- * FUNCTION:    allocate a disk inode from the inode working map
+ * FUNCTION:	allocate a disk inode from the inode working map
  *		for a fileset or aggregate.
  *
  * PARAMETERS:
- *      pip	- pointer to incore inode for the parent inode.
- *      dir	- 'true' if the new disk inode is for a directory.
- *      ip	- pointer to a new inode
+ *	pip	- pointer to incore inode for the parent inode.
+ *	dir	- 'true' if the new disk inode is for a directory.
+ *	ip	- pointer to a new inode
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 int diAlloc(struct inode *pip, bool dir, struct inode *ip)
 {
@@ -1433,7 +1422,7 @@
 	addext = (imap->im_agctl[agno].numfree < 32 && iagp->nfreeexts);
 
 	/*
-	 *      try to allocate from the IAG
+	 *	try to allocate from the IAG
 	 */
 	/* check if the inode may be allocated from the iag
 	 * (i.e. the inode has free inodes or new extent can be added).
@@ -1633,9 +1622,9 @@
 
 
 /*
- * NAME:        diAllocAG(imap,agno,dir,ip)
+ * NAME:	diAllocAG(imap,agno,dir,ip)
  *
- * FUNCTION:    allocate a disk inode from the allocation group.
+ * FUNCTION:	allocate a disk inode from the allocation group.
  *
  *		this routine first determines if a new extent of free
  *		inodes should be added for the allocation group, with
@@ -1649,17 +1638,17 @@
  * PRE CONDITION: Already have the AG lock for this AG.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      agno	- allocation group to allocate from.
- *      dir	- 'true' if the new disk inode is for a directory.
- *      ip	- pointer to the new inode to be filled in on successful return
+ *	imap	- pointer to inode map control structure.
+ *	agno	- allocation group to allocate from.
+ *	dir	- 'true' if the new disk inode is for a directory.
+ *	ip	- pointer to the new inode to be filled in on successful return
  *		  with the disk inode number allocated, its extent address
  *		  and the start of the ag.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int
 diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
@@ -1709,9 +1698,9 @@
 
 
 /*
- * NAME:        diAllocAny(imap,agno,dir,iap)
+ * NAME:	diAllocAny(imap,agno,dir,iap)
  *
- * FUNCTION:    allocate a disk inode from any other allocation group.
+ * FUNCTION:	allocate a disk inode from any other allocation group.
  *
  *		this routine is called when an allocation attempt within
  *		the primary allocation group has failed. if attempts to
@@ -1719,17 +1708,17 @@
  *		specified primary group.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      agno	- primary allocation group (to avoid).
- *      dir	- 'true' if the new disk inode is for a directory.
- *      ip	- pointer to a new inode to be filled in on successful return
+ *	imap	- pointer to inode map control structure.
+ *	agno	- primary allocation group (to avoid).
+ *	dir	- 'true' if the new disk inode is for a directory.
+ *	ip	- pointer to a new inode to be filled in on successful return
  *		  with the disk inode number allocated, its extent address
  *		  and the start of the ag.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int
 diAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
@@ -1772,9 +1761,9 @@
 
 
 /*
- * NAME:        diAllocIno(imap,agno,ip)
+ * NAME:	diAllocIno(imap,agno,ip)
  *
- * FUNCTION:    allocate a disk inode from the allocation group's free
+ * FUNCTION:	allocate a disk inode from the allocation group's free
  *		inode list, returning an error if this free list is
  *		empty (i.e. no iags on the list).
  *
@@ -1785,16 +1774,16 @@
  * PRE CONDITION: Already have AG lock for this AG.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      agno	- allocation group.
- *      ip	- pointer to new inode to be filled in on successful return
+ *	imap	- pointer to inode map control structure.
+ *	agno	- allocation group.
+ *	ip	- pointer to new inode to be filled in on successful return
  *		  with the disk inode number allocated, its extent address
  *		  and the start of the ag.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
 {
@@ -1890,7 +1879,7 @@
 
 
 /*
- * NAME:        diAllocExt(imap,agno,ip)
+ * NAME:	diAllocExt(imap,agno,ip)
  *
  * FUNCTION:	add a new extent of free inodes to an iag, allocating
  *		an inode from this extent to satisfy the current allocation
@@ -1910,16 +1899,16 @@
  *		for the purpose of satisfying this request.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      agno	- allocation group number.
- *      ip	- pointer to new inode to be filled in on successful return
+ *	imap	- pointer to inode map control structure.
+ *	agno	- allocation group number.
+ *	ip	- pointer to new inode to be filled in on successful return
  *		  with the disk inode number allocated, its extent address
  *		  and the start of the ag.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
 {
@@ -2010,7 +1999,7 @@
 
 
 /*
- * NAME:        diAllocBit(imap,iagp,ino)
+ * NAME:	diAllocBit(imap,iagp,ino)
  *
  * FUNCTION:	allocate a backed inode from an iag.
  *
@@ -2030,14 +2019,14 @@
  *	this AG.  Must have read lock on imap inode.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      iagp	- pointer to iag.
- *      ino	- inode number to be allocated within the iag.
+ *	imap	- pointer to inode map control structure.
+ *	iagp	- pointer to iag.
+ *	ino	- inode number to be allocated within the iag.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
 {
@@ -2144,11 +2133,11 @@
 
 
 /*
- * NAME:        diNewExt(imap,iagp,extno)
+ * NAME:	diNewExt(imap,iagp,extno)
  *
- * FUNCTION:    initialize a new extent of inodes for an iag, allocating
- *	        the first inode of the extent for use for the current
- *	        allocation request.
+ * FUNCTION:	initialize a new extent of inodes for an iag, allocating
+ *		the first inode of the extent for use for the current
+ *		allocation request.
  *
  *		disk resources are allocated for the new extent of inodes
  *		and the inodes themselves are initialized to reflect their
@@ -2177,14 +2166,14 @@
  *	this AG.  Must have read lock on imap inode.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      iagp	- pointer to iag.
- *      extno	- extent number.
+ *	imap	- pointer to inode map control structure.
+ *	iagp	- pointer to iag.
+ *	extno	- extent number.
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  */
 static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
 {
@@ -2430,7 +2419,7 @@
 
 
 /*
- * NAME:        diNewIAG(imap,iagnop,agno)
+ * NAME:	diNewIAG(imap,iagnop,agno)
  *
  * FUNCTION:	allocate a new iag for an allocation group.
  *
@@ -2443,16 +2432,16 @@
  *		and returned to satisfy the request.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      iagnop	- pointer to an iag number set with the number of the
+ *	imap	- pointer to inode map control structure.
+ *	iagnop	- pointer to an iag number set with the number of the
  *		  newly allocated iag upon successful return.
- *      agno	- allocation group number.
+ *	agno	- allocation group number.
  *	bpp	- Buffer pointer to be filled in with new IAG's buffer
  *
  * RETURN VALUES:
- *      0       - success.
- *      -ENOSPC	- insufficient disk resources.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-ENOSPC	- insufficient disk resources.
+ *	-EIO	- i/o error.
  *
  * serialization:
  *	AG lock held on entry/exit;
@@ -2461,7 +2450,7 @@
  *
  * note: new iag transaction:
  * . synchronously write iag;
- * . write log of xtree and inode  of imap;
+ * . write log of xtree and inode of imap;
  * . commit;
  * . synchronous write of xtree (right to left, bottom to top);
  * . at start of logredo(): init in-memory imap with one additional iag page;
@@ -2481,9 +2470,6 @@
 	s64 xaddr = 0;
 	s64 blkno;
 	tid_t tid;
-#ifdef _STILL_TO_PORT
-	xad_t xad;
-#endif				/*  _STILL_TO_PORT */
 	struct inode *iplist[1];
 
 	/* pick up pointers to the inode map and mount inodes */
@@ -2674,15 +2660,15 @@
 }
 
 /*
- * NAME:        diIAGRead()
+ * NAME:	diIAGRead()
  *
- * FUNCTION:    get the buffer for the specified iag within a fileset
+ * FUNCTION:	get the buffer for the specified iag within a fileset
  *		or aggregate inode map.
  *
  * PARAMETERS:
- *      imap	- pointer to inode map control structure.
- *      iagno	- iag number.
- *      bpp	- point to buffer pointer to be filled in on successful
+ *	imap	- pointer to inode map control structure.
+ *	iagno	- iag number.
+ *	bpp	- point to buffer pointer to be filled in on successful
  *		  exit.
  *
  * SERIALIZATION:
@@ -2691,8 +2677,8 @@
  *	 the read lock is unnecessary.)
  *
  * RETURN VALUES:
- *      0       - success.
- *      -EIO	- i/o error.
+ *	0	- success.
+ *	-EIO	- i/o error.
  */
 static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
 {
@@ -2712,17 +2698,17 @@
 }
 
 /*
- * NAME:        diFindFree()
+ * NAME:	diFindFree()
  *
- * FUNCTION:    find the first free bit in a word starting at
+ * FUNCTION:	find the first free bit in a word starting at
  *		the specified bit position.
  *
  * PARAMETERS:
- *      word	- word to be examined.
- *      start	- starting bit position.
+ *	word	- word to be examined.
+ *	start	- starting bit position.
  *
  * RETURN VALUES:
- *      bit position of first free bit in the word or 32 if
+ *	bit position of first free bit in the word or 32 if
  *	no free bits were found.
  */
 static int diFindFree(u32 word, int start)
@@ -2897,7 +2883,7 @@
 		   atomic_read(&imap->im_numfree));
 
 	/*
-	 *      reconstruct imap
+	 *	reconstruct imap
 	 *
 	 * coalesce contiguous k (newAGSize/oldAGSize) AGs;
 	 * i.e., (AGi, ..., AGj) where i = k*n and j = k*(n+1) - 1 to AGn;
@@ -2913,7 +2899,7 @@
 	}
 
 	/*
-	 *      process each iag page of the map.
+	 *	process each iag page of the map.
 	 *
 	 * rebuild AG Free Inode List, AG Free Inode Extent List;
 	 */
@@ -2932,7 +2918,7 @@
 
 		/* leave free iag in the free iag list */
 		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {
-		        release_metapage(bp);
+			release_metapage(bp);
 			continue;
 		}
 
@@ -3063,13 +3049,13 @@
 }
 
 /*
- * NAME:        copy_from_dinode()
+ * NAME:	copy_from_dinode()
  *
- * FUNCTION:    Copies inode info from disk inode to in-memory inode
+ * FUNCTION:	Copies inode info from disk inode to in-memory inode
  *
  * RETURN VALUES:
- *      0       - success
- *      -ENOMEM	- insufficient memory
+ *	0	- success
+ *	-ENOMEM	- insufficient memory
  */
 static int copy_from_dinode(struct dinode * dip, struct inode *ip)
 {
@@ -3151,9 +3137,9 @@
 }
 
 /*
- * NAME:        copy_to_dinode()
+ * NAME:	copy_to_dinode()
  *
- * FUNCTION:    Copies inode info from in-memory inode to disk inode
+ * FUNCTION:	Copies inode info from in-memory inode to disk inode
  */
 static void copy_to_dinode(struct dinode * dip, struct inode *ip)
 {
diff --git a/fs/jfs/jfs_imap.h b/fs/jfs/jfs_imap.h
index 4f9c346..610a0e9 100644
--- a/fs/jfs/jfs_imap.h
+++ b/fs/jfs/jfs_imap.h
@@ -24,17 +24,17 @@
  *	jfs_imap.h: disk inode manager
  */
 
-#define	EXTSPERIAG	128	/* number of disk inode extent per iag  */
-#define IMAPBLKNO	0	/* lblkno of dinomap within inode map   */
-#define SMAPSZ		4	/* number of words per summary map      */
+#define	EXTSPERIAG	128	/* number of disk inode extent per iag	*/
+#define IMAPBLKNO	0	/* lblkno of dinomap within inode map	*/
+#define SMAPSZ		4	/* number of words per summary map	*/
 #define	EXTSPERSUM	32	/* number of extents per summary map entry */
 #define	L2EXTSPERSUM	5	/* l2 number of extents per summary map */
 #define	PGSPERIEXT	4	/* number of 4K pages per dinode extent */
-#define	MAXIAGS		((1<<20)-1)	/* maximum number of iags       */
-#define	MAXAG		128	/* maximum number of allocation groups  */
+#define	MAXIAGS		((1<<20)-1)	/* maximum number of iags	*/
+#define	MAXAG		128	/* maximum number of allocation groups	*/
 
-#define AMAPSIZE      512	/* bytes in the IAG allocation maps */
-#define SMAPSIZE      16	/* bytes in the IAG summary maps */
+#define AMAPSIZE	512	/* bytes in the IAG allocation maps */
+#define SMAPSIZE	16	/* bytes in the IAG summary maps */
 
 /* convert inode number to iag number */
 #define	INOTOIAG(ino)	((ino) >> L2INOSPERIAG)
@@ -60,31 +60,31 @@
  *	inode allocation group page (per 4096 inodes of an AG)
  */
 struct iag {
-	__le64 agstart;		/* 8: starting block of ag              */
-	__le32 iagnum;		/* 4: inode allocation group number     */
-	__le32 inofreefwd;	/* 4: ag inode free list forward        */
-	__le32 inofreeback;	/* 4: ag inode free list back           */
-	__le32 extfreefwd;	/* 4: ag inode extent free list forward */
-	__le32 extfreeback;	/* 4: ag inode extent free list back    */
-	__le32 iagfree;		/* 4: iag free list                     */
+	__le64 agstart;		/* 8: starting block of ag		*/
+	__le32 iagnum;		/* 4: inode allocation group number	*/
+	__le32 inofreefwd;	/* 4: ag inode free list forward	*/
+	__le32 inofreeback;	/* 4: ag inode free list back		*/
+	__le32 extfreefwd;	/* 4: ag inode extent free list forward	*/
+	__le32 extfreeback;	/* 4: ag inode extent free list back	*/
+	__le32 iagfree;		/* 4: iag free list			*/
 
 	/* summary map: 1 bit per inode extent */
 	__le32 inosmap[SMAPSZ];	/* 16: sum map of mapwords w/ free inodes;
-				 *      note: this indicates free and backed
-				 *      inodes, if the extent is not backed the
-				 *      value will be 1.  if the extent is
-				 *      backed but all inodes are being used the
-				 *      value will be 1.  if the extent is
-				 *      backed but at least one of the inodes is
-				 *      free the value will be 0.
+				 *	note: this indicates free and backed
+				 *	inodes, if the extent is not backed the
+				 *	value will be 1.  if the extent is
+				 *	backed but all inodes are being used the
+				 *	value will be 1.  if the extent is
+				 *	backed but at least one of the inodes is
+				 *	free the value will be 0.
 				 */
 	__le32 extsmap[SMAPSZ];	/* 16: sum map of mapwords w/ free extents */
-	__le32 nfreeinos;		/* 4: number of free inodes             */
-	__le32 nfreeexts;		/* 4: number of free extents            */
+	__le32 nfreeinos;	/* 4: number of free inodes		*/
+	__le32 nfreeexts;	/* 4: number of free extents		*/
 	/* (72) */
 	u8 pad[1976];		/* 1976: pad to 2048 bytes */
 	/* allocation bit map: 1 bit per inode (0 - free, 1 - allocated) */
-	__le32 wmap[EXTSPERIAG];	/* 512: working allocation map  */
+	__le32 wmap[EXTSPERIAG];	/* 512: working allocation map */
 	__le32 pmap[EXTSPERIAG];	/* 512: persistent allocation map */
 	pxd_t inoext[EXTSPERIAG];	/* 1024: inode extent addresses */
 };				/* (4096) */
@@ -93,44 +93,44 @@
  *	per AG control information (in inode map control page)
  */
 struct iagctl_disk {
-	__le32 inofree;		/* 4: free inode list anchor            */
-	__le32 extfree;		/* 4: free extent list anchor           */
-	__le32 numinos;		/* 4: number of backed inodes           */
-	__le32 numfree;		/* 4: number of free inodes             */
+	__le32 inofree;		/* 4: free inode list anchor		*/
+	__le32 extfree;		/* 4: free extent list anchor		*/
+	__le32 numinos;		/* 4: number of backed inodes		*/
+	__le32 numfree;		/* 4: number of free inodes		*/
 };				/* (16) */
 
 struct iagctl {
-	int inofree;		/* free inode list anchor            */
-	int extfree;		/* free extent list anchor           */
-	int numinos;		/* number of backed inodes           */
-	int numfree;		/* number of free inodes             */
+	int inofree;		/* free inode list anchor		*/
+	int extfree;		/* free extent list anchor		*/
+	int numinos;		/* number of backed inodes		*/
+	int numfree;		/* number of free inodes		*/
 };
 
 /*
  *	per fileset/aggregate inode map control page
  */
 struct dinomap_disk {
-	__le32 in_freeiag;	/* 4: free iag list anchor     */
-	__le32 in_nextiag;	/* 4: next free iag number     */
-	__le32 in_numinos;	/* 4: num of backed inodes */
+	__le32 in_freeiag;	/* 4: free iag list anchor	*/
+	__le32 in_nextiag;	/* 4: next free iag number	*/
+	__le32 in_numinos;	/* 4: num of backed inodes	*/
 	__le32 in_numfree;	/* 4: num of free backed inodes */
 	__le32 in_nbperiext;	/* 4: num of blocks per inode extent */
-	__le32 in_l2nbperiext;	/* 4: l2 of in_nbperiext */
-	__le32 in_diskblock;	/* 4: for standalone test driver  */
-	__le32 in_maxag;	/* 4: for standalone test driver  */
-	u8 pad[2016];		/* 2016: pad to 2048 */
+	__le32 in_l2nbperiext;	/* 4: l2 of in_nbperiext	*/
+	__le32 in_diskblock;	/* 4: for standalone test driver */
+	__le32 in_maxag;	/* 4: for standalone test driver */
+	u8 pad[2016];		/* 2016: pad to 2048		*/
 	struct iagctl_disk in_agctl[MAXAG]; /* 2048: AG control information */
 };				/* (4096) */
 
 struct dinomap {
-	int in_freeiag;		/* free iag list anchor     */
-	int in_nextiag;		/* next free iag number     */
-	int in_numinos;		/* num of backed inodes */
-	int in_numfree;		/* num of free backed inodes */
+	int in_freeiag;		/* free iag list anchor		*/
+	int in_nextiag;		/* next free iag number		*/
+	int in_numinos;		/* num of backed inodes		*/
+	int in_numfree;		/* num of free backed inodes	*/
 	int in_nbperiext;	/* num of blocks per inode extent */
-	int in_l2nbperiext;	/* l2 of in_nbperiext */
-	int in_diskblock;	/* for standalone test driver  */
-	int in_maxag;		/* for standalone test driver  */
+	int in_l2nbperiext;	/* l2 of in_nbperiext		*/
+	int in_diskblock;	/* for standalone test driver	*/
+	int in_maxag;		/* for standalone test driver	*/
 	struct iagctl in_agctl[MAXAG];	/* AG control information */
 };
 
@@ -139,9 +139,9 @@
  */
 struct inomap {
 	struct dinomap im_imap;		/* 4096: inode allocation control */
-	struct inode *im_ipimap;	/* 4: ptr to inode for imap   */
-	struct mutex im_freelock;	/* 4: iag free list lock      */
-	struct mutex im_aglock[MAXAG];	/* 512: per AG locks          */
+	struct inode *im_ipimap;	/* 4: ptr to inode for imap	*/
+	struct mutex im_freelock;	/* 4: iag free list lock	*/
+	struct mutex im_aglock[MAXAG];	/* 512: per AG locks		*/
 	u32 *im_DBGdimap;
 	atomic_t im_numinos;	/* num of backed inodes */
 	atomic_t im_numfree;	/* num of free backed inodes */
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index 8f453ef..cb8f309 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -40,7 +40,7 @@
 	uint	mode2;		/* jfs-specific mode		*/
 	uint	saved_uid;	/* saved for uid mount option */
 	uint	saved_gid;	/* saved for gid mount option */
-	pxd_t   ixpxd;		/* inode extent descriptor	*/
+	pxd_t	ixpxd;		/* inode extent descriptor	*/
 	dxd_t	acl;		/* dxd describing acl	*/
 	dxd_t	ea;		/* dxd describing ea	*/
 	time_t	otime;		/* time created	*/
@@ -190,7 +190,7 @@
 	uint		gengen;		/* inode generation generator*/
 	uint		inostamp;	/* shows inode belongs to fileset*/
 
-        /* Formerly in ipbmap */
+	/* Formerly in ipbmap */
 	struct bmap	*bmap;		/* incore bmap descriptor	*/
 	struct nls_table *nls_tab;	/* current codepage		*/
 	struct inode *direct_inode;	/* metadata inode */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 44a2f33..de3e4a5 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -244,7 +244,7 @@
 		goto writeRecord;
 
 	/*
-	 *      initialize/update page/transaction recovery lsn
+	 *	initialize/update page/transaction recovery lsn
 	 */
 	lsn = log->lsn;
 
@@ -263,7 +263,7 @@
 	}
 
 	/*
-	 *      initialize/update lsn of tblock of the page
+	 *	initialize/update lsn of tblock of the page
 	 *
 	 * transaction inherits oldest lsn of pages associated
 	 * with allocation/deallocation of resources (their
@@ -307,7 +307,7 @@
 	LOGSYNC_UNLOCK(log, flags);
 
 	/*
-	 *      write the log record
+	 *	write the log record
 	 */
       writeRecord:
 	lsn = lmWriteRecord(log, tblk, lrd, tlck);
@@ -372,7 +372,7 @@
 		goto moveLrd;
 
 	/*
-	 *      move log record data
+	 *	move log record data
 	 */
 	/* retrieve source meta-data page to log */
 	if (tlck->flag & tlckPAGELOCK) {
@@ -465,7 +465,7 @@
 	}
 
 	/*
-	 *      move log record descriptor
+	 *	move log record descriptor
 	 */
       moveLrd:
 	lrd->length = cpu_to_le16(len);
@@ -574,7 +574,7 @@
 	LOGGC_LOCK(log);
 
 	/*
-	 *      write or queue the full page at the tail of write queue
+	 *	write or queue the full page at the tail of write queue
 	 */
 	/* get the tail tblk on commit queue */
 	if (list_empty(&log->cqueue))
@@ -625,7 +625,7 @@
 	LOGGC_UNLOCK(log);
 
 	/*
-	 *      allocate/initialize next page
+	 *	allocate/initialize next page
 	 */
 	/* if log wraps, the first data page of log is 2
 	 * (0 never used, 1 is superblock).
@@ -953,7 +953,7 @@
 		}
 
 	/*
-	 *      forward syncpt
+	 *	forward syncpt
 	 */
 	/* if last sync is same as last syncpt,
 	 * invoke sync point forward processing to update sync.
@@ -989,7 +989,7 @@
 		lsn = log->lsn;
 
 	/*
-	 *      setup next syncpt trigger (SWAG)
+	 *	setup next syncpt trigger (SWAG)
 	 */
 	logsize = log->logsize;
 
@@ -1000,11 +1000,11 @@
 	if (more < 2 * LOGPSIZE) {
 		jfs_warn("\n ... Log Wrap ... Log Wrap ... Log Wrap ...\n");
 		/*
-		 *      log wrapping
+		 *	log wrapping
 		 *
 		 * option 1 - panic ? No.!
 		 * option 2 - shutdown file systems
-		 *            associated with log ?
+		 *	      associated with log ?
 		 * option 3 - extend log ?
 		 */
 		/*
@@ -1062,7 +1062,7 @@
 /*
  * NAME:	lmLogOpen()
  *
- * FUNCTION:    open the log on first open;
+ * FUNCTION:	open the log on first open;
  *	insert filesystem in the active list of the log.
  *
  * PARAMETER:	ipmnt	- file system mount inode
@@ -1113,7 +1113,7 @@
 	init_waitqueue_head(&log->syncwait);
 
 	/*
-	 *      external log as separate logical volume
+	 *	external log as separate logical volume
 	 *
 	 * file systems to log may have n-to-1 relationship;
 	 */
@@ -1155,7 +1155,7 @@
 	return 0;
 
 	/*
-	 *      unwind on error
+	 *	unwind on error
 	 */
       shutdown:		/* unwind lbmLogInit() */
 	list_del(&log->journal_list);
@@ -1427,7 +1427,7 @@
 	return 0;
 
 	/*
-	 *      unwind on error
+	 *	unwind on error
 	 */
       errout30:		/* release log page */
 	log->wqueue = NULL;
@@ -1480,7 +1480,7 @@
 
 	if (test_bit(log_INLINELOG, &log->flag)) {
 		/*
-		 *      in-line log in host file system
+		 *	in-line log in host file system
 		 */
 		rc = lmLogShutdown(log);
 		kfree(log);
@@ -1504,7 +1504,7 @@
 		goto out;
 
 	/*
-	 *      external log as separate logical volume
+	 *	external log as separate logical volume
 	 */
 	list_del(&log->journal_list);
 	bdev = log->bdev;
@@ -1622,20 +1622,26 @@
 	if (!list_empty(&log->synclist)) {
 		struct logsyncblk *lp;
 
+		printk(KERN_ERR "jfs_flush_journal: synclist not empty\n");
 		list_for_each_entry(lp, &log->synclist, synclist) {
 			if (lp->xflag & COMMIT_PAGE) {
 				struct metapage *mp = (struct metapage *)lp;
-				dump_mem("orphan metapage", lp,
-					 sizeof(struct metapage));
-				dump_mem("page", mp->page, sizeof(struct page));
-			}
-			else
-				dump_mem("orphan tblock", lp,
-					 sizeof(struct tblock));
+				print_hex_dump(KERN_ERR, "metapage: ",
+					       DUMP_PREFIX_ADDRESS, 16, 4,
+					       mp, sizeof(struct metapage), 0);
+				print_hex_dump(KERN_ERR, "page: ",
+					       DUMP_PREFIX_ADDRESS, 16,
+					       sizeof(long), mp->page,
+					       sizeof(struct page), 0);
+			} else
+				print_hex_dump(KERN_ERR, "tblock:",
+					       DUMP_PREFIX_ADDRESS, 16, 4,
+					       lp, sizeof(struct tblock), 0);
 		}
 	}
+#else
+	WARN_ON(!list_empty(&log->synclist));
 #endif
-	//assert(list_empty(&log->synclist));
 	clear_bit(log_FLUSH, &log->flag);
 }
 
@@ -1723,7 +1729,7 @@
  *
  * PARAMETE:	log	- pointer to logs inode.
  *		fsdev	- kdev_t of filesystem.
- *		serial  - pointer to returned log serial number
+ *		serial	- pointer to returned log serial number
  *		activate - insert/remove device from active list.
  *
  * RETURN:	0	- success
@@ -1963,7 +1969,7 @@
  * FUNCTION:	add a log buffer to the log redrive list
  *
  * PARAMETER:
- *     bp	- log buffer
+ *	bp	- log buffer
  *
  * NOTES:
  *	Takes log_redrive_lock.
@@ -2054,7 +2060,7 @@
 	bp->l_flag = flag;
 
 	/*
-	 *      insert bp at tail of write queue associated with log
+	 *	insert bp at tail of write queue associated with log
 	 *
 	 * (request is either for bp already/currently at head of queue
 	 * or new bp to be inserted at tail)
@@ -2117,7 +2123,7 @@
 	    log->base + (bp->l_pn << (L2LOGPSIZE - log->l2bsize));
 
 	/*
-	 *      initiate pageout of the page
+	 *	initiate pageout of the page
 	 */
 	lbmStartIO(bp);
 }
@@ -2128,7 +2134,7 @@
  *
  * FUNCTION:	Interface to DD strategy routine
  *
- * RETURN:      none
+ * RETURN:	none
  *
  * serialization: LCACHE_LOCK() is NOT held during log i/o;
  */
@@ -2222,7 +2228,7 @@
 	bio_put(bio);
 
 	/*
-	 *      pagein completion
+	 *	pagein completion
 	 */
 	if (bp->l_flag & lbmREAD) {
 		bp->l_flag &= ~lbmREAD;
@@ -2236,7 +2242,7 @@
 	}
 
 	/*
-	 *      pageout completion
+	 *	pageout completion
 	 *
 	 * the bp at the head of write queue has completed pageout.
 	 *
@@ -2302,7 +2308,7 @@
 	}
 
 	/*
-	 *      synchronous pageout:
+	 *	synchronous pageout:
 	 *
 	 * buffer has not necessarily been removed from write queue
 	 * (e.g., synchronous write of partial-page with COMMIT):
@@ -2316,7 +2322,7 @@
 	}
 
 	/*
-	 *      Group Commit pageout:
+	 *	Group Commit pageout:
 	 */
 	else if (bp->l_flag & lbmGC) {
 		LCACHE_UNLOCK(flags);
@@ -2324,7 +2330,7 @@
 	}
 
 	/*
-	 *      asynchronous pageout:
+	 *	asynchronous pageout:
 	 *
 	 * buffer must have been removed from write queue:
 	 * insert buffer at head of freelist where it can be recycled
@@ -2375,7 +2381,7 @@
  * FUNCTION:	format file system log
  *
  * PARAMETERS:
- *      log	- volume log
+ *	log	- volume log
  *	logAddress - start address of log space in FS block
  *	logSize	- length of log space in FS block;
  *
@@ -2407,16 +2413,16 @@
 	npages = logSize >> sbi->l2nbperpage;
 
 	/*
-	 *      log space:
+	 *	log space:
 	 *
 	 * page 0 - reserved;
 	 * page 1 - log superblock;
 	 * page 2 - log data page: A SYNC log record is written
-	 *          into this page at logform time;
+	 *	    into this page at logform time;
 	 * pages 3-N - log data page: set to empty log data pages;
 	 */
 	/*
-	 *      init log superblock: log page 1
+	 *	init log superblock: log page 1
 	 */
 	logsuper = (struct logsuper *) bp->l_ldata;
 
@@ -2436,7 +2442,7 @@
 		goto exit;
 
 	/*
-	 *      init pages 2 to npages-1 as log data pages:
+	 *	init pages 2 to npages-1 as log data pages:
 	 *
 	 * log page sequence number (lpsn) initialization:
 	 *
@@ -2479,7 +2485,7 @@
 		goto exit;
 
 	/*
-	 *      initialize succeeding log pages: lpsn = 0, 1, ..., (N-2)
+	 *	initialize succeeding log pages: lpsn = 0, 1, ..., (N-2)
 	 */
 	for (lspn = 0; lspn < npages - 3; lspn++) {
 		lp->h.page = lp->t.page = cpu_to_le32(lspn);
@@ -2495,7 +2501,7 @@
 	rc = 0;
 exit:
 	/*
-	 *      finalize log
+	 *	finalize log
 	 */
 	/* release the buffer */
 	lbmFree(bp);
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index a53fb17..1f85ef0 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -144,7 +144,7 @@
  *
  * (this comment should be rewritten !)
  * jfs uses only "after" log records (only a single writer is allowed
- * in a  page, pages are written to temporary paging space if
+ * in a page, pages are written to temporary paging space if
  * if they must be written to disk before commit, and i/o is
  * scheduled for modified pages to their home location after
  * the log records containing the after values and the commit
@@ -153,7 +153,7 @@
  *
  * a log record consists of a data area of variable length followed by
  * a descriptor of fixed size LOGRDSIZE bytes.
- * the  data area is rounded up to an integral number of 4-bytes and
+ * the data area is rounded up to an integral number of 4-bytes and
  * must be no longer than LOGPSIZE.
  * the descriptor is of size of multiple of 4-bytes and aligned on a
  * 4-byte boundary.
@@ -215,13 +215,13 @@
 	union {
 
 		/*
-		 *      COMMIT: commit
+		 *	COMMIT: commit
 		 *
 		 * transaction commit: no type-dependent information;
 		 */
 
 		/*
-		 *      REDOPAGE: after-image
+		 *	REDOPAGE: after-image
 		 *
 		 * apply after-image;
 		 *
@@ -236,7 +236,7 @@
 		} redopage;	/* (20) */
 
 		/*
-		 *      NOREDOPAGE: the page is freed
+		 *	NOREDOPAGE: the page is freed
 		 *
 		 * do not apply after-image records which precede this record
 		 * in the log with the same page block number to this page.
@@ -252,7 +252,7 @@
 		} noredopage;	/* (20) */
 
 		/*
-		 *      UPDATEMAP: update block allocation map
+		 *	UPDATEMAP: update block allocation map
 		 *
 		 * either in-line PXD,
 		 * or     out-of-line  XADLIST;
@@ -268,7 +268,7 @@
 		} updatemap;	/* (20) */
 
 		/*
-		 *      NOREDOINOEXT: the inode extent is freed
+		 *	NOREDOINOEXT: the inode extent is freed
 		 *
 		 * do not apply after-image records which precede this
 		 * record in the log with the any of the 4 page block
@@ -286,7 +286,7 @@
 		} noredoinoext;	/* (20) */
 
 		/*
-		 *      SYNCPT: log sync point
+		 *	SYNCPT: log sync point
 		 *
 		 * replay log upto syncpt address specified;
 		 */
@@ -295,13 +295,13 @@
 		} syncpt;
 
 		/*
-		 *      MOUNT: file system mount
+		 *	MOUNT: file system mount
 		 *
 		 * file system mount: no type-dependent information;
 		 */
 
 		/*
-		 *      ? FREEXTENT: free specified extent(s)
+		 *	? FREEXTENT: free specified extent(s)
 		 *
 		 * free specified extent(s) from block allocation map
 		 * N.B.: nextents should be length of data/sizeof(xad_t)
@@ -314,7 +314,7 @@
 		} freextent;
 
 		/*
-		 *      ? NOREDOFILE: this file is freed
+		 *	? NOREDOFILE: this file is freed
 		 *
 		 * do not apply records which precede this record in the log
 		 * with the same inode number.
@@ -330,7 +330,7 @@
 		} noredofile;
 
 		/*
-		 *      ? NEWPAGE:
+		 *	? NEWPAGE:
 		 *
 		 * metadata type dependent
 		 */
@@ -342,7 +342,7 @@
 		} newpage;
 
 		/*
-		 *      ? DUMMY: filler
+		 *	? DUMMY: filler
 		 *
 		 * no type-dependent information
 		 */
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 43d4f69..77c7f11 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -472,7 +472,8 @@
 	printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");
 	goto skip;
 dump_bio:
-	dump_mem("bio", bio, sizeof(*bio));
+	print_hex_dump(KERN_ERR, "JFS: dump of bio: ", DUMP_PREFIX_ADDRESS, 16,
+		       4, bio, sizeof(*bio), 0);
 skip:
 	bio_put(bio);
 	unlock_page(page);
diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
index 4dd4798..644429a 100644
--- a/fs/jfs/jfs_mount.c
+++ b/fs/jfs/jfs_mount.c
@@ -80,7 +80,7 @@
  */
 int jfs_mount(struct super_block *sb)
 {
-	int rc = 0;		/* Return code          */
+	int rc = 0;		/* Return code */
 	struct jfs_sb_info *sbi = JFS_SBI(sb);
 	struct inode *ipaimap = NULL;
 	struct inode *ipaimap2 = NULL;
@@ -169,7 +169,7 @@
 		sbi->ipaimap2 = NULL;
 
 	/*
-	 *      mount (the only/single) fileset
+	 *	mount (the only/single) fileset
 	 */
 	/*
 	 * open fileset inode allocation map (aka fileset inode)
@@ -195,7 +195,7 @@
 	goto out;
 
 	/*
-	 *      unwind on error
+	 *	unwind on error
 	 */
       errout41:		/* close fileset inode allocation map inode */
 	diFreeSpecial(ipimap);
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 25430d0..7aa1f70 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -18,7 +18,7 @@
  */
 
 /*
- *      jfs_txnmgr.c: transaction manager
+ *	jfs_txnmgr.c: transaction manager
  *
  * notes:
  * transaction starts with txBegin() and ends with txCommit()
@@ -60,7 +60,7 @@
 #include "jfs_debug.h"
 
 /*
- *      transaction management structures
+ *	transaction management structures
  */
 static struct {
 	int freetid;		/* index of a free tid structure */
@@ -103,19 +103,19 @@
 MODULE_PARM_DESC(nTxLock,
 		 "Number of transaction locks (max:65536)");
 
-struct tblock *TxBlock;	        /* transaction block table */
-static int TxLockLWM;		/* Low water mark for number of txLocks used */
-static int TxLockHWM;		/* High water mark for number of txLocks used */
-static int TxLockVHWM;		/* Very High water mark */
-struct tlock *TxLock;           /* transaction lock table */
+struct tblock *TxBlock;	/* transaction block table */
+static int TxLockLWM;	/* Low water mark for number of txLocks used */
+static int TxLockHWM;	/* High water mark for number of txLocks used */
+static int TxLockVHWM;	/* Very High water mark */
+struct tlock *TxLock;	/* transaction lock table */
 
 /*
- *      transaction management lock
+ *	transaction management lock
  */
 static DEFINE_SPINLOCK(jfsTxnLock);
 
-#define TXN_LOCK()              spin_lock(&jfsTxnLock)
-#define TXN_UNLOCK()            spin_unlock(&jfsTxnLock)
+#define TXN_LOCK()		spin_lock(&jfsTxnLock)
+#define TXN_UNLOCK()		spin_unlock(&jfsTxnLock)
 
 #define LAZY_LOCK_INIT()	spin_lock_init(&TxAnchor.LazyLock);
 #define LAZY_LOCK(flags)	spin_lock_irqsave(&TxAnchor.LazyLock, flags)
@@ -148,7 +148,7 @@
 #define TXN_WAKEUP(event) wake_up_all(event)
 
 /*
- *      statistics
+ *	statistics
  */
 static struct {
 	tid_t maxtid;		/* 4: biggest tid ever used */
@@ -181,8 +181,8 @@
 static void LogSyncRelease(struct metapage * mp);
 
 /*
- *              transaction block/lock management
- *              ---------------------------------
+ *		transaction block/lock management
+ *		---------------------------------
  */
 
 /*
@@ -227,9 +227,9 @@
 }
 
 /*
- * NAME:        txInit()
+ * NAME:	txInit()
  *
- * FUNCTION:    initialize transaction management structures
+ * FUNCTION:	initialize transaction management structures
  *
  * RETURN:
  *
@@ -333,9 +333,9 @@
 }
 
 /*
- * NAME:        txExit()
+ * NAME:	txExit()
  *
- * FUNCTION:    clean up when module is unloaded
+ * FUNCTION:	clean up when module is unloaded
  */
 void txExit(void)
 {
@@ -346,12 +346,12 @@
 }
 
 /*
- * NAME:        txBegin()
+ * NAME:	txBegin()
  *
- * FUNCTION:    start a transaction.
+ * FUNCTION:	start a transaction.
  *
- * PARAMETER:   sb	- superblock
- *              flag	- force for nested tx;
+ * PARAMETER:	sb	- superblock
+ *		flag	- force for nested tx;
  *
  * RETURN:	tid	- transaction id
  *
@@ -447,13 +447,13 @@
 }
 
 /*
- * NAME:        txBeginAnon()
+ * NAME:	txBeginAnon()
  *
- * FUNCTION:    start an anonymous transaction.
+ * FUNCTION:	start an anonymous transaction.
  *		Blocks if logsync or available tlocks are low to prevent
  *		anonymous tlocks from depleting supply.
  *
- * PARAMETER:   sb	- superblock
+ * PARAMETER:	sb	- superblock
  *
  * RETURN:	none
  */
@@ -489,11 +489,11 @@
 }
 
 /*
- *      txEnd()
+ *	txEnd()
  *
  * function: free specified transaction block.
  *
- *      logsync barrier processing:
+ *	logsync barrier processing:
  *
  * serialization:
  */
@@ -577,13 +577,13 @@
 }
 
 /*
- *      txLock()
+ *	txLock()
  *
  * function: acquire a transaction lock on the specified <mp>
  *
  * parameter:
  *
- * return:      transaction lock id
+ * return:	transaction lock id
  *
  * serialization:
  */
@@ -829,12 +829,16 @@
 	/* Only locks on ipimap or ipaimap should reach here */
 	/* assert(jfs_ip->fileset == AGGREGATE_I); */
 	if (jfs_ip->fileset != AGGREGATE_I) {
-		jfs_err("txLock: trying to lock locked page!");
-		dump_mem("ip", ip, sizeof(struct inode));
-		dump_mem("mp", mp, sizeof(struct metapage));
-		dump_mem("Locker's tblk", tid_to_tblock(tid),
-			 sizeof(struct tblock));
-		dump_mem("Tlock", tlck, sizeof(struct tlock));
+		printk(KERN_ERR "txLock: trying to lock locked page!");
+		print_hex_dump(KERN_ERR, "ip: ", DUMP_PREFIX_ADDRESS, 16, 4,
+			       ip, sizeof(*ip), 0);
+		print_hex_dump(KERN_ERR, "mp: ", DUMP_PREFIX_ADDRESS, 16, 4,
+			       mp, sizeof(*mp), 0);
+		print_hex_dump(KERN_ERR, "Locker's tblock: ",
+			       DUMP_PREFIX_ADDRESS, 16, 4, tid_to_tblock(tid),
+			       sizeof(struct tblock), 0);
+		print_hex_dump(KERN_ERR, "Tlock: ", DUMP_PREFIX_ADDRESS, 16, 4,
+			       tlck, sizeof(*tlck), 0);
 		BUG();
 	}
 	INCREMENT(stattx.waitlock);	/* statistics */
@@ -857,17 +861,17 @@
 }
 
 /*
- * NAME:        txRelease()
+ * NAME:	txRelease()
  *
- * FUNCTION:    Release buffers associated with transaction locks, but don't
+ * FUNCTION:	Release buffers associated with transaction locks, but don't
  *		mark homeok yet.  The allows other transactions to modify
  *		buffers, but won't let them go to disk until commit record
  *		actually gets written.
  *
  * PARAMETER:
- *              tblk    -
+ *		tblk	-
  *
- * RETURN:      Errors from subroutines.
+ * RETURN:	Errors from subroutines.
  */
 static void txRelease(struct tblock * tblk)
 {
@@ -896,10 +900,10 @@
 }
 
 /*
- * NAME:        txUnlock()
+ * NAME:	txUnlock()
  *
- * FUNCTION:    Initiates pageout of pages modified by tid in journalled
- *              objects and frees their lockwords.
+ * FUNCTION:	Initiates pageout of pages modified by tid in journalled
+ *		objects and frees their lockwords.
  */
 static void txUnlock(struct tblock * tblk)
 {
@@ -983,10 +987,10 @@
 }
 
 /*
- *      txMaplock()
+ *	txMaplock()
  *
  * function: allocate a transaction lock for freed page/entry;
- *      for freed page, maplock is used as xtlock/dtlock type;
+ *	for freed page, maplock is used as xtlock/dtlock type;
  */
 struct tlock *txMaplock(tid_t tid, struct inode *ip, int type)
 {
@@ -1057,7 +1061,7 @@
 }
 
 /*
- *      txLinelock()
+ *	txLinelock()
  *
  * function: allocate a transaction lock for log vector list
  */
@@ -1092,39 +1096,39 @@
 }
 
 /*
- *              transaction commit management
- *              -----------------------------
+ *		transaction commit management
+ *		-----------------------------
  */
 
 /*
- * NAME:        txCommit()
+ * NAME:	txCommit()
  *
- * FUNCTION:    commit the changes to the objects specified in
- *              clist.  For journalled segments only the
- *              changes of the caller are committed, ie by tid.
- *              for non-journalled segments the data are flushed to
- *              disk and then the change to the disk inode and indirect
- *              blocks committed (so blocks newly allocated to the
- *              segment will be made a part of the segment atomically).
+ * FUNCTION:	commit the changes to the objects specified in
+ *		clist.  For journalled segments only the
+ *		changes of the caller are committed, ie by tid.
+ *		for non-journalled segments the data are flushed to
+ *		disk and then the change to the disk inode and indirect
+ *		blocks committed (so blocks newly allocated to the
+ *		segment will be made a part of the segment atomically).
  *
- *              all of the segments specified in clist must be in
- *              one file system. no more than 6 segments are needed
- *              to handle all unix svcs.
+ *		all of the segments specified in clist must be in
+ *		one file system. no more than 6 segments are needed
+ *		to handle all unix svcs.
  *
- *              if the i_nlink field (i.e. disk inode link count)
- *              is zero, and the type of inode is a regular file or
- *              directory, or symbolic link , the inode is truncated
- *              to zero length. the truncation is committed but the
- *              VM resources are unaffected until it is closed (see
- *              iput and iclose).
+ *		if the i_nlink field (i.e. disk inode link count)
+ *		is zero, and the type of inode is a regular file or
+ *		directory, or symbolic link , the inode is truncated
+ *		to zero length. the truncation is committed but the
+ *		VM resources are unaffected until it is closed (see
+ *		iput and iclose).
  *
  * PARAMETER:
  *
  * RETURN:
  *
  * serialization:
- *              on entry the inode lock on each segment is assumed
- *              to be held.
+ *		on entry the inode lock on each segment is assumed
+ *		to be held.
  *
  * i/o error:
  */
@@ -1175,7 +1179,7 @@
 	if ((flag & (COMMIT_FORCE | COMMIT_SYNC)) == 0)
 		tblk->xflag |= COMMIT_LAZY;
 	/*
-	 *      prepare non-journaled objects for commit
+	 *	prepare non-journaled objects for commit
 	 *
 	 * flush data pages of non-journaled file
 	 * to prevent the file getting non-initialized disk blocks
@@ -1186,7 +1190,7 @@
 	cd.nip = nip;
 
 	/*
-	 *      acquire transaction lock on (on-disk) inodes
+	 *	acquire transaction lock on (on-disk) inodes
 	 *
 	 * update on-disk inode from in-memory inode
 	 * acquiring transaction locks for AFTER records
@@ -1262,7 +1266,7 @@
 	}
 
 	/*
-	 *      write log records from transaction locks
+	 *	write log records from transaction locks
 	 *
 	 * txUpdateMap() resets XAD_NEW in XAD.
 	 */
@@ -1294,7 +1298,7 @@
 		!test_cflag(COMMIT_Nolink, tblk->u.ip)));
 
 	/*
-	 *      write COMMIT log record
+	 *	write COMMIT log record
 	 */
 	lrd->type = cpu_to_le16(LOG_COMMIT);
 	lrd->length = 0;
@@ -1303,7 +1307,7 @@
 	lmGroupCommit(log, tblk);
 
 	/*
-	 *      - transaction is now committed -
+	 *	- transaction is now committed -
 	 */
 
 	/*
@@ -1314,11 +1318,11 @@
 		txForce(tblk);
 
 	/*
-	 *      update allocation map.
+	 *	update allocation map.
 	 *
 	 * update inode allocation map and inode:
 	 * free pager lock on memory object of inode if any.
-	 * update  block allocation map.
+	 * update block allocation map.
 	 *
 	 * txUpdateMap() resets XAD_NEW in XAD.
 	 */
@@ -1326,7 +1330,7 @@
 		txUpdateMap(tblk);
 
 	/*
-	 *      free transaction locks and pageout/free pages
+	 *	free transaction locks and pageout/free pages
 	 */
 	txRelease(tblk);
 
@@ -1335,7 +1339,7 @@
 
 
 	/*
-	 *      reset in-memory object state
+	 *	reset in-memory object state
 	 */
 	for (k = 0; k < cd.nip; k++) {
 		ip = cd.iplist[k];
@@ -1358,11 +1362,11 @@
 }
 
 /*
- * NAME:        txLog()
+ * NAME:	txLog()
  *
- * FUNCTION:    Writes AFTER log records for all lines modified
- *              by tid for segments specified by inodes in comdata.
- *              Code assumes only WRITELOCKS are recorded in lockwords.
+ * FUNCTION:	Writes AFTER log records for all lines modified
+ *		by tid for segments specified by inodes in comdata.
+ *		Code assumes only WRITELOCKS are recorded in lockwords.
  *
  * PARAMETERS:
  *
@@ -1421,12 +1425,12 @@
 }
 
 /*
- *      diLog()
+ *	diLog()
  *
- * function:    log inode tlock and format maplock to update bmap;
+ * function:	log inode tlock and format maplock to update bmap;
  */
 static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
-	  struct tlock * tlck, struct commit * cd)
+		 struct tlock * tlck, struct commit * cd)
 {
 	int rc = 0;
 	struct metapage *mp;
@@ -1442,7 +1446,7 @@
 	pxd = &lrd->log.redopage.pxd;
 
 	/*
-	 *      inode after image
+	 *	inode after image
 	 */
 	if (tlck->type & tlckENTRY) {
 		/* log after-image for logredo(): */
@@ -1456,7 +1460,7 @@
 		tlck->flag |= tlckWRITEPAGE;
 	} else if (tlck->type & tlckFREE) {
 		/*
-		 *      free inode extent
+		 *	free inode extent
 		 *
 		 * (pages of the freed inode extent have been invalidated and
 		 * a maplock for free of the extent has been formatted at
@@ -1498,7 +1502,7 @@
 		jfs_err("diLog: UFO type tlck:0x%p", tlck);
 #ifdef  _JFS_WIP
 	/*
-	 *      alloc/free external EA extent
+	 *	alloc/free external EA extent
 	 *
 	 * a maplock for txUpdateMap() to update bPWMAP for alloc/free
 	 * of the extent has been formatted at txLock() time;
@@ -1534,9 +1538,9 @@
 }
 
 /*
- *      dataLog()
+ *	dataLog()
  *
- * function:    log data tlock
+ * function:	log data tlock
  */
 static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
 	    struct tlock * tlck)
@@ -1580,9 +1584,9 @@
 }
 
 /*
- *      dtLog()
+ *	dtLog()
  *
- * function:    log dtree tlock and format maplock to update bmap;
+ * function:	log dtree tlock and format maplock to update bmap;
  */
 static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
 	   struct tlock * tlck)
@@ -1603,10 +1607,10 @@
 		lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT);
 
 	/*
-	 *      page extension via relocation: entry insertion;
-	 *      page extension in-place: entry insertion;
-	 *      new right page from page split, reinitialized in-line
-	 *      root from root page split: entry insertion;
+	 *	page extension via relocation: entry insertion;
+	 *	page extension in-place: entry insertion;
+	 *	new right page from page split, reinitialized in-line
+	 *	root from root page split: entry insertion;
 	 */
 	if (tlck->type & (tlckNEW | tlckEXTEND)) {
 		/* log after-image of the new page for logredo():
@@ -1641,8 +1645,8 @@
 	}
 
 	/*
-	 *      entry insertion/deletion,
-	 *      sibling page link update (old right page before split);
+	 *	entry insertion/deletion,
+	 *	sibling page link update (old right page before split);
 	 */
 	if (tlck->type & (tlckENTRY | tlckRELINK)) {
 		/* log after-image for logredo(): */
@@ -1658,11 +1662,11 @@
 	}
 
 	/*
-	 *      page deletion: page has been invalidated
-	 *      page relocation: source extent
+	 *	page deletion: page has been invalidated
+	 *	page relocation: source extent
 	 *
-	 *      a maplock for free of the page has been formatted
-	 *      at txLock() time);
+	 *	a maplock for free of the page has been formatted
+	 *	at txLock() time);
 	 */
 	if (tlck->type & (tlckFREE | tlckRELOCATE)) {
 		/* log LOG_NOREDOPAGE of the deleted page for logredo()
@@ -1683,9 +1687,9 @@
 }
 
 /*
- *      xtLog()
+ *	xtLog()
  *
- * function:    log xtree tlock and format maplock to update bmap;
+ * function:	log xtree tlock and format maplock to update bmap;
  */
 static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
 	   struct tlock * tlck)
@@ -1725,8 +1729,8 @@
 	xadlock = (struct xdlistlock *) maplock;
 
 	/*
-	 *      entry insertion/extension;
-	 *      sibling page link update (old right page before split);
+	 *	entry insertion/extension;
+	 *	sibling page link update (old right page before split);
 	 */
 	if (tlck->type & (tlckNEW | tlckGROW | tlckRELINK)) {
 		/* log after-image for logredo():
@@ -1801,7 +1805,7 @@
 	}
 
 	/*
-	 *      page deletion: file deletion/truncation (ref. xtTruncate())
+	 *	page deletion: file deletion/truncation (ref. xtTruncate())
 	 *
 	 * (page will be invalidated after log is written and bmap
 	 * is updated from the page);
@@ -1908,13 +1912,13 @@
 	}
 
 	/*
-	 *      page/entry truncation: file truncation (ref. xtTruncate())
+	 *	page/entry truncation: file truncation (ref. xtTruncate())
 	 *
-	 *     |----------+------+------+---------------|
-	 *                |      |      |
-	 *                |      |     hwm - hwm before truncation
-	 *                |     next - truncation point
-	 *               lwm - lwm before truncation
+	 *	|----------+------+------+---------------|
+	 *		   |      |      |
+	 *		   |      |     hwm - hwm before truncation
+	 *		   |     next - truncation point
+	 *		  lwm - lwm before truncation
 	 * header ?
 	 */
 	if (tlck->type & tlckTRUNCATE) {
@@ -1937,7 +1941,7 @@
 		twm = xtlck->twm.offset;
 
 		/*
-		 *      write log records
+		 *	write log records
 		 */
 		/* log after-image for logredo():
 		 *
@@ -1997,7 +2001,7 @@
 		}
 
 		/*
-		 *      format maplock(s) for txUpdateMap() to update bmap
+		 *	format maplock(s) for txUpdateMap() to update bmap
 		 */
 		maplock->index = 0;
 
@@ -2069,9 +2073,9 @@
 }
 
 /*
- *      mapLog()
+ *	mapLog()
  *
- * function:    log from maplock of freed data extents;
+ * function:	log from maplock of freed data extents;
  */
 static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
 		   struct tlock * tlck)
@@ -2081,7 +2085,7 @@
 	pxd_t *pxd;
 
 	/*
-	 *      page relocation: free the source page extent
+	 *	page relocation: free the source page extent
 	 *
 	 * a maplock for txUpdateMap() for free of the page
 	 * has been formatted at txLock() time saving the src
@@ -2155,10 +2159,10 @@
 }
 
 /*
- *      txEA()
+ *	txEA()
  *
- * function:    acquire maplock for EA/ACL extents or
- *              set COMMIT_INLINE flag;
+ * function:	acquire maplock for EA/ACL extents or
+ *		set COMMIT_INLINE flag;
  */
 void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea)
 {
@@ -2207,10 +2211,10 @@
 }
 
 /*
- *      txForce()
+ *	txForce()
  *
  * function: synchronously write pages locked by transaction
- *              after txLog() but before txUpdateMap();
+ *	     after txLog() but before txUpdateMap();
  */
 static void txForce(struct tblock * tblk)
 {
@@ -2273,10 +2277,10 @@
 }
 
 /*
- *      txUpdateMap()
+ *	txUpdateMap()
  *
- * function:    update persistent allocation map (and working map
- *              if appropriate);
+ * function:	update persistent allocation map (and working map
+ *		if appropriate);
  *
  * parameter:
  */
@@ -2298,7 +2302,7 @@
 
 
 	/*
-	 *      update block allocation map
+	 *	update block allocation map
 	 *
 	 * update allocation state in pmap (and wmap) and
 	 * update lsn of the pmap page;
@@ -2382,7 +2386,7 @@
 		}
 	}
 	/*
-	 *      update inode allocation map
+	 *	update inode allocation map
 	 *
 	 * update allocation state in pmap and
 	 * update lsn of the pmap page;
@@ -2407,24 +2411,24 @@
 }
 
 /*
- *      txAllocPMap()
+ *	txAllocPMap()
  *
  * function: allocate from persistent map;
  *
  * parameter:
- *      ipbmap  -
- *      malock -
- *              xad list:
- *              pxd:
+ *	ipbmap	-
+ *	malock	-
+ *		xad list:
+ *		pxd:
  *
- *      maptype -
- *              allocate from persistent map;
- *              free from persistent map;
- *              (e.g., tmp file - free from working map at releae
- *               of last reference);
- *              free from persistent and working map;
+ *	maptype -
+ *		allocate from persistent map;
+ *		free from persistent map;
+ *		(e.g., tmp file - free from working map at releae
+ *		 of last reference);
+ *		free from persistent and working map;
  *
- *      lsn     - log sequence number;
+ *	lsn	- log sequence number;
  */
 static void txAllocPMap(struct inode *ip, struct maplock * maplock,
 			struct tblock * tblk)
@@ -2478,9 +2482,9 @@
 }
 
 /*
- *      txFreeMap()
+ *	txFreeMap()
  *
- * function:    free from persistent and/or working map;
+ * function:	free from persistent and/or working map;
  *
  * todo: optimization
  */
@@ -2579,9 +2583,9 @@
 }
 
 /*
- *      txFreelock()
+ *	txFreelock()
  *
- * function:    remove tlock from inode anonymous locklist
+ * function:	remove tlock from inode anonymous locklist
  */
 void txFreelock(struct inode *ip)
 {
@@ -2619,7 +2623,7 @@
 }
 
 /*
- *      txAbort()
+ *	txAbort()
  *
  * function: abort tx before commit;
  *
@@ -2679,7 +2683,7 @@
 }
 
 /*
- *      txLazyCommit(void)
+ *	txLazyCommit(void)
  *
  *	All transactions except those changing ipimap (COMMIT_FORCE) are
  *	processed by this routine.  This insures that the inode and block
@@ -2728,7 +2732,7 @@
 }
 
 /*
- *      jfs_lazycommit(void)
+ *	jfs_lazycommit(void)
  *
  *	To be run as a kernel daemon.  If lbmIODone is called in an interrupt
  *	context, or where blocking is not wanted, this routine will process
@@ -2913,7 +2917,7 @@
 }
 
 /*
- *      jfs_sync(void)
+ *	jfs_sync(void)
  *
  *	To be run as a kernel daemon.  This is awakened when tlocks run low.
  *	We write any inodes that have anonymous tlocks so they will become
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index 7863cf2..ab72889 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -94,7 +94,7 @@
  */
 struct tlock {
 	lid_t next;		/* 2: index next lockword on tid locklist
-				 *          next lockword on freelist
+				 *	    next lockword on freelist
 				 */
 	tid_t tid;		/* 2: transaction id holding lock */
 
diff --git a/fs/jfs/jfs_types.h b/fs/jfs/jfs_types.h
index 09b2529..649f981 100644
--- a/fs/jfs/jfs_types.h
+++ b/fs/jfs/jfs_types.h
@@ -21,7 +21,7 @@
 /*
  *	jfs_types.h:
  *
- * basic type/utility  definitions
+ * basic type/utility definitions
  *
  * note: this header file must be the 1st include file
  * of JFS include list in all JFS .c file.
@@ -54,8 +54,8 @@
  */
 
 #define LEFTMOSTONE	0x80000000
-#define	HIGHORDER	0x80000000u	/* high order bit on            */
-#define	ONES		0xffffffffu	/* all bit on                   */
+#define	HIGHORDER	0x80000000u	/* high order bit on	*/
+#define	ONES		0xffffffffu	/* all bit on		*/
 
 /*
  *	logical xd (lxd)
@@ -148,7 +148,7 @@
 #define sizeDXD(dxd)	le32_to_cpu((dxd)->size)
 
 /*
- *      directory entry argument
+ *	directory entry argument
  */
 struct component_name {
 	int namlen;
@@ -160,14 +160,14 @@
  *	DASD limit information - stored in directory inode
  */
 struct dasd {
-	u8 thresh;		/* Alert Threshold (in percent) */
-	u8 delta;		/* Alert Threshold delta (in percent)   */
+	u8 thresh;		/* Alert Threshold (in percent)		*/
+	u8 delta;		/* Alert Threshold delta (in percent)	*/
 	u8 rsrvd1;
-	u8 limit_hi;		/* DASD limit (in logical blocks)       */
-	__le32 limit_lo;	/* DASD limit (in logical blocks)       */
+	u8 limit_hi;		/* DASD limit (in logical blocks)	*/
+	__le32 limit_lo;	/* DASD limit (in logical blocks)	*/
 	u8 rsrvd2[3];
-	u8 used_hi;		/* DASD usage (in logical blocks)       */
-	__le32 used_lo;		/* DASD usage (in logical blocks)       */
+	u8 used_hi;		/* DASD usage (in logical blocks)	*/
+	__le32 used_lo;		/* DASD usage (in logical blocks)	*/
 };
 
 #define DASDLIMIT(dasdp) \
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index a386f48..7971f37 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -60,7 +60,7 @@
 	jfs_info("UnMount JFS: sb:0x%p", sb);
 
 	/*
-	 *      update superblock and close log
+	 *	update superblock and close log
 	 *
 	 * if mounted read-write and log based recovery was enabled
 	 */
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index acc97c4..1543906 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -16,7 +16,7 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 /*
- *      jfs_xtree.c: extent allocation descriptor B+-tree manager
+ *	jfs_xtree.c: extent allocation descriptor B+-tree manager
  */
 
 #include <linux/fs.h>
@@ -32,30 +32,30 @@
 /*
  * xtree local flag
  */
-#define XT_INSERT       0x00000001
+#define XT_INSERT	0x00000001
 
 /*
- *       xtree key/entry comparison: extent offset
+ *	xtree key/entry comparison: extent offset
  *
  * return:
- *      -1: k < start of extent
- *       0: start_of_extent <= k <= end_of_extent
- *       1: k > end_of_extent
+ *	-1: k < start of extent
+ *	 0: start_of_extent <= k <= end_of_extent
+ *	 1: k > end_of_extent
  */
 #define XT_CMP(CMP, K, X, OFFSET64)\
 {\
-        OFFSET64 = offsetXAD(X);\
-        (CMP) = ((K) >= OFFSET64 + lengthXAD(X)) ? 1 :\
-              ((K) < OFFSET64) ? -1 : 0;\
+	OFFSET64 = offsetXAD(X);\
+	(CMP) = ((K) >= OFFSET64 + lengthXAD(X)) ? 1 :\
+		((K) < OFFSET64) ? -1 : 0;\
 }
 
 /* write a xad entry */
 #define XT_PUTENTRY(XAD, FLAG, OFF, LEN, ADDR)\
 {\
-        (XAD)->flag = (FLAG);\
-        XADoffset((XAD), (OFF));\
-        XADlength((XAD), (LEN));\
-        XADaddress((XAD), (ADDR));\
+	(XAD)->flag = (FLAG);\
+	XADoffset((XAD), (OFF));\
+	XADlength((XAD), (LEN));\
+	XADaddress((XAD), (ADDR));\
 }
 
 #define XT_PAGE(IP, MP) BT_PAGE(IP, MP, xtpage_t, i_xtroot)
@@ -76,13 +76,13 @@
 			MP = NULL;\
 			RC = -EIO;\
 		}\
-        }\
+	}\
 }
 
 /* for consistency */
 #define XT_PUTPAGE(MP) BT_PUTPAGE(MP)
 
-#define XT_GETSEARCH(IP, LEAF, BN, MP,  P, INDEX) \
+#define XT_GETSEARCH(IP, LEAF, BN, MP, P, INDEX) \
 	BT_GETSEARCH(IP, LEAF, BN, MP, xtpage_t, P, INDEX, i_xtroot)
 /* xtree entry parameter descriptor */
 struct xtsplit {
@@ -97,7 +97,7 @@
 
 
 /*
- *      statistics
+ *	statistics
  */
 #ifdef CONFIG_JFS_STATISTICS
 static struct {
@@ -136,7 +136,7 @@
 #endif				/*  _STILL_TO_PORT */
 
 /*
- *      xtLookup()
+ *	xtLookup()
  *
  * function: map a single page into a physical extent;
  */
@@ -179,7 +179,7 @@
 	}
 
 	/*
-	 *      compute the physical extent covering logical extent
+	 *	compute the physical extent covering logical extent
 	 *
 	 * N.B. search may have failed (e.g., hole in sparse file),
 	 * and returned the index of the next entry.
@@ -220,27 +220,27 @@
 
 
 /*
- *      xtLookupList()
+ *	xtLookupList()
  *
  * function: map a single logical extent into a list of physical extent;
  *
  * parameter:
- *      struct inode    *ip,
- *      struct lxdlist  *lxdlist,       lxd list (in)
- *      struct xadlist  *xadlist,       xad list (in/out)
- *      int		flag)
+ *	struct inode	*ip,
+ *	struct lxdlist	*lxdlist,	lxd list (in)
+ *	struct xadlist	*xadlist,	xad list (in/out)
+ *	int		flag)
  *
  * coverage of lxd by xad under assumption of
  * . lxd's are ordered and disjoint.
  * . xad's are ordered and disjoint.
  *
  * return:
- *      0:      success
+ *	0:	success
  *
  * note: a page being written (even a single byte) is backed fully,
- *      except the last page which is only backed with blocks
- *      required to cover the last byte;
- *      the extent backing a page is fully contained within an xad;
+ *	except the last page which is only backed with blocks
+ *	required to cover the last byte;
+ *	the extent backing a page is fully contained within an xad;
  */
 int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
 		 struct xadlist * xadlist, int flag)
@@ -284,7 +284,7 @@
 		return rc;
 
 	/*
-	 *      compute the physical extent covering logical extent
+	 *	compute the physical extent covering logical extent
 	 *
 	 * N.B. search may have failed (e.g., hole in sparse file),
 	 * and returned the index of the next entry.
@@ -343,7 +343,7 @@
 		if (lstart >= size)
 			goto mapend;
 
-		/* compare with the current xad  */
+		/* compare with the current xad */
 		goto compare1;
 	}
 	/* lxd is covered by xad */
@@ -430,7 +430,7 @@
 	/*
 	 * lxd is partially covered by xad
 	 */
-	else {			/* (xend < lend)  */
+	else {			/* (xend < lend) */
 
 		/*
 		 * get next xad
@@ -477,22 +477,22 @@
 
 
 /*
- *      xtSearch()
+ *	xtSearch()
  *
- * function:    search for the xad entry covering specified offset.
+ * function:	search for the xad entry covering specified offset.
  *
  * parameters:
- *      ip      - file object;
- *      xoff    - extent offset;
- *      nextp	- address of next extent (if any) for search miss
- *      cmpp    - comparison result:
- *      btstack - traverse stack;
- *      flag    - search process flag (XT_INSERT);
+ *	ip	- file object;
+ *	xoff	- extent offset;
+ *	nextp	- address of next extent (if any) for search miss
+ *	cmpp	- comparison result:
+ *	btstack - traverse stack;
+ *	flag	- search process flag (XT_INSERT);
  *
  * returns:
- *      btstack contains (bn, index) of search path traversed to the entry.
- *      *cmpp is set to result of comparison with the entry returned.
- *      the page containing the entry is pinned at exit.
+ *	btstack contains (bn, index) of search path traversed to the entry.
+ *	*cmpp is set to result of comparison with the entry returned.
+ *	the page containing the entry is pinned at exit.
  */
 static int xtSearch(struct inode *ip, s64 xoff,	s64 *nextp,
 		    int *cmpp, struct btstack * btstack, int flag)
@@ -517,7 +517,7 @@
 	btstack->nsplit = 0;
 
 	/*
-	 *      search down tree from root:
+	 *	search down tree from root:
 	 *
 	 * between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
 	 * internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -642,7 +642,7 @@
 			XT_CMP(cmp, xoff, &p->xad[index], t64);
 			if (cmp == 0) {
 				/*
-				 *      search hit
+				 *	search hit
 				 */
 				/* search hit - leaf page:
 				 * return the entry found
@@ -692,7 +692,7 @@
 		}
 
 		/*
-		 *      search miss
+		 *	search miss
 		 *
 		 * base is the smallest index with key (Kj) greater than
 		 * search key (K) and may be zero or maxentry index.
@@ -773,22 +773,22 @@
 }
 
 /*
- *      xtInsert()
+ *	xtInsert()
  *
  * function:
  *
  * parameter:
- *      tid     - transaction id;
- *      ip      - file object;
- *      xflag   - extent flag (XAD_NOTRECORDED):
- *      xoff    - extent offset;
- *      xlen    - extent length;
- *      xaddrp  - extent address pointer (in/out):
- *              if (*xaddrp)
- *                      caller allocated data extent at *xaddrp;
- *              else
- *                      allocate data extent and return its xaddr;
- *      flag    -
+ *	tid	- transaction id;
+ *	ip	- file object;
+ *	xflag	- extent flag (XAD_NOTRECORDED):
+ *	xoff	- extent offset;
+ *	xlen	- extent length;
+ *	xaddrp	- extent address pointer (in/out):
+ *		if (*xaddrp)
+ *			caller allocated data extent at *xaddrp;
+ *		else
+ *			allocate data extent and return its xaddr;
+ *	flag	-
  *
  * return:
  */
@@ -813,7 +813,7 @@
 	jfs_info("xtInsert: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);
 
 	/*
-	 *      search for the entry location at which to insert:
+	 *	search for the entry location at which to insert:
 	 *
 	 * xtFastSearch() and xtSearch() both returns (leaf page
 	 * pinned, index at which to insert).
@@ -853,13 +853,13 @@
 	}
 
 	/*
-	 *      insert entry for new extent
+	 *	insert entry for new extent
 	 */
 	xflag |= XAD_NEW;
 
 	/*
-	 *      if the leaf page is full, split the page and
-	 *      propagate up the router entry for the new page from split
+	 *	if the leaf page is full, split the page and
+	 *	propagate up the router entry for the new page from split
 	 *
 	 * The xtSplitUp() will insert the entry and unpin the leaf page.
 	 */
@@ -886,7 +886,7 @@
 	}
 
 	/*
-	 *      insert the new entry into the leaf page
+	 *	insert the new entry into the leaf page
 	 */
 	/*
 	 * acquire a transaction lock on the leaf page;
@@ -930,16 +930,16 @@
 
 
 /*
- *      xtSplitUp()
+ *	xtSplitUp()
  *
  * function:
- *      split full pages as propagating insertion up the tree
+ *	split full pages as propagating insertion up the tree
  *
  * parameter:
- *      tid     - transaction id;
- *      ip      - file object;
- *      split   - entry parameter descriptor;
- *      btstack - traverse stack from xtSearch()
+ *	tid	- transaction id;
+ *	ip	- file object;
+ *	split	- entry parameter descriptor;
+ *	btstack - traverse stack from xtSearch()
  *
  * return:
  */
@@ -1199,22 +1199,22 @@
 
 
 /*
- *      xtSplitPage()
+ *	xtSplitPage()
  *
  * function:
- *      split a full non-root page into
- *      original/split/left page and new right page
- *      i.e., the original/split page remains as left page.
+ *	split a full non-root page into
+ *	original/split/left page and new right page
+ *	i.e., the original/split page remains as left page.
  *
  * parameter:
- *      int		tid,
- *      struct inode    *ip,
- *      struct xtsplit  *split,
- *      struct metapage	**rmpp,
- *      u64		*rbnp,
+ *	int		tid,
+ *	struct inode	*ip,
+ *	struct xtsplit	*split,
+ *	struct metapage	**rmpp,
+ *	u64		*rbnp,
  *
  * return:
- *      Pointer to page in which to insert or NULL on error.
+ *	Pointer to page in which to insert or NULL on error.
  */
 static int
 xtSplitPage(tid_t tid, struct inode *ip,
@@ -1248,9 +1248,9 @@
 	rbn = addressPXD(pxd);
 
 	/* Allocate blocks to quota. */
-       if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
-	       rc = -EDQUOT;
-	       goto clean_up;
+	if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+		rc = -EDQUOT;
+		goto clean_up;
 	}
 
 	quota_allocation += lengthPXD(pxd);
@@ -1304,7 +1304,7 @@
 	skip = split->index;
 
 	/*
-	 *      sequential append at tail (after last entry of last page)
+	 *	sequential append at tail (after last entry of last page)
 	 *
 	 * if splitting the last page on a level because of appending
 	 * a entry to it (skip is maxentry), it's likely that the access is
@@ -1342,7 +1342,7 @@
 	}
 
 	/*
-	 *      non-sequential insert (at possibly middle page)
+	 *	non-sequential insert (at possibly middle page)
 	 */
 
 	/*
@@ -1465,25 +1465,24 @@
 
 
 /*
- *      xtSplitRoot()
+ *	xtSplitRoot()
  *
  * function:
- *      split the full root page into
- *      original/root/split page and new right page
- *      i.e., root remains fixed in tree anchor (inode) and
- *      the root is copied to a single new right child page
- *      since root page << non-root page, and
- *      the split root page contains a single entry for the
- *      new right child page.
+ *	split the full root page into original/root/split page and new
+ *	right page
+ *	i.e., root remains fixed in tree anchor (inode) and the root is
+ *	copied to a single new right child page since root page <<
+ *	non-root page, and the split root page contains a single entry
+ *	for the new right child page.
  *
  * parameter:
- *      int		tid,
- *      struct inode    *ip,
- *      struct xtsplit  *split,
- *      struct metapage	**rmpp)
+ *	int		tid,
+ *	struct inode	*ip,
+ *	struct xtsplit	*split,
+ *	struct metapage	**rmpp)
  *
  * return:
- *      Pointer to page in which to insert or NULL on error.
+ *	Pointer to page in which to insert or NULL on error.
  */
 static int
 xtSplitRoot(tid_t tid,
@@ -1505,7 +1504,7 @@
 	INCREMENT(xtStat.split);
 
 	/*
-	 *      allocate a single (right) child page
+	 *	allocate a single (right) child page
 	 */
 	pxdlist = split->pxdlist;
 	pxd = &pxdlist->pxd[pxdlist->npxd];
@@ -1573,7 +1572,7 @@
 	}
 
 	/*
-	 *      reset the root
+	 *	reset the root
 	 *
 	 * init root with the single entry for the new right page
 	 * set the 1st entry offset to 0, which force the left-most key
@@ -1610,7 +1609,7 @@
 
 
 /*
- *      xtExtend()
+ *	xtExtend()
  *
  * function: extend in-place;
  *
@@ -1677,7 +1676,7 @@
 		goto extendOld;
 
 	/*
-	 *      extent overflow: insert entry for new extent
+	 *	extent overflow: insert entry for new extent
 	 */
 //insertNew:
 	xoff = offsetXAD(xad) + MAXXLEN;
@@ -1685,8 +1684,8 @@
 	nextindex = le16_to_cpu(p->header.nextindex);
 
 	/*
-	 *      if the leaf page is full, insert the new entry and
-	 *      propagate up the router entry for the new page from split
+	 *	if the leaf page is full, insert the new entry and
+	 *	propagate up the router entry for the new page from split
 	 *
 	 * The xtSplitUp() will insert the entry and unpin the leaf page.
 	 */
@@ -1731,7 +1730,7 @@
 		}
 	}
 	/*
-	 *      insert the new entry into the leaf page
+	 *	insert the new entry into the leaf page
 	 */
 	else {
 		/* insert the new entry: mark the entry NEW */
@@ -1771,11 +1770,11 @@
 
 #ifdef _NOTYET
 /*
- *      xtTailgate()
+ *	xtTailgate()
  *
  * function: split existing 'tail' extent
- *      (split offset >= start offset of tail extent), and
- *      relocate and extend the split tail half;
+ *	(split offset >= start offset of tail extent), and
+ *	relocate and extend the split tail half;
  *
  * note: existing extent may or may not have been committed.
  * caller is responsible for pager buffer cache update, and
@@ -1804,7 +1803,7 @@
 
 /*
 printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
-        (ulong)xoff, xlen, (ulong)xaddr);
+	(ulong)xoff, xlen, (ulong)xaddr);
 */
 
 	/* there must exist extent to be tailgated */
@@ -1842,18 +1841,18 @@
 	xad = &p->xad[index];
 /*
 printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
-        (ulong)offsetXAD(xad), lengthXAD(xad), (ulong)addressXAD(xad));
+	(ulong)offsetXAD(xad), lengthXAD(xad), (ulong)addressXAD(xad));
 */
 	if ((llen = xoff - offsetXAD(xad)) == 0)
 		goto updateOld;
 
 	/*
-	 *      partially replace extent: insert entry for new extent
+	 *	partially replace extent: insert entry for new extent
 	 */
 //insertNew:
 	/*
-	 *      if the leaf page is full, insert the new entry and
-	 *      propagate up the router entry for the new page from split
+	 *	if the leaf page is full, insert the new entry and
+	 *	propagate up the router entry for the new page from split
 	 *
 	 * The xtSplitUp() will insert the entry and unpin the leaf page.
 	 */
@@ -1898,7 +1897,7 @@
 		}
 	}
 	/*
-	 *      insert the new entry into the leaf page
+	 *	insert the new entry into the leaf page
 	 */
 	else {
 		/* insert the new entry: mark the entry NEW */
@@ -1955,17 +1954,17 @@
 #endif /* _NOTYET */
 
 /*
- *      xtUpdate()
+ *	xtUpdate()
  *
  * function: update XAD;
  *
- *      update extent for allocated_but_not_recorded or
- *      compressed extent;
+ *	update extent for allocated_but_not_recorded or
+ *	compressed extent;
  *
  * parameter:
- *      nxad    - new XAD;
- *                logical extent of the specified XAD must be completely
- *                contained by an existing XAD;
+ *	nxad	- new XAD;
+ *		logical extent of the specified XAD must be completely
+ *		contained by an existing XAD;
  */
 int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
 {				/* new XAD */
@@ -2416,19 +2415,19 @@
 
 
 /*
- *      xtAppend()
+ *	xtAppend()
  *
  * function: grow in append mode from contiguous region specified ;
  *
  * parameter:
- *      tid             - transaction id;
- *      ip              - file object;
- *      xflag           - extent flag:
- *      xoff            - extent offset;
- *      maxblocks       - max extent length;
- *      xlen            - extent length (in/out);
- *      xaddrp          - extent address pointer (in/out):
- *      flag            -
+ *	tid		- transaction id;
+ *	ip		- file object;
+ *	xflag		- extent flag:
+ *	xoff		- extent offset;
+ *	maxblocks	- max extent length;
+ *	xlen		- extent length (in/out);
+ *	xaddrp		- extent address pointer (in/out):
+ *	flag		-
  *
  * return:
  */
@@ -2460,7 +2459,7 @@
 		 (ulong) xoff, maxblocks, xlen, (ulong) xaddr);
 
 	/*
-	 *      search for the entry location at which to insert:
+	 *	search for the entry location at which to insert:
 	 *
 	 * xtFastSearch() and xtSearch() both returns (leaf page
 	 * pinned, index at which to insert).
@@ -2482,13 +2481,13 @@
 		xlen = min(xlen, (int)(next - xoff));
 //insert:
 	/*
-	 *      insert entry for new extent
+	 *	insert entry for new extent
 	 */
 	xflag |= XAD_NEW;
 
 	/*
-	 *      if the leaf page is full, split the page and
-	 *      propagate up the router entry for the new page from split
+	 *	if the leaf page is full, split the page and
+	 *	propagate up the router entry for the new page from split
 	 *
 	 * The xtSplitUp() will insert the entry and unpin the leaf page.
 	 */
@@ -2545,7 +2544,7 @@
 	return 0;
 
 	/*
-	 *      insert the new entry into the leaf page
+	 *	insert the new entry into the leaf page
 	 */
       insertLeaf:
 	/*
@@ -2589,17 +2588,17 @@
 
 /* - TBD for defragmentaion/reorganization -
  *
- *      xtDelete()
+ *	xtDelete()
  *
  * function:
- *      delete the entry with the specified key.
+ *	delete the entry with the specified key.
  *
- *      N.B.: whole extent of the entry is assumed to be deleted.
+ *	N.B.: whole extent of the entry is assumed to be deleted.
  *
  * parameter:
  *
  * return:
- *       ENOENT: if the entry is not found.
+ *	ENOENT: if the entry is not found.
  *
  * exception:
  */
@@ -2665,10 +2664,10 @@
 
 /* - TBD for defragmentaion/reorganization -
  *
- *      xtDeleteUp()
+ *	xtDeleteUp()
  *
  * function:
- *      free empty pages as propagating deletion up the tree
+ *	free empty pages as propagating deletion up the tree
  *
  * parameter:
  *
@@ -2815,15 +2814,15 @@
 
 
 /*
- * NAME:        xtRelocate()
+ * NAME:	xtRelocate()
  *
- * FUNCTION:    relocate xtpage or data extent of regular file;
- *              This function is mainly used by defragfs utility.
+ * FUNCTION:	relocate xtpage or data extent of regular file;
+ *		This function is mainly used by defragfs utility.
  *
- * NOTE:        This routine does not have the logic to handle
- *              uncommitted allocated extent. The caller should call
- *              txCommit() to commit all the allocation before call
- *              this routine.
+ * NOTE:	This routine does not have the logic to handle
+ *		uncommitted allocated extent. The caller should call
+ *		txCommit() to commit all the allocation before call
+ *		this routine.
  */
 int
 xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad,	/* old XAD */
@@ -2865,8 +2864,8 @@
 		 xtype, (ulong) xoff, xlen, (ulong) oxaddr, (ulong) nxaddr);
 
 	/*
-	 *      1. get and validate the parent xtpage/xad entry
-	 *      covering the source extent to be relocated;
+	 *	1. get and validate the parent xtpage/xad entry
+	 *	covering the source extent to be relocated;
 	 */
 	if (xtype == DATAEXT) {
 		/* search in leaf entry */
@@ -2910,7 +2909,7 @@
 	jfs_info("xtRelocate: parent xad entry validated.");
 
 	/*
-	 *      2. relocate the extent
+	 *	2. relocate the extent
 	 */
 	if (xtype == DATAEXT) {
 		/* if the extent is allocated-but-not-recorded
@@ -2923,7 +2922,7 @@
 			XT_PUTPAGE(pmp);
 
 		/*
-		 *      cmRelocate()
+		 *	cmRelocate()
 		 *
 		 * copy target data pages to be relocated;
 		 *
@@ -2945,8 +2944,8 @@
 		pno = offset >> CM_L2BSIZE;
 		npages = (nbytes + (CM_BSIZE - 1)) >> CM_L2BSIZE;
 /*
-                npages = ((offset + nbytes - 1) >> CM_L2BSIZE) -
-                         (offset >> CM_L2BSIZE) + 1;
+		npages = ((offset + nbytes - 1) >> CM_L2BSIZE) -
+			  (offset >> CM_L2BSIZE) + 1;
 */
 		sxaddr = oxaddr;
 		dxaddr = nxaddr;
@@ -2981,7 +2980,7 @@
 
 		XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
 		jfs_info("xtRelocate: target data extent relocated.");
-	} else {		/* (xtype  == XTPAGE) */
+	} else {		/* (xtype == XTPAGE) */
 
 		/*
 		 * read in the target xtpage from the source extent;
@@ -3026,16 +3025,14 @@
 		 */
 		if (lmp) {
 			BT_MARK_DIRTY(lmp, ip);
-			tlck =
-			    txLock(tid, ip, lmp, tlckXTREE | tlckRELINK);
+			tlck = txLock(tid, ip, lmp, tlckXTREE | tlckRELINK);
 			lp->header.next = cpu_to_le64(nxaddr);
 			XT_PUTPAGE(lmp);
 		}
 
 		if (rmp) {
 			BT_MARK_DIRTY(rmp, ip);
-			tlck =
-			    txLock(tid, ip, rmp, tlckXTREE | tlckRELINK);
+			tlck = txLock(tid, ip, rmp, tlckXTREE | tlckRELINK);
 			rp->header.prev = cpu_to_le64(nxaddr);
 			XT_PUTPAGE(rmp);
 		}
@@ -3062,7 +3059,7 @@
 		 * scan may be skipped by commit() and logredo();
 		 */
 		BT_MARK_DIRTY(mp, ip);
-		/* tlckNEW init  xtlck->lwm.offset = XTENTRYSTART; */
+		/* tlckNEW init xtlck->lwm.offset = XTENTRYSTART; */
 		tlck = txLock(tid, ip, mp, tlckXTREE | tlckNEW);
 		xtlck = (struct xtlock *) & tlck->lock;
 
@@ -3084,7 +3081,7 @@
 	}
 
 	/*
-	 *      3. acquire maplock for the source extent to be freed;
+	 *	3. acquire maplock for the source extent to be freed;
 	 *
 	 * acquire a maplock saving the src relocated extent address;
 	 * to free of the extent at commit time;
@@ -3105,7 +3102,7 @@
 	 *      is no buffer associated with this lock since the buffer
 	 *      has been redirected to the target location.
 	 */
-	else			/* (xtype  == XTPAGE) */
+	else			/* (xtype == XTPAGE) */
 		tlck = txMaplock(tid, ip, tlckMAP | tlckRELOCATE);
 
 	pxdlock = (struct pxd_lock *) & tlck->lock;
@@ -3115,7 +3112,7 @@
 	pxdlock->index = 1;
 
 	/*
-	 *      4. update the parent xad entry for relocation;
+	 *	4. update the parent xad entry for relocation;
 	 *
 	 * acquire tlck for the parent entry with XAD_NEW as entry
 	 * update which will write LOG_REDOPAGE and update bmap for
@@ -3143,22 +3140,22 @@
 
 
 /*
- *      xtSearchNode()
+ *	xtSearchNode()
  *
- * function:    search for the internal xad entry covering specified extent.
- *              This function is mainly used by defragfs utility.
+ * function:	search for the internal xad entry covering specified extent.
+ *		This function is mainly used by defragfs utility.
  *
  * parameters:
- *      ip      - file object;
- *      xad     - extent to find;
- *      cmpp    - comparison result:
- *      btstack - traverse stack;
- *      flag    - search process flag;
+ *	ip	- file object;
+ *	xad	- extent to find;
+ *	cmpp	- comparison result:
+ *	btstack - traverse stack;
+ *	flag	- search process flag;
  *
  * returns:
- *      btstack contains (bn, index) of search path traversed to the entry.
- *      *cmpp is set to result of comparison with the entry returned.
- *      the page containing the entry is pinned at exit.
+ *	btstack contains (bn, index) of search path traversed to the entry.
+ *	*cmpp is set to result of comparison with the entry returned.
+ *	the page containing the entry is pinned at exit.
  */
 static int xtSearchNode(struct inode *ip, xad_t * xad,	/* required XAD entry */
 			int *cmpp, struct btstack * btstack, int flag)
@@ -3181,7 +3178,7 @@
 	xaddr = addressXAD(xad);
 
 	/*
-	 *      search down tree from root:
+	 *	search down tree from root:
 	 *
 	 * between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
 	 * internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -3217,7 +3214,7 @@
 			XT_CMP(cmp, xoff, &p->xad[index], t64);
 			if (cmp == 0) {
 				/*
-				 *      search hit
+				 *	search hit
 				 *
 				 * verify for exact match;
 				 */
@@ -3245,7 +3242,7 @@
 		}
 
 		/*
-		 *      search miss - non-leaf page:
+		 *	search miss - non-leaf page:
 		 *
 		 * base is the smallest index with key (Kj) greater than
 		 * search key (K) and may be zero or maxentry index.
@@ -3268,15 +3265,15 @@
 
 
 /*
- *      xtRelink()
+ *	xtRelink()
  *
  * function:
- *      link around a freed page.
+ *	link around a freed page.
  *
  * Parameter:
- *      int           tid,
- *      struct inode    *ip,
- *      xtpage_t        *p)
+ *	int		tid,
+ *	struct inode	*ip,
+ *	xtpage_t	*p)
  *
  * returns:
  */
@@ -3338,7 +3335,7 @@
 
 
 /*
- *      xtInitRoot()
+ *	xtInitRoot()
  *
  * initialize file root (inline in inode)
  */
@@ -3385,42 +3382,42 @@
 #define MAX_TRUNCATE_LEAVES 50
 
 /*
- *      xtTruncate()
+ *	xtTruncate()
  *
  * function:
- *      traverse for truncation logging backward bottom up;
- *      terminate at the last extent entry at the current subtree
- *      root page covering new down size.
- *      truncation may occur within the last extent entry.
+ *	traverse for truncation logging backward bottom up;
+ *	terminate at the last extent entry at the current subtree
+ *	root page covering new down size.
+ *	truncation may occur within the last extent entry.
  *
  * parameter:
- *      int           tid,
- *      struct inode    *ip,
- *      s64           newsize,
- *      int           type)   {PWMAP, PMAP, WMAP; DELETE, TRUNCATE}
+ *	int		tid,
+ *	struct inode	*ip,
+ *	s64		newsize,
+ *	int		type)	{PWMAP, PMAP, WMAP; DELETE, TRUNCATE}
  *
  * return:
  *
  * note:
- *      PWMAP:
- *       1. truncate (non-COMMIT_NOLINK file)
- *          by jfs_truncate() or jfs_open(O_TRUNC):
- *          xtree is updated;
+ *	PWMAP:
+ *	 1. truncate (non-COMMIT_NOLINK file)
+ *	    by jfs_truncate() or jfs_open(O_TRUNC):
+ *	    xtree is updated;
  *	 2. truncate index table of directory when last entry removed
- *       map update via tlock at commit time;
- *      PMAP:
+ *	map update via tlock at commit time;
+ *	PMAP:
  *	 Call xtTruncate_pmap instead
- *      WMAP:
- *       1. remove (free zero link count) on last reference release
- *          (pmap has been freed at commit zero link count);
- *       2. truncate (COMMIT_NOLINK file, i.e., tmp file):
- *          xtree is updated;
- *       map update directly at truncation time;
+ *	WMAP:
+ *	 1. remove (free zero link count) on last reference release
+ *	    (pmap has been freed at commit zero link count);
+ *	 2. truncate (COMMIT_NOLINK file, i.e., tmp file):
+ *	    xtree is updated;
+ *	 map update directly at truncation time;
  *
- *      if (DELETE)
- *              no LOG_NOREDOPAGE is required (NOREDOFILE is sufficient);
- *      else if (TRUNCATE)
- *              must write LOG_NOREDOPAGE for deleted index page;
+ *	if (DELETE)
+ *		no LOG_NOREDOPAGE is required (NOREDOFILE is sufficient);
+ *	else if (TRUNCATE)
+ *		must write LOG_NOREDOPAGE for deleted index page;
  *
  * pages may already have been tlocked by anonymous transactions
  * during file growth (i.e., write) before truncation;
@@ -3493,7 +3490,7 @@
 	 * retained in the new sized file.
 	 * if type is PMAP, the data and index pages are NOT
 	 * freed, and the data and index blocks are NOT freed
-	 * from  working map.
+	 * from working map.
 	 * (this will allow continued access of data/index of
 	 * temporary file (zerolink count file truncated to zero-length)).
 	 */
@@ -3542,7 +3539,7 @@
 		goto getChild;
 
 	/*
-	 *      leaf page
+	 *	leaf page
 	 */
 	freed = 0;
 
@@ -3916,7 +3913,7 @@
 	}
 
 	/*
-	 *      internal page: go down to child page of current entry
+	 *	internal page: go down to child page of current entry
 	 */
       getChild:
 	/* save current parent entry for the child page */
@@ -3965,7 +3962,7 @@
 
 
 /*
- *      xtTruncate_pmap()
+ *	xtTruncate_pmap()
  *
  * function:
  *	Perform truncate to zero lenghth for deleted file, leaving the
@@ -3974,9 +3971,9 @@
  *	is committed to disk.
  *
  * parameter:
- *      tid_t		tid,
- *      struct inode	*ip,
- *      s64		committed_size)
+ *	tid_t		tid,
+ *	struct inode	*ip,
+ *	s64		committed_size)
  *
  * return: new committed size
  *
@@ -4050,7 +4047,7 @@
 	}
 
 	/*
-	 *      leaf page
+	 *	leaf page
 	 */
 
 	if (++locked_leaves > MAX_TRUNCATE_LEAVES) {
@@ -4062,7 +4059,7 @@
 		xoff = offsetXAD(xad);
 		xlen = lengthXAD(xad);
 		XT_PUTPAGE(mp);
-		return  (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
+		return (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
 	}
 	tlck = txLock(tid, ip, mp, tlckXTREE);
 	tlck->type = tlckXTREE | tlckFREE;
@@ -4099,8 +4096,7 @@
 		 */
 		tlck = txLock(tid, ip, mp, tlckXTREE);
 		xtlck = (struct xtlock *) & tlck->lock;
-		xtlck->hwm.offset =
-		    le16_to_cpu(p->header.nextindex) - 1;
+		xtlck->hwm.offset = le16_to_cpu(p->header.nextindex) - 1;
 		tlck->type = tlckXTREE | tlckFREE;
 
 		XT_PUTPAGE(mp);
@@ -4118,7 +4114,7 @@
 	else
 		index--;
 	/*
-	 *      internal page: go down to child page of current entry
+	 *	internal page: go down to child page of current entry
 	 */
       getChild:
 	/* save current parent entry for the child page */
diff --git a/fs/jfs/jfs_xtree.h b/fs/jfs/jfs_xtree.h
index 164f6f2..70815c8a3 100644
--- a/fs/jfs/jfs_xtree.h
+++ b/fs/jfs/jfs_xtree.h
@@ -19,14 +19,14 @@
 #define _H_JFS_XTREE
 
 /*
- *      jfs_xtree.h: extent allocation descriptor B+-tree manager
+ *	jfs_xtree.h: extent allocation descriptor B+-tree manager
  */
 
 #include "jfs_btree.h"
 
 
 /*
- *      extent allocation descriptor (xad)
+ *	extent allocation descriptor (xad)
  */
 typedef struct xad {
 	unsigned flag:8;	/* 1: flag */
@@ -38,30 +38,30 @@
 	__le32 addr2;		/* 4: address in unit of fsblksize */
 } xad_t;			/* (16) */
 
-#define MAXXLEN         ((1 << 24) - 1)
+#define MAXXLEN		((1 << 24) - 1)
 
-#define XTSLOTSIZE      16
-#define L2XTSLOTSIZE    4
+#define XTSLOTSIZE	16
+#define L2XTSLOTSIZE	4
 
 /* xad_t field construction */
 #define XADoffset(xad, offset64)\
 {\
-        (xad)->off1 = ((u64)offset64) >> 32;\
-        (xad)->off2 = __cpu_to_le32((offset64) & 0xffffffff);\
+	(xad)->off1 = ((u64)offset64) >> 32;\
+	(xad)->off2 = __cpu_to_le32((offset64) & 0xffffffff);\
 }
 #define XADaddress(xad, address64)\
 {\
-        (xad)->addr1 = ((u64)address64) >> 32;\
-        (xad)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\
+	(xad)->addr1 = ((u64)address64) >> 32;\
+	(xad)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\
 }
-#define XADlength(xad, length32)        (xad)->len = __cpu_to_le24(length32)
+#define XADlength(xad, length32)	(xad)->len = __cpu_to_le24(length32)
 
 /* xad_t field extraction */
 #define offsetXAD(xad)\
-        ( ((s64)((xad)->off1)) << 32 | __le32_to_cpu((xad)->off2))
+	( ((s64)((xad)->off1)) << 32 | __le32_to_cpu((xad)->off2))
 #define addressXAD(xad)\
-        ( ((s64)((xad)->addr1)) << 32 | __le32_to_cpu((xad)->addr2))
-#define lengthXAD(xad)  __le24_to_cpu((xad)->len)
+	( ((s64)((xad)->addr1)) << 32 | __le32_to_cpu((xad)->addr2))
+#define lengthXAD(xad)	__le24_to_cpu((xad)->len)
 
 /* xad list */
 struct xadlist {
@@ -71,22 +71,22 @@
 };
 
 /* xad_t flags */
-#define XAD_NEW         0x01	/* new */
-#define XAD_EXTENDED    0x02	/* extended */
-#define XAD_COMPRESSED  0x04	/* compressed with recorded length */
+#define XAD_NEW		0x01	/* new */
+#define XAD_EXTENDED	0x02	/* extended */
+#define XAD_COMPRESSED	0x04	/* compressed with recorded length */
 #define XAD_NOTRECORDED 0x08	/* allocated but not recorded */
-#define XAD_COW         0x10	/* copy-on-write */
+#define XAD_COW		0x10	/* copy-on-write */
 
 
 /* possible values for maxentry */
-#define XTROOTINITSLOT_DIR  6
-#define XTROOTINITSLOT  10
-#define XTROOTMAXSLOT   18
-#define XTPAGEMAXSLOT   256
-#define XTENTRYSTART    2
+#define XTROOTINITSLOT_DIR 6
+#define XTROOTINITSLOT	10
+#define XTROOTMAXSLOT	18
+#define XTPAGEMAXSLOT	256
+#define XTENTRYSTART	2
 
 /*
- *      xtree page:
+ *	xtree page:
  */
 typedef union {
 	struct xtheader {
@@ -106,7 +106,7 @@
 } xtpage_t;
 
 /*
- *      external declaration
+ *	external declaration
  */
 extern int xtLookup(struct inode *ip, s64 lstart, s64 llen,
 		    int *pflag, s64 * paddr, int *plen, int flag);
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 41c2047..25161c4 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -328,7 +328,7 @@
  *		dentry	- child directory dentry
  *
  * RETURN:	-EINVAL	- if name is . or ..
- *		-EINVAL  - if . or .. exist but are invalid.
+ *		-EINVAL - if . or .. exist but are invalid.
  *		errors from subroutines
  *
  * note:
@@ -517,7 +517,7 @@
 	inode_dec_link_count(ip);
 
 	/*
-	 *      commit zero link count object
+	 *	commit zero link count object
 	 */
 	if (ip->i_nlink == 0) {
 		assert(!test_cflag(COMMIT_Nolink, ip));
@@ -596,7 +596,7 @@
 /*
  * NAME:	commitZeroLink()
  *
- * FUNCTION:    for non-directory, called by jfs_remove(),
+ * FUNCTION:	for non-directory, called by jfs_remove(),
  *		truncate a regular file, directory or symbolic
  *		link to zero length. return 0 if type is not
  *		one of these.
@@ -676,7 +676,7 @@
 /*
  * NAME:	jfs_free_zero_link()
  *
- * FUNCTION:    for non-directory, called by iClose(),
+ * FUNCTION:	for non-directory, called by iClose(),
  *		free resources of a file from cache and WORKING map
  *		for a file previously committed with zero link count
  *		while associated with a pager object,
@@ -855,12 +855,12 @@
  * NAME:	jfs_symlink(dip, dentry, name)
  *
  * FUNCTION:	creates a symbolic link to <symlink> by name <name>
- *		        in directory <dip>
+ *			in directory <dip>
  *
- * PARAMETER:	dip	    - parent directory vnode
- *		        dentry	- dentry of symbolic link
- *		        name    - the path name of the existing object
- *			              that will be the source of the link
+ * PARAMETER:	dip	- parent directory vnode
+ *		dentry	- dentry of symbolic link
+ *		name	- the path name of the existing object
+ *			  that will be the source of the link
  *
  * RETURN:	errors from subroutines
  *
@@ -1052,9 +1052,9 @@
 
 
 /*
- * NAME:        jfs_rename
+ * NAME:	jfs_rename
  *
- * FUNCTION:    rename a file or directory
+ * FUNCTION:	rename a file or directory
  */
 static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	       struct inode *new_dir, struct dentry *new_dentry)
@@ -1331,9 +1331,9 @@
 
 
 /*
- * NAME:        jfs_mknod
+ * NAME:	jfs_mknod
  *
- * FUNCTION:    Create a special file (device)
+ * FUNCTION:	Create a special file (device)
  */
 static int jfs_mknod(struct inode *dir, struct dentry *dentry,
 		int mode, dev_t rdev)
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index 79d625f..71984ee 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -29,17 +29,17 @@
 #include "jfs_txnmgr.h"
 #include "jfs_debug.h"
 
-#define BITSPERPAGE     (PSIZE << 3)
-#define L2MEGABYTE      20
-#define MEGABYTE        (1 << L2MEGABYTE)
-#define MEGABYTE32     (MEGABYTE << 5)
+#define BITSPERPAGE	(PSIZE << 3)
+#define L2MEGABYTE	20
+#define MEGABYTE	(1 << L2MEGABYTE)
+#define MEGABYTE32	(MEGABYTE << 5)
 
 /* convert block number to bmap file page number */
 #define BLKTODMAPN(b)\
-        (((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1)
+	(((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1)
 
 /*
- *      jfs_extendfs()
+ *	jfs_extendfs()
  *
  * function: extend file system;
  *
@@ -48,9 +48,9 @@
  *                                   workspace  space
  *
  * input:
- *      new LVSize: in LV blocks (required)
- *      new LogSize: in LV blocks (optional)
- *      new FSSize: in LV blocks (optional)
+ *	new LVSize: in LV blocks (required)
+ *	new LogSize: in LV blocks (optional)
+ *	new FSSize: in LV blocks (optional)
  *
  * new configuration:
  * 1. set new LogSize as specified or default from new LVSize;
@@ -125,8 +125,8 @@
 	}
 
 	/*
-	 *      reconfigure LV spaces
-	 *      ---------------------
+	 *	reconfigure LV spaces
+	 *	---------------------
 	 *
 	 * validate new size, or, if not specified, determine new size
 	 */
@@ -198,7 +198,7 @@
 		log_formatted = 1;
 	}
 	/*
-	 *      quiesce file system
+	 *	quiesce file system
 	 *
 	 * (prepare to move the inline log and to prevent map update)
 	 *
@@ -270,8 +270,8 @@
 	}
 
 	/*
-	 *      extend block allocation map
-	 *      ---------------------------
+	 *	extend block allocation map
+	 *	---------------------------
 	 *
 	 * extendfs() for new extension, retry after crash recovery;
 	 *
@@ -283,7 +283,7 @@
 	 *  s_size: aggregate size in physical blocks;
 	 */
 	/*
-	 *      compute the new block allocation map configuration
+	 *	compute the new block allocation map configuration
 	 *
 	 * map dinode:
 	 *  di_size: map file size in byte;
@@ -301,7 +301,7 @@
 	newNpages = BLKTODMAPN(t64) + 1;
 
 	/*
-	 *      extend map from current map (WITHOUT growing mapfile)
+	 *	extend map from current map (WITHOUT growing mapfile)
 	 *
 	 * map new extension with unmapped part of the last partial
 	 * dmap page, if applicable, and extra page(s) allocated
@@ -341,8 +341,8 @@
 	XSize -= nblocks;
 
 	/*
-	 *      grow map file to cover remaining extension
-	 *      and/or one extra dmap page for next extendfs();
+	 *	grow map file to cover remaining extension
+	 *	and/or one extra dmap page for next extendfs();
 	 *
 	 * allocate new map pages and its backing blocks, and
 	 * update map file xtree
@@ -422,8 +422,8 @@
 	dbFinalizeBmap(ipbmap);
 
 	/*
-	 *      update inode allocation map
-	 *      ---------------------------
+	 *	update inode allocation map
+	 *	---------------------------
 	 *
 	 * move iag lists from old to new iag;
 	 * agstart field is not updated for logredo() to reconstruct
@@ -442,8 +442,8 @@
 	}
 
 	/*
-	 *      finalize
-	 *      --------
+	 *	finalize
+	 *	--------
 	 *
 	 * extension is committed when on-disk super block is
 	 * updated with new descriptors: logredo will recover
@@ -480,7 +480,7 @@
 	diFreeSpecial(ipbmap2);
 
 	/*
-	 *      update superblock
+	 *	update superblock
 	 */
 	if ((rc = readSuper(sb, &bh)))
 		goto error_out;
@@ -530,7 +530,7 @@
 
       resume:
 	/*
-	 *      resume file system transactions
+	 *	resume file system transactions
 	 */
 	txResume(sb);
 
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index b753ba2..b2375f0 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -63,9 +63,9 @@
  *
  *   On-disk:
  *
- *     FEALISTs are stored on disk using blocks allocated by dbAlloc() and
- *     written directly. An EA list may be in-lined in the inode if there is
- *     sufficient room available.
+ *	FEALISTs are stored on disk using blocks allocated by dbAlloc() and
+ *	written directly. An EA list may be in-lined in the inode if there is
+ *	sufficient room available.
  */
 
 struct ea_buffer {
@@ -590,7 +590,8 @@
       size_check:
 	if (EALIST_SIZE(ea_buf->xattr) != ea_size) {
 		printk(KERN_ERR "ea_get: invalid extended attribute\n");
-		dump_mem("xattr", ea_buf->xattr, ea_size);
+		print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1,
+				     ea_buf->xattr, ea_size, 1);
 		ea_release(inode, ea_buf);
 		rc = -EIO;
 		goto clean_up;
diff --git a/fs/minix/file.c b/fs/minix/file.c
index f92baa1..17765f6 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -23,7 +23,7 @@
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.fsync		= minix_sync_file,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 const struct inode_operations minix_file_inode_operations = {
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 9eb8eb4..8689b73 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -41,7 +41,9 @@
 static int nfs_file_release(struct inode *, struct file *);
 static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
 static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
-static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
+static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos,
+					struct pipe_inode_info *pipe,
+					size_t count, unsigned int flags);
 static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
 				unsigned long nr_segs, loff_t pos);
 static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
@@ -65,7 +67,7 @@
 	.fsync		= nfs_fsync,
 	.lock		= nfs_lock,
 	.flock		= nfs_flock,
-	.sendfile	= nfs_file_sendfile,
+	.splice_read	= nfs_file_splice_read,
 	.check_flags	= nfs_check_flags,
 };
 
@@ -224,20 +226,21 @@
 }
 
 static ssize_t
-nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
-		read_actor_t actor, void *target)
+nfs_file_splice_read(struct file *filp, loff_t *ppos,
+		     struct pipe_inode_info *pipe, size_t count,
+		     unsigned int flags)
 {
 	struct dentry *dentry = filp->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
 	ssize_t res;
 
-	dfprintk(VFS, "nfs: sendfile(%s/%s, %lu@%Lu)\n",
+	dfprintk(VFS, "nfs: splice_read(%s/%s, %lu@%Lu)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		(unsigned long) count, (unsigned long long) *ppos);
 
 	res = nfs_revalidate_mapping(inode, filp->f_mapping);
 	if (!res)
-		res = generic_file_sendfile(filp, ppos, count, actor, target);
+		res = generic_file_splice_read(filp, ppos, pipe, count, flags);
 	return res;
 }
 
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7e6aa24..8604e35 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -23,7 +23,7 @@
 #include <linux/file.h>
 #include <linux/mount.h>
 #include <linux/major.h>
-#include <linux/ext2_fs.h>
+#include <linux/splice.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
@@ -801,26 +801,32 @@
 }
 
 /*
- * Grab and keep cached pages assosiated with a file in the svc_rqst
- * so that they can be passed to the netowork sendmsg/sendpage routines
- * directrly. They will be released after the sending has completed.
+ * Grab and keep cached pages associated with a file in the svc_rqst
+ * so that they can be passed to the network sendmsg/sendpage routines
+ * directly. They will be released after the sending has completed.
  */
 static int
-nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
+nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+		  struct splice_desc *sd)
 {
-	unsigned long count = desc->count;
-	struct svc_rqst *rqstp = desc->arg.data;
+	struct svc_rqst *rqstp = sd->u.data;
 	struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
+	struct page *page = buf->page;
+	size_t size;
+	int ret;
 
-	if (size > count)
-		size = count;
+	ret = buf->ops->confirm(pipe, buf);
+	if (unlikely(ret))
+		return ret;
+
+	size = sd->len;
 
 	if (rqstp->rq_res.page_len == 0) {
 		get_page(page);
 		put_page(*pp);
 		*pp = page;
 		rqstp->rq_resused++;
-		rqstp->rq_res.page_base = offset;
+		rqstp->rq_res.page_base = buf->offset;
 		rqstp->rq_res.page_len = size;
 	} else if (page != pp[-1]) {
 		get_page(page);
@@ -832,11 +838,15 @@
 	} else
 		rqstp->rq_res.page_len += size;
 
-	desc->count = count - size;
-	desc->written += size;
 	return size;
 }
 
+static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe,
+				    struct splice_desc *sd)
+{
+	return __splice_from_pipe(pipe, sd, nfsd_splice_actor);
+}
+
 static __be32
 nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
               loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
@@ -861,10 +871,15 @@
 	if (ra && ra->p_set)
 		file->f_ra = ra->p_ra;
 
-	if (file->f_op->sendfile && rqstp->rq_sendfile_ok) {
-		rqstp->rq_resused = 1;
-		host_err = file->f_op->sendfile(file, &offset, *count,
-						 nfsd_read_actor, rqstp);
+	if (file->f_op->splice_read && rqstp->rq_splice_ok) {
+		struct splice_desc sd = {
+			.len		= 0,
+			.total_len	= *count,
+			.pos		= offset,
+			.u.data		= rqstp,
+		};
+
+		host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor);
 	} else {
 		oldfs = get_fs();
 		set_fs(KERNEL_DS);
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 7ed5639..ffcc504 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2276,7 +2276,7 @@
 						    mounted filesystem. */
 	.mmap		= generic_file_mmap,	 /* Mmap file. */
 	.open		= ntfs_file_open,	 /* Open file. */
-	.sendfile	= generic_file_sendfile, /* Zero-copy data send with
+	.splice_read	= generic_file_splice_read /* Zero-copy data send with
 						    the data source being on
 						    the ntfs partition.  We do
 						    not need to care about the
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index ac6c964..4979b66 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -31,7 +31,7 @@
 #include <linux/pagemap.h>
 #include <linux/uio.h>
 #include <linux/sched.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
 #include <linux/mount.h>
 #include <linux/writeback.h>
 
@@ -1583,7 +1583,7 @@
 	ssize_t copied = 0;
 	struct ocfs2_splice_write_priv sp;
 
-	ret = buf->ops->pin(pipe, buf);
+	ret = buf->ops->confirm(pipe, buf);
 	if (ret)
 		goto out;
 
@@ -1604,7 +1604,7 @@
 		 * might enter ocfs2_buffered_write_cluster() more
 		 * than once, so keep track of our progress here.
 		 */
-		copied = ocfs2_buffered_write_cluster(sd->file,
+		copied = ocfs2_buffered_write_cluster(sd->u.file,
 						      (loff_t)sd->pos + total,
 						      count,
 						      ocfs2_map_and_write_splice_data,
@@ -1636,9 +1636,14 @@
 	int ret, err;
 	struct address_space *mapping = out->f_mapping;
 	struct inode *inode = mapping->host;
+	struct splice_desc sd = {
+		.total_len = len,
+		.flags = flags,
+		.pos = *ppos,
+		.u.file = out,
+	};
 
-	ret = __splice_from_pipe(pipe, out, ppos, len, flags,
-				 ocfs2_splice_write_actor);
+	ret = __splice_from_pipe(pipe, &sd, ocfs2_splice_write_actor);
 	if (ret > 0) {
 		*ppos += ret;
 
@@ -1817,7 +1822,6 @@
 const struct file_operations ocfs2_fops = {
 	.read		= do_sync_read,
 	.write		= do_sync_write,
-	.sendfile	= generic_file_sendfile,
 	.mmap		= ocfs2_mmap,
 	.fsync		= ocfs2_sync_file,
 	.release	= ocfs2_file_release,
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c
index 9f7ad42..1e064c4 100644
--- a/fs/partitions/ibm.c
+++ b/fs/partitions/ibm.c
@@ -45,7 +45,7 @@
 {
 	int blocksize, offset, size,res;
 	loff_t i_size;
-	dasd_information_t *info;
+	dasd_information2_t *info;
 	struct hd_geometry *geo;
 	char type[5] = {0,};
 	char name[7] = {0,};
@@ -64,14 +64,17 @@
 	if (i_size == 0)
 		goto out_exit;
 
-	if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL)
+	info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL);
+	if (info == NULL)
 		goto out_exit;
-	if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
+	geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL);
+	if (geo == NULL)
 		goto out_nogeo;
-	if ((label = kmalloc(sizeof(union label_t), GFP_KERNEL)) == NULL)
+	label = kmalloc(sizeof(union label_t), GFP_KERNEL);
+	if (label == NULL)
 		goto out_nolab;
 
-	if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 ||
+	if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 ||
 	    ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
 		goto out_freeall;
 
@@ -96,84 +99,108 @@
 	res = 1;
 
 	/*
-	 * Three different types: CMS1, VOL1 and LNX1/unlabeled
+	 * Three different formats: LDL, CDL and unformated disk
+	 *
+	 * identified by info->format
+	 *
+	 * unformated disks we do not have to care about
 	 */
-	if (strncmp(type, "CMS1", 4) == 0) {
-		/*
-		 * VM style CMS1 labeled disk
-		 */
-		if (label->cms.disk_offset != 0) {
-			printk("CMS1/%8s(MDSK):", name);
-			/* disk is reserved minidisk */
-			blocksize = label->cms.block_size;
-			offset = label->cms.disk_offset;
-			size = (label->cms.block_count - 1) * (blocksize >> 9);
+	if (info->format == DASD_FORMAT_LDL) {
+		if (strncmp(type, "CMS1", 4) == 0) {
+			/*
+			 * VM style CMS1 labeled disk
+			 */
+			if (label->cms.disk_offset != 0) {
+				printk("CMS1/%8s(MDSK):", name);
+				/* disk is reserved minidisk */
+				blocksize = label->cms.block_size;
+				offset = label->cms.disk_offset;
+				size = (label->cms.block_count - 1)
+					* (blocksize >> 9);
+			} else {
+				printk("CMS1/%8s:", name);
+				offset = (info->label_block + 1);
+				size = i_size >> 9;
+			}
 		} else {
-			printk("CMS1/%8s:", name);
+			/*
+			 * Old style LNX1 or unlabeled disk
+			 */
+			if (strncmp(type, "LNX1", 4) == 0)
+				printk ("LNX1/%8s:", name);
+			else
+				printk("(nonl)");
 			offset = (info->label_block + 1);
 			size = i_size >> 9;
 		}
 		put_partition(state, 1, offset*(blocksize >> 9),
-				 size-offset*(blocksize >> 9));
-	} else if ((strncmp(type, "VOL1", 4) == 0) &&
-		(!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) {
+				      size-offset*(blocksize >> 9));
+	} else if (info->format == DASD_FORMAT_CDL) {
 		/*
-		 * New style VOL1 labeled disk
+		 * New style CDL formatted disk
 		 */
 		unsigned int blk;
 		int counter;
 
-		printk("VOL1/%8s:", name);
+		/*
+		 * check if VOL1 label is available
+		 * if not, something is wrong, skipping partition detection
+		 */
+		if (strncmp(type, "VOL1",  4) == 0) {
+			printk("VOL1/%8s:", name);
+			/*
+			 * get block number and read then go through format1
+			 * labels
+			 */
+			blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
+			counter = 0;
+			data = read_dev_sector(bdev, blk * (blocksize/512),
+					       &sect);
+			while (data != NULL) {
+				struct vtoc_format1_label f1;
 
-		/* get block number and read then go through format1 labels */
-		blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
-		counter = 0;
-		while ((data = read_dev_sector(bdev, blk*(blocksize/512),
-					       &sect)) != NULL) {
-			struct vtoc_format1_label f1;
+				memcpy(&f1, data,
+				       sizeof(struct vtoc_format1_label));
+				put_dev_sector(sect);
 
-			memcpy(&f1, data, sizeof(struct vtoc_format1_label));
-			put_dev_sector(sect);
+				/* skip FMT4 / FMT5 / FMT7 labels */
+				if (f1.DS1FMTID == _ascebc['4']
+				    || f1.DS1FMTID == _ascebc['5']
+				    || f1.DS1FMTID == _ascebc['7']) {
+					blk++;
+					data = read_dev_sector(bdev, blk *
+							       (blocksize/512),
+								&sect);
+					continue;
+				}
 
-			/* skip FMT4 / FMT5 / FMT7 labels */
-			if (f1.DS1FMTID == _ascebc['4']
-			    || f1.DS1FMTID == _ascebc['5']
-			    || f1.DS1FMTID == _ascebc['7']) {
-			        blk++;
-				continue;
+				/* only FMT1 valid at this point */
+				if (f1.DS1FMTID != _ascebc['1'])
+					break;
+
+				/* OK, we got valid partition data */
+				offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
+				size  = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
+					offset + geo->sectors;
+				if (counter >= state->limit)
+					break;
+				put_partition(state, counter + 1,
+					      offset * (blocksize >> 9),
+					      size * (blocksize >> 9));
+				counter++;
+				blk++;
+				data = read_dev_sector(bdev,
+						       blk * (blocksize/512),
+						       &sect);
 			}
 
-			/* only FMT1 valid at this point */
-			if (f1.DS1FMTID != _ascebc['1'])
-				break;
+			if (!data)
+				/* Are we not supposed to report this ? */
+				goto out_readerr;
+		} else
+			printk(KERN_WARNING "Warning, expected Label VOL1 not "
+			       "found, treating as CDL formated Disk");
 
-			/* OK, we got valid partition data */
-		        offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
-			size  = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
-				offset + geo->sectors;
-			if (counter >= state->limit)
-				break;
-			put_partition(state, counter + 1,
-				      offset * (blocksize >> 9),
-				      size * (blocksize >> 9));
-			counter++;
-			blk++;
-		}
-		if (!data)
-		/* Are we not supposed to report this ? */
-			goto out_readerr;
-	} else {
-		/*
-		 * Old style LNX1 or unlabeled disk
-		 */
-		if (strncmp(type, "LNX1", 4) == 0)
-			printk ("LNX1/%8s:", name);
-		else
-			printk("(nonl)/%8s:", name);
-		offset = (info->label_block + 1);
-		size = i_size >> 9;
-		put_partition(state, 1, offset*(blocksize >> 9),
-			      size-offset*(blocksize >> 9));
 	}
 
 	printk("\n");
diff --git a/fs/pipe.c b/fs/pipe.c
index 3a89592..d007830 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -164,6 +164,20 @@
 		page_cache_release(page);
 }
 
+/**
+ * generic_pipe_buf_map - virtually map a pipe buffer
+ * @pipe:	the pipe that the buffer belongs to
+ * @buf:	the buffer that should be mapped
+ * @atomic:	whether to use an atomic map
+ *
+ * Description:
+ *	This function returns a kernel virtual address mapping for the
+ *	passed in @pipe_buffer. If @atomic is set, an atomic map is provided
+ *	and the caller has to be careful not to fault before calling
+ *	the unmap function.
+ *
+ *	Note that this function occupies KM_USER0 if @atomic != 0.
+ */
 void *generic_pipe_buf_map(struct pipe_inode_info *pipe,
 			   struct pipe_buffer *buf, int atomic)
 {
@@ -175,6 +189,15 @@
 	return kmap(buf->page);
 }
 
+/**
+ * generic_pipe_buf_unmap - unmap a previously mapped pipe buffer
+ * @pipe:	the pipe that the buffer belongs to
+ * @buf:	the buffer that should be unmapped
+ * @map_data:	the data that the mapping function returned
+ *
+ * Description:
+ *	This function undoes the mapping that ->map() provided.
+ */
 void generic_pipe_buf_unmap(struct pipe_inode_info *pipe,
 			    struct pipe_buffer *buf, void *map_data)
 {
@@ -185,11 +208,28 @@
 		kunmap(buf->page);
 }
 
+/**
+ * generic_pipe_buf_steal - attempt to take ownership of a @pipe_buffer
+ * @pipe:	the pipe that the buffer belongs to
+ * @buf:	the buffer to attempt to steal
+ *
+ * Description:
+ *	This function attempts to steal the @struct page attached to
+ *	@buf. If successful, this function returns 0 and returns with
+ *	the page locked. The caller may then reuse the page for whatever
+ *	he wishes, the typical use is insertion into a different file
+ *	page cache.
+ */
 int generic_pipe_buf_steal(struct pipe_inode_info *pipe,
 			   struct pipe_buffer *buf)
 {
 	struct page *page = buf->page;
 
+	/*
+	 * A reference of one is golden, that means that the owner of this
+	 * page is the only one holding a reference to it. lock the page
+	 * and return OK.
+	 */
 	if (page_count(page) == 1) {
 		lock_page(page);
 		return 0;
@@ -198,12 +238,32 @@
 	return 1;
 }
 
-void generic_pipe_buf_get(struct pipe_inode_info *info, struct pipe_buffer *buf)
+/**
+ * generic_pipe_buf_get - get a reference to a @struct pipe_buffer
+ * @pipe:	the pipe that the buffer belongs to
+ * @buf:	the buffer to get a reference to
+ *
+ * Description:
+ *	This function grabs an extra reference to @buf. It's used in
+ *	in the tee() system call, when we duplicate the buffers in one
+ *	pipe into another.
+ */
+void generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
 {
 	page_cache_get(buf->page);
 }
 
-int generic_pipe_buf_pin(struct pipe_inode_info *info, struct pipe_buffer *buf)
+/**
+ * generic_pipe_buf_confirm - verify contents of the pipe buffer
+ * @pipe:	the pipe that the buffer belongs to
+ * @buf:	the buffer to confirm
+ *
+ * Description:
+ *	This function does nothing, because the generic pipe code uses
+ *	pages that are always good when inserted into the pipe.
+ */
+int generic_pipe_buf_confirm(struct pipe_inode_info *info,
+			     struct pipe_buffer *buf)
 {
 	return 0;
 }
@@ -212,7 +272,7 @@
 	.can_merge = 1,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
-	.pin = generic_pipe_buf_pin,
+	.confirm = generic_pipe_buf_confirm,
 	.release = anon_pipe_buf_release,
 	.steal = generic_pipe_buf_steal,
 	.get = generic_pipe_buf_get,
@@ -252,7 +312,7 @@
 			if (chars > total_len)
 				chars = total_len;
 
-			error = ops->pin(pipe, buf);
+			error = ops->confirm(pipe, buf);
 			if (error) {
 				if (!ret)
 					error = ret;
@@ -373,7 +433,7 @@
 			int error, atomic = 1;
 			void *addr;
 
-			error = ops->pin(pipe, buf);
+			error = ops->confirm(pipe, buf);
 			if (error)
 				goto out;
 
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 74f30e0..98e78e2 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -165,7 +165,6 @@
 	rcu_read_lock();
 	buffer += sprintf(buffer,
 		"State:\t%s\n"
-		"SleepAVG:\t%lu%%\n"
 		"Tgid:\t%d\n"
 		"Pid:\t%d\n"
 		"PPid:\t%d\n"
@@ -173,7 +172,6 @@
 		"Uid:\t%d\t%d\t%d\t%d\n"
 		"Gid:\t%d\t%d\t%d\t%d\n",
 		get_task_state(p),
-		(p->sleep_avg/1024)*100/(1020000000/1024),
 	       	p->tgid, p->pid,
 	       	pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
 		pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
@@ -312,6 +310,41 @@
 	return buffer - orig;
 }
 
+static clock_t task_utime(struct task_struct *p)
+{
+	clock_t utime = cputime_to_clock_t(p->utime),
+		total = utime + cputime_to_clock_t(p->stime);
+	u64 temp;
+
+	/*
+	 * Use CFS's precise accounting:
+	 */
+	temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime);
+
+	if (total) {
+		temp *= utime;
+		do_div(temp, total);
+	}
+	utime = (clock_t)temp;
+
+	return utime;
+}
+
+static clock_t task_stime(struct task_struct *p)
+{
+	clock_t stime = cputime_to_clock_t(p->stime);
+
+	/*
+	 * Use CFS's precise accounting. (we subtract utime from
+	 * the total, to make sure the total observed by userspace
+	 * grows monotonically - apps rely on that):
+	 */
+	stime = nsec_to_clock_t(p->se.sum_exec_runtime) - task_utime(p);
+
+	return stime;
+}
+
+
 static int do_task_stat(struct task_struct *task, char * buffer, int whole)
 {
 	unsigned long vsize, eip, esp, wchan = ~0UL;
@@ -326,7 +359,8 @@
 	unsigned long long start_time;
 	unsigned long cmin_flt = 0, cmaj_flt = 0;
 	unsigned long  min_flt = 0,  maj_flt = 0;
-	cputime_t cutime, cstime, utime, stime;
+	cputime_t cutime, cstime;
+	clock_t utime, stime;
 	unsigned long rsslim = 0;
 	char tcomm[sizeof(task->comm)];
 	unsigned long flags;
@@ -344,7 +378,8 @@
 
 	sigemptyset(&sigign);
 	sigemptyset(&sigcatch);
-	cutime = cstime = utime = stime = cputime_zero;
+	cutime = cstime = cputime_zero;
+	utime = stime = 0;
 
 	rcu_read_lock();
 	if (lock_task_sighand(task, &flags)) {
@@ -370,15 +405,15 @@
 			do {
 				min_flt += t->min_flt;
 				maj_flt += t->maj_flt;
-				utime = cputime_add(utime, t->utime);
-				stime = cputime_add(stime, t->stime);
+				utime += task_utime(t);
+				stime += task_stime(t);
 				t = next_thread(t);
 			} while (t != task);
 
 			min_flt += sig->min_flt;
 			maj_flt += sig->maj_flt;
-			utime = cputime_add(utime, sig->utime);
-			stime = cputime_add(stime, sig->stime);
+			utime += cputime_to_clock_t(sig->utime);
+			stime += cputime_to_clock_t(sig->stime);
 		}
 
 		sid = signal_session(sig);
@@ -394,8 +429,8 @@
 	if (!whole) {
 		min_flt = task->min_flt;
 		maj_flt = task->maj_flt;
-		utime = task->utime;
-		stime = task->stime;
+		utime = task_utime(task);
+		stime = task_stime(task);
 	}
 
 	/* scale priority and nice values from timeslices to -20..20 */
@@ -426,8 +461,8 @@
 		cmin_flt,
 		maj_flt,
 		cmaj_flt,
-		cputime_to_clock_t(utime),
-		cputime_to_clock_t(stime),
+		utime,
+		stime,
 		cputime_to_clock_t(cutime),
 		cputime_to_clock_t(cstime),
 		priority,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a5fa1fd..46ea5d5 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -296,7 +296,7 @@
  */
 static int proc_pid_schedstat(struct task_struct *task, char *buffer)
 {
-	return sprintf(buffer, "%lu %lu %lu\n",
+	return sprintf(buffer, "%llu %llu %lu\n",
 			task->sched_info.cpu_time,
 			task->sched_info.run_delay,
 			task->sched_info.pcnt);
@@ -929,6 +929,69 @@
 };
 #endif
 
+#ifdef CONFIG_SCHED_DEBUG
+/*
+ * Print out various scheduling related per-task fields:
+ */
+static int sched_show(struct seq_file *m, void *v)
+{
+	struct inode *inode = m->private;
+	struct task_struct *p;
+
+	WARN_ON(!inode);
+
+	p = get_proc_task(inode);
+	if (!p)
+		return -ESRCH;
+	proc_sched_show_task(p, m);
+
+	put_task_struct(p);
+
+	return 0;
+}
+
+static ssize_t
+sched_write(struct file *file, const char __user *buf,
+	    size_t count, loff_t *offset)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct task_struct *p;
+
+	WARN_ON(!inode);
+
+	p = get_proc_task(inode);
+	if (!p)
+		return -ESRCH;
+	proc_sched_set_task(p);
+
+	put_task_struct(p);
+
+	return count;
+}
+
+static int sched_open(struct inode *inode, struct file *filp)
+{
+	int ret;
+
+	ret = single_open(filp, sched_show, NULL);
+	if (!ret) {
+		struct seq_file *m = filp->private_data;
+
+		m->private = inode;
+	}
+	return ret;
+}
+
+static const struct file_operations proc_pid_sched_operations = {
+	.open		= sched_open,
+	.read		= seq_read,
+	.write		= sched_write,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+#endif
+
 static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
@@ -1963,6 +2026,9 @@
 	INF("environ",    S_IRUSR, pid_environ),
 	INF("auxv",       S_IRUSR, pid_auxv),
 	INF("status",     S_IRUGO, pid_status),
+#ifdef CONFIG_SCHED_DEBUG
+	REG("sched",      S_IRUGO|S_IWUSR, pid_sched),
+#endif
 	INF("cmdline",    S_IRUGO, pid_cmdline),
 	INF("stat",       S_IRUGO, tgid_stat),
 	INF("statm",      S_IRUGO, pid_statm),
@@ -2247,6 +2313,9 @@
 	INF("environ",   S_IRUSR, pid_environ),
 	INF("auxv",      S_IRUSR, pid_auxv),
 	INF("status",    S_IRUGO, pid_status),
+#ifdef CONFIG_SCHED_DEBUG
+	REG("sched",     S_IRUGO|S_IWUSR, pid_sched),
+#endif
 	INF("cmdline",   S_IRUGO, pid_cmdline),
 	INF("stat",      S_IRUGO, tid_stat),
 	INF("statm",     S_IRUGO, pid_statm),
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c
index 4464998..867f42b 100644
--- a/fs/qnx4/file.c
+++ b/fs/qnx4/file.c
@@ -25,7 +25,7 @@
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
 	.mmap		= generic_file_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 #ifdef CONFIG_QNX4FS_RW
 	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 2f14774..97bdc0b 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -41,7 +41,7 @@
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.fsync		= simple_sync_file,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 	.llseek		= generic_file_llseek,
 };
 
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index 5d258c4..cad2b7a 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -42,7 +42,7 @@
 	.write			= do_sync_write,
 	.aio_write		= generic_file_aio_write,
 	.fsync			= simple_sync_file,
-	.sendfile		= generic_file_sendfile,
+	.splice_read		= generic_file_splice_read,
 	.llseek			= generic_file_llseek,
 };
 
diff --git a/fs/read_write.c b/fs/read_write.c
index 4d03008..507ddff 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/syscalls.h>
 #include <linux/pagemap.h>
+#include <linux/splice.h>
 #include "read_write.h"
 
 #include <asm/uaccess.h>
@@ -25,7 +26,7 @@
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
 	.mmap		= generic_file_readonly_mmap,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 EXPORT_SYMBOL(generic_ro_fops);
@@ -708,7 +709,7 @@
 	struct inode * in_inode, * out_inode;
 	loff_t pos;
 	ssize_t retval;
-	int fput_needed_in, fput_needed_out;
+	int fput_needed_in, fput_needed_out, fl;
 
 	/*
 	 * Get input file, and verify that it is ok..
@@ -723,7 +724,7 @@
 	in_inode = in_file->f_path.dentry->d_inode;
 	if (!in_inode)
 		goto fput_in;
-	if (!in_file->f_op || !in_file->f_op->sendfile)
+	if (!in_file->f_op || !in_file->f_op->splice_read)
 		goto fput_in;
 	retval = -ESPIPE;
 	if (!ppos)
@@ -776,7 +777,18 @@
 		count = max - pos;
 	}
 
-	retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file);
+	fl = 0;
+#if 0
+	/*
+	 * We need to debate whether we can enable this or not. The
+	 * man page documents EAGAIN return for the output at least,
+	 * and the application is arguably buggy if it doesn't expect
+	 * EAGAIN on a non-blocking file descriptor.
+	 */
+	if (in_file->f_flags & O_NONBLOCK)
+		fl = SPLICE_F_NONBLOCK;
+#endif
+	retval = do_splice_direct(in_file, ppos, out_file, count, fl);
 
 	if (retval > 0) {
 		add_rchar(current, retval);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 9e451a6..30eebfb 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1531,7 +1531,6 @@
 	.open = generic_file_open,
 	.release = reiserfs_file_release,
 	.fsync = reiserfs_sync_file,
-	.sendfile = generic_file_sendfile,
 	.aio_read = generic_file_aio_read,
 	.aio_write = generic_file_aio_write,
 	.splice_read = generic_file_splice_read,
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 0ac22af..49194a4 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -447,3 +447,37 @@
 	return -1;
 }
 EXPORT_SYMBOL(seq_puts);
+
+struct list_head *seq_list_start(struct list_head *head, loff_t pos)
+{
+	struct list_head *lh;
+
+	list_for_each(lh, head)
+		if (pos-- == 0)
+			return lh;
+
+	return NULL;
+}
+
+EXPORT_SYMBOL(seq_list_start);
+
+struct list_head *seq_list_start_head(struct list_head *head, loff_t pos)
+{
+	if (!pos)
+		return head;
+
+	return seq_list_start(head, pos - 1);
+}
+
+EXPORT_SYMBOL(seq_list_start_head);
+
+struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos)
+{
+	struct list_head *lh;
+
+	lh = ((struct list_head *)v)->next;
+	++*ppos;
+	return lh == head ? NULL : lh;
+}
+
+EXPORT_SYMBOL(seq_list_next);
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index aea3f8a..c5d78a7 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -262,8 +262,9 @@
 }
 
 static ssize_t
-smb_file_sendfile(struct file *file, loff_t *ppos,
-		  size_t count, read_actor_t actor, void *target)
+smb_file_splice_read(struct file *file, loff_t *ppos,
+		     struct pipe_inode_info *pipe, size_t count,
+		     unsigned int flags)
 {
 	struct dentry *dentry = file->f_path.dentry;
 	ssize_t status;
@@ -277,7 +278,7 @@
 			 DENTRY_PATH(dentry), status);
 		goto out;
 	}
-	status = generic_file_sendfile(file, ppos, count, actor, target);
+	status = generic_file_splice_read(file, ppos, pipe, count, flags);
 out:
 	return status;
 }
@@ -416,7 +417,7 @@
 	.open		= smb_file_open,
 	.release	= smb_file_release,
 	.fsync		= smb_fsync,
-	.sendfile	= smb_file_sendfile,
+	.splice_read	= smb_file_splice_read,
 };
 
 const struct inode_operations smb_file_inode_operations =
diff --git a/fs/splice.c b/fs/splice.c
index e7d7080..ed2ce99 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -20,7 +20,7 @@
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/pagemap.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
 #include <linux/mm_inline.h>
 #include <linux/swap.h>
 #include <linux/writeback.h>
@@ -29,22 +29,6 @@
 #include <linux/syscalls.h>
 #include <linux/uio.h>
 
-struct partial_page {
-	unsigned int offset;
-	unsigned int len;
-};
-
-/*
- * Passed to splice_to_pipe
- */
-struct splice_pipe_desc {
-	struct page **pages;		/* page map */
-	struct partial_page *partial;	/* pages[] may not be contig */
-	int nr_pages;			/* number of pages in map */
-	unsigned int flags;		/* splice flags */
-	const struct pipe_buf_operations *ops;/* ops associated with output pipe */
-};
-
 /*
  * Attempt to steal a page from a pipe buffer. This should perhaps go into
  * a vm helper function, it's already simplified quite a bit by the
@@ -101,8 +85,12 @@
 	buf->flags &= ~PIPE_BUF_FLAG_LRU;
 }
 
-static int page_cache_pipe_buf_pin(struct pipe_inode_info *pipe,
-				   struct pipe_buffer *buf)
+/*
+ * Check whether the contents of buf is OK to access. Since the content
+ * is a page cache page, IO may be in flight.
+ */
+static int page_cache_pipe_buf_confirm(struct pipe_inode_info *pipe,
+				       struct pipe_buffer *buf)
 {
 	struct page *page = buf->page;
 	int err;
@@ -143,7 +131,7 @@
 	.can_merge = 0,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
-	.pin = page_cache_pipe_buf_pin,
+	.confirm = page_cache_pipe_buf_confirm,
 	.release = page_cache_pipe_buf_release,
 	.steal = page_cache_pipe_buf_steal,
 	.get = generic_pipe_buf_get,
@@ -163,18 +151,25 @@
 	.can_merge = 0,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
-	.pin = generic_pipe_buf_pin,
+	.confirm = generic_pipe_buf_confirm,
 	.release = page_cache_pipe_buf_release,
 	.steal = user_page_pipe_buf_steal,
 	.get = generic_pipe_buf_get,
 };
 
-/*
- * Pipe output worker. This sets up our pipe format with the page cache
- * pipe buffer operations. Otherwise very similar to the regular pipe_writev().
+/**
+ * splice_to_pipe - fill passed data into a pipe
+ * @pipe:	pipe to fill
+ * @spd:	data to fill
+ *
+ * Description:
+ *    @spd contains a map of pages and len/offset tupples, a long with
+ *    the struct pipe_buf_operations associated with these pages. This
+ *    function will link that data to the pipe.
+ *
  */
-static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
-			      struct splice_pipe_desc *spd)
+ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
+		       struct splice_pipe_desc *spd)
 {
 	unsigned int spd_pages = spd->nr_pages;
 	int ret, do_wakeup, page_nr;
@@ -201,6 +196,7 @@
 			buf->page = spd->pages[page_nr];
 			buf->offset = spd->partial[page_nr].offset;
 			buf->len = spd->partial[page_nr].len;
+			buf->private = spd->partial[page_nr].private;
 			buf->ops = spd->ops;
 			if (spd->flags & SPLICE_F_GIFT)
 				buf->flags |= PIPE_BUF_FLAG_GIFT;
@@ -296,19 +292,15 @@
 	page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
 
 	/*
-	 * Now fill in the holes:
-	 */
-	error = 0;
-
-	/*
 	 * Lookup the (hopefully) full range of pages we need.
 	 */
 	spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages);
 
 	/*
 	 * If find_get_pages_contig() returned fewer pages than we needed,
-	 * allocate the rest.
+	 * allocate the rest and fill in the holes.
 	 */
+	error = 0;
 	index += spd.nr_pages;
 	while (spd.nr_pages < nr_pages) {
 		/*
@@ -470,11 +462,16 @@
 /**
  * generic_file_splice_read - splice data from file to a pipe
  * @in:		file to splice from
+ * @ppos:	position in @in
  * @pipe:	pipe to splice to
  * @len:	number of bytes to splice
  * @flags:	splice modifier flags
  *
- * Will read pages from given file and fill them into a pipe.
+ * Description:
+ *    Will read pages from given file and fill them into a pipe. Can be
+ *    used as long as the address_space operations for the source implements
+ *    a readpage() hook.
+ *
  */
 ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
 				 struct pipe_inode_info *pipe, size_t len,
@@ -528,11 +525,11 @@
 static int pipe_to_sendpage(struct pipe_inode_info *pipe,
 			    struct pipe_buffer *buf, struct splice_desc *sd)
 {
-	struct file *file = sd->file;
+	struct file *file = sd->u.file;
 	loff_t pos = sd->pos;
 	int ret, more;
 
-	ret = buf->ops->pin(pipe, buf);
+	ret = buf->ops->confirm(pipe, buf);
 	if (!ret) {
 		more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
 
@@ -566,7 +563,7 @@
 static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
 			struct splice_desc *sd)
 {
-	struct file *file = sd->file;
+	struct file *file = sd->u.file;
 	struct address_space *mapping = file->f_mapping;
 	unsigned int offset, this_len;
 	struct page *page;
@@ -576,7 +573,7 @@
 	/*
 	 * make sure the data in this buffer is uptodate
 	 */
-	ret = buf->ops->pin(pipe, buf);
+	ret = buf->ops->confirm(pipe, buf);
 	if (unlikely(ret))
 		return ret;
 
@@ -663,36 +660,37 @@
 	return ret;
 }
 
-/*
- * Pipe input worker. Most of this logic works like a regular pipe, the
- * key here is the 'actor' worker passed in that actually moves the data
- * to the wanted destination. See pipe_to_file/pipe_to_sendpage above.
+/**
+ * __splice_from_pipe - splice data from a pipe to given actor
+ * @pipe:	pipe to splice from
+ * @sd:		information to @actor
+ * @actor:	handler that splices the data
+ *
+ * Description:
+ *    This function does little more than loop over the pipe and call
+ *    @actor to do the actual moving of a single struct pipe_buffer to
+ *    the desired destination. See pipe_to_file, pipe_to_sendpage, or
+ *    pipe_to_user.
+ *
  */
-ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
-			   struct file *out, loff_t *ppos, size_t len,
-			   unsigned int flags, splice_actor *actor)
+ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
+			   splice_actor *actor)
 {
 	int ret, do_wakeup, err;
-	struct splice_desc sd;
 
 	ret = 0;
 	do_wakeup = 0;
 
-	sd.total_len = len;
-	sd.flags = flags;
-	sd.file = out;
-	sd.pos = *ppos;
-
 	for (;;) {
 		if (pipe->nrbufs) {
 			struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
 			const struct pipe_buf_operations *ops = buf->ops;
 
-			sd.len = buf->len;
-			if (sd.len > sd.total_len)
-				sd.len = sd.total_len;
+			sd->len = buf->len;
+			if (sd->len > sd->total_len)
+				sd->len = sd->total_len;
 
-			err = actor(pipe, buf, &sd);
+			err = actor(pipe, buf, sd);
 			if (err <= 0) {
 				if (!ret && err != -ENODATA)
 					ret = err;
@@ -704,10 +702,10 @@
 			buf->offset += err;
 			buf->len -= err;
 
-			sd.len -= err;
-			sd.pos += err;
-			sd.total_len -= err;
-			if (sd.len)
+			sd->len -= err;
+			sd->pos += err;
+			sd->total_len -= err;
+			if (sd->len)
 				continue;
 
 			if (!buf->len) {
@@ -719,7 +717,7 @@
 					do_wakeup = 1;
 			}
 
-			if (!sd.total_len)
+			if (!sd->total_len)
 				break;
 		}
 
@@ -732,7 +730,7 @@
 				break;
 		}
 
-		if (flags & SPLICE_F_NONBLOCK) {
+		if (sd->flags & SPLICE_F_NONBLOCK) {
 			if (!ret)
 				ret = -EAGAIN;
 			break;
@@ -766,12 +764,32 @@
 }
 EXPORT_SYMBOL(__splice_from_pipe);
 
+/**
+ * splice_from_pipe - splice data from a pipe to a file
+ * @pipe:	pipe to splice from
+ * @out:	file to splice to
+ * @ppos:	position in @out
+ * @len:	how many bytes to splice
+ * @flags:	splice modifier flags
+ * @actor:	handler that splices the data
+ *
+ * Description:
+ *    See __splice_from_pipe. This function locks the input and output inodes,
+ *    otherwise it's identical to __splice_from_pipe().
+ *
+ */
 ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
 			 loff_t *ppos, size_t len, unsigned int flags,
 			 splice_actor *actor)
 {
 	ssize_t ret;
 	struct inode *inode = out->f_mapping->host;
+	struct splice_desc sd = {
+		.total_len = len,
+		.flags = flags,
+		.pos = *ppos,
+		.u.file = out,
+	};
 
 	/*
 	 * The actor worker might be calling ->prepare_write and
@@ -780,7 +798,7 @@
 	 * pipe->inode, we have to order lock acquiry here.
 	 */
 	inode_double_lock(inode, pipe->inode);
-	ret = __splice_from_pipe(pipe, out, ppos, len, flags, actor);
+	ret = __splice_from_pipe(pipe, &sd, actor);
 	inode_double_unlock(inode, pipe->inode);
 
 	return ret;
@@ -790,12 +808,14 @@
  * generic_file_splice_write_nolock - generic_file_splice_write without mutexes
  * @pipe:	pipe info
  * @out:	file to write to
+ * @ppos:	position in @out
  * @len:	number of bytes to splice
  * @flags:	splice modifier flags
  *
- * Will either move or copy pages (determined by @flags options) from
- * the given pipe inode to the given file. The caller is responsible
- * for acquiring i_mutex on both inodes.
+ * Description:
+ *    Will either move or copy pages (determined by @flags options) from
+ *    the given pipe inode to the given file. The caller is responsible
+ *    for acquiring i_mutex on both inodes.
  *
  */
 ssize_t
@@ -804,6 +824,12 @@
 {
 	struct address_space *mapping = out->f_mapping;
 	struct inode *inode = mapping->host;
+	struct splice_desc sd = {
+		.total_len = len,
+		.flags = flags,
+		.pos = *ppos,
+		.u.file = out,
+	};
 	ssize_t ret;
 	int err;
 
@@ -811,7 +837,7 @@
 	if (unlikely(err))
 		return err;
 
-	ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
+	ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
 	if (ret > 0) {
 		unsigned long nr_pages;
 
@@ -841,11 +867,13 @@
  * generic_file_splice_write - splice data from a pipe to a file
  * @pipe:	pipe info
  * @out:	file to write to
+ * @ppos:	position in @out
  * @len:	number of bytes to splice
  * @flags:	splice modifier flags
  *
- * Will either move or copy pages (determined by @flags options) from
- * the given pipe inode to the given file.
+ * Description:
+ *    Will either move or copy pages (determined by @flags options) from
+ *    the given pipe inode to the given file.
  *
  */
 ssize_t
@@ -896,13 +924,15 @@
 
 /**
  * generic_splice_sendpage - splice data from a pipe to a socket
- * @inode:	pipe inode
+ * @pipe:	pipe to splice from
  * @out:	socket to write to
+ * @ppos:	position in @out
  * @len:	number of bytes to splice
  * @flags:	splice modifier flags
  *
- * Will send @len bytes from the pipe to a network socket. No data copying
- * is involved.
+ * Description:
+ *    Will send @len bytes from the pipe to a network socket. No data copying
+ *    is involved.
  *
  */
 ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out,
@@ -956,14 +986,27 @@
 	return in->f_op->splice_read(in, ppos, pipe, len, flags);
 }
 
-long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
-		      size_t len, unsigned int flags)
+/**
+ * splice_direct_to_actor - splices data directly between two non-pipes
+ * @in:		file to splice from
+ * @sd:		actor information on where to splice to
+ * @actor:	handles the data splicing
+ *
+ * Description:
+ *    This is a special case helper to splice directly between two
+ *    points, without requiring an explicit pipe. Internally an allocated
+ *    pipe is cached in the process, and reused during the life time of
+ *    that process.
+ *
+ */
+ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
+			       splice_direct_actor *actor)
 {
 	struct pipe_inode_info *pipe;
 	long ret, bytes;
-	loff_t out_off;
 	umode_t i_mode;
-	int i;
+	size_t len;
+	int i, flags;
 
 	/*
 	 * We require the input being a regular file, as we don't want to
@@ -999,7 +1042,13 @@
 	 */
 	ret = 0;
 	bytes = 0;
-	out_off = 0;
+	len = sd->total_len;
+	flags = sd->flags;
+
+	/*
+	 * Don't block on output, we have to drain the direct pipe.
+	 */
+	sd->flags &= ~SPLICE_F_NONBLOCK;
 
 	while (len) {
 		size_t read_len, max_read_len;
@@ -1009,19 +1058,19 @@
 		 */
 		max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
 
-		ret = do_splice_to(in, ppos, pipe, max_read_len, flags);
+		ret = do_splice_to(in, &sd->pos, pipe, max_read_len, flags);
 		if (unlikely(ret < 0))
 			goto out_release;
 
 		read_len = ret;
+		sd->total_len = read_len;
 
 		/*
 		 * NOTE: nonblocking mode only applies to the input. We
 		 * must not do the output in nonblocking mode as then we
 		 * could get stuck data in the internal pipe:
 		 */
-		ret = do_splice_from(pipe, out, &out_off, read_len,
-				     flags & ~SPLICE_F_NONBLOCK);
+		ret = actor(pipe, sd);
 		if (unlikely(ret < 0))
 			goto out_release;
 
@@ -1066,6 +1115,48 @@
 		return bytes;
 
 	return ret;
+
+}
+EXPORT_SYMBOL(splice_direct_to_actor);
+
+static int direct_splice_actor(struct pipe_inode_info *pipe,
+			       struct splice_desc *sd)
+{
+	struct file *file = sd->u.file;
+
+	return do_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags);
+}
+
+/**
+ * do_splice_direct - splices data directly between two files
+ * @in:		file to splice from
+ * @ppos:	input file offset
+ * @out:	file to splice to
+ * @len:	number of bytes to splice
+ * @flags:	splice modifier flags
+ *
+ * Description:
+ *    For use by do_sendfile(). splice can easily emulate sendfile, but
+ *    doing it in the application would incur an extra system call
+ *    (splice in + splice out, as compared to just sendfile()). So this helper
+ *    can splice directly through a process-private pipe.
+ *
+ */
+long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+		      size_t len, unsigned int flags)
+{
+	struct splice_desc sd = {
+		.len		= len,
+		.total_len	= len,
+		.flags		= flags,
+		.pos		= *ppos,
+		.u.file		= out,
+	};
+	size_t ret;
+
+	ret = splice_direct_to_actor(in, &sd, direct_splice_actor);
+	*ppos = sd.pos;
+	return ret;
 }
 
 /*
@@ -1248,28 +1339,131 @@
 	return error;
 }
 
+static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+			struct splice_desc *sd)
+{
+	char *src;
+	int ret;
+
+	ret = buf->ops->confirm(pipe, buf);
+	if (unlikely(ret))
+		return ret;
+
+	/*
+	 * See if we can use the atomic maps, by prefaulting in the
+	 * pages and doing an atomic copy
+	 */
+	if (!fault_in_pages_writeable(sd->u.userptr, sd->len)) {
+		src = buf->ops->map(pipe, buf, 1);
+		ret = __copy_to_user_inatomic(sd->u.userptr, src + buf->offset,
+							sd->len);
+		buf->ops->unmap(pipe, buf, src);
+		if (!ret) {
+			ret = sd->len;
+			goto out;
+		}
+	}
+
+	/*
+	 * No dice, use slow non-atomic map and copy
+ 	 */
+	src = buf->ops->map(pipe, buf, 0);
+
+	ret = sd->len;
+	if (copy_to_user(sd->u.userptr, src + buf->offset, sd->len))
+		ret = -EFAULT;
+
+out:
+	if (ret > 0)
+		sd->u.userptr += ret;
+	buf->ops->unmap(pipe, buf, src);
+	return ret;
+}
+
+/*
+ * For lack of a better implementation, implement vmsplice() to userspace
+ * as a simple copy of the pipes pages to the user iov.
+ */
+static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
+			     unsigned long nr_segs, unsigned int flags)
+{
+	struct pipe_inode_info *pipe;
+	struct splice_desc sd;
+	ssize_t size;
+	int error;
+	long ret;
+
+	pipe = pipe_info(file->f_path.dentry->d_inode);
+	if (!pipe)
+		return -EBADF;
+
+	if (pipe->inode)
+		mutex_lock(&pipe->inode->i_mutex);
+
+	error = ret = 0;
+	while (nr_segs) {
+		void __user *base;
+		size_t len;
+
+		/*
+		 * Get user address base and length for this iovec.
+		 */
+		error = get_user(base, &iov->iov_base);
+		if (unlikely(error))
+			break;
+		error = get_user(len, &iov->iov_len);
+		if (unlikely(error))
+			break;
+
+		/*
+		 * Sanity check this iovec. 0 read succeeds.
+		 */
+		if (unlikely(!len))
+			break;
+		if (unlikely(!base)) {
+			error = -EFAULT;
+			break;
+		}
+
+		sd.len = 0;
+		sd.total_len = len;
+		sd.flags = flags;
+		sd.u.userptr = base;
+		sd.pos = 0;
+
+		size = __splice_from_pipe(pipe, &sd, pipe_to_user);
+		if (size < 0) {
+			if (!ret)
+				ret = size;
+
+			break;
+		}
+
+		ret += size;
+
+		if (size < len)
+			break;
+
+		nr_segs--;
+		iov++;
+	}
+
+	if (pipe->inode)
+		mutex_unlock(&pipe->inode->i_mutex);
+
+	if (!ret)
+		ret = error;
+
+	return ret;
+}
+
 /*
  * vmsplice splices a user address range into a pipe. It can be thought of
  * as splice-from-memory, where the regular splice is splice-from-file (or
  * to file). In both cases the output is a pipe, naturally.
- *
- * Note that vmsplice only supports splicing _from_ user memory to a pipe,
- * not the other way around. Splicing from user memory is a simple operation
- * that can be supported without any funky alignment restrictions or nasty
- * vm tricks. We simply map in the user memory and fill them into a pipe.
- * The reverse isn't quite as easy, though. There are two possible solutions
- * for that:
- *
- *	- memcpy() the data internally, at which point we might as well just
- *	  do a regular read() on the buffer anyway.
- *	- Lots of nasty vm tricks, that are neither fast nor flexible (it
- *	  has restriction limitations on both ends of the pipe).
- *
- * Alas, it isn't here.
- *
  */
-static long do_vmsplice(struct file *file, const struct iovec __user *iov,
-			unsigned long nr_segs, unsigned int flags)
+static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
+			     unsigned long nr_segs, unsigned int flags)
 {
 	struct pipe_inode_info *pipe;
 	struct page *pages[PIPE_BUFFERS];
@@ -1284,10 +1478,6 @@
 	pipe = pipe_info(file->f_path.dentry->d_inode);
 	if (!pipe)
 		return -EBADF;
-	if (unlikely(nr_segs > UIO_MAXIOV))
-		return -EINVAL;
-	else if (unlikely(!nr_segs))
-		return 0;
 
 	spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial,
 					    flags & SPLICE_F_GIFT);
@@ -1297,6 +1487,22 @@
 	return splice_to_pipe(pipe, &spd);
 }
 
+/*
+ * Note that vmsplice only really supports true splicing _from_ user memory
+ * to a pipe, not the other way around. Splicing from user memory is a simple
+ * operation that can be supported without any funky alignment restrictions
+ * or nasty vm tricks. We simply map in the user memory and fill them into
+ * a pipe. The reverse isn't quite as easy, though. There are two possible
+ * solutions for that:
+ *
+ *	- memcpy() the data internally, at which point we might as well just
+ *	  do a regular read() on the buffer anyway.
+ *	- Lots of nasty vm tricks, that are neither fast nor flexible (it
+ *	  has restriction limitations on both ends of the pipe).
+ *
+ * Currently we punt and implement it as a normal copy, see pipe_to_user().
+ *
+ */
 asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
 			     unsigned long nr_segs, unsigned int flags)
 {
@@ -1304,11 +1510,18 @@
 	long error;
 	int fput;
 
+	if (unlikely(nr_segs > UIO_MAXIOV))
+		return -EINVAL;
+	else if (unlikely(!nr_segs))
+		return 0;
+
 	error = -EBADF;
 	file = fget_light(fd, &fput);
 	if (file) {
 		if (file->f_mode & FMODE_WRITE)
-			error = do_vmsplice(file, iov, nr_segs, flags);
+			error = vmsplice_to_pipe(file, iov, nr_segs, flags);
+		else if (file->f_mode & FMODE_READ)
+			error = vmsplice_to_user(file, iov, nr_segs, flags);
 
 		fput_light(file, fput);
 	}
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 0732ddb..589be21 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -27,7 +27,7 @@
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
 	.fsync		= sysv_sync_file,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
 
 const struct inode_operations sysv_file_inode_operations = {
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 51b5764..df070be 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -261,7 +261,7 @@
 	.aio_write		= udf_file_aio_write,
 	.release		= udf_release_file,
 	.fsync			= udf_fsync_file,
-	.sendfile		= generic_file_sendfile,
+	.splice_read		= generic_file_splice_read,
 };
 
 const struct inode_operations udf_file_inode_operations = {
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 1e09632..6705d74 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -60,5 +60,5 @@
 	.mmap		= generic_file_mmap,
 	.open           = generic_file_open,
 	.fsync		= ufs_sync_file,
-	.sendfile	= generic_file_sendfile,
+	.splice_read	= generic_file_splice_read,
 };
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index cb51dc9..8c43cd2 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -124,30 +124,6 @@
 }
 
 STATIC ssize_t
-xfs_file_sendfile(
-	struct file		*filp,
-	loff_t			*pos,
-	size_t			count,
-	read_actor_t		actor,
-	void			*target)
-{
-	return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
-				filp, pos, 0, count, actor, target, NULL);
-}
-
-STATIC ssize_t
-xfs_file_sendfile_invis(
-	struct file		*filp,
-	loff_t			*pos,
-	size_t			count,
-	read_actor_t		actor,
-	void			*target)
-{
-	return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
-				filp, pos, IO_INVIS, count, actor, target, NULL);
-}
-
-STATIC ssize_t
 xfs_file_splice_read(
 	struct file		*infilp,
 	loff_t			*ppos,
@@ -452,7 +428,6 @@
 	.write		= do_sync_write,
 	.aio_read	= xfs_file_aio_read,
 	.aio_write	= xfs_file_aio_write,
-	.sendfile	= xfs_file_sendfile,
 	.splice_read	= xfs_file_splice_read,
 	.splice_write	= xfs_file_splice_write,
 	.unlocked_ioctl	= xfs_file_ioctl,
@@ -475,7 +450,6 @@
 	.write		= do_sync_write,
 	.aio_read	= xfs_file_aio_read_invis,
 	.aio_write	= xfs_file_aio_write_invis,
-	.sendfile	= xfs_file_sendfile_invis,
 	.splice_read	= xfs_file_splice_read_invis,
 	.splice_write	= xfs_file_splice_write_invis,
 	.unlocked_ioctl	= xfs_file_ioctl_invis,
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 715adad..af24a45 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -101,7 +101,6 @@
  * Feature macros (disable/enable)
  */
 #undef  HAVE_REFCACHE	/* reference cache not needed for NFS in 2.6 */
-#define HAVE_SENDFILE	/* sendfile(2) exists in 2.6, but not in 2.4 */
 #define HAVE_SPLICE	/* a splice(2) exists in 2.6, but not in 2.4 */
 #ifdef CONFIG_SMP
 #define HAVE_PERCPU_SB	/* per cpu superblock counters are a 2.6 feature */
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index ed90403..765ec16 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -287,50 +287,6 @@
 }
 
 ssize_t
-xfs_sendfile(
-	bhv_desc_t		*bdp,
-	struct file		*filp,
-	loff_t			*offset,
-	int			ioflags,
-	size_t			count,
-	read_actor_t		actor,
-	void			*target,
-	cred_t			*credp)
-{
-	xfs_inode_t		*ip = XFS_BHVTOI(bdp);
-	xfs_mount_t		*mp = ip->i_mount;
-	ssize_t			ret;
-
-	XFS_STATS_INC(xs_read_calls);
-	if (XFS_FORCED_SHUTDOWN(mp))
-		return -EIO;
-
-	xfs_ilock(ip, XFS_IOLOCK_SHARED);
-
-	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
-	    (!(ioflags & IO_INVIS))) {
-		bhv_vrwlock_t locktype = VRWLOCK_READ;
-		int error;
-
-		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
-				      *offset, count,
-				      FILP_DELAY_FLAG(filp), &locktype);
-		if (error) {
-			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-			return -error;
-		}
-	}
-	xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
-		   (void *)(unsigned long)target, count, *offset, ioflags);
-	ret = generic_file_sendfile(filp, offset, count, actor, target);
-	if (ret > 0)
-		XFS_STATS_ADD(xs_read_bytes, ret);
-
-	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-	return ret;
-}
-
-ssize_t
 xfs_splice_read(
 	bhv_desc_t		*bdp,
 	struct file		*infilp,
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 7ac51b1..7c60a1e 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -90,9 +90,6 @@
 extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
 				const struct iovec *, unsigned int,
 				loff_t *, int, struct cred *);
-extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
-				loff_t *, int, size_t, read_actor_t,
-				void *, struct cred *);
 extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *,
 				struct pipe_inode_info *, size_t, int, int,
 				struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index d1b2d01..013048a 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -139,9 +139,6 @@
 typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
 				const struct iovec *, unsigned int,
 				loff_t *, int, struct cred *);
-typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
-				loff_t *, int, size_t, read_actor_t,
-				void *, struct cred *);
 typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *,
 				struct pipe_inode_info *, size_t, int, int,
 				struct cred *);
@@ -206,7 +203,6 @@
 	vop_close_t		vop_close;
 	vop_read_t		vop_read;
 	vop_write_t		vop_write;
-	vop_sendfile_t		vop_sendfile;
 	vop_splice_read_t	vop_splice_read;
 	vop_splice_write_t	vop_splice_write;
 	vop_ioctl_t		vop_ioctl;
@@ -254,8 +250,6 @@
 		VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
 #define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr)		\
 		VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
-#define bhv_vop_sendfile(vp,f,off,ioflags,cnt,act,targ,cr)		\
-		VOP(vop_sendfile, vp)(VNHEAD(vp),f,off,ioflags,cnt,act,targ,cr)
 #define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr)			\
 		VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
 #define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr)		\
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index de17aed..70bc82f 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -4680,9 +4680,6 @@
 	.vop_open		= xfs_open,
 	.vop_close		= xfs_close,
 	.vop_read		= xfs_read,
-#ifdef HAVE_SENDFILE
-	.vop_sendfile		= xfs_sendfile,
-#endif
 #ifdef HAVE_SPLICE
 	.vop_splice_read	= xfs_splice_read,
 	.vop_splice_write	= xfs_splice_write,
diff --git a/include/asm-arm26/termbits.h b/include/asm-arm26/termbits.h
index a3f4fe1..f66b518 100644
--- a/include/asm-arm26/termbits.h
+++ b/include/asm-arm26/termbits.h
@@ -15,7 +15,7 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
-struct ktermios {
+struct termios2 {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
 	tcflag_t c_cflag;		/* control mode flags */
@@ -26,6 +26,16 @@
 	speed_t c_ospeed;		/* output speed */
 };
 
+struct ktermios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
 
 /* c_cc characters */
 #define VINTR 0
diff --git a/include/asm-avr32/termbits.h b/include/asm-avr32/termbits.h
index c215fafda..db2daab 100644
--- a/include/asm-avr32/termbits.h
+++ b/include/asm-avr32/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-blackfin/termbits.h b/include/asm-blackfin/termbits.h
index 2fd9dab..4eac38d 100644
--- a/include/asm-blackfin/termbits.h
+++ b/include/asm-blackfin/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];	/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;               /* input mode flags */
+	tcflag_t c_oflag;               /* output mode flags */
+	tcflag_t c_cflag;               /* control mode flags */
+	tcflag_t c_lflag;               /* local mode flags */
+	cc_t c_line;                    /* line discipline */
+	cc_t c_cc[NCCS];                /* control characters */
+	speed_t c_ispeed;               /* input speed */
+	speed_t c_ospeed;               /* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;               /* input mode flags */
 	tcflag_t c_oflag;               /* output mode flags */
diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h
index 8d8cec2..6cc2e27 100644
--- a/include/asm-cris/termbits.h
+++ b/include/asm-cris/termbits.h
@@ -19,6 +19,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-frv/termbits.h b/include/asm-frv/termbits.h
index 2d6d389..74851b4 100644
--- a/include/asm-frv/termbits.h
+++ b/include/asm-frv/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-generic/bitops/sched.h b/include/asm-generic/bitops/sched.h
index 815bb01..604fab7 100644
--- a/include/asm-generic/bitops/sched.h
+++ b/include/asm-generic/bitops/sched.h
@@ -6,28 +6,23 @@
 
 /*
  * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
+ * way of searching a 100-bit bitmap.  It's guaranteed that at least
+ * one of the 100 bits is cleared.
  */
 static inline int sched_find_first_bit(const unsigned long *b)
 {
 #if BITS_PER_LONG == 64
-	if (unlikely(b[0]))
+	if (b[0])
 		return __ffs(b[0]);
-	if (likely(b[1]))
-		return __ffs(b[1]) + 64;
-	return __ffs(b[2]) + 128;
+	return __ffs(b[1]) + 64;
 #elif BITS_PER_LONG == 32
-	if (unlikely(b[0]))
+	if (b[0])
 		return __ffs(b[0]);
-	if (unlikely(b[1]))
+	if (b[1])
 		return __ffs(b[1]) + 32;
-	if (unlikely(b[2]))
+	if (b[2])
 		return __ffs(b[2]) + 64;
-	if (b[3])
-		return __ffs(b[3]) + 96;
-	return __ffs(b[4]) + 128;
+	return __ffs(b[3]) + 96;
 #else
 #error BITS_PER_LONG not defined
 #endif
diff --git a/include/asm-h8300/termbits.h b/include/asm-h8300/termbits.h
index 6a1f4d3..e877b40 100644
--- a/include/asm-h8300/termbits.h
+++ b/include/asm-h8300/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-ia64/termbits.h b/include/asm-ia64/termbits.h
index 4531a51..7fae310 100644
--- a/include/asm-ia64/termbits.h
+++ b/include/asm-ia64/termbits.h
@@ -26,6 +26,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-m32r/termbits.h b/include/asm-m32r/termbits.h
index e402641df..6be3b8a 100644
--- a/include/asm-m32r/termbits.h
+++ b/include/asm-m32r/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-m68k/termbits.h b/include/asm-m68k/termbits.h
index a194092..0e520f3 100644
--- a/include/asm-m68k/termbits.h
+++ b/include/asm-m68k/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
index 964c5ed..0b3ff9c 100644
--- a/include/asm-mips/addrspace.h
+++ b/include/asm-mips/addrspace.h
@@ -129,29 +129,12 @@
 #define PHYS_TO_XKPHYS(cm,a)		(_CONST64_(0x8000000000000000) | \
 					 ((cm)<<59) | (a))
 
-#if defined (CONFIG_CPU_R4300)						\
-    || defined (CONFIG_CPU_R4X00)					\
-    || defined (CONFIG_CPU_R5000)					\
-    || defined (CONFIG_CPU_RM7000)					\
-    || defined (CONFIG_CPU_RM9000)					\
-    || defined (CONFIG_CPU_NEVADA)					\
-    || defined (CONFIG_CPU_TX49XX)					\
-    || defined (CONFIG_CPU_MIPS64)
-#define TO_PHYS_MASK	_CONST64_(0x0000000fffffffff)	/* 2^^36 - 1 */
-#endif
-
-#if defined (CONFIG_CPU_R8000)
-/* We keep KUSIZE consistent with R4000 for now (2^^40) instead of (2^^48) */
-#define TO_PHYS_MASK	_CONST64_(0x000000ffffffffff)	/* 2^^40 - 1 */
-#endif
-
-#if defined (CONFIG_CPU_R10000)
-#define TO_PHYS_MASK	_CONST64_(0x000000ffffffffff)	/* 2^^40 - 1 */
-#endif
-
-#if defined(CONFIG_CPU_SB1) || defined(CONFIG_CPU_SB1A)
-#define TO_PHYS_MASK	_CONST64_(0x00000fffffffffff)	/* 2^^44 - 1 */
-#endif
+/*
+ * The ultimate limited of the 64-bit MIPS architecture:  2 bits for selecting
+ * the region, 3 bits for the CCA mode.  This leaves 59 bits of which the
+ * R8000 implements most with its 48-bit physical address space.
+ */
+#define TO_PHYS_MASK	_CONST64_(0x07ffffffffffffff)	/* 2^^59 - 1 */
 
 #ifndef CONFIG_CPU_R8000
 
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
index b0c3297..087126a 100644
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -109,18 +109,12 @@
 #define  MACH_COSINE_ORION	0
 
 /*
- * Valid machtype for group GALILEO
- */
-#define MACH_GROUP_GALILEO     11	/* Galileo Eval Boards		*/
-#define  MACH_EV64120A		0	/* EV64120A */
-
-/*
  * Valid machtype for group MOMENCO
  */
 #define MACH_GROUP_MOMENCO	12	/* Momentum Boards		*/
 #define  MACH_MOMENCO_OCELOT	0
 #define  MACH_MOMENCO_OCELOT_G	1	/* no more supported (may 2007) */
-#define  MACH_MOMENCO_OCELOT_C	2
+#define  MACH_MOMENCO_OCELOT_C	2	/* no more supported (jun 2007) */
 #define  MACH_MOMENCO_JAGUAR_ATX 3	/* no more supported (may 2007) */
 #define  MACH_MOMENCO_OCELOT_3	4
 
@@ -194,13 +188,6 @@
 #define  MACH_HP_LASERJET	1
 
 /*
- * Valid machtype for group LASAT
- */
-#define MACH_GROUP_LASAT       21
-#define  MACH_LASAT_100		0	/* Masquerade II/SP100/SP50/SP25 */
-#define  MACH_LASAT_200		1	/* Masquerade PRO/SP200 */
-
-/*
  * Valid machtype for group TITAN
  */
 #define MACH_GROUP_TITAN       22	/* PMC-Sierra Titan		*/
@@ -213,6 +200,27 @@
 #define MACH_GROUP_NEC_EMMA2RH 25	/* NEC EMMA2RH (was 23)		*/
 #define  MACH_NEC_MARKEINS	0	/* NEC EMMA2RH Mark-eins	*/
 
+/*
+ * Valid machtype for group LEMOTE
+ */
+#define MACH_GROUP_LEMOTE          27
+#define  MACH_LEMOTE_FULONG        0
+
+/*
+ * Valid machtype for group PMC-MSP
+ */
+#define MACH_GROUP_MSP         26	/* PMC-Sierra MSP boards/CPUs    */
+#define MACH_MSP4200_EVAL       0	/* PMC-Sierra MSP4200 Evaluation */
+#define MACH_MSP4200_GW         1	/* PMC-Sierra MSP4200 Gateway demo */
+#define MACH_MSP4200_FPGA       2	/* PMC-Sierra MSP4200 Emulation */
+#define MACH_MSP7120_EVAL       3	/* PMC-Sierra MSP7120 Evaluation */
+#define MACH_MSP7120_GW         4	/* PMC-Sierra MSP7120 Residential GW */
+#define MACH_MSP7120_FPGA       5	/* PMC-Sierra MSP7120 Emulation */
+#define MACH_MSP_OTHER        255	/* PMC-Sierra unknown board type */
+
+#define MACH_GROUP_WINDRIVER   28	/* Windriver boards */
+#define MACH_WRPPMC             1
+
 #define CL_SIZE			COMMAND_LINE_SIZE
 
 const char *get_system_type(void);
diff --git a/include/asm-mips/cacheops.h b/include/asm-mips/cacheops.h
index c4a1ec3..df7f2de 100644
--- a/include/asm-mips/cacheops.h
+++ b/include/asm-mips/cacheops.h
@@ -20,7 +20,11 @@
 #define Index_Load_Tag_D	0x05
 #define Index_Store_Tag_I	0x08
 #define Index_Store_Tag_D	0x09
+#if defined(CONFIG_CPU_LOONGSON2)
+#define Hit_Invalidate_I    	0x00
+#else
 #define Hit_Invalidate_I	0x10
+#endif
 #define Hit_Invalidate_D	0x11
 #define Hit_Writeback_Inv_D	0x15
 
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 5e4bed1..d95a83e 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -150,6 +150,10 @@
 #define cpu_has_mipsmt		(cpu_data[0].ases & MIPS_ASE_MIPSMT)
 #endif
 
+#ifndef cpu_has_userlocal
+#define cpu_has_userlocal	(cpu_data[0].options & MIPS_CPU_ULRI)
+#endif
+
 #ifdef CONFIG_32BIT
 # ifndef cpu_has_nofpuex
 # define cpu_has_nofpuex	(cpu_data[0].options & MIPS_CPU_NOFPUEX)
diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h
index 2924069..3857358 100644
--- a/include/asm-mips/cpu.h
+++ b/include/asm-mips/cpu.h
@@ -89,6 +89,8 @@
 #define PRID_IMP_34K		0x9500
 #define PRID_IMP_24KE		0x9600
 #define PRID_IMP_74K		0x9700
+#define PRID_IMP_LOONGSON1      0x4200
+#define PRID_IMP_LOONGSON2      0x6300
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -107,6 +109,7 @@
  * Definitions for 7:0 on legacy processors
  */
 
+#define PRID_REV_MASK		0x00ff
 
 #define PRID_REV_TX4927		0x0022
 #define PRID_REV_TX4937		0x0030
@@ -123,6 +126,7 @@
 #define PRID_REV_VR4122		0x0070
 #define PRID_REV_VR4181A	0x0070	/* Same as VR4122 */
 #define PRID_REV_VR4130		0x0080
+#define PRID_REV_34K_V1_0_2	0x0022
 
 /*
  * Older processors used to encode processor version and revision in two
@@ -211,7 +215,10 @@
 #define CPU_SB1A		62
 #define CPU_74K			63
 #define CPU_R14000		64
-#define CPU_LAST		64
+#define CPU_LOONGSON1           65
+#define CPU_LOONGSON2           66
+
+#define CPU_LAST		66
 
 /*
  * ISA Level encodings
@@ -257,6 +264,7 @@
 #define MIPS_CPU_PREFETCH	0x00080000 /* CPU has usable prefetch */
 #define MIPS_CPU_VINT		0x00100000 /* CPU supports MIPSR2 vectored interrupts */
 #define MIPS_CPU_VEIC		0x00200000 /* CPU supports MIPSR2 external interrupt controller mode */
+#define MIPS_CPU_ULRI		0x00400000 /* CPU has ULRI feature */
 
 /*
  * CPU ASE encodings
diff --git a/include/asm-mips/div64.h b/include/asm-mips/div64.h
index 66189f5..716371b 100644
--- a/include/asm-mips/div64.h
+++ b/include/asm-mips/div64.h
@@ -20,7 +20,7 @@
  */
 
 #define do_div64_32(res, high, low, base) ({ \
-	unsigned long __quot, __mod; \
+	unsigned long __quot32, __mod32; \
 	unsigned long __cf, __tmp, __tmp2, __i; \
 	\
 	__asm__(".set	push\n\t" \
@@ -48,12 +48,13 @@
 		"bnez	%4, 0b\n\t" \
 		" srl	%5, %1, 0x1f\n\t" \
 		".set	pop" \
-		: "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \
+		: "=&r" (__mod32), "=&r" (__tmp), \
+		  "=&r" (__quot32), "=&r" (__cf), \
 		  "=&r" (__i), "=&r" (__tmp2) \
 		: "Jr" (base), "0" (high), "1" (low)); \
 	\
-	(res) = __quot; \
-	__mod; })
+	(res) = __quot32; \
+	__mod32; })
 
 #define do_div(n, base) ({ \
 	unsigned long long __quot; \
diff --git a/include/asm-mips/gpio.h b/include/asm-mips/gpio.h
new file mode 100644
index 0000000..06e46fa
--- /dev/null
+++ b/include/asm-mips/gpio.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_MIPS_GPIO_H
+#define __ASM_MIPS_GPIO_H
+
+#include <gpio.h>
+
+#endif /* __ASM_MIPS_GPIO_H */
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index 92ec261..12bcc1f 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -178,6 +178,11 @@
 static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
 	unsigned long flags)
 {
+	void __iomem *addr = plat_ioremap(offset, size, flags);
+
+	if (addr)
+		return addr;
+
 #define __IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))
 
 	if (cpu_has_64bit_addresses) {
@@ -282,6 +287,9 @@
 
 static inline void iounmap(const volatile void __iomem *addr)
 {
+	if (plat_iounmap(addr))
+		return;
+
 #define __IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1)
 
 	if (cpu_has_64bit_addresses ||
diff --git a/include/asm-mips/lasat/ds1603.h b/include/asm-mips/lasat/ds1603.h
deleted file mode 100644
index edcd754..0000000
--- a/include/asm-mips/lasat/ds1603.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <asm/addrspace.h>
-
-/* Lasat 100	*/
-#define DS1603_REG_100		(KSEG1ADDR(0x1c810000))
-#define DS1603_RST_100		(1 << 2)
-#define DS1603_CLK_100		(1 << 0)
-#define DS1603_DATA_SHIFT_100	1
-#define DS1603_DATA_100		(1 << DS1603_DATA_SHIFT_100)
-
-/* Lasat 200	*/
-#define DS1603_REG_200		(KSEG1ADDR(0x11000000))
-#define DS1603_RST_200		(1 << 3)
-#define DS1603_CLK_200		(1 << 4)
-#define DS1603_DATA_200		(1 << 5)
-
-#define DS1603_DATA_REG_200		(DS1603_REG_200 + 0x10000)
-#define DS1603_DATA_READ_SHIFT_200	9
-#define DS1603_DATA_READ_200	(1 << DS1603_DATA_READ_SHIFT_200)
diff --git a/include/asm-mips/lasat/eeprom.h b/include/asm-mips/lasat/eeprom.h
deleted file mode 100644
index 7b53edd..0000000
--- a/include/asm-mips/lasat/eeprom.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <asm/addrspace.h>
-
-/* lasat 100 */
-#define AT93C_REG_100               KSEG1ADDR(0x1c810000)
-#define AT93C_RDATA_REG_100         AT93C_REG_100
-#define AT93C_RDATA_SHIFT_100       4
-#define AT93C_WDATA_SHIFT_100       4
-#define AT93C_CS_M_100              ( 1 << 5 )
-#define AT93C_CLK_M_100             ( 1 << 3 )
-
-/* lasat 200 */
-#define AT93C_REG_200		KSEG1ADDR(0x11000000)
-#define AT93C_RDATA_REG_200	(AT93C_REG_200+0x10000)
-#define AT93C_RDATA_SHIFT_200	8
-#define AT93C_WDATA_SHIFT_200	2
-#define AT93C_CS_M_200		( 1 << 0 )
-#define AT93C_CLK_M_200		( 1 << 1 )
diff --git a/include/asm-mips/lasat/head.h b/include/asm-mips/lasat/head.h
deleted file mode 100644
index f5589f3..0000000
--- a/include/asm-mips/lasat/head.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Image header stuff
- */
-#ifndef _HEAD_H
-#define _HEAD_H
-
-#define LASAT_K_MAGIC0_VAL	0xfedeabba
-#define LASAT_K_MAGIC1_VAL	0x00bedead
-
-#ifndef _LANGUAGE_ASSEMBLY
-#include <linux/types.h>
-struct bootloader_header {
-	u32 magic[2];
-	u32 version;
-	u32 image_start;
-	u32 image_size;
-	u32 kernel_start;
-	u32 kernel_entry;
-};
-#endif
-
-#endif /* _HEAD_H */
diff --git a/include/asm-mips/lasat/lasat.h b/include/asm-mips/lasat/lasat.h
deleted file mode 100644
index 42077e3..0000000
--- a/include/asm-mips/lasat/lasat.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * lasat.h
- *
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Configuration for LASAT boards, loads the appropriate include files.
- */
-#ifndef _LASAT_H
-#define _LASAT_H
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-extern struct lasat_misc {
-	volatile u32 *reset_reg;
-	volatile u32 *flash_wp_reg;
-	u32 flash_wp_bit;
-} *lasat_misc;
-
-enum lasat_mtdparts {
-	LASAT_MTD_BOOTLOADER,
-	LASAT_MTD_SERVICE,
-	LASAT_MTD_NORMAL,
-	LASAT_MTD_CONFIG,
-	LASAT_MTD_FS,
-	LASAT_MTD_LAST
-};
-
-/*
- * The format of the data record in the EEPROM.
- * See Documentation/LASAT/eeprom.txt for a detailed description
- * of the fields in this struct, and the LASAT Hardware Configuration
- * field specification for a detailed description of the config
- * field.
- */
-#include <linux/types.h>
-
-#define LASAT_EEPROM_VERSION 7
-struct lasat_eeprom_struct {
-	unsigned int  version;
-	unsigned int  cfg[3];
-	unsigned char hwaddr[6];
-	unsigned char print_partno[12];
-	unsigned char term0;
-	unsigned char print_serial[14];
-	unsigned char term1;
-	unsigned char prod_partno[12];
-	unsigned char term2;
-	unsigned char prod_serial[14];
-	unsigned char term3;
-	unsigned char passwd_hash[16];
-	unsigned char pwdnull;
-	unsigned char vendid;
-	unsigned char ts_ref;
-	unsigned char ts_signoff;
-	unsigned char reserved[11];
-	unsigned char debugaccess;
-	unsigned short prid;
-	unsigned int  serviceflag;
-	unsigned int  ipaddr;
-	unsigned int  netmask;
-	unsigned int  crc32;
-};
-
-struct lasat_eeprom_struct_pre7 {
-	unsigned int  version;
-	unsigned int  flags[3];
-	unsigned char hwaddr0[6];
-	unsigned char hwaddr1[6];
-	unsigned char print_partno[9];
-	unsigned char term0;
-	unsigned char print_serial[14];
-	unsigned char term1;
-	unsigned char prod_partno[9];
-	unsigned char term2;
-	unsigned char prod_serial[14];
-	unsigned char term3;
-	unsigned char passwd_hash[24];
-	unsigned char pwdnull;
-	unsigned char vendor;
-	unsigned char ts_ref;
-	unsigned char ts_signoff;
-	unsigned char reserved[6];
-	unsigned int  writecount;
-	unsigned int  ipaddr;
-	unsigned int  netmask;
-	unsigned int  crc32;
-};
-
-/* Configuration descriptor encoding - see the doc for details */
-
-#define LASAT_W0_DSCTYPE(v)		( ( (v)         ) & 0xf )
-#define LASAT_W0_BMID(v)		( ( (v) >> 0x04 ) & 0xf )
-#define LASAT_W0_CPUTYPE(v)		( ( (v) >> 0x08 ) & 0xf )
-#define LASAT_W0_BUSSPEED(v)		( ( (v) >> 0x0c ) & 0xf )
-#define LASAT_W0_CPUCLK(v)		( ( (v) >> 0x10 ) & 0xf )
-#define LASAT_W0_SDRAMBANKSZ(v)		( ( (v) >> 0x14 ) & 0xf )
-#define LASAT_W0_SDRAMBANKS(v)		( ( (v) >> 0x18 ) & 0xf )
-#define LASAT_W0_L2CACHE(v)		( ( (v) >> 0x1c ) & 0xf )
-
-#define LASAT_W1_EDHAC(v)		( ( (v)         ) & 0xf )
-#define LASAT_W1_HIFN(v)		( ( (v) >> 0x04 ) & 0x1 )
-#define LASAT_W1_ISDN(v)		( ( (v) >> 0x05 ) & 0x1 )
-#define LASAT_W1_IDE(v)			( ( (v) >> 0x06 ) & 0x1 )
-#define LASAT_W1_HDLC(v)		( ( (v) >> 0x07 ) & 0x1 )
-#define LASAT_W1_USVERSION(v)		( ( (v) >> 0x08 ) & 0x1 )
-#define LASAT_W1_4MACS(v)		( ( (v) >> 0x09 ) & 0x1 )
-#define LASAT_W1_EXTSERIAL(v)		( ( (v) >> 0x0a ) & 0x1 )
-#define LASAT_W1_FLASHSIZE(v)		( ( (v) >> 0x0c ) & 0xf )
-#define LASAT_W1_PCISLOTS(v)		( ( (v) >> 0x10 ) & 0xf )
-#define LASAT_W1_PCI1OPT(v)		( ( (v) >> 0x14 ) & 0xf )
-#define LASAT_W1_PCI2OPT(v)		( ( (v) >> 0x18 ) & 0xf )
-#define LASAT_W1_PCI3OPT(v)		( ( (v) >> 0x1c ) & 0xf )
-
-/* Routines specific to LASAT boards */
-
-#define LASAT_BMID_MASQUERADE2		0
-#define LASAT_BMID_MASQUERADEPRO	1
-#define LASAT_BMID_SAFEPIPE25			2
-#define LASAT_BMID_SAFEPIPE50			3
-#define LASAT_BMID_SAFEPIPE100		4
-#define LASAT_BMID_SAFEPIPE5000		5
-#define LASAT_BMID_SAFEPIPE7000		6
-#define LASAT_BMID_SAFEPIPE1000		7
-//#define LASAT_BMID_SAFEPIPE30		7
-//#define LASAT_BMID_SAFEPIPE5100	8
-//#define LASAT_BMID_SAFEPIPE7100	9
-#define LASAT_BMID_UNKNOWN				0xf
-#define LASAT_MAX_BMID_NAMES			9   // no larger than 15!
-
-#define LASAT_HAS_EDHAC			( 1 << 0 )
-#define LASAT_EDHAC_FAST		( 1 << 1 )
-#define LASAT_HAS_EADI			( 1 << 2 )
-#define LASAT_HAS_HIFN			( 1 << 3 )
-#define LASAT_HAS_ISDN			( 1 << 4 )
-#define LASAT_HAS_LEASEDLINE_IF		( 1 << 5 )
-#define LASAT_HAS_HDC			( 1 << 6 )
-
-#define LASAT_PRID_MASQUERADE2		0
-#define LASAT_PRID_MASQUERADEPRO	1
-#define LASAT_PRID_SAFEPIPE25			2
-#define LASAT_PRID_SAFEPIPE50			3
-#define LASAT_PRID_SAFEPIPE100		4
-#define LASAT_PRID_SAFEPIPE5000		5
-#define LASAT_PRID_SAFEPIPE7000		6
-#define LASAT_PRID_SAFEPIPE30			7
-#define LASAT_PRID_SAFEPIPE5100		8
-#define LASAT_PRID_SAFEPIPE7100		9
-
-#define LASAT_PRID_SAFEPIPE1110		10
-#define LASAT_PRID_SAFEPIPE3020		11
-#define LASAT_PRID_SAFEPIPE3030		12
-#define LASAT_PRID_SAFEPIPE5020		13
-#define LASAT_PRID_SAFEPIPE5030		14
-#define LASAT_PRID_SAFEPIPE1120		15
-#define LASAT_PRID_SAFEPIPE1130		16
-#define LASAT_PRID_SAFEPIPE6010		17
-#define LASAT_PRID_SAFEPIPE6110		18
-#define LASAT_PRID_SAFEPIPE6210		19
-#define LASAT_PRID_SAFEPIPE1020		20
-#define LASAT_PRID_SAFEPIPE1040		21
-#define LASAT_PRID_SAFEPIPE1060		22
-
-struct lasat_info {
-	unsigned int  li_cpu_hz;
-	unsigned int  li_bus_hz;
-	unsigned int  li_bmid;
-	unsigned int  li_memsize;
-	unsigned int  li_flash_size;
-	unsigned int  li_prid;
-	unsigned char li_bmstr[16];
-	unsigned char li_namestr[32];
-	unsigned char li_typestr[16];
-	/* Info on the Flash layout */
-	unsigned int  li_flash_base;
-	unsigned long li_flashpart_base[LASAT_MTD_LAST];
-	unsigned long li_flashpart_size[LASAT_MTD_LAST];
-	struct lasat_eeprom_struct li_eeprom_info;
-	unsigned int  li_eeprom_upgrade_version;
-	unsigned int  li_debugaccess;
-};
-
-extern struct lasat_info lasat_board_info;
-
-static inline unsigned long lasat_flash_partition_start(int partno)
-{
-	if (partno < 0 || partno >= LASAT_MTD_LAST)
-		return 0;
-
-	return lasat_board_info.li_flashpart_base[partno];
-}
-
-static inline unsigned long lasat_flash_partition_size(int partno)
-{
-	if (partno < 0 || partno >= LASAT_MTD_LAST)
-		return 0;
-
-	return lasat_board_info.li_flashpart_size[partno];
-}
-
-/* Called from setup() to initialize the global board_info struct */
-extern int lasat_init_board_info(void);
-
-/* Write the modified EEPROM info struct */
-extern void lasat_write_eeprom_info(void);
-
-#define N_MACHTYPES		2
-/* for calibration of delays */
-
-/* the lasat_ndelay function is necessary because it is used at an
- * early stage of the boot process where ndelay is not calibrated.
- * It is used for the bit-banging rtc and eeprom drivers */
-
-#include <asm/delay.h>
-/* calculating with the slowest board with 100 MHz clock */
-#define LASAT_100_DIVIDER 20
-/* All 200's run at 250 MHz clock */
-#define LASAT_200_DIVIDER 8
-
-extern unsigned int lasat_ndelay_divider;
-
-static inline void lasat_ndelay(unsigned int ns)
-{
-            __delay(ns / lasat_ndelay_divider);
-}
-
-#endif /* !defined (_LANGUAGE_ASSEMBLY) */
-
-#define LASAT_SERVICEMODE_MAGIC_1     0xdeadbeef
-#define LASAT_SERVICEMODE_MAGIC_2     0xfedeabba
-
-/* Lasat 100 boards */
-#define LASAT_GT_BASE           (KSEG1ADDR(0x14000000))
-
-/* Lasat 200 boards */
-#define Vrc5074_PHYS_BASE       0x1fa00000
-#define Vrc5074_BASE            (KSEG1ADDR(Vrc5074_PHYS_BASE))
-#define PCI_WINDOW1             0x1a000000
-
-#endif /* _LASAT_H */
diff --git a/include/asm-mips/lasat/lasatint.h b/include/asm-mips/lasat/lasatint.h
deleted file mode 100644
index 065474f..0000000
--- a/include/asm-mips/lasat/lasatint.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#define LASATINT_END 16
-
-/* lasat 100 */
-#define LASAT_INT_STATUS_REG_100	(KSEG1ADDR(0x1c880000))
-#define LASAT_INT_MASK_REG_100		(KSEG1ADDR(0x1c890000))
-#define LASATINT_MASK_SHIFT_100		0
-
-/* lasat 200 */
-#define LASAT_INT_STATUS_REG_200	(KSEG1ADDR(0x1104003c))
-#define LASAT_INT_MASK_REG_200		(KSEG1ADDR(0x1104003c))
-#define LASATINT_MASK_SHIFT_200		16
-
diff --git a/include/asm-mips/lasat/picvue.h b/include/asm-mips/lasat/picvue.h
deleted file mode 100644
index 42a492e..0000000
--- a/include/asm-mips/lasat/picvue.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Lasat 100 */
-#define PVC_REG_100		KSEG1ADDR(0x1c820000)
-#define PVC_DATA_SHIFT_100	0
-#define PVC_DATA_M_100		0xFF
-#define PVC_E_100		(1 << 8)
-#define PVC_RW_100		(1 << 9)
-#define PVC_RS_100		(1 << 10)
-
-/* Lasat 200 */
-#define PVC_REG_200		KSEG1ADDR(0x11000000)
-#define PVC_DATA_SHIFT_200	24
-#define PVC_DATA_M_200		(0xFF << PVC_DATA_SHIFT_200)
-#define PVC_E_200		(1 << 16)
-#define PVC_RW_200		(1 << 17)
-#define PVC_RS_200		(1 << 18)
diff --git a/include/asm-mips/lasat/serial.h b/include/asm-mips/lasat/serial.h
deleted file mode 100644
index 9e88c76..0000000
--- a/include/asm-mips/lasat/serial.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <asm/lasat/lasat.h>
-
-/* Lasat 100 boards serial configuration */
-#define LASAT_BASE_BAUD_100 		( 7372800 / 16 )
-#define LASAT_UART_REGS_BASE_100	0x1c8b0000
-#define LASAT_UART_REGS_SHIFT_100	2
-#define LASATINT_UART_100		8
-
-/* * LASAT 200 boards serial configuration */
-#define LASAT_BASE_BAUD_200		(100000000 / 16 / 12)
-#define LASAT_UART_REGS_BASE_200	(Vrc5074_PHYS_BASE + 0x0300)
-#define LASAT_UART_REGS_SHIFT_200	3
-#define LASATINT_UART_200		13
diff --git a/include/asm-mips/mach-au1x00/au1xxx_gpio.h b/include/asm-mips/mach-au1x00/au1xxx_gpio.h
deleted file mode 100644
index 27911e0..0000000
--- a/include/asm-mips/mach-au1x00/au1xxx_gpio.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __AU1XXX_GPIO_H
-#define __AU1XXX_GPIO_H
-
-void au1xxx_gpio1_set_inputs(void);
-void au1xxx_gpio_tristate(int signal);
-void au1xxx_gpio_write(int signal, int value);
-int  au1xxx_gpio_read(int signal);
-
-typedef volatile struct
-{
-	u32 dir;
-	u32 reserved;
-	u32 output;
-	u32 pinstate;
-	u32 inten;
-	u32 enable;
-
-} AU1X00_GPIO2;
-
-#endif //__AU1XXX_GPIO_H
diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/include/asm-mips/mach-au1x00/au1xxx_ide.h
index 8fcae21..4663e8b 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_ide.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_ide.h
@@ -88,26 +88,26 @@
 /*
  * Hitachi
  */
-        { "HITACHI_DK14FA-20"    ,       "ALL"           },
-        { "HTS726060M9AT00"      ,       "ALL"           },
+        { "HITACHI_DK14FA-20"    ,       NULL            },
+        { "HTS726060M9AT00"      ,       NULL            },
 /*
  * Maxtor
  */
-        { "Maxtor 6E040L0"      ,       "ALL"           },
-        { "Maxtor 6Y080P0"      ,       "ALL"           },
-        { "Maxtor 6Y160P0"      ,       "ALL"           },
+        { "Maxtor 6E040L0"      ,       NULL            },
+        { "Maxtor 6Y080P0"      ,       NULL            },
+        { "Maxtor 6Y160P0"      ,       NULL            },
 /*
  * Seagate
  */
-        { "ST3120026A"          ,       "ALL"           },
-        { "ST320014A"           ,       "ALL"           },
-        { "ST94011A"            ,       "ALL"           },
-        { "ST340016A"           ,       "ALL"           },
+        { "ST3120026A"          ,       NULL            },
+        { "ST320014A"           ,       NULL            },
+        { "ST94011A"            ,       NULL            },
+        { "ST340016A"           ,       NULL            },
 /*
  * Western Digital
  */
-        { "WDC WD400UE-00HCT0"  ,       "ALL"           },
-        { "WDC WD400JB-00JJC0"  ,       "ALL"           },
+        { "WDC WD400UE-00HCT0"  ,       NULL            },
+        { "WDC WD400JB-00JJC0"  ,       NULL            },
         { NULL                  ,       NULL            }
 };
 
@@ -116,9 +116,9 @@
 /*
  * Western Digital
  */
-        { "WDC WD100EB-00CGH0"  ,       "ALL"           },
-        { "WDC WD200BB-00AUA1"  ,       "ALL"           },
-        { "WDC AC24300L"        ,       "ALL"           },
+        { "WDC WD100EB-00CGH0"  ,       NULL            },
+        { "WDC WD200BB-00AUA1"  ,       NULL            },
+        { "WDC AC24300L"        ,       NULL            },
         { NULL                  ,       NULL            }
 };
 #endif
diff --git a/include/asm-mips/mach-au1x00/gpio.h b/include/asm-mips/mach-au1x00/gpio.h
new file mode 100644
index 0000000..2dc61e0
--- /dev/null
+++ b/include/asm-mips/mach-au1x00/gpio.h
@@ -0,0 +1,69 @@
+#ifndef _AU1XXX_GPIO_H_
+#define _AU1XXX_GPIO_H_
+
+#include <linux/types.h>
+
+#define AU1XXX_GPIO_BASE	200
+
+struct au1x00_gpio2 {
+	u32	dir;
+	u32	reserved;
+	u32	output;
+	u32	pinstate;
+	u32	inten;
+	u32	enable;
+};
+
+extern int au1xxx_gpio_get_value(unsigned gpio);
+extern void au1xxx_gpio_set_value(unsigned gpio, int value);
+extern int au1xxx_gpio_direction_input(unsigned gpio);
+extern int au1xxx_gpio_direction_output(unsigned gpio, int value);
+
+
+/* Wrappers for the arch-neutral GPIO API */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	/* Not yet implemented */
+	return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	/* Not yet implemented */
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	return au1xxx_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+	return au1xxx_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return au1xxx_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	au1xxx_gpio_set_value(gpio, value);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return irq;
+}
+
+/* For cansleep */
+#include <asm-generic/gpio.h>
+
+#endif /* _AU1XXX_GPIO_H_ */
diff --git a/include/asm-mips/mach-au1x00/ioremap.h b/include/asm-mips/mach-au1x00/ioremap.h
index 098fca4..364cea2 100644
--- a/include/asm-mips/mach-au1x00/ioremap.h
+++ b/include/asm-mips/mach-au1x00/ioremap.h
@@ -28,4 +28,15 @@
 	return __fixup_bigphys_addr(phys_addr, size);
 }
 
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+	unsigned long flags)
+{
+	return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+	return 0;
+}
+
 #endif /* __ASM_MACH_AU1X00_IOREMAP_H */
diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h
index 684a501..9c9d2b9 100644
--- a/include/asm-mips/mach-cobalt/cobalt.h
+++ b/include/asm-mips/mach-cobalt/cobalt.h
@@ -30,7 +30,6 @@
 #define COBALT_CPU_IRQ		MIPS_CPU_IRQ_BASE
 
 #define COBALT_GALILEO_IRQ	(COBALT_CPU_IRQ + 2)
-#define COBALT_SCC_IRQ          (COBALT_CPU_IRQ + 3)	/* pre-production has 85C30 */
 #define COBALT_RAQ_SCSI_IRQ	(COBALT_CPU_IRQ + 3)
 #define COBALT_ETH0_IRQ		(COBALT_CPU_IRQ + 3)
 #define COBALT_QUBE1_ETH0_IRQ	(COBALT_CPU_IRQ + 4)
@@ -71,10 +70,6 @@
 
 extern int cobalt_board_id;
 
-#define PCI_CFG_SET(devfn,where)					\
-	GT_WRITE(GT_PCI0_CFGADDR_OFS, (0x80000000 | (PCI_SLOT (devfn) << 11) |		\
-		(PCI_FUNC (devfn) << 8) | (where)))
-
 #define COBALT_LED_PORT		(*(volatile unsigned char *) CKSEG1ADDR(0x1c000000))
 # define COBALT_LED_BAR_LEFT	(1 << 0)	/* Qube */
 # define COBALT_LED_BAR_RIGHT	(1 << 1)	/* Qube */
diff --git a/include/asm-mips/mach-ev64120/mach-gt64120.h b/include/asm-mips/mach-ev64120/mach-gt64120.h
deleted file mode 100644
index 7e272ce5..0000000
--- a/include/asm-mips/mach-ev64120/mach-gt64120.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  This is a direct copy of the ev96100.h file, with a global
- * search and replace.  The numbers are the same.
- *
- *  The reason I'm duplicating this is so that the 64120/96100
- * defines won't be confusing in the source code.
- */
-#ifndef __ASM_GALILEO_BOARDS_MIPS_EV64120_H
-#define __ASM_GALILEO_BOARDS_MIPS_EV64120_H
-
-/*
- *   GT64120 config space base address
- */
-extern unsigned long gt64120_base;
-
-#define GT64120_BASE	(gt64120_base)
-
-/*
- *   PCI Bus allocation
- */
-#define GT_PCI_MEM_BASE	0x12000000UL
-#define GT_PCI_MEM_SIZE	0x02000000UL
-#define GT_PCI_IO_BASE	0x10000000UL
-#define GT_PCI_IO_SIZE	0x02000000UL
-#define GT_ISA_IO_BASE	PCI_IO_BASE
-
-/*
- *   Duart I/O ports.
- */
-#define EV64120_COM1_BASE_ADDR	(0x1d000000 + 0x20)
-#define EV64120_COM2_BASE_ADDR	(0x1d000000 + 0x00)
-
-
-/*
- *   EV64120 interrupt controller register base.
- */
-#define EV64120_ICTRL_REGS_BASE	(KSEG1ADDR(0x1f000000))
-
-/*
- *   EV64120 UART register base.
- */
-#define EV64120_UART0_REGS_BASE	(KSEG1ADDR(EV64120_COM1_BASE_ADDR))
-#define EV64120_UART1_REGS_BASE	(KSEG1ADDR(EV64120_COM2_BASE_ADDR))
-#define EV64120_BASE_BAUD ( 3686400 / 16 )
-#define EV64120_UART_IRQ	6
-
-/*
- * PCI interrupts will come in on either the INTA or INTD interrups lines,
- * which are mapped to the #2 and #5 interrupt pins of the MIPS.  On our
- * boards, they all either come in on IntD or they all come in on IntA, they
- * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the
- * "requested" interrupt numbers and go through the list whenever we get an
- * IntA/D.
- *
- * Interrupts < 8 are directly wired to the processor; PCI INTA is 8 and
- * INTD is 11.
- */
-#define GT_TIMER	4
-#define GT_INTA		2
-#define GT_INTD		5
-
-#endif /* __ASM_GALILEO_BOARDS_MIPS_EV64120_H */
diff --git a/include/asm-mips/mach-generic/gpio.h b/include/asm-mips/mach-generic/gpio.h
new file mode 100644
index 0000000..6eaf5ef
--- /dev/null
+++ b/include/asm-mips/mach-generic/gpio.h
@@ -0,0 +1,15 @@
+#ifndef __ASM_MACH_GENERIC_GPIO_H
+#define __ASM_MACH_GENERIC_GPIO_H
+
+int gpio_request(unsigned gpio, const char *label);
+void gpio_free(unsigned gpio);
+int gpio_direction_input(unsigned gpio);
+int gpio_direction_output(unsigned gpio, int value);
+int gpio_get_value(unsigned gpio);
+void gpio_set_value(unsigned gpio, int value);
+int gpio_to_irq(unsigned gpio);
+int irq_to_gpio(unsigned irq);
+
+#include <asm-generic/gpio.h>		/* cansleep wrappers */
+
+#endif /* __ASM_MACH_GENERIC_GPIO_H */
diff --git a/include/asm-mips/mach-generic/ioremap.h b/include/asm-mips/mach-generic/ioremap.h
index 9b64ff6..b379938 100644
--- a/include/asm-mips/mach-generic/ioremap.h
+++ b/include/asm-mips/mach-generic/ioremap.h
@@ -20,4 +20,15 @@
 	return phys_addr;
 }
 
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+	unsigned long flags)
+{
+	return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+	return 0;
+}
+
 #endif /* __ASM_MACH_GENERIC_IOREMAP_H */
diff --git a/include/asm-mips/mach-generic/spaces.h b/include/asm-mips/mach-generic/spaces.h
index 0ae9997..c9fa4b1 100644
--- a/include/asm-mips/mach-generic/spaces.h
+++ b/include/asm-mips/mach-generic/spaces.h
@@ -10,38 +10,54 @@
 #ifndef _ASM_MACH_GENERIC_SPACES_H
 #define _ASM_MACH_GENERIC_SPACES_H
 
+#include <linux/const.h>
+
+/*
+ * This gives the physical RAM offset.
+ */
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET		_AC(0, UL)
+#endif
 
 #ifdef CONFIG_32BIT
 
-#define CAC_BASE		0x80000000
-#define IO_BASE			0xa0000000
-#define UNCAC_BASE		0xa0000000
-#define MAP_BASE		0xc0000000
+#define CAC_BASE		_AC(0x80000000, UL)
+#define IO_BASE			_AC(0xa0000000, UL)
+#define UNCAC_BASE		_AC(0xa0000000, UL)
 
-/*
- * This handles the memory map.
- * We handle pages at KSEG0 for kernels with 32 bit address space.
- */
-#define PAGE_OFFSET		0x80000000UL
+#ifndef MAP_BASE
+#define MAP_BASE		_AC(0xc0000000, UL)
+#endif
 
 /*
  * Memory above this physical address will be considered highmem.
  */
 #ifndef HIGHMEM_START
-#define HIGHMEM_START		0x20000000UL
+#define HIGHMEM_START		_AC(0x20000000, UL)
 #endif
 
 #endif /* CONFIG_32BIT */
 
 #ifdef CONFIG_64BIT
 
-/*
- * This handles the memory map.
- */
+#ifndef CAC_BASE
 #ifdef CONFIG_DMA_NONCOHERENT
-#define PAGE_OFFSET	0x9800000000000000UL
+#define CAC_BASE		_AC(0x9800000000000000, UL)
 #else
-#define PAGE_OFFSET	0xa800000000000000UL
+#define CAC_BASE		_AC(0xa800000000000000, UL)
+#endif
+#endif
+
+#ifndef IO_BASE
+#define IO_BASE			_AC(0x9000000000000000, UL)
+#endif
+
+#ifndef UNCAC_BASE
+#define UNCAC_BASE		_AC(0x9000000000000000, UL)
+#endif
+
+#ifndef MAP_BASE
+#define MAP_BASE		_AC(0xc000000000000000, UL)
 #endif
 
 /*
@@ -50,22 +66,20 @@
  * in the distant future.  Nobody will care for a few years :-)
  */
 #ifndef HIGHMEM_START
-#define HIGHMEM_START		(1UL << 59UL)
+#define HIGHMEM_START		(_AC(1, UL) << _AC(59, UL))
 #endif
 
-#ifdef CONFIG_DMA_NONCOHERENT
-#define CAC_BASE		0x9800000000000000UL
-#else
-#define CAC_BASE		0xa800000000000000UL
-#endif
-#define IO_BASE			0x9000000000000000UL
-#define UNCAC_BASE		0x9000000000000000UL
-#define MAP_BASE		0xc000000000000000UL
-
 #define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
 #define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
 #define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
 
 #endif /* CONFIG_64BIT */
 
+/*
+ * This handles the memory map.
+ */
+#ifndef PAGE_OFFSET
+#define PAGE_OFFSET		(CAC_BASE + PHYS_OFFSET)
+#endif
+
 #endif /* __ASM_MACH_GENERIC_SPACES_H */
diff --git a/include/asm-mips/mach-ip22/spaces.h b/include/asm-mips/mach-ip22/spaces.h
index ab20c02..7f9fa6f 100644
--- a/include/asm-mips/mach-ip22/spaces.h
+++ b/include/asm-mips/mach-ip22/spaces.h
@@ -11,44 +11,17 @@
 #define _ASM_MACH_IP22_SPACES_H
 
 
-#ifdef CONFIG_32BIT
-
-#define CAC_BASE		0x80000000
-#define IO_BASE			0xa0000000
-#define UNCAC_BASE		0xa0000000
-#define MAP_BASE		0xc0000000
-
-/*
- * This handles the memory map.
- * We handle pages at KSEG0 for kernels with 32 bit address space.
- */
-#define PAGE_OFFSET		0x80000000UL
-
-/*
- * Memory above this physical address will be considered highmem.
- */
-#ifndef HIGHMEM_START
-#define HIGHMEM_START		0x20000000UL
-#endif
-
-#endif /* CONFIG_32BIT */
-
 #ifdef CONFIG_64BIT
-#define PAGE_OFFSET		0xffffffff80000000UL
 
-#ifndef HIGHMEM_START
-#define HIGHMEM_START		(1UL << 59UL)
-#endif
+#define PAGE_OFFSET		0xffffffff80000000UL
 
 #define CAC_BASE		0xffffffff80000000
 #define IO_BASE			0xffffffffa0000000
 #define UNCAC_BASE		0xffffffffa0000000
 #define MAP_BASE		0xc000000000000000
 
-#define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
-#define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
-
 #endif /* CONFIG_64BIT */
 
+#include <asm/mach-generic/spaces.h>
+
 #endif /* __ASM_MACH_IP22_SPACES_H */
diff --git a/include/asm-mips/mach-ip27/spaces.h b/include/asm-mips/mach-ip27/spaces.h
index 45e6178..b18802a 100644
--- a/include/asm-mips/mach-ip27/spaces.h
+++ b/include/asm-mips/mach-ip27/spaces.h
@@ -14,22 +14,17 @@
  * IP27 uses the R10000's uncached attribute feature.  Attribute 3 selects
  * uncached memory addressing.
  */
-#define CAC_BASE		0xa800000000000000
 
 #define HSPEC_BASE		0x9000000000000000
 #define IO_BASE			0x9200000000000000
 #define MSPEC_BASE		0x9400000000000000
 #define UNCAC_BASE		0x9600000000000000
-#define MAP_BASE		0xc000000000000000
 
-#define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
-#define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
 #define TO_MSPEC(x)		(MSPEC_BASE | ((x) & TO_PHYS_MASK))
 #define TO_HSPEC(x)		(HSPEC_BASE | ((x) & TO_PHYS_MASK))
 
-#define PAGE_OFFSET		CAC_BASE
-
 #define HIGHMEM_START		(~0UL)
 
+#include <asm/mach-generic/spaces.h>
+
 #endif /* _ASM_MACH_IP27_SPACES_H */
diff --git a/include/asm-mips/mach-ip32/spaces.h b/include/asm-mips/mach-ip32/spaces.h
deleted file mode 100644
index 44abe5c..0000000
--- a/include/asm-mips/mach-ip32/spaces.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 1999, 2000, 03, 04, 05 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2000, 2002  Maciej W. Rozycki
- * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
- */
-#ifndef _ASM_MACH_IP32_SPACES_H
-#define _ASM_MACH_IP32_SPACES_H
-
-/*
- * Memory above this physical address will be considered highmem.
- * Fixme: 59 bits is a fictive number and makes assumptions about processors
- * in the distant future.  Nobody will care for a few years :-)
- */
-#ifndef HIGHMEM_START
-#define HIGHMEM_START		(1UL << 59UL)
-#endif
-
-#define CAC_BASE		0x9800000000000000UL
-#define IO_BASE			0x9000000000000000UL
-#define UNCAC_BASE		0x9000000000000000UL
-#define MAP_BASE		0xc000000000000000UL
-
-#define TO_PHYS(x)		(             ((x) & TO_PHYS_MASK))
-#define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
-
-/*
- * This handles the memory map.
- */
-#define PAGE_OFFSET		CAC_BASE
-
-#endif /* __ASM_MACH_IP32_SPACES_H */
diff --git a/include/asm-mips/mach-jmr3927/ioremap.h b/include/asm-mips/mach-jmr3927/ioremap.h
new file mode 100644
index 0000000..aa131ad
--- /dev/null
+++ b/include/asm-mips/mach-jmr3927/ioremap.h
@@ -0,0 +1,38 @@
+/*
+ *	include/asm-mips/mach-jmr3927/ioremap.h
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_MACH_JMR3927_IOREMAP_H
+#define __ASM_MACH_JMR3927_IOREMAP_H
+
+#include <linux/types.h>
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+	unsigned long flags)
+{
+#define TXX9_DIRECTMAP_BASE	0xff000000ul
+	if (offset >= TXX9_DIRECTMAP_BASE &&
+	    offset < TXX9_DIRECTMAP_BASE + 0xf0000)
+		return (void __iomem *)offset;
+	return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr >= TXX9_DIRECTMAP_BASE;
+}
+
+#endif /* __ASM_MACH_JMR3927_IOREMAP_H */
diff --git a/include/asm-mips/mach-lasat/mach-gt64120.h b/include/asm-mips/mach-lasat/mach-gt64120.h
deleted file mode 100644
index 1a9ad45..0000000
--- a/include/asm-mips/mach-lasat/mach-gt64120.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  This is a direct copy of the ev96100.h file, with a global
- * search and replace.  The numbers are the same.
- *
- *  The reason I'm duplicating this is so that the 64120/96100
- * defines won't be confusing in the source code.
- */
-#ifndef _ASM_GT64120_LASAT_GT64120_DEP_H
-#define _ASM_GT64120_LASAT_GT64120_DEP_H
-
-/*
- *   GT64120 config space base address on Lasat 100
- */
-#define GT64120_BASE	(KSEG1ADDR(0x14000000))
-
-/*
- *   PCI Bus allocation
- *
- *   (Guessing ...)
- */
-#define GT_PCI_MEM_BASE	0x12000000UL
-#define GT_PCI_MEM_SIZE	0x02000000UL
-#define GT_PCI_IO_BASE	0x10000000UL
-#define GT_PCI_IO_SIZE	0x02000000UL
-#define GT_ISA_IO_BASE	PCI_IO_BASE
-
-#endif /* _ASM_GT64120_LASAT_GT64120_DEP_H */
diff --git a/include/asm-mips/mach-lemote/dma-coherence.h b/include/asm-mips/mach-lemote/dma-coherence.h
new file mode 100644
index 0000000..7e91477
--- /dev/null
+++ b/include/asm-mips/mach-lemote/dma-coherence.h
@@ -0,0 +1,42 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006, 07  Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ */
+#ifndef __ASM_MACH_LEMOTE_DMA_COHERENCE_H
+#define __ASM_MACH_LEMOTE_DMA_COHERENCE_H
+
+struct device;
+
+static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
+					  size_t size)
+{
+	return virt_to_phys(addr) | 0x80000000;
+}
+
+static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
+					       struct page *page)
+{
+	return page_to_phys(page) | 0x80000000;
+}
+
+static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+	return dma_addr & 0x7fffffff;
+}
+
+static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+	return 0;
+}
+
+#endif /* __ASM_MACH_LEMOTE_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-lemote/mc146818rtc.h b/include/asm-mips/mach-lemote/mc146818rtc.h
new file mode 100644
index 0000000..ed5147e
--- /dev/null
+++ b/include/asm-mips/mach-lemote/mc146818rtc.h
@@ -0,0 +1,36 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998, 2001, 03, 07 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * RTC routines for PC style attached Dallas chip.
+ */
+#ifndef __ASM_MACH_LEMOTE_MC146818RTC_H
+#define __ASM_MACH_LEMOTE_MC146818RTC_H
+
+#include <linux/io.h>
+
+#define RTC_PORT(x)	(0x70 + (x))
+#define RTC_IRQ		8
+
+static inline unsigned char CMOS_READ(unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	return inb_p(RTC_PORT(1));
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	outb_p(data, RTC_PORT(1));
+}
+
+#define RTC_ALWAYS_BCD	0
+
+#ifndef mc146818_decode_year
+#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970)
+#endif
+
+#endif /* __ASM_MACH_LEMOTE_MC146818RTC_H */
diff --git a/include/asm-mips/mach-mips/kernel-entry-init.h b/include/asm-mips/mach-mips/kernel-entry-init.h
new file mode 100644
index 0000000..0b793e7
--- /dev/null
+++ b/include/asm-mips/mach-mips/kernel-entry-init.h
@@ -0,0 +1,52 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Chris Dearman (chris@mips.com)
+ * Copyright (C) 2007 Mips Technologies, Inc.
+ */
+#ifndef __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
+#define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
+
+	.macro	kernel_entry_setup
+#ifdef CONFIG_MIPS_MT_SMTC
+	mfc0	t0, CP0_CONFIG
+	bgez	t0, 9f
+	mfc0	t0, CP0_CONFIG, 1
+	bgez	t0, 9f
+	mfc0	t0, CP0_CONFIG, 2
+	bgez	t0, 9f
+	mfc0	t0, CP0_CONFIG, 3
+	and	t0, 1<<2
+	bnez	t0, 0f
+9:
+	/* Assume we came from YAMON... */
+	PTR_LA	v0, 0x9fc00534	/* YAMON print */
+	lw	v0, (v0)
+	move	a0, zero
+	PTR_LA	a1, nonmt_processor
+	jal	v0
+
+	PTR_LA	v0, 0x9fc00520	/* YAMON exit */
+	lw	v0, (v0)
+	li	a0, 1
+	jal	v0
+
+1:	b	1b
+
+	__INITDATA
+nonmt_processor:
+	.asciz	"SMTC kernel requires the MT ASE to run\n"
+	__FINIT
+0:
+#endif
+	.endm
+
+/*
+ * Do SMP slave processor setup necessary before we can safely execute C code.
+ */
+	.macro	smp_slave_setup
+	.endm
+
+#endif /* __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H */
diff --git a/include/asm-mips/mach-sim/cpu-feature-overrides.h b/include/asm-mips/mach-mipssim/cpu-feature-overrides.h
similarity index 100%
rename from include/asm-mips/mach-sim/cpu-feature-overrides.h
rename to include/asm-mips/mach-mipssim/cpu-feature-overrides.h
diff --git a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
deleted file mode 100644
index 57a12de..0000000
--- a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- * Copyright (C) 2004 Ralf Baechle
- */
-#ifndef __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-#define __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-
-/*
- * Momentum Ocelot-3 is based on Rm7900 processor which
- * is based on the E9000 core.
- */
-#define cpu_has_watch		1
-#define cpu_has_mips16		0
-#define cpu_has_divec		0
-#define cpu_has_vce		0
-#define cpu_has_cache_cdex_p	0
-#define cpu_has_cache_cdex_s	0
-#define cpu_has_prefetch	1
-#define cpu_has_mcheck		0
-#define cpu_has_ejtag		0
-
-#define cpu_has_llsc		1
-#define cpu_has_vtag_icache	0
-#define cpu_has_dc_aliases	0
-#define cpu_has_ic_fills_f_dc	0
-#define cpu_has_dsp		0
-#define cpu_icache_snoops_remote_store	0
-
-#define cpu_has_nofpuex 	0
-#define cpu_has_64bits		1
-
-#define cpu_has_inclusive_pcaches	0
-
-#define cpu_dcache_line_size()	32
-#define cpu_icache_line_size()	32
-#define cpu_scache_line_size()	32
-
-#define cpu_has_mips32r1	0
-#define cpu_has_mips32r2	0
-#define cpu_has_mips64r1	0
-#define cpu_has_mips64r2	0
-
-#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-tx49xx/ioremap.h b/include/asm-mips/mach-tx49xx/ioremap.h
new file mode 100644
index 0000000..88cf546
--- /dev/null
+++ b/include/asm-mips/mach-tx49xx/ioremap.h
@@ -0,0 +1,42 @@
+/*
+ *	include/asm-mips/mach-tx49xx/ioremap.h
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_MACH_TX49XX_IOREMAP_H
+#define __ASM_MACH_TX49XX_IOREMAP_H
+
+#include <linux/types.h>
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+	unsigned long flags)
+{
+#ifdef CONFIG_64BIT
+#define TXX9_DIRECTMAP_BASE	0xfff000000ul
+#else
+#define TXX9_DIRECTMAP_BASE	0xff000000ul
+#endif
+	if (offset >= TXX9_DIRECTMAP_BASE &&
+	    offset < TXX9_DIRECTMAP_BASE + 0x400000)
+		return (void __iomem *)(unsigned long)(int)offset;
+	return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr >= (unsigned long)(int)TXX9_DIRECTMAP_BASE;
+}
+
+#endif /* __ASM_MACH_TX49XX_IOREMAP_H */
diff --git a/include/asm-mips/mips-boards/bonito64.h b/include/asm-mips/mips-boards/bonito64.h
index cd71256..dc3fc32 100644
--- a/include/asm-mips/mips-boards/bonito64.h
+++ b/include/asm-mips/mips-boards/bonito64.h
@@ -26,7 +26,12 @@
 /* offsets from base register */
 #define BONITO(x)	(x)
 
-#else /* !__ASSEMBLY__ */
+#elif defined(CONFIG_LEMOTE_FULONG)
+
+#define BONITO(x) (*(volatile u32 *)((char *)CKSEG1ADDR(BONITO_REG_BASE) + (x)))
+#define BONITO_IRQ_BASE   32
+
+#else
 
 /*
  * Algorithmics Bonito64 system controller register base.
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 89c8192..706b369 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -7,7 +7,7 @@
  * Copyright (C) 2000 Silicon Graphics, Inc.
  * Modified for further R[236]000 support by Paul M. Antoine, 1996.
  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2000, 07 MIPS Technologies, Inc.
  * Copyright (C) 2003, 2004  Maciej W. Rozycki
  */
 #ifndef _ASM_MIPSREGS_H
@@ -15,6 +15,7 @@
 
 #include <linux/linkage.h>
 #include <asm/hazards.h>
+#include <asm/war.h>
 
 /*
  * The following macros are especially useful for __asm__
@@ -533,9 +534,13 @@
 #define MIPS_CONF3_VEIC		(_ULCAST_(1) <<  6)
 #define MIPS_CONF3_LPA		(_ULCAST_(1) <<  7)
 #define MIPS_CONF3_DSP		(_ULCAST_(1) << 10)
+#define MIPS_CONF3_ULRI		(_ULCAST_(1) << 13)
 
 #define MIPS_CONF7_WII		(_ULCAST_(1) << 31)
 
+#define MIPS_CONF7_RPS		(_ULCAST_(1) << 2)
+
+
 /*
  * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
  */
@@ -772,6 +777,9 @@
 #define read_c0_context()	__read_ulong_c0_register($4, 0)
 #define write_c0_context(val)	__write_ulong_c0_register($4, 0, val)
 
+#define read_c0_userlocal()	__read_ulong_c0_register($4, 2)
+#define write_c0_userlocal(val)	__write_ulong_c0_register($4, 2, val)
+
 #define read_c0_pagemask()	__read_32bit_c0_register($5, 0)
 #define write_c0_pagemask(val)	__write_32bit_c0_register($5, 0, val)
 
@@ -1294,10 +1302,39 @@
 
 static inline void tlb_read(void)
 {
+#if MIPS34K_MISSED_ITLB_WAR
+	int res = 0;
+
+	__asm__ __volatile__(
+	"	.set	push					\n"
+	"	.set	noreorder				\n"
+	"	.set	noat					\n"
+	"	.set	mips32r2				\n"
+	"	.word	0x41610001		# dvpe $1	\n"
+	"	move	%0, $1					\n"
+	"	ehb						\n"
+	"	.set	pop					\n"
+	: "=r" (res));
+
+	instruction_hazard();
+#endif
+
 	__asm__ __volatile__(
 		".set noreorder\n\t"
 		"tlbr\n\t"
 		".set reorder");
+
+#if MIPS34K_MISSED_ITLB_WAR
+	if ((res & _ULCAST_(1)))
+		__asm__ __volatile__(
+		"	.set	push				\n"
+		"	.set	noreorder			\n"
+		"	.set	noat				\n"
+		"	.set	mips32r2			\n"
+		"	.word	0x41600021	# evpe		\n"
+		"	ehb					\n"
+		"	.set	pop				\n");
+#endif
 }
 
 static inline void tlb_write_indexed(void)
diff --git a/include/asm-mips/module.h b/include/asm-mips/module.h
index c5ef324..de6d09e 100644
--- a/include/asm-mips/module.h
+++ b/include/asm-mips/module.h
@@ -112,6 +112,8 @@
 #define MODULE_PROC_FAMILY "RM9000 "
 #elif defined CONFIG_CPU_SB1
 #define MODULE_PROC_FAMILY "SB1 "
+#elif defined CONFIG_CPU_LOONGSON2
+#define MODULE_PROC_FAMILY "LOONGSON2 "
 #else
 #error MODULE_PROC_FAMILY undefined for your processor configuration
 #endif
diff --git a/include/asm-mips/nile4.h b/include/asm-mips/nile4.h
deleted file mode 100644
index c3ca959..0000000
--- a/include/asm-mips/nile4.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- *  asm-mips/nile4.h -- NEC Vrc-5074 Nile 4 definitions
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  This file is based on the following documentation:
- *
- *	NEC Vrc 5074 System Controller Data Sheet, June 1998
- */
-
-#ifndef _ASM_NILE4_H
-#define _ASM_NILE4_H
-
-#define NILE4_BASE		0xbfa00000
-#define NILE4_SIZE		0x00200000		/* 2 MB */
-
-
-    /*
-     *  Physical Device Address Registers (PDARs)
-     */
-
-#define NILE4_SDRAM0	0x0000	/* SDRAM Bank 0 [R/W] */
-#define NILE4_SDRAM1	0x0008	/* SDRAM Bank 1 [R/W] */
-#define NILE4_DCS2	0x0010	/* Device Chip-Select 2 [R/W] */
-#define NILE4_DCS3	0x0018	/* Device Chip-Select 3 [R/W] */
-#define NILE4_DCS4	0x0020	/* Device Chip-Select 4 [R/W] */
-#define NILE4_DCS5	0x0028	/* Device Chip-Select 5 [R/W] */
-#define NILE4_DCS6	0x0030	/* Device Chip-Select 6 [R/W] */
-#define NILE4_DCS7	0x0038	/* Device Chip-Select 7 [R/W] */
-#define NILE4_DCS8	0x0040	/* Device Chip-Select 8 [R/W] */
-#define NILE4_PCIW0	0x0060	/* PCI Address Window 0 [R/W] */
-#define NILE4_PCIW1	0x0068	/* PCI Address Window 1 [R/W] */
-#define NILE4_INTCS	0x0070	/* Controller Internal Registers and Devices */
-				/* [R/W] */
-#define NILE4_BOOTCS	0x0078	/* Boot ROM Chip-Select [R/W] */
-
-
-    /*
-     *  CPU Interface Registers
-     */
-
-#define NILE4_CPUSTAT	0x0080	/* CPU Status [R/W] */
-#define NILE4_INTCTRL	0x0088	/* Interrupt Control [R/W] */
-#define NILE4_INTSTAT0	0x0090	/* Interrupt Status 0 [R] */
-#define NILE4_INTSTAT1	0x0098	/* Interrupt Status 1 and CPU Interrupt */
-				/* Enable [R/W] */
-#define NILE4_INTCLR	0x00A0	/* Interrupt Clear [R/W] */
-#define NILE4_INTPPES	0x00A8	/* PCI Interrupt Control [R/W] */
-
-
-    /*
-     *  Memory-Interface Registers
-     */
-
-#define NILE4_MEMCTRL	0x00C0	/* Memory Control */
-#define NILE4_ACSTIME	0x00C8	/* Memory Access Timing [R/W] */
-#define NILE4_CHKERR	0x00D0	/* Memory Check Error Status [R] */
-
-
-    /*
-     *  PCI-Bus Registers
-     */
-
-#define NILE4_PCICTRL	0x00E0	/* PCI Control [R/W] */
-#define NILE4_PCIARB	0x00E8	/* PCI Arbiter [R/W] */
-#define NILE4_PCIINIT0	0x00F0	/* PCI Master (Initiator) 0 [R/W] */
-#define NILE4_PCIINIT1	0x00F8	/* PCI Master (Initiator) 1 [R/W] */
-#define NILE4_PCIERR	0x00B8	/* PCI Error [R/W] */
-
-
-    /*
-     *  Local-Bus Registers
-     */
-
-#define NILE4_LCNFG	0x0100	/* Local Bus Configuration [R/W] */
-#define NILE4_LCST2	0x0110	/* Local Bus Chip-Select Timing 2 [R/W] */
-#define NILE4_LCST3	0x0118	/* Local Bus Chip-Select Timing 3 [R/W] */
-#define NILE4_LCST4	0x0120	/* Local Bus Chip-Select Timing 4 [R/W] */
-#define NILE4_LCST5	0x0128	/* Local Bus Chip-Select Timing 5 [R/W] */
-#define NILE4_LCST6	0x0130	/* Local Bus Chip-Select Timing 6 [R/W] */
-#define NILE4_LCST7	0x0138	/* Local Bus Chip-Select Timing 7 [R/W] */
-#define NILE4_LCST8	0x0140	/* Local Bus Chip-Select Timing 8 [R/W] */
-#define NILE4_DCSFN	0x0150	/* Device Chip-Select Muxing and Output */
-				/* Enables [R/W] */
-#define NILE4_DCSIO	0x0158	/* Device Chip-Selects As I/O Bits [R/W] */
-#define NILE4_BCST	0x0178	/* Local Boot Chip-Select Timing [R/W] */
-
-
-    /*
-     *  DMA Registers
-     */
-
-#define NILE4_DMACTRL0	0x0180	/* DMA Control 0 [R/W] */
-#define NILE4_DMASRCA0	0x0188	/* DMA Source Address 0 [R/W] */
-#define NILE4_DMADESA0	0x0190	/* DMA Destination Address 0 [R/W] */
-#define NILE4_DMACTRL1	0x0198	/* DMA Control 1 [R/W] */
-#define NILE4_DMASRCA1	0x01A0	/* DMA Source Address 1 [R/W] */
-#define NILE4_DMADESA1	0x01A8	/* DMA Destination Address 1 [R/W] */
-
-
-    /*
-     *  Timer Registers
-     */
-
-#define NILE4_T0CTRL	0x01C0	/* SDRAM Refresh Control [R/W] */
-#define NILE4_T0CNTR	0x01C8	/* SDRAM Refresh Counter [R/W] */
-#define NILE4_T1CTRL	0x01D0	/* CPU-Bus Read Time-Out Control [R/W] */
-#define NILE4_T1CNTR	0x01D8	/* CPU-Bus Read Time-Out Counter [R/W] */
-#define NILE4_T2CTRL	0x01E0	/* General-Purpose Timer Control [R/W] */
-#define NILE4_T2CNTR	0x01E8	/* General-Purpose Timer Counter [R/W] */
-#define NILE4_T3CTRL	0x01F0	/* Watchdog Timer Control [R/W] */
-#define NILE4_T3CNTR	0x01F8	/* Watchdog Timer Counter [R/W] */
-
-
-    /*
-     *  PCI Configuration Space Registers
-     */
-
-#define NILE4_PCI_BASE	0x0200
-
-#define NILE4_VID	0x0200	/* PCI Vendor ID [R] */
-#define NILE4_DID	0x0202	/* PCI Device ID [R] */
-#define NILE4_PCICMD	0x0204	/* PCI Command [R/W] */
-#define NILE4_PCISTS	0x0206	/* PCI Status [R/W] */
-#define NILE4_REVID	0x0208	/* PCI Revision ID [R] */
-#define NILE4_CLASS	0x0209	/* PCI Class Code [R] */
-#define NILE4_CLSIZ	0x020C	/* PCI Cache Line Size [R/W] */
-#define NILE4_MLTIM	0x020D	/* PCI Latency Timer [R/W] */
-#define NILE4_HTYPE	0x020E	/* PCI Header Type [R] */
-#define NILE4_BIST	0x020F	/* BIST [R] (unimplemented) */
-#define NILE4_BARC	0x0210	/* PCI Base Address Register Control [R/W] */
-#define NILE4_BAR0	0x0218	/* PCI Base Address Register 0 [R/W] */
-#define NILE4_BAR1	0x0220	/* PCI Base Address Register 1 [R/W] */
-#define NILE4_CIS	0x0228	/* PCI Cardbus CIS Pointer [R] */
-				/* (unimplemented) */
-#define NILE4_SSVID	0x022C	/* PCI Sub-System Vendor ID [R/W] */
-#define NILE4_SSID	0x022E	/* PCI Sub-System ID [R/W] */
-#define NILE4_ROM	0x0230	/* Expansion ROM Base Address [R] */
-				/* (unimplemented) */
-#define NILE4_INTLIN	0x023C	/* PCI Interrupt Line [R/W] */
-#define NILE4_INTPIN	0x023D	/* PCI Interrupt Pin [R] */
-#define NILE4_MINGNT	0x023E	/* PCI Min_Gnt [R] (unimplemented) */
-#define NILE4_MAXLAT	0x023F	/* PCI Max_Lat [R] (unimplemented) */
-#define NILE4_BAR2	0x0240	/* PCI Base Address Register 2 [R/W] */
-#define NILE4_BAR3	0x0248	/* PCI Base Address Register 3 [R/W] */
-#define NILE4_BAR4	0x0250	/* PCI Base Address Register 4 [R/W] */
-#define NILE4_BAR5	0x0258	/* PCI Base Address Register 5 [R/W] */
-#define NILE4_BAR6	0x0260	/* PCI Base Address Register 6 [R/W] */
-#define NILE4_BAR7	0x0268	/* PCI Base Address Register 7 [R/W] */
-#define NILE4_BAR8	0x0270	/* PCI Base Address Register 8 [R/W] */
-#define NILE4_BARB	0x0278	/* PCI Base Address Register BOOT [R/W] */
-
-
-    /*
-     *  Serial-Port Registers
-     */
-
-#define NILE4_UART_BASE	0x0300
-
-#define NILE4_UARTRBR	0x0300	/* UART Receiver Data Buffer [R] */
-#define NILE4_UARTTHR	0x0300	/* UART Transmitter Data Holding [W] */
-#define NILE4_UARTIER	0x0308	/* UART Interrupt Enable [R/W] */
-#define NILE4_UARTDLL	0x0300	/* UART Divisor Latch LSB [R/W] */
-#define NILE4_UARTDLM	0x0308	/* UART Divisor Latch MSB [R/W] */
-#define NILE4_UARTIIR	0x0310	/* UART Interrupt ID [R] */
-#define NILE4_UARTFCR	0x0310	/* UART FIFO Control [W] */
-#define NILE4_UARTLCR	0x0318	/* UART Line Control [R/W] */
-#define NILE4_UARTMCR	0x0320	/* UART Modem Control [R/W] */
-#define NILE4_UARTLSR	0x0328	/* UART Line Status [R/W] */
-#define NILE4_UARTMSR	0x0330	/* UART Modem Status [R/W] */
-#define NILE4_UARTSCR	0x0338	/* UART Scratch [R/W] */
-
-#define NILE4_UART_BASE_BAUD	520833	/* 100 MHz / 12 / 16 */
-
-
-    /*
-     *  Interrupt Lines
-     */
-
-#define NILE4_INT_CPCE	0	/* CPU-Interface Parity-Error Interrupt */
-#define NILE4_INT_CNTD	1	/* CPU No-Target Decode Interrupt */
-#define NILE4_INT_MCE	2	/* Memory-Check Error Interrupt */
-#define NILE4_INT_DMA	3	/* DMA Controller Interrupt */
-#define NILE4_INT_UART	4	/* UART Interrupt */
-#define NILE4_INT_WDOG	5	/* Watchdog Timer Interrupt */
-#define NILE4_INT_GPT	6	/* General-Purpose Timer Interrupt */
-#define NILE4_INT_LBRTD	7	/* Local-Bus Ready Timer Interrupt */
-#define NILE4_INT_INTA	8	/* PCI Interrupt Signal INTA# */
-#define NILE4_INT_INTB	9	/* PCI Interrupt Signal INTB# */
-#define NILE4_INT_INTC	10	/* PCI Interrupt Signal INTC# */
-#define NILE4_INT_INTD	11	/* PCI Interrupt Signal INTD# */
-#define NILE4_INT_INTE	12	/* PCI Interrupt Signal INTE# (ISA cascade) */
-#define NILE4_INT_RESV	13	/* Reserved */
-#define NILE4_INT_PCIS	14	/* PCI SERR# Interrupt */
-#define NILE4_INT_PCIE	15	/* PCI Internal Error Interrupt */
-
-
-    /*
-     *  Nile 4 Register Access
-     */
-
-static inline void nile4_sync(void)
-{
-    volatile u32 *p = (volatile u32 *)0xbfc00000;
-    (void)(*p);
-}
-
-static inline void nile4_out32(u32 offset, u32 val)
-{
-    *(volatile u32 *)(NILE4_BASE+offset) = val;
-    nile4_sync();
-}
-
-static inline u32 nile4_in32(u32 offset)
-{
-    u32 val = *(volatile u32 *)(NILE4_BASE+offset);
-    nile4_sync();
-    return val;
-}
-
-static inline void nile4_out16(u32 offset, u16 val)
-{
-    *(volatile u16 *)(NILE4_BASE+offset) = val;
-    nile4_sync();
-}
-
-static inline u16 nile4_in16(u32 offset)
-{
-    u16 val = *(volatile u16 *)(NILE4_BASE+offset);
-    nile4_sync();
-    return val;
-}
-
-static inline void nile4_out8(u32 offset, u8 val)
-{
-    *(volatile u8 *)(NILE4_BASE+offset) = val;
-    nile4_sync();
-}
-
-static inline u8 nile4_in8(u32 offset)
-{
-    u8 val = *(volatile u8 *)(NILE4_BASE+offset);
-    nile4_sync();
-    return val;
-}
-
-
-    /*
-     *  Physical Device Address Registers
-     */
-
-extern void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
-			   int on_memory_bus, int visible);
-
-
-    /*
-     *  PCI Master Registers
-     */
-
-#define NILE4_PCICMD_IACK	0	/* PCI Interrupt Acknowledge */
-#define NILE4_PCICMD_IO		1	/* PCI I/O Space */
-#define NILE4_PCICMD_MEM	3	/* PCI Memory Space */
-#define NILE4_PCICMD_CFG	5	/* PCI Configuration Space */
-
-
-    /*
-     *  PCI Address Spaces
-     *
-     *  Note that these are multiplexed using PCIINIT[01]!
-     */
-
-#define NILE4_PCI_IO_BASE	0xa6000000
-#define NILE4_PCI_MEM_BASE	0xa8000000
-#define NILE4_PCI_CFG_BASE	NILE4_PCI_MEM_BASE
-#define NILE4_PCI_IACK_BASE	NILE4_PCI_IO_BASE
-
-
-extern void nile4_set_pmr(u32 pmr, u32 type, u32 addr);
-
-
-    /*
-     *  Interrupt Programming
-     */
-
-#define NUM_I8259_INTERRUPTS	16
-#define NUM_NILE4_INTERRUPTS	16
-
-#define IRQ_I8259_CASCADE	NILE4_INT_INTE
-#define is_i8259_irq(irq)	((irq) < NUM_I8259_INTERRUPTS)
-#define nile4_to_irq(n)		((n)+NUM_I8259_INTERRUPTS)
-#define irq_to_nile4(n)		((n)-NUM_I8259_INTERRUPTS)
-
-extern void nile4_map_irq(int nile4_irq, int cpu_irq);
-extern void nile4_map_irq_all(int cpu_irq);
-extern void nile4_enable_irq(unsigned int nile4_irq);
-extern void nile4_disable_irq(unsigned int nile4_irq);
-extern void nile4_disable_irq_all(void);
-extern u16 nile4_get_irq_stat(int cpu_irq);
-extern void nile4_enable_irq_output(int cpu_irq);
-extern void nile4_disable_irq_output(int cpu_irq);
-extern void nile4_set_pci_irq_polarity(int pci_irq, int high);
-extern void nile4_set_pci_irq_level_or_edge(int pci_irq, int level);
-extern void nile4_clear_irq(int nile4_irq);
-extern void nile4_clear_irq_mask(u32 mask);
-extern u8 nile4_i8259_iack(void);
-extern void nile4_dump_irq_status(void);	/* Debug */
-
-#endif
-
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 5c3239d..b92dd8c 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -34,12 +34,8 @@
 
 #ifndef __ASSEMBLY__
 
-/*
- * This gives the physical RAM offset.
- */
-#ifndef PHYS_OFFSET
-#define PHYS_OFFSET		0UL
-#endif
+#include <linux/pfn.h>
+#include <asm/io.h>
 
 /*
  * It's normally defined only for FLATMEM config but it's
@@ -48,9 +44,6 @@
  */
 #define ARCH_PFN_OFFSET		PFN_UP(PHYS_OFFSET)
 
-#include <linux/pfn.h>
-#include <asm/io.h>
-
 extern void clear_page(void * page);
 extern void copy_page(void * to, void * from);
 
@@ -150,11 +143,15 @@
  * __pa()/__va() should be used only during mem init.
  */
 #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
-#define __pa_page_offset(x)	((unsigned long)(x) < CKSEG0 ? PAGE_OFFSET : CKSEG0)
+#define __pa(x)								\
+({									\
+    unsigned long __x = (unsigned long)(x);				\
+    __x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x);			\
+})
 #else
-#define __pa_page_offset(x)	PAGE_OFFSET
+#define __pa(x)								\
+    ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
 #endif
-#define __pa(x)		((unsigned long)(x) - __pa_page_offset(x) + PHYS_OFFSET)
 #define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
 #define __pa_symbol(x)	__pa(RELOC_HIDE((unsigned long)(x),0))
 
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index 3eea3ba..a59d547 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -56,7 +56,7 @@
 /*
  * board supplied pci irq fixup routine
  */
-extern int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
+extern int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
 
 
 /* Can be used to override the logic in pci_scan_bus for skipping
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h
new file mode 100644
index 0000000..c84bcf9
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h
@@ -0,0 +1,151 @@
+/*
+ * Defines for the MSP interrupt controller.
+ *
+ * Copyright (C) 1999 MIPS Technologies, Inc.  All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _MSP_CIC_INT_H
+#define _MSP_CIC_INT_H
+
+/*
+ * The PMC-Sierra CIC interrupts are all centrally managed by the
+ * CIC sub-system.
+ * We attempt to keep the interrupt numbers as consistent as possible
+ * across all of the MSP devices, but some differences will creep in ...
+ * The interrupts which are directly forwarded to the MIPS core interrupts
+ * are assigned interrupts in the range 0-7, interrupts cascaded through
+ * the CIC are assigned interrupts 8-39.  The cascade occurs on C_IRQ4
+ * (MSP_INT_CIC).  Currently we don't really distinguish between VPE1
+ * and VPE0 (or thread contexts for that matter).  Will have to fix.
+ * The PER interrupts are assigned interrupts in the range 40-71.
+*/
+
+
+/*
+ * IRQs directly forwarded to the CPU
+ */
+#define MSP_MIPS_INTBASE	0
+#define MSP_INT_SW0		0	/* IRQ for swint0,       C_SW0  */
+#define MSP_INT_SW1		1	/* IRQ for swint1,       C_SW1  */
+#define MSP_INT_MAC0		2	/* IRQ for MAC 0,        C_IRQ0 */
+#define MSP_INT_MAC1		3	/* IRQ for MAC 1,        C_IRQ1 */
+#define MSP_INT_USB		4	/* IRQ for USB,          C_IRQ2 */
+#define MSP_INT_SAR		5	/* IRQ for ADSL2+ SAR,   C_IRQ3 */
+#define MSP_INT_CIC		6	/* IRQ for CIC block,    C_IRQ4 */
+#define MSP_INT_SEC		7	/* IRQ for Sec engine,   C_IRQ5 */
+
+/*
+ * IRQs cascaded on CPU interrupt 4 (CAUSE bit 12, C_IRQ4)
+ * These defines should be tied to the register definitions for the CIC
+ * interrupt routine.  For now, just use hard-coded values.
+ */
+#define MSP_CIC_INTBASE		(MSP_MIPS_INTBASE + 8)
+#define MSP_INT_EXT0		(MSP_CIC_INTBASE + 0)
+					/* External interrupt 0         */
+#define MSP_INT_EXT1		(MSP_CIC_INTBASE + 1)
+					/* External interrupt 1         */
+#define MSP_INT_EXT2		(MSP_CIC_INTBASE + 2)
+					/* External interrupt 2         */
+#define MSP_INT_EXT3		(MSP_CIC_INTBASE + 3)
+					/* External interrupt 3         */
+#define MSP_INT_CPUIF		(MSP_CIC_INTBASE + 4)
+					/* CPU interface interrupt      */
+#define MSP_INT_EXT4		(MSP_CIC_INTBASE + 5)
+					/* External interrupt 4         */
+#define MSP_INT_CIC_USB		(MSP_CIC_INTBASE + 6)
+					/* Cascaded IRQ for USB         */
+#define MSP_INT_MBOX		(MSP_CIC_INTBASE + 7)
+					/* Sec engine mailbox IRQ       */
+#define MSP_INT_EXT5		(MSP_CIC_INTBASE + 8)
+					/* External interrupt 5         */
+#define MSP_INT_TDM		(MSP_CIC_INTBASE + 9)
+					/* TDM interrupt                */
+#define MSP_INT_CIC_MAC0	(MSP_CIC_INTBASE + 10)
+					/* Cascaded IRQ for MAC 0       */
+#define MSP_INT_CIC_MAC1	(MSP_CIC_INTBASE + 11)
+					/* Cascaded IRQ for MAC 1       */
+#define MSP_INT_CIC_SEC		(MSP_CIC_INTBASE + 12)
+					/* Cascaded IRQ for sec engine  */
+#define	MSP_INT_PER		(MSP_CIC_INTBASE + 13)
+					/* Peripheral interrupt         */
+#define	MSP_INT_TIMER0		(MSP_CIC_INTBASE + 14)
+					/* SLP timer 0                  */
+#define	MSP_INT_TIMER1		(MSP_CIC_INTBASE + 15)
+					/* SLP timer 1                  */
+#define	MSP_INT_TIMER2		(MSP_CIC_INTBASE + 16)
+					/* SLP timer 2                  */
+#define	MSP_INT_VPE0_TIMER	(MSP_CIC_INTBASE + 17)
+					/* VPE0 MIPS timer              */
+#define MSP_INT_BLKCP		(MSP_CIC_INTBASE + 18)
+					/* Block Copy                   */
+#define MSP_INT_UART0		(MSP_CIC_INTBASE + 19)
+					/* UART 0                       */
+#define MSP_INT_PCI		(MSP_CIC_INTBASE + 20)
+					/* PCI subsystem                */
+#define MSP_INT_EXT6		(MSP_CIC_INTBASE + 21)
+					/* External interrupt 5         */
+#define MSP_INT_PCI_MSI		(MSP_CIC_INTBASE + 22)
+					/* PCI Message Signal           */
+#define MSP_INT_CIC_SAR		(MSP_CIC_INTBASE + 23)
+					/* Cascaded ADSL2+ SAR IRQ      */
+#define MSP_INT_DSL		(MSP_CIC_INTBASE + 24)
+					/* ADSL2+ IRQ                   */
+#define MSP_INT_CIC_ERR		(MSP_CIC_INTBASE + 25)
+					/* SLP error condition          */
+#define MSP_INT_VPE1_TIMER	(MSP_CIC_INTBASE + 26)
+					/* VPE1 MIPS timer              */
+#define MSP_INT_VPE0_PC		(MSP_CIC_INTBASE + 27)
+					/* VPE0 Performance counter     */
+#define MSP_INT_VPE1_PC		(MSP_CIC_INTBASE + 28)
+					/* VPE1 Performance counter     */
+#define MSP_INT_EXT7		(MSP_CIC_INTBASE + 29)
+					/* External interrupt 5         */
+#define MSP_INT_VPE0_SW		(MSP_CIC_INTBASE + 30)
+					/* VPE0 Software interrupt      */
+#define MSP_INT_VPE1_SW		(MSP_CIC_INTBASE + 31)
+					/* VPE0 Software interrupt      */
+
+/*
+ * IRQs cascaded on CIC PER interrupt (MSP_INT_PER)
+ */
+#define MSP_PER_INTBASE		(MSP_CIC_INTBASE + 32)
+/* Reserved					   0-1                  */
+#define MSP_INT_UART1		(MSP_PER_INTBASE + 2)
+					/* UART 1                       */
+/* Reserved					   3-5                  */
+#define MSP_INT_2WIRE		(MSP_PER_INTBASE + 6)
+					/* 2-wire                       */
+#define MSP_INT_TM0		(MSP_PER_INTBASE + 7)
+					/* Peripheral timer block out 0 */
+#define MSP_INT_TM1		(MSP_PER_INTBASE + 8)
+					/* Peripheral timer block out 1 */
+/* Reserved					   9                    */
+#define MSP_INT_SPRX		(MSP_PER_INTBASE + 10)
+					/* SPI RX complete              */
+#define MSP_INT_SPTX		(MSP_PER_INTBASE + 11)
+					/* SPI TX complete              */
+#define MSP_INT_GPIO		(MSP_PER_INTBASE + 12)
+					/* GPIO                         */
+#define MSP_INT_PER_ERR		(MSP_PER_INTBASE + 13)
+					/* Peripheral error             */
+/* Reserved					   14-31                */
+
+#endif /* !_MSP_CIC_INT_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_int.h
new file mode 100644
index 0000000..1d9f054
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_int.h
@@ -0,0 +1,43 @@
+/*
+ * Defines for the MSP interrupt handlers.
+ *
+ * Copyright (C) 2005, PMC-Sierra, Inc.  All rights reserved.
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _MSP_INT_H
+#define _MSP_INT_H
+
+/*
+ * The PMC-Sierra MSP product line has at least two different interrupt
+ * controllers, the SLP register based scheme and the CIC interrupt
+ * controller block mechanism.  This file distinguishes between them
+ * so that devices see a uniform interface.
+ */
+
+#if defined(CONFIG_IRQ_MSP_SLP)
+	#include "msp_slp_int.h"
+#elif defined(CONFIG_IRQ_MSP_CIC)
+	#include "msp_cic_int.h"
+#else
+	#error "What sort of interrupt controller does *your* MSP have?"
+#endif
+
+#endif /* !_MSP_INT_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h b/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h
new file mode 100644
index 0000000..4156069
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2000-2006 PMC-Sierra INC.
+ *
+ *     This program is free software; you can redistribute it
+ *     and/or modify it under the terms of the GNU General
+ *     Public License as published by the Free Software
+ *     Foundation; either version 2 of the License, or (at your
+ *     option) any later version.
+ *
+ *     This program is distributed in the hope that it will be
+ *     useful, but WITHOUT ANY WARRANTY; without even the implied
+ *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *     PURPOSE.  See the GNU General Public License for more
+ *     details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this program; if not, write to the Free
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ *     02139, USA.
+ *
+ * PMC-SIERRA INC. DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef _MSP_PCI_H_
+#define _MSP_PCI_H_
+
+#define MSP_HAS_PCI(ID)	(((u32)(ID) <= 0x4236) && ((u32)(ID) >= 0x4220))
+
+/*
+ * It is convenient to program the OATRAN register so that
+ * Athena virtual address space and PCI address space are
+ * the same. This is not a requirement, just a convenience.
+ *
+ * The only hard restrictions on the value of OATRAN is that
+ * OATRAN must not be programmed to allow translated memory
+ * addresses to fall within the lowest 512MB of
+ * PCI address space. This region is hardcoded
+ * for use as Athena PCI Host Controller target
+ * access memory space to the Athena's SDRAM.
+ *
+ * Note that OATRAN applies only to memory accesses, not
+ * to I/O accesses.
+ *
+ * To program OATRAN to make Athena virtual address space
+ * and PCI address space have the same values, OATRAN
+ * is to be programmed to 0xB8000000. The top seven
+ * bits of the value mimic the seven bits clipped off
+ * by the PCI Host controller.
+ *
+ * With OATRAN at the said value, when the CPU does
+ * an access to its virtual address at, say 0xB900_5000,
+ * the address appearing on the PCI bus will be
+ * 0xB900_5000.
+ *    - Michael Penner
+ */
+#define MSP_PCI_OATRAN		0xB8000000UL
+
+#define MSP_PCI_SPACE_BASE	(MSP_PCI_OATRAN + 0x1002000UL)
+#define MSP_PCI_SPACE_SIZE	(0x3000000UL - 0x2000)
+#define MSP_PCI_SPACE_END \
+		(MSP_PCI_SPACE_BASE + MSP_PCI_SPACE_SIZE - 1)
+#define MSP_PCI_IOSPACE_BASE	(MSP_PCI_OATRAN + 0x1001000UL)
+#define MSP_PCI_IOSPACE_SIZE	0x1000
+#define MSP_PCI_IOSPACE_END  \
+		(MSP_PCI_IOSPACE_BASE + MSP_PCI_IOSPACE_SIZE - 1)
+
+/* IRQ for PCI status interrupts */
+#define PCI_STAT_IRQ	20
+
+#define QFLUSH_REG_1	0xB7F40000
+
+typedef volatile unsigned int pcireg;
+typedef void * volatile ppcireg;
+
+struct pci_block_copy
+{
+    pcireg   unused1; /* +0x00 */
+    pcireg   unused2; /* +0x04 */
+    ppcireg  unused3; /* +0x08 */
+    ppcireg  unused4; /* +0x0C */
+    pcireg   unused5; /* +0x10 */
+    pcireg   unused6; /* +0x14 */
+    pcireg   unused7; /* +0x18 */
+    ppcireg  unused8; /* +0x1C */
+    ppcireg  unused9; /* +0x20 */
+    pcireg   unusedA; /* +0x24 */
+    ppcireg  unusedB; /* +0x28 */
+    ppcireg  unusedC; /* +0x2C */
+};
+
+enum
+{
+    config_device_vendor,  /* 0 */
+    config_status_command, /* 1 */
+    config_class_revision, /* 2 */
+    config_BIST_header_latency_cache, /* 3 */
+    config_BAR0,           /* 4 */
+    config_BAR1,           /* 5 */
+    config_BAR2,           /* 6 */
+    config_not_used7,      /* 7 */
+    config_not_used8,      /* 8 */
+    config_not_used9,      /* 9 */
+    config_CIS,            /* 10 */
+    config_subsystem,      /* 11 */
+    config_not_used12,     /* 12 */
+    config_capabilities,   /* 13 */
+    config_not_used14,     /* 14 */
+    config_lat_grant_irq,  /* 15 */
+    config_message_control,/* 16 */
+    config_message_addr,   /* 17 */
+    config_message_data,   /* 18 */
+    config_VPD_addr,       /* 19 */
+    config_VPD_data,       /* 20 */
+    config_maxregs         /* 21 - number of registers */
+};
+
+struct msp_pci_regs
+{
+    pcireg hop_unused_00; /* +0x00 */
+    pcireg hop_unused_04; /* +0x04 */
+    pcireg hop_unused_08; /* +0x08 */
+    pcireg hop_unused_0C; /* +0x0C */
+    pcireg hop_unused_10; /* +0x10 */
+    pcireg hop_unused_14; /* +0x14 */
+    pcireg hop_unused_18; /* +0x18 */
+    pcireg hop_unused_1C; /* +0x1C */
+    pcireg hop_unused_20; /* +0x20 */
+    pcireg hop_unused_24; /* +0x24 */
+    pcireg hop_unused_28; /* +0x28 */
+    pcireg hop_unused_2C; /* +0x2C */
+    pcireg hop_unused_30; /* +0x30 */
+    pcireg hop_unused_34; /* +0x34 */
+    pcireg if_control;    /* +0x38 */
+    pcireg oatran;        /* +0x3C */
+    pcireg reset_ctl;     /* +0x40 */
+    pcireg config_addr;   /* +0x44 */
+    pcireg hop_unused_48; /* +0x48 */
+    pcireg msg_signaled_int_status; /* +0x4C */
+    pcireg msg_signaled_int_mask;   /* +0x50 */
+    pcireg if_status;     /* +0x54 */
+    pcireg if_mask;       /* +0x58 */
+    pcireg hop_unused_5C; /* +0x5C */
+    pcireg hop_unused_60; /* +0x60 */
+    pcireg hop_unused_64; /* +0x64 */
+    pcireg hop_unused_68; /* +0x68 */
+    pcireg hop_unused_6C; /* +0x6C */
+    pcireg hop_unused_70; /* +0x70 */
+
+    struct pci_block_copy pci_bc[2] __attribute__((aligned(64)));
+
+    pcireg error_hdr1; /* +0xE0 */
+    pcireg error_hdr2; /* +0xE4 */
+
+    pcireg config[config_maxregs] __attribute__((aligned(256)));
+
+};
+
+#define BPCI_CFGADDR_BUSNUM_SHF 16
+#define BPCI_CFGADDR_FUNCTNUM_SHF 8
+#define BPCI_CFGADDR_REGNUM_SHF 2
+#define BPCI_CFGADDR_ENABLE (1<<31)
+
+#define BPCI_IFCONTROL_RTO (1<<20) /* Retry timeout */
+#define BPCI_IFCONTROL_HCE (1<<16) /* Host configuration enable */
+#define BPCI_IFCONTROL_CTO_SHF 12  /* Shift count for CTO bits */
+#define BPCI_IFCONTROL_SE  (1<<5)  /* Enable exceptions on errors */
+#define BPCI_IFCONTROL_BIST (1<<4) /* Use BIST in per. mode */
+#define BPCI_IFCONTROL_CAP (1<<3)  /* Enable capabilities */
+#define BPCI_IFCONTROL_MMC_SHF 0   /* Shift count for MMC bits */
+
+#define BPCI_IFSTATUS_MGT  (1<<8)  /* Master Grant timeout */
+#define BPCI_IFSTATUS_MTT  (1<<9)  /* Master TRDY timeout */
+#define BPCI_IFSTATUS_MRT  (1<<10) /* Master retry timeout */
+#define BPCI_IFSTATUS_BC0F (1<<13) /* Block copy 0 fault */
+#define BPCI_IFSTATUS_BC1F (1<<14) /* Block copy 1 fault */
+#define BPCI_IFSTATUS_PCIU (1<<15) /* PCI unable to respond */
+#define BPCI_IFSTATUS_BSIZ (1<<16) /* PCI access with illegal size */
+#define BPCI_IFSTATUS_BADD (1<<17) /* PCI access with illegal addr */
+#define BPCI_IFSTATUS_RTO  (1<<18) /* Retry time out */
+#define BPCI_IFSTATUS_SER  (1<<19) /* System error */
+#define BPCI_IFSTATUS_PER  (1<<20) /* Parity error */
+#define BPCI_IFSTATUS_LCA  (1<<21) /* Local CPU abort */
+#define BPCI_IFSTATUS_MEM  (1<<22) /* Memory prot. violation */
+#define BPCI_IFSTATUS_ARB  (1<<23) /* Arbiter timed out */
+#define BPCI_IFSTATUS_STA  (1<<27) /* Signaled target abort */
+#define BPCI_IFSTATUS_TA   (1<<28) /* Target abort */
+#define BPCI_IFSTATUS_MA   (1<<29) /* Master abort */
+#define BPCI_IFSTATUS_PEI  (1<<30) /* Parity error as initiator */
+#define BPCI_IFSTATUS_PET  (1<<31) /* Parity error as target */
+
+#define BPCI_RESETCTL_PR (1<<0)    /* True if reset asserted */
+#define BPCI_RESETCTL_RT (1<<4)    /* Release time */
+#define BPCI_RESETCTL_CT (1<<8)    /* Config time */
+#define BPCI_RESETCTL_PE (1<<12)   /* PCI enabled */
+#define BPCI_RESETCTL_HM (1<<13)   /* PCI host mode */
+#define BPCI_RESETCTL_RI (1<<14)   /* PCI reset in */
+
+extern struct msp_pci_regs msp_pci_regs
+			__attribute__((section(".register")));
+extern unsigned long msp_pci_config_space
+			__attribute__((section(".register")));
+
+#endif /* !_MSP_PCI_H_ */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h b/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h
new file mode 100644
index 0000000..14ca7dc
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h
@@ -0,0 +1,176 @@
+/*
+ * MIPS boards bootprom interface for the Linux kernel.
+ *
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _ASM_MSP_PROM_H
+#define _ASM_MSP_PROM_H
+
+#include <linux/types.h>
+
+#define DEVICEID			"deviceid"
+#define FEATURES			"features"
+#define PROM_ENV			"prom_env"
+#define PROM_ENV_FILE			"/proc/"PROM_ENV
+#define PROM_ENV_SIZE			256
+
+#define CPU_DEVID_FAMILY		0x0000ff00
+#define CPU_DEVID_REVISION		0x000000ff
+
+#define FPGA_IS_POLO(revision) \
+		(((revision >= 0xb0) && (revision < 0xd0)))
+#define FPGA_IS_5000(revision) \
+		((revision >= 0x80) && (revision <= 0x90))
+#define	FPGA_IS_ZEUS(revision)		((revision < 0x7f))
+#define FPGA_IS_DUET(revision) \
+		(((revision >= 0xa0) && (revision < 0xb0)))
+#define FPGA_IS_MSP4200(revision)	((revision >= 0xd0))
+#define FPGA_IS_MSP7100(revision)	((revision >= 0xd0))
+
+#define MACHINE_TYPE_POLO		"POLO"
+#define MACHINE_TYPE_DUET		"DUET"
+#define	MACHINE_TYPE_ZEUS		"ZEUS"
+#define MACHINE_TYPE_MSP2000REVB	"MSP2000REVB"
+#define MACHINE_TYPE_MSP5000		"MSP5000"
+#define MACHINE_TYPE_MSP4200		"MSP4200"
+#define MACHINE_TYPE_MSP7120		"MSP7120"
+#define MACHINE_TYPE_MSP7130		"MSP7130"
+#define MACHINE_TYPE_OTHER		"OTHER"
+
+#define MACHINE_TYPE_POLO_FPGA		"POLO-FPGA"
+#define MACHINE_TYPE_DUET_FPGA		"DUET-FPGA"
+#define	MACHINE_TYPE_ZEUS_FPGA		"ZEUS_FPGA"
+#define MACHINE_TYPE_MSP2000REVB_FPGA	"MSP2000REVB-FPGA"
+#define MACHINE_TYPE_MSP5000_FPGA	"MSP5000-FPGA"
+#define MACHINE_TYPE_MSP4200_FPGA	"MSP4200-FPGA"
+#define MACHINE_TYPE_MSP7100_FPGA	"MSP7100-FPGA"
+#define MACHINE_TYPE_OTHER_FPGA		"OTHER-FPGA"
+
+/* Device Family definitions */
+#define FAMILY_FPGA			0x0000
+#define FAMILY_ZEUS			0x1000
+#define FAMILY_POLO			0x2000
+#define FAMILY_DUET			0x4000
+#define FAMILY_TRIAD			0x5000
+#define FAMILY_MSP4200			0x4200
+#define FAMILY_MSP4200_FPGA		0x4f00
+#define FAMILY_MSP7100			0x7100
+#define FAMILY_MSP7100_FPGA		0x7f00
+
+/* Device Type definitions */
+#define TYPE_MSP7120			0x7120
+#define TYPE_MSP7130			0x7130
+
+#define ENET_KEY		'E'
+#define ENETTXD_KEY		'e'
+#define PCI_KEY			'P'
+#define PCIMUX_KEY		'p'
+#define SEC_KEY			'S'
+#define SPAD_KEY		'D'
+#define TDM_KEY			'T'
+#define ZSP_KEY			'Z'
+
+#define FEATURE_NOEXIST		'-'
+#define FEATURE_EXIST		'+'
+
+#define ENET_MII		'M'
+#define ENET_RMII		'R'
+
+#define	ENETTXD_FALLING		'F'
+#define ENETTXD_RISING		'R'
+
+#define PCI_HOST		'H'
+#define PCI_PERIPHERAL		'P'
+
+#define PCIMUX_FULL		'F'
+#define PCIMUX_SINGLE		'S'
+
+#define SEC_DUET		'D'
+#define SEC_POLO		'P'
+#define SEC_SLOW		'S'
+#define SEC_TRIAD		'T'
+
+#define SPAD_POLO		'P'
+
+#define TDM_DUET		'D'	/* DUET TDMs might exist */
+#define TDM_POLO		'P'	/* POLO TDMs might exist */
+#define TDM_TRIAD		'T'	/* TRIAD TDMs might exist */
+
+#define ZSP_DUET		'D'	/* one DUET zsp engine */
+#define ZSP_TRIAD		'T'	/* two TRIAD zsp engines */
+
+extern char *prom_getcmdline(void);
+extern char *prom_getenv(char *name);
+extern void prom_init_cmdline(void);
+extern void prom_meminit(void);
+extern void prom_fixup_mem_map(unsigned long start_mem,
+			       unsigned long end_mem);
+
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+extern bool get_ramroot(void **start, unsigned long *size);
+#endif
+
+extern int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr);
+extern unsigned long get_deviceid(void);
+extern char identify_enet(unsigned long interface_num);
+extern char identify_enetTxD(unsigned long interface_num);
+extern char identify_pci(void);
+extern char identify_sec(void);
+extern char identify_spad(void);
+extern char identify_sec(void);
+extern char identify_tdm(void);
+extern char identify_zsp(void);
+extern unsigned long identify_family(void);
+extern unsigned long identify_revision(void);
+
+/*
+ * The following macro calls prom_printf and puts the format string
+ * into an init section so it can be reclaimed.
+ */
+#define ppfinit(f, x...) \
+	do { \
+		static char _f[] __initdata = KERN_INFO f; \
+		printk(_f, ## x); \
+	} while (0)
+
+/* Memory descriptor management. */
+#define PROM_MAX_PMEMBLOCKS    7	/* 6 used */
+
+enum yamon_memtypes {
+	yamon_dontuse,
+	yamon_prom,
+	yamon_free,
+};
+
+struct prom_pmemblock {
+	unsigned long base; /* Within KSEG0. */
+	unsigned int size;  /* In bytes. */
+	unsigned int type;  /* free or prom memory */
+};
+
+extern int prom_argc;
+extern char **prom_argv;
+extern char **prom_envp;
+extern int *prom_vec;
+extern struct prom_pmemblock *prom_getmdesc(void);
+
+#endif /* !_ASM_MSP_PROM_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h b/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h
new file mode 100644
index 0000000..60a5a38
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h
@@ -0,0 +1,236 @@
+/*
+ * SMP/VPE-safe functions to access "registers" (see note).
+ *
+ * NOTES:
+* - These macros use ll/sc instructions, so it is your responsibility to
+ * ensure these are available on your platform before including this file.
+ * - The MIPS32 spec states that ll/sc results are undefined for uncached
+ * accesses. This means they can't be used on HW registers accessed
+ * through kseg1. Code which requires these macros for this purpose must
+ * front-end the registers with cached memory "registers" and have a single
+ * thread update the actual HW registers.
+ * - A maximum of 2k of code can be inserted between ll and sc. Every
+ * memory accesses between the instructions will increase the chance of
+ * sc failing and having to loop.
+ * - When using custom_read_reg32/custom_write_reg32 only perform the
+ * necessary logical operations on the register value in between these
+ * two calls. All other logic should be performed before the first call.
+  * - There is a bug on the R10000 chips which has a workaround. If you
+ * are affected by this bug, make sure to define the symbol 'R10000_LLSC_WAR'
+ * to be non-zero.  If you are using this header from within linux, you may
+ * include <asm/war.h> before including this file to have this defined
+ * appropriately for you.
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
+ *  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF USE,
+ *  DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc., 675
+ *  Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_REGOPS_H__
+#define __ASM_REGOPS_H__
+
+#include <linux/types.h>
+
+#include <asm/war.h>
+
+#ifndef R10000_LLSC_WAR
+#define R10000_LLSC_WAR 0
+#endif
+
+#if R10000_LLSC_WAR == 1
+#define __beqz	"beqzl	"
+#else
+#define __beqz	"beqz	"
+#endif
+
+#ifndef _LINUX_TYPES_H
+typedef unsigned int u32;
+#endif
+
+/*
+ * Sets all the masked bits to the corresponding value bits
+ */
+static inline void set_value_reg32(volatile u32 *const addr,
+					u32 const mask,
+					u32 const value)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	mips3				\n"
+	"1:	ll	%0, %1	# set_value_reg32	\n"
+	"	and	%0, %2				\n"
+	"	or	%0, %3				\n"
+	"	sc	%0, %1				\n"
+	"	"__beqz"%0, 1b				\n"
+	"	nop					\n"
+	"	.set	pop				\n"
+	: "=&r" (temp), "=m" (*addr)
+	: "ir" (~mask), "ir" (value), "m" (*addr));
+}
+
+/*
+ * Sets all the masked bits to '1'
+ */
+static inline void set_reg32(volatile u32 *const addr,
+				u32 const mask)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	mips3				\n"
+	"1:	ll	%0, %1		# set_reg32	\n"
+	"	or	%0, %2				\n"
+	"	sc	%0, %1				\n"
+	"	"__beqz"%0, 1b				\n"
+	"	nop					\n"
+	"	.set	pop				\n"
+	: "=&r" (temp), "=m" (*addr)
+	: "ir" (mask), "m" (*addr));
+}
+
+/*
+ * Sets all the masked bits to '0'
+ */
+static inline void clear_reg32(volatile u32 *const addr,
+				u32 const mask)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	mips3				\n"
+	"1:	ll	%0, %1		# clear_reg32	\n"
+	"	and	%0, %2				\n"
+	"	sc	%0, %1				\n"
+	"	"__beqz"%0, 1b				\n"
+	"	nop					\n"
+	"	.set	pop				\n"
+	: "=&r" (temp), "=m" (*addr)
+	: "ir" (~mask), "m" (*addr));
+}
+
+/*
+ * Toggles all masked bits from '0' to '1' and '1' to '0'
+ */
+static inline void toggle_reg32(volatile u32 *const addr,
+				u32 const mask)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	mips3				\n"
+	"1:	ll	%0, %1		# toggle_reg32	\n"
+	"	xor	%0, %2				\n"
+	"	sc	%0, %1				\n"
+	"	"__beqz"%0, 1b				\n"
+	"	nop					\n"
+	"	.set	pop				\n"
+	: "=&r" (temp), "=m" (*addr)
+	: "ir" (mask), "m" (*addr));
+}
+
+/*
+ * Read all masked bits others are returned as '0'
+ */
+static inline u32 read_reg32(volatile u32 *const addr,
+				u32 const mask)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	noreorder			\n"
+	"	lw	%0, %1		# read		\n"
+	"	and	%0, %2		# mask		\n"
+	"	.set	pop				\n"
+	: "=&r" (temp)
+	: "m" (*addr), "ir" (mask));
+
+	return temp;
+}
+
+/*
+ * blocking_read_reg32 - Read address with blocking load
+ *
+ * Uncached writes need to be read back to ensure they reach RAM.
+ * The returned value must be 'used' to prevent from becoming a
+ * non-blocking load.
+ */
+static inline u32 blocking_read_reg32(volatile u32 *const addr)
+{
+	u32 temp;
+
+	__asm__ __volatile__(
+	"	.set	push				\n"
+	"	.set	noreorder			\n"
+	"	lw	%0, %1		# read		\n"
+	"	move	%0, %0		# block		\n"
+	"	.set	pop				\n"
+	: "=&r" (temp)
+	: "m" (*addr));
+
+	return temp;
+}
+
+/*
+ * For special strange cases only:
+ *
+ * If you need custom processing within a ll/sc loop, use the following macros
+ * VERY CAREFULLY:
+ *
+ *   u32 tmp;				<-- Define a variable to hold the data
+ *
+ *   custom_read_reg32(address, tmp);	<-- Reads the address and put the value
+ *						in the 'tmp' variable given
+ *
+ *	From here on out, you are (basicly) atomic, so don't do anything too
+ *	fancy!
+ *	Also, this code may loop if the end of this block fails to write
+ *	everything back safely due do the other CPU, so do NOT do anything
+ *	with side-effects!
+ *
+ *   custom_write_reg32(address, tmp);	<-- Writes back 'tmp' safely.
+ */
+#define custom_read_reg32(address, tmp)				\
+	__asm__ __volatile__(					\
+	"	.set	push				\n"	\
+	"	.set	mips3				\n"	\
+	"1:	ll	%0, %1	#custom_read_reg32	\n"	\
+	"	.set	pop				\n"	\
+	: "=r" (tmp), "=m" (*address)				\
+	: "m" (*address))
+
+#define custom_write_reg32(address, tmp)			\
+	__asm__ __volatile__(					\
+	"	.set	push				\n"	\
+	"	.set	mips3				\n"	\
+	"	sc	%0, %1	#custom_write_reg32	\n"	\
+	"	"__beqz"%0, 1b				\n"	\
+	"	nop					\n"	\
+	"	.set	pop				\n"	\
+	: "=&r" (tmp), "=m" (*address)				\
+	: "0" (tmp), "m" (*address))
+
+#endif  /* __ASM_REGOPS_H__ */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h b/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h
new file mode 100644
index 0000000..0b56f55
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h
@@ -0,0 +1,667 @@
+/*
+ * Defines for the address space, registers and register configuration
+ * (bit masks, access macros etc) for the PMC-Sierra line of MSP products.
+ * This file contains addess maps for all the devices in the line of
+ * products but only has register definitions and configuration masks for
+ * registers which aren't definitely associated with any device.  Things
+ * like clock settings, reset access, the ELB etc.  Individual device
+ * drivers will reference the appropriate XXX_BASE value defined here
+ * and have individual registers offset from that.
+ *
+ * Copyright (C) 2005-2007 PMC-Sierra, Inc.  All rights reserved.
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#include <asm/addrspace.h>
+#include <linux/types.h>
+
+#ifndef _ASM_MSP_REGS_H
+#define _ASM_MSP_REGS_H
+
+/*
+ ########################################################################
+ #  Address space and device base definitions                           #
+ ########################################################################
+ */
+
+/*
+ ***************************************************************************
+ * System Logic and Peripherals (ELB, UART0, etc) device address space     *
+ ***************************************************************************
+ */
+#define MSP_SLP_BASE		0x1c000000
+					/* System Logic and Peripherals */
+#define MSP_RST_BASE		(MSP_SLP_BASE + 0x10)
+					/* System reset register base	*/
+#define MSP_RST_SIZE		0x0C	/* System reset register space	*/
+
+#define MSP_WTIMER_BASE		(MSP_SLP_BASE + 0x04C)
+					/* watchdog timer base          */
+#define MSP_ITIMER_BASE		(MSP_SLP_BASE + 0x054)
+					/* internal timer base          */
+#define MSP_UART0_BASE		(MSP_SLP_BASE + 0x100)
+					/* UART0 controller base        */
+#define MSP_BCPY_CTRL_BASE	(MSP_SLP_BASE + 0x120)
+					/* Block Copy controller base   */
+#define MSP_BCPY_DESC_BASE	(MSP_SLP_BASE + 0x160)
+					/* Block Copy descriptor base   */
+
+/*
+ ***************************************************************************
+ * PCI address space                                                       *
+ ***************************************************************************
+ */
+#define MSP_PCI_BASE		0x19000000
+
+/*
+ ***************************************************************************
+ * MSbus device address space                                              *
+ ***************************************************************************
+ */
+#define MSP_MSB_BASE		0x18000000
+					/* MSbus address start          */
+#define MSP_PER_BASE		(MSP_MSB_BASE + 0x400000)
+					/* Peripheral device registers  */
+#define MSP_MAC0_BASE		(MSP_MSB_BASE + 0x600000)
+					/* MAC A device registers       */
+#define MSP_MAC1_BASE		(MSP_MSB_BASE + 0x700000)
+					/* MAC B device registers       */
+#define MSP_MAC_SIZE		0xE0	/* MAC register space		*/
+
+#define MSP_SEC_BASE		(MSP_MSB_BASE + 0x800000)
+					/* Security Engine registers    */
+#define MSP_MAC2_BASE		(MSP_MSB_BASE + 0x900000)
+					/* MAC C device registers       */
+#define MSP_ADSL2_BASE		(MSP_MSB_BASE + 0xA80000)
+					/* ADSL2 device registers       */
+#define MSP_USB_BASE		(MSP_MSB_BASE + 0xB40000)
+					/* USB device registers         */
+#define MSP_USB_BASE_START	(MSP_MSB_BASE + 0xB40100)
+					/* USB device registers         */
+#define MSP_USB_BASE_END	(MSP_MSB_BASE + 0xB401FF)
+					/* USB device registers         */
+#define MSP_CPUIF_BASE		(MSP_MSB_BASE + 0xC00000)
+					/* CPU interface registers      */
+
+/* Devices within the MSbus peripheral block */
+#define MSP_UART1_BASE		(MSP_PER_BASE + 0x030)
+					/* UART1 controller base        */
+#define MSP_SPI_BASE		(MSP_PER_BASE + 0x058)
+					/* SPI/MPI control registers    */
+#define MSP_TWI_BASE		(MSP_PER_BASE + 0x090)
+					/* Two-wire control registers   */
+#define MSP_PTIMER_BASE		(MSP_PER_BASE + 0x0F0)
+					/* Programmable timer control   */
+
+/*
+ ***************************************************************************
+ * Physical Memory configuration address space                             *
+ ***************************************************************************
+ */
+#define MSP_MEM_CFG_BASE	0x17f00000
+
+#define MSP_MEM_INDIRECT_CTL_10	0x10
+
+/*
+ * Notes:
+ *  1) The SPI registers are split into two blocks, one offset from the
+ *     MSP_SPI_BASE by 0x00 and the other offset from the MSP_SPI_BASE by
+ *     0x68.  The SPI driver definitions for the register must be aware
+ *     of this.
+ *  2) The block copy engine register are divided into two regions, one
+ *     for the control/configuration of the engine proper and one for the
+ *     values of the descriptors used in the copy process.  These have
+ *     different base defines (CTRL_BASE vs DESC_BASE)
+ *  3) These constants are for physical addresses which means that they
+ *     work correctly with "ioremap" and friends.  This means that device
+ *     drivers will need to remap these addresses using ioremap and perhaps
+ *     the readw/writew macros.  Or they could use the regptr() macro
+ *     defined below, but the readw/writew calls are the correct thing.
+ *  4) The UARTs have an additional status register offset from the base
+ *     address.  This register isn't used in the standard 8250 driver but
+ *     may be used in other software.  Consult the hardware datasheet for
+ *     offset details.
+ *  5) For some unknown reason the security engine (MSP_SEC_BASE) registers
+ *     start at an offset of 0x84 from the base address but the block of
+ *     registers before this is reserved for the security engine.  The
+ *     driver will have to be aware of this but it makes the register
+ *     definitions line up better with the documentation.
+ */
+
+/*
+ ########################################################################
+ #  System register definitions.  Not associated with a specific device #
+ ########################################################################
+ */
+
+/*
+ * This macro maps the physical register number into uncached space
+ * and (for C code) casts it into a u32 pointer so it can be dereferenced
+ * Normally these would be accessed with ioremap and readX/writeX, but
+ * these are convenient for a lot of internal kernel code.
+ */
+#ifdef __ASSEMBLER__
+	#define regptr(addr) (KSEG1ADDR(addr))
+#else
+	#define regptr(addr) ((volatile u32 *const)(KSEG1ADDR(addr)))
+#endif
+
+/*
+ ***************************************************************************
+ * System Logic and Peripherals (RESET, ELB, etc) registers                *
+ ***************************************************************************
+ */
+
+/* System Control register definitions */
+#define	DEV_ID_REG	regptr(MSP_SLP_BASE + 0x00)
+					/* Device-ID                 RO */
+#define	FWR_ID_REG	regptr(MSP_SLP_BASE + 0x04)
+					/* Firmware-ID Register      RW */
+#define	SYS_ID_REG0	regptr(MSP_SLP_BASE + 0x08)
+					/* System-ID Register-0      RW */
+#define	SYS_ID_REG1	regptr(MSP_SLP_BASE + 0x0C)
+					/* System-ID Register-1      RW */
+
+/* System Reset register definitions */
+#define	RST_STS_REG	regptr(MSP_SLP_BASE + 0x10)
+					/* System Reset Status       RO */
+#define	RST_SET_REG	regptr(MSP_SLP_BASE + 0x14)
+					/* System Set Reset          WO */
+#define	RST_CLR_REG	regptr(MSP_SLP_BASE + 0x18)
+					/* System Clear Reset        WO */
+
+/* System Clock Registers */
+#define PCI_SLP_REG	regptr(MSP_SLP_BASE + 0x1C)
+					/* PCI clock generator       RW */
+#define URT_SLP_REG	regptr(MSP_SLP_BASE + 0x20)
+					/* UART clock generator      RW */
+/* reserved		      (MSP_SLP_BASE + 0x24)                     */
+/* reserved		      (MSP_SLP_BASE + 0x28)                     */
+#define PLL1_SLP_REG	regptr(MSP_SLP_BASE + 0x2C)
+					/* PLL1 clock generator      RW */
+#define PLL0_SLP_REG	regptr(MSP_SLP_BASE + 0x30)
+					/* PLL0 clock generator      RW */
+#define MIPS_SLP_REG	regptr(MSP_SLP_BASE + 0x34)
+					/* MIPS clock generator      RW */
+#define	VE_SLP_REG	regptr(MSP_SLP_BASE + 0x38)
+					/* Voice Eng clock generator RW */
+/* reserved		      (MSP_SLP_BASE + 0x3C)                     */
+#define MSB_SLP_REG	regptr(MSP_SLP_BASE + 0x40)
+					/* MS-Bus clock generator    RW */
+#define SMAC_SLP_REG	regptr(MSP_SLP_BASE + 0x44)
+					/* Sec & MAC clock generator RW */
+#define PERF_SLP_REG	regptr(MSP_SLP_BASE + 0x48)
+					/* Per & TDM clock generator RW */
+
+/* Interrupt Controller Registers */
+#define SLP_INT_STS_REG regptr(MSP_SLP_BASE + 0x70)
+					/* Interrupt status register RW */
+#define SLP_INT_MSK_REG regptr(MSP_SLP_BASE + 0x74)
+					/* Interrupt enable/mask     RW */
+#define SE_MBOX_REG	regptr(MSP_SLP_BASE + 0x78)
+					/* Security Engine mailbox   RW */
+#define VE_MBOX_REG	regptr(MSP_SLP_BASE + 0x7C)
+					/* Voice Engine mailbox      RW */
+
+/* ELB Controller Registers */
+#define CS0_CNFG_REG	regptr(MSP_SLP_BASE + 0x80)
+					/* ELB CS0 Configuration Reg    */
+#define CS0_ADDR_REG	regptr(MSP_SLP_BASE + 0x84)
+					/* ELB CS0 Base Address Reg     */
+#define CS0_MASK_REG	regptr(MSP_SLP_BASE + 0x88)
+					/* ELB CS0 Mask Register        */
+#define CS0_ACCESS_REG	regptr(MSP_SLP_BASE + 0x8C)
+					/* ELB CS0 access register      */
+
+#define CS1_CNFG_REG	regptr(MSP_SLP_BASE + 0x90)
+					/* ELB CS1 Configuration Reg    */
+#define CS1_ADDR_REG	regptr(MSP_SLP_BASE + 0x94)
+					/* ELB CS1 Base Address Reg     */
+#define CS1_MASK_REG	regptr(MSP_SLP_BASE + 0x98)
+					/* ELB CS1 Mask Register        */
+#define CS1_ACCESS_REG	regptr(MSP_SLP_BASE + 0x9C)
+					/* ELB CS1 access register      */
+
+#define CS2_CNFG_REG	regptr(MSP_SLP_BASE + 0xA0)
+					/* ELB CS2 Configuration Reg    */
+#define CS2_ADDR_REG	regptr(MSP_SLP_BASE + 0xA4)
+					/* ELB CS2 Base Address Reg     */
+#define CS2_MASK_REG	regptr(MSP_SLP_BASE + 0xA8)
+					/* ELB CS2 Mask Register        */
+#define CS2_ACCESS_REG	regptr(MSP_SLP_BASE + 0xAC)
+					/* ELB CS2 access register      */
+
+#define CS3_CNFG_REG	regptr(MSP_SLP_BASE + 0xB0)
+					/* ELB CS3 Configuration Reg    */
+#define CS3_ADDR_REG	regptr(MSP_SLP_BASE + 0xB4)
+					/* ELB CS3 Base Address Reg     */
+#define CS3_MASK_REG	regptr(MSP_SLP_BASE + 0xB8)
+					/* ELB CS3 Mask Register        */
+#define CS3_ACCESS_REG	regptr(MSP_SLP_BASE + 0xBC)
+					/* ELB CS3 access register      */
+
+#define CS4_CNFG_REG	regptr(MSP_SLP_BASE + 0xC0)
+					/* ELB CS4 Configuration Reg    */
+#define CS4_ADDR_REG	regptr(MSP_SLP_BASE + 0xC4)
+					/* ELB CS4 Base Address Reg     */
+#define CS4_MASK_REG	regptr(MSP_SLP_BASE + 0xC8)
+					/* ELB CS4 Mask Register        */
+#define CS4_ACCESS_REG	regptr(MSP_SLP_BASE + 0xCC)
+					/* ELB CS4 access register      */
+
+#define CS5_CNFG_REG	regptr(MSP_SLP_BASE + 0xD0)
+					/* ELB CS5 Configuration Reg    */
+#define CS5_ADDR_REG	regptr(MSP_SLP_BASE + 0xD4)
+					/* ELB CS5 Base Address Reg     */
+#define CS5_MASK_REG	regptr(MSP_SLP_BASE + 0xD8)
+					/* ELB CS5 Mask Register        */
+#define CS5_ACCESS_REG	regptr(MSP_SLP_BASE + 0xDC)
+					/* ELB CS5 access register      */
+
+/* reserved			       0xE0 - 0xE8                      */
+#define ELB_1PC_EN_REG	regptr(MSP_SLP_BASE + 0xEC)
+					/* ELB single PC card detect    */
+
+/* reserved			       0xF0 - 0xF8                      */
+#define ELB_CLK_CFG_REG	regptr(MSP_SLP_BASE + 0xFC)
+					/* SDRAM read/ELB timing Reg    */
+
+/* Extended UART status registers */
+#define UART0_STATUS_REG	regptr(MSP_UART0_BASE + 0x0c0)
+					/* UART Status Register 0       */
+#define UART1_STATUS_REG	regptr(MSP_UART1_BASE + 0x170)
+					/* UART Status Register 1       */
+
+/* Performance monitoring registers */
+#define PERF_MON_CTRL_REG	regptr(MSP_SLP_BASE + 0x140)
+					/* Performance monitor control  */
+#define PERF_MON_CLR_REG	regptr(MSP_SLP_BASE + 0x144)
+					/* Performance monitor clear    */
+#define PERF_MON_CNTH_REG	regptr(MSP_SLP_BASE + 0x148)
+					/* Perf monitor counter high    */
+#define PERF_MON_CNTL_REG	regptr(MSP_SLP_BASE + 0x14C)
+					/* Perf monitor counter low     */
+
+/* System control registers */
+#define SYS_CTRL_REG		regptr(MSP_SLP_BASE + 0x150)
+					/* System control register      */
+#define SYS_ERR1_REG		regptr(MSP_SLP_BASE + 0x154)
+					/* System Error status 1        */
+#define SYS_ERR2_REG		regptr(MSP_SLP_BASE + 0x158)
+					/* System Error status 2        */
+#define SYS_INT_CFG_REG		regptr(MSP_SLP_BASE + 0x15C)
+					/* System Interrupt config      */
+
+/* Voice Engine Memory configuration */
+#define VE_MEM_REG		regptr(MSP_SLP_BASE + 0x17C)
+					/* Voice engine memory config   */
+
+/* CPU/SLP Error Status registers */
+#define CPU_ERR1_REG		regptr(MSP_SLP_BASE + 0x180)
+					/* CPU/SLP Error status 1       */
+#define CPU_ERR2_REG		regptr(MSP_SLP_BASE + 0x184)
+					/* CPU/SLP Error status 1       */
+
+#define EXTENDED_GPIO_REG	regptr(MSP_SLP_BASE + 0x188)
+					/* Extended GPIO register       */
+
+/* System Error registers */
+#define SLP_ERR_STS_REG		regptr(MSP_SLP_BASE + 0x190)
+					/* Int status for SLP errors    */
+#define SLP_ERR_MSK_REG		regptr(MSP_SLP_BASE + 0x194)
+					/* Int mask for SLP errors      */
+#define SLP_ELB_ERST_REG	regptr(MSP_SLP_BASE + 0x198)
+					/* External ELB reset           */
+#define SLP_BOOT_STS_REG	regptr(MSP_SLP_BASE + 0x19C)
+					/* Boot Status                  */
+
+/* Extended ELB addressing */
+#define CS0_EXT_ADDR_REG	regptr(MSP_SLP_BASE + 0x1A0)
+					/* CS0 Extended address         */
+#define CS1_EXT_ADDR_REG	regptr(MSP_SLP_BASE + 0x1A4)
+					/* CS1 Extended address         */
+#define CS2_EXT_ADDR_REG	regptr(MSP_SLP_BASE + 0x1A8)
+					/* CS2 Extended address         */
+#define CS3_EXT_ADDR_REG	regptr(MSP_SLP_BASE + 0x1AC)
+					/* CS3 Extended address         */
+/* reserved					      0x1B0             */
+#define CS5_EXT_ADDR_REG	regptr(MSP_SLP_BASE + 0x1B4)
+					/* CS5 Extended address         */
+
+/* PLL Adjustment registers */
+#define PLL_LOCK_REG		regptr(MSP_SLP_BASE + 0x200)
+					/* PLL0 lock status             */
+#define PLL_ARST_REG		regptr(MSP_SLP_BASE + 0x204)
+					/* PLL Analog reset status      */
+#define PLL0_ADJ_REG		regptr(MSP_SLP_BASE + 0x208)
+					/* PLL0 Adjustment value        */
+#define PLL1_ADJ_REG		regptr(MSP_SLP_BASE + 0x20C)
+					/* PLL1 Adjustment value        */
+
+/*
+ ***************************************************************************
+ * Peripheral Register definitions                                         *
+ ***************************************************************************
+ */
+
+/* Peripheral status */
+#define PER_CTRL_REG		regptr(MSP_PER_BASE + 0x50)
+					/* Peripheral control register  */
+#define PER_STS_REG		regptr(MSP_PER_BASE + 0x54)
+					/* Peripheral status register   */
+
+/* SPI/MPI Registers */
+#define SMPI_TX_SZ_REG		regptr(MSP_PER_BASE + 0x58)
+					/* SPI/MPI Tx Size register     */
+#define SMPI_RX_SZ_REG		regptr(MSP_PER_BASE + 0x5C)
+					/* SPI/MPI Rx Size register     */
+#define SMPI_CTL_REG		regptr(MSP_PER_BASE + 0x60)
+					/* SPI/MPI Control register     */
+#define SMPI_MS_REG		regptr(MSP_PER_BASE + 0x64)
+					/* SPI/MPI Chip Select reg      */
+#define SMPI_CORE_DATA_REG	regptr(MSP_PER_BASE + 0xC0)
+					/* SPI/MPI Core Data reg        */
+#define SMPI_CORE_CTRL_REG	regptr(MSP_PER_BASE + 0xC4)
+					/* SPI/MPI Core Control reg     */
+#define SMPI_CORE_STAT_REG	regptr(MSP_PER_BASE + 0xC8)
+					/* SPI/MPI Core Status reg      */
+#define SMPI_CORE_SSEL_REG	regptr(MSP_PER_BASE + 0xCC)
+					/* SPI/MPI Core Ssel reg        */
+#define SMPI_FIFO_REG		regptr(MSP_PER_BASE + 0xD0)
+					/* SPI/MPI Data FIFO reg        */
+
+/* Peripheral Block Error Registers           */
+#define PER_ERR_STS_REG		regptr(MSP_PER_BASE + 0x70)
+					/* Error Bit Status Register    */
+#define PER_ERR_MSK_REG		regptr(MSP_PER_BASE + 0x74)
+					/* Error Bit Mask Register      */
+#define PER_HDR1_REG		regptr(MSP_PER_BASE + 0x78)
+					/* Error Header 1 Register      */
+#define PER_HDR2_REG		regptr(MSP_PER_BASE + 0x7C)
+					/* Error Header 2 Register      */
+
+/* Peripheral Block Interrupt Registers       */
+#define PER_INT_STS_REG		regptr(MSP_PER_BASE + 0x80)
+					/* Interrupt status register    */
+#define PER_INT_MSK_REG		regptr(MSP_PER_BASE + 0x84)
+					/* Interrupt Mask Register      */
+#define GPIO_INT_STS_REG	regptr(MSP_PER_BASE + 0x88)
+					/* GPIO interrupt status reg    */
+#define GPIO_INT_MSK_REG	regptr(MSP_PER_BASE + 0x8C)
+					/* GPIO interrupt MASK Reg      */
+
+/* POLO GPIO registers                        */
+#define POLO_GPIO_DAT1_REG	regptr(MSP_PER_BASE + 0x0E0)
+					/* Polo GPIO[8:0]  data reg     */
+#define POLO_GPIO_CFG1_REG	regptr(MSP_PER_BASE + 0x0E4)
+					/* Polo GPIO[7:0]  config reg   */
+#define POLO_GPIO_CFG2_REG	regptr(MSP_PER_BASE + 0x0E8)
+					/* Polo GPIO[15:8] config reg   */
+#define POLO_GPIO_OD1_REG	regptr(MSP_PER_BASE + 0x0EC)
+					/* Polo GPIO[31:0] output drive */
+#define POLO_GPIO_CFG3_REG	regptr(MSP_PER_BASE + 0x170)
+					/* Polo GPIO[23:16] config reg  */
+#define POLO_GPIO_DAT2_REG	regptr(MSP_PER_BASE + 0x174)
+					/* Polo GPIO[15:9]  data reg    */
+#define POLO_GPIO_DAT3_REG	regptr(MSP_PER_BASE + 0x178)
+					/* Polo GPIO[23:16]  data reg   */
+#define POLO_GPIO_DAT4_REG	regptr(MSP_PER_BASE + 0x17C)
+					/* Polo GPIO[31:24]  data reg   */
+#define POLO_GPIO_DAT5_REG	regptr(MSP_PER_BASE + 0x180)
+					/* Polo GPIO[39:32]  data reg   */
+#define POLO_GPIO_DAT6_REG	regptr(MSP_PER_BASE + 0x184)
+					/* Polo GPIO[47:40]  data reg   */
+#define POLO_GPIO_DAT7_REG	regptr(MSP_PER_BASE + 0x188)
+					/* Polo GPIO[54:48]  data reg   */
+#define POLO_GPIO_CFG4_REG	regptr(MSP_PER_BASE + 0x18C)
+					/* Polo GPIO[31:24] config reg  */
+#define POLO_GPIO_CFG5_REG	regptr(MSP_PER_BASE + 0x190)
+					/* Polo GPIO[39:32] config reg  */
+#define POLO_GPIO_CFG6_REG	regptr(MSP_PER_BASE + 0x194)
+					/* Polo GPIO[47:40] config reg  */
+#define POLO_GPIO_CFG7_REG	regptr(MSP_PER_BASE + 0x198)
+					/* Polo GPIO[54:48] config reg  */
+#define POLO_GPIO_OD2_REG	regptr(MSP_PER_BASE + 0x19C)
+					/* Polo GPIO[54:32] output drive */
+
+/* Generic GPIO registers                     */
+#define GPIO_DATA1_REG		regptr(MSP_PER_BASE + 0x170)
+					/* GPIO[1:0] data register      */
+#define GPIO_DATA2_REG		regptr(MSP_PER_BASE + 0x174)
+					/* GPIO[5:2] data register      */
+#define GPIO_DATA3_REG		regptr(MSP_PER_BASE + 0x178)
+					/* GPIO[9:6] data register      */
+#define GPIO_DATA4_REG		regptr(MSP_PER_BASE + 0x17C)
+					/* GPIO[15:10] data register    */
+#define GPIO_CFG1_REG		regptr(MSP_PER_BASE + 0x180)
+					/* GPIO[1:0] config register    */
+#define GPIO_CFG2_REG		regptr(MSP_PER_BASE + 0x184)
+					/* GPIO[5:2] config register    */
+#define GPIO_CFG3_REG		regptr(MSP_PER_BASE + 0x188)
+					/* GPIO[9:6] config register    */
+#define GPIO_CFG4_REG		regptr(MSP_PER_BASE + 0x18C)
+					/* GPIO[15:10] config register  */
+#define GPIO_OD_REG		regptr(MSP_PER_BASE + 0x190)
+					/* GPIO[15:0] output drive      */
+
+/*
+ ***************************************************************************
+ * CPU Interface register definitions                                      *
+ ***************************************************************************
+ */
+#define PCI_FLUSH_REG		regptr(MSP_CPUIF_BASE + 0x00)
+					/* PCI-SDRAM queue flush trigger */
+#define OCP_ERR1_REG		regptr(MSP_CPUIF_BASE + 0x04)
+					/* OCP Error Attribute 1        */
+#define OCP_ERR2_REG		regptr(MSP_CPUIF_BASE + 0x08)
+					/* OCP Error Attribute 2        */
+#define OCP_STS_REG		regptr(MSP_CPUIF_BASE + 0x0C)
+					/* OCP Error Status             */
+#define CPUIF_PM_REG		regptr(MSP_CPUIF_BASE + 0x10)
+					/* CPU policy configuration     */
+#define CPUIF_CFG_REG		regptr(MSP_CPUIF_BASE + 0x10)
+					/* Misc configuration options   */
+
+/* Central Interrupt Controller Registers */
+#define MSP_CIC_BASE		(MSP_CPUIF_BASE + 0x8000)
+					/* Central Interrupt registers  */
+#define CIC_EXT_CFG_REG		regptr(MSP_CIC_BASE + 0x00)
+					/* External interrupt config    */
+#define CIC_STS_REG		regptr(MSP_CIC_BASE + 0x04)
+					/* CIC Interrupt Status         */
+#define CIC_VPE0_MSK_REG	regptr(MSP_CIC_BASE + 0x08)
+					/* VPE0 Interrupt Mask          */
+#define CIC_VPE1_MSK_REG	regptr(MSP_CIC_BASE + 0x0C)
+					/* VPE1 Interrupt Mask          */
+#define CIC_TC0_MSK_REG		regptr(MSP_CIC_BASE + 0x10)
+					/* Thread Context 0 Int Mask    */
+#define CIC_TC1_MSK_REG		regptr(MSP_CIC_BASE + 0x14)
+					/* Thread Context 1 Int Mask    */
+#define CIC_TC2_MSK_REG		regptr(MSP_CIC_BASE + 0x18)
+					/* Thread Context 2 Int Mask    */
+#define CIC_TC3_MSK_REG		regptr(MSP_CIC_BASE + 0x18)
+					/* Thread Context 3 Int Mask    */
+#define CIC_TC4_MSK_REG		regptr(MSP_CIC_BASE + 0x18)
+					/* Thread Context 4 Int Mask    */
+#define CIC_PCIMSI_STS_REG	regptr(MSP_CIC_BASE + 0x18)
+#define CIC_PCIMSI_MSK_REG	regptr(MSP_CIC_BASE + 0x18)
+#define CIC_PCIFLSH_REG		regptr(MSP_CIC_BASE + 0x18)
+#define CIC_VPE0_SWINT_REG	regptr(MSP_CIC_BASE + 0x08)
+
+
+/*
+ ***************************************************************************
+ * Memory controller registers                                             *
+ ***************************************************************************
+ */
+#define MEM_CFG1_REG		regptr(MSP_MEM_CFG_BASE + 0x00)
+#define MEM_SS_ADDR		regptr(MSP_MEM_CFG_BASE + 0x00)
+#define MEM_SS_DATA		regptr(MSP_MEM_CFG_BASE + 0x04)
+#define MEM_SS_WRITE		regptr(MSP_MEM_CFG_BASE + 0x08)
+
+/*
+ ***************************************************************************
+ * PCI controller registers                                                *
+ ***************************************************************************
+ */
+#define PCI_BASE_REG		regptr(MSP_PCI_BASE + 0x00)
+#define PCI_CONFIG_SPACE_REG	regptr(MSP_PCI_BASE + 0x800)
+#define PCI_JTAG_DEVID_REG	regptr(MSP_SLP_BASE + 0x13c)
+
+/*
+ ########################################################################
+ #  Register content & macro definitions                                #
+ ########################################################################
+ */
+
+/*
+ ***************************************************************************
+ * DEV_ID defines                                                          *
+ ***************************************************************************
+ */
+#define DEV_ID_PCI_DIS		(1 << 26)       /* Set if PCI disabled */
+#define DEV_ID_PCI_HOST		(1 << 20)       /* Set if PCI host */
+#define DEV_ID_SINGLE_PC	(1 << 19)       /* Set if single PC Card */
+#define DEV_ID_FAMILY		(0xff << 8)     /* family ID code */
+#define POLO_ZEUS_SUB_FAMILY	(0x7  << 16)    /* sub family for Polo/Zeus */
+
+#define MSPFPGA_ID		(0x00  << 8)    /* you are on your own here */
+#define MSP5000_ID		(0x50  << 8)
+#define MSP4F00_ID		(0x4f  << 8)    /* FPGA version of MSP4200 */
+#define MSP4E00_ID		(0x4f  << 8)    /* FPGA version of MSP7120 */
+#define MSP4200_ID		(0x42  << 8)
+#define MSP4000_ID		(0x40  << 8)
+#define MSP2XXX_ID		(0x20  << 8)
+#define MSPZEUS_ID		(0x10  << 8)
+
+#define MSP2004_SUB_ID		(0x0   << 16)
+#define MSP2005_SUB_ID		(0x1   << 16)
+#define MSP2006_SUB_ID		(0x1   << 16)
+#define MSP2007_SUB_ID		(0x2   << 16)
+#define MSP2010_SUB_ID		(0x3   << 16)
+#define MSP2015_SUB_ID		(0x4   << 16)
+#define MSP2020_SUB_ID		(0x5   << 16)
+#define MSP2100_SUB_ID		(0x6   << 16)
+
+/*
+ ***************************************************************************
+ * RESET defines                                                           *
+ ***************************************************************************
+ */
+#define MSP_GR_RST		(0x01 << 0)     /* Global reset bit     */
+#define MSP_MR_RST		(0x01 << 1)     /* MIPS reset bit       */
+#define MSP_PD_RST		(0x01 << 2)     /* PVC DMA reset bit    */
+#define MSP_PP_RST		(0x01 << 3)     /* PVC reset bit        */
+/* reserved                                                             */
+#define MSP_EA_RST		(0x01 << 6)     /* Mac A reset bit      */
+#define MSP_EB_RST		(0x01 << 7)     /* Mac B reset bit      */
+#define MSP_SE_RST		(0x01 << 8)     /* Security Eng reset bit */
+#define MSP_PB_RST		(0x01 << 9)     /* Per block reset bit  */
+#define MSP_EC_RST		(0x01 << 10)    /* Mac C reset bit      */
+#define MSP_TW_RST		(0x01 << 11)    /* TWI reset bit        */
+#define MSP_SPI_RST		(0x01 << 12)    /* SPI/MPI reset bit    */
+#define MSP_U1_RST		(0x01 << 13)    /* UART1 reset bit      */
+#define MSP_U0_RST		(0x01 << 14)    /* UART0 reset bit      */
+
+/*
+ ***************************************************************************
+ * UART defines                                                            *
+ ***************************************************************************
+ */
+#ifndef CONFIG_MSP_FPGA
+#define MSP_BASE_BAUD		25000000
+#else
+#define MSP_BASE_BAUD		6000000
+#endif
+#define MSP_UART_REG_LEN	0x20
+
+/*
+ ***************************************************************************
+ * ELB defines                                                             *
+ ***************************************************************************
+ */
+#define PCCARD_32		0x02    /* Set if is PCCARD 32 (Cardbus) */
+#define SINGLE_PCCARD		0x01    /* Set to enable single PC card */
+
+/*
+ ***************************************************************************
+ * CIC defines                                                             *
+ ***************************************************************************
+ */
+
+/* CIC_EXT_CFG_REG */
+#define EXT_INT_POL(eirq)			(1 << (eirq + 8))
+#define EXT_INT_EDGE(eirq)			(1 << eirq)
+
+#define CIC_EXT_SET_TRIGGER_LEVEL(reg, eirq)	(reg &= ~EXT_INT_EDGE(eirq))
+#define CIC_EXT_SET_TRIGGER_EDGE(reg, eirq)	(reg |= EXT_INT_EDGE(eirq))
+#define CIC_EXT_SET_ACTIVE_HI(reg, eirq)	(reg |= EXT_INT_POL(eirq))
+#define CIC_EXT_SET_ACTIVE_LO(reg, eirq)	(reg &= ~EXT_INT_POL(eirq))
+#define CIC_EXT_SET_ACTIVE_RISING		CIC_EXT_SET_ACTIVE_HI
+#define CIC_EXT_SET_ACTIVE_FALLING		CIC_EXT_SET_ACTIVE_LO
+
+#define CIC_EXT_IS_TRIGGER_LEVEL(reg, eirq) \
+				((reg & EXT_INT_EDGE(eirq)) == 0)
+#define CIC_EXT_IS_TRIGGER_EDGE(reg, eirq)	(reg & EXT_INT_EDGE(eirq))
+#define CIC_EXT_IS_ACTIVE_HI(reg, eirq)		(reg & EXT_INT_POL(eirq))
+#define CIC_EXT_IS_ACTIVE_LO(reg, eirq) \
+				((reg & EXT_INT_POL(eirq)) == 0)
+#define CIC_EXT_IS_ACTIVE_RISING		CIC_EXT_IS_ACTIVE_HI
+#define CIC_EXT_IS_ACTIVE_FALLING		CIC_EXT_IS_ACTIVE_LO
+
+/*
+ ***************************************************************************
+ * Memory Controller defines                                               *
+ ***************************************************************************
+ */
+
+/* Indirect memory controller registers */
+#define DDRC_CFG(n)		(n)
+#define DDRC_DEBUG(n)		(0x04 + n)
+#define DDRC_CTL(n)		(0x40 + n)
+
+/* Macro to perform DDRC indirect write */
+#define DDRC_INDIRECT_WRITE(reg, mask, value) \
+({ \
+	*MEM_SS_ADDR = (((mask) & 0xf) << 8) | ((reg) & 0xff); \
+	*MEM_SS_DATA = (value); \
+	*MEM_SS_WRITE = 1; \
+})
+
+/*
+ ***************************************************************************
+ * SPI/MPI Mode                                                            *
+ ***************************************************************************
+ */
+#define SPI_MPI_RX_BUSY		0x00008000	/* SPI/MPI Receive Busy */
+#define SPI_MPI_FIFO_EMPTY	0x00004000	/* SPI/MPI Fifo Empty   */
+#define SPI_MPI_TX_BUSY		0x00002000	/* SPI/MPI Transmit Busy */
+#define SPI_MPI_FIFO_FULL	0x00001000	/* SPI/MPU FIFO full    */
+
+/*
+ ***************************************************************************
+ * SPI/MPI Control Register                                                *
+ ***************************************************************************
+ */
+#define SPI_MPI_RX_START	0x00000004	/* Start receive command */
+#define SPI_MPI_FLUSH_Q		0x00000002	/* Flush SPI/MPI Queue */
+#define SPI_MPI_TX_START	0x00000001	/* Start Transmit Command */
+
+#endif /* !_ASM_MSP_REGS_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h
new file mode 100644
index 0000000..96d4c8c
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h
@@ -0,0 +1,141 @@
+/*
+ * Defines for the MSP interrupt controller.
+ *
+ * Copyright (C) 1999 MIPS Technologies, Inc.  All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#ifndef _MSP_SLP_INT_H
+#define _MSP_SLP_INT_H
+
+/*
+ * The PMC-Sierra SLP interrupts are arranged in a 3 level cascaded
+ * hierarchical system.  The first level are the direct MIPS interrupts
+ * and are assigned the interrupt range 0-7.  The second level is the SLM
+ * interrupt controller and is assigned the range 8-39.  The third level
+ * comprises the Peripherial block, the PCI block, the PCI MSI block and
+ * the SLP.  The PCI interrupts and the SLP errors are handled by the
+ * relevant subsystems so the core interrupt code needs only concern
+ * itself with the Peripheral block.  These are assigned interrupts in
+ * the range 40-71.
+ */
+
+/*
+ * IRQs directly connected to CPU
+ */
+#define MSP_MIPS_INTBASE	0
+#define MSP_INT_SW0		0  /* IRQ for swint0,         C_SW0  */
+#define MSP_INT_SW1		1  /* IRQ for swint1,         C_SW1  */
+#define MSP_INT_MAC0 		2  /* IRQ for MAC 0,          C_IRQ0 */
+#define MSP_INT_MAC1		3  /* IRQ for MAC 1,          C_IRQ1 */
+#define MSP_INT_C_IRQ2		4  /* Wired off,              C_IRQ2 */
+#define MSP_INT_VE		5  /* IRQ for Voice Engine,   C_IRQ3 */
+#define MSP_INT_SLP		6  /* IRQ for SLM block,      C_IRQ4 */
+#define MSP_INT_TIMER		7  /* IRQ for the MIPS timer, C_IRQ5 */
+
+/*
+ * IRQs cascaded on CPU interrupt 4 (CAUSE bit 12, C_IRQ4)
+ * These defines should be tied to the register definition for the SLM
+ * interrupt routine.  For now, just use hard-coded values.
+ */
+#define MSP_SLP_INTBASE		(MSP_MIPS_INTBASE + 8)
+#define MSP_INT_EXT0		(MSP_SLP_INTBASE + 0)
+					/* External interrupt 0         */
+#define MSP_INT_EXT1		(MSP_SLP_INTBASE + 1)
+					/* External interrupt 1         */
+#define MSP_INT_EXT2		(MSP_SLP_INTBASE + 2)
+					/* External interrupt 2         */
+#define MSP_INT_EXT3		(MSP_SLP_INTBASE + 3)
+					/* External interrupt 3         */
+/* Reserved					   4-7                  */
+
+/*
+ *************************************************************************
+ * DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER *
+ * Some MSP produces have this interrupt labelled as Voice and some are  *
+ * SEC mbox ...                                                          *
+ *************************************************************************
+ */
+#define MSP_INT_SLP_VE		(MSP_SLP_INTBASE + 8)
+					/* Cascaded IRQ for Voice Engine*/
+#define MSP_INT_SLP_TDM		(MSP_SLP_INTBASE + 9)
+					/* TDM interrupt                */
+#define MSP_INT_SLP_MAC0	(MSP_SLP_INTBASE + 10)
+					/* Cascaded IRQ for MAC 0       */
+#define MSP_INT_SLP_MAC1	(MSP_SLP_INTBASE + 11)
+					/* Cascaded IRQ for MAC 1       */
+#define MSP_INT_SEC		(MSP_SLP_INTBASE + 12)
+					/* IRQ for security engine      */
+#define	MSP_INT_PER		(MSP_SLP_INTBASE + 13)
+					/* Peripheral interrupt         */
+#define	MSP_INT_TIMER0		(MSP_SLP_INTBASE + 14)
+					/* SLP timer 0                  */
+#define	MSP_INT_TIMER1		(MSP_SLP_INTBASE + 15)
+					/* SLP timer 1                  */
+#define	MSP_INT_TIMER2		(MSP_SLP_INTBASE + 16)
+					/* SLP timer 2                  */
+#define	MSP_INT_SLP_TIMER	(MSP_SLP_INTBASE + 17)
+					/* Cascaded MIPS timer          */
+#define MSP_INT_BLKCP		(MSP_SLP_INTBASE + 18)
+					/* Block Copy                   */
+#define MSP_INT_UART0		(MSP_SLP_INTBASE + 19)
+					/* UART 0                       */
+#define MSP_INT_PCI		(MSP_SLP_INTBASE + 20)
+					/* PCI subsystem                */
+#define MSP_INT_PCI_DBELL	(MSP_SLP_INTBASE + 21)
+					/* PCI doorbell                 */
+#define MSP_INT_PCI_MSI		(MSP_SLP_INTBASE + 22)
+					/* PCI Message Signal           */
+#define MSP_INT_PCI_BC0		(MSP_SLP_INTBASE + 23)
+					/* PCI Block Copy 0             */
+#define MSP_INT_PCI_BC1		(MSP_SLP_INTBASE + 24)
+					/* PCI Block Copy 1             */
+#define MSP_INT_SLP_ERR		(MSP_SLP_INTBASE + 25)
+					/* SLP error condition          */
+#define MSP_INT_MAC2		(MSP_SLP_INTBASE + 26)
+					/* IRQ for MAC2                 */
+/* Reserved					   26-31                */
+
+/*
+ * IRQs cascaded on SLP PER interrupt (MSP_INT_PER)
+ */
+#define MSP_PER_INTBASE		(MSP_SLP_INTBASE + 32)
+/* Reserved					   0-1                  */
+#define MSP_INT_UART1		(MSP_PER_INTBASE + 2)
+					/* UART 1                       */
+/* Reserved					   3-5                  */
+#define MSP_INT_2WIRE		(MSP_PER_INTBASE + 6)
+					/* 2-wire                       */
+#define MSP_INT_TM0		(MSP_PER_INTBASE + 7)
+					/* Peripheral timer block out 0 */
+#define MSP_INT_TM1		(MSP_PER_INTBASE + 8)
+					/* Peripheral timer block out 1 */
+/* Reserved					   9                    */
+#define MSP_INT_SPRX		(MSP_PER_INTBASE + 10)
+					/* SPI RX complete              */
+#define MSP_INT_SPTX		(MSP_PER_INTBASE + 11)
+					/* SPI TX complete              */
+#define MSP_INT_GPIO		(MSP_PER_INTBASE + 12)
+					/* GPIO                         */
+#define MSP_INT_PER_ERR		(MSP_PER_INTBASE + 13)
+					/* Peripheral error             */
+/* Reserved					   14-31                */
+
+#endif /* !_MSP_SLP_INT_H */
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index 5f80ba7..1d8b9a8 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -82,10 +82,6 @@
 	unsigned int	fcr31;
 };
 
-#define INIT_FPU { \
-	{0,} \
-}
-
 #define NUM_DSP_REGS   6
 
 typedef __u32 dspreg_t;
@@ -95,8 +91,6 @@
 	unsigned int    dspcontrol;
 };
 
-#define INIT_DSP {{0,},}
-
 #define INIT_CPUMASK { \
 	{0,} \
 }
@@ -155,41 +149,63 @@
 #define MF_N64		0
 
 #ifdef CONFIG_MIPS_MT_FPAFF
-#define FPAFF_INIT 0, INIT_CPUMASK,
+#define FPAFF_INIT						\
+	.emulated_fp			= 0,			\
+	.user_cpus_allowed		= INIT_CPUMASK,
 #else
 #define FPAFF_INIT
 #endif /* CONFIG_MIPS_MT_FPAFF */
 
-#define INIT_THREAD  { \
-        /* \
-         * saved main processor registers \
-         */ \
-	0, 0, 0, 0, 0, 0, 0, 0, \
-	               0, 0, 0, \
-	/* \
-	 * saved cp0 stuff \
-	 */ \
-	0, \
-	/* \
-	 * saved fpu/fpu emulator stuff \
-	 */ \
-	INIT_FPU, \
-	/* \
-	 * fpu affinity state (null if not FPAFF) \
-	 */ \
-	FPAFF_INIT \
-	/* \
-	 * saved dsp/dsp emulator stuff \
-	 */ \
-	INIT_DSP, \
-	/* \
-	 * Other stuff associated with the process \
-	 */ \
-	0, 0, 0, 0, \
-	/* \
-	 * For now the default is to fix address errors \
-	 */ \
-	MF_FIXADE, 0, 0 \
+#define INIT_THREAD  {						\
+        /*							\
+         * Saved main processor registers			\
+         */							\
+	.reg16			= 0,				\
+	.reg17			= 0,				\
+	.reg18			= 0,				\
+	.reg19			= 0,				\
+	.reg20			= 0,				\
+	.reg21			= 0,				\
+	.reg22			= 0,				\
+	.reg23			= 0,				\
+	.reg29			= 0,				\
+	.reg30			= 0,				\
+	.reg31			= 0,				\
+	/*							\
+	 * Saved cp0 stuff					\
+	 */							\
+	.cp0_status		= 0,				\
+	/*							\
+	 * Saved FPU/FPU emulator stuff				\
+	 */							\
+	.fpu			= {				\
+		.fpr		= {0,},				\
+		.fcr31		= 0,				\
+	},							\
+	/*							\
+	 * FPU affinity state (null if not FPAFF)		\
+	 */							\
+	FPAFF_INIT						\
+	/*							\
+	 * Saved DSP stuff					\
+	 */							\
+	.dsp			= {				\
+		.dspr		= {0, },			\
+		.dspcontrol	= 0,				\
+	},							\
+	/*							\
+	 * Other stuff associated with the process		\
+	 */							\
+	.cp0_badvaddr		= 0,				\
+	.cp0_baduaddr		= 0,				\
+	.error_code		= 0,				\
+	.trap_no		= 0,				\
+	/*							\
+	 * For now the default is to fix address errors		\
+	 */							\
+	.mflags			= MF_FIXADE,			\
+	.irix_trampoline	= 0,				\
+	.irix_oldctx		= 0,				\
 }
 
 struct task_struct;
@@ -237,7 +253,7 @@
 
 #define ARCH_HAS_PREFETCH
 
-extern inline void prefetch(const void *addr)
+static inline void prefetch(const void *addr)
 {
 	__asm__ __volatile__(
 	"	.set	mips4		\n"
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index ce51213..c07ebd8 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -19,159 +19,4 @@
  */
 #define BASE_BAUD (1843200 / 16)
 
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
-#endif
-
-#ifdef CONFIG_MACH_JAZZ
-#include <asm/jazz.h>
-
-#ifndef CONFIG_OLIVETTI_M700
-   /* Some Jazz machines seem to have an 8MHz crystal clock but I don't know
-      exactly which ones ... XXX */
-#define JAZZ_BASE_BAUD ( 8000000 / 16 ) /* ( 3072000 / 16) */
-#else
-/* but the M700 isn't such a strange beast */
-#define JAZZ_BASE_BAUD BASE_BAUD
-#endif
-
-#define _JAZZ_SERIAL_INIT(int, base)					\
-	{ .baud_base = JAZZ_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS,	\
-	  .iomem_base = (u8 *) base, .iomem_reg_shift = 0,			\
-	  .io_type = SERIAL_IO_MEM }
-#define JAZZ_SERIAL_PORT_DEFNS						\
-	_JAZZ_SERIAL_INIT(JAZZ_SERIAL1_IRQ, JAZZ_SERIAL1_BASE),		\
-	_JAZZ_SERIAL_INIT(JAZZ_SERIAL2_IRQ, JAZZ_SERIAL2_BASE),
-#else
-#define JAZZ_SERIAL_PORT_DEFNS
-#endif
-
-/*
- * Galileo EV64120 evaluation board
- */
-#ifdef CONFIG_MIPS_EV64120
-#include <mach-gt64120.h>
-#define EV64120_SERIAL_PORT_DEFNS                                  \
-    { .baud_base = EV64120_BASE_BAUD, .irq = EV64120_UART_IRQ, \
-      .flags = STD_COM_FLAGS,  \
-      .iomem_base = EV64120_UART0_REGS_BASE, .iomem_reg_shift = 2, \
-      .io_type = SERIAL_IO_MEM }, \
-    { .baud_base = EV64120_BASE_BAUD, .irq = EV64120_UART_IRQ, \
-      .flags = STD_COM_FLAGS, \
-      .iomem_base = EV64120_UART1_REGS_BASE, .iomem_reg_shift = 2, \
-      .io_type = SERIAL_IO_MEM },
-#else
-#define EV64120_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT
-#define STD_SERIAL_PORT_DEFNS			\
-	/* UART CLK   PORT IRQ     FLAGS        */			\
-	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
-	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },	/* ttyS1 */	\
-	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
-	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
-
-#else /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
-#define STD_SERIAL_PORT_DEFNS
-#endif /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
-
-#ifdef CONFIG_MOMENCO_OCELOT_3
-#define OCELOT_3_BASE_BAUD	( 20000000 / 16 )
-#define OCELOT_3_SERIAL_IRQ	6
-#define OCELOT_3_SERIAL_BASE	(signed)0xfd000020
-
-#define _OCELOT_3_SERIAL_INIT(int, base)				\
-	{ .baud_base = OCELOT_3_BASE_BAUD, irq: int, 			\
-	  .flags = STD_COM_FLAGS,						\
-	  .iomem_base = (u8 *) base, iomem_reg_shift: 2,			\
-	  io_type: SERIAL_IO_MEM }
-
-#define MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS				\
-	_OCELOT_3_SERIAL_INIT(OCELOT_3_SERIAL_IRQ, OCELOT_3_SERIAL_BASE)
-#else
-#define MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_MOMENCO_OCELOT
-/* Ordinary NS16552 duart with a 20MHz crystal.  */
-#define OCELOT_BASE_BAUD ( 20000000 / 16 )
-
-#define OCELOT_SERIAL1_IRQ	4
-#define OCELOT_SERIAL1_BASE	0xe0001020
-
-#define _OCELOT_SERIAL_INIT(int, base)					\
-	{ .baud_base = OCELOT_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS,	\
-	  .iomem_base = (u8 *) base, .iomem_reg_shift = 2,			\
-	  .io_type = SERIAL_IO_MEM }
-#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS				\
-	_OCELOT_SERIAL_INIT(OCELOT_SERIAL1_IRQ, OCELOT_SERIAL1_BASE)
-#else
-#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_MOMENCO_OCELOT_C
-/* Ordinary NS16552 duart with a 20MHz crystal.  */
-#define OCELOT_C_BASE_BAUD ( 20000000 / 16 )
-
-#define OCELOT_C_SERIAL1_IRQ	80
-#define OCELOT_C_SERIAL1_BASE	0xfd000020
-
-#define OCELOT_C_SERIAL2_IRQ	81
-#define OCELOT_C_SERIAL2_BASE	0xfd000000
-
-#define _OCELOT_C_SERIAL_INIT(int, base)				\
-	{ .baud_base		= OCELOT_C_BASE_BAUD,			\
-	  .irq			= (int),				\
-	  .flags		= STD_COM_FLAGS,			\
-	  .iomem_base		= (u8 *) base,				\
-	  .iomem_reg_shift	= 2,					\
-	  .io_type		= SERIAL_IO_MEM				\
-	 }
-#define MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS				\
-	_OCELOT_C_SERIAL_INIT(OCELOT_C_SERIAL1_IRQ, OCELOT_C_SERIAL1_BASE), \
-	_OCELOT_C_SERIAL_INIT(OCELOT_C_SERIAL2_IRQ, OCELOT_C_SERIAL2_BASE)
-#else
-#define MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_DDB5477
-#include <asm/ddb5xxx/ddb5477.h>
-#define DDB5477_SERIAL_PORT_DEFNS                                       \
-        { .baud_base = BASE_BAUD, .irq = VRC5477_IRQ_UART0, 		\
-	  .flags = STD_COM_FLAGS, .iomem_base = (u8*)0xbfa04200, 	\
-	  .iomem_reg_shift = 3, .io_type = SERIAL_IO_MEM},		\
-        { .baud_base = BASE_BAUD, .irq = VRC5477_IRQ_UART1, 		\
-	  .flags = STD_COM_FLAGS, .iomem_base = (u8*)0xbfa04240, 	\
-	  .iomem_reg_shift = 3, .io_type = SERIAL_IO_MEM},
-#else
-#define DDB5477_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_SGI_IP32
-/*
- * The IP32 (SGI O2) has standard serial ports (UART 16550A) mapped in memory
- * They are initialized in ip32_setup
- */
-#define IP32_SERIAL_PORT_DEFNS				\
-        {},{},
-#else
-#define IP32_SERIAL_PORT_DEFNS
-#endif /* CONFIG_SGI_IP32 */
-
-#define SERIAL_PORT_DFNS				\
-	DDB5477_SERIAL_PORT_DEFNS			\
-	EV64120_SERIAL_PORT_DEFNS			\
-	IP32_SERIAL_PORT_DEFNS                          \
-	JAZZ_SERIAL_PORT_DEFNS				\
-	STD_SERIAL_PORT_DEFNS				\
-	MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS		\
-	MOMENCO_OCELOT_SERIAL_PORT_DEFNS		\
-	MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
-
 #endif /* _ASM_SERIAL_H */
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h
index 1608fd7..13aef6a 100644
--- a/include/asm-mips/smp.h
+++ b/include/asm-mips/smp.h
@@ -49,13 +49,6 @@
 extern cpumask_t phys_cpu_present_map;
 #define cpu_possible_map	phys_cpu_present_map
 
-extern cpumask_t cpu_callout_map;
-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
-static inline int num_booting_cpus(void)
-{
-	return cpus_weight(cpu_callout_map);
-}
-
 /*
  * These are defined by the board-specific code.
  */
diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h
index f257509..ddaf36a 100644
--- a/include/asm-mips/sni.h
+++ b/include/asm-mips/sni.h
@@ -146,9 +146,6 @@
 #define SNI_A20R_IRQ_BASE       MIPS_CPU_IRQ_BASE
 #define SNI_A20R_IRQ_TIMER      (SNI_A20R_IRQ_BASE+5)
 
-#define SNI_DS1216_A20R_BASE    0xbc081ffc
-#define SNI_DS1216_RM200_BASE   0xbcd41ffc
-
 #define SNI_PCIT_INT_REG        0xbfff000c
 
 #define SNI_PCIT_INT_START      24
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index bb0b289..46bdb3f 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -44,7 +44,7 @@
  * different thread.
  */
 
-#define switch_to(prev,next,last)					\
+#define __mips_mt_fpaff_switch_to(prev)					\
 do {									\
 	if (cpu_has_fpu &&						\
 	    (prev->thread.mflags & MF_FPUBOUND) &&			\
@@ -52,24 +52,24 @@
 		prev->thread.mflags &= ~MF_FPUBOUND;			\
 		prev->cpus_allowed = prev->thread.user_cpus_allowed;	\
 	}								\
-	if (cpu_has_dsp)						\
-		__save_dsp(prev);					\
 	next->thread.emulated_fp = 0;					\
-	(last) = resume(prev, next, task_thread_info(next));		\
-	if (cpu_has_dsp)						\
-		__restore_dsp(current);					\
 } while(0)
 
 #else
+#define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0)
+#endif
+
 #define switch_to(prev,next,last)					\
 do {									\
+	__mips_mt_fpaff_switch_to(prev);				\
 	if (cpu_has_dsp)						\
 		__save_dsp(prev);					\
 	(last) = resume(prev, next, task_thread_info(next));		\
 	if (cpu_has_dsp)						\
 		__restore_dsp(current);					\
+	if (cpu_has_userlocal)						\
+		write_c0_userlocal(task_thread_info(current)->tp_value);\
 } while(0)
-#endif
 
 /*
  * On SMP systems, when the scheduler does migration-cost autodetection,
diff --git a/include/asm-mips/termbits.h b/include/asm-mips/termbits.h
index 0bbe07b..5bfdc3b 100644
--- a/include/asm-mips/termbits.h
+++ b/include/asm-mips/termbits.h
@@ -30,6 +30,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-mips/tx4938/rbtx4938.h b/include/asm-mips/tx4938/rbtx4938.h
index 0fbedaf..74e7d80 100644
--- a/include/asm-mips/tx4938/rbtx4938.h
+++ b/include/asm-mips/tx4938/rbtx4938.h
@@ -105,12 +105,6 @@
 #define rbtx4938_pcireset_ptr	\
 	((volatile unsigned char *)RBTX4938_PCIRESET_ADDR)
 
-/* SPI */
-#define RBTX4938_SEEPROM1_CHIPID	0
-#define RBTX4938_SEEPROM2_CHIPID	1
-#define RBTX4938_SEEPROM3_CHIPID	2
-#define RBTX4938_SRTC_CHIPID	3
-
 /*
  * IRQ mappings
  */
diff --git a/include/asm-mips/tx4938/spi.h b/include/asm-mips/tx4938/spi.h
index 0dbbab8..6a60c83 100644
--- a/include/asm-mips/tx4938/spi.h
+++ b/include/asm-mips/tx4938/spi.h
@@ -14,61 +14,7 @@
 #ifndef __ASM_TX_BOARDS_TX4938_SPI_H
 #define __ASM_TX_BOARDS_TX4938_SPI_H
 
-/* SPI */
-struct spi_dev_desc {
-	unsigned int baud;
-	unsigned short tcss, tcsh, tcsr; /* CS setup/hold/recovery time */
-	unsigned int byteorder:1;	/* 0:LSB-First, 1:MSB-First */
-	unsigned int polarity:1;	/* 0:High-Active */
-	unsigned int phase:1;		/* 0:Sample-Then-Shift */
-};
-
-extern void txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on)) __init;
-extern void txx9_spi_irqinit(int irc_irq) __init;
-extern int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
-		       unsigned char **inbufs, unsigned int *incounts,
-		       unsigned char **outbufs, unsigned int *outcounts,
-		       int cansleep);
-extern int spi_eeprom_write_enable(int chipid, int enable);
-extern int spi_eeprom_read_status(int chipid);
+extern int spi_eeprom_register(int chipid);
 extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len);
-extern int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len);
-extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid) __init;
-
-#define TXX9_IMCLK     (txx9_gbus_clock / 2)
-
-/*
-* SPI
-*/
-
-/* SPMCR : SPI Master Control */
-#define TXx9_SPMCR_OPMODE	0xc0
-#define TXx9_SPMCR_CONFIG	0x40
-#define TXx9_SPMCR_ACTIVE	0x80
-#define TXx9_SPMCR_SPSTP	0x02
-#define TXx9_SPMCR_BCLR	0x01
-
-/* SPCR0 : SPI Status */
-#define TXx9_SPCR0_TXIFL_MASK	0xc000
-#define TXx9_SPCR0_RXIFL_MASK	0x3000
-#define TXx9_SPCR0_SIDIE	0x0800
-#define TXx9_SPCR0_SOEIE	0x0400
-#define TXx9_SPCR0_RBSIE	0x0200
-#define TXx9_SPCR0_TBSIE	0x0100
-#define TXx9_SPCR0_IFSPSE	0x0010
-#define TXx9_SPCR0_SBOS	0x0004
-#define TXx9_SPCR0_SPHA	0x0002
-#define TXx9_SPCR0_SPOL	0x0001
-
-/* SPSR : SPI Status */
-#define TXx9_SPSR_TBSI	0x8000
-#define TXx9_SPSR_RBSI	0x4000
-#define TXx9_SPSR_TBS_MASK	0x3800
-#define TXx9_SPSR_RBS_MASK	0x0700
-#define TXx9_SPSR_SPOE	0x0080
-#define TXx9_SPSR_IFSD	0x0008
-#define TXx9_SPSR_SIDLE	0x0004
-#define TXx9_SPSR_STRDY	0x0002
-#define TXx9_SPSR_SRRDY	0x0001
 
 #endif /* __ASM_TX_BOARDS_TX4938_SPI_H */
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h
index ec0eeeb..9de52a5 100644
--- a/include/asm-mips/war.h
+++ b/include/asm-mips/war.h
@@ -169,10 +169,9 @@
 
 /*
  * On the RM9000 there is a problem which makes the CreateDirtyExclusive
- * cache operation unusable on SMP systems.
+ * eache operation unusable on SMP systems.
  */
-#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_PMC_YOSEMITE) || \
-    defined(CONFIG_BASLER_EXCITE)
+#if defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_BASLER_EXCITE)
 #define  RM9000_CDEX_SMP_WAR		1
 #endif
 
@@ -182,11 +181,10 @@
  * I-cache line worth of instructions being fetched may case spurious
  * exceptions.
  */
-#if defined(CONFIG_BASLER_EXCITE) || defined(CONFIG_MOMENCO_JAGUAR_ATX) || \
-    defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA) || \
-    defined(CONFIG_MOMENCO_OCELOT) || defined(CONFIG_MOMENCO_OCELOT_3) || \
-    defined(CONFIG_MOMENCO_OCELOT_C) || defined(CONFIG_PMC_YOSEMITE) || \
-    defined(CONFIG_SGI_IP32) || defined(CONFIG_WR_PPMC)
+#if defined(CONFIG_BASLER_EXCITE) || defined(CONFIG_MIPS_ATLAS) || \
+    defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MOMENCO_OCELOT) || \
+    defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_SGI_IP32) || \
+    defined(CONFIG_WR_PPMC)
 #define ICACHE_REFILLS_WORKAROUND_WAR	1
 #endif
 
@@ -200,6 +198,14 @@
 #endif
 
 /*
+ * 34K core erratum: "Problems Executing the TLBR Instruction"
+ */
+#if defined(CONFIG_PMC_MSP7120_EVAL) || defined(CONFIG_PMC_MSP7120_GW) || \
+	defined(CONFIG_PMC_MSP7120_FPGA)
+#define MIPS34K_MISSED_ITLB_WAR		1
+#endif
+
+/*
  * Workarounds default to off
  */
 #ifndef ICACHE_REFILLS_WORKAROUND_WAR
@@ -238,5 +244,8 @@
 #ifndef R10000_LLSC_WAR
 #define R10000_LLSC_WAR			0
 #endif
+#ifndef MIPS34K_MISSED_ITLB_WAR
+#define MIPS34K_MISSED_ITLB_WAR		0
+#endif
 
 #endif /* _ASM_WAR_H */
diff --git a/include/asm-mips/watch.h b/include/asm-mips/watch.h
deleted file mode 100644
index 6aa90ca..0000000
--- a/include/asm-mips/watch.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996, 1997, 1998, 2000, 2001 by Ralf Baechle
- */
-#ifndef _ASM_WATCH_H
-#define _ASM_WATCH_H
-
-#include <linux/linkage.h>
-
-/*
- * Types of reference for watch_set()
- */
-enum wref_type {
-	wr_save = 1,
-	wr_load = 2
-};
-
-extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref);
-extern asmlinkage void __watch_clear(void);
-extern asmlinkage void __watch_reenable(void);
-
-#define watch_set(addr, ref)					\
-	if (cpu_has_watch)					\
-		__watch_set(addr, ref)
-#define watch_clear()						\
-	if (cpu_has_watch)					\
-		__watch_clear()
-#define watch_reenable()					\
-	if (cpu_has_watch)					\
-		__watch_reenable()
-
-#endif /* _ASM_WATCH_H */
diff --git a/include/asm-parisc/termbits.h b/include/asm-parisc/termbits.h
index a46e299..e847fe9 100644
--- a/include/asm-parisc/termbits.h
+++ b/include/asm-parisc/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index c17bdbf..ea48695 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -24,7 +24,7 @@
  */
 
 typedef struct {
-	volatile int counter;
+	int counter;
 } __attribute__ ((aligned (4))) atomic_t;
 #define ATOMIC_INIT(i)  { (i) }
 
@@ -141,7 +141,7 @@
 
 #ifdef __s390x__
 typedef struct {
-	volatile long long counter;
+	long long counter;
 } __attribute__ ((aligned (8))) atomic64_t;
 #define ATOMIC64_INIT(i)  { (i) }
 
diff --git a/include/asm-s390/cmb.h b/include/asm-s390/cmb.h
index 241756f..021e7c3 100644
--- a/include/asm-s390/cmb.h
+++ b/include/asm-s390/cmb.h
@@ -88,7 +88,6 @@
  *    any
  **/
 extern int cmf_readall(struct ccw_device *cdev, struct cmbdata*data);
-extern void cmf_reset(struct ccw_device *cdev);
 
 #endif /* __KERNEL__ */
 #endif /* S390_CMB_H */
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 5cb480a..3b972d4 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -357,8 +357,8 @@
 /*
  * CPU idle notifier chain.
  */
-#define CPU_IDLE	0
-#define CPU_NOT_IDLE	1
+#define S390_CPU_IDLE		0
+#define S390_CPU_NOT_IDLE	1
 
 struct notifier_block;
 int register_idle_notifier(struct notifier_block *nb);
diff --git a/include/asm-s390/sclp.h b/include/asm-s390/sclp.h
index 21ed647..cb9faf1 100644
--- a/include/asm-s390/sclp.h
+++ b/include/asm-s390/sclp.h
@@ -11,29 +11,6 @@
 #include <linux/types.h>
 #include <asm/chpid.h>
 
-struct sccb_header {
-	u16	length;
-	u8	function_code;
-	u8	control_mask[3];
-	u16	response_code;
-} __attribute__((packed));
-
-#define LOADPARM_LEN 8
-
-struct sclp_readinfo_sccb {
-	struct	sccb_header header;	/* 0-7 */
-	u16	rnmax;			/* 8-9 */
-	u8	rnsize;			/* 10 */
-	u8	_reserved0[24 - 11];	/* 11-23 */
-	u8	loadparm[LOADPARM_LEN];	/* 24-31 */
-	u8	_reserved1[91 - 32];	/* 32-90 */
-	u8	flags;			/* 91 */
-	u8	_reserved2[100 - 92];	/* 92-99 */
-	u32	rnsize2;		/* 100-103 */
-	u64	rnmax2;			/* 104-111 */
-	u8	_reserved3[4096 - 112];	/* 112-4095 */
-} __attribute__((packed, aligned(4096)));
-
 #define SCLP_CHP_INFO_MASK_SIZE		32
 
 struct sclp_chp_info {
@@ -42,12 +19,22 @@
 	u8 configured[SCLP_CHP_INFO_MASK_SIZE];
 };
 
-extern struct sclp_readinfo_sccb s390_readinfo_sccb;
-extern void sclp_readinfo_early(void);
-extern int sclp_sdias_blk_count(void);
-extern int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
-extern int sclp_chp_configure(struct chp_id chpid);
-extern int sclp_chp_deconfigure(struct chp_id chpid);
-extern int sclp_chp_read_info(struct sclp_chp_info *info);
+#define LOADPARM_LEN 8
+
+struct sclp_ipl_info {
+	int is_valid;
+	int has_dump;
+	char loadparm[LOADPARM_LEN];
+};
+
+void sclp_readinfo_early(void);
+void sclp_facilities_detect(void);
+unsigned long long sclp_memory_detect(void);
+int sclp_sdias_blk_count(void);
+int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
+int sclp_chp_configure(struct chp_id chpid);
+int sclp_chp_deconfigure(struct chp_id chpid);
+int sclp_chp_read_info(struct sclp_chp_info *info);
+void sclp_get_ipl_info(struct sclp_ipl_info *info);
 
 #endif /* _ASM_S390_SCLP_H */
diff --git a/include/asm-s390/sfp-machine.h b/include/asm-s390/sfp-machine.h
index 8ca8c77..4e16aed 100644
--- a/include/asm-s390/sfp-machine.h
+++ b/include/asm-s390/sfp-machine.h
@@ -27,9 +27,9 @@
    
 
 #define _FP_W_TYPE_SIZE		32
-#define _FP_W_TYPE		unsigned long
-#define _FP_WS_TYPE		signed long
-#define _FP_I_TYPE		long
+#define _FP_W_TYPE		unsigned int
+#define _FP_WS_TYPE		signed int
+#define _FP_I_TYPE		int
 
 #define _FP_MUL_MEAT_S(R,X,Y)					\
   _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
diff --git a/include/asm-s390/sfp-util.h b/include/asm-s390/sfp-util.h
index 8cabcd2..0addc64 100644
--- a/include/asm-s390/sfp-util.h
+++ b/include/asm-s390/sfp-util.h
@@ -51,6 +51,16 @@
 	wl = __wl;					\
 })
 
+#ifdef __s390x__
+#define udiv_qrnnd(q, r, n1, n0, d)			\
+  do { unsigned long __n;				\
+       unsigned int __r, __d;				\
+    __n = ((unsigned long)(n1) << 32) + n0;		\
+    __d = (d);						\
+    (q) = __n / __d;					\
+    (r) = __n % __d;					\
+  } while (0)
+#else
 #define udiv_qrnnd(q, r, n1, n0, d)			\
   do { unsigned int __r;				\
     (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));		\
@@ -58,6 +68,7 @@
   } while (0)
 extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int,
 				   unsigned int , unsigned int);
+#endif
 
 #define UDIV_NEEDS_NORMALIZATION 0
 
diff --git a/include/asm-s390/termbits.h b/include/asm-s390/termbits.h
index 585c78a..811b9a9 100644
--- a/include/asm-s390/termbits.h
+++ b/include/asm-s390/termbits.h
@@ -25,6 +25,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-sh/termbits.h b/include/asm-sh/termbits.h
index f1b7b46..7ee1b42 100644
--- a/include/asm-sh/termbits.h
+++ b/include/asm-sh/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-v850/termbits.h b/include/asm-v850/termbits.h
index f3b4330..35412f7 100644
--- a/include/asm-v850/termbits.h
+++ b/include/asm-v850/termbits.h
@@ -17,6 +17,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/asm-xtensa/termbits.h b/include/asm-xtensa/termbits.h
index 057b9a3..9972c25 100644
--- a/include/asm-xtensa/termbits.h
+++ b/include/asm-xtensa/termbits.h
@@ -30,6 +30,17 @@
 	cc_t c_cc[NCCS];		/* control characters */
 };
 
+struct termios2 {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
 struct ktermios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index f317c27..127d2d1 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -49,6 +49,7 @@
 header-y += const.h
 header-y += cycx_cfm.h
 header-y += dlm_device.h
+header-y += dlm_netlink.h
 header-y += dm-ioctl.h
 header-y += dn.h
 header-y += dqblk_v1.h
@@ -90,7 +91,6 @@
 header-y += in_route.h
 header-y += ioctl.h
 header-y += ipmi_msgdefs.h
-header-y += ip_mp_alg.h
 header-y += ipsec.h
 header-y += ipx.h
 header-y += irda.h
@@ -225,6 +225,7 @@
 unifdef-y += if_frad.h
 unifdef-y += if_ltalk.h
 unifdef-y += if_link.h
+unifdef-y += if_pppol2tp.h
 unifdef-y += if_pppox.h
 unifdef-y += if_shaper.h
 unifdef-y += if_tr.h
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 703febb..407dc7e 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -126,6 +126,7 @@
 	ATA_REG_IRQ		= ATA_REG_NSECT,
 
 	/* ATA device commands */
+	ATA_CMD_DEV_RESET	= 0x08, /* ATAPI device reset */
 	ATA_CMD_CHK_POWER	= 0xE5, /* check power mode */
 	ATA_CMD_STANDBY		= 0xE2, /* place in standby power mode */
 	ATA_CMD_IDLE		= 0xE3, /* place in idle power mode */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index db5b00a..fae138b 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -868,11 +868,6 @@
  */
 #define buffer_heads_over_limit 0
 
-static inline long blk_congestion_wait(int rw, long timeout)
-{
-	return io_schedule_timeout(timeout);
-}
-
 static inline long nr_blockdev_pages(void)
 {
 	return 0;
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index 1b1dcb9..be9d278 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -85,7 +85,11 @@
  * Only relevant to locks originating in userspace.  A persistent lock will not
  * be removed if the process holding the lock exits.
  *
- * DLM_LKF_NODLKWT
+ * DLM_LKF_NODLCKWT
+ *
+ * Do not cancel the lock if it gets into conversion deadlock.
+ * Exclude this lock from being monitored due to DLM_LSFL_TIMEWARN.
+ *
  * DLM_LKF_NODLCKBLK
  *
  * net yet implemented
@@ -149,6 +153,7 @@
 #define DLM_LKF_ALTPR		0x00008000
 #define DLM_LKF_ALTCW		0x00010000
 #define DLM_LKF_FORCEUNLOCK	0x00020000
+#define DLM_LKF_TIMEOUT		0x00040000
 
 /*
  * Some return codes that are not in errno.h
@@ -199,11 +204,12 @@
 	char *	 sb_lvbptr;
 };
 
+#define DLM_LSFL_NODIR		0x00000001
+#define DLM_LSFL_TIMEWARN	0x00000002
+#define DLM_LSFL_FS     	0x00000004
 
 #ifdef __KERNEL__
 
-#define DLM_LSFL_NODIR		0x00000001
-
 /*
  * dlm_new_lockspace
  *
diff --git a/include/linux/dlm_device.h b/include/linux/dlm_device.h
index c2735ca..9642277 100644
--- a/include/linux/dlm_device.h
+++ b/include/linux/dlm_device.h
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -18,21 +18,24 @@
 #define DLM_USER_LVB_LEN	32
 
 /* Version of the device interface */
-#define DLM_DEVICE_VERSION_MAJOR 5
-#define DLM_DEVICE_VERSION_MINOR 1
+#define DLM_DEVICE_VERSION_MAJOR 6
+#define DLM_DEVICE_VERSION_MINOR 0
 #define DLM_DEVICE_VERSION_PATCH 0
 
 /* struct passed to the lock write */
 struct dlm_lock_params {
 	__u8 mode;
 	__u8 namelen;
-	__u16 flags;
+	__u16 unused;
+	__u32 flags;
 	__u32 lkid;
 	__u32 parent;
-        void __user *castparam;
+	__u64 xid;
+	__u64 timeout;
+	void __user *castparam;
 	void __user *castaddr;
 	void __user *bastparam;
-        void __user *bastaddr;
+	void __user *bastaddr;
 	struct dlm_lksb __user *lksb;
 	char lvb[DLM_USER_LVB_LEN];
 	char name[0];
@@ -62,9 +65,15 @@
 	} i;
 };
 
+struct dlm_device_version {
+	__u32 version[3];
+};
+
 /* struct read from the "device" fd,
    consists mainly of userspace pointers for the library to use */
+
 struct dlm_lock_result {
+	__u32 version[3];
 	__u32 length;
 	void __user * user_astaddr;
 	void __user * user_astparam;
@@ -83,6 +92,7 @@
 #define DLM_USER_CREATE_LOCKSPACE  4
 #define DLM_USER_REMOVE_LOCKSPACE  5
 #define DLM_USER_PURGE        6
+#define DLM_USER_DEADLOCK     7
 
 /* Arbitrary length restriction */
 #define MAX_LS_NAME_LEN 64
diff --git a/include/linux/dlm_netlink.h b/include/linux/dlm_netlink.h
new file mode 100644
index 0000000..1927633
--- /dev/null
+++ b/include/linux/dlm_netlink.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 Red Hat, Inc.  All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
+
+#ifndef _DLM_NETLINK_H
+#define _DLM_NETLINK_H
+
+enum {
+	DLM_STATUS_WAITING = 1,
+	DLM_STATUS_GRANTED = 2,
+	DLM_STATUS_CONVERT = 3,
+};
+
+#define DLM_LOCK_DATA_VERSION 1
+
+struct dlm_lock_data {
+	uint16_t version;
+	uint32_t lockspace_id;
+	int nodeid;
+	int ownpid;
+	uint32_t id;
+	uint32_t remid;
+	uint64_t xid;
+	int8_t status;
+	int8_t grmode;
+	int8_t rqmode;
+	unsigned long timestamp;
+	int resource_namelen;
+	char resource_name[DLM_RESNAME_MAXLEN];
+};
+
+enum {
+	DLM_CMD_UNSPEC = 0,
+	DLM_CMD_HELLO,		/* user->kernel */
+	DLM_CMD_TIMEOUT,	/* kernel->user */
+	__DLM_CMD_MAX,
+};
+
+#define DLM_CMD_MAX (__DLM_CMD_MAX - 1)
+
+enum {
+	DLM_TYPE_UNSPEC = 0,
+	DLM_TYPE_LOCK,
+	__DLM_TYPE_MAX,
+};
+
+#define DLM_TYPE_MAX (__DLM_TYPE_MAX - 1)
+
+#define DLM_GENL_VERSION 0x1
+#define DLM_GENL_NAME "DLM"
+
+#endif /* _DLM_NETLINK_H */
diff --git a/include/linux/eeprom_93cx6.h b/include/linux/eeprom_93cx6.h
new file mode 100644
index 0000000..d774b77
--- /dev/null
+++ b/include/linux/eeprom_93cx6.h
@@ -0,0 +1,72 @@
+/*
+	Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
+	<http://rt2x00.serialmonkey.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.
+ */
+
+/*
+	Module: eeprom_93cx6
+	Abstract: EEPROM reader datastructures for 93cx6 chipsets.
+	Supported chipsets: 93c46 & 93c66.
+ */
+
+/*
+ * EEPROM operation defines.
+ */
+#define PCI_EEPROM_WIDTH_93C46	6
+#define PCI_EEPROM_WIDTH_93C66	8
+#define PCI_EEPROM_WIDTH_OPCODE	3
+#define PCI_EEPROM_WRITE_OPCODE	0x05
+#define PCI_EEPROM_READ_OPCODE	0x06
+#define PCI_EEPROM_EWDS_OPCODE	0x10
+#define PCI_EEPROM_EWEN_OPCODE	0x13
+
+/**
+ * struct eeprom_93cx6 - control structure for setting the commands
+ * for reading the eeprom data.
+ * @data: private pointer for the driver.
+ * @register_read(struct eeprom_93cx6 *eeprom): handler to
+ * read the eeprom register, this function should set all reg_* fields.
+ * @register_write(struct eeprom_93cx6 *eeprom): handler to
+ * write to the eeprom register by using all reg_* fields.
+ * @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
+ * @reg_data_in: register field to indicate data input
+ * @reg_data_out: register field to indicate data output
+ * @reg_data_clock: register field to set the data clock
+ * @reg_chip_select: register field to set the chip select
+ *
+ * This structure is used for the communication between the driver
+ * and the eeprom_93cx6 handlers for reading the eeprom.
+ */
+struct eeprom_93cx6 {
+	void *data;
+
+	void (*register_read)(struct eeprom_93cx6 *eeprom);
+	void (*register_write)(struct eeprom_93cx6 *eeprom);
+
+	int width;
+
+	char reg_data_in;
+	char reg_data_out;
+	char reg_data_clock;
+	char reg_chip_select;
+};
+
+extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom,
+	const u8 word, u16 *data);
+extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
+	const u8 word, __le16 *data, const u16 words);
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 071c67a..6cdb973 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -39,13 +39,8 @@
 extern int		eth_header_cache(struct neighbour *neigh,
 					 struct hh_cache *hh);
 
-extern struct net_device *alloc_etherdev(int sizeof_priv);
-static inline void eth_copy_and_sum (struct sk_buff *dest, 
-				     const unsigned char *src, 
-				     int len, int base)
-{
-	memcpy (dest->data, src, len);
-}
+extern struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count);
+#define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1)
 
 /**
  * is_zero_ether_addr - Determine if give Ethernet address is all zeros.
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index efbe1fd..1a45d6f 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -30,16 +30,38 @@
 #define FW_CDEV_EVENT_REQUEST		0x02
 #define FW_CDEV_EVENT_ISO_INTERRUPT	0x03
 
-/* The 'closure' fields are for user space to use.  Data passed in the
- * 'closure' field for a request will be returned in the corresponding
- * event.  It's a 64-bit type so that it's a fixed size type big
- * enough to hold a pointer on all platforms. */
-
+/**
+ * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
+ * @closure:	For arbitrary use by userspace
+ * @type:	Discriminates the fw_cdev_event_ types
+ *
+ * This struct may be used to access generic members of all fw_cdev_event_
+ * types regardless of the specific type.
+ *
+ * Data passed in the @closure field for a request will be returned in the
+ * corresponding event.  It is big enough to hold a pointer on all platforms.
+ * The ioctl used to set @closure depends on the @type of event.
+ */
 struct fw_cdev_event_common {
 	__u64 closure;
 	__u32 type;
 };
 
+/**
+ * struct fw_cdev_event_bus_reset - Sent when a bus reset occurred
+ * @closure:	See &fw_cdev_event_common; set by %FW_CDEV_IOC_GET_INFO ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_BUS_RESET
+ * @node_id:       New node ID of this node
+ * @local_node_id: Node ID of the local node, i.e. of the controller
+ * @bm_node_id:    Node ID of the bus manager
+ * @irm_node_id:   Node ID of the iso resource manager
+ * @root_node_id:  Node ID of the root node
+ * @generation:    New bus generation
+ *
+ * This event is sent when the bus the device belongs to goes through a bus
+ * reset.  It provides information about the new bus configuration, such as
+ * new node ID for this device, new root ID, and others.
+ */
 struct fw_cdev_event_bus_reset {
 	__u64 closure;
 	__u32 type;
@@ -51,6 +73,20 @@
 	__u32 generation;
 };
 
+/**
+ * struct fw_cdev_event_response - Sent when a response packet was received
+ * @closure:	See &fw_cdev_event_common;
+ *		set by %FW_CDEV_IOC_SEND_REQUEST ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_RESPONSE
+ * @rcode:	Response code returned by the remote node
+ * @length:	Data length, i.e. the response's payload size in bytes
+ * @data:	Payload data, if any
+ *
+ * This event is sent when the stack receives a response to an outgoing request
+ * sent by %FW_CDEV_IOC_SEND_REQUEST ioctl.  The payload data for responses
+ * carrying data (read and lock responses) follows immediately and can be
+ * accessed through the @data field.
+ */
 struct fw_cdev_event_response {
 	__u64 closure;
 	__u32 type;
@@ -59,6 +95,25 @@
 	__u32 data[0];
 };
 
+/**
+ * struct fw_cdev_event_request - Sent on incoming request to an address region
+ * @closure:	See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST
+ * @tcode:	Transaction code of the incoming request
+ * @offset:	The offset into the 48-bit per-node address space
+ * @handle:	Reference to the kernel-side pending request
+ * @length:	Data length, i.e. the request's payload size in bytes
+ * @data:	Incoming data, if any
+ *
+ * This event is sent when the stack receives an incoming request to an address
+ * region registered using the %FW_CDEV_IOC_ALLOCATE ioctl.  The request is
+ * guaranteed to be completely contained in the specified region.  Userspace is
+ * responsible for sending the response by %FW_CDEV_IOC_SEND_RESPONSE ioctl,
+ * using the same @handle.
+ *
+ * The payload data for requests carrying data (write and lock requests)
+ * follows immediately and can be accessed through the @data field.
+ */
 struct fw_cdev_event_request {
 	__u64 closure;
 	__u32 type;
@@ -69,14 +124,39 @@
 	__u32 data[0];
 };
 
+/**
+ * struct fw_cdev_event_iso_interrupt - Sent when an iso packet was completed
+ * @closure:	See &fw_cdev_event_common;
+ *		set by %FW_CDEV_CREATE_ISO_CONTEXT ioctl
+ * @type:	See &fw_cdev_event_common; always %FW_CDEV_EVENT_ISO_INTERRUPT
+ * @cycle:	Cycle counter of the interrupt packet
+ * @header_length: Total length of following headers, in bytes
+ * @header:	Stripped headers, if any
+ *
+ * This event is sent when the controller has completed an &fw_cdev_iso_packet
+ * with the %FW_CDEV_ISO_INTERRUPT bit set.  In the receive case, the headers
+ * stripped of all packets up until and including the interrupt packet are
+ * returned in the @header field.
+ */
 struct fw_cdev_event_iso_interrupt {
 	__u64 closure;
 	__u32 type;
 	__u32 cycle;
-	__u32 header_length;	/* Length in bytes of following headers. */
+	__u32 header_length;
 	__u32 header[0];
 };
 
+/**
+ * union fw_cdev_event - Convenience union of fw_cdev_event_ types
+ * @common:        Valid for all types
+ * @bus_reset:     Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET
+ * @response:      Valid if @common.type == %FW_CDEV_EVENT_RESPONSE
+ * @request:       Valid if @common.type == %FW_CDEV_EVENT_REQUEST
+ * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
+ *
+ * Convenience union for userspace use.  Events could be read(2) into a char
+ * buffer and then cast to this union for further processing.
+ */
 union fw_cdev_event {
 	struct fw_cdev_event_common common;
 	struct fw_cdev_event_bus_reset bus_reset;
@@ -105,35 +185,47 @@
  */
 #define FW_CDEV_VERSION		1
 
+/**
+ * struct fw_cdev_get_info - General purpose information ioctl
+ * @version:	The version field is just a running serial number.
+ *		We never break backwards compatibility, but may add more
+ *		structs and ioctls in later revisions.
+ * @rom_length:	If @rom is non-zero, at most rom_length bytes of configuration
+ *		ROM will be copied into that user space address.  In either
+ *		case, @rom_length is updated with the actual length of the
+ *		configuration ROM.
+ * @rom:	If non-zero, address of a buffer to be filled by a copy of the
+ *		local node's configuration ROM
+ * @bus_reset:	If non-zero, address of a buffer to be filled by a
+ *		&struct fw_cdev_event_bus_reset with the current state
+ *		of the bus.  This does not cause a bus reset to happen.
+ * @bus_reset_closure: Value of &closure in this and subsequent bus reset events
+ * @card:	The index of the card this device belongs to
+ */
 struct fw_cdev_get_info {
-	/* The version field is just a running serial number.  We
-	 * never break backwards compatibility.  Userspace passes in
-	 * the version it expects and the kernel passes back the
-	 * highest version it can provide.  Even if the structs in
-	 * this interface are extended in a later version, the kernel
-	 * will not copy back more data than what was present in the
-	 * interface version userspace expects. */
 	__u32 version;
-
-	/* If non-zero, at most rom_length bytes of config rom will be
-	 * copied into that user space address.  In either case,
-	 * rom_length is updated with the actual length of the config
-	 * rom. */
 	__u32 rom_length;
 	__u64 rom;
-
-	/* If non-zero, a fw_cdev_event_bus_reset struct will be
-	 * copied here with the current state of the bus.  This does
-	 * not cause a bus reset to happen.  The value of closure in
-	 * this and sub-sequent bus reset events is set to
-	 * bus_reset_closure. */
 	__u64 bus_reset;
 	__u64 bus_reset_closure;
-
-	/* The index of the card this devices belongs to. */
 	__u32 card;
 };
 
+/**
+ * struct fw_cdev_send_request - Send an asynchronous request packet
+ * @tcode:	Transaction code of the request
+ * @length:	Length of outgoing payload, in bytes
+ * @offset:	48-bit offset at destination node
+ * @closure:	Passed back to userspace in the response event
+ * @data:	Userspace pointer to payload
+ * @generation:	The bus generation where packet is valid
+ *
+ * Send a request to the device.  This ioctl implements all outgoing requests.
+ * Both quadlet and block request specify the payload as a pointer to the data
+ * in the @data field.  Once the transaction completes, the kernel writes an
+ * &fw_cdev_event_request event back.  The @closure field is passed back to
+ * user space in the response event.
+ */
 struct fw_cdev_send_request {
 	__u32 tcode;
 	__u32 length;
@@ -143,6 +235,19 @@
 	__u32 generation;
 };
 
+/**
+ * struct fw_cdev_send_response - Send an asynchronous response packet
+ * @rcode:	Response code as determined by the userspace handler
+ * @length:	Length of outgoing payload, in bytes
+ * @data:	Userspace pointer to payload
+ * @handle:	The handle from the &fw_cdev_event_request
+ *
+ * Send a response to an incoming request.  By setting up an address range using
+ * the %FW_CDEV_IOC_ALLOCATE ioctl, userspace can listen for incoming requests.  An
+ * incoming request will generate an %FW_CDEV_EVENT_REQUEST, and userspace must
+ * send a reply using this ioctl.  The event has a handle to the kernel-side
+ * pending transaction, which should be used with this ioctl.
+ */
 struct fw_cdev_send_response {
 	__u32 rcode;
 	__u32 length;
@@ -150,6 +255,21 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_allocate - Allocate a CSR address range
+ * @offset:	Start offset of the address range
+ * @closure:	To be passed back to userspace in request events
+ * @length:	Length of the address range, in bytes
+ * @handle:	Handle to the allocation, written by the kernel
+ *
+ * Allocate an address range in the 48-bit address space on the local node
+ * (the controller).  This allows userspace to listen for requests with an
+ * offset within that address range.  When the kernel receives a request
+ * within the range, an &fw_cdev_event_request event will be written back.
+ * The @closure field is passed back to userspace in the response event.
+ * The @handle field is an out parameter, returning a handle to the allocated
+ * range to be used for later deallocation of the range.
+ */
 struct fw_cdev_allocate {
 	__u64 offset;
 	__u64 closure;
@@ -157,6 +277,11 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_deallocate - Free an address range allocation
+ * @handle:	Handle to the address range, as returned by the kernel when the
+ *		range was allocated
+ */
 struct fw_cdev_deallocate {
 	__u32 handle;
 };
@@ -164,10 +289,41 @@
 #define FW_CDEV_LONG_RESET	0
 #define FW_CDEV_SHORT_RESET	1
 
+/**
+ * struct fw_cdev_initiate_bus_reset - Initiate a bus reset
+ * @type:	%FW_CDEV_SHORT_RESET or %FW_CDEV_LONG_RESET
+ *
+ * Initiate a bus reset for the bus this device is on.  The bus reset can be
+ * either the original (long) bus reset or the arbitrated (short) bus reset
+ * introduced in 1394a-2000.
+ */
 struct fw_cdev_initiate_bus_reset {
-	__u32 type;
+	__u32 type;	/* FW_CDEV_SHORT_RESET or FW_CDEV_LONG_RESET */
 };
 
+/**
+ * struct fw_cdev_add_descriptor - Add contents to the local node's config ROM
+ * @immediate:	If non-zero, immediate key to insert before pointer
+ * @key:	Upper 8 bits of root directory pointer
+ * @data:	Userspace pointer to contents of descriptor block
+ * @length:	Length of descriptor block data, in bytes
+ * @handle:	Handle to the descriptor, written by the kernel
+ *
+ * Add a descriptor block and optionally a preceding immediate key to the local
+ * node's configuration ROM.
+ *
+ * The @key field specifies the upper 8 bits of the descriptor root directory
+ * pointer and the @data and @length fields specify the contents. The @key
+ * should be of the form 0xXX000000. The offset part of the root directory entry
+ * will be filled in by the kernel.
+ *
+ * If not 0, the @immediate field specifies an immediate key which will be
+ * inserted before the root directory pointer.
+ *
+ * If successful, the kernel adds the descriptor and writes back a handle to the
+ * kernel-side object to be used for later removal of the descriptor block and
+ * immediate key.
+ */
 struct fw_cdev_add_descriptor {
 	__u32 immediate;
 	__u32 key;
@@ -176,6 +332,14 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_remove_descriptor - Remove contents from the configuration ROM
+ * @handle:	Handle to the descriptor, as returned by the kernel when the
+ *		descriptor was added
+ *
+ * Remove a descriptor block and accompanying immediate key from the local
+ * node's configuration ROM.
+ */
 struct fw_cdev_remove_descriptor {
 	__u32 handle;
 };
@@ -183,12 +347,24 @@
 #define FW_CDEV_ISO_CONTEXT_TRANSMIT	0
 #define FW_CDEV_ISO_CONTEXT_RECEIVE	1
 
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0		 1
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1		 2
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2		 4
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3		 8
-#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS	15
-
+/**
+ * struct fw_cdev_create_iso_context - Create a context for isochronous IO
+ * @type:	%FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE
+ * @header_size: Header size to strip for receive contexts
+ * @channel:	Channel to bind to
+ * @speed:	Speed to transmit at
+ * @closure:	To be returned in &fw_cdev_event_iso_interrupt
+ * @handle:	Handle to context, written back by kernel
+ *
+ * Prior to sending or receiving isochronous I/O, a context must be created.
+ * The context records information about the transmit or receive configuration
+ * and typically maps to an underlying hardware resource.  A context is set up
+ * for either sending or receiving.  It is bound to a specific isochronous
+ * channel.
+ *
+ * If a context was successfully created, the kernel writes back a handle to the
+ * context, which must be passed in for subsequent operations on that context.
+ */
 struct fw_cdev_create_iso_context {
 	__u32 type;
 	__u32 header_size;
@@ -201,15 +377,49 @@
 #define FW_CDEV_ISO_PAYLOAD_LENGTH(v)	(v)
 #define FW_CDEV_ISO_INTERRUPT		(1 << 16)
 #define FW_CDEV_ISO_SKIP		(1 << 17)
+#define FW_CDEV_ISO_SYNC		(1 << 17)
 #define FW_CDEV_ISO_TAG(v)		((v) << 18)
 #define FW_CDEV_ISO_SY(v)		((v) << 20)
 #define FW_CDEV_ISO_HEADER_LENGTH(v)	((v) << 24)
 
+/**
+ * struct fw_cdev_iso_packet - Isochronous packet
+ * @control:	Contains the header length (8 uppermost bits), the sy field
+ *		(4 bits), the tag field (2 bits), a sync flag (1 bit),
+ *		a skip flag (1 bit), an interrupt flag (1 bit), and the
+ *		payload length (16 lowermost bits)
+ * @header:	Header and payload
+ *
+ * &struct fw_cdev_iso_packet is used to describe isochronous packet queues.
+ *
+ * Use the FW_CDEV_ISO_ macros to fill in @control.  The sy and tag fields are
+ * specified by IEEE 1394a and IEC 61883.
+ *
+ * FIXME - finish this documentation
+ */
 struct fw_cdev_iso_packet {
 	__u32 control;
 	__u32 header[0];
 };
 
+/**
+ * struct fw_cdev_queue_iso - Queue isochronous packets for I/O
+ * @packets:	Userspace pointer to packet data
+ * @data:	Pointer into mmap()'ed payload buffer
+ * @size:	Size of packet data in bytes
+ * @handle:	Isochronous context handle
+ *
+ * Queue a number of isochronous packets for reception or transmission.
+ * This ioctl takes a pointer to an array of &fw_cdev_iso_packet structs,
+ * which describe how to transmit from or receive into a contiguous region
+ * of a mmap()'ed payload buffer.  As part of the packet descriptors,
+ * a series of headers can be supplied, which will be prepended to the
+ * payload during DMA.
+ *
+ * The kernel may or may not queue all packets, but will write back updated
+ * values of the @packets, @data and @size fields, so the ioctl can be
+ * resubmitted easily.
+ */
 struct fw_cdev_queue_iso {
 	__u64 packets;
 	__u64 data;
@@ -217,6 +427,23 @@
 	__u32 handle;
 };
 
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0		 1
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1		 2
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2		 4
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3		 8
+#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS	15
+
+/**
+ * struct fw_cdev_start_iso - Start an isochronous transmission or reception
+ * @cycle:	Cycle in which to start I/O.  If @cycle is greater than or
+ *		equal to 0, the I/O will start on that cycle.
+ * @sync:	Determines the value to wait for for receive packets that have
+ *		the %FW_CDEV_ISO_SYNC bit set
+ * @tags:	Tag filter bit mask.  Only valid for isochronous reception.
+ *		Determines the tag values for which packets will be accepted.
+ *		Use FW_CDEV_ISO_CONTEXT_MATCH_ macros to set @tags.
+ * @handle:	Isochronous context handle within which to transmit or receive
+ */
 struct fw_cdev_start_iso {
 	__s32 cycle;
 	__u32 sync;
@@ -224,6 +451,10 @@
 	__u32 handle;
 };
 
+/**
+ * struct fw_cdev_stop_iso - Stop an isochronous transmission or reception
+ * @handle:	Handle of isochronous context to stop
+ */
 struct fw_cdev_stop_iso {
 	__u32 handle;
 };
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6a41f4c..4f0b3bf 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1054,7 +1054,7 @@
 };
 
 /*
- * "descriptor" for what we're up to with a read for sendfile().
+ * "descriptor" for what we're up to with a read.
  * This allows us to use the same read code yet
  * have multiple different users of the data that
  * we read from a file.
@@ -1105,7 +1105,6 @@
 	int (*aio_fsync) (struct kiocb *, int datasync);
 	int (*fasync) (int, struct file *, int);
 	int (*lock) (struct file *, int, struct file_lock *);
-	ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
 	ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
 	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 	int (*check_flags)(int);
@@ -1762,7 +1761,6 @@
 		unsigned long, loff_t, loff_t *, size_t, ssize_t);
 extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
 extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
-extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
 extern void do_generic_mapping_read(struct address_space *mapping,
 				    struct file_ra_state *, struct file *,
 				    loff_t *, read_descriptor_t *, read_actor_t);
@@ -1792,9 +1790,6 @@
 #ifdef CONFIG_FS_XIP
 extern ssize_t xip_file_read(struct file *filp, char __user *buf, size_t len,
 			     loff_t *ppos);
-extern ssize_t xip_file_sendfile(struct file *in_file, loff_t *ppos,
-				 size_t count, read_actor_t actor,
-				 void *target);
 extern int xip_file_mmap(struct file * file, struct vm_area_struct * vma);
 extern ssize_t xip_file_write(struct file *filp, const char __user *buf,
 			      size_t len, loff_t *ppos);
diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h
index 8b7e4c1..a44a6a0 100644
--- a/include/linux/gfs2_ondisk.h
+++ b/include/linux/gfs2_ondisk.h
@@ -54,18 +54,6 @@
 	__be64 no_addr;
 };
 
-struct gfs2_inum_host {
-	__u64 no_formal_ino;
-	__u64 no_addr;
-};
-
-static inline int gfs2_inum_equal(const struct gfs2_inum_host *ino1,
-				  const struct gfs2_inum_host *ino2)
-{
-	return ino1->no_formal_ino == ino2->no_formal_ino &&
-	       ino1->no_addr == ino2->no_addr;
-}
-
 /*
  * Generic metadata head structure
  * Every inplace buffer logged in the journal must start with this.
@@ -94,12 +82,6 @@
 	__be32 __pad1;		/* Was incarnation number in gfs1 */
 };
 
-struct gfs2_meta_header_host {
-	__u32 mh_magic;
-	__u32 mh_type;
-	__u32 mh_format;
-};
-
 /*
  * super-block structure
  *
@@ -139,23 +121,6 @@
 	/* In gfs1, quota and license dinodes followed */
 };
 
-struct gfs2_sb_host {
-	struct gfs2_meta_header_host sb_header;
-
-	__u32 sb_fs_format;
-	__u32 sb_multihost_format;
-
-	__u32 sb_bsize;
-	__u32 sb_bsize_shift;
-
-	struct gfs2_inum_host sb_master_dir; /* Was jindex dinode in gfs1 */
-	struct gfs2_inum_host sb_root_dir;
-
-	char sb_lockproto[GFS2_LOCKNAME_LEN];
-	char sb_locktable[GFS2_LOCKNAME_LEN];
-	/* In gfs1, quota and license dinodes followed */
-};
-
 /*
  * resource index structure
  */
@@ -173,14 +138,6 @@
 	__u8 ri_reserved[64];
 };
 
-struct gfs2_rindex_host {
-	__u64 ri_addr;	/* grp block disk address */
-	__u64 ri_data0;	/* first data location */
-	__u32 ri_length;	/* length of rgrp header in fs blocks */
-	__u32 ri_data;	/* num of data blocks in rgrp */
-	__u32 ri_bitbytes;	/* number of bytes in data bitmaps */
-};
-
 /*
  * resource group header structure
  */
@@ -212,13 +169,6 @@
 	__u8 rg_reserved[80]; /* Several fields from gfs1 now reserved */
 };
 
-struct gfs2_rgrp_host {
-	__u32 rg_flags;
-	__u32 rg_free;
-	__u32 rg_dinodes;
-	__u64 rg_igeneration;
-};
-
 /*
  * quota structure
  */
@@ -230,12 +180,6 @@
 	__u8 qu_reserved[64];
 };
 
-struct gfs2_quota_host {
-	__u64 qu_limit;
-	__u64 qu_warn;
-	__u64 qu_value;
-};
-
 /*
  * dinode structure
  */
@@ -315,29 +259,11 @@
 	struct gfs2_inum __pad4; /* Unused even in current gfs1 */
 
 	__be64 di_eattr;	/* extended attribute block number */
+	__be32 di_atime_nsec;   /* nsec portion of atime */
+	__be32 di_mtime_nsec;   /* nsec portion of mtime */
+	__be32 di_ctime_nsec;   /* nsec portion of ctime */
 
-	__u8 di_reserved[56];
-};
-
-struct gfs2_dinode_host {
-	__u64 di_size;	/* number of bytes in file */
-	__u64 di_blocks;	/* number of blocks in file */
-
-	/* This section varies from gfs1. Padding added to align with
-         * remainder of dinode
-	 */
-	__u64 di_goal_meta;	/* rgrp to alloc from next */
-	__u64 di_goal_data;	/* data block goal */
-	__u64 di_generation;	/* generation number for NFS */
-
-	__u32 di_flags;	/* GFS2_DIF_... */
-	__u16 di_height;	/* height of metadata */
-
-	/* These only apply to directories  */
-	__u16 di_depth;	/* Number of bits in the table */
-	__u32 di_entries;	/* The number of entries in the directory */
-
-	__u64 di_eattr;	/* extended attribute block number */
+	__u8 di_reserved[44];
 };
 
 /*
@@ -414,16 +340,6 @@
 	__be32 lh_hash;
 };
 
-struct gfs2_log_header_host {
-	struct gfs2_meta_header_host lh_header;
-
-	__u64 lh_sequence;	/* Sequence number of this transaction */
-	__u32 lh_flags;	/* GFS2_LOG_HEAD_... */
-	__u32 lh_tail;		/* Block number of log tail */
-	__u32 lh_blkno;
-	__u32 lh_hash;
-};
-
 /*
  * Log type descriptor
  */
@@ -464,11 +380,6 @@
 	__be64 ir_length;
 };
 
-struct gfs2_inum_range_host {
-	__u64 ir_start;
-	__u64 ir_length;
-};
-
 /*
  * Statfs change
  * Describes an change to the pool of free and allocated
@@ -481,12 +392,6 @@
 	__be64 sc_dinodes;
 };
 
-struct gfs2_statfs_change_host {
-	__u64 sc_total;
-	__u64 sc_free;
-	__u64 sc_dinodes;
-};
-
 /*
  * Quota change
  * Describes an allocation change for a particular
@@ -501,39 +406,12 @@
 	__be32 qc_id;
 };
 
-struct gfs2_quota_change_host {
-	__u64 qc_change;
-	__u32 qc_flags;	/* GFS2_QCF_... */
-	__u32 qc_id;
+struct gfs2_quota_lvb {
+        __be32 qb_magic;
+        __u32 __pad;
+        __be64 qb_limit;      /* Hard limit of # blocks to alloc */
+        __be64 qb_warn;       /* Warn user when alloc is above this # */
+        __be64 qb_value;       /* Current # blocks allocated */
 };
 
-#ifdef __KERNEL__
-/* Translation functions */
-
-extern void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf);
-extern void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf);
-extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf);
-extern void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf);
-extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf);
-extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf);
-extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf);
-extern void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf);
-struct gfs2_inode;
-extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
-extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf);
-extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf);
-extern void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf);
-extern void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf);
-extern void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf);
-extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf);
-extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf);
-extern void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf);
-
-/* Printing functions */
-
-extern void gfs2_rindex_print(const struct gfs2_rindex_host *ri);
-extern void gfs2_dinode_print(const struct gfs2_inode *ip);
-
-#endif /* __KERNEL__ */
-
 #endif /* __GFS2_ONDISK_DOT_H__ */
diff --git a/include/linux/gpio_mouse.h b/include/linux/gpio_mouse.h
new file mode 100644
index 0000000..44ed7aa
--- /dev/null
+++ b/include/linux/gpio_mouse.h
@@ -0,0 +1,61 @@
+/*
+ * Driver for simulating a mouse on GPIO lines.
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _GPIO_MOUSE_H
+#define _GPIO_MOUSE_H
+
+#define GPIO_MOUSE_POLARITY_ACT_HIGH	0x00
+#define GPIO_MOUSE_POLARITY_ACT_LOW	0x01
+
+#define GPIO_MOUSE_PIN_UP	0
+#define GPIO_MOUSE_PIN_DOWN	1
+#define GPIO_MOUSE_PIN_LEFT	2
+#define GPIO_MOUSE_PIN_RIGHT	3
+#define GPIO_MOUSE_PIN_BLEFT	4
+#define GPIO_MOUSE_PIN_BMIDDLE	5
+#define GPIO_MOUSE_PIN_BRIGHT	6
+#define GPIO_MOUSE_PIN_MAX	7
+
+/**
+ * struct gpio_mouse_platform_data
+ * @scan_ms: integer in ms specifying the scan periode.
+ * @polarity: Pin polarity, active high or low.
+ * @up: GPIO line for up value.
+ * @down: GPIO line for down value.
+ * @left: GPIO line for left value.
+ * @right: GPIO line for right value.
+ * @bleft: GPIO line for left button.
+ * @bmiddle: GPIO line for middle button.
+ * @bright: GPIO line for right button.
+ *
+ * This struct must be added to the platform_device in the board code.
+ * It is used by the gpio_mouse driver to setup GPIO lines and to
+ * calculate mouse movement.
+ */
+struct gpio_mouse_platform_data {
+	int scan_ms;
+	int polarity;
+
+	union {
+		struct {
+			int up;
+			int down;
+			int left;
+			int right;
+
+			int bleft;
+			int bmiddle;
+			int bright;
+		};
+		int pins[GPIO_MOUSE_PIN_MAX];
+	};
+};
+
+#endif /* _GPIO_MOUSE_H */
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 7803014..8d30229 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -79,6 +79,19 @@
 #endif
 
 #ifdef CONFIG_PREEMPT
+# define PREEMPT_CHECK_OFFSET 1
+#else
+# define PREEMPT_CHECK_OFFSET 0
+#endif
+
+/*
+ * Check whether we were atomic before we did preempt_disable():
+ * (used by the scheduler)
+ */
+#define in_atomic_preempt_off() \
+		((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_CHECK_OFFSET)
+
+#ifdef CONFIG_PREEMPT
 # define preemptible()	(preempt_count() == 0 && !irqs_disabled())
 # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 827ee74..898103b 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -263,19 +263,28 @@
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_5		0x00000100
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON		0x00000200
 #define HID_QUIRK_MIGHTYMOUSE			0x00000400
-#define HID_QUIRK_CYMOTION			0x00000800
-#define HID_QUIRK_POWERBOOK_HAS_FN		0x00001000
-#define HID_QUIRK_POWERBOOK_FN_ON		0x00002000
-#define HID_QUIRK_INVERT_HWHEEL			0x00004000
-#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD        0x00008000
-#define HID_QUIRK_BAD_RELATIVE_KEYS		0x00010000
-#define HID_QUIRK_SKIP_OUTPUT_REPORTS		0x00020000
-#define HID_QUIRK_IGNORE_MOUSE			0x00040000
-#define HID_QUIRK_SONY_PS3_CONTROLLER		0x00080000
-#define HID_QUIRK_LOGITECH_DESCRIPTOR		0x00100000
-#define HID_QUIRK_DUPLICATE_USAGES		0x00200000
-#define HID_QUIRK_RESET_LEDS			0x00400000
-#define HID_QUIRK_SWAPPED_MIN_MAX		0x00800000
+#define HID_QUIRK_POWERBOOK_HAS_FN		0x00000800
+#define HID_QUIRK_POWERBOOK_FN_ON		0x00001000
+#define HID_QUIRK_INVERT_HWHEEL			0x00002000
+#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD        0x00004000
+#define HID_QUIRK_BAD_RELATIVE_KEYS		0x00008000
+#define HID_QUIRK_SKIP_OUTPUT_REPORTS		0x00010000
+#define HID_QUIRK_IGNORE_MOUSE			0x00020000
+#define HID_QUIRK_SONY_PS3_CONTROLLER		0x00040000
+#define HID_QUIRK_DUPLICATE_USAGES		0x00080000
+#define HID_QUIRK_RESET_LEDS			0x00100000
+#define HID_QUIRK_HIDINPUT			0x00200000
+#define HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL	0x00400000
+#define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP	0x00800000
+
+/*
+ * Separate quirks for runtime report descriptor fixup
+ */
+
+#define HID_QUIRK_RDESC_CYMOTION		0x00000001
+#define HID_QUIRK_RDESC_LOGITECH		0x00000002
+#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX		0x00000004
+#define HID_QUIRK_RDESC_PETALYNX		0x00000008
 
 /*
  * This is the global environment of the parser. This information is
@@ -488,6 +497,11 @@
 #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
 
 /* HID core API */
+
+#ifdef CONFIG_HID_DEBUG
+extern int hid_debug;
+#endif
+
 extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
 extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
 extern int hidinput_connect(struct hid_device *);
@@ -506,6 +520,7 @@
 int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, const u32 quirks);
 int usbhid_quirks_init(char **quirks_param);
 void usbhid_quirks_exit(void);
+void usbhid_fixup_report_descriptor(const u16, const u16, char *, unsigned, char **);
 
 #ifdef CONFIG_HID_FF
 int hid_ff_init(struct hid_device *hid);
@@ -523,14 +538,19 @@
 #else
 static inline int hid_ff_init(struct hid_device *hid) { return -1; }
 #endif
-#ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
-		__FILE__ , ## arg)
+
+#ifdef CONFIG_HID_DEBUG
+#define dbg_hid(format, arg...) if (hid_debug) \
+				printk(KERN_DEBUG "%s: " format ,\
+				__FILE__ , ## arg)
+#define dbg_hid_line(format, arg...) if (hid_debug) \
+				printk(format, ## arg)
 #else
-#define dbg(format, arg...) do {} while (0)
+#define dbg_hid(format, arg...) do {} while (0)
+#define dbg_hid_line dbg_hid
 #endif
 
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
+#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
 		__FILE__ , ## arg)
 #endif
 
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 1e365ac..19ab258 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -25,6 +25,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/semaphore.h>
+#include <asm/mutex.h>
 
 /******************************************************************************
  * IDE driver configuration options (play with these as desired):
@@ -685,6 +686,8 @@
 	u8 mwdma_mask;
 	u8 swdma_mask;
 
+	u8 cbl;		/* cable type */
+
 	hwif_chipset_t chipset;	/* sub-module for tuning.. */
 
 	struct pci_dev  *pci_dev;	/* for pci chipsets */
@@ -735,8 +738,8 @@
 	void (*ide_dma_clear_irq)(ide_drive_t *drive);
 	void (*dma_host_on)(ide_drive_t *drive);
 	void (*dma_host_off)(ide_drive_t *drive);
-	int (*ide_dma_lostirq)(ide_drive_t *drive);
-	int (*ide_dma_timeout)(ide_drive_t *drive);
+	void (*dma_lost_irq)(ide_drive_t *drive);
+	void (*dma_timeout)(ide_drive_t *drive);
 
 	void (*OUTB)(u8 addr, unsigned long port);
 	void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port);
@@ -791,7 +794,6 @@
 	unsigned	sharing_irq: 1;	/* 1 = sharing irq with another hwif */
 	unsigned	reset      : 1;	/* reset after probe */
 	unsigned	autodma    : 1;	/* auto-attempt using DMA at boot */
-	unsigned	udma_four  : 1;	/* 1=ATA-66 capable, 0=default */
 	unsigned	no_lba48   : 1; /* 1 = cannot do LBA48 */
 	unsigned	no_lba48_dma : 1; /* 1 = cannot do LBA48 DMA */
 	unsigned	auto_poll  : 1; /* supports nop auto-poll */
@@ -863,7 +865,7 @@
 
 typedef struct ide_driver_s ide_driver_t;
 
-extern struct semaphore ide_setting_sem;
+extern struct mutex ide_setting_mtx;
 
 int set_io_32bit(ide_drive_t *, int);
 int set_pio_mode(ide_drive_t *, int);
@@ -1304,8 +1306,8 @@
 extern int ide_dma_setup(ide_drive_t *);
 extern void ide_dma_start(ide_drive_t *);
 extern int __ide_dma_end(ide_drive_t *);
-extern int __ide_dma_lostirq(ide_drive_t *);
-extern int __ide_dma_timeout(ide_drive_t *);
+extern void ide_dma_lost_irq(ide_drive_t *);
+extern void ide_dma_timeout(ide_drive_t *);
 #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
 
 #else
@@ -1382,11 +1384,11 @@
 
 
 extern spinlock_t ide_lock;
-extern struct semaphore ide_cfg_sem;
+extern struct mutex ide_cfg_mtx;
 /*
  * Structure locking:
  *
- * ide_cfg_sem and ide_lock together protect changes to
+ * ide_cfg_mtx and ide_lock together protect changes to
  * ide_hwif_t->{next,hwgroup}
  * ide_drive_t->next
  *
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 604c243..422084d 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -76,6 +76,8 @@
 #define IFLA_WEIGHT IFLA_WEIGHT
 	IFLA_OPERSTATE,
 	IFLA_LINKMODE,
+	IFLA_LINKINFO,
+#define IFLA_LINKINFO IFLA_LINKINFO
 	__IFLA_MAX
 };
 
@@ -140,4 +142,49 @@
 	__u32	retrans_time;
 };
 
+enum
+{
+	IFLA_INFO_UNSPEC,
+	IFLA_INFO_KIND,
+	IFLA_INFO_DATA,
+	IFLA_INFO_XSTATS,
+	__IFLA_INFO_MAX,
+};
+
+#define IFLA_INFO_MAX	(__IFLA_INFO_MAX - 1)
+
+/* VLAN section */
+
+enum
+{
+	IFLA_VLAN_UNSPEC,
+	IFLA_VLAN_ID,
+	IFLA_VLAN_FLAGS,
+	IFLA_VLAN_EGRESS_QOS,
+	IFLA_VLAN_INGRESS_QOS,
+	__IFLA_VLAN_MAX,
+};
+
+#define IFLA_VLAN_MAX	(__IFLA_VLAN_MAX - 1)
+
+struct ifla_vlan_flags {
+	__u32	flags;
+	__u32	mask;
+};
+
+enum
+{
+	IFLA_VLAN_QOS_UNSPEC,
+	IFLA_VLAN_QOS_MAPPING,
+	__IFLA_VLAN_QOS_MAX
+};
+
+#define IFLA_VLAN_QOS_MAX	(__IFLA_VLAN_QOS_MAX - 1)
+
+struct ifla_vlan_qos_mapping
+{
+	__u32 from;
+	__u32 to;
+};
+
 #endif /* _LINUX_IF_LINK_H */
diff --git a/include/linux/if_ppp.h b/include/linux/if_ppp.h
index 768372f..0f2f70d 100644
--- a/include/linux/if_ppp.h
+++ b/include/linux/if_ppp.h
@@ -110,6 +110,21 @@
 	struct ppp_comp_stats stats;
 };
 
+/* For PPPIOCGL2TPSTATS */
+struct pppol2tp_ioc_stats {
+	__u16		tunnel_id;	/* redundant */
+	__u16		session_id;	/* if zero, get tunnel stats */
+	__u32		using_ipsec:1;	/* valid only for session_id == 0 */
+	aligned_u64	tx_packets;
+	aligned_u64	tx_bytes;
+	aligned_u64	tx_errors;
+	aligned_u64	rx_packets;
+	aligned_u64	rx_bytes;
+	aligned_u64	rx_seq_discards;
+	aligned_u64	rx_oos_packets;
+	aligned_u64	rx_errors;
+};
+
 #define ifr__name       b.ifr_ifrn.ifrn_name
 #define stats_ptr       b.ifr_ifru.ifru_data
 
@@ -146,6 +161,7 @@
 #define PPPIOCDISCONN	_IO('t', 57)		/* disconnect channel */
 #define PPPIOCATTCHAN	_IOW('t', 56, int)	/* attach to ppp channel */
 #define PPPIOCGCHAN	_IOR('t', 55, int)	/* get ppp channel number */
+#define PPPIOCGL2TPSTATS _IOR('t', 54, struct pppol2tp_ioc_stats)
 
 #define SIOCGPPPSTATS   (SIOCDEVPRIVATE + 0)
 #define SIOCGPPPVER     (SIOCDEVPRIVATE + 1)	/* NEVER change this!! */
diff --git a/include/linux/if_pppol2tp.h b/include/linux/if_pppol2tp.h
new file mode 100644
index 0000000..516203b
--- /dev/null
+++ b/include/linux/if_pppol2tp.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * Linux PPP over L2TP (PPPoL2TP) Socket Implementation (RFC 2661)
+ *
+ * This file supplies definitions required by the PPP over L2TP driver
+ * (pppol2tp.c).  All version information wrt this file is located in pppol2tp.c
+ *
+ * License:
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef __LINUX_IF_PPPOL2TP_H
+#define __LINUX_IF_PPPOL2TP_H
+
+#include <asm/types.h>
+
+#ifdef __KERNEL__
+#include <linux/in.h>
+#endif
+
+/* Structure used to connect() the socket to a particular tunnel UDP
+ * socket.
+ */
+struct pppol2tp_addr
+{
+	pid_t	pid;			/* pid that owns the fd.
+					 * 0 => current */
+	int	fd;			/* FD of UDP socket to use */
+
+	struct sockaddr_in addr;	/* IP address and port to send to */
+
+	__be16 s_tunnel, s_session;	/* For matching incoming packets */
+	__be16 d_tunnel, d_session;	/* For sending outgoing packets */
+};
+
+/* Socket options:
+ * DEBUG	- bitmask of debug message categories
+ * SENDSEQ	- 0 => don't send packets with sequence numbers
+ *		  1 => send packets with sequence numbers
+ * RECVSEQ	- 0 => receive packet sequence numbers are optional
+ *		  1 => drop receive packets without sequence numbers
+ * LNSMODE	- 0 => act as LAC.
+ *		  1 => act as LNS.
+ * REORDERTO	- reorder timeout (in millisecs). If 0, don't try to reorder.
+ */
+enum {
+	PPPOL2TP_SO_DEBUG	= 1,
+	PPPOL2TP_SO_RECVSEQ	= 2,
+	PPPOL2TP_SO_SENDSEQ	= 3,
+	PPPOL2TP_SO_LNSMODE	= 4,
+	PPPOL2TP_SO_REORDERTO	= 5,
+};
+
+/* Debug message categories for the DEBUG socket option */
+enum {
+	PPPOL2TP_MSG_DEBUG	= (1 << 0),	/* verbose debug (if
+						 * compiled in) */
+	PPPOL2TP_MSG_CONTROL	= (1 << 1),	/* userspace - kernel
+						 * interface */
+	PPPOL2TP_MSG_SEQ	= (1 << 2),	/* sequence numbers */
+	PPPOL2TP_MSG_DATA	= (1 << 3),	/* data packets */
+};
+
+
+
+#endif
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index 6f987be..2565254 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -27,6 +27,7 @@
 #include <asm/semaphore.h>
 #include <linux/ppp_channel.h>
 #endif /* __KERNEL__ */
+#include <linux/if_pppol2tp.h>
 
 /* For user-space programs to pick up these definitions
  * which they wouldn't get otherwise without defining __KERNEL__
@@ -50,8 +51,9 @@
  * Protocols supported by AF_PPPOX 
  */ 
 #define PX_PROTO_OE    0 /* Currently just PPPoE */
-#define PX_MAX_PROTO   1	
- 
+#define PX_PROTO_OL2TP 1 /* Now L2TP also */
+#define PX_MAX_PROTO   2
+
 struct sockaddr_pppox { 
        sa_family_t     sa_family;            /* address family, AF_PPPOX */ 
        unsigned int    sa_protocol;          /* protocol identifier */ 
@@ -60,6 +62,16 @@
        }sa_addr; 
 }__attribute__ ((packed)); 
 
+/* The use of the above union isn't viable because the size of this
+ * struct must stay fixed over time -- applications use sizeof(struct
+ * sockaddr_pppox) to fill it. We use a protocol specific sockaddr
+ * type instead.
+ */
+struct sockaddr_pppol2tp {
+	sa_family_t     sa_family;      /* address family, AF_PPPOX */
+	unsigned int    sa_protocol;    /* protocol identifier */
+	struct pppol2tp_addr pppol2tp;
+}__attribute__ ((packed));
 
 /*********************************************************************
  *
diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
index 88aef7b..42eb694 100644
--- a/include/linux/if_tun.h
+++ b/include/linux/if_tun.h
@@ -36,6 +36,7 @@
 	unsigned long 		flags;
 	int			attached;
 	uid_t			owner;
+	gid_t			group;
 
 	wait_queue_head_t	read_wait;
 	struct sk_buff_head	readq;
@@ -78,6 +79,7 @@
 #define TUNSETPERSIST _IOW('T', 203, int) 
 #define TUNSETOWNER   _IOW('T', 204, int)
 #define TUNSETLINK    _IOW('T', 205, int)
+#define TUNSETGROUP   _IOW('T', 206, int)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN		0x0001
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 81e9bc9..c791287 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -99,7 +99,7 @@
 }
 
 struct vlan_priority_tci_mapping {
-	unsigned long priority;
+	u32 priority;
 	unsigned short vlan_qos; /* This should be shifted when first set, so we only do it
 				  * at provisioning time.
 				  * ((skb->priority << 13) & 0xE000)
@@ -112,7 +112,10 @@
 	/** This will be the mapping that correlates skb->priority to
 	 * 3 bits of VLAN QOS tags...
 	 */
-	unsigned long ingress_priority_map[8];
+	unsigned int nr_ingress_mappings;
+	u32 ingress_priority_map[8];
+
+	unsigned int nr_egress_mappings;
 	struct vlan_priority_tci_mapping *egress_priority_map[16]; /* hash table */
 
 	unsigned short vlan_id;        /*  The VLAN Identifier for this interface. */
@@ -395,6 +398,10 @@
 	GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
 };
 
+enum vlan_flags {
+	VLAN_FLAG_REORDER_HDR	= 0x1,
+};
+
 enum vlan_name_types {
 	VLAN_NAME_TYPE_PLUS_VID, /* Name will look like:  vlan0005 */
 	VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like:  eth1.0005 */
diff --git a/include/linux/input.h b/include/linux/input.h
index d8521c7..18c98b5 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -981,15 +981,15 @@
 	struct mutex mutex;	/* serializes open and close operations */
 	unsigned int users;
 
-	struct class_device cdev;
+	struct device dev;
 	union {			/* temporarily so while we switching to struct device */
-		struct device *parent;
-	} dev;
+		struct device *dev;
+	} cdev;
 
 	struct list_head	h_list;
 	struct list_head	node;
 };
-#define to_input_dev(d) container_of(d, struct input_dev, cdev)
+#define to_input_dev(d) container_of(d, struct input_dev, dev)
 
 /*
  * Verify that we are in sync with input_device_id mod_devicetable.h #defines
@@ -1096,22 +1096,22 @@
 	struct list_head	h_node;
 };
 
-#define to_dev(n) container_of(n,struct input_dev,node)
-#define to_handler(n) container_of(n,struct input_handler,node)
-#define to_handle(n) container_of(n,struct input_handle,d_node)
-#define to_handle_h(n) container_of(n,struct input_handle,h_node)
+#define to_dev(n) container_of(n, struct input_dev, node)
+#define to_handler(n) container_of(n, struct input_handler, node)
+#define to_handle(n) container_of(n, struct input_handle, d_node)
+#define to_handle_h(n) container_of(n, struct input_handle, h_node)
 
 struct input_dev *input_allocate_device(void);
 void input_free_device(struct input_dev *dev);
 
 static inline struct input_dev *input_get_device(struct input_dev *dev)
 {
-	return to_input_dev(class_device_get(&dev->cdev));
+	return to_input_dev(get_device(&dev->dev));
 }
 
 static inline void input_put_device(struct input_dev *dev)
 {
-	class_device_put(&dev->cdev);
+	put_device(&dev->dev);
 }
 
 static inline void *input_get_drvdata(struct input_dev *dev)
diff --git a/include/linux/ioprio.h b/include/linux/ioprio.h
index 8e2042b..2eaa142 100644
--- a/include/linux/ioprio.h
+++ b/include/linux/ioprio.h
@@ -47,8 +47,10 @@
 #define IOPRIO_NORM	(4)
 static inline int task_ioprio(struct task_struct *task)
 {
-	WARN_ON(!ioprio_valid(task->ioprio));
-	return IOPRIO_PRIO_DATA(task->ioprio);
+	if (ioprio_valid(task->ioprio))
+		return IOPRIO_PRIO_DATA(task->ioprio);
+
+	return IOPRIO_NORM;
 }
 
 static inline int task_nice_ioprio(struct task_struct *task)
diff --git a/include/linux/ip_mp_alg.h b/include/linux/ip_mp_alg.h
deleted file mode 100644
index e234e20..0000000
--- a/include/linux/ip_mp_alg.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values.
- *
- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
- */
-
-#ifndef _LINUX_IP_MP_ALG_H
-#define _LINUX_IP_MP_ALG_H
-
-enum ip_mp_alg {
-	IP_MP_ALG_NONE,
-	IP_MP_ALG_RR,
-	IP_MP_ALG_DRR,
-	IP_MP_ALG_RANDOM,
-	IP_MP_ALG_WRANDOM,
-	__IP_MP_ALG_MAX
-};
-
-#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1)
-
-#endif /* _LINUX_IP_MP_ALG_H */
-
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 648bd1f..97983dc9 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -27,8 +27,8 @@
 	int		ifr6_ifindex; 
 };
 
-#define IPV6_SRCRT_STRICT	0x01	/* this hop must be a neighbor	*/
-#define IPV6_SRCRT_TYPE_0	0	/* IPv6 type 0 Routing Header	*/
+#define IPV6_SRCRT_STRICT	0x01	/* Deprecated; will be removed */
+#define IPV6_SRCRT_TYPE_0	0	/* Deprecated; will be removed */
 #define IPV6_SRCRT_TYPE_2	2	/* IPv6 type 2 Routing Header	*/
 
 /*
@@ -247,7 +247,7 @@
 	__u16			lastopt;
 	__u32			nhoff;
 	__u16			flags;
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	__u16			dsthao;
 #endif
 
@@ -299,8 +299,8 @@
 	/* pktoption flags */
 	union {
 		struct {
-			__u16	srcrt:2,
-				osrcrt:2,
+			__u16	srcrt:1,
+				osrcrt:1,
 			        rxinfo:1,
 			        rxoinfo:1,
 				rxhlim:1,
diff --git a/include/linux/irda.h b/include/linux/irda.h
index 945ba31..8e37357 100644
--- a/include/linux/irda.h
+++ b/include/linux/irda.h
@@ -216,6 +216,34 @@
 #define ifr_dtr       ifr_ifru.ifru_line.dtr
 #define ifr_rts       ifr_ifru.ifru_line.rts
 
+
+/* IrDA netlink definitions */
+#define IRDA_NL_NAME "irda"
+#define IRDA_NL_VERSION 1
+
+enum irda_nl_commands {
+	IRDA_NL_CMD_UNSPEC,
+	IRDA_NL_CMD_SET_MODE,
+	IRDA_NL_CMD_GET_MODE,
+
+	__IRDA_NL_CMD_AFTER_LAST
+};
+#define IRDA_NL_CMD_MAX (__IRDA_NL_CMD_AFTER_LAST - 1)
+
+enum nl80211_attrs {
+	IRDA_NL_ATTR_UNSPEC,
+	IRDA_NL_ATTR_IFNAME,
+	IRDA_NL_ATTR_MODE,
+
+	__IRDA_NL_ATTR_AFTER_LAST
+};
+#define IRDA_NL_ATTR_MAX (__IRDA_NL_ATTR_AFTER_LAST - 1)
+
+/* IrDA modes */
+#define IRDA_MODE_PRIMARY   0x1
+#define IRDA_MODE_SECONDARY 0x2
+#define IRDA_MODE_MONITOR   0x4
+
 #endif /* KERNEL_IRDA_H */
 
 
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 2b139f6..dae7143 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -279,6 +279,16 @@
 	return (s64) tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
 }
 
+static inline s64 ktime_us_delta(const ktime_t later, const ktime_t earlier)
+{
+       return ktime_to_us(ktime_sub(later, earlier));
+}
+
+static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec)
+{
+	return ktime_add_ns(kt, usec * 1000);
+}
+
 /*
  * The resolution of the clocks. The resolution value is returned in
  * the clock_getres() system call to give application programmers an
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 620da7b..a3df646 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -116,6 +116,7 @@
 enum {
 	/* various global constants */
 	LIBATA_MAX_PRD		= ATA_MAX_PRD / 2,
+	LIBATA_DUMB_MAX_PRD	= ATA_MAX_PRD / 4,	/* Worst case */
 	ATA_MAX_PORTS		= 8,
 	ATA_DEF_QUEUE		= 1,
 	/* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
@@ -136,6 +137,8 @@
 	ATA_DFLAG_CDB_INTR	= (1 << 2), /* device asserts INTRQ when ready for CDB */
 	ATA_DFLAG_NCQ		= (1 << 3), /* device supports NCQ */
 	ATA_DFLAG_FLUSH_EXT	= (1 << 4), /* do FLUSH_EXT instead of FLUSH */
+	ATA_DFLAG_ACPI_PENDING	= (1 << 5), /* ACPI resume action pending */
+	ATA_DFLAG_ACPI_FAILED	= (1 << 6), /* ACPI on devcfg has failed */
 	ATA_DFLAG_CFG_MASK	= (1 << 8) - 1,
 
 	ATA_DFLAG_PIO		= (1 << 8), /* device limited to PIO mode */
@@ -196,6 +199,7 @@
 	ATA_PFLAG_FLUSH_PORT_TASK = (1 << 16), /* flush port task */
 	ATA_PFLAG_SUSPENDED	= (1 << 17), /* port is suspended (power) */
 	ATA_PFLAG_PM_PENDING	= (1 << 18), /* PM operation pending */
+	ATA_PFLAG_GTM_VALID	= (1 << 19), /* acpi_gtm data valid */
 
 	/* struct ata_queued_cmd flags */
 	ATA_QCFLAG_ACTIVE	= (1 << 0), /* cmd not yet ack'd to scsi lyer */
@@ -363,6 +367,9 @@
 	void			*private_data;
 	const struct ata_port_operations *ops;
 	unsigned long		flags;
+#ifdef CONFIG_ATA_ACPI
+	acpi_handle		acpi_handle;
+#endif
 	struct ata_port		*simplex_claimed;	/* channel owning the DMA */
 	struct ata_port		*ports[0];
 };
@@ -429,6 +436,9 @@
 	unsigned int		devno;		/* 0 or 1 */
 	unsigned long		flags;		/* ATA_DFLAG_xxx */
 	struct scsi_device	*sdev;		/* attached SCSI device */
+#ifdef CONFIG_ATA_ACPI
+	acpi_handle		acpi_handle;
+#endif
 	/* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */
 	u64			n_sectors;	/* size of device, if ATA */
 	unsigned int		class;		/* ATA_DEV_xxx */
@@ -457,10 +467,6 @@
 	struct ata_ering	ering;
 	int			spdn_cnt;
 	unsigned int		horkage;	/* List of broken features */
-#ifdef CONFIG_ATA_ACPI
-	/* ACPI objects info */
-	acpi_handle obj_handle;
-#endif
 };
 
 /* Offset into struct ata_device.  Fields above it are maintained
@@ -489,6 +495,17 @@
 	unsigned int		did_probe_mask;
 };
 
+struct ata_acpi_drive
+{
+	u32 pio;
+	u32 dma;
+} __packed;
+
+struct ata_acpi_gtm {
+	struct ata_acpi_drive drive[2];
+	u32 flags;
+} __packed;
+
 struct ata_port {
 	struct Scsi_Host	*scsi_host; /* our co-allocated scsi host */
 	const struct ata_port_operations *ops;
@@ -549,6 +566,10 @@
 
 	void			*private_data;
 
+#ifdef CONFIG_ATA_ACPI
+	acpi_handle		acpi_handle;
+	struct ata_acpi_gtm	acpi_gtm;
+#endif
 	u8			sector_buf[ATA_SECT_SIZE]; /* owned by EH */
 };
 
@@ -758,6 +779,7 @@
 			  unsigned int buflen, int write_data);
 extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
 				unsigned int buflen, int write_data);
+extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
 extern void ata_qc_prep(struct ata_queued_cmd *qc);
 extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
 extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
diff --git a/include/linux/lzo.h b/include/linux/lzo.h
new file mode 100644
index 0000000..582d8b7
--- /dev/null
+++ b/include/linux/lzo.h
@@ -0,0 +1,44 @@
+#ifndef __LZO_H__
+#define __LZO_H__
+/*
+ *  LZO Public Kernel Interface
+ *  A mini subset of the LZO real-time data compression library
+ *
+ *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ *  The full LZO package can be found at:
+ *  http://www.oberhumer.com/opensource/lzo/
+ *
+ *  Changed for kernel use by:
+ *  Nitin Gupta <nitingupta910@gmail.com>
+ *  Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#define LZO1X_MEM_COMPRESS	(16384 * sizeof(unsigned char *))
+#define LZO1X_1_MEM_COMPRESS	LZO1X_MEM_COMPRESS
+
+#define lzo1x_worst_compress(x) (x + (x / 64) + 16 + 3)
+
+/* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */
+int lzo1x_1_compress(const unsigned char *src, size_t src_len,
+			unsigned char *dst, size_t *dst_len, void *wrkmem);
+
+/* safe decompression with overrun testing */
+int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
+			unsigned char *dst, size_t *dst_len);
+
+/*
+ * Return values (< 0 = Error)
+ */
+#define LZO_E_OK			0
+#define LZO_E_ERROR			(-1)
+#define LZO_E_OUT_OF_MEMORY		(-2)
+#define LZO_E_NOT_COMPRESSIBLE		(-3)
+#define LZO_E_INPUT_OVERRUN		(-4)
+#define LZO_E_OUTPUT_OVERRUN		(-5)
+#define LZO_E_LOOKBEHIND_OVERRUN	(-6)
+#define LZO_E_EOF_NOT_FOUND		(-7)
+#define LZO_E_INPUT_NOT_CONSUMED	(-8)
+#define LZO_E_NOT_YET_IMPLEMENTED	(-9)
+
+#endif
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
index c6d4ab8..b021b3a 100644
--- a/include/linux/mv643xx.h
+++ b/include/linux/mv643xx.h
@@ -13,10 +13,6 @@
 #ifndef __ASM_MV643XX_H
 #define __ASM_MV643XX_H
 
-#ifdef __mips__
-#include <asm/addrspace.h>
-#include <asm/marvell.h>
-#endif
 #include <asm/types.h>
 
 /****************************************/
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3a70f55..79cc3da 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -108,6 +108,14 @@
 #define MAX_HEADER (LL_MAX_HEADER + 48)
 #endif
 
+struct net_device_subqueue
+{
+	/* Give a control state for each queue.  This struct may contain
+	 * per-queue locks in the future.
+	 */
+	unsigned long   state;
+};
+
 /*
  *	Network device statistics. Akin to the 2.0 ether stats but
  *	with byte counters.
@@ -177,19 +185,24 @@
 
 DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat);
 
+struct dev_addr_list
+{
+	struct dev_addr_list	*next;
+	u8			da_addr[MAX_ADDR_LEN];
+	u8			da_addrlen;
+	int			da_users;
+	int			da_gusers;
+};
 
 /*
  *	We tag multicasts with these structures.
  */
- 
-struct dev_mc_list
-{	
-	struct dev_mc_list	*next;
-	__u8			dmi_addr[MAX_ADDR_LEN];
-	unsigned char		dmi_addrlen;
-	int			dmi_users;
-	int			dmi_gusers;
-};
+
+#define dev_mc_list	dev_addr_list
+#define dmi_addr	da_addr
+#define dmi_addrlen	da_addrlen
+#define dmi_users	da_users
+#define dmi_gusers	da_gusers
 
 struct hh_cache
 {
@@ -248,6 +261,8 @@
 	__LINK_STATE_LINKWATCH_PENDING,
 	__LINK_STATE_DORMANT,
 	__LINK_STATE_QDISC_RUNNING,
+	/* Set by the netpoll NAPI code */
+	__LINK_STATE_POLL_LIST_FROZEN,
 };
 
 
@@ -314,9 +329,10 @@
 	/* 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_IP_CSUM		2	/* Can checksum 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_IPV6_CSUM	16	/* Can checksum TCP/UDP over IPV6 */
 #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 */
@@ -325,6 +341,7 @@
 #define NETIF_F_VLAN_CHALLENGED	1024	/* Device cannot handle VLAN packets */
 #define NETIF_F_GSO		2048	/* Enable software GSO. */
 #define NETIF_F_LLTX		4096	/* LockLess TX */
+#define NETIF_F_MULTI_QUEUE	16384	/* Has multiple TX/RX queues */
 
 	/* Segmentation offload features */
 #define NETIF_F_GSO_SHIFT	16
@@ -338,8 +355,11 @@
 	/* List of features with software fallbacks. */
 #define NETIF_F_GSO_SOFTWARE	(NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
 
+
 #define NETIF_F_GEN_CSUM	(NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
-#define NETIF_F_ALL_CSUM	(NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
+#define NETIF_F_V4_CSUM		(NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
+#define NETIF_F_V6_CSUM		(NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
+#define NETIF_F_ALL_CSUM	(NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)
 
 	struct net_device	*next_sched;
 
@@ -388,7 +408,10 @@
 	unsigned char		addr_len;	/* hardware address length	*/
 	unsigned short          dev_id;		/* for shared network cards */
 
-	struct dev_mc_list	*mc_list;	/* Multicast mac addresses	*/
+	struct dev_addr_list	*uc_list;	/* Secondary unicast mac addresses */
+	int			uc_count;	/* Number of installed ucasts	*/
+	int			uc_promisc;
+	struct dev_addr_list	*mc_list;	/* Multicast mac addresses	*/
 	int			mc_count;	/* Number of installed mcasts	*/
 	int			promiscuity;
 	int			allmulti;
@@ -493,6 +516,8 @@
 						void *saddr,
 						unsigned len);
 	int			(*rebuild_header)(struct sk_buff *skb);
+#define HAVE_SET_RX_MODE
+	void			(*set_rx_mode)(struct net_device *dev);
 #define HAVE_MULTICAST			 
 	void			(*set_multicast_list)(struct net_device *dev);
 #define HAVE_SET_MAC_ADDR  		 
@@ -540,17 +565,22 @@
 	struct device		dev;
 	/* space for optional statistics and wireless sysfs groups */
 	struct attribute_group  *sysfs_groups[3];
+
+	/* rtnetlink link ops */
+	const struct rtnl_link_ops *rtnl_link_ops;
+
+	/* The TX queue control structures */
+	unsigned int			egress_subqueue_count;
+	struct net_device_subqueue	egress_subqueue[0];
 };
 #define to_net_dev(d) container_of(d, struct net_device, dev)
 
 #define	NETDEV_ALIGN		32
 #define	NETDEV_ALIGN_CONST	(NETDEV_ALIGN - 1)
 
-static inline void *netdev_priv(struct net_device *dev)
+static inline void *netdev_priv(const struct net_device *dev)
 {
-	return (char *)dev + ((sizeof(struct net_device)
-					+ NETDEV_ALIGN_CONST)
-				& ~NETDEV_ALIGN_CONST);
+	return dev->priv;
 }
 
 #define SET_MODULE_OWNER(dev) do { } while (0)
@@ -702,6 +732,62 @@
 	return test_bit(__LINK_STATE_START, &dev->state);
 }
 
+/*
+ * Routines to manage the subqueues on a device.  We only need start
+ * stop, and a check if it's stopped.  All other device management is
+ * done at the overall netdevice level.
+ * Also test the device if we're multiqueue.
+ */
+static inline void netif_start_subqueue(struct net_device *dev, u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	clear_bit(__LINK_STATE_XOFF, &dev->egress_subqueue[queue_index].state);
+#endif
+}
+
+static inline void netif_stop_subqueue(struct net_device *dev, u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+#ifdef CONFIG_NETPOLL_TRAP
+	if (netpoll_trap())
+		return;
+#endif
+	set_bit(__LINK_STATE_XOFF, &dev->egress_subqueue[queue_index].state);
+#endif
+}
+
+static inline int netif_subqueue_stopped(const struct net_device *dev,
+					 u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	return test_bit(__LINK_STATE_XOFF,
+			&dev->egress_subqueue[queue_index].state);
+#else
+	return 0;
+#endif
+}
+
+static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+#ifdef CONFIG_NETPOLL_TRAP
+	if (netpoll_trap())
+		return;
+#endif
+	if (test_and_clear_bit(__LINK_STATE_XOFF,
+			       &dev->egress_subqueue[queue_index].state))
+		__netif_schedule(dev);
+#endif
+}
+
+static inline int netif_is_multiqueue(const struct net_device *dev)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	return (!!(NETIF_F_MULTI_QUEUE & dev->features));
+#else
+	return 0;
+#endif
+}
 
 /* Use this variant when it is known for sure that it
  * is executing from interrupt context.
@@ -930,6 +1016,14 @@
 {
 	unsigned long flags;
 
+#ifdef CONFIG_NETPOLL
+	/* Prevent race with netpoll - yes, this is a kludge.
+	 * But at least it doesn't penalize the non-netpoll
+	 * code path. */
+	if (test_bit(__LINK_STATE_POLL_LIST_FROZEN, &dev->state))
+		return;
+#endif
+
 	local_irq_save(flags);
 	__netif_rx_complete(dev);
 	local_irq_restore(flags);
@@ -992,15 +1086,24 @@
 extern void		ether_setup(struct net_device *dev);
 
 /* Support for loadable net-drivers */
-extern struct net_device *alloc_netdev(int sizeof_priv, const char *name,
-				       void (*setup)(struct net_device *));
+extern struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+				       void (*setup)(struct net_device *),
+				       unsigned int queue_count);
+#define alloc_netdev(sizeof_priv, name, setup) \
+	alloc_netdev_mq(sizeof_priv, name, setup, 1)
 extern int		register_netdev(struct net_device *dev);
 extern void		unregister_netdev(struct net_device *dev);
-/* Functions used for multicast support */
-extern void		dev_mc_upload(struct net_device *dev);
+/* Functions used for secondary unicast and multicast support */
+extern void		dev_set_rx_mode(struct net_device *dev);
+extern void		__dev_set_rx_mode(struct net_device *dev);
+extern int		dev_unicast_delete(struct net_device *dev, void *addr, int alen);
+extern int		dev_unicast_add(struct net_device *dev, void *addr, int alen);
 extern int 		dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
 extern int		dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
 extern void		dev_mc_discard(struct net_device *dev);
+extern int 		__dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all);
+extern int		__dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly);
+extern void		__dev_addr_discard(struct dev_addr_list **list);
 extern void		dev_set_promiscuity(struct net_device *dev, int inc);
 extern void		dev_set_allmulti(struct net_device *dev, int inc);
 extern void		netdev_state_change(struct net_device *dev);
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 10b5c62..0eed0b7 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -275,7 +275,8 @@
 };
 extern int nf_register_queue_handler(int pf, 
                                      struct nf_queue_handler *qh);
-extern int nf_unregister_queue_handler(int pf);
+extern int nf_unregister_queue_handler(int pf,
+				       struct nf_queue_handler *qh);
 extern void nf_unregister_queue_handlers(struct nf_queue_handler *qh);
 extern void nf_reinject(struct sk_buff *skb,
 			struct nf_info *info,
diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h
index 9d8144a..c93061f 100644
--- a/include/linux/netfilter/nf_conntrack_pptp.h
+++ b/include/linux/netfilter/nf_conntrack_pptp.h
@@ -4,6 +4,8 @@
 
 #include <linux/netfilter/nf_conntrack_common.h>
 
+extern const char *pptp_msg_name[];
+
 /* state of the control session */
 enum pptp_ctrlsess_state {
 	PPTP_SESSION_NONE,			/* no session present */
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 7e733a6..64f425a8 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -141,22 +141,22 @@
 	/* Arguments changed since 2.6.9, as this must now handle
 	   non-linear skb, using skb_header_pointer and
 	   skb_ip_make_writable. */
-	int (*match)(const struct sk_buff *skb,
-		     const struct net_device *in,
-		     const struct net_device *out,
-		     const struct xt_match *match,
-		     const void *matchinfo,
-		     int offset,
-		     unsigned int protoff,
-		     int *hotdrop);
+	bool (*match)(const struct sk_buff *skb,
+		      const struct net_device *in,
+		      const struct net_device *out,
+		      const struct xt_match *match,
+		      const void *matchinfo,
+		      int offset,
+		      unsigned int protoff,
+		      bool *hotdrop);
 
 	/* Called when user tries to insert an entry of this type. */
 	/* Should return true or false. */
-	int (*checkentry)(const char *tablename,
-			  const void *ip,
-			  const struct xt_match *match,
-			  void *matchinfo,
-			  unsigned int hook_mask);
+	bool (*checkentry)(const char *tablename,
+			   const void *ip,
+			   const struct xt_match *match,
+			   void *matchinfo,
+			   unsigned int hook_mask);
 
 	/* Called when entry of this type deleted. */
 	void (*destroy)(const struct xt_match *match, void *matchinfo);
@@ -202,11 +202,11 @@
            hook_mask is a bitmask of hooks from which it can be
            called. */
 	/* Should return true or false. */
-	int (*checkentry)(const char *tablename,
-			  const void *entry,
-			  const struct xt_target *target,
-			  void *targinfo,
-			  unsigned int hook_mask);
+	bool (*checkentry)(const char *tablename,
+			   const void *entry,
+			   const struct xt_target *target,
+			   void *targinfo,
+			   unsigned int hook_mask);
 
 	/* Called when entry of this type deleted. */
 	void (*destroy)(const struct xt_target *target, void *targinfo);
diff --git a/include/linux/netfilter/xt_u32.h b/include/linux/netfilter/xt_u32.h
new file mode 100644
index 0000000..9947f56
--- /dev/null
+++ b/include/linux/netfilter/xt_u32.h
@@ -0,0 +1,40 @@
+#ifndef _XT_U32_H
+#define _XT_U32_H 1
+
+enum xt_u32_ops {
+	XT_U32_AND,
+	XT_U32_LEFTSH,
+	XT_U32_RIGHTSH,
+	XT_U32_AT,
+};
+
+struct xt_u32_location_element {
+	u_int32_t number;
+	u_int8_t nextop;
+};
+
+struct xt_u32_value_element {
+	u_int32_t min;
+	u_int32_t max;
+};
+
+/*
+ * Any way to allow for an arbitrary number of elements?
+ * For now, I settle with a limit of 10 each.
+ */
+#define XT_U32_MAXSIZE 10
+
+struct xt_u32_test {
+	struct xt_u32_location_element location[XT_U32_MAXSIZE+1];
+	struct xt_u32_value_element value[XT_U32_MAXSIZE+1];
+	u_int8_t nnums;
+	u_int8_t nvalues;
+};
+
+struct xt_u32 {
+	struct xt_u32_test tests[XT_U32_MAXSIZE+1];
+	u_int8_t ntests;
+	u_int8_t invert;
+};
+
+#endif /* _XT_U32_H */
diff --git a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
index d9bceed..daf50be 100644
--- a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
+++ b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
@@ -18,13 +18,13 @@
 struct ipt_clusterip_tgt_info {
 
 	u_int32_t flags;
-	
+
 	/* only relevant for new ones */
 	u_int8_t clustermac[6];
 	u_int16_t num_total_nodes;
 	u_int16_t num_local_nodes;
 	u_int16_t local_nodes[CLUSTERIP_MAX_NODES];
-	enum clusterip_hashmode hash_mode;
+	u_int32_t hash_mode;
 	u_int32_t hash_initval;
 
 	struct clusterip_config *config;
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 4686f83..9a720f0 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -44,8 +44,14 @@
 	char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
 	unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
 
-	/* ARGH, HopByHop uses 0, so can't do 0 = ANY,
-	   instead IP6T_F_NOPROTO must be set */
+	/* Upper protocol number
+	 * - The allowed value is 0 (any) or protocol number of last parsable
+	 *   header, which is 50 (ESP), 59 (No Next Header), 135 (MH), or
+	 *   the non IPv6 extension headers.
+	 * - The protocol numbers of IPv6 extension headers except of ESP and
+	 *   MH do not match any packets.
+	 * - You also need to set IP6T_FLAGS_PROTO to "flags" to check protocol.
+	 */
 	u_int16_t proto;
 	/* TOS to match iff flags & IP6T_F_TOS */
 	u_int8_t tos;
diff --git a/include/linux/pata_platform.h b/include/linux/pata_platform.h
index 2d5fd64..5799e8d 100644
--- a/include/linux/pata_platform.h
+++ b/include/linux/pata_platform.h
@@ -8,6 +8,11 @@
 	 * spacing used by ata_std_ports().
 	 */
 	unsigned int ioport_shift;
+	/* 
+	 * Indicate platform specific irq types and initial
+	 * IRQ flags when call request_irq()
+	 */
+	unsigned int irq_flags;
 };
 
 #endif /* __LINUX_PATA_PLATFORM_H */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 5b1c999..75c4d4d 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2000,6 +2000,7 @@
 
 #define PCI_VENDOR_ID_ENE		0x1524
 #define PCI_DEVICE_ID_ENE_CB712_SD	0x0550
+#define PCI_DEVICE_ID_ENE_CB712_SD_2	0x0551
 #define PCI_DEVICE_ID_ENE_1211		0x1211
 #define PCI_DEVICE_ID_ENE_1225		0x1225
 #define PCI_DEVICE_ID_ENE_1410		0x1410
diff --git a/include/linux/pda_power.h b/include/linux/pda_power.h
new file mode 100644
index 0000000..1375f15
--- /dev/null
+++ b/include/linux/pda_power.h
@@ -0,0 +1,31 @@
+/*
+ * Common power driver for PDAs and phones with one or two external
+ * power supplies (AC/USB) connected to main and backup batteries,
+ * and optional builtin charger.
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PDA_POWER_H__
+#define __PDA_POWER_H__
+
+#define PDA_POWER_CHARGE_AC  (1 << 0)
+#define PDA_POWER_CHARGE_USB (1 << 1)
+
+struct pda_power_pdata {
+	int (*is_ac_online)(void);
+	int (*is_usb_online)(void);
+	void (*set_charge)(int flags);
+
+	char **supplied_to;
+	size_t num_supplicants;
+
+	unsigned int wait_for_status; /* msecs, default is 500 */
+	unsigned int wait_for_charger; /* msecs, default is 500 */
+};
+
+#endif /* __PDA_POWER_H__ */
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index c8884f9..8e41202 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -9,13 +9,39 @@
 #define PIPE_BUF_FLAG_ATOMIC	0x02	/* was atomically mapped */
 #define PIPE_BUF_FLAG_GIFT	0x04	/* page is a gift */
 
+/**
+ *	struct pipe_buffer - a linux kernel pipe buffer
+ *	@page: the page containing the data for the pipe buffer
+ *	@offset: offset of data inside the @page
+ *	@len: length of data inside the @page
+ *	@ops: operations associated with this buffer. See @pipe_buf_operations.
+ *	@flags: pipe buffer flags. See above.
+ *	@private: private data owned by the ops.
+ **/
 struct pipe_buffer {
 	struct page *page;
 	unsigned int offset, len;
 	const struct pipe_buf_operations *ops;
 	unsigned int flags;
+	unsigned long private;
 };
 
+/**
+ *	struct pipe_inode_info - a linux kernel pipe
+ *	@wait: reader/writer wait point in case of empty/full pipe
+ *	@nrbufs: the number of non-empty pipe buffers in this pipe
+ *	@curbuf: the current pipe buffer entry
+ *	@tmp_page: cached released page
+ *	@readers: number of current readers of this pipe
+ *	@writers: number of current writers of this pipe
+ *	@waiting_writers: number of writers blocked waiting for room
+ *	@r_counter: reader counter
+ *	@w_counter: writer counter
+ *	@fasync_readers: reader side fasync
+ *	@fasync_writers: writer side fasync
+ *	@inode: inode this pipe is attached to
+ *	@bufs: the circular array of pipe buffers
+ **/
 struct pipe_inode_info {
 	wait_queue_head_t wait;
 	unsigned int nrbufs, curbuf;
@@ -34,22 +60,73 @@
 /*
  * Note on the nesting of these functions:
  *
- * ->pin()
+ * ->confirm()
  *	->steal()
  *	...
  *	->map()
  *	...
  *	->unmap()
  *
- * That is, ->map() must be called on a pinned buffer, same goes for ->steal().
+ * That is, ->map() must be called on a confirmed buffer,
+ * same goes for ->steal(). See below for the meaning of each
+ * operation. Also see kerneldoc in fs/pipe.c for the pipe
+ * and generic variants of these hooks.
  */
 struct pipe_buf_operations {
+	/*
+	 * This is set to 1, if the generic pipe read/write may coalesce
+	 * data into an existing buffer. If this is set to 0, a new pipe
+	 * page segment is always used for new data.
+	 */
 	int can_merge;
+
+	/*
+	 * ->map() returns a virtual address mapping of the pipe buffer.
+	 * The last integer flag reflects whether this should be an atomic
+	 * mapping or not. The atomic map is faster, however you can't take
+	 * page faults before calling ->unmap() again. So if you need to eg
+	 * access user data through copy_to/from_user(), then you must get
+	 * a non-atomic map. ->map() uses the KM_USER0 atomic slot for
+	 * atomic maps, so you can't map more than one pipe_buffer at once
+	 * and you have to be careful if mapping another page as source
+	 * or destination for a copy (IOW, it has to use something else
+	 * than KM_USER0).
+	 */
 	void * (*map)(struct pipe_inode_info *, struct pipe_buffer *, int);
+
+	/*
+	 * Undoes ->map(), finishes the virtual mapping of the pipe buffer.
+	 */
 	void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *, void *);
-	int (*pin)(struct pipe_inode_info *, struct pipe_buffer *);
+
+	/*
+	 * ->confirm() verifies that the data in the pipe buffer is there
+	 * and that the contents are good. If the pages in the pipe belong
+	 * to a file system, we may need to wait for IO completion in this
+	 * hook. Returns 0 for good, or a negative error value in case of
+	 * error.
+	 */
+	int (*confirm)(struct pipe_inode_info *, struct pipe_buffer *);
+
+	/*
+	 * When the contents of this pipe buffer has been completely
+	 * consumed by a reader, ->release() is called.
+	 */
 	void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
+
+	/*
+	 * Attempt to take ownership of the pipe buffer and its contents.
+	 * ->steal() returns 0 for success, in which case the contents
+	 * of the pipe (the buf->page) is locked and now completely owned
+	 * by the caller. The page may then be transferred to a different
+	 * mapping, the most often used case is insertion into different
+	 * file address space cache.
+	 */
 	int (*steal)(struct pipe_inode_info *, struct pipe_buffer *);
+
+	/*
+	 * Get a reference to the pipe buffer.
+	 */
 	void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
 };
 
@@ -68,39 +145,7 @@
 void *generic_pipe_buf_map(struct pipe_inode_info *, struct pipe_buffer *, int);
 void generic_pipe_buf_unmap(struct pipe_inode_info *, struct pipe_buffer *, void *);
 void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *);
-int generic_pipe_buf_pin(struct pipe_inode_info *, struct pipe_buffer *);
+int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *);
 int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *);
 
-/*
- * splice is tied to pipes as a transport (at least for now), so we'll just
- * add the splice flags here.
- */
-#define SPLICE_F_MOVE	(0x01)	/* move pages instead of copying */
-#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
-				 /* we may still block on the fd we splice */
-				 /* from/to, of course */
-#define SPLICE_F_MORE	(0x04)	/* expect more data */
-#define SPLICE_F_GIFT	(0x08)	/* pages passed in are a gift */
-
-/*
- * Passed to the actors
- */
-struct splice_desc {
-	unsigned int len, total_len;	/* current and remaining length */
-	unsigned int flags;		/* splice flags */
-	struct file *file;		/* file to read/write */
-	loff_t pos;			/* file position */
-};
-
-typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
-			   struct splice_desc *);
-
-extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
-				loff_t *, size_t, unsigned int,
-				splice_actor *);
-
-extern ssize_t __splice_from_pipe(struct pipe_inode_info *, struct file *,
-				  loff_t *, size_t, unsigned int,
-				  splice_actor *);
-
 #endif
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index d10f353..268c515 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -101,6 +101,15 @@
 	__u8	priomap[TC_PRIO_MAX+1];	/* Map: logical priority -> PRIO band */
 };
 
+enum
+{
+	TCA_PRIO_UNSPEC,
+	TCA_PRIO_MQ,
+	__TCA_PRIO_MAX
+};
+
+#define TCA_PRIO_MAX    (__TCA_PRIO_MAX - 1)
+
 /* TBF section */
 
 struct tc_tbf_qopt
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
new file mode 100644
index 0000000..606c095
--- /dev/null
+++ b/include/linux/power_supply.h
@@ -0,0 +1,180 @@
+/*
+ *  Universal power supply monitor class
+ *
+ *  Copyright © 2007  Anton Vorontsov <cbou@mail.ru>
+ *  Copyright © 2004  Szabolcs Gyurko
+ *  Copyright © 2003  Ian Molton <spyro@f2s.com>
+ *
+ *  Modified: 2004, Oct     Szabolcs Gyurko
+ *
+ *  You may use this code as per GPL version 2
+ */
+
+#ifndef __LINUX_POWER_SUPPLY_H__
+#define __LINUX_POWER_SUPPLY_H__
+
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/leds.h>
+
+/*
+ * All voltages, currents, charges, energies, time and temperatures in uV,
+ * µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+ * stated. It's driver's job to convert its raw values to units in which
+ * this class operates.
+ */
+
+/*
+ * For systems where the charger determines the maximum battery capacity
+ * the min and max fields should be used to present these values to user
+ * space. Unused/unknown fields will not appear in sysfs.
+ */
+
+enum {
+	POWER_SUPPLY_STATUS_UNKNOWN = 0,
+	POWER_SUPPLY_STATUS_CHARGING,
+	POWER_SUPPLY_STATUS_DISCHARGING,
+	POWER_SUPPLY_STATUS_NOT_CHARGING,
+	POWER_SUPPLY_STATUS_FULL,
+};
+
+enum {
+	POWER_SUPPLY_HEALTH_UNKNOWN = 0,
+	POWER_SUPPLY_HEALTH_GOOD,
+	POWER_SUPPLY_HEALTH_OVERHEAT,
+	POWER_SUPPLY_HEALTH_DEAD,
+	POWER_SUPPLY_HEALTH_OVERVOLTAGE,
+	POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,
+};
+
+enum {
+	POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0,
+	POWER_SUPPLY_TECHNOLOGY_NiMH,
+	POWER_SUPPLY_TECHNOLOGY_LION,
+	POWER_SUPPLY_TECHNOLOGY_LIPO,
+	POWER_SUPPLY_TECHNOLOGY_LiFe,
+	POWER_SUPPLY_TECHNOLOGY_NiCd,
+};
+
+enum {
+	POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0,
+	POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL,
+	POWER_SUPPLY_CAPACITY_LEVEL_LOW,
+	POWER_SUPPLY_CAPACITY_LEVEL_NORMAL,
+	POWER_SUPPLY_CAPACITY_LEVEL_HIGH,
+	POWER_SUPPLY_CAPACITY_LEVEL_FULL,
+};
+
+enum power_supply_property {
+	/* Properties of type `int' */
+	POWER_SUPPLY_PROP_STATUS = 0,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_VOLTAGE_AVG,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CURRENT_AVG,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_EMPTY,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CHARGE_AVG,
+	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+	POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
+	POWER_SUPPLY_PROP_ENERGY_FULL,
+	POWER_SUPPLY_PROP_ENERGY_EMPTY,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
+	POWER_SUPPLY_PROP_ENERGY_AVG,
+	POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
+	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_TEMP_AMBIENT,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+	POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+	POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
+	/* Properties of type `const char *' */
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+enum power_supply_type {
+	POWER_SUPPLY_TYPE_BATTERY = 0,
+	POWER_SUPPLY_TYPE_UPS,
+	POWER_SUPPLY_TYPE_MAINS,
+	POWER_SUPPLY_TYPE_USB,
+};
+
+union power_supply_propval {
+	int intval;
+	const char *strval;
+};
+
+struct power_supply {
+	const char *name;
+	enum power_supply_type type;
+	enum power_supply_property *properties;
+	size_t num_properties;
+
+	char **supplied_to;
+	size_t num_supplicants;
+
+	int (*get_property)(struct power_supply *psy,
+			    enum power_supply_property psp,
+			    union power_supply_propval *val);
+	void (*external_power_changed)(struct power_supply *psy);
+
+	/* For APM emulation, think legacy userspace. */
+	int use_for_apm;
+
+	/* private */
+	struct device *dev;
+	struct work_struct changed_work;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+	struct led_trigger *charging_full_trig;
+	char *charging_full_trig_name;
+	struct led_trigger *charging_trig;
+	char *charging_trig_name;
+	struct led_trigger *full_trig;
+	char *full_trig_name;
+	struct led_trigger *online_trig;
+	char *online_trig_name;
+#endif
+};
+
+/*
+ * This is recommended structure to specify static power supply parameters.
+ * Generic one, parametrizable for different power supplies. Power supply
+ * class itself does not use it, but that's what implementing most platform
+ * drivers, should try reuse for consistency.
+ */
+
+struct power_supply_info {
+	const char *name;
+	int technology;
+	int voltage_max_design;
+	int voltage_min_design;
+	int charge_full_design;
+	int charge_empty_design;
+	int energy_full_design;
+	int energy_empty_design;
+	int use_for_apm;
+};
+
+extern void power_supply_changed(struct power_supply *psy);
+extern int power_supply_am_i_supplied(struct power_supply *psy);
+
+extern int power_supply_register(struct device *parent,
+				 struct power_supply *psy);
+extern void power_supply_unregister(struct power_supply *psy);
+
+/* For APM emulation, think legacy userspace. */
+extern struct class *power_supply_class;
+
+#endif /* __LINUX_POWER_SUPPLY_H__ */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 1fae30a..c91476c 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -261,7 +261,7 @@
 	RTA_FLOW,
 	RTA_CACHEINFO,
 	RTA_SESSION,
-	RTA_MP_ALGO,
+	RTA_MP_ALGO, /* no longer used */
 	RTA_TABLE,
 	__RTA_MAX
 };
@@ -570,10 +570,16 @@
 }
 
 extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len);
+extern int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
+				        struct rtattr *rta, int len);
 
 #define rtattr_parse_nested(tb, max, rta) \
 	rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta)))
 
+#define rtattr_parse_nested_compat(tb, max, rta, data, len) \
+({	data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \
+	__rtattr_parse_nested_compat(tb, max, rta, len); })
+
 extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo);
 extern int rtnl_unicast(struct sk_buff *skb, u32 pid);
 extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
@@ -638,6 +644,18 @@
 ({	(start)->rta_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
 	(skb)->len; })
 
+#define RTA_NEST_COMPAT(skb, type, attrlen, data) \
+({	struct rtattr *__start = (struct rtattr *)skb_tail_pointer(skb); \
+	RTA_PUT(skb, type, attrlen, data); \
+	RTA_NEST(skb, type); \
+	__start; })
+
+#define RTA_NEST_COMPAT_END(skb, start) \
+({	struct rtattr *__nest = (void *)(start) + NLMSG_ALIGN((start)->rta_len); \
+	(start)->rta_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
+	RTA_NEST_END(skb, __nest); \
+	(skb)->len; })
+
 #define RTA_NEST_CANCEL(skb, start) \
 ({	if (start) \
 		skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 693f0e6..cfb6805 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -34,6 +34,8 @@
 #define SCHED_FIFO		1
 #define SCHED_RR		2
 #define SCHED_BATCH		3
+/* SCHED_ISO: reserved but not implemented yet */
+#define SCHED_IDLE		5
 
 #ifdef __KERNEL__
 
@@ -130,6 +132,26 @@
 extern unsigned long nr_iowait(void);
 extern unsigned long weighted_cpuload(const int cpu);
 
+struct seq_file;
+struct cfs_rq;
+#ifdef CONFIG_SCHED_DEBUG
+extern void proc_sched_show_task(struct task_struct *p, struct seq_file *m);
+extern void proc_sched_set_task(struct task_struct *p);
+extern void
+print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now);
+#else
+static inline void
+proc_sched_show_task(struct task_struct *p, struct seq_file *m)
+{
+}
+static inline void proc_sched_set_task(struct task_struct *p)
+{
+}
+static inline void
+print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now)
+{
+}
+#endif
 
 /*
  * Task state bitmask. NOTE! These bits are also
@@ -193,6 +215,7 @@
 extern void sched_init(void);
 extern void sched_init_smp(void);
 extern void init_idle(struct task_struct *idle, int cpu);
+extern void init_idle_bootup_task(struct task_struct *idle);
 
 extern cpumask_t nohz_cpu_mask;
 #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ)
@@ -479,7 +502,7 @@
 	 * from jiffies_to_ns(utime + stime) if sched_clock uses something
 	 * other than jiffies.)
 	 */
-	unsigned long long sched_time;
+	unsigned long long sum_sched_runtime;
 
 	/*
 	 * We don't bother to synchronize most readers of this at all,
@@ -521,31 +544,6 @@
 #define SIGNAL_STOP_CONTINUED	0x00000004 /* SIGCONT since WCONTINUED reap */
 #define SIGNAL_GROUP_EXIT	0x00000008 /* group exit in progress */
 
-
-/*
- * Priority of a process goes from 0..MAX_PRIO-1, valid RT
- * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
- * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
- * values are inverted: lower p->prio value means higher priority.
- *
- * The MAX_USER_RT_PRIO value allows the actual maximum
- * RT priority to be separate from the value exported to
- * user-space.  This allows kernel threads to set their
- * priority to a value higher than any user task. Note:
- * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
- */
-
-#define MAX_USER_RT_PRIO	100
-#define MAX_RT_PRIO		MAX_USER_RT_PRIO
-
-#define MAX_PRIO		(MAX_RT_PRIO + 40)
-
-#define rt_prio(prio)		unlikely((prio) < MAX_RT_PRIO)
-#define rt_task(p)		rt_prio((p)->prio)
-#define batch_task(p)		(unlikely((p)->policy == SCHED_BATCH))
-#define is_rt_policy(p)		((p) != SCHED_NORMAL && (p) != SCHED_BATCH)
-#define has_rt_policy(p)	unlikely(is_rt_policy((p)->policy))
-
 /*
  * Some day this will be a full-fledged user tracking system..
  */
@@ -583,13 +581,13 @@
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
 struct sched_info {
 	/* cumulative counters */
-	unsigned long	cpu_time,	/* time spent on the cpu */
-			run_delay,	/* time spent waiting on a runqueue */
-			pcnt;		/* # of timeslices run on this cpu */
+	unsigned long pcnt;	      /* # of times run on this cpu */
+	unsigned long long cpu_time,  /* time spent on the cpu */
+			   run_delay; /* time spent waiting on a runqueue */
 
 	/* timestamps */
-	unsigned long	last_arrival,	/* when we last ran on a cpu */
-			last_queued;	/* when we were last queued to run */
+	unsigned long long last_arrival,/* when we last ran on a cpu */
+			   last_queued;	/* when we were last queued to run */
 };
 #endif /* defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) */
 
@@ -639,18 +637,24 @@
 #endif
 }
 
-enum idle_type
-{
-	SCHED_IDLE,
-	NOT_IDLE,
-	NEWLY_IDLE,
-	MAX_IDLE_TYPES
+enum cpu_idle_type {
+	CPU_IDLE,
+	CPU_NOT_IDLE,
+	CPU_NEWLY_IDLE,
+	CPU_MAX_IDLE_TYPES
 };
 
 /*
  * sched-domains (multiprocessor balancing) declarations:
  */
-#define SCHED_LOAD_SCALE	128UL	/* increase resolution of load */
+
+/*
+ * Increase resolution of nice-level calculations:
+ */
+#define SCHED_LOAD_SHIFT	10
+#define SCHED_LOAD_SCALE	(1L << SCHED_LOAD_SHIFT)
+
+#define SCHED_LOAD_SCALE_FUZZ	(SCHED_LOAD_SCALE >> 5)
 
 #ifdef CONFIG_SMP
 #define SD_LOAD_BALANCE		1	/* Do load balancing on this domain. */
@@ -719,14 +723,14 @@
 
 #ifdef CONFIG_SCHEDSTATS
 	/* load_balance() stats */
-	unsigned long lb_cnt[MAX_IDLE_TYPES];
-	unsigned long lb_failed[MAX_IDLE_TYPES];
-	unsigned long lb_balanced[MAX_IDLE_TYPES];
-	unsigned long lb_imbalance[MAX_IDLE_TYPES];
-	unsigned long lb_gained[MAX_IDLE_TYPES];
-	unsigned long lb_hot_gained[MAX_IDLE_TYPES];
-	unsigned long lb_nobusyg[MAX_IDLE_TYPES];
-	unsigned long lb_nobusyq[MAX_IDLE_TYPES];
+	unsigned long lb_cnt[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_failed[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_balanced[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_imbalance[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_gained[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_hot_gained[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_nobusyg[CPU_MAX_IDLE_TYPES];
+	unsigned long lb_nobusyq[CPU_MAX_IDLE_TYPES];
 
 	/* Active load balancing */
 	unsigned long alb_cnt;
@@ -753,12 +757,6 @@
 extern int partition_sched_domains(cpumask_t *partition1,
 				    cpumask_t *partition2);
 
-/*
- * Maximum cache size the migration-costs auto-tuning code will
- * search from:
- */
-extern unsigned int max_cache_size;
-
 #endif	/* CONFIG_SMP */
 
 
@@ -809,14 +807,86 @@
 struct pipe_inode_info;
 struct uts_namespace;
 
-enum sleep_type {
-	SLEEP_NORMAL,
-	SLEEP_NONINTERACTIVE,
-	SLEEP_INTERACTIVE,
-	SLEEP_INTERRUPTED,
+struct rq;
+struct sched_domain;
+
+struct sched_class {
+	struct sched_class *next;
+
+	void (*enqueue_task) (struct rq *rq, struct task_struct *p,
+			      int wakeup, u64 now);
+	void (*dequeue_task) (struct rq *rq, struct task_struct *p,
+			      int sleep, u64 now);
+	void (*yield_task) (struct rq *rq, struct task_struct *p);
+
+	void (*check_preempt_curr) (struct rq *rq, struct task_struct *p);
+
+	struct task_struct * (*pick_next_task) (struct rq *rq, u64 now);
+	void (*put_prev_task) (struct rq *rq, struct task_struct *p, u64 now);
+
+	int (*load_balance) (struct rq *this_rq, int this_cpu,
+			struct rq *busiest,
+			unsigned long max_nr_move, unsigned long max_load_move,
+			struct sched_domain *sd, enum cpu_idle_type idle,
+			int *all_pinned, unsigned long *total_load_moved);
+
+	void (*set_curr_task) (struct rq *rq);
+	void (*task_tick) (struct rq *rq, struct task_struct *p);
+	void (*task_new) (struct rq *rq, struct task_struct *p);
 };
 
-struct prio_array;
+struct load_weight {
+	unsigned long weight, inv_weight;
+};
+
+/*
+ * CFS stats for a schedulable entity (task, task-group etc)
+ *
+ * Current field usage histogram:
+ *
+ *     4 se->block_start
+ *     4 se->run_node
+ *     4 se->sleep_start
+ *     4 se->sleep_start_fair
+ *     6 se->load.weight
+ *     7 se->delta_fair
+ *    15 se->wait_runtime
+ */
+struct sched_entity {
+	long			wait_runtime;
+	unsigned long		delta_fair_run;
+	unsigned long		delta_fair_sleep;
+	unsigned long		delta_exec;
+	s64			fair_key;
+	struct load_weight	load;		/* for load-balancing */
+	struct rb_node		run_node;
+	unsigned int		on_rq;
+
+	u64			wait_start_fair;
+	u64			wait_start;
+	u64			exec_start;
+	u64			sleep_start;
+	u64			sleep_start_fair;
+	u64			block_start;
+	u64			sleep_max;
+	u64			block_max;
+	u64			exec_max;
+	u64			wait_max;
+	u64			last_ran;
+
+	u64			sum_exec_runtime;
+	s64			sum_wait_runtime;
+	s64			sum_sleep_runtime;
+	unsigned long		wait_runtime_overruns;
+	unsigned long		wait_runtime_underruns;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	struct sched_entity	*parent;
+	/* rq on which this entity is (to be) queued: */
+	struct cfs_rq		*cfs_rq;
+	/* rq "owned" by this entity/group: */
+	struct cfs_rq		*my_q;
+#endif
+};
 
 struct task_struct {
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
@@ -832,23 +902,20 @@
 	int oncpu;
 #endif
 #endif
-	int load_weight;	/* for niceness load balancing purposes */
+
 	int prio, static_prio, normal_prio;
 	struct list_head run_list;
-	struct prio_array *array;
+	struct sched_class *sched_class;
+	struct sched_entity se;
 
 	unsigned short ioprio;
 #ifdef CONFIG_BLK_DEV_IO_TRACE
 	unsigned int btrace_seq;
 #endif
-	unsigned long sleep_avg;
-	unsigned long long timestamp, last_ran;
-	unsigned long long sched_time; /* sched_clock time spent running */
-	enum sleep_type sleep_type;
 
 	unsigned int policy;
 	cpumask_t cpus_allowed;
-	unsigned int time_slice, first_time_slice;
+	unsigned int time_slice;
 
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
 	struct sched_info sched_info;
@@ -1078,6 +1145,37 @@
 #endif
 };
 
+/*
+ * Priority of a process goes from 0..MAX_PRIO-1, valid RT
+ * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
+ * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
+ * values are inverted: lower p->prio value means higher priority.
+ *
+ * The MAX_USER_RT_PRIO value allows the actual maximum
+ * RT priority to be separate from the value exported to
+ * user-space.  This allows kernel threads to set their
+ * priority to a value higher than any user task. Note:
+ * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
+ */
+
+#define MAX_USER_RT_PRIO	100
+#define MAX_RT_PRIO		MAX_USER_RT_PRIO
+
+#define MAX_PRIO		(MAX_RT_PRIO + 40)
+#define DEFAULT_PRIO		(MAX_RT_PRIO + 20)
+
+static inline int rt_prio(int prio)
+{
+	if (unlikely(prio < MAX_RT_PRIO))
+		return 1;
+	return 0;
+}
+
+static inline int rt_task(struct task_struct *p)
+{
+	return rt_prio(p->prio);
+}
+
 static inline pid_t process_group(struct task_struct *tsk)
 {
 	return tsk->signal->pgrp;
@@ -1223,7 +1321,7 @@
 
 extern unsigned long long sched_clock(void);
 extern unsigned long long
-current_sched_time(const struct task_struct *current_task);
+task_sched_runtime(struct task_struct *task);
 
 /* sched_exec is called by processes performing an exec */
 #ifdef CONFIG_SMP
@@ -1232,6 +1330,8 @@
 #define sched_exec()   {}
 #endif
 
+extern void sched_clock_unstable_event(void);
+
 #ifdef CONFIG_HOTPLUG_CPU
 extern void idle_task_exit(void);
 #else
@@ -1240,6 +1340,14 @@
 
 extern void sched_idle_next(void);
 
+extern unsigned int sysctl_sched_granularity;
+extern unsigned int sysctl_sched_wakeup_granularity;
+extern unsigned int sysctl_sched_batch_wakeup_granularity;
+extern unsigned int sysctl_sched_stat_granularity;
+extern unsigned int sysctl_sched_runtime_limit;
+extern unsigned int sysctl_sched_child_runs_first;
+extern unsigned int sysctl_sched_features;
+
 #ifdef CONFIG_RT_MUTEXES
 extern int rt_mutex_getprio(struct task_struct *p);
 extern void rt_mutex_setprio(struct task_struct *p, int prio);
@@ -1317,8 +1425,8 @@
 #else
  static inline void kick_process(struct task_struct *tsk) { }
 #endif
-extern void FASTCALL(sched_fork(struct task_struct * p, int clone_flags));
-extern void FASTCALL(sched_exit(struct task_struct * p));
+extern void sched_fork(struct task_struct *p, int clone_flags);
+extern void sched_dead(struct task_struct *p);
 
 extern int in_group_p(gid_t);
 extern int in_egroup_p(gid_t);
@@ -1406,7 +1514,7 @@
 extern void FASTCALL(__mmdrop(struct mm_struct *));
 static inline void mmdrop(struct mm_struct * mm)
 {
-	if (atomic_dec_and_test(&mm->mm_count))
+	if (unlikely(atomic_dec_and_test(&mm->mm_count)))
 		__mmdrop(mm);
 }
 
@@ -1638,10 +1746,7 @@
 	return task_thread_info(p)->cpu;
 }
 
-static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
-{
-	task_thread_info(p)->cpu = cpu;
-}
+extern void set_task_cpu(struct task_struct *p, unsigned int cpu);
 
 #else
 
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 3e3cccb..83783ab 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -50,5 +50,16 @@
 
 #define SEQ_START_TOKEN ((void *)1)
 
+/*
+ * Helpers for iteration over list_head-s in seq_files
+ */
+
+extern struct list_head *seq_list_start(struct list_head *head,
+		loff_t pos);
+extern struct list_head *seq_list_start_head(struct list_head *head,
+		loff_t pos);
+extern struct list_head *seq_list_next(void *v, struct list_head *head,
+		loff_t *ppos);
+
 #endif
 #endif
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6f0b2f7..9391e4a 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -65,13 +65,20 @@
  *	    is able to produce some skb->csum, it MUST use COMPLETE,
  *	    not UNNECESSARY.
  *
+ *	PARTIAL: identical to the case for output below.  This may occur
+ *	    on a packet received directly from another Linux OS, e.g.,
+ *	    a virtualised Linux kernel on the same host.  The packet can
+ *	    be treated in the same way as UNNECESSARY except that on
+ *	    output (i.e., forwarding) the checksum must be filled in
+ *	    by the OS or the hardware.
+ *
  * B. Checksumming on output.
  *
  *	NONE: skb is checksummed by protocol or csum is not required.
  *
  *	PARTIAL: device is required to csum packet as seen by hard_start_xmit
- *	from skb->transport_header to the end and to record the checksum
- *	at skb->transport_header + skb->csum.
+ *	from skb->csum_start to the end and to record the checksum
+ *	at skb->csum_start + skb->csum_offset.
  *
  *	Device must show its capabilities in dev->features, set
  *	at device setup time.
@@ -82,6 +89,7 @@
  *			  TCP/UDP over IPv4. Sigh. Vendors like this
  *			  way by an unknown reason. Though, see comment above
  *			  about CHECKSUM_UNNECESSARY. 8)
+ *	NETIF_F_IPV6_CSUM about as dumb as the last one but does IPv6 instead.
  *
  *	Any questions? No questions, good. 		--ANK
  */
@@ -147,8 +155,8 @@
 
 /* We divide dataref into two halves.  The higher 16 bits hold references
  * to the payload part of skb->data.  The lower 16 bits hold references to
- * the entire skb->data.  It is up to the users of the skb to agree on
- * where the payload starts.
+ * the entire skb->data.  A clone of a headerless skb holds the length of
+ * the header in skb->hdr_len.
  *
  * All users must obey the rule that the skb->data reference count must be
  * greater than or equal to the payload reference count.
@@ -196,7 +204,6 @@
  *	@sk: Socket we are owned by
  *	@tstamp: Time we arrived
  *	@dev: Device we arrived on/are leaving by
- *	@iif: ifindex of device we arrived on
  *	@transport_header: Transport layer header
  *	@network_header: Network layer header
  *	@mac_header: Link layer header
@@ -206,6 +213,7 @@
  *	@len: Length of actual data
  *	@data_len: Data length
  *	@mac_len: Length of link layer header
+ *	@hdr_len: writable header length of cloned skb
  *	@csum: Checksum (must include start/offset pair)
  *	@csum_start: Offset from skb->head where checksumming should start
  *	@csum_offset: Offset from csum_start where checksum should be stored
@@ -227,9 +235,12 @@
  *	@mark: Generic packet mark
  *	@nfct: Associated connection, if any
  *	@ipvs_property: skbuff is owned by ipvs
+ *	@nf_trace: netfilter packet trace flag
  *	@nfctinfo: Relationship of this skb to the connection
  *	@nfct_reasm: netfilter conntrack re-assembly pointer
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
+ *	@iif: ifindex of device we arrived on
+ *	@queue_mapping: Queue mapping for multiqueue devices
  *	@tc_index: Traffic control index
  *	@tc_verd: traffic control verdict
  *	@dma_cookie: a cookie to one of several possible DMA operations
@@ -245,8 +256,6 @@
 	struct sock		*sk;
 	ktime_t			tstamp;
 	struct net_device	*dev;
-	int			iif;
-	/* 4 byte hole on 64 bit*/
 
 	struct  dst_entry	*dst;
 	struct	sec_path	*sp;
@@ -260,8 +269,9 @@
 	char			cb[48];
 
 	unsigned int		len,
-				data_len,
-				mac_len;
+				data_len;
+	__u16			mac_len,
+				hdr_len;
 	union {
 		__wsum		csum;
 		struct {
@@ -277,7 +287,8 @@
 				nfctinfo:3;
 	__u8			pkt_type:3,
 				fclone:2,
-				ipvs_property:1;
+				ipvs_property:1,
+				nf_trace:1;
 	__be16			protocol;
 
 	void			(*destructor)(struct sk_buff *skb);
@@ -288,12 +299,18 @@
 #ifdef CONFIG_BRIDGE_NETFILTER
 	struct nf_bridge_info	*nf_bridge;
 #endif
+
+	int			iif;
+	__u16			queue_mapping;
+
 #ifdef CONFIG_NET_SCHED
 	__u16			tc_index;	/* traffic control index */
 #ifdef CONFIG_NET_CLS_ACT
 	__u16			tc_verd;	/* traffic control verdict */
 #endif
 #endif
+	/* 2 byte hole */
+
 #ifdef CONFIG_NET_DMA
 	dma_cookie_t		dma_cookie;
 #endif
@@ -1322,6 +1339,20 @@
 }
 
 /**
+ *	skb_clone_writable - is the header of a clone writable
+ *	@skb: buffer to check
+ *	@len: length up to which to write
+ *
+ *	Returns true if modifying the header part of the cloned buffer
+ *	does not requires the data to be copied.
+ */
+static inline int skb_clone_writable(struct sk_buff *skb, int len)
+{
+	return !skb_header_cloned(skb) &&
+	       skb_headroom(skb) + len <= skb->hdr_len;
+}
+
+/**
  *	skb_cow - copy header of skb when it is required
  *	@skb: buffer to cow
  *	@headroom: needed headroom
@@ -1709,6 +1740,20 @@
 { }
 #endif
 
+static inline void skb_set_queue_mapping(struct sk_buff *skb, u16 queue_mapping)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	skb->queue_mapping = queue_mapping;
+#endif
+}
+
+static inline void skb_copy_queue_mapping(struct sk_buff *to, const struct sk_buff *from)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+	to->queue_mapping = from->queue_mapping;
+#endif
+}
+
 static inline int skb_is_gso(const struct sk_buff *skb)
 {
 	return skb_shinfo(skb)->gso_size;
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 6e7c948..fe195c9 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -287,6 +287,7 @@
 #define SOL_NETLINK	270
 #define SOL_TIPC	271
 #define SOL_RXRPC	272
+#define SOL_PPPOL2TP	273
 
 /* IPX options */
 #define IPX_TYPE	1
diff --git a/include/linux/splice.h b/include/linux/splice.h
new file mode 100644
index 0000000..33e447f
--- /dev/null
+++ b/include/linux/splice.h
@@ -0,0 +1,73 @@
+/*
+ * Function declerations and data structures related to the splice
+ * implementation.
+ *
+ * Copyright (C) 2007 Jens Axboe <jens.axboe@oracle.com>
+ *
+ */
+#ifndef SPLICE_H
+#define SPLICE_H
+
+#include <linux/pipe_fs_i.h>
+
+/*
+ * splice is tied to pipes as a transport (at least for now), so we'll just
+ * add the splice flags here.
+ */
+#define SPLICE_F_MOVE	(0x01)	/* move pages instead of copying */
+#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
+				 /* we may still block on the fd we splice */
+				 /* from/to, of course */
+#define SPLICE_F_MORE	(0x04)	/* expect more data */
+#define SPLICE_F_GIFT	(0x08)	/* pages passed in are a gift */
+
+/*
+ * Passed to the actors
+ */
+struct splice_desc {
+	unsigned int len, total_len;	/* current and remaining length */
+	unsigned int flags;		/* splice flags */
+	/*
+	 * actor() private data
+	 */
+	union {
+		void __user *userptr;	/* memory to write to */
+		struct file *file;	/* file to read/write */
+		void *data;		/* cookie */
+	} u;
+	loff_t pos;			/* file position */
+};
+
+struct partial_page {
+	unsigned int offset;
+	unsigned int len;
+	unsigned long private;
+};
+
+/*
+ * Passed to splice_to_pipe
+ */
+struct splice_pipe_desc {
+	struct page **pages;		/* page map */
+	struct partial_page *partial;	/* pages[] may not be contig */
+	int nr_pages;			/* number of pages in map */
+	unsigned int flags;		/* splice flags */
+	const struct pipe_buf_operations *ops;/* ops associated with output pipe */
+};
+
+typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
+			   struct splice_desc *);
+typedef int (splice_direct_actor)(struct pipe_inode_info *,
+				  struct splice_desc *);
+
+extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
+				loff_t *, size_t, unsigned int,
+				splice_actor *);
+extern ssize_t __splice_from_pipe(struct pipe_inode_info *,
+				  struct splice_desc *, splice_actor *);
+extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+			      struct splice_pipe_desc *);
+extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
+				      splice_direct_actor *);
+
+#endif
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 4a7ae8a..129d50f 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -253,7 +253,7 @@
 						 * determine what device number
 						 * to report (real or virtual)
 						 */
-	int			rq_sendfile_ok; /* turned off in gss privacy
+	int			rq_splice_ok;   /* turned off in gss privacy
 						 * to prevent encrypting page
 						 * cache pages */
 	wait_queue_head_t	rq_wait;	/* synchronization */
diff --git a/include/linux/topology.h b/include/linux/topology.h
index a9d1f04..da6c39b 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -98,7 +98,7 @@
 	.cache_nice_tries	= 0,			\
 	.busy_idx		= 0,			\
 	.idle_idx		= 0,			\
-	.newidle_idx		= 1,			\
+	.newidle_idx		= 0,			\
 	.wake_idx		= 0,			\
 	.forkexec_idx		= 0,			\
 	.flags			= SD_LOAD_BALANCE	\
@@ -128,14 +128,15 @@
 	.imbalance_pct		= 125,			\
 	.cache_nice_tries	= 1,			\
 	.busy_idx		= 2,			\
-	.idle_idx		= 1,			\
-	.newidle_idx		= 2,			\
+	.idle_idx		= 0,			\
+	.newidle_idx		= 0,			\
 	.wake_idx		= 1,			\
 	.forkexec_idx		= 1,			\
 	.flags			= SD_LOAD_BALANCE	\
 				| SD_BALANCE_NEWIDLE	\
 				| SD_BALANCE_EXEC	\
 				| SD_WAKE_AFFINE	\
+				| SD_WAKE_IDLE		\
 				| SD_SHARE_PKG_RESOURCES\
 				| BALANCE_FOR_MC_POWER,	\
 	.last_balance		= jiffies,		\
@@ -158,14 +159,15 @@
 	.imbalance_pct		= 125,			\
 	.cache_nice_tries	= 1,			\
 	.busy_idx		= 2,			\
-	.idle_idx		= 1,			\
-	.newidle_idx		= 2,			\
+	.idle_idx		= 0,			\
+	.newidle_idx		= 0,			\
 	.wake_idx		= 1,			\
 	.forkexec_idx		= 1,			\
 	.flags			= SD_LOAD_BALANCE	\
 				| SD_BALANCE_NEWIDLE	\
 				| SD_BALANCE_EXEC	\
 				| SD_WAKE_AFFINE	\
+				| SD_WAKE_IDLE		\
 				| BALANCE_FOR_PKG_POWER,\
 	.last_balance		= jiffies,		\
 	.balance_interval	= 1,			\
diff --git a/include/linux/udp.h b/include/linux/udp.h
index 6de445c..8ec703f 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -42,6 +42,7 @@
 /* UDP encapsulation types */
 #define UDP_ENCAP_ESPINUDP_NON_IKE	1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
 #define UDP_ENCAP_ESPINUDP	2 /* draft-ietf-ipsec-udp-encaps-06 */
+#define UDP_ENCAP_L2TPINUDP	3 /* rfc2661 */
 
 #ifdef __KERNEL__
 #include <linux/types.h>
@@ -70,6 +71,11 @@
 #define UDPLITE_SEND_CC  0x2  		/* set via udplite setsockopt         */
 #define UDPLITE_RECV_CC  0x4		/* set via udplite setsocktopt        */
 	__u8		 pcflag;        /* marks socket as UDP-Lite if > 0    */
+	__u8		 unused[3];
+	/*
+	 * For encapsulation sockets.
+	 */
+	int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
 };
 
 static inline struct udp_sock *udp_sk(const struct sock *sk)
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 94bd38a..56aa2ee 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -729,6 +729,22 @@
 	.bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
 
 /**
+ * USB_DEVICE_INTERFACE_PROTOCOL - macro used to describe a usb
+ *		device with a specific interface protocol
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ * @pr: bInterfaceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific interface protocol of devices.
+ */
+#define USB_DEVICE_INTERFACE_PROTOCOL(vend,prod,pr) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
+	.idVendor = (vend), \
+	.idProduct = (prod), \
+	.bInterfaceProtocol = (pr)
+
+/**
  * USB_DEVICE_INFO - macro used to describe a class of usb devices
  * @cl: bDeviceClass value
  * @sc: bDeviceSubClass value
diff --git a/include/linux/wait.h b/include/linux/wait.h
index e820d00..0e68628 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -366,15 +366,15 @@
 
 /*
  * These are the old interfaces to sleep waiting for an event.
- * They are racy.  DO NOT use them, use the wait_event* interfaces above.  
- * We plan to remove these interfaces during 2.7.
+ * They are racy.  DO NOT use them, use the wait_event* interfaces above.
+ * We plan to remove these interfaces.
  */
-extern void FASTCALL(sleep_on(wait_queue_head_t *q));
-extern long FASTCALL(sleep_on_timeout(wait_queue_head_t *q,
-				      signed long timeout));
-extern void FASTCALL(interruptible_sleep_on(wait_queue_head_t *q));
-extern long FASTCALL(interruptible_sleep_on_timeout(wait_queue_head_t *q,
-						    signed long timeout));
+extern void sleep_on(wait_queue_head_t *q);
+extern long sleep_on_timeout(wait_queue_head_t *q,
+				      signed long timeout);
+extern void interruptible_sleep_on(wait_queue_head_t *q);
+extern long interruptible_sleep_on_timeout(wait_queue_head_t *q,
+					   signed long timeout);
 
 /*
  * Waitqueues which are removed from the waitqueue_head at wakeup time
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 8b06c2f..2f0273f 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -19,7 +19,6 @@
 	struct gnet_stats_basic		tcfc_bstats;
 	struct gnet_stats_queue		tcfc_qstats;
 	struct gnet_stats_rate_est	tcfc_rate_est;
-	spinlock_t			*tcfc_stats_lock;
 	spinlock_t			tcfc_lock;
 };
 #define tcf_next	common.tcfc_next
@@ -32,7 +31,6 @@
 #define tcf_bstats	common.tcfc_bstats
 #define tcf_qstats	common.tcfc_qstats
 #define tcf_rate_est	common.tcfc_rate_est
-#define tcf_stats_lock	common.tcfc_stats_lock
 #define tcf_lock	common.tcfc_lock
 
 struct tcf_police {
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index f3531d0..33b593e 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -61,7 +61,7 @@
 extern int			ipv6_chk_addr(struct in6_addr *addr,
 					      struct net_device *dev,
 					      int strict);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 extern int			ipv6_chk_home_addr(struct in6_addr *addr);
 #endif
 extern struct inet6_ifaddr *	ipv6_get_ifaddr(struct in6_addr *addr,
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 65f49fd..6de1e9e 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -79,9 +79,10 @@
 	struct mutex		readlock;
         struct sock		*peer;
         struct sock		*other;
-        struct sock		*gc_tree;
+	struct list_head	link;
         atomic_t                inflight;
         spinlock_t		lock;
+	unsigned int		gc_candidate : 1;
         wait_queue_head_t       peer_wait;
 };
 #define unix_sk(__sk) ((struct unix_sock *)__sk)
diff --git a/include/net/ax88796.h b/include/net/ax88796.h
new file mode 100644
index 0000000..ee786a0
--- /dev/null
+++ b/include/net/ax88796.h
@@ -0,0 +1,27 @@
+/* include/net/ax88796.h
+ *
+ * Copyright 2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#ifndef __NET_AX88796_PLAT_H
+#define __NET_AX88796_PLAT_H
+
+#define AXFLG_HAS_EEPROM		(1<<0)
+#define AXFLG_MAC_FROMDEV		(1<<1)	/* device already has MAC */
+
+struct ax_plat_data {
+	unsigned int	 flags;
+	unsigned char	 wordlength;		/* 1 or 2 */
+	unsigned char	 dcr_val;		/* default value for DCR */
+	unsigned char	 rcr_val;		/* default value for RCR */
+	unsigned char	 gpoc_val;		/* default value for GPOC */
+	u32		*reg_offsets;		/* register offsets */
+};
+
+#endif /* __NET_AX88796_PLAT_H */
diff --git a/include/net/dn.h b/include/net/dn.h
index ac4ce90..6277783 100644
--- a/include/net/dn.h
+++ b/include/net/dn.h
@@ -3,7 +3,6 @@
 
 #include <linux/dn.h>
 #include <net/sock.h>
-#include <net/tcp.h>
 #include <asm/byteorder.h>
 
 #define dn_ntohs(x) le16_to_cpu(x)
diff --git a/include/net/dst.h b/include/net/dst.h
index 82270f9..e9ff4a4 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -47,7 +47,6 @@
 #define DST_NOXFRM		2
 #define DST_NOPOLICY		4
 #define DST_NOHASH		8
-#define DST_BALANCED            0x10
 	unsigned long		expires;
 
 	unsigned short		header_len;	/* more space at head required */
diff --git a/include/net/flow.h b/include/net/flow.h
index f3cc1f8..af59fa5 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -67,20 +67,16 @@
 
 		__be32		spi;
 
-#ifdef CONFIG_IPV6_MIP6
 		struct {
 			__u8	type;
 		} mht;
-#endif
 	} uli_u;
 #define fl_ip_sport	uli_u.ports.sport
 #define fl_ip_dport	uli_u.ports.dport
 #define fl_icmp_type	uli_u.icmpt.type
 #define fl_icmp_code	uli_u.icmpt.code
 #define fl_ipsec_spi	uli_u.spi
-#ifdef CONFIG_IPV6_MIP6
 #define fl_mh_type	uli_u.mht.type
-#endif
 	__u32           secid;	/* used by xfrm; see secid.txt */
 } __attribute__((__aligned__(BITS_PER_LONG/8)));
 
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 69252cb..8cadc77 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -39,7 +39,6 @@
 	int			fc_mx_len;
 	int			fc_mp_len;
 	u32			fc_flow;
-	u32			fc_mp_alg;
 	u32			fc_nlflags;
 	struct nl_info		fc_nlinfo;
  };
@@ -86,9 +85,6 @@
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 	int			fib_power;
 #endif
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	u32			fib_mp_alg;
-#endif
 	struct fib_nh		fib_nh[0];
 #define fib_dev		fib_nh[0].nh_dev
 };
@@ -103,10 +99,6 @@
 	unsigned char	nh_sel;
 	unsigned char	type;
 	unsigned char	scope;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	__be32          network;
-	__be32          netmask;
-#endif
 	struct fib_info *fi;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	struct fib_rule	*r;
@@ -145,14 +137,6 @@
 #define FIB_RES_DEV(res)		(FIB_RES_NH(res).nh_dev)
 #define FIB_RES_OIF(res)		(FIB_RES_NH(res).nh_oif)
 
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-#define FIB_RES_NETWORK(res)		((res).network)
-#define FIB_RES_NETMASK(res)	        ((res).netmask)
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
-#define FIB_RES_NETWORK(res)		(0)
-#define FIB_RES_NETMASK(res)	        (0)
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */
-
 struct fib_table {
 	struct hlist_node tb_hlist;
 	u32		tb_id;
diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h
deleted file mode 100644
index 25b5657..0000000
--- a/include/net/ip_mp_alg.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* ip_mp_alg.h: IPV4 multipath algorithm support.
- *
- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
- */
-
-#ifndef _NET_IP_MP_ALG_H
-#define _NET_IP_MP_ALG_H
-
-#include <linux/ip_mp_alg.h>
-#include <net/flow.h>
-#include <net/route.h>
-
-struct fib_nh;
-
-struct ip_mp_alg_ops {
-	void	(*mp_alg_select_route)(const struct flowi *flp,
-				       struct rtable *rth, struct rtable **rp);
-	void	(*mp_alg_flush)(void);
-	void	(*mp_alg_set_nhinfo)(__be32 network, __be32 netmask,
-				     unsigned char prefixlen,
-				     const struct fib_nh *nh);
-	void	(*mp_alg_remove)(struct rtable *rth);
-};
-
-extern int multipath_alg_register(struct ip_mp_alg_ops *, enum ip_mp_alg);
-extern void multipath_alg_unregister(struct ip_mp_alg_ops *, enum ip_mp_alg);
-
-extern struct ip_mp_alg_ops *ip_mp_alg_table[];
-
-static inline int multipath_select_route(const struct flowi *flp,
-					 struct rtable *rth,
-					 struct rtable **rp)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
-
-	/* mp_alg_select_route _MUST_ be implemented */
-	if (ops && (rth->u.dst.flags & DST_BALANCED)) {
-		ops->mp_alg_select_route(flp, rth, rp);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-static inline void multipath_flush(void)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	int i;
-
-	for (i = IP_MP_ALG_NONE; i <= IP_MP_ALG_MAX; i++) {
-		struct ip_mp_alg_ops *ops = ip_mp_alg_table[i];
-
-		if (ops && ops->mp_alg_flush)
-			ops->mp_alg_flush();
-	}
-#endif
-}
-
-static inline void multipath_set_nhinfo(struct rtable *rth,
-					__be32 network, __be32 netmask,
-					unsigned char prefixlen,
-					const struct fib_nh *nh)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
-
-	if (ops && ops->mp_alg_set_nhinfo)
-		ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh);
-#endif
-}
-
-static inline void multipath_remove(struct rtable *rth)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
-
-	if (ops && ops->mp_alg_remove &&
-	    (rth->u.dst.flags & DST_BALANCED))
-		ops->mp_alg_remove(rth);
-#endif
-}
-
-static inline int multipath_comparekeys(const struct flowi *flp1,
-					const struct flowi *flp2)
-{
-	return flp1->fl4_dst == flp2->fl4_dst &&
-		flp1->fl4_src == flp2->fl4_src &&
-		flp1->oif == flp2->oif &&
-		flp1->mark == flp2->mark &&
-		!((flp1->fl4_tos ^ flp2->fl4_tos) &
-		  (IPTOS_RT_MASK | RTO_ONLINK));
-}
-
-#endif /* _NET_IP_MP_ALG_H */
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 78a0d06..46b9dce 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -512,10 +512,6 @@
 
 extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
 
-extern struct ipv6_txoptions *	ipv6_invert_rthdr(struct sock *sk,
-						  struct ipv6_rt_hdr *hdr);
-
-
 /*
  *	socket options (ipv6_sockglue.c)
  */
diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h
index 36bee44..0838755 100644
--- a/include/net/irda/irda.h
+++ b/include/net/irda/irda.h
@@ -125,6 +125,9 @@
 extern int irsock_init(void);
 extern void irsock_cleanup(void);
 
+extern int irda_nl_register(void);
+extern void irda_nl_unregister(void);
+
 extern int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
 			    struct packet_type *ptype,
 			    struct net_device *orig_dev);
diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h
index a3d370e..9d0c78ea 100644
--- a/include/net/irda/irlap.h
+++ b/include/net/irda/irlap.h
@@ -208,6 +208,8 @@
 	int    xbofs_delay;   /* Nr of XBOF's used to MTT */
 	int    bofs_count;    /* Negotiated extra BOFs */
 	int    next_bofs;     /* Negotiated extra BOFs after next frame */
+
+	int    mode;     /* IrLAP mode (primary, secondary or monitor) */
 };
 
 /* 
diff --git a/include/net/mip6.h b/include/net/mip6.h
index 68263c6..6327261 100644
--- a/include/net/mip6.h
+++ b/include/net/mip6.h
@@ -54,8 +54,4 @@
 #define IP6_MH_TYPE_BERROR	7   /* Binding Error */
 #define IP6_MH_TYPE_MAX		IP6_MH_TYPE_BERROR
 
-extern int mip6_init(void);
-extern void mip6_fini(void);
-extern int mip6_mh_filter(struct sock *sk, struct sk_buff *skb);
-
 #endif
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 1401ccc..3ed4e14 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -9,29 +9,8 @@
 #ifndef _NF_CONNTRACK_IPV4_H
 #define _NF_CONNTRACK_IPV4_H
 
-#ifdef CONFIG_NF_NAT_NEEDED
-#include <net/netfilter/nf_nat.h>
-#include <linux/netfilter/nf_conntrack_pptp.h>
-
-/* per conntrack: nat application helper private data */
-union nf_conntrack_nat_help {
-        /* insert nat helper private data here */
-	struct nf_nat_pptp nat_pptp_info;
-};
-
-struct nf_conn_nat {
-	struct nf_nat_info info;
-	union nf_conntrack_nat_help help;
-#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
-	defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
-	int masq_index;
-#endif
-};
-#endif /* CONFIG_NF_NAT_NEEDED */
-
 /* Returns new sk_buff, or NULL */
-struct sk_buff *
-nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
+struct sk_buff *nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
 
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 4732432..d4f02eb 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -82,6 +82,8 @@
 
 	union nf_conntrack_help help;
 
+	struct hlist_head expectations;
+
 	/* Current number of expected connections */
 	unsigned int expecting;
 };
@@ -117,9 +119,6 @@
 	/* Unique ID that identifies this conntrack*/
 	unsigned int id;
 
-	/* features - nat, helper, ... used by allocating system */
-	u_int32_t features;
-
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	u_int32_t mark;
 #endif
@@ -131,8 +130,8 @@
 	/* Storage reserved for other modules: */
 	union nf_conntrack_proto proto;
 
-	/* features dynamically at the end: helper, nat (both optional) */
-	char data[0];
+	/* Extensions */
+	struct nf_ct_ext *ext;
 };
 
 static inline struct nf_conn *
@@ -175,6 +174,10 @@
 extern int nf_ct_l3proto_try_module_get(unsigned short l3proto);
 extern void nf_ct_l3proto_module_put(unsigned short l3proto);
 
+extern struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced);
+extern void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced,
+				 int size);
+
 extern struct nf_conntrack_tuple_hash *
 __nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
 		    const struct nf_conn *ignored_conntrack);
@@ -216,9 +219,6 @@
 				    struct nf_conn *conntrack,
 				    int dir);
 
-/* Call me when a conntrack is destroyed. */
-extern void (*nf_conntrack_destroyed)(struct nf_conn *conntrack);
-
 /* Fake conntrack entry for untracked connections */
 extern struct nf_conn nf_conntrack_untracked;
 
@@ -262,60 +262,10 @@
 	local_bh_enable();				\
 } while (0)
 
-/* no helper, no nat */
-#define	NF_CT_F_BASIC	0
-/* for helper */
-#define	NF_CT_F_HELP	1
-/* for nat. */
-#define	NF_CT_F_NAT	2
-#define NF_CT_F_NUM	4
-
 extern int
 nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size);
 extern void
 nf_conntrack_unregister_cache(u_int32_t features);
 
-/* valid combinations:
- * basic: nf_conn, nf_conn .. nf_conn_help
- * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat .. nf_conn help
- */
-#ifdef CONFIG_NF_NAT_NEEDED
-static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
-{
-	unsigned int offset = sizeof(struct nf_conn);
-
-	if (!(ct->features & NF_CT_F_NAT))
-		return NULL;
-
-	offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
-	return (struct nf_conn_nat *) ((void *)ct + offset);
-}
-
-static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
-{
-	unsigned int offset = sizeof(struct nf_conn);
-
-	if (!(ct->features & NF_CT_F_HELP))
-		return NULL;
-	if (ct->features & NF_CT_F_NAT) {
-		offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
-		offset += sizeof(struct nf_conn_nat);
-	}
-
-	offset = ALIGN(offset, __alignof__(struct nf_conn_help));
-	return (struct nf_conn_help *) ((void *)ct + offset);
-}
-#else /* No NAT */
-static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
-{
-	unsigned int offset = sizeof(struct nf_conn);
-
-	if (!(ct->features & NF_CT_F_HELP))
-		return NULL;
-
-	offset = ALIGN(offset, __alignof__(struct nf_conn_help));
-	return (struct nf_conn_help *) ((void *)ct + offset);
-}
-#endif /* CONFIG_NF_NAT_NEEDED */
 #endif /* __KERNEL__ */
 #endif /* _NF_CONNTRACK_H */
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index 9fb9066..4056f5f 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -30,6 +30,9 @@
 extern int nf_conntrack_proto_init(void);
 extern void nf_conntrack_proto_fini(void);
 
+extern int nf_conntrack_helper_init(void);
+extern void nf_conntrack_helper_fini(void);
+
 struct nf_conntrack_l3proto;
 extern struct nf_conntrack_l3proto *nf_ct_find_l3proto(u_int16_t pf);
 /* Like above, but you already have conntrack read lock. */
@@ -55,8 +58,7 @@
 
 /* Find a connection corresponding to a tuple. */
 extern struct nf_conntrack_tuple_hash *
-nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
-		      const struct nf_conn *ignored_conntrack);
+nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple);
 
 extern int __nf_conntrack_confirm(struct sk_buff **pskb);
 
@@ -81,9 +83,8 @@
 	    struct nf_conntrack_l3proto *l3proto,
 	    struct nf_conntrack_l4proto *proto);
 
-extern struct list_head *nf_conntrack_hash;
-extern struct list_head nf_conntrack_expect_list;
+extern struct hlist_head *nf_conntrack_hash;
 extern rwlock_t nf_conntrack_lock ;
-extern struct list_head unconfirmed;
+extern struct hlist_head unconfirmed;
 
 #endif /* _NF_CONNTRACK_CORE_H */
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 811c907..f0b9078 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -49,15 +49,15 @@
 		atomic_notifier_call_chain(&nf_conntrack_chain, event, ct);
 }
 
-extern struct atomic_notifier_head nf_conntrack_expect_chain;
-extern int nf_conntrack_expect_register_notifier(struct notifier_block *nb);
-extern int nf_conntrack_expect_unregister_notifier(struct notifier_block *nb);
+extern struct atomic_notifier_head nf_ct_expect_chain;
+extern int nf_ct_expect_register_notifier(struct notifier_block *nb);
+extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb);
 
 static inline void
-nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
-			  struct nf_conntrack_expect *exp)
+nf_ct_expect_event(enum ip_conntrack_expect_events event,
+		   struct nf_conntrack_expect *exp)
 {
-	atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
+	atomic_notifier_call_chain(&nf_ct_expect_chain, event, exp);
 }
 
 #else /* CONFIG_NF_CONNTRACK_EVENTS */
@@ -67,9 +67,8 @@
 static inline void nf_conntrack_event(enum ip_conntrack_events event,
 				      struct nf_conn *ct) {}
 static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
-static inline void
-nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
-			  struct nf_conntrack_expect *exp) {}
+static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event,
+				      struct nf_conntrack_expect *exp) {}
 static inline void nf_ct_event_cache_flush(void) {}
 #endif /* CONFIG_NF_CONNTRACK_EVENTS */
 
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 173c7c1..cae1a0d 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -6,17 +6,21 @@
 #define _NF_CONNTRACK_EXPECT_H
 #include <net/netfilter/nf_conntrack.h>
 
-extern struct list_head nf_conntrack_expect_list;
-extern struct kmem_cache *nf_conntrack_expect_cachep;
-extern const struct file_operations exp_file_ops;
+extern struct hlist_head *nf_ct_expect_hash;
+extern unsigned int nf_ct_expect_hsize;
+extern unsigned int nf_ct_expect_max;
 
 struct nf_conntrack_expect
 {
-	/* Internal linked list (global expectation list) */
-	struct list_head list;
+	/* Conntrack expectation list member */
+	struct hlist_node lnode;
+
+	/* Hash member */
+	struct hlist_node hnode;
 
 	/* We expect this tuple, with the following mask */
-	struct nf_conntrack_tuple tuple, mask;
+	struct nf_conntrack_tuple tuple;
+	struct nf_conntrack_tuple_mask mask;
 
 	/* Function to call after setup and insertion */
 	void (*expectfn)(struct nf_conn *new,
@@ -52,29 +56,31 @@
 
 #define NF_CT_EXPECT_PERMANENT 0x1
 
+int nf_conntrack_expect_init(void);
+void nf_conntrack_expect_fini(void);
 
 struct nf_conntrack_expect *
-__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+__nf_ct_expect_find(const struct nf_conntrack_tuple *tuple);
 
 struct nf_conntrack_expect *
-nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple);
+nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple);
 
 struct nf_conntrack_expect *
-find_expectation(const struct nf_conntrack_tuple *tuple);
+nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple);
 
 void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
 void nf_ct_remove_expectations(struct nf_conn *ct);
-void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp);
+void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
 
 /* Allocate space for an expectation: this is mandatory before calling
-   nf_conntrack_expect_related.  You will have to call put afterwards. */
-struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me);
-void nf_conntrack_expect_init(struct nf_conntrack_expect *, int,
-			      union nf_conntrack_address *,
-			      union nf_conntrack_address *,
-			      u_int8_t, __be16 *, __be16 *);
-void nf_conntrack_expect_put(struct nf_conntrack_expect *exp);
-int nf_conntrack_expect_related(struct nf_conntrack_expect *expect);
+   nf_ct_expect_related.  You will have to call put afterwards. */
+struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me);
+void nf_ct_expect_init(struct nf_conntrack_expect *, int,
+		       union nf_conntrack_address *,
+		       union nf_conntrack_address *,
+		       u_int8_t, __be16 *, __be16 *);
+void nf_ct_expect_put(struct nf_conntrack_expect *exp);
+int nf_ct_expect_related(struct nf_conntrack_expect *expect);
 
 #endif /*_NF_CONNTRACK_EXPECT_H*/
 
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
new file mode 100644
index 0000000..73b5711
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -0,0 +1,85 @@
+#ifndef _NF_CONNTRACK_EXTEND_H
+#define _NF_CONNTRACK_EXTEND_H
+
+#include <net/netfilter/nf_conntrack.h>
+
+enum nf_ct_ext_id
+{
+	NF_CT_EXT_HELPER,
+	NF_CT_EXT_NAT,
+	NF_CT_EXT_NUM,
+};
+
+#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
+#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
+
+/* Extensions: optional stuff which isn't permanently in struct. */
+struct nf_ct_ext {
+	u8 offset[NF_CT_EXT_NUM];
+	u8 len;
+	u8 real_len;
+	char data[0];
+};
+
+static inline int nf_ct_ext_exist(const struct nf_conn *ct, u8 id)
+{
+	return (ct->ext && ct->ext->offset[id]);
+}
+
+static inline void *__nf_ct_ext_find(const struct nf_conn *ct, u8 id)
+{
+	if (!nf_ct_ext_exist(ct, id))
+		return NULL;
+
+	return (void *)ct->ext + ct->ext->offset[id];
+}
+#define nf_ct_ext_find(ext, id)	\
+	((id##_TYPE *)__nf_ct_ext_find((ext), (id)))
+
+/* Destroy all relationships */
+extern void __nf_ct_ext_destroy(struct nf_conn *ct);
+static inline void nf_ct_ext_destroy(struct nf_conn *ct)
+{
+	if (ct->ext)
+		__nf_ct_ext_destroy(ct);
+}
+
+/* Free operation. If you want to free a object referred from private area,
+ * please implement __nf_ct_ext_free() and call it.
+ */
+static inline void nf_ct_ext_free(struct nf_conn *ct)
+{
+	if (ct->ext)
+		kfree(ct->ext);
+}
+
+/* Add this type, returns pointer to data or NULL. */
+void *
+__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp);
+#define nf_ct_ext_add(ct, id, gfp) \
+	((id##_TYPE *)__nf_ct_ext_add((ct), (id), (gfp)))
+
+#define NF_CT_EXT_F_PREALLOC	0x0001
+
+struct nf_ct_ext_type
+{
+	/* Destroys relationships (can be NULL). */
+	void (*destroy)(struct nf_conn *ct);
+	/* Called when realloacted (can be NULL).
+	   Contents has already been moved. */
+	void (*move)(struct nf_conn *ct, void *old);
+
+	enum nf_ct_ext_id id;
+
+	unsigned int flags;
+
+	/* Length and min alignment. */
+	u8 len;
+	u8 align;
+	/* initial size of nf_ct_ext. */
+	u8 alloc_size;
+};
+
+int nf_ct_extend_register(struct nf_ct_ext_type *type);
+void nf_ct_extend_unregister(struct nf_ct_ext_type *type);
+#endif /* _NF_CONNTRACK_EXTEND_H */
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 8c72ac9..d04f999 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -10,12 +10,13 @@
 #ifndef _NF_CONNTRACK_HELPER_H
 #define _NF_CONNTRACK_HELPER_H
 #include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 
 struct module;
 
 struct nf_conntrack_helper
-{	
-	struct list_head list; 		/* Internal use. */
+{
+	struct hlist_node hnode;	/* Internal use. */
 
 	const char *name;		/* name of the module */
 	struct module *me;		/* pointer to self */
@@ -23,10 +24,9 @@
 					 * expected connections */
 	unsigned int timeout;		/* timeout for expecteds */
 
-	/* Mask of things we will help (compared against server response) */
+	/* Tuple of things we will help (compared against server response) */
 	struct nf_conntrack_tuple tuple;
-	struct nf_conntrack_tuple mask;
-	
+
 	/* Function to call when data passes; return verdict, or -1 to
            invalidate. */
 	int (*help)(struct sk_buff **pskb,
@@ -52,4 +52,10 @@
 extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
 extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
 
+extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
+
+static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
+{
+	return nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
+}
 #endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 96a58d8..890752d 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -64,8 +64,6 @@
 	int (*prepare)(struct sk_buff **pskb, unsigned int hooknum,
 		       unsigned int *dataoff, u_int8_t *protonum);
 
-	u_int32_t (*get_features)(const struct nf_conntrack_tuple *tuple);
-
 	int (*tuple_to_nfattr)(struct sk_buff *skb,
 			       const struct nf_conntrack_tuple *t);
 
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
index 5d72b16..040dae5 100644
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -100,6 +100,14 @@
 	} dst;
 };
 
+struct nf_conntrack_tuple_mask
+{
+	struct {
+		union nf_conntrack_address u3;
+		union nf_conntrack_man_proto u;
+	} src;
+};
+
 /* This is optimized opposed to a memset of the whole structure.  Everything we
  * really care about is the  source/destination unions */
 #define NF_CT_TUPLE_U_BLANK(tuple)                              	\
@@ -112,11 +120,11 @@
 
 #ifdef __KERNEL__
 
-#define NF_CT_DUMP_TUPLE(tp)						    \
-DEBUGP("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n",	    \
-	(tp), (tp)->src.l3num, (tp)->dst.protonum,			    \
-	NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
-	NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
+#define NF_CT_DUMP_TUPLE(tp)						     \
+pr_debug("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n",	     \
+	 (tp), (tp)->src.l3num, (tp)->dst.protonum,			     \
+	 NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
+	 NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
 
 /* If we're the first tuple, it's the original dir. */
 #define NF_CT_DIRECTION(h)						\
@@ -125,8 +133,7 @@
 /* Connections have two entries in the hash table: one for each way */
 struct nf_conntrack_tuple_hash
 {
-	struct list_head list;
-
+	struct hlist_node hnode;
 	struct nf_conntrack_tuple tuple;
 };
 
@@ -162,31 +169,44 @@
 	return nf_ct_tuple_src_equal(t1, t2) && nf_ct_tuple_dst_equal(t1, t2);
 }
 
+static inline int nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
+					 const struct nf_conntrack_tuple_mask *m2)
+{
+	return (m1->src.u3.all[0] == m2->src.u3.all[0] &&
+		m1->src.u3.all[1] == m2->src.u3.all[1] &&
+		m1->src.u3.all[2] == m2->src.u3.all[2] &&
+		m1->src.u3.all[3] == m2->src.u3.all[3] &&
+		m1->src.u.all == m2->src.u.all);
+}
+
+static inline int nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1,
+					   const struct nf_conntrack_tuple *t2,
+					   const struct nf_conntrack_tuple_mask *mask)
+{
+	int count;
+
+	for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++) {
+		if ((t1->src.u3.all[count] ^ t2->src.u3.all[count]) &
+		    mask->src.u3.all[count])
+			return 0;
+	}
+
+	if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all)
+		return 0;
+
+	if (t1->src.l3num != t2->src.l3num ||
+	    t1->dst.protonum != t2->dst.protonum)
+		return 0;
+
+	return 1;
+}
+
 static inline int nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
 				       const struct nf_conntrack_tuple *tuple,
-				       const struct nf_conntrack_tuple *mask)
+				       const struct nf_conntrack_tuple_mask *mask)
 {
-	int count = 0;
-
-        for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
-                if ((t->src.u3.all[count] ^ tuple->src.u3.all[count]) &
-                    mask->src.u3.all[count])
-                        return 0;
-        }
-
-        for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
-                if ((t->dst.u3.all[count] ^ tuple->dst.u3.all[count]) &
-                    mask->dst.u3.all[count])
-                        return 0;
-        }
-
-        if ((t->src.u.all ^ tuple->src.u.all) & mask->src.u.all ||
-            (t->dst.u.all ^ tuple->dst.u.all) & mask->dst.u.all ||
-            (t->src.l3num ^ tuple->src.l3num) & mask->src.l3num ||
-            (t->dst.protonum ^ tuple->dst.protonum) & mask->dst.protonum)
-                return 0;
-
-        return 1;
+	return nf_ct_tuple_src_mask_cmp(t, tuple, mask) &&
+	       nf_ct_tuple_dst_equal(t, tuple);
 }
 
 #endif /* _NF_CONNTRACK_TUPLE_H */
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index bc57dd7..6ae52f7 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -51,16 +51,31 @@
 
 #ifdef __KERNEL__
 #include <linux/list.h>
+#include <linux/netfilter/nf_conntrack_pptp.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 
-/* The structure embedded in the conntrack structure. */
-struct nf_nat_info
+/* per conntrack: nat application helper private data */
+union nf_conntrack_nat_help
 {
-	struct list_head bysource;
-	struct nf_nat_seq seq[IP_CT_DIR_MAX];
+	/* insert nat helper private data here */
+	struct nf_nat_pptp nat_pptp_info;
 };
 
 struct nf_conn;
 
+/* The structure embedded in the conntrack structure. */
+struct nf_conn_nat
+{
+	struct hlist_node bysource;
+	struct nf_nat_seq seq[IP_CT_DIR_MAX];
+	struct nf_conn *ct;
+	union nf_conntrack_nat_help help;
+#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
+    defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
+	int masq_index;
+#endif
+};
+
 /* Set up the info structure to map into this range. */
 extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
 				      const struct nf_nat_range *range,
@@ -70,7 +85,10 @@
 extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
 			     const struct nf_conn *ignored_conntrack);
 
-extern int nf_nat_module_is_loaded;
+static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
+{
+	return nf_ct_ext_find(ct, NF_CT_EXT_NAT);
+}
 
 #else  /* !__KERNEL__: iptables wants this to compile. */
 #define nf_nat_multi_range nf_nat_multi_range_compat
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h
index 9778ffa..c3cd127 100644
--- a/include/net/netfilter/nf_nat_core.h
+++ b/include/net/netfilter/nf_nat_core.h
@@ -2,6 +2,7 @@
 #define _NF_NAT_CORE_H
 #include <linux/list.h>
 #include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat.h>
 
 /* This header used to share core functionality between the standalone
    NAT module, and the compatibility layer's use of NAT for masquerading. */
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 7b510a9..d7b824b 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -118,6 +118,9 @@
  * Nested Attributes Construction:
  *   nla_nest_start(skb, type)		start a nested attribute
  *   nla_nest_end(skb, nla)		finalize a nested attribute
+ *   nla_nest_compat_start(skb, type,	start a nested compat attribute
+ *			   len, data)
+ *   nla_nest_compat_end(skb, type)	finalize a nested compat attribute
  *   nla_nest_cancel(skb, nla)		cancel nested attribute construction
  *
  * Attribute Length Calculations:
@@ -152,6 +155,7 @@
  *   nla_find_nested()			find attribute in nested attributes
  *   nla_parse()			parse and validate stream of attrs
  *   nla_parse_nested()			parse nested attribuets
+ *   nla_parse_nested_compat()		parse nested compat attributes
  *   nla_for_each_attr()		loop over all attributes
  *   nla_for_each_nested()		loop over the nested attributes
  *=========================================================================
@@ -170,6 +174,7 @@
 	NLA_FLAG,
 	NLA_MSECS,
 	NLA_NESTED,
+	NLA_NESTED_COMPAT,
 	NLA_NUL_STRING,
 	NLA_BINARY,
 	__NLA_TYPE_MAX,
@@ -190,6 +195,7 @@
  *    NLA_NUL_STRING       Maximum length of string (excluding NUL)
  *    NLA_FLAG             Unused
  *    NLA_BINARY           Maximum length of attribute payload
+ *    NLA_NESTED_COMPAT    Exact length of structure payload
  *    All other            Exact length of attribute payload
  *
  * Example:
@@ -733,6 +739,39 @@
 {
 	return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
 }
+
+/**
+ * nla_parse_nested_compat - parse nested compat attributes
+ * @tb: destination array with maxtype+1 elements
+ * @maxtype: maximum attribute type to be expected
+ * @nla: attribute containing the nested attributes
+ * @data: pointer to point to contained structure
+ * @len: length of contained structure
+ * @policy: validation policy
+ *
+ * Parse a nested compat attribute. The compat attribute contains a structure
+ * and optionally a set of nested attributes. On success the data pointer
+ * points to the nested data and tb contains the parsed attributes
+ * (see nla_parse).
+ */
+static inline int __nla_parse_nested_compat(struct nlattr *tb[], int maxtype,
+					    struct nlattr *nla,
+					    const struct nla_policy *policy,
+					    int len)
+{
+	if (nla_len(nla) < len)
+		return -1;
+	if (nla_len(nla) >= NLA_ALIGN(len) + sizeof(struct nlattr))
+		return nla_parse_nested(tb, maxtype,
+					nla_data(nla) + NLA_ALIGN(len),
+					policy);
+	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
+	return 0;
+}
+
+#define nla_parse_nested_compat(tb, maxtype, nla, policy, data, len) \
+({	data = nla_len(nla) >= len ? nla_data(nla) : NULL; \
+	__nla_parse_nested_compat(tb, maxtype, nla, policy, len); })
 /**
  * nla_put_u8 - Add a u16 netlink attribute to a socket buffer
  * @skb: socket buffer to add attribute to
@@ -965,6 +1004,51 @@
 }
 
 /**
+ * nla_nest_compat_start - Start a new level of nested compat attributes
+ * @skb: socket buffer to add attributes to
+ * @attrtype: attribute type of container
+ * @attrlen: length of structure
+ * @data: pointer to structure
+ *
+ * Start a nested compat attribute that contains both a structure and
+ * a set of nested attributes.
+ *
+ * Returns the container attribute
+ */
+static inline struct nlattr *nla_nest_compat_start(struct sk_buff *skb,
+						   int attrtype, int attrlen,
+						   const void *data)
+{
+	struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb);
+
+	if (nla_put(skb, attrtype, attrlen, data) < 0)
+		return NULL;
+	if (nla_nest_start(skb, attrtype) == NULL) {
+		nlmsg_trim(skb, start);
+		return NULL;
+	}
+	return start;
+}
+
+/**
+ * nla_nest_compat_end - Finalize nesting of compat attributes
+ * @skb: socket buffer the attribtues are stored in
+ * @start: container attribute
+ *
+ * Corrects the container attribute header to include the all
+ * appeneded attributes.
+ *
+ * Returns the total data length of the skb.
+ */
+static inline int nla_nest_compat_end(struct sk_buff *skb, struct nlattr *start)
+{
+	struct nlattr *nest = (void *)start + NLMSG_ALIGN(start->nla_len);
+
+	start->nla_len = skb_tail_pointer(skb) - (unsigned char *)start;
+	return nla_nest_end(skb, nest);
+}
+
+/**
  * nla_nest_cancel - Cancel nesting of attributes
  * @skb: socket buffer the message is stored in
  * @start: container attribute
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index af89608..a581989 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -3,6 +3,8 @@
 
 #ifdef __KERNEL__
 
+#include <net/protocol.h>
+
 #define RAWV6_HTABLE_SIZE	MAX_INET_PROTOS
 extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE];
 extern rwlock_t raw_v6_lock;
@@ -23,6 +25,13 @@
 					  int type, int code, 
 					  int offset, __be32 info);
 
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
+					   struct sk_buff *skb));
+int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
+					     struct sk_buff *skb));
+#endif
+
 #endif
 
 #endif
diff --git a/include/net/route.h b/include/net/route.h
index 749e4df..f7ce625 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -62,7 +62,6 @@
 	
 	unsigned		rt_flags;
 	__u16			rt_type;
-	__u16			rt_multipath_alg;
 
 	__be32			rt_dst;	/* Path destination	*/
 	__be32			rt_src;	/* Path source		*/
@@ -136,7 +135,7 @@
 
 #define IPTOS_RT_MASK	(IPTOS_TOS_MASK & ~3)
 
-extern __u8 ip_tos2prio[16];
+extern const __u8 ip_tos2prio[16];
 
 static inline char rt_tos2priority(u8 tos)
 {
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 3b3d474..3861c05 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -22,4 +22,62 @@
 		return AF_UNSPEC;
 }
 
+/**
+ *	struct rtnl_link_ops - rtnetlink link operations
+ *
+ *	@list: Used internally
+ *	@kind: Identifier
+ *	@maxtype: Highest device specific netlink attribute number
+ *	@policy: Netlink policy for device specific attribute validation
+ *	@validate: Optional validation function for netlink/changelink parameters
+ *	@priv_size: sizeof net_device private space
+ *	@setup: net_device setup function
+ *	@newlink: Function for configuring and registering a new device
+ *	@changelink: Function for changing parameters of an existing device
+ *	@dellink: Function to remove a device
+ *	@get_size: Function to calculate required room for dumping device
+ *		   specific netlink attributes
+ *	@fill_info: Function to dump device specific netlink attributes
+ *	@get_xstats_size: Function to calculate required room for dumping devic
+ *			  specific statistics
+ *	@fill_xstats: Function to dump device specific statistics
+ */
+struct rtnl_link_ops {
+	struct list_head	list;
+
+	const char		*kind;
+
+	size_t			priv_size;
+	void			(*setup)(struct net_device *dev);
+
+	int			maxtype;
+	const struct nla_policy	*policy;
+	int			(*validate)(struct nlattr *tb[],
+					    struct nlattr *data[]);
+
+	int			(*newlink)(struct net_device *dev,
+					   struct nlattr *tb[],
+					   struct nlattr *data[]);
+	int			(*changelink)(struct net_device *dev,
+					      struct nlattr *tb[],
+					      struct nlattr *data[]);
+	void			(*dellink)(struct net_device *dev);
+
+	size_t			(*get_size)(const struct net_device *dev);
+	int			(*fill_info)(struct sk_buff *skb,
+					     const struct net_device *dev);
+
+	size_t			(*get_xstats_size)(const struct net_device *dev);
+	int			(*fill_xstats)(struct sk_buff *skb,
+					       const struct net_device *dev);
+};
+
+extern int	__rtnl_link_register(struct rtnl_link_ops *ops);
+extern void	__rtnl_link_unregister(struct rtnl_link_ops *ops);
+
+extern int	rtnl_link_register(struct rtnl_link_ops *ops);
+extern void	rtnl_link_unregister(struct rtnl_link_ops *ops);
+
+#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
+
 #endif
diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h
index 333bba6..cfc4ba4 100644
--- a/include/net/tipc/tipc_port.h
+++ b/include/net/tipc/tipc_port.h
@@ -1,8 +1,8 @@
 /*
  * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports
  * 
- * Copyright (c) 1994-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 1994-2007, Ericsson AB
+ * Copyright (c) 2005-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -55,6 +55,7 @@
  * @conn_unacked: number of unacknowledged messages received from peer port
  * @published: non-zero if port has one or more associated names
  * @congested: non-zero if cannot send because of link or port congestion
+ * @max_pkt: maximum packet size "hint" used when building messages sent by port
  * @ref: unique reference to port in TIPC object registry
  * @phdr: preformatted message header used when sending messages
  */
@@ -68,6 +69,7 @@
 	u32 conn_unacked;
 	int published;
 	u32 congested;
+	u32 max_pkt;
 	u32 ref;
 	struct tipc_msg phdr;
 };
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 311f25a..ae959e9 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -19,9 +19,19 @@
 #include <net/ipv6.h>
 #include <net/ip6_fib.h>
 
+#define XFRM_PROTO_ESP		50
+#define XFRM_PROTO_AH		51
+#define XFRM_PROTO_COMP		108
+#define XFRM_PROTO_IPIP		4
+#define XFRM_PROTO_IPV6		41
+#define XFRM_PROTO_ROUTING	IPPROTO_ROUTING
+#define XFRM_PROTO_DSTOPTS	IPPROTO_DSTOPTS
+
 #define XFRM_ALIGN8(len)	(((len) + 7) & ~7)
 #define MODULE_ALIAS_XFRM_MODE(family, encap) \
 	MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
+#define MODULE_ALIAS_XFRM_TYPE(family, proto) \
+	MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto))
 
 extern struct sock *xfrm_nl;
 extern u32 sysctl_xfrm_aevent_etime;
@@ -509,11 +519,9 @@
 	case IPPROTO_ICMPV6:
 		port = htons(fl->fl_icmp_type);
 		break;
-#ifdef CONFIG_IPV6_MIP6
 	case IPPROTO_MH:
 		port = htons(fl->fl_mh_type);
 		break;
-#endif
 	default:
 		port = 0;	/*XXX*/
 	}
@@ -920,6 +928,10 @@
 					  struct flowi *fl, struct xfrm_tmpl *tmpl,
 					  struct xfrm_policy *pol, int *err,
 					  unsigned short family);
+extern struct xfrm_state * xfrm_stateonly_find(xfrm_address_t *daddr,
+					       xfrm_address_t *saddr,
+					       unsigned short family,
+					       u8 mode, u8 proto, u32 reqid);
 extern int xfrm_state_check_expire(struct xfrm_state *x);
 extern void xfrm_state_insert(struct xfrm_state *x);
 extern int xfrm_state_add(struct xfrm_state *x);
@@ -991,7 +1003,7 @@
 				 u8 **prevhdr);
 
 #ifdef CONFIG_XFRM
-extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
+extern int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
 extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen);
 extern int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family);
 #else
@@ -1000,12 +1012,13 @@
  	return -ENOPROTOOPT;
 } 
 
-static inline int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
+static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
 {
  	/* should not happen */
  	kfree_skb(skb);
 	return 0;
 }
+
 static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family)
 {
 	return -EINVAL;
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index eae7e2e..ad6e278 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -126,4 +126,6 @@
 #define MANFID_POSSIO			0x030c
 #define PRODID_POSSIO_GCC		0x0003
 
+#define MANFID_NEC			0x0010
+
 #endif /* _LINUX_CISCODE_H */
diff --git a/init/Kconfig b/init/Kconfig
index a9e99f8..d9d878a 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -686,6 +686,4 @@
 	  Need stop_machine() primitive.
 endmenu
 
-menu "Block layer"
 source "block/Kconfig"
-endmenu
diff --git a/init/main.c b/init/main.c
index eb8bdba..0eb1c74 100644
--- a/init/main.c
+++ b/init/main.c
@@ -436,15 +436,16 @@
 
 	/*
 	 * The boot idle thread must execute schedule()
-	 * at least one to get things moving:
+	 * at least once to get things moving:
 	 */
+	init_idle_bootup_task(current);
 	preempt_enable_no_resched();
 	schedule();
 	preempt_disable();
 
 	/* Call into cpu_idle with preempt disabled */
 	cpu_idle();
-} 
+}
 
 /* Check for early params. */
 static int __init do_early_param(char *param, char *val)
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index c0148ae..81e6978 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -99,9 +99,10 @@
 int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
 {
 	s64 tmp;
-	struct timespec ts;
-	unsigned long t1,t2,t3;
+	unsigned long t1;
+	unsigned long long t2, t3;
 	unsigned long flags;
+	struct timespec ts;
 
 	/* Though tsk->delays accessed later, early exit avoids
 	 * unnecessary returning of other data
@@ -124,11 +125,10 @@
 
 	d->cpu_count += t1;
 
-	jiffies_to_timespec(t2, &ts);
-	tmp = (s64)d->cpu_delay_total + timespec_to_ns(&ts);
+	tmp = (s64)d->cpu_delay_total + t2;
 	d->cpu_delay_total = (tmp < (s64)d->cpu_delay_total) ? 0 : tmp;
 
-	tmp = (s64)d->cpu_run_virtual_total + (s64)jiffies_to_usecs(t3) * 1000;
+	tmp = (s64)d->cpu_run_virtual_total + t3;
 	d->cpu_run_virtual_total =
 		(tmp < (s64)d->cpu_run_virtual_total) ?	0 : tmp;
 
diff --git a/kernel/exit.c b/kernel/exit.c
index 5c8ecba..ca6a11b 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -122,9 +122,9 @@
 		sig->maj_flt += tsk->maj_flt;
 		sig->nvcsw += tsk->nvcsw;
 		sig->nivcsw += tsk->nivcsw;
-		sig->sched_time += tsk->sched_time;
 		sig->inblock += task_io_get_inblock(tsk);
 		sig->oublock += task_io_get_oublock(tsk);
+		sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
 		sig = NULL; /* Marker for below. */
 	}
 
@@ -182,7 +182,6 @@
 		zap_leader = (leader->exit_signal == -1);
 	}
 
-	sched_exit(p);
 	write_unlock_irq(&tasklist_lock);
 	proc_flush_task(p);
 	release_thread(p);
@@ -291,7 +290,7 @@
 	/* Set the exit signal to SIGCHLD so we signal init on exit */
 	current->exit_signal = SIGCHLD;
 
-	if (!has_rt_policy(current) && (task_nice(current) < 0))
+	if (task_nice(current) < 0)
 		set_user_nice(current, 0);
 	/* cpus_allowed? */
 	/* rt_priority? */
diff --git a/kernel/fork.c b/kernel/fork.c
index 73ad5cd..da3a155 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -877,7 +877,7 @@
 	sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
 	sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
 	sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
-	sig->sched_time = 0;
+	sig->sum_sched_runtime = 0;
 	INIT_LIST_HEAD(&sig->cpu_timers[0]);
 	INIT_LIST_HEAD(&sig->cpu_timers[1]);
 	INIT_LIST_HEAD(&sig->cpu_timers[2]);
@@ -1040,7 +1040,7 @@
 
 	p->utime = cputime_zero;
 	p->stime = cputime_zero;
- 	p->sched_time = 0;
+
 #ifdef CONFIG_TASK_XACCT
 	p->rchar = 0;		/* I/O counter: bytes read */
 	p->wchar = 0;		/* I/O counter: bytes written */
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 1de710e1..b53c8fc 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -161,7 +161,7 @@
 }
 static inline unsigned long long sched_ns(struct task_struct *p)
 {
-	return (p == current) ? current_sched_time(p) : p->sched_time;
+	return task_sched_runtime(p);
 }
 
 int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
@@ -246,10 +246,10 @@
 		} while (t != p);
 		break;
 	case CPUCLOCK_SCHED:
-		cpu->sched = p->signal->sched_time;
+		cpu->sched = p->signal->sum_sched_runtime;
 		/* Add in each other live thread.  */
 		while ((t = next_thread(t)) != p) {
-			cpu->sched += t->sched_time;
+			cpu->sched += t->se.sum_exec_runtime;
 		}
 		cpu->sched += sched_ns(p);
 		break;
@@ -422,7 +422,7 @@
  */
 static void cleanup_timers(struct list_head *head,
 			   cputime_t utime, cputime_t stime,
-			   unsigned long long sched_time)
+			   unsigned long long sum_exec_runtime)
 {
 	struct cpu_timer_list *timer, *next;
 	cputime_t ptime = cputime_add(utime, stime);
@@ -451,10 +451,10 @@
 	++head;
 	list_for_each_entry_safe(timer, next, head, entry) {
 		list_del_init(&timer->entry);
-		if (timer->expires.sched < sched_time) {
+		if (timer->expires.sched < sum_exec_runtime) {
 			timer->expires.sched = 0;
 		} else {
-			timer->expires.sched -= sched_time;
+			timer->expires.sched -= sum_exec_runtime;
 		}
 	}
 }
@@ -467,7 +467,7 @@
 void posix_cpu_timers_exit(struct task_struct *tsk)
 {
 	cleanup_timers(tsk->cpu_timers,
-		       tsk->utime, tsk->stime, tsk->sched_time);
+		       tsk->utime, tsk->stime, tsk->se.sum_exec_runtime);
 
 }
 void posix_cpu_timers_exit_group(struct task_struct *tsk)
@@ -475,7 +475,7 @@
 	cleanup_timers(tsk->signal->cpu_timers,
 		       cputime_add(tsk->utime, tsk->signal->utime),
 		       cputime_add(tsk->stime, tsk->signal->stime),
-		       tsk->sched_time + tsk->signal->sched_time);
+		     tsk->se.sum_exec_runtime + tsk->signal->sum_sched_runtime);
 }
 
 
@@ -536,7 +536,7 @@
 		nsleft = max_t(unsigned long long, nsleft, 1);
 		do {
 			if (likely(!(t->flags & PF_EXITING))) {
-				ns = t->sched_time + nsleft;
+				ns = t->se.sum_exec_runtime + nsleft;
 				if (t->it_sched_expires == 0 ||
 				    t->it_sched_expires > ns) {
 					t->it_sched_expires = ns;
@@ -1004,7 +1004,7 @@
 		struct cpu_timer_list *t = list_first_entry(timers,
 						      struct cpu_timer_list,
 						      entry);
-		if (!--maxfire || tsk->sched_time < t->expires.sched) {
+		if (!--maxfire || tsk->se.sum_exec_runtime < t->expires.sched) {
 			tsk->it_sched_expires = t->expires.sched;
 			break;
 		}
@@ -1024,7 +1024,7 @@
 	int maxfire;
 	struct signal_struct *const sig = tsk->signal;
 	cputime_t utime, stime, ptime, virt_expires, prof_expires;
-	unsigned long long sched_time, sched_expires;
+	unsigned long long sum_sched_runtime, sched_expires;
 	struct task_struct *t;
 	struct list_head *timers = sig->cpu_timers;
 
@@ -1044,12 +1044,12 @@
 	 */
 	utime = sig->utime;
 	stime = sig->stime;
-	sched_time = sig->sched_time;
+	sum_sched_runtime = sig->sum_sched_runtime;
 	t = tsk;
 	do {
 		utime = cputime_add(utime, t->utime);
 		stime = cputime_add(stime, t->stime);
-		sched_time += t->sched_time;
+		sum_sched_runtime += t->se.sum_exec_runtime;
 		t = next_thread(t);
 	} while (t != tsk);
 	ptime = cputime_add(utime, stime);
@@ -1090,7 +1090,7 @@
 		struct cpu_timer_list *t = list_first_entry(timers,
 						      struct cpu_timer_list,
 						      entry);
-		if (!--maxfire || sched_time < t->expires.sched) {
+		if (!--maxfire || sum_sched_runtime < t->expires.sched) {
 			sched_expires = t->expires.sched;
 			break;
 		}
@@ -1182,7 +1182,7 @@
 		virt_left = cputime_sub(virt_expires, utime);
 		virt_left = cputime_div_non_zero(virt_left, nthreads);
 		if (sched_expires) {
-			sched_left = sched_expires - sched_time;
+			sched_left = sched_expires - sum_sched_runtime;
 			do_div(sched_left, nthreads);
 			sched_left = max_t(unsigned long long, sched_left, 1);
 		} else {
@@ -1208,7 +1208,7 @@
 				t->it_virt_expires = ticks;
 			}
 
-			sched = t->sched_time + sched_left;
+			sched = t->se.sum_exec_runtime + sched_left;
 			if (sched_expires && (t->it_sched_expires == 0 ||
 					      t->it_sched_expires > sched)) {
 				t->it_sched_expires = sched;
@@ -1300,7 +1300,7 @@
 
 	if (UNEXPIRED(prof) && UNEXPIRED(virt) &&
 	    (tsk->it_sched_expires == 0 ||
-	     tsk->sched_time < tsk->it_sched_expires))
+	     tsk->se.sum_exec_runtime < tsk->it_sched_expires))
 		return;
 
 #undef	UNEXPIRED
diff --git a/kernel/relay.c b/kernel/relay.c
index 95db8c7..3b299fb 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -21,6 +21,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/cpu.h>
+#include <linux/splice.h>
 
 /* list of open channels, for cpu hotplug */
 static DEFINE_MUTEX(relay_channels_mutex);
@@ -121,6 +122,7 @@
 		buf->page_array[i] = alloc_page(GFP_KERNEL);
 		if (unlikely(!buf->page_array[i]))
 			goto depopulate;
+		set_page_private(buf->page_array[i], (unsigned long)buf);
 	}
 	mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL);
 	if (!mem)
@@ -970,43 +972,6 @@
 	return ret;
 }
 
-/*
- *	subbuf_send_actor - send up to one subbuf's worth of data
- */
-static int subbuf_send_actor(size_t read_start,
-			     struct rchan_buf *buf,
-			     size_t avail,
-			     read_descriptor_t *desc,
-			     read_actor_t actor)
-{
-	unsigned long pidx, poff;
-	unsigned int subbuf_pages;
-	int ret = 0;
-
-	subbuf_pages = buf->chan->alloc_size >> PAGE_SHIFT;
-	pidx = (read_start / PAGE_SIZE) % subbuf_pages;
-	poff = read_start & ~PAGE_MASK;
-	while (avail) {
-		struct page *p = buf->page_array[pidx];
-		unsigned int len;
-
-		len = PAGE_SIZE - poff;
-		if (len > avail)
-			len = avail;
-
-		len = actor(desc, p, poff, len);
-		if (desc->error)
-			break;
-
-		avail -= len;
-		ret += len;
-		poff = 0;
-		pidx = (pidx + 1) % subbuf_pages;
-	}
-
-	return ret;
-}
-
 typedef int (*subbuf_actor_t) (size_t read_start,
 			       struct rchan_buf *buf,
 			       size_t avail,
@@ -1067,19 +1032,159 @@
 				       NULL, &desc);
 }
 
-static ssize_t relay_file_sendfile(struct file *filp,
-				   loff_t *ppos,
-				   size_t count,
-				   read_actor_t actor,
-				   void *target)
+static void relay_consume_bytes(struct rchan_buf *rbuf, int bytes_consumed)
 {
-	read_descriptor_t desc;
-	desc.written = 0;
-	desc.count = count;
-	desc.arg.data = target;
-	desc.error = 0;
-	return relay_file_read_subbufs(filp, ppos, subbuf_send_actor,
-				       actor, &desc);
+	rbuf->bytes_consumed += bytes_consumed;
+
+	if (rbuf->bytes_consumed >= rbuf->chan->subbuf_size) {
+		relay_subbufs_consumed(rbuf->chan, rbuf->cpu, 1);
+		rbuf->bytes_consumed %= rbuf->chan->subbuf_size;
+	}
+}
+
+static void relay_pipe_buf_release(struct pipe_inode_info *pipe,
+				   struct pipe_buffer *buf)
+{
+	struct rchan_buf *rbuf;
+
+	rbuf = (struct rchan_buf *)page_private(buf->page);
+	relay_consume_bytes(rbuf, buf->private);
+}
+
+static struct pipe_buf_operations relay_pipe_buf_ops = {
+	.can_merge = 0,
+	.map = generic_pipe_buf_map,
+	.unmap = generic_pipe_buf_unmap,
+	.confirm = generic_pipe_buf_confirm,
+	.release = relay_pipe_buf_release,
+	.steal = generic_pipe_buf_steal,
+	.get = generic_pipe_buf_get,
+};
+
+/**
+ *	subbuf_splice_actor - splice up to one subbuf's worth of data
+ */
+static int subbuf_splice_actor(struct file *in,
+			       loff_t *ppos,
+			       struct pipe_inode_info *pipe,
+			       size_t len,
+			       unsigned int flags,
+			       int *nonpad_ret)
+{
+	unsigned int pidx, poff, total_len, subbuf_pages, ret;
+	struct rchan_buf *rbuf = in->private_data;
+	unsigned int subbuf_size = rbuf->chan->subbuf_size;
+	size_t read_start = ((size_t)*ppos) % rbuf->chan->alloc_size;
+	size_t read_subbuf = read_start / subbuf_size;
+	size_t padding = rbuf->padding[read_subbuf];
+	size_t nonpad_end = read_subbuf * subbuf_size + subbuf_size - padding;
+	struct page *pages[PIPE_BUFFERS];
+	struct partial_page partial[PIPE_BUFFERS];
+	struct splice_pipe_desc spd = {
+		.pages = pages,
+		.nr_pages = 0,
+		.partial = partial,
+		.flags = flags,
+		.ops = &relay_pipe_buf_ops,
+	};
+
+	if (rbuf->subbufs_produced == rbuf->subbufs_consumed)
+		return 0;
+
+	/*
+	 * Adjust read len, if longer than what is available
+	 */
+	if (len > (subbuf_size - read_start % subbuf_size))
+		len = subbuf_size - read_start % subbuf_size;
+
+	subbuf_pages = rbuf->chan->alloc_size >> PAGE_SHIFT;
+	pidx = (read_start / PAGE_SIZE) % subbuf_pages;
+	poff = read_start & ~PAGE_MASK;
+
+	for (total_len = 0; spd.nr_pages < subbuf_pages; spd.nr_pages++) {
+		unsigned int this_len, this_end, private;
+		unsigned int cur_pos = read_start + total_len;
+
+		if (!len)
+			break;
+
+		this_len = min_t(unsigned long, len, PAGE_SIZE - poff);
+		private = this_len;
+
+		spd.pages[spd.nr_pages] = rbuf->page_array[pidx];
+		spd.partial[spd.nr_pages].offset = poff;
+
+		this_end = cur_pos + this_len;
+		if (this_end >= nonpad_end) {
+			this_len = nonpad_end - cur_pos;
+			private = this_len + padding;
+		}
+		spd.partial[spd.nr_pages].len = this_len;
+		spd.partial[spd.nr_pages].private = private;
+
+		len -= this_len;
+		total_len += this_len;
+		poff = 0;
+		pidx = (pidx + 1) % subbuf_pages;
+
+		if (this_end >= nonpad_end) {
+			spd.nr_pages++;
+			break;
+		}
+	}
+
+	if (!spd.nr_pages)
+		return 0;
+
+	ret = *nonpad_ret = splice_to_pipe(pipe, &spd);
+	if (ret < 0 || ret < total_len)
+		return ret;
+
+        if (read_start + ret == nonpad_end)
+                ret += padding;
+
+        return ret;
+}
+
+static ssize_t relay_file_splice_read(struct file *in,
+				      loff_t *ppos,
+				      struct pipe_inode_info *pipe,
+				      size_t len,
+				      unsigned int flags)
+{
+	ssize_t spliced;
+	int ret;
+	int nonpad_ret = 0;
+
+	ret = 0;
+	spliced = 0;
+
+	while (len) {
+		ret = subbuf_splice_actor(in, ppos, pipe, len, flags, &nonpad_ret);
+		if (ret < 0)
+			break;
+		else if (!ret) {
+			if (spliced)
+				break;
+			if (flags & SPLICE_F_NONBLOCK) {
+				ret = -EAGAIN;
+				break;
+			}
+		}
+
+		*ppos += ret;
+		if (ret > len)
+			len = 0;
+		else
+			len -= ret;
+		spliced += nonpad_ret;
+		nonpad_ret = 0;
+	}
+
+	if (spliced)
+		return spliced;
+
+	return ret;
 }
 
 const struct file_operations relay_file_operations = {
@@ -1089,7 +1194,7 @@
 	.read		= relay_file_read,
 	.llseek		= no_llseek,
 	.release	= relay_file_release,
-	.sendfile       = relay_file_sendfile,
+	.splice_read	= relay_file_splice_read,
 };
 EXPORT_SYMBOL_GPL(relay_file_operations);
 
diff --git a/kernel/sched.c b/kernel/sched.c
index 50e1a31..9fbced6 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -16,13 +16,19 @@
  *		by Davide Libenzi, preemptible kernel bits by Robert Love.
  *  2003-09-03	Interactivity tuning by Con Kolivas.
  *  2004-04-02	Scheduler domains code by Nick Piggin
+ *  2007-04-15  Work begun on replacing all interactivity tuning with a
+ *              fair scheduling design by Con Kolivas.
+ *  2007-05-05  Load balancing (smp-nice) and other improvements
+ *              by Peter Williams
+ *  2007-05-06  Interactivity improvements to CFS by Mike Galbraith
+ *  2007-07-01  Group scheduling enhancements by Srivatsa Vaddagiri
  */
 
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/nmi.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/highmem.h>
 #include <linux/smp_lock.h>
 #include <asm/mmu_context.h>
@@ -53,9 +59,9 @@
 #include <linux/kprobes.h>
 #include <linux/delayacct.h>
 #include <linux/reciprocal_div.h>
+#include <linux/unistd.h>
 
 #include <asm/tlb.h>
-#include <asm/unistd.h>
 
 /*
  * Scheduler clock - returns current time in nanosec units.
@@ -91,6 +97,9 @@
 #define NS_TO_JIFFIES(TIME)	((TIME) / (1000000000 / HZ))
 #define JIFFIES_TO_NS(TIME)	((TIME) * (1000000000 / HZ))
 
+#define NICE_0_LOAD		SCHED_LOAD_SCALE
+#define NICE_0_SHIFT		SCHED_LOAD_SHIFT
+
 /*
  * These are the 'tuning knobs' of the scheduler:
  *
@@ -100,87 +109,6 @@
  */
 #define MIN_TIMESLICE		max(5 * HZ / 1000, 1)
 #define DEF_TIMESLICE		(100 * HZ / 1000)
-#define ON_RUNQUEUE_WEIGHT	 30
-#define CHILD_PENALTY		 95
-#define PARENT_PENALTY		100
-#define EXIT_WEIGHT		  3
-#define PRIO_BONUS_RATIO	 25
-#define MAX_BONUS		(MAX_USER_PRIO * PRIO_BONUS_RATIO / 100)
-#define INTERACTIVE_DELTA	  2
-#define MAX_SLEEP_AVG		(DEF_TIMESLICE * MAX_BONUS)
-#define STARVATION_LIMIT	(MAX_SLEEP_AVG)
-#define NS_MAX_SLEEP_AVG	(JIFFIES_TO_NS(MAX_SLEEP_AVG))
-
-/*
- * If a task is 'interactive' then we reinsert it in the active
- * array after it has expired its current timeslice. (it will not
- * continue to run immediately, it will still roundrobin with
- * other interactive tasks.)
- *
- * This part scales the interactivity limit depending on niceness.
- *
- * We scale it linearly, offset by the INTERACTIVE_DELTA delta.
- * Here are a few examples of different nice levels:
- *
- *  TASK_INTERACTIVE(-20): [1,1,1,1,1,1,1,1,1,0,0]
- *  TASK_INTERACTIVE(-10): [1,1,1,1,1,1,1,0,0,0,0]
- *  TASK_INTERACTIVE(  0): [1,1,1,1,0,0,0,0,0,0,0]
- *  TASK_INTERACTIVE( 10): [1,1,0,0,0,0,0,0,0,0,0]
- *  TASK_INTERACTIVE( 19): [0,0,0,0,0,0,0,0,0,0,0]
- *
- * (the X axis represents the possible -5 ... 0 ... +5 dynamic
- *  priority range a task can explore, a value of '1' means the
- *  task is rated interactive.)
- *
- * Ie. nice +19 tasks can never get 'interactive' enough to be
- * reinserted into the active array. And only heavily CPU-hog nice -20
- * tasks will be expired. Default nice 0 tasks are somewhere between,
- * it takes some effort for them to get interactive, but it's not
- * too hard.
- */
-
-#define CURRENT_BONUS(p) \
-	(NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \
-		MAX_SLEEP_AVG)
-
-#define GRANULARITY	(10 * HZ / 1000 ? : 1)
-
-#ifdef CONFIG_SMP
-#define TIMESLICE_GRANULARITY(p)	(GRANULARITY * \
-		(1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)) * \
-			num_online_cpus())
-#else
-#define TIMESLICE_GRANULARITY(p)	(GRANULARITY * \
-		(1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)))
-#endif
-
-#define SCALE(v1,v1_max,v2_max) \
-	(v1) * (v2_max) / (v1_max)
-
-#define DELTA(p) \
-	(SCALE(TASK_NICE(p) + 20, 40, MAX_BONUS) - 20 * MAX_BONUS / 40 + \
-		INTERACTIVE_DELTA)
-
-#define TASK_INTERACTIVE(p) \
-	((p)->prio <= (p)->static_prio - DELTA(p))
-
-#define INTERACTIVE_SLEEP(p) \
-	(JIFFIES_TO_NS(MAX_SLEEP_AVG * \
-		(MAX_BONUS / 2 + DELTA((p)) + 1) / MAX_BONUS - 1))
-
-#define TASK_PREEMPTS_CURR(p, rq) \
-	((p)->prio < (rq)->curr->prio)
-
-#define SCALE_PRIO(x, prio) \
-	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
-
-static unsigned int static_prio_timeslice(int static_prio)
-{
-	if (static_prio < NICE_TO_PRIO(0))
-		return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
-	else
-		return SCALE_PRIO(DEF_TIMESLICE, static_prio);
-}
 
 #ifdef CONFIG_SMP
 /*
@@ -203,28 +131,87 @@
 }
 #endif
 
-/*
- * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
- * to time slice values: [800ms ... 100ms ... 5ms]
- *
- * The higher a thread's priority, the bigger timeslices
- * it gets during one round of execution. But even the lowest
- * priority thread gets MIN_TIMESLICE worth of execution time.
- */
+#define SCALE_PRIO(x, prio) \
+	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
 
-static inline unsigned int task_timeslice(struct task_struct *p)
+/*
+ * static_prio_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
+ * to time slice values: [800ms ... 100ms ... 5ms]
+ */
+static unsigned int static_prio_timeslice(int static_prio)
 {
-	return static_prio_timeslice(p->static_prio);
+	if (static_prio == NICE_TO_PRIO(19))
+		return 1;
+
+	if (static_prio < NICE_TO_PRIO(0))
+		return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
+	else
+		return SCALE_PRIO(DEF_TIMESLICE, static_prio);
+}
+
+static inline int rt_policy(int policy)
+{
+	if (unlikely(policy == SCHED_FIFO) || unlikely(policy == SCHED_RR))
+		return 1;
+	return 0;
+}
+
+static inline int task_has_rt_policy(struct task_struct *p)
+{
+	return rt_policy(p->policy);
 }
 
 /*
- * These are the runqueue data structures:
+ * This is the priority-queue data structure of the RT scheduling class:
  */
+struct rt_prio_array {
+	DECLARE_BITMAP(bitmap, MAX_RT_PRIO+1); /* include 1 bit for delimiter */
+	struct list_head queue[MAX_RT_PRIO];
+};
 
-struct prio_array {
-	unsigned int nr_active;
-	DECLARE_BITMAP(bitmap, MAX_PRIO+1); /* include 1 bit for delimiter */
-	struct list_head queue[MAX_PRIO];
+struct load_stat {
+	struct load_weight load;
+	u64 load_update_start, load_update_last;
+	unsigned long delta_fair, delta_exec, delta_stat;
+};
+
+/* CFS-related fields in a runqueue */
+struct cfs_rq {
+	struct load_weight load;
+	unsigned long nr_running;
+
+	s64 fair_clock;
+	u64 exec_clock;
+	s64 wait_runtime;
+	u64 sleeper_bonus;
+	unsigned long wait_runtime_overruns, wait_runtime_underruns;
+
+	struct rb_root tasks_timeline;
+	struct rb_node *rb_leftmost;
+	struct rb_node *rb_load_balance_curr;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	/* 'curr' points to currently running entity on this cfs_rq.
+	 * It is set to NULL otherwise (i.e when none are currently running).
+	 */
+	struct sched_entity *curr;
+	struct rq *rq;	/* cpu runqueue to which this cfs_rq is attached */
+
+	/* leaf cfs_rqs are those that hold tasks (lowest schedulable entity in
+	 * a hierarchy). Non-leaf lrqs hold other higher schedulable entities
+	 * (like users, containers etc.)
+	 *
+	 * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
+	 * list is used during load balance.
+	 */
+	struct list_head leaf_cfs_rq_list; /* Better name : task_cfs_rq_list? */
+#endif
+};
+
+/* Real-Time classes' related field in a runqueue: */
+struct rt_rq {
+	struct rt_prio_array active;
+	int rt_load_balance_idx;
+	struct list_head *rt_load_balance_head, *rt_load_balance_curr;
 };
 
 /*
@@ -235,22 +222,28 @@
  * acquire operations must be ordered by ascending &runqueue.
  */
 struct rq {
-	spinlock_t lock;
+	spinlock_t lock;	/* runqueue lock */
 
 	/*
 	 * nr_running and cpu_load should be in the same cacheline because
 	 * remote CPUs use both these fields when doing load calculation.
 	 */
 	unsigned long nr_running;
-	unsigned long raw_weighted_load;
-#ifdef CONFIG_SMP
-	unsigned long cpu_load[3];
+	#define CPU_LOAD_IDX_MAX 5
+	unsigned long cpu_load[CPU_LOAD_IDX_MAX];
 	unsigned char idle_at_tick;
 #ifdef CONFIG_NO_HZ
 	unsigned char in_nohz_recently;
 #endif
+	struct load_stat ls;	/* capture load from *all* tasks on this cpu */
+	unsigned long nr_load_updates;
+	u64 nr_switches;
+
+	struct cfs_rq cfs;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	struct list_head leaf_cfs_rq_list; /* list of leaf cfs_rq on this cpu */
 #endif
-	unsigned long long nr_switches;
+	struct rt_rq  rt;
 
 	/*
 	 * This is part of a global counter where only the total sum
@@ -260,14 +253,18 @@
 	 */
 	unsigned long nr_uninterruptible;
 
-	unsigned long expired_timestamp;
-	/* Cached timestamp set by update_cpu_clock() */
-	unsigned long long most_recent_timestamp;
 	struct task_struct *curr, *idle;
 	unsigned long next_balance;
 	struct mm_struct *prev_mm;
-	struct prio_array *active, *expired, arrays[2];
-	int best_expired_prio;
+
+	u64 clock, prev_clock_raw;
+	s64 clock_max_delta;
+
+	unsigned int clock_warps, clock_overflows;
+	unsigned int clock_unstable_events;
+
+	struct sched_class *load_balance_class;
+
 	atomic_t nr_iowait;
 
 #ifdef CONFIG_SMP
@@ -307,6 +304,11 @@
 static DEFINE_PER_CPU(struct rq, runqueues) ____cacheline_aligned_in_smp;
 static DEFINE_MUTEX(sched_hotcpu_mutex);
 
+static inline void check_preempt_curr(struct rq *rq, struct task_struct *p)
+{
+	rq->curr->sched_class->check_preempt_curr(rq, p);
+}
+
 static inline int cpu_of(struct rq *rq)
 {
 #ifdef CONFIG_SMP
@@ -317,6 +319,52 @@
 }
 
 /*
+ * Per-runqueue clock, as finegrained as the platform can give us:
+ */
+static unsigned long long __rq_clock(struct rq *rq)
+{
+	u64 prev_raw = rq->prev_clock_raw;
+	u64 now = sched_clock();
+	s64 delta = now - prev_raw;
+	u64 clock = rq->clock;
+
+	/*
+	 * Protect against sched_clock() occasionally going backwards:
+	 */
+	if (unlikely(delta < 0)) {
+		clock++;
+		rq->clock_warps++;
+	} else {
+		/*
+		 * Catch too large forward jumps too:
+		 */
+		if (unlikely(delta > 2*TICK_NSEC)) {
+			clock++;
+			rq->clock_overflows++;
+		} else {
+			if (unlikely(delta > rq->clock_max_delta))
+				rq->clock_max_delta = delta;
+			clock += delta;
+		}
+	}
+
+	rq->prev_clock_raw = now;
+	rq->clock = clock;
+
+	return clock;
+}
+
+static inline unsigned long long rq_clock(struct rq *rq)
+{
+	int this_cpu = smp_processor_id();
+
+	if (this_cpu == cpu_of(rq))
+		return __rq_clock(rq);
+
+	return rq->clock;
+}
+
+/*
  * The domain tree (rq->sd) is protected by RCU's quiescent state transition.
  * See detach_destroy_domains: synchronize_sched for details.
  *
@@ -331,6 +379,18 @@
 #define task_rq(p)		cpu_rq(task_cpu(p))
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/* Change a task's ->cfs_rq if it moves across CPUs */
+static inline void set_task_cfs_rq(struct task_struct *p)
+{
+	p->se.cfs_rq = &task_rq(p)->cfs;
+}
+#else
+static inline void set_task_cfs_rq(struct task_struct *p)
+{
+}
+#endif
+
 #ifndef prepare_arch_switch
 # define prepare_arch_switch(next)	do { } while (0)
 #endif
@@ -460,134 +520,6 @@
 	spin_unlock_irqrestore(&rq->lock, *flags);
 }
 
-#ifdef CONFIG_SCHEDSTATS
-/*
- * bump this up when changing the output format or the meaning of an existing
- * format, so that tools can adapt (or abort)
- */
-#define SCHEDSTAT_VERSION 14
-
-static int show_schedstat(struct seq_file *seq, void *v)
-{
-	int cpu;
-
-	seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
-	seq_printf(seq, "timestamp %lu\n", jiffies);
-	for_each_online_cpu(cpu) {
-		struct rq *rq = cpu_rq(cpu);
-#ifdef CONFIG_SMP
-		struct sched_domain *sd;
-		int dcnt = 0;
-#endif
-
-		/* runqueue-specific stats */
-		seq_printf(seq,
-		    "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
-		    cpu, rq->yld_both_empty,
-		    rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt,
-		    rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
-		    rq->ttwu_cnt, rq->ttwu_local,
-		    rq->rq_sched_info.cpu_time,
-		    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
-
-		seq_printf(seq, "\n");
-
-#ifdef CONFIG_SMP
-		/* domain-specific stats */
-		preempt_disable();
-		for_each_domain(cpu, sd) {
-			enum idle_type itype;
-			char mask_str[NR_CPUS];
-
-			cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
-			seq_printf(seq, "domain%d %s", dcnt++, mask_str);
-			for (itype = SCHED_IDLE; itype < MAX_IDLE_TYPES;
-					itype++) {
-				seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
-						"%lu",
-				    sd->lb_cnt[itype],
-				    sd->lb_balanced[itype],
-				    sd->lb_failed[itype],
-				    sd->lb_imbalance[itype],
-				    sd->lb_gained[itype],
-				    sd->lb_hot_gained[itype],
-				    sd->lb_nobusyq[itype],
-				    sd->lb_nobusyg[itype]);
-			}
-			seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
-			    " %lu %lu %lu\n",
-			    sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
-			    sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
-			    sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
-			    sd->ttwu_wake_remote, sd->ttwu_move_affine,
-			    sd->ttwu_move_balance);
-		}
-		preempt_enable();
-#endif
-	}
-	return 0;
-}
-
-static int schedstat_open(struct inode *inode, struct file *file)
-{
-	unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
-	char *buf = kmalloc(size, GFP_KERNEL);
-	struct seq_file *m;
-	int res;
-
-	if (!buf)
-		return -ENOMEM;
-	res = single_open(file, show_schedstat, NULL);
-	if (!res) {
-		m = file->private_data;
-		m->buf = buf;
-		m->size = size;
-	} else
-		kfree(buf);
-	return res;
-}
-
-const struct file_operations proc_schedstat_operations = {
-	.open    = schedstat_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = single_release,
-};
-
-/*
- * Expects runqueue lock to be held for atomicity of update
- */
-static inline void
-rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
-{
-	if (rq) {
-		rq->rq_sched_info.run_delay += delta_jiffies;
-		rq->rq_sched_info.pcnt++;
-	}
-}
-
-/*
- * Expects runqueue lock to be held for atomicity of update
- */
-static inline void
-rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
-{
-	if (rq)
-		rq->rq_sched_info.cpu_time += delta_jiffies;
-}
-# define schedstat_inc(rq, field)	do { (rq)->field++; } while (0)
-# define schedstat_add(rq, field, amt)	do { (rq)->field += (amt); } while (0)
-#else /* !CONFIG_SCHEDSTATS */
-static inline void
-rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
-{}
-static inline void
-rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
-{}
-# define schedstat_inc(rq, field)	do { } while (0)
-# define schedstat_add(rq, field, amt)	do { } while (0)
-#endif
-
 /*
  * this_rq_lock - lock this runqueue and disable interrupts.
  */
@@ -603,444 +535,18 @@
 	return rq;
 }
 
-#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
 /*
- * Called when a process is dequeued from the active array and given
- * the cpu.  We should note that with the exception of interactive
- * tasks, the expired queue will become the active queue after the active
- * queue is empty, without explicitly dequeuing and requeuing tasks in the
- * expired queue.  (Interactive tasks may be requeued directly to the
- * active queue, thus delaying tasks in the expired queue from running;
- * see scheduler_tick()).
- *
- * This function is only called from sched_info_arrive(), rather than
- * dequeue_task(). Even though a task may be queued and dequeued multiple
- * times as it is shuffled about, we're really interested in knowing how
- * long it was from the *first* time it was queued to the time that it
- * finally hit a cpu.
+ * CPU frequency is/was unstable - start new by setting prev_clock_raw:
  */
-static inline void sched_info_dequeued(struct task_struct *t)
+void sched_clock_unstable_event(void)
 {
-	t->sched_info.last_queued = 0;
-}
+	unsigned long flags;
+	struct rq *rq;
 
-/*
- * Called when a task finally hits the cpu.  We can now calculate how
- * long it was waiting to run.  We also note when it began so that we
- * can keep stats on how long its timeslice is.
- */
-static void sched_info_arrive(struct task_struct *t)
-{
-	unsigned long now = jiffies, delta_jiffies = 0;
-
-	if (t->sched_info.last_queued)
-		delta_jiffies = now - t->sched_info.last_queued;
-	sched_info_dequeued(t);
-	t->sched_info.run_delay += delta_jiffies;
-	t->sched_info.last_arrival = now;
-	t->sched_info.pcnt++;
-
-	rq_sched_info_arrive(task_rq(t), delta_jiffies);
-}
-
-/*
- * Called when a process is queued into either the active or expired
- * array.  The time is noted and later used to determine how long we
- * had to wait for us to reach the cpu.  Since the expired queue will
- * become the active queue after active queue is empty, without dequeuing
- * and requeuing any tasks, we are interested in queuing to either. It
- * is unusual but not impossible for tasks to be dequeued and immediately
- * requeued in the same or another array: this can happen in sched_yield(),
- * set_user_nice(), and even load_balance() as it moves tasks from runqueue
- * to runqueue.
- *
- * This function is only called from enqueue_task(), but also only updates
- * the timestamp if it is already not set.  It's assumed that
- * sched_info_dequeued() will clear that stamp when appropriate.
- */
-static inline void sched_info_queued(struct task_struct *t)
-{
-	if (unlikely(sched_info_on()))
-		if (!t->sched_info.last_queued)
-			t->sched_info.last_queued = jiffies;
-}
-
-/*
- * Called when a process ceases being the active-running process, either
- * voluntarily or involuntarily.  Now we can calculate how long we ran.
- */
-static inline void sched_info_depart(struct task_struct *t)
-{
-	unsigned long delta_jiffies = jiffies - t->sched_info.last_arrival;
-
-	t->sched_info.cpu_time += delta_jiffies;
-	rq_sched_info_depart(task_rq(t), delta_jiffies);
-}
-
-/*
- * Called when tasks are switched involuntarily due, typically, to expiring
- * their time slice.  (This may also be called when switching to or from
- * the idle task.)  We are only called when prev != next.
- */
-static inline void
-__sched_info_switch(struct task_struct *prev, struct task_struct *next)
-{
-	struct rq *rq = task_rq(prev);
-
-	/*
-	 * prev now departs the cpu.  It's not interesting to record
-	 * stats about how efficient we were at scheduling the idle
-	 * process, however.
-	 */
-	if (prev != rq->idle)
-		sched_info_depart(prev);
-
-	if (next != rq->idle)
-		sched_info_arrive(next);
-}
-static inline void
-sched_info_switch(struct task_struct *prev, struct task_struct *next)
-{
-	if (unlikely(sched_info_on()))
-		__sched_info_switch(prev, next);
-}
-#else
-#define sched_info_queued(t)		do { } while (0)
-#define sched_info_switch(t, next)	do { } while (0)
-#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
-
-/*
- * Adding/removing a task to/from a priority array:
- */
-static void dequeue_task(struct task_struct *p, struct prio_array *array)
-{
-	array->nr_active--;
-	list_del(&p->run_list);
-	if (list_empty(array->queue + p->prio))
-		__clear_bit(p->prio, array->bitmap);
-}
-
-static void enqueue_task(struct task_struct *p, struct prio_array *array)
-{
-	sched_info_queued(p);
-	list_add_tail(&p->run_list, array->queue + p->prio);
-	__set_bit(p->prio, array->bitmap);
-	array->nr_active++;
-	p->array = array;
-}
-
-/*
- * Put task to the end of the run list without the overhead of dequeue
- * followed by enqueue.
- */
-static void requeue_task(struct task_struct *p, struct prio_array *array)
-{
-	list_move_tail(&p->run_list, array->queue + p->prio);
-}
-
-static inline void
-enqueue_task_head(struct task_struct *p, struct prio_array *array)
-{
-	list_add(&p->run_list, array->queue + p->prio);
-	__set_bit(p->prio, array->bitmap);
-	array->nr_active++;
-	p->array = array;
-}
-
-/*
- * __normal_prio - return the priority that is based on the static
- * priority but is modified by bonuses/penalties.
- *
- * We scale the actual sleep average [0 .... MAX_SLEEP_AVG]
- * into the -5 ... 0 ... +5 bonus/penalty range.
- *
- * We use 25% of the full 0...39 priority range so that:
- *
- * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs.
- * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks.
- *
- * Both properties are important to certain workloads.
- */
-
-static inline int __normal_prio(struct task_struct *p)
-{
-	int bonus, prio;
-
-	bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
-
-	prio = p->static_prio - bonus;
-	if (prio < MAX_RT_PRIO)
-		prio = MAX_RT_PRIO;
-	if (prio > MAX_PRIO-1)
-		prio = MAX_PRIO-1;
-	return prio;
-}
-
-/*
- * To aid in avoiding the subversion of "niceness" due to uneven distribution
- * of tasks with abnormal "nice" values across CPUs the contribution that
- * each task makes to its run queue's load is weighted according to its
- * scheduling class and "nice" value.  For SCHED_NORMAL tasks this is just a
- * scaled version of the new time slice allocation that they receive on time
- * slice expiry etc.
- */
-
-/*
- * Assume: static_prio_timeslice(NICE_TO_PRIO(0)) == DEF_TIMESLICE
- * If static_prio_timeslice() is ever changed to break this assumption then
- * this code will need modification
- */
-#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE
-#define LOAD_WEIGHT(lp) \
-	(((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO)
-#define PRIO_TO_LOAD_WEIGHT(prio) \
-	LOAD_WEIGHT(static_prio_timeslice(prio))
-#define RTPRIO_TO_LOAD_WEIGHT(rp) \
-	(PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + LOAD_WEIGHT(rp))
-
-static void set_load_weight(struct task_struct *p)
-{
-	if (has_rt_policy(p)) {
-#ifdef CONFIG_SMP
-		if (p == task_rq(p)->migration_thread)
-			/*
-			 * The migration thread does the actual balancing.
-			 * Giving its load any weight will skew balancing
-			 * adversely.
-			 */
-			p->load_weight = 0;
-		else
-#endif
-			p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
-	} else
-		p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio);
-}
-
-static inline void
-inc_raw_weighted_load(struct rq *rq, const struct task_struct *p)
-{
-	rq->raw_weighted_load += p->load_weight;
-}
-
-static inline void
-dec_raw_weighted_load(struct rq *rq, const struct task_struct *p)
-{
-	rq->raw_weighted_load -= p->load_weight;
-}
-
-static inline void inc_nr_running(struct task_struct *p, struct rq *rq)
-{
-	rq->nr_running++;
-	inc_raw_weighted_load(rq, p);
-}
-
-static inline void dec_nr_running(struct task_struct *p, struct rq *rq)
-{
-	rq->nr_running--;
-	dec_raw_weighted_load(rq, p);
-}
-
-/*
- * Calculate the expected normal priority: i.e. priority
- * without taking RT-inheritance into account. Might be
- * boosted by interactivity modifiers. Changes upon fork,
- * setprio syscalls, and whenever the interactivity
- * estimator recalculates.
- */
-static inline int normal_prio(struct task_struct *p)
-{
-	int prio;
-
-	if (has_rt_policy(p))
-		prio = MAX_RT_PRIO-1 - p->rt_priority;
-	else
-		prio = __normal_prio(p);
-	return prio;
-}
-
-/*
- * Calculate the current priority, i.e. the priority
- * taken into account by the scheduler. This value might
- * be boosted by RT tasks, or might be boosted by
- * interactivity modifiers. Will be RT if the task got
- * RT-boosted. If not then it returns p->normal_prio.
- */
-static int effective_prio(struct task_struct *p)
-{
-	p->normal_prio = normal_prio(p);
-	/*
-	 * If we are RT tasks or we were boosted to RT priority,
-	 * keep the priority unchanged. Otherwise, update priority
-	 * to the normal priority:
-	 */
-	if (!rt_prio(p->prio))
-		return p->normal_prio;
-	return p->prio;
-}
-
-/*
- * __activate_task - move a task to the runqueue.
- */
-static void __activate_task(struct task_struct *p, struct rq *rq)
-{
-	struct prio_array *target = rq->active;
-
-	if (batch_task(p))
-		target = rq->expired;
-	enqueue_task(p, target);
-	inc_nr_running(p, rq);
-}
-
-/*
- * __activate_idle_task - move idle task to the _front_ of runqueue.
- */
-static inline void __activate_idle_task(struct task_struct *p, struct rq *rq)
-{
-	enqueue_task_head(p, rq->active);
-	inc_nr_running(p, rq);
-}
-
-/*
- * Recalculate p->normal_prio and p->prio after having slept,
- * updating the sleep-average too:
- */
-static int recalc_task_prio(struct task_struct *p, unsigned long long now)
-{
-	/* Caller must always ensure 'now >= p->timestamp' */
-	unsigned long sleep_time = now - p->timestamp;
-
-	if (batch_task(p))
-		sleep_time = 0;
-
-	if (likely(sleep_time > 0)) {
-		/*
-		 * This ceiling is set to the lowest priority that would allow
-		 * a task to be reinserted into the active array on timeslice
-		 * completion.
-		 */
-		unsigned long ceiling = INTERACTIVE_SLEEP(p);
-
-		if (p->mm && sleep_time > ceiling && p->sleep_avg < ceiling) {
-			/*
-			 * Prevents user tasks from achieving best priority
-			 * with one single large enough sleep.
-			 */
-			p->sleep_avg = ceiling;
-			/*
-			 * Using INTERACTIVE_SLEEP() as a ceiling places a
-			 * nice(0) task 1ms sleep away from promotion, and
-			 * gives it 700ms to round-robin with no chance of
-			 * being demoted.  This is more than generous, so
-			 * mark this sleep as non-interactive to prevent the
-			 * on-runqueue bonus logic from intervening should
-			 * this task not receive cpu immediately.
-			 */
-			p->sleep_type = SLEEP_NONINTERACTIVE;
-		} else {
-			/*
-			 * Tasks waking from uninterruptible sleep are
-			 * limited in their sleep_avg rise as they
-			 * are likely to be waiting on I/O
-			 */
-			if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) {
-				if (p->sleep_avg >= ceiling)
-					sleep_time = 0;
-				else if (p->sleep_avg + sleep_time >=
-					 ceiling) {
-						p->sleep_avg = ceiling;
-						sleep_time = 0;
-				}
-			}
-
-			/*
-			 * This code gives a bonus to interactive tasks.
-			 *
-			 * The boost works by updating the 'average sleep time'
-			 * value here, based on ->timestamp. The more time a
-			 * task spends sleeping, the higher the average gets -
-			 * and the higher the priority boost gets as well.
-			 */
-			p->sleep_avg += sleep_time;
-
-		}
-		if (p->sleep_avg > NS_MAX_SLEEP_AVG)
-			p->sleep_avg = NS_MAX_SLEEP_AVG;
-	}
-
-	return effective_prio(p);
-}
-
-/*
- * activate_task - move a task to the runqueue and do priority recalculation
- *
- * Update all the scheduling statistics stuff. (sleep average
- * calculation, priority modifiers, etc.)
- */
-static void activate_task(struct task_struct *p, struct rq *rq, int local)
-{
-	unsigned long long now;
-
-	if (rt_task(p))
-		goto out;
-
-	now = sched_clock();
-#ifdef CONFIG_SMP
-	if (!local) {
-		/* Compensate for drifting sched_clock */
-		struct rq *this_rq = this_rq();
-		now = (now - this_rq->most_recent_timestamp)
-			+ rq->most_recent_timestamp;
-	}
-#endif
-
-	/*
-	 * Sleep time is in units of nanosecs, so shift by 20 to get a
-	 * milliseconds-range estimation of the amount of time that the task
-	 * spent sleeping:
-	 */
-	if (unlikely(prof_on == SLEEP_PROFILING)) {
-		if (p->state == TASK_UNINTERRUPTIBLE)
-			profile_hits(SLEEP_PROFILING, (void *)get_wchan(p),
-				     (now - p->timestamp) >> 20);
-	}
-
-	p->prio = recalc_task_prio(p, now);
-
-	/*
-	 * This checks to make sure it's not an uninterruptible task
-	 * that is now waking up.
-	 */
-	if (p->sleep_type == SLEEP_NORMAL) {
-		/*
-		 * Tasks which were woken up by interrupts (ie. hw events)
-		 * are most likely of interactive nature. So we give them
-		 * the credit of extending their sleep time to the period
-		 * of time they spend on the runqueue, waiting for execution
-		 * on a CPU, first time around:
-		 */
-		if (in_interrupt())
-			p->sleep_type = SLEEP_INTERRUPTED;
-		else {
-			/*
-			 * Normal first-time wakeups get a credit too for
-			 * on-runqueue time, but it will be weighted down:
-			 */
-			p->sleep_type = SLEEP_INTERACTIVE;
-		}
-	}
-	p->timestamp = now;
-out:
-	__activate_task(p, rq);
-}
-
-/*
- * deactivate_task - remove a task from the runqueue.
- */
-static void deactivate_task(struct task_struct *p, struct rq *rq)
-{
-	dec_nr_running(p, rq);
-	dequeue_task(p, p->array);
-	p->array = NULL;
+	rq = task_rq_lock(current, &flags);
+	rq->prev_clock_raw = sched_clock();
+	rq->clock_unstable_events++;
+	task_rq_unlock(rq, &flags);
 }
 
 /*
@@ -1095,6 +601,345 @@
 }
 #endif
 
+static u64 div64_likely32(u64 divident, unsigned long divisor)
+{
+#if BITS_PER_LONG == 32
+	if (likely(divident <= 0xffffffffULL))
+		return (u32)divident / divisor;
+	do_div(divident, divisor);
+
+	return divident;
+#else
+	return divident / divisor;
+#endif
+}
+
+#if BITS_PER_LONG == 32
+# define WMULT_CONST	(~0UL)
+#else
+# define WMULT_CONST	(1UL << 32)
+#endif
+
+#define WMULT_SHIFT	32
+
+static inline unsigned long
+calc_delta_mine(unsigned long delta_exec, unsigned long weight,
+		struct load_weight *lw)
+{
+	u64 tmp;
+
+	if (unlikely(!lw->inv_weight))
+		lw->inv_weight = WMULT_CONST / lw->weight;
+
+	tmp = (u64)delta_exec * weight;
+	/*
+	 * Check whether we'd overflow the 64-bit multiplication:
+	 */
+	if (unlikely(tmp > WMULT_CONST)) {
+		tmp = ((tmp >> WMULT_SHIFT/2) * lw->inv_weight)
+				>> (WMULT_SHIFT/2);
+	} else {
+		tmp = (tmp * lw->inv_weight) >> WMULT_SHIFT;
+	}
+
+	return (unsigned long)min(tmp, (u64)sysctl_sched_runtime_limit);
+}
+
+static inline unsigned long
+calc_delta_fair(unsigned long delta_exec, struct load_weight *lw)
+{
+	return calc_delta_mine(delta_exec, NICE_0_LOAD, lw);
+}
+
+static void update_load_add(struct load_weight *lw, unsigned long inc)
+{
+	lw->weight += inc;
+	lw->inv_weight = 0;
+}
+
+static void update_load_sub(struct load_weight *lw, unsigned long dec)
+{
+	lw->weight -= dec;
+	lw->inv_weight = 0;
+}
+
+static void __update_curr_load(struct rq *rq, struct load_stat *ls)
+{
+	if (rq->curr != rq->idle && ls->load.weight) {
+		ls->delta_exec += ls->delta_stat;
+		ls->delta_fair += calc_delta_fair(ls->delta_stat, &ls->load);
+		ls->delta_stat = 0;
+	}
+}
+
+/*
+ * Update delta_exec, delta_fair fields for rq.
+ *
+ * delta_fair clock advances at a rate inversely proportional to
+ * total load (rq->ls.load.weight) on the runqueue, while
+ * delta_exec advances at the same rate as wall-clock (provided
+ * cpu is not idle).
+ *
+ * delta_exec / delta_fair is a measure of the (smoothened) load on this
+ * runqueue over any given interval. This (smoothened) load is used
+ * during load balance.
+ *
+ * This function is called /before/ updating rq->ls.load
+ * and when switching tasks.
+ */
+static void update_curr_load(struct rq *rq, u64 now)
+{
+	struct load_stat *ls = &rq->ls;
+	u64 start;
+
+	start = ls->load_update_start;
+	ls->load_update_start = now;
+	ls->delta_stat += now - start;
+	/*
+	 * Stagger updates to ls->delta_fair. Very frequent updates
+	 * can be expensive.
+	 */
+	if (ls->delta_stat >= sysctl_sched_stat_granularity)
+		__update_curr_load(rq, ls);
+}
+
+/*
+ * To aid in avoiding the subversion of "niceness" due to uneven distribution
+ * of tasks with abnormal "nice" values across CPUs the contribution that
+ * each task makes to its run queue's load is weighted according to its
+ * scheduling class and "nice" value.  For SCHED_NORMAL tasks this is just a
+ * scaled version of the new time slice allocation that they receive on time
+ * slice expiry etc.
+ */
+
+/*
+ * Assume: static_prio_timeslice(NICE_TO_PRIO(0)) == DEF_TIMESLICE
+ * If static_prio_timeslice() is ever changed to break this assumption then
+ * this code will need modification
+ */
+#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE
+#define load_weight(lp) \
+	(((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO)
+#define PRIO_TO_LOAD_WEIGHT(prio) \
+	load_weight(static_prio_timeslice(prio))
+#define RTPRIO_TO_LOAD_WEIGHT(rp) \
+	(PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + load_weight(rp))
+
+#define WEIGHT_IDLEPRIO		2
+#define WMULT_IDLEPRIO		(1 << 31)
+
+/*
+ * Nice levels are multiplicative, with a gentle 10% change for every
+ * nice level changed. I.e. when a CPU-bound task goes from nice 0 to
+ * nice 1, it will get ~10% less CPU time than another CPU-bound task
+ * that remained on nice 0.
+ *
+ * The "10% effect" is relative and cumulative: from _any_ nice level,
+ * if you go up 1 level, it's -10% CPU usage, if you go down 1 level
+ * it's +10% CPU usage.
+ */
+static const int prio_to_weight[40] = {
+/* -20 */ 88818, 71054, 56843, 45475, 36380, 29104, 23283, 18626, 14901, 11921,
+/* -10 */  9537,  7629,  6103,  4883,  3906,  3125,  2500,  2000,  1600,  1280,
+/*   0 */  NICE_0_LOAD /* 1024 */,
+/*   1 */          819,   655,   524,   419,   336,   268,   215,   172,   137,
+/*  10 */   110,    87,    70,    56,    45,    36,    29,    23,    18,    15,
+};
+
+static const u32 prio_to_wmult[40] = {
+	48356,   60446,   75558,   94446,  118058,  147573,
+	184467,  230589,  288233,  360285,  450347,
+	562979,  703746,  879575, 1099582, 1374389,
+	717986, 2147483, 2684354, 3355443, 4194304,
+	244160, 6557201, 8196502, 10250518, 12782640,
+	16025997, 19976592, 24970740, 31350126, 39045157,
+	49367440, 61356675, 76695844, 95443717, 119304647,
+	148102320, 186737708, 238609294, 286331153,
+};
+
+static inline void
+inc_load(struct rq *rq, const struct task_struct *p, u64 now)
+{
+	update_curr_load(rq, now);
+	update_load_add(&rq->ls.load, p->se.load.weight);
+}
+
+static inline void
+dec_load(struct rq *rq, const struct task_struct *p, u64 now)
+{
+	update_curr_load(rq, now);
+	update_load_sub(&rq->ls.load, p->se.load.weight);
+}
+
+static inline void inc_nr_running(struct task_struct *p, struct rq *rq, u64 now)
+{
+	rq->nr_running++;
+	inc_load(rq, p, now);
+}
+
+static inline void dec_nr_running(struct task_struct *p, struct rq *rq, u64 now)
+{
+	rq->nr_running--;
+	dec_load(rq, p, now);
+}
+
+static void activate_task(struct rq *rq, struct task_struct *p, int wakeup);
+
+/*
+ * runqueue iterator, to support SMP load-balancing between different
+ * scheduling classes, without having to expose their internal data
+ * structures to the load-balancing proper:
+ */
+struct rq_iterator {
+	void *arg;
+	struct task_struct *(*start)(void *);
+	struct task_struct *(*next)(void *);
+};
+
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+		      unsigned long max_nr_move, unsigned long max_load_move,
+		      struct sched_domain *sd, enum cpu_idle_type idle,
+		      int *all_pinned, unsigned long *load_moved,
+		      int this_best_prio, int best_prio, int best_prio_seen,
+		      struct rq_iterator *iterator);
+
+#include "sched_stats.h"
+#include "sched_rt.c"
+#include "sched_fair.c"
+#include "sched_idletask.c"
+#ifdef CONFIG_SCHED_DEBUG
+# include "sched_debug.c"
+#endif
+
+#define sched_class_highest (&rt_sched_class)
+
+static void set_load_weight(struct task_struct *p)
+{
+	task_rq(p)->cfs.wait_runtime -= p->se.wait_runtime;
+	p->se.wait_runtime = 0;
+
+	if (task_has_rt_policy(p)) {
+		p->se.load.weight = prio_to_weight[0] * 2;
+		p->se.load.inv_weight = prio_to_wmult[0] >> 1;
+		return;
+	}
+
+	/*
+	 * SCHED_IDLE tasks get minimal weight:
+	 */
+	if (p->policy == SCHED_IDLE) {
+		p->se.load.weight = WEIGHT_IDLEPRIO;
+		p->se.load.inv_weight = WMULT_IDLEPRIO;
+		return;
+	}
+
+	p->se.load.weight = prio_to_weight[p->static_prio - MAX_RT_PRIO];
+	p->se.load.inv_weight = prio_to_wmult[p->static_prio - MAX_RT_PRIO];
+}
+
+static void
+enqueue_task(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+	sched_info_queued(p);
+	p->sched_class->enqueue_task(rq, p, wakeup, now);
+	p->se.on_rq = 1;
+}
+
+static void
+dequeue_task(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+	p->sched_class->dequeue_task(rq, p, sleep, now);
+	p->se.on_rq = 0;
+}
+
+/*
+ * __normal_prio - return the priority that is based on the static prio
+ */
+static inline int __normal_prio(struct task_struct *p)
+{
+	return p->static_prio;
+}
+
+/*
+ * Calculate the expected normal priority: i.e. priority
+ * without taking RT-inheritance into account. Might be
+ * boosted by interactivity modifiers. Changes upon fork,
+ * setprio syscalls, and whenever the interactivity
+ * estimator recalculates.
+ */
+static inline int normal_prio(struct task_struct *p)
+{
+	int prio;
+
+	if (task_has_rt_policy(p))
+		prio = MAX_RT_PRIO-1 - p->rt_priority;
+	else
+		prio = __normal_prio(p);
+	return prio;
+}
+
+/*
+ * Calculate the current priority, i.e. the priority
+ * taken into account by the scheduler. This value might
+ * be boosted by RT tasks, or might be boosted by
+ * interactivity modifiers. Will be RT if the task got
+ * RT-boosted. If not then it returns p->normal_prio.
+ */
+static int effective_prio(struct task_struct *p)
+{
+	p->normal_prio = normal_prio(p);
+	/*
+	 * If we are RT tasks or we were boosted to RT priority,
+	 * keep the priority unchanged. Otherwise, update priority
+	 * to the normal priority:
+	 */
+	if (!rt_prio(p->prio))
+		return p->normal_prio;
+	return p->prio;
+}
+
+/*
+ * activate_task - move a task to the runqueue.
+ */
+static void activate_task(struct rq *rq, struct task_struct *p, int wakeup)
+{
+	u64 now = rq_clock(rq);
+
+	if (p->state == TASK_UNINTERRUPTIBLE)
+		rq->nr_uninterruptible--;
+
+	enqueue_task(rq, p, wakeup, now);
+	inc_nr_running(p, rq, now);
+}
+
+/*
+ * activate_idle_task - move idle task to the _front_ of runqueue.
+ */
+static inline void activate_idle_task(struct task_struct *p, struct rq *rq)
+{
+	u64 now = rq_clock(rq);
+
+	if (p->state == TASK_UNINTERRUPTIBLE)
+		rq->nr_uninterruptible--;
+
+	enqueue_task(rq, p, 0, now);
+	inc_nr_running(p, rq, now);
+}
+
+/*
+ * deactivate_task - remove a task from the runqueue.
+ */
+static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep)
+{
+	u64 now = rq_clock(rq);
+
+	if (p->state == TASK_UNINTERRUPTIBLE)
+		rq->nr_uninterruptible++;
+
+	dequeue_task(rq, p, sleep, now);
+	dec_nr_running(p, rq, now);
+}
+
 /**
  * task_curr - is this task currently executing on a CPU?
  * @p: the task in question.
@@ -1107,10 +952,42 @@
 /* Used instead of source_load when we know the type == 0 */
 unsigned long weighted_cpuload(const int cpu)
 {
-	return cpu_rq(cpu)->raw_weighted_load;
+	return cpu_rq(cpu)->ls.load.weight;
+}
+
+static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
+{
+#ifdef CONFIG_SMP
+	task_thread_info(p)->cpu = cpu;
+	set_task_cfs_rq(p);
+#endif
 }
 
 #ifdef CONFIG_SMP
+
+void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
+{
+	int old_cpu = task_cpu(p);
+	struct rq *old_rq = cpu_rq(old_cpu), *new_rq = cpu_rq(new_cpu);
+	u64 clock_offset, fair_clock_offset;
+
+	clock_offset = old_rq->clock - new_rq->clock;
+	fair_clock_offset = old_rq->cfs.fair_clock -
+						 new_rq->cfs.fair_clock;
+	if (p->se.wait_start)
+		p->se.wait_start -= clock_offset;
+	if (p->se.wait_start_fair)
+		p->se.wait_start_fair -= fair_clock_offset;
+	if (p->se.sleep_start)
+		p->se.sleep_start -= clock_offset;
+	if (p->se.block_start)
+		p->se.block_start -= clock_offset;
+	if (p->se.sleep_start_fair)
+		p->se.sleep_start_fair -= fair_clock_offset;
+
+	__set_task_cpu(p, new_cpu);
+}
+
 struct migration_req {
 	struct list_head list;
 
@@ -1133,7 +1010,7 @@
 	 * If the task is not on a runqueue (and not running), then
 	 * it is sufficient to simply update the task's cpu field.
 	 */
-	if (!p->array && !task_running(rq, p)) {
+	if (!p->se.on_rq && !task_running(rq, p)) {
 		set_task_cpu(p, dest_cpu);
 		return 0;
 	}
@@ -1158,9 +1035,8 @@
 void wait_task_inactive(struct task_struct *p)
 {
 	unsigned long flags;
+	int running, on_rq;
 	struct rq *rq;
-	struct prio_array *array;
-	int running;
 
 repeat:
 	/*
@@ -1192,7 +1068,7 @@
 	 */
 	rq = task_rq_lock(p, &flags);
 	running = task_running(rq, p);
-	array = p->array;
+	on_rq = p->se.on_rq;
 	task_rq_unlock(rq, &flags);
 
 	/*
@@ -1215,7 +1091,7 @@
 	 * running right now), it's preempted, and we should
 	 * yield - it could be a while.
 	 */
-	if (unlikely(array)) {
+	if (unlikely(on_rq)) {
 		yield();
 		goto repeat;
 	}
@@ -1261,11 +1137,12 @@
 static inline unsigned long source_load(int cpu, int type)
 {
 	struct rq *rq = cpu_rq(cpu);
+	unsigned long total = weighted_cpuload(cpu);
 
 	if (type == 0)
-		return rq->raw_weighted_load;
+		return total;
 
-	return min(rq->cpu_load[type-1], rq->raw_weighted_load);
+	return min(rq->cpu_load[type-1], total);
 }
 
 /*
@@ -1275,11 +1152,12 @@
 static inline unsigned long target_load(int cpu, int type)
 {
 	struct rq *rq = cpu_rq(cpu);
+	unsigned long total = weighted_cpuload(cpu);
 
 	if (type == 0)
-		return rq->raw_weighted_load;
+		return total;
 
-	return max(rq->cpu_load[type-1], rq->raw_weighted_load);
+	return max(rq->cpu_load[type-1], total);
 }
 
 /*
@@ -1288,9 +1166,10 @@
 static inline unsigned long cpu_avg_load_per_task(int cpu)
 {
 	struct rq *rq = cpu_rq(cpu);
+	unsigned long total = weighted_cpuload(cpu);
 	unsigned long n = rq->nr_running;
 
-	return n ? rq->raw_weighted_load / n : SCHED_LOAD_SCALE;
+	return n ? total / n : SCHED_LOAD_SCALE;
 }
 
 /*
@@ -1392,9 +1271,9 @@
 	struct sched_domain *tmp, *sd = NULL;
 
 	for_each_domain(cpu, tmp) {
- 		/*
- 	 	 * If power savings logic is enabled for a domain, stop there.
- 	 	 */
+		/*
+		 * If power savings logic is enabled for a domain, stop there.
+		 */
 		if (tmp->flags & SD_POWERSAVINGS_BALANCE)
 			break;
 		if (tmp->flags & flag)
@@ -1477,9 +1356,9 @@
 				if (idle_cpu(i))
 					return i;
 			}
-		}
-		else
+		} else {
 			break;
+		}
 	}
 	return cpu;
 }
@@ -1521,7 +1400,7 @@
 	if (!(old_state & state))
 		goto out;
 
-	if (p->array)
+	if (p->se.on_rq)
 		goto out_running;
 
 	cpu = task_cpu(p);
@@ -1576,11 +1455,11 @@
 			 * of the current CPU:
 			 */
 			if (sync)
-				tl -= current->load_weight;
+				tl -= current->se.load.weight;
 
 			if ((tl <= load &&
 				tl + target_load(cpu, idx) <= tl_per_task) ||
-				100*(tl + p->load_weight) <= imbalance*load) {
+			       100*(tl + p->se.load.weight) <= imbalance*load) {
 				/*
 				 * This domain has SD_WAKE_AFFINE and
 				 * p is cache cold in this domain, and
@@ -1614,7 +1493,7 @@
 		old_state = p->state;
 		if (!(old_state & state))
 			goto out;
-		if (p->array)
+		if (p->se.on_rq)
 			goto out_running;
 
 		this_cpu = smp_processor_id();
@@ -1623,25 +1502,7 @@
 
 out_activate:
 #endif /* CONFIG_SMP */
-	if (old_state == TASK_UNINTERRUPTIBLE) {
-		rq->nr_uninterruptible--;
-		/*
-		 * Tasks on involuntary sleep don't earn
-		 * sleep_avg beyond just interactive state.
-		 */
-		p->sleep_type = SLEEP_NONINTERACTIVE;
-	} else
-
-	/*
-	 * Tasks that have marked their sleep as noninteractive get
-	 * woken up with their sleep average not weighted in an
-	 * interactive way.
-	 */
-		if (old_state & TASK_NONINTERACTIVE)
-			p->sleep_type = SLEEP_NONINTERACTIVE;
-
-
-	activate_task(p, rq, cpu == this_cpu);
+	activate_task(rq, p, 1);
 	/*
 	 * Sync wakeups (i.e. those types of wakeups where the waker
 	 * has indicated that it will leave the CPU in short order)
@@ -1650,10 +1511,8 @@
 	 * the waker guarantees that the freshly woken up task is going
 	 * to be considered on this CPU.)
 	 */
-	if (!sync || cpu != this_cpu) {
-		if (TASK_PREEMPTS_CURR(p, rq))
-			resched_task(rq->curr);
-	}
+	if (!sync || cpu != this_cpu)
+		check_preempt_curr(rq, p);
 	success = 1;
 
 out_running:
@@ -1676,19 +1535,36 @@
 	return try_to_wake_up(p, state, 0);
 }
 
-static void task_running_tick(struct rq *rq, struct task_struct *p);
 /*
  * Perform scheduler related setup for a newly forked process p.
  * p is forked by current.
+ *
+ * __sched_fork() is basic setup used by init_idle() too:
  */
-void fastcall sched_fork(struct task_struct *p, int clone_flags)
+static void __sched_fork(struct task_struct *p)
 {
-	int cpu = get_cpu();
+	p->se.wait_start_fair		= 0;
+	p->se.wait_start		= 0;
+	p->se.exec_start		= 0;
+	p->se.sum_exec_runtime		= 0;
+	p->se.delta_exec		= 0;
+	p->se.delta_fair_run		= 0;
+	p->se.delta_fair_sleep		= 0;
+	p->se.wait_runtime		= 0;
+	p->se.sum_wait_runtime		= 0;
+	p->se.sum_sleep_runtime		= 0;
+	p->se.sleep_start		= 0;
+	p->se.sleep_start_fair		= 0;
+	p->se.block_start		= 0;
+	p->se.sleep_max			= 0;
+	p->se.block_max			= 0;
+	p->se.exec_max			= 0;
+	p->se.wait_max			= 0;
+	p->se.wait_runtime_overruns	= 0;
+	p->se.wait_runtime_underruns	= 0;
 
-#ifdef CONFIG_SMP
-	cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
-#endif
-	set_task_cpu(p, cpu);
+	INIT_LIST_HEAD(&p->run_list);
+	p->se.on_rq = 0;
 
 	/*
 	 * We mark the process as running here, but have not actually
@@ -1697,16 +1573,29 @@
 	 * event cannot wake it up and insert it on the runqueue either.
 	 */
 	p->state = TASK_RUNNING;
+}
+
+/*
+ * fork()/clone()-time setup:
+ */
+void sched_fork(struct task_struct *p, int clone_flags)
+{
+	int cpu = get_cpu();
+
+	__sched_fork(p);
+
+#ifdef CONFIG_SMP
+	cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
+#endif
+	__set_task_cpu(p, cpu);
 
 	/*
 	 * Make sure we do not leak PI boosting priority to the child:
 	 */
 	p->prio = current->normal_prio;
 
-	INIT_LIST_HEAD(&p->run_list);
-	p->array = NULL;
 #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
-	if (unlikely(sched_info_on()))
+	if (likely(sched_info_on()))
 		memset(&p->sched_info, 0, sizeof(p->sched_info));
 #endif
 #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
@@ -1716,34 +1605,16 @@
 	/* Want to start with kernel preemption disabled. */
 	task_thread_info(p)->preempt_count = 1;
 #endif
-	/*
-	 * Share the timeslice between parent and child, thus the
-	 * total amount of pending timeslices in the system doesn't change,
-	 * resulting in more scheduling fairness.
-	 */
-	local_irq_disable();
-	p->time_slice = (current->time_slice + 1) >> 1;
-	/*
-	 * The remainder of the first timeslice might be recovered by
-	 * the parent if the child exits early enough.
-	 */
-	p->first_time_slice = 1;
-	current->time_slice >>= 1;
-	p->timestamp = sched_clock();
-	if (unlikely(!current->time_slice)) {
-		/*
-		 * This case is rare, it happens when the parent has only
-		 * a single jiffy left from its timeslice. Taking the
-		 * runqueue lock is not a problem.
-		 */
-		current->time_slice = 1;
-		task_running_tick(cpu_rq(cpu), current);
-	}
-	local_irq_enable();
 	put_cpu();
 }
 
 /*
+ * After fork, child runs first. (default) If set to 0 then
+ * parent will (try to) run first.
+ */
+unsigned int __read_mostly sysctl_sched_child_runs_first = 1;
+
+/*
  * wake_up_new_task - wake up a newly created task for the first time.
  *
  * This function will do some initial scheduler statistics housekeeping
@@ -1752,107 +1623,27 @@
  */
 void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
 {
-	struct rq *rq, *this_rq;
 	unsigned long flags;
-	int this_cpu, cpu;
+	struct rq *rq;
+	int this_cpu;
 
 	rq = task_rq_lock(p, &flags);
 	BUG_ON(p->state != TASK_RUNNING);
-	this_cpu = smp_processor_id();
-	cpu = task_cpu(p);
-
-	/*
-	 * We decrease the sleep average of forking parents
-	 * and children as well, to keep max-interactive tasks
-	 * from forking tasks that are max-interactive. The parent
-	 * (current) is done further down, under its lock.
-	 */
-	p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
-		CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
+	this_cpu = smp_processor_id(); /* parent's CPU */
 
 	p->prio = effective_prio(p);
 
-	if (likely(cpu == this_cpu)) {
-		if (!(clone_flags & CLONE_VM)) {
-			/*
-			 * The VM isn't cloned, so we're in a good position to
-			 * do child-runs-first in anticipation of an exec. This
-			 * usually avoids a lot of COW overhead.
-			 */
-			if (unlikely(!current->array))
-				__activate_task(p, rq);
-			else {
-				p->prio = current->prio;
-				p->normal_prio = current->normal_prio;
-				list_add_tail(&p->run_list, &current->run_list);
-				p->array = current->array;
-				p->array->nr_active++;
-				inc_nr_running(p, rq);
-			}
-			set_need_resched();
-		} else
-			/* Run child last */
-			__activate_task(p, rq);
-		/*
-		 * We skip the following code due to cpu == this_cpu
-	 	 *
-		 *   task_rq_unlock(rq, &flags);
-		 *   this_rq = task_rq_lock(current, &flags);
-		 */
-		this_rq = rq;
+	if (!sysctl_sched_child_runs_first || (clone_flags & CLONE_VM) ||
+			task_cpu(p) != this_cpu || !current->se.on_rq) {
+		activate_task(rq, p, 0);
 	} else {
-		this_rq = cpu_rq(this_cpu);
-
 		/*
-		 * Not the local CPU - must adjust timestamp. This should
-		 * get optimised away in the !CONFIG_SMP case.
+		 * Let the scheduling class do new task startup
+		 * management (if any):
 		 */
-		p->timestamp = (p->timestamp - this_rq->most_recent_timestamp)
-					+ rq->most_recent_timestamp;
-		__activate_task(p, rq);
-		if (TASK_PREEMPTS_CURR(p, rq))
-			resched_task(rq->curr);
-
-		/*
-		 * Parent and child are on different CPUs, now get the
-		 * parent runqueue to update the parent's ->sleep_avg:
-		 */
-		task_rq_unlock(rq, &flags);
-		this_rq = task_rq_lock(current, &flags);
+		p->sched_class->task_new(rq, p);
 	}
-	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
-		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
-	task_rq_unlock(this_rq, &flags);
-}
-
-/*
- * Potentially available exiting-child timeslices are
- * retrieved here - this way the parent does not get
- * penalized for creating too many threads.
- *
- * (this cannot be used to 'generate' timeslices
- * artificially, because any timeslice recovered here
- * was given away by the parent in the first place.)
- */
-void fastcall sched_exit(struct task_struct *p)
-{
-	unsigned long flags;
-	struct rq *rq;
-
-	/*
-	 * If the child was a (relative-) CPU hog then decrease
-	 * the sleep_avg of the parent as well.
-	 */
-	rq = task_rq_lock(p->parent, &flags);
-	if (p->first_time_slice && task_cpu(p) == task_cpu(p->parent)) {
-		p->parent->time_slice += p->time_slice;
-		if (unlikely(p->parent->time_slice > task_timeslice(p)))
-			p->parent->time_slice = task_timeslice(p);
-	}
-	if (p->sleep_avg < p->parent->sleep_avg)
-		p->parent->sleep_avg = p->parent->sleep_avg /
-		(EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg /
-		(EXIT_WEIGHT + 1);
+	check_preempt_curr(rq, p);
 	task_rq_unlock(rq, &flags);
 }
 
@@ -1917,7 +1708,7 @@
 		/*
 		 * Remove function-return probe instances associated with this
 		 * task and put them back on the free list.
-	 	 */
+		 */
 		kprobe_flush_task(prev);
 		put_task_struct(prev);
 	}
@@ -1945,13 +1736,15 @@
  * context_switch - switch to the new MM and the new
  * thread's register state.
  */
-static inline struct task_struct *
+static inline void
 context_switch(struct rq *rq, struct task_struct *prev,
 	       struct task_struct *next)
 {
-	struct mm_struct *mm = next->mm;
-	struct mm_struct *oldmm = prev->active_mm;
+	struct mm_struct *mm, *oldmm;
 
+	prepare_task_switch(rq, next);
+	mm = next->mm;
+	oldmm = prev->active_mm;
 	/*
 	 * For paravirt, this is coupled with an exit in switch_to to
 	 * combine the page table reload and the switch backend into
@@ -1959,16 +1752,15 @@
 	 */
 	arch_enter_lazy_cpu_mode();
 
-	if (!mm) {
+	if (unlikely(!mm)) {
 		next->active_mm = oldmm;
 		atomic_inc(&oldmm->mm_count);
 		enter_lazy_tlb(oldmm, next);
 	} else
 		switch_mm(oldmm, mm, next);
 
-	if (!prev->mm) {
+	if (unlikely(!prev->mm)) {
 		prev->active_mm = NULL;
-		WARN_ON(rq->prev_mm);
 		rq->prev_mm = oldmm;
 	}
 	/*
@@ -1984,7 +1776,13 @@
 	/* Here we just switch the register state and the stack. */
 	switch_to(prev, next, prev);
 
-	return prev;
+	barrier();
+	/*
+	 * this_rq must be evaluated again because prev may have moved
+	 * CPUs since it called schedule(), thus the 'rq' on its stack
+	 * frame will be invalid.
+	 */
+	finish_task_switch(this_rq(), prev);
 }
 
 /*
@@ -2057,17 +1855,65 @@
 	return running + uninterruptible;
 }
 
-#ifdef CONFIG_SMP
-
 /*
- * Is this task likely cache-hot:
+ * Update rq->cpu_load[] statistics. This function is usually called every
+ * scheduler tick (TICK_NSEC).
  */
-static inline int
-task_hot(struct task_struct *p, unsigned long long now, struct sched_domain *sd)
+static void update_cpu_load(struct rq *this_rq)
 {
-	return (long long)(now - p->last_ran) < (long long)sd->cache_hot_time;
+	u64 fair_delta64, exec_delta64, idle_delta64, sample_interval64, tmp64;
+	unsigned long total_load = this_rq->ls.load.weight;
+	unsigned long this_load =  total_load;
+	struct load_stat *ls = &this_rq->ls;
+	u64 now = __rq_clock(this_rq);
+	int i, scale;
+
+	this_rq->nr_load_updates++;
+	if (unlikely(!(sysctl_sched_features & SCHED_FEAT_PRECISE_CPU_LOAD)))
+		goto do_avg;
+
+	/* Update delta_fair/delta_exec fields first */
+	update_curr_load(this_rq, now);
+
+	fair_delta64 = ls->delta_fair + 1;
+	ls->delta_fair = 0;
+
+	exec_delta64 = ls->delta_exec + 1;
+	ls->delta_exec = 0;
+
+	sample_interval64 = now - ls->load_update_last;
+	ls->load_update_last = now;
+
+	if ((s64)sample_interval64 < (s64)TICK_NSEC)
+		sample_interval64 = TICK_NSEC;
+
+	if (exec_delta64 > sample_interval64)
+		exec_delta64 = sample_interval64;
+
+	idle_delta64 = sample_interval64 - exec_delta64;
+
+	tmp64 = div64_64(SCHED_LOAD_SCALE * exec_delta64, fair_delta64);
+	tmp64 = div64_64(tmp64 * exec_delta64, sample_interval64);
+
+	this_load = (unsigned long)tmp64;
+
+do_avg:
+
+	/* Update our load: */
+	for (i = 0, scale = 1; i < CPU_LOAD_IDX_MAX; i++, scale += scale) {
+		unsigned long old_load, new_load;
+
+		/* scale is effectively 1 << i now, and >> i divides by scale */
+
+		old_load = this_rq->cpu_load[i];
+		new_load = this_load;
+
+		this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
+	}
 }
 
+#ifdef CONFIG_SMP
+
 /*
  * double_rq_lock - safely lock two runqueues
  *
@@ -2184,23 +2030,17 @@
  * pull_task - move a task from a remote runqueue to the local runqueue.
  * Both runqueues must be locked.
  */
-static void pull_task(struct rq *src_rq, struct prio_array *src_array,
-		      struct task_struct *p, struct rq *this_rq,
-		      struct prio_array *this_array, int this_cpu)
+static void pull_task(struct rq *src_rq, struct task_struct *p,
+		      struct rq *this_rq, int this_cpu)
 {
-	dequeue_task(p, src_array);
-	dec_nr_running(p, src_rq);
+	deactivate_task(src_rq, p, 0);
 	set_task_cpu(p, this_cpu);
-	inc_nr_running(p, this_rq);
-	enqueue_task(p, this_array);
-	p->timestamp = (p->timestamp - src_rq->most_recent_timestamp)
-				+ this_rq->most_recent_timestamp;
+	activate_task(this_rq, p, 0);
 	/*
 	 * Note that idle threads have a prio of MAX_PRIO, for this test
 	 * to be always true for them.
 	 */
-	if (TASK_PREEMPTS_CURR(p, this_rq))
-		resched_task(this_rq->curr);
+	check_preempt_curr(this_rq, p);
 }
 
 /*
@@ -2208,7 +2048,7 @@
  */
 static
 int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
-		     struct sched_domain *sd, enum idle_type idle,
+		     struct sched_domain *sd, enum cpu_idle_type idle,
 		     int *all_pinned)
 {
 	/*
@@ -2225,132 +2065,67 @@
 		return 0;
 
 	/*
-	 * Aggressive migration if:
-	 * 1) task is cache cold, or
-	 * 2) too many balance attempts have failed.
+	 * Aggressive migration if too many balance attempts have failed:
 	 */
-
-	if (sd->nr_balance_failed > sd->cache_nice_tries) {
-#ifdef CONFIG_SCHEDSTATS
-		if (task_hot(p, rq->most_recent_timestamp, sd))
-			schedstat_inc(sd, lb_hot_gained[idle]);
-#endif
+	if (sd->nr_balance_failed > sd->cache_nice_tries)
 		return 1;
-	}
 
-	if (task_hot(p, rq->most_recent_timestamp, sd))
-		return 0;
 	return 1;
 }
 
-#define rq_best_prio(rq) min((rq)->curr->prio, (rq)->best_expired_prio)
-
-/*
- * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
- * load from busiest to this_rq, as part of a balancing operation within
- * "domain". Returns the number of tasks moved.
- *
- * Called with both runqueues locked.
- */
-static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
 		      unsigned long max_nr_move, unsigned long max_load_move,
-		      struct sched_domain *sd, enum idle_type idle,
-		      int *all_pinned)
+		      struct sched_domain *sd, enum cpu_idle_type idle,
+		      int *all_pinned, unsigned long *load_moved,
+		      int this_best_prio, int best_prio, int best_prio_seen,
+		      struct rq_iterator *iterator)
 {
-	int idx, pulled = 0, pinned = 0, this_best_prio, best_prio,
-	    best_prio_seen, skip_for_load;
-	struct prio_array *array, *dst_array;
-	struct list_head *head, *curr;
-	struct task_struct *tmp;
-	long rem_load_move;
+	int pulled = 0, pinned = 0, skip_for_load;
+	struct task_struct *p;
+	long rem_load_move = max_load_move;
 
 	if (max_nr_move == 0 || max_load_move == 0)
 		goto out;
 
-	rem_load_move = max_load_move;
 	pinned = 1;
-	this_best_prio = rq_best_prio(this_rq);
-	best_prio = rq_best_prio(busiest);
-	/*
-	 * Enable handling of the case where there is more than one task
-	 * with the best priority.   If the current running task is one
-	 * of those with prio==best_prio we know it won't be moved
-	 * and therefore it's safe to override the skip (based on load) of
-	 * any task we find with that prio.
-	 */
-	best_prio_seen = best_prio == busiest->curr->prio;
 
 	/*
-	 * We first consider expired tasks. Those will likely not be
-	 * executed in the near future, and they are most likely to
-	 * be cache-cold, thus switching CPUs has the least effect
-	 * on them.
+	 * Start the load-balancing iterator:
 	 */
-	if (busiest->expired->nr_active) {
-		array = busiest->expired;
-		dst_array = this_rq->expired;
-	} else {
-		array = busiest->active;
-		dst_array = this_rq->active;
-	}
-
-new_array:
-	/* Start searching at priority 0: */
-	idx = 0;
-skip_bitmap:
-	if (!idx)
-		idx = sched_find_first_bit(array->bitmap);
-	else
-		idx = find_next_bit(array->bitmap, MAX_PRIO, idx);
-	if (idx >= MAX_PRIO) {
-		if (array == busiest->expired && busiest->active->nr_active) {
-			array = busiest->active;
-			dst_array = this_rq->active;
-			goto new_array;
-		}
+	p = iterator->start(iterator->arg);
+next:
+	if (!p)
 		goto out;
-	}
-
-	head = array->queue + idx;
-	curr = head->prev;
-skip_queue:
-	tmp = list_entry(curr, struct task_struct, run_list);
-
-	curr = curr->prev;
-
 	/*
 	 * To help distribute high priority tasks accross CPUs we don't
 	 * skip a task if it will be the highest priority task (i.e. smallest
 	 * prio value) on its new queue regardless of its load weight
 	 */
-	skip_for_load = tmp->load_weight > rem_load_move;
-	if (skip_for_load && idx < this_best_prio)
-		skip_for_load = !best_prio_seen && idx == best_prio;
+	skip_for_load = (p->se.load.weight >> 1) > rem_load_move +
+							 SCHED_LOAD_SCALE_FUZZ;
+	if (skip_for_load && p->prio < this_best_prio)
+		skip_for_load = !best_prio_seen && p->prio == best_prio;
 	if (skip_for_load ||
-	    !can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) {
+	    !can_migrate_task(p, busiest, this_cpu, sd, idle, &pinned)) {
 
-		best_prio_seen |= idx == best_prio;
-		if (curr != head)
-			goto skip_queue;
-		idx++;
-		goto skip_bitmap;
+		best_prio_seen |= p->prio == best_prio;
+		p = iterator->next(iterator->arg);
+		goto next;
 	}
 
-	pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
+	pull_task(busiest, p, this_rq, this_cpu);
 	pulled++;
-	rem_load_move -= tmp->load_weight;
+	rem_load_move -= p->se.load.weight;
 
 	/*
 	 * We only want to steal up to the prescribed number of tasks
 	 * and the prescribed amount of weighted load.
 	 */
 	if (pulled < max_nr_move && rem_load_move > 0) {
-		if (idx < this_best_prio)
-			this_best_prio = idx;
-		if (curr != head)
-			goto skip_queue;
-		idx++;
-		goto skip_bitmap;
+		if (p->prio < this_best_prio)
+			this_best_prio = p->prio;
+		p = iterator->next(iterator->arg);
+		goto next;
 	}
 out:
 	/*
@@ -2362,18 +2137,48 @@
 
 	if (all_pinned)
 		*all_pinned = pinned;
+	*load_moved = max_load_move - rem_load_move;
 	return pulled;
 }
 
 /*
+ * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
+ * load from busiest to this_rq, as part of a balancing operation within
+ * "domain". Returns the number of tasks moved.
+ *
+ * Called with both runqueues locked.
+ */
+static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+		      unsigned long max_nr_move, unsigned long max_load_move,
+		      struct sched_domain *sd, enum cpu_idle_type idle,
+		      int *all_pinned)
+{
+	struct sched_class *class = sched_class_highest;
+	unsigned long load_moved, total_nr_moved = 0, nr_moved;
+	long rem_load_move = max_load_move;
+
+	do {
+		nr_moved = class->load_balance(this_rq, this_cpu, busiest,
+				max_nr_move, (unsigned long)rem_load_move,
+				sd, idle, all_pinned, &load_moved);
+		total_nr_moved += nr_moved;
+		max_nr_move -= nr_moved;
+		rem_load_move -= load_moved;
+		class = class->next;
+	} while (class && max_nr_move && rem_load_move > 0);
+
+	return total_nr_moved;
+}
+
+/*
  * find_busiest_group finds and returns the busiest CPU group within the
  * domain. It calculates and returns the amount of weighted load which
  * should be moved to restore balance via the imbalance parameter.
  */
 static struct sched_group *
 find_busiest_group(struct sched_domain *sd, int this_cpu,
-		   unsigned long *imbalance, enum idle_type idle, int *sd_idle,
-		   cpumask_t *cpus, int *balance)
+		   unsigned long *imbalance, enum cpu_idle_type idle,
+		   int *sd_idle, cpumask_t *cpus, int *balance)
 {
 	struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
 	unsigned long max_load, avg_load, total_load, this_load, total_pwr;
@@ -2391,9 +2196,9 @@
 	max_load = this_load = total_load = total_pwr = 0;
 	busiest_load_per_task = busiest_nr_running = 0;
 	this_load_per_task = this_nr_running = 0;
-	if (idle == NOT_IDLE)
+	if (idle == CPU_NOT_IDLE)
 		load_idx = sd->busy_idx;
-	else if (idle == NEWLY_IDLE)
+	else if (idle == CPU_NEWLY_IDLE)
 		load_idx = sd->newidle_idx;
 	else
 		load_idx = sd->idle_idx;
@@ -2437,7 +2242,7 @@
 
 			avg_load += load;
 			sum_nr_running += rq->nr_running;
-			sum_weighted_load += rq->raw_weighted_load;
+			sum_weighted_load += weighted_cpuload(i);
 		}
 
 		/*
@@ -2477,8 +2282,9 @@
 		 * Busy processors will not participate in power savings
 		 * balance.
 		 */
- 		if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
- 			goto group_next;
+		if (idle == CPU_NOT_IDLE ||
+				!(sd->flags & SD_POWERSAVINGS_BALANCE))
+			goto group_next;
 
 		/*
 		 * If the local group is idle or completely loaded
@@ -2488,42 +2294,42 @@
 				    !this_nr_running))
 			power_savings_balance = 0;
 
- 		/*
+		/*
 		 * If a group is already running at full capacity or idle,
 		 * don't include that group in power savings calculations
- 		 */
- 		if (!power_savings_balance || sum_nr_running >= group_capacity
+		 */
+		if (!power_savings_balance || sum_nr_running >= group_capacity
 		    || !sum_nr_running)
- 			goto group_next;
+			goto group_next;
 
- 		/*
+		/*
 		 * Calculate the group which has the least non-idle load.
- 		 * This is the group from where we need to pick up the load
- 		 * for saving power
- 		 */
- 		if ((sum_nr_running < min_nr_running) ||
- 		    (sum_nr_running == min_nr_running &&
+		 * This is the group from where we need to pick up the load
+		 * for saving power
+		 */
+		if ((sum_nr_running < min_nr_running) ||
+		    (sum_nr_running == min_nr_running &&
 		     first_cpu(group->cpumask) <
 		     first_cpu(group_min->cpumask))) {
- 			group_min = group;
- 			min_nr_running = sum_nr_running;
+			group_min = group;
+			min_nr_running = sum_nr_running;
 			min_load_per_task = sum_weighted_load /
 						sum_nr_running;
- 		}
+		}
 
- 		/*
+		/*
 		 * Calculate the group which is almost near its
- 		 * capacity but still has some space to pick up some load
- 		 * from other group and save more power
- 		 */
- 		if (sum_nr_running <= group_capacity - 1) {
- 			if (sum_nr_running > leader_nr_running ||
- 			    (sum_nr_running == leader_nr_running &&
- 			     first_cpu(group->cpumask) >
- 			      first_cpu(group_leader->cpumask))) {
- 				group_leader = group;
- 				leader_nr_running = sum_nr_running;
- 			}
+		 * capacity but still has some space to pick up some load
+		 * from other group and save more power
+		 */
+		if (sum_nr_running <= group_capacity - 1) {
+			if (sum_nr_running > leader_nr_running ||
+			    (sum_nr_running == leader_nr_running &&
+			     first_cpu(group->cpumask) >
+			      first_cpu(group_leader->cpumask))) {
+				group_leader = group;
+				leader_nr_running = sum_nr_running;
+			}
 		}
 group_next:
 #endif
@@ -2578,7 +2384,7 @@
 	 * a think about bumping its value to force at least one task to be
 	 * moved
 	 */
-	if (*imbalance < busiest_load_per_task) {
+	if (*imbalance + SCHED_LOAD_SCALE_FUZZ < busiest_load_per_task/2) {
 		unsigned long tmp, pwr_now, pwr_move;
 		unsigned int imbn;
 
@@ -2592,7 +2398,8 @@
 		} else
 			this_load_per_task = SCHED_LOAD_SCALE;
 
-		if (max_load - this_load >= busiest_load_per_task * imbn) {
+		if (max_load - this_load + SCHED_LOAD_SCALE_FUZZ >=
+					busiest_load_per_task * imbn) {
 			*imbalance = busiest_load_per_task;
 			return busiest;
 		}
@@ -2639,7 +2446,7 @@
 
 out_balanced:
 #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
-	if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
+	if (idle == CPU_NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
 		goto ret;
 
 	if (this == group_leader && group_leader != group_min) {
@@ -2656,7 +2463,7 @@
  * find_busiest_queue - find the busiest runqueue among the cpus in group.
  */
 static struct rq *
-find_busiest_queue(struct sched_group *group, enum idle_type idle,
+find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle,
 		   unsigned long imbalance, cpumask_t *cpus)
 {
 	struct rq *busiest = NULL, *rq;
@@ -2664,17 +2471,19 @@
 	int i;
 
 	for_each_cpu_mask(i, group->cpumask) {
+		unsigned long wl;
 
 		if (!cpu_isset(i, *cpus))
 			continue;
 
 		rq = cpu_rq(i);
+		wl = weighted_cpuload(i);
 
-		if (rq->nr_running == 1 && rq->raw_weighted_load > imbalance)
+		if (rq->nr_running == 1 && wl > imbalance)
 			continue;
 
-		if (rq->raw_weighted_load > max_load) {
-			max_load = rq->raw_weighted_load;
+		if (wl > max_load) {
+			max_load = wl;
 			busiest = rq;
 		}
 	}
@@ -2698,7 +2507,7 @@
  * tasks if there is an imbalance.
  */
 static int load_balance(int this_cpu, struct rq *this_rq,
-			struct sched_domain *sd, enum idle_type idle,
+			struct sched_domain *sd, enum cpu_idle_type idle,
 			int *balance)
 {
 	int nr_moved, all_pinned = 0, active_balance = 0, sd_idle = 0;
@@ -2711,10 +2520,10 @@
 	/*
 	 * When power savings policy is enabled for the parent domain, idle
 	 * sibling can pick up load irrespective of busy siblings. In this case,
-	 * let the state of idle sibling percolate up as IDLE, instead of
-	 * portraying it as NOT_IDLE.
+	 * let the state of idle sibling percolate up as CPU_IDLE, instead of
+	 * portraying it as CPU_NOT_IDLE.
 	 */
-	if (idle != NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER &&
+	if (idle != CPU_NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER &&
 	    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
 		sd_idle = 1;
 
@@ -2848,7 +2657,7 @@
  * Check this_cpu to ensure it is balanced within domain. Attempt to move
  * tasks if there is an imbalance.
  *
- * Called from schedule when this_rq is about to become idle (NEWLY_IDLE).
+ * Called from schedule when this_rq is about to become idle (CPU_NEWLY_IDLE).
  * this_rq is locked.
  */
 static int
@@ -2865,31 +2674,31 @@
 	 * When power savings policy is enabled for the parent domain, idle
 	 * sibling can pick up load irrespective of busy siblings. In this case,
 	 * let the state of idle sibling percolate up as IDLE, instead of
-	 * portraying it as NOT_IDLE.
+	 * portraying it as CPU_NOT_IDLE.
 	 */
 	if (sd->flags & SD_SHARE_CPUPOWER &&
 	    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
 		sd_idle = 1;
 
-	schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
+	schedstat_inc(sd, lb_cnt[CPU_NEWLY_IDLE]);
 redo:
-	group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE,
+	group = find_busiest_group(sd, this_cpu, &imbalance, CPU_NEWLY_IDLE,
 				   &sd_idle, &cpus, NULL);
 	if (!group) {
-		schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
+		schedstat_inc(sd, lb_nobusyg[CPU_NEWLY_IDLE]);
 		goto out_balanced;
 	}
 
-	busiest = find_busiest_queue(group, NEWLY_IDLE, imbalance,
+	busiest = find_busiest_queue(group, CPU_NEWLY_IDLE, imbalance,
 				&cpus);
 	if (!busiest) {
-		schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]);
+		schedstat_inc(sd, lb_nobusyq[CPU_NEWLY_IDLE]);
 		goto out_balanced;
 	}
 
 	BUG_ON(busiest == this_rq);
 
-	schedstat_add(sd, lb_imbalance[NEWLY_IDLE], imbalance);
+	schedstat_add(sd, lb_imbalance[CPU_NEWLY_IDLE], imbalance);
 
 	nr_moved = 0;
 	if (busiest->nr_running > 1) {
@@ -2897,7 +2706,7 @@
 		double_lock_balance(this_rq, busiest);
 		nr_moved = move_tasks(this_rq, this_cpu, busiest,
 					minus_1_or_zero(busiest->nr_running),
-					imbalance, sd, NEWLY_IDLE, NULL);
+					imbalance, sd, CPU_NEWLY_IDLE, NULL);
 		spin_unlock(&busiest->lock);
 
 		if (!nr_moved) {
@@ -2908,7 +2717,7 @@
 	}
 
 	if (!nr_moved) {
-		schedstat_inc(sd, lb_failed[NEWLY_IDLE]);
+		schedstat_inc(sd, lb_failed[CPU_NEWLY_IDLE]);
 		if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
 		    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
 			return -1;
@@ -2918,7 +2727,7 @@
 	return nr_moved;
 
 out_balanced:
-	schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
+	schedstat_inc(sd, lb_balanced[CPU_NEWLY_IDLE]);
 	if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
 	    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
 		return -1;
@@ -2934,8 +2743,8 @@
 static void idle_balance(int this_cpu, struct rq *this_rq)
 {
 	struct sched_domain *sd;
-	int pulled_task = 0;
-	unsigned long next_balance = jiffies + 60 *  HZ;
+	int pulled_task = -1;
+	unsigned long next_balance = jiffies + HZ;
 
 	for_each_domain(this_cpu, sd) {
 		unsigned long interval;
@@ -2954,12 +2763,13 @@
 		if (pulled_task)
 			break;
 	}
-	if (!pulled_task)
+	if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
 		/*
 		 * We are going idle. next_balance may be set based on
 		 * a busy processor. So reset next_balance.
 		 */
 		this_rq->next_balance = next_balance;
+	}
 }
 
 /*
@@ -3003,7 +2813,7 @@
 		schedstat_inc(sd, alb_cnt);
 
 		if (move_tasks(target_rq, target_cpu, busiest_rq, 1,
-			       RTPRIO_TO_LOAD_WEIGHT(100), sd, SCHED_IDLE,
+			       RTPRIO_TO_LOAD_WEIGHT(100), sd, CPU_IDLE,
 			       NULL))
 			schedstat_inc(sd, alb_pushed);
 		else
@@ -3012,32 +2822,6 @@
 	spin_unlock(&target_rq->lock);
 }
 
-static void update_load(struct rq *this_rq)
-{
-	unsigned long this_load;
-	unsigned int i, scale;
-
-	this_load = this_rq->raw_weighted_load;
-
-	/* Update our load: */
-	for (i = 0, scale = 1; i < 3; i++, scale += scale) {
-		unsigned long old_load, new_load;
-
-		/* scale is effectively 1 << i now, and >> i divides by scale */
-
-		old_load = this_rq->cpu_load[i];
-		new_load = this_load;
-		/*
-		 * Round up the averaging division if load is increasing. This
-		 * prevents us from getting stuck on 9 if the load is 10, for
-		 * example.
-		 */
-		if (new_load > old_load)
-			new_load += scale-1;
-		this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
-	}
-}
-
 #ifdef CONFIG_NO_HZ
 static struct {
 	atomic_t load_balancer;
@@ -3120,7 +2904,7 @@
  *
  * Balancing parameters are set up in arch_init_sched_domains.
  */
-static inline void rebalance_domains(int cpu, enum idle_type idle)
+static inline void rebalance_domains(int cpu, enum cpu_idle_type idle)
 {
 	int balance = 1;
 	struct rq *rq = cpu_rq(cpu);
@@ -3134,13 +2918,16 @@
 			continue;
 
 		interval = sd->balance_interval;
-		if (idle != SCHED_IDLE)
+		if (idle != CPU_IDLE)
 			interval *= sd->busy_factor;
 
 		/* scale ms to jiffies */
 		interval = msecs_to_jiffies(interval);
 		if (unlikely(!interval))
 			interval = 1;
+		if (interval > HZ*NR_CPUS/10)
+			interval = HZ*NR_CPUS/10;
+
 
 		if (sd->flags & SD_SERIALIZE) {
 			if (!spin_trylock(&balancing))
@@ -3154,7 +2941,7 @@
 				 * longer idle, or one of our SMT siblings is
 				 * not idle.
 				 */
-				idle = NOT_IDLE;
+				idle = CPU_NOT_IDLE;
 			}
 			sd->last_balance = jiffies;
 		}
@@ -3182,11 +2969,12 @@
  */
 static void run_rebalance_domains(struct softirq_action *h)
 {
-	int local_cpu = smp_processor_id();
-	struct rq *local_rq = cpu_rq(local_cpu);
-	enum idle_type idle = local_rq->idle_at_tick ? SCHED_IDLE : NOT_IDLE;
+	int this_cpu = smp_processor_id();
+	struct rq *this_rq = cpu_rq(this_cpu);
+	enum cpu_idle_type idle = this_rq->idle_at_tick ?
+						CPU_IDLE : CPU_NOT_IDLE;
 
-	rebalance_domains(local_cpu, idle);
+	rebalance_domains(this_cpu, idle);
 
 #ifdef CONFIG_NO_HZ
 	/*
@@ -3194,13 +2982,13 @@
 	 * balancing on behalf of the other idle cpus whose ticks are
 	 * stopped.
 	 */
-	if (local_rq->idle_at_tick &&
-	    atomic_read(&nohz.load_balancer) == local_cpu) {
+	if (this_rq->idle_at_tick &&
+	    atomic_read(&nohz.load_balancer) == this_cpu) {
 		cpumask_t cpus = nohz.cpu_mask;
 		struct rq *rq;
 		int balance_cpu;
 
-		cpu_clear(local_cpu, cpus);
+		cpu_clear(this_cpu, cpus);
 		for_each_cpu_mask(balance_cpu, cpus) {
 			/*
 			 * If this cpu gets work to do, stop the load balancing
@@ -3213,8 +3001,8 @@
 			rebalance_domains(balance_cpu, SCHED_IDLE);
 
 			rq = cpu_rq(balance_cpu);
-			if (time_after(local_rq->next_balance, rq->next_balance))
-				local_rq->next_balance = rq->next_balance;
+			if (time_after(this_rq->next_balance, rq->next_balance))
+				this_rq->next_balance = rq->next_balance;
 		}
 	}
 #endif
@@ -3227,9 +3015,8 @@
  * idle load balancing owner or decide to stop the periodic load balancing,
  * if the whole system is idle.
  */
-static inline void trigger_load_balance(int cpu)
+static inline void trigger_load_balance(struct rq *rq, int cpu)
 {
-	struct rq *rq = cpu_rq(cpu);
 #ifdef CONFIG_NO_HZ
 	/*
 	 * If we were in the nohz mode recently and busy at the current
@@ -3281,13 +3068,29 @@
 	if (time_after_eq(jiffies, rq->next_balance))
 		raise_softirq(SCHED_SOFTIRQ);
 }
-#else
+
+#else	/* CONFIG_SMP */
+
 /*
  * on UP we do not need to balance between CPUs:
  */
 static inline void idle_balance(int cpu, struct rq *rq)
 {
 }
+
+/* Avoid "used but not defined" warning on UP */
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+		      unsigned long max_nr_move, unsigned long max_load_move,
+		      struct sched_domain *sd, enum cpu_idle_type idle,
+		      int *all_pinned, unsigned long *load_moved,
+		      int this_best_prio, int best_prio, int best_prio_seen,
+		      struct rq_iterator *iterator)
+{
+	*load_moved = 0;
+
+	return 0;
+}
+
 #endif
 
 DEFINE_PER_CPU(struct kernel_stat, kstat);
@@ -3295,54 +3098,28 @@
 EXPORT_PER_CPU_SYMBOL(kstat);
 
 /*
- * This is called on clock ticks and on context switches.
- * Bank in p->sched_time the ns elapsed since the last tick or switch.
+ * Return p->sum_exec_runtime plus any more ns on the sched_clock
+ * that have not yet been banked in case the task is currently running.
  */
-static inline void
-update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now)
+unsigned long long task_sched_runtime(struct task_struct *p)
 {
-	p->sched_time += now - p->last_ran;
-	p->last_ran = rq->most_recent_timestamp = now;
-}
-
-/*
- * Return current->sched_time plus any more ns on the sched_clock
- * that have not yet been banked.
- */
-unsigned long long current_sched_time(const struct task_struct *p)
-{
-	unsigned long long ns;
 	unsigned long flags;
+	u64 ns, delta_exec;
+	struct rq *rq;
 
-	local_irq_save(flags);
-	ns = p->sched_time + sched_clock() - p->last_ran;
-	local_irq_restore(flags);
+	rq = task_rq_lock(p, &flags);
+	ns = p->se.sum_exec_runtime;
+	if (rq->curr == p) {
+		delta_exec = rq_clock(rq) - p->se.exec_start;
+		if ((s64)delta_exec > 0)
+			ns += delta_exec;
+	}
+	task_rq_unlock(rq, &flags);
 
 	return ns;
 }
 
 /*
- * We place interactive tasks back into the active array, if possible.
- *
- * To guarantee that this does not starve expired tasks we ignore the
- * interactivity of a task if the first expired task had to wait more
- * than a 'reasonable' amount of time. This deadline timeout is
- * load-dependent, as the frequency of array switched decreases with
- * increasing number of running tasks. We also ignore the interactivity
- * if a better static_prio task has expired:
- */
-static inline int expired_starving(struct rq *rq)
-{
-	if (rq->curr->static_prio > rq->best_expired_prio)
-		return 1;
-	if (!STARVATION_LIMIT || !rq->expired_timestamp)
-		return 0;
-	if (jiffies - rq->expired_timestamp > STARVATION_LIMIT * rq->nr_running)
-		return 1;
-	return 0;
-}
-
-/*
  * Account user cpu time to a process.
  * @p: the process that the cpu time gets accounted to
  * @hardirq_offset: the offset to subtract from hardirq_count()
@@ -3415,81 +3192,6 @@
 		cpustat->steal = cputime64_add(cpustat->steal, tmp);
 }
 
-static void task_running_tick(struct rq *rq, struct task_struct *p)
-{
-	if (p->array != rq->active) {
-		/* Task has expired but was not scheduled yet */
-		set_tsk_need_resched(p);
-		return;
-	}
-	spin_lock(&rq->lock);
-	/*
-	 * The task was running during this tick - update the
-	 * time slice counter. Note: we do not update a thread's
-	 * priority until it either goes to sleep or uses up its
-	 * timeslice. This makes it possible for interactive tasks
-	 * to use up their timeslices at their highest priority levels.
-	 */
-	if (rt_task(p)) {
-		/*
-		 * RR tasks need a special form of timeslice management.
-		 * FIFO tasks have no timeslices.
-		 */
-		if ((p->policy == SCHED_RR) && !--p->time_slice) {
-			p->time_slice = task_timeslice(p);
-			p->first_time_slice = 0;
-			set_tsk_need_resched(p);
-
-			/* put it at the end of the queue: */
-			requeue_task(p, rq->active);
-		}
-		goto out_unlock;
-	}
-	if (!--p->time_slice) {
-		dequeue_task(p, rq->active);
-		set_tsk_need_resched(p);
-		p->prio = effective_prio(p);
-		p->time_slice = task_timeslice(p);
-		p->first_time_slice = 0;
-
-		if (!rq->expired_timestamp)
-			rq->expired_timestamp = jiffies;
-		if (!TASK_INTERACTIVE(p) || expired_starving(rq)) {
-			enqueue_task(p, rq->expired);
-			if (p->static_prio < rq->best_expired_prio)
-				rq->best_expired_prio = p->static_prio;
-		} else
-			enqueue_task(p, rq->active);
-	} else {
-		/*
-		 * Prevent a too long timeslice allowing a task to monopolize
-		 * the CPU. We do this by splitting up the timeslice into
-		 * smaller pieces.
-		 *
-		 * Note: this does not mean the task's timeslices expire or
-		 * get lost in any way, they just might be preempted by
-		 * another task of equal priority. (one with higher
-		 * priority would have preempted this task already.) We
-		 * requeue this task to the end of the list on this priority
-		 * level, which is in essence a round-robin of tasks with
-		 * equal priority.
-		 *
-		 * This only applies to tasks in the interactive
-		 * delta range with at least TIMESLICE_GRANULARITY to requeue.
-		 */
-		if (TASK_INTERACTIVE(p) && !((task_timeslice(p) -
-			p->time_slice) % TIMESLICE_GRANULARITY(p)) &&
-			(p->time_slice >= TIMESLICE_GRANULARITY(p)) &&
-			(p->array == rq->active)) {
-
-			requeue_task(p, rq->active);
-			set_tsk_need_resched(p);
-		}
-	}
-out_unlock:
-	spin_unlock(&rq->lock);
-}
-
 /*
  * This function gets called by the timer code, with HZ frequency.
  * We call it with interrupts disabled.
@@ -3499,20 +3201,19 @@
  */
 void scheduler_tick(void)
 {
-	unsigned long long now = sched_clock();
-	struct task_struct *p = current;
 	int cpu = smp_processor_id();
-	int idle_at_tick = idle_cpu(cpu);
 	struct rq *rq = cpu_rq(cpu);
+	struct task_struct *curr = rq->curr;
 
-	update_cpu_clock(p, rq, now);
+	spin_lock(&rq->lock);
+	if (curr != rq->idle) /* FIXME: needed? */
+		curr->sched_class->task_tick(rq, curr);
+	update_cpu_load(rq);
+	spin_unlock(&rq->lock);
 
-	if (!idle_at_tick)
-		task_running_tick(rq, p);
 #ifdef CONFIG_SMP
-	update_load(rq);
-	rq->idle_at_tick = idle_at_tick;
-	trigger_load_balance(cpu);
+	rq->idle_at_tick = idle_cpu(cpu);
+	trigger_load_balance(rq, cpu);
 #endif
 }
 
@@ -3554,10 +3255,67 @@
 
 #endif
 
-static inline int interactive_sleep(enum sleep_type sleep_type)
+/*
+ * Print scheduling while atomic bug:
+ */
+static noinline void __schedule_bug(struct task_struct *prev)
 {
-	return (sleep_type == SLEEP_INTERACTIVE ||
-		sleep_type == SLEEP_INTERRUPTED);
+	printk(KERN_ERR "BUG: scheduling while atomic: %s/0x%08x/%d\n",
+		prev->comm, preempt_count(), prev->pid);
+	debug_show_held_locks(prev);
+	if (irqs_disabled())
+		print_irqtrace_events(prev);
+	dump_stack();
+}
+
+/*
+ * Various schedule()-time debugging checks and statistics:
+ */
+static inline void schedule_debug(struct task_struct *prev)
+{
+	/*
+	 * Test if we are atomic.  Since do_exit() needs to call into
+	 * schedule() atomically, we ignore that path for now.
+	 * Otherwise, whine if we are scheduling when we should not be.
+	 */
+	if (unlikely(in_atomic_preempt_off()) && unlikely(!prev->exit_state))
+		__schedule_bug(prev);
+
+	profile_hit(SCHED_PROFILING, __builtin_return_address(0));
+
+	schedstat_inc(this_rq(), sched_cnt);
+}
+
+/*
+ * Pick up the highest-prio task:
+ */
+static inline struct task_struct *
+pick_next_task(struct rq *rq, struct task_struct *prev, u64 now)
+{
+	struct sched_class *class;
+	struct task_struct *p;
+
+	/*
+	 * Optimization: we know that if all tasks are in
+	 * the fair class we can call that function directly:
+	 */
+	if (likely(rq->nr_running == rq->cfs.nr_running)) {
+		p = fair_sched_class.pick_next_task(rq, now);
+		if (likely(p))
+			return p;
+	}
+
+	class = sched_class_highest;
+	for ( ; ; ) {
+		p = class->pick_next_task(rq, now);
+		if (p)
+			return p;
+		/*
+		 * Will never be NULL as the idle class always
+		 * returns a non-NULL p:
+		 */
+		class = class->next;
+	}
 }
 
 /*
@@ -3566,158 +3324,60 @@
 asmlinkage void __sched schedule(void)
 {
 	struct task_struct *prev, *next;
-	struct prio_array *array;
-	struct list_head *queue;
-	unsigned long long now;
-	unsigned long run_time;
-	int cpu, idx, new_prio;
 	long *switch_count;
 	struct rq *rq;
-
-	/*
-	 * Test if we are atomic.  Since do_exit() needs to call into
-	 * schedule() atomically, we ignore that path for now.
-	 * Otherwise, whine if we are scheduling when we should not be.
-	 */
-	if (unlikely(in_atomic() && !current->exit_state)) {
-		printk(KERN_ERR "BUG: scheduling while atomic: "
-			"%s/0x%08x/%d\n",
-			current->comm, preempt_count(), current->pid);
-		debug_show_held_locks(current);
-		if (irqs_disabled())
-			print_irqtrace_events(current);
-		dump_stack();
-	}
-	profile_hit(SCHED_PROFILING, __builtin_return_address(0));
+	u64 now;
+	int cpu;
 
 need_resched:
 	preempt_disable();
-	prev = current;
+	cpu = smp_processor_id();
+	rq = cpu_rq(cpu);
+	rcu_qsctr_inc(cpu);
+	prev = rq->curr;
+	switch_count = &prev->nivcsw;
+
 	release_kernel_lock(prev);
 need_resched_nonpreemptible:
-	rq = this_rq();
 
-	/*
-	 * The idle thread is not allowed to schedule!
-	 * Remove this check after it has been exercised a bit.
-	 */
-	if (unlikely(prev == rq->idle) && prev->state != TASK_RUNNING) {
-		printk(KERN_ERR "bad: scheduling from the idle thread!\n");
-		dump_stack();
-	}
-
-	schedstat_inc(rq, sched_cnt);
-	now = sched_clock();
-	if (likely((long long)(now - prev->timestamp) < NS_MAX_SLEEP_AVG)) {
-		run_time = now - prev->timestamp;
-		if (unlikely((long long)(now - prev->timestamp) < 0))
-			run_time = 0;
-	} else
-		run_time = NS_MAX_SLEEP_AVG;
-
-	/*
-	 * Tasks charged proportionately less run_time at high sleep_avg to
-	 * delay them losing their interactive status
-	 */
-	run_time /= (CURRENT_BONUS(prev) ? : 1);
+	schedule_debug(prev);
 
 	spin_lock_irq(&rq->lock);
-
-	switch_count = &prev->nivcsw;
-	if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
-		switch_count = &prev->nvcsw;
-		if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
-				unlikely(signal_pending(prev))))
-			prev->state = TASK_RUNNING;
-		else {
-			if (prev->state == TASK_UNINTERRUPTIBLE)
-				rq->nr_uninterruptible++;
-			deactivate_task(prev, rq);
-		}
-	}
-
-	cpu = smp_processor_id();
-	if (unlikely(!rq->nr_running)) {
-		idle_balance(cpu, rq);
-		if (!rq->nr_running) {
-			next = rq->idle;
-			rq->expired_timestamp = 0;
-			goto switch_tasks;
-		}
-	}
-
-	array = rq->active;
-	if (unlikely(!array->nr_active)) {
-		/*
-		 * Switch the active and expired arrays.
-		 */
-		schedstat_inc(rq, sched_switch);
-		rq->active = rq->expired;
-		rq->expired = array;
-		array = rq->active;
-		rq->expired_timestamp = 0;
-		rq->best_expired_prio = MAX_PRIO;
-	}
-
-	idx = sched_find_first_bit(array->bitmap);
-	queue = array->queue + idx;
-	next = list_entry(queue->next, struct task_struct, run_list);
-
-	if (!rt_task(next) && interactive_sleep(next->sleep_type)) {
-		unsigned long long delta = now - next->timestamp;
-		if (unlikely((long long)(now - next->timestamp) < 0))
-			delta = 0;
-
-		if (next->sleep_type == SLEEP_INTERACTIVE)
-			delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
-
-		array = next->array;
-		new_prio = recalc_task_prio(next, next->timestamp + delta);
-
-		if (unlikely(next->prio != new_prio)) {
-			dequeue_task(next, array);
-			next->prio = new_prio;
-			enqueue_task(next, array);
-		}
-	}
-	next->sleep_type = SLEEP_NORMAL;
-switch_tasks:
-	if (next == rq->idle)
-		schedstat_inc(rq, sched_goidle);
-	prefetch(next);
-	prefetch_stack(next);
 	clear_tsk_need_resched(prev);
-	rcu_qsctr_inc(task_cpu(prev));
 
-	update_cpu_clock(prev, rq, now);
+	if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
+		if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
+				unlikely(signal_pending(prev)))) {
+			prev->state = TASK_RUNNING;
+		} else {
+			deactivate_task(rq, prev, 1);
+		}
+		switch_count = &prev->nvcsw;
+	}
 
-	prev->sleep_avg -= run_time;
-	if ((long)prev->sleep_avg <= 0)
-		prev->sleep_avg = 0;
-	prev->timestamp = prev->last_ran = now;
+	if (unlikely(!rq->nr_running))
+		idle_balance(cpu, rq);
+
+	now = __rq_clock(rq);
+	prev->sched_class->put_prev_task(rq, prev, now);
+	next = pick_next_task(rq, prev, now);
 
 	sched_info_switch(prev, next);
+
 	if (likely(prev != next)) {
-		next->timestamp = next->last_ran = now;
 		rq->nr_switches++;
 		rq->curr = next;
 		++*switch_count;
 
-		prepare_task_switch(rq, next);
-		prev = context_switch(rq, prev, next);
-		barrier();
-		/*
-		 * this_rq must be evaluated again because prev may have moved
-		 * CPUs since it called schedule(), thus the 'rq' on its stack
-		 * frame will be invalid.
-		 */
-		finish_task_switch(this_rq(), prev);
+		context_switch(rq, prev, next); /* unlocks the rq */
 	} else
 		spin_unlock_irq(&rq->lock);
 
-	prev = current;
-	if (unlikely(reacquire_kernel_lock(prev) < 0))
+	if (unlikely(reacquire_kernel_lock(current) < 0)) {
+		cpu = smp_processor_id();
+		rq = cpu_rq(cpu);
 		goto need_resched_nonpreemptible;
+	}
 	preempt_enable_no_resched();
 	if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
 		goto need_resched;
@@ -4045,74 +3705,85 @@
 }
 EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);
 
-
-#define	SLEEP_ON_VAR					\
-	unsigned long flags;				\
-	wait_queue_t wait;				\
-	init_waitqueue_entry(&wait, current);
-
-#define SLEEP_ON_HEAD					\
-	spin_lock_irqsave(&q->lock,flags);		\
-	__add_wait_queue(q, &wait);			\
-	spin_unlock(&q->lock);
-
-#define	SLEEP_ON_TAIL					\
-	spin_lock_irq(&q->lock);			\
-	__remove_wait_queue(q, &wait);			\
-	spin_unlock_irqrestore(&q->lock, flags);
-
-void fastcall __sched interruptible_sleep_on(wait_queue_head_t *q)
+static inline void
+sleep_on_head(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags)
 {
-	SLEEP_ON_VAR
+	spin_lock_irqsave(&q->lock, *flags);
+	__add_wait_queue(q, wait);
+	spin_unlock(&q->lock);
+}
+
+static inline void
+sleep_on_tail(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags)
+{
+	spin_lock_irq(&q->lock);
+	__remove_wait_queue(q, wait);
+	spin_unlock_irqrestore(&q->lock, *flags);
+}
+
+void __sched interruptible_sleep_on(wait_queue_head_t *q)
+{
+	unsigned long flags;
+	wait_queue_t wait;
+
+	init_waitqueue_entry(&wait, current);
 
 	current->state = TASK_INTERRUPTIBLE;
 
-	SLEEP_ON_HEAD
+	sleep_on_head(q, &wait, &flags);
 	schedule();
-	SLEEP_ON_TAIL
+	sleep_on_tail(q, &wait, &flags);
 }
 EXPORT_SYMBOL(interruptible_sleep_on);
 
-long fastcall __sched
+long __sched
 interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
-	SLEEP_ON_VAR
+	unsigned long flags;
+	wait_queue_t wait;
+
+	init_waitqueue_entry(&wait, current);
 
 	current->state = TASK_INTERRUPTIBLE;
 
-	SLEEP_ON_HEAD
+	sleep_on_head(q, &wait, &flags);
 	timeout = schedule_timeout(timeout);
-	SLEEP_ON_TAIL
+	sleep_on_tail(q, &wait, &flags);
 
 	return timeout;
 }
 EXPORT_SYMBOL(interruptible_sleep_on_timeout);
 
-void fastcall __sched sleep_on(wait_queue_head_t *q)
+void __sched sleep_on(wait_queue_head_t *q)
 {
-	SLEEP_ON_VAR
+	unsigned long flags;
+	wait_queue_t wait;
+
+	init_waitqueue_entry(&wait, current);
 
 	current->state = TASK_UNINTERRUPTIBLE;
 
-	SLEEP_ON_HEAD
+	sleep_on_head(q, &wait, &flags);
 	schedule();
-	SLEEP_ON_TAIL
+	sleep_on_tail(q, &wait, &flags);
 }
 EXPORT_SYMBOL(sleep_on);
 
-long fastcall __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)
+long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
-	SLEEP_ON_VAR
+	unsigned long flags;
+	wait_queue_t wait;
+
+	init_waitqueue_entry(&wait, current);
 
 	current->state = TASK_UNINTERRUPTIBLE;
 
-	SLEEP_ON_HEAD
+	sleep_on_head(q, &wait, &flags);
 	timeout = schedule_timeout(timeout);
-	SLEEP_ON_TAIL
+	sleep_on_tail(q, &wait, &flags);
 
 	return timeout;
 }
-
 EXPORT_SYMBOL(sleep_on_timeout);
 
 #ifdef CONFIG_RT_MUTEXES
@@ -4129,29 +3800,30 @@
  */
 void rt_mutex_setprio(struct task_struct *p, int prio)
 {
-	struct prio_array *array;
 	unsigned long flags;
+	int oldprio, on_rq;
 	struct rq *rq;
-	int oldprio;
+	u64 now;
 
 	BUG_ON(prio < 0 || prio > MAX_PRIO);
 
 	rq = task_rq_lock(p, &flags);
+	now = rq_clock(rq);
 
 	oldprio = p->prio;
-	array = p->array;
-	if (array)
-		dequeue_task(p, array);
+	on_rq = p->se.on_rq;
+	if (on_rq)
+		dequeue_task(rq, p, 0, now);
+
+	if (rt_prio(prio))
+		p->sched_class = &rt_sched_class;
+	else
+		p->sched_class = &fair_sched_class;
+
 	p->prio = prio;
 
-	if (array) {
-		/*
-		 * If changing to an RT priority then queue it
-		 * in the active array!
-		 */
-		if (rt_task(p))
-			array = rq->active;
-		enqueue_task(p, array);
+	if (on_rq) {
+		enqueue_task(rq, p, 0, now);
 		/*
 		 * Reschedule if we are currently running on this runqueue and
 		 * our priority decreased, or if we are not currently running on
@@ -4160,8 +3832,9 @@
 		if (task_running(rq, p)) {
 			if (p->prio > oldprio)
 				resched_task(rq->curr);
-		} else if (TASK_PREEMPTS_CURR(p, rq))
-			resched_task(rq->curr);
+		} else {
+			check_preempt_curr(rq, p);
+		}
 	}
 	task_rq_unlock(rq, &flags);
 }
@@ -4170,10 +3843,10 @@
 
 void set_user_nice(struct task_struct *p, long nice)
 {
-	struct prio_array *array;
-	int old_prio, delta;
+	int old_prio, delta, on_rq;
 	unsigned long flags;
 	struct rq *rq;
+	u64 now;
 
 	if (TASK_NICE(p) == nice || nice < -20 || nice > 19)
 		return;
@@ -4182,20 +3855,21 @@
 	 * the task might be in the middle of scheduling on another CPU.
 	 */
 	rq = task_rq_lock(p, &flags);
+	now = rq_clock(rq);
 	/*
 	 * The RT priorities are set via sched_setscheduler(), but we still
 	 * allow the 'normal' nice value to be set - but as expected
 	 * it wont have any effect on scheduling until the task is
-	 * not SCHED_NORMAL/SCHED_BATCH:
+	 * SCHED_FIFO/SCHED_RR:
 	 */
-	if (has_rt_policy(p)) {
+	if (task_has_rt_policy(p)) {
 		p->static_prio = NICE_TO_PRIO(nice);
 		goto out_unlock;
 	}
-	array = p->array;
-	if (array) {
-		dequeue_task(p, array);
-		dec_raw_weighted_load(rq, p);
+	on_rq = p->se.on_rq;
+	if (on_rq) {
+		dequeue_task(rq, p, 0, now);
+		dec_load(rq, p, now);
 	}
 
 	p->static_prio = NICE_TO_PRIO(nice);
@@ -4204,9 +3878,9 @@
 	p->prio = effective_prio(p);
 	delta = p->prio - old_prio;
 
-	if (array) {
-		enqueue_task(p, array);
-		inc_raw_weighted_load(rq, p);
+	if (on_rq) {
+		enqueue_task(rq, p, 0, now);
+		inc_load(rq, p, now);
 		/*
 		 * If the task increased its priority or is running and
 		 * lowered its priority, then reschedule its CPU:
@@ -4326,20 +4000,28 @@
 }
 
 /* Actually do priority change: must hold rq lock. */
-static void __setscheduler(struct task_struct *p, int policy, int prio)
+static void
+__setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
 {
-	BUG_ON(p->array);
+	BUG_ON(p->se.on_rq);
 
 	p->policy = policy;
+	switch (p->policy) {
+	case SCHED_NORMAL:
+	case SCHED_BATCH:
+	case SCHED_IDLE:
+		p->sched_class = &fair_sched_class;
+		break;
+	case SCHED_FIFO:
+	case SCHED_RR:
+		p->sched_class = &rt_sched_class;
+		break;
+	}
+
 	p->rt_priority = prio;
 	p->normal_prio = normal_prio(p);
 	/* we are holding p->pi_lock already */
 	p->prio = rt_mutex_getprio(p);
-	/*
-	 * SCHED_BATCH tasks are treated as perpetual CPU hogs:
-	 */
-	if (policy == SCHED_BATCH)
-		p->sleep_avg = 0;
 	set_load_weight(p);
 }
 
@@ -4354,8 +4036,7 @@
 int sched_setscheduler(struct task_struct *p, int policy,
 		       struct sched_param *param)
 {
-	int retval, oldprio, oldpolicy = -1;
-	struct prio_array *array;
+	int retval, oldprio, oldpolicy = -1, on_rq;
 	unsigned long flags;
 	struct rq *rq;
 
@@ -4366,27 +4047,27 @@
 	if (policy < 0)
 		policy = oldpolicy = p->policy;
 	else if (policy != SCHED_FIFO && policy != SCHED_RR &&
-			policy != SCHED_NORMAL && policy != SCHED_BATCH)
+			policy != SCHED_NORMAL && policy != SCHED_BATCH &&
+			policy != SCHED_IDLE)
 		return -EINVAL;
 	/*
 	 * Valid priorities for SCHED_FIFO and SCHED_RR are
-	 * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and
-	 * SCHED_BATCH is 0.
+	 * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL,
+	 * SCHED_BATCH and SCHED_IDLE is 0.
 	 */
 	if (param->sched_priority < 0 ||
 	    (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) ||
 	    (!p->mm && param->sched_priority > MAX_RT_PRIO-1))
 		return -EINVAL;
-	if (is_rt_policy(policy) != (param->sched_priority != 0))
+	if (rt_policy(policy) != (param->sched_priority != 0))
 		return -EINVAL;
 
 	/*
 	 * Allow unprivileged RT tasks to decrease priority:
 	 */
 	if (!capable(CAP_SYS_NICE)) {
-		if (is_rt_policy(policy)) {
+		if (rt_policy(policy)) {
 			unsigned long rlim_rtprio;
-			unsigned long flags;
 
 			if (!lock_task_sighand(p, &flags))
 				return -ESRCH;
@@ -4402,6 +4083,12 @@
 			    param->sched_priority > rlim_rtprio)
 				return -EPERM;
 		}
+		/*
+		 * Like positive nice levels, dont allow tasks to
+		 * move out of SCHED_IDLE either:
+		 */
+		if (p->policy == SCHED_IDLE && policy != SCHED_IDLE)
+			return -EPERM;
 
 		/* can't change other user's priorities */
 		if ((current->euid != p->euid) &&
@@ -4429,13 +4116,13 @@
 		spin_unlock_irqrestore(&p->pi_lock, flags);
 		goto recheck;
 	}
-	array = p->array;
-	if (array)
-		deactivate_task(p, rq);
+	on_rq = p->se.on_rq;
+	if (on_rq)
+		deactivate_task(rq, p, 0);
 	oldprio = p->prio;
-	__setscheduler(p, policy, param->sched_priority);
-	if (array) {
-		__activate_task(p, rq);
+	__setscheduler(rq, p, policy, param->sched_priority);
+	if (on_rq) {
+		activate_task(rq, p, 0);
 		/*
 		 * Reschedule if we are currently running on this runqueue and
 		 * our priority decreased, or if we are not currently running on
@@ -4444,8 +4131,9 @@
 		if (task_running(rq, p)) {
 			if (p->prio > oldprio)
 				resched_task(rq->curr);
-		} else if (TASK_PREEMPTS_CURR(p, rq))
-			resched_task(rq->curr);
+		} else {
+			check_preempt_curr(rq, p);
+		}
 	}
 	__task_rq_unlock(rq);
 	spin_unlock_irqrestore(&p->pi_lock, flags);
@@ -4717,41 +4405,18 @@
 /**
  * sys_sched_yield - yield the current processor to other threads.
  *
- * This function yields the current CPU by moving the calling thread
- * to the expired array. If there are no other threads running on this
- * CPU then this function will return.
+ * This function yields the current CPU to other tasks. If there are no
+ * other threads running on this CPU then this function will return.
  */
 asmlinkage long sys_sched_yield(void)
 {
 	struct rq *rq = this_rq_lock();
-	struct prio_array *array = current->array, *target = rq->expired;
 
 	schedstat_inc(rq, yld_cnt);
-	/*
-	 * We implement yielding by moving the task into the expired
-	 * queue.
-	 *
-	 * (special rule: RT tasks will just roundrobin in the active
-	 *  array.)
-	 */
-	if (rt_task(current))
-		target = rq->active;
-
-	if (array->nr_active == 1) {
+	if (unlikely(rq->nr_running == 1))
 		schedstat_inc(rq, yld_act_empty);
-		if (!rq->expired->nr_active)
-			schedstat_inc(rq, yld_both_empty);
-	} else if (!rq->expired->nr_active)
-		schedstat_inc(rq, yld_exp_empty);
-
-	if (array != target) {
-		dequeue_task(current, array);
-		enqueue_task(current, target);
-	} else
-		/*
-		 * requeue_task is cheaper so perform that if possible.
-		 */
-		requeue_task(current, array);
+	else
+		current->sched_class->yield_task(rq, current);
 
 	/*
 	 * Since we are going to call schedule() anyway, there's
@@ -4902,6 +4567,7 @@
 		break;
 	case SCHED_NORMAL:
 	case SCHED_BATCH:
+	case SCHED_IDLE:
 		ret = 0;
 		break;
 	}
@@ -4926,6 +4592,7 @@
 		break;
 	case SCHED_NORMAL:
 	case SCHED_BATCH:
+	case SCHED_IDLE:
 		ret = 0;
 	}
 	return ret;
@@ -4960,7 +4627,7 @@
 		goto out_unlock;
 
 	jiffies_to_timespec(p->policy == SCHED_FIFO ?
-				0 : task_timeslice(p), &t);
+				0 : static_prio_timeslice(p->static_prio), &t);
 	read_unlock(&tasklist_lock);
 	retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
 out_nounlock:
@@ -5035,6 +4702,9 @@
 
 	touch_all_softlockup_watchdogs();
 
+#ifdef CONFIG_SCHED_DEBUG
+	sysrq_sched_debug_show();
+#endif
 	read_unlock(&tasklist_lock);
 	/*
 	 * Only show locks if all tasks are dumped:
@@ -5043,6 +4713,11 @@
 		debug_show_all_locks();
 }
 
+void __cpuinit init_idle_bootup_task(struct task_struct *idle)
+{
+	idle->sched_class = &idle_sched_class;
+}
+
 /**
  * init_idle - set up an idle thread for a given CPU
  * @idle: task in question
@@ -5056,13 +4731,12 @@
 	struct rq *rq = cpu_rq(cpu);
 	unsigned long flags;
 
-	idle->timestamp = sched_clock();
-	idle->sleep_avg = 0;
-	idle->array = NULL;
+	__sched_fork(idle);
+	idle->se.exec_start = sched_clock();
+
 	idle->prio = idle->normal_prio = MAX_PRIO;
-	idle->state = TASK_RUNNING;
 	idle->cpus_allowed = cpumask_of_cpu(cpu);
-	set_task_cpu(idle, cpu);
+	__set_task_cpu(idle, cpu);
 
 	spin_lock_irqsave(&rq->lock, flags);
 	rq->curr = rq->idle = idle;
@@ -5077,6 +4751,10 @@
 #else
 	task_thread_info(idle)->preempt_count = 0;
 #endif
+	/*
+	 * The idle tasks have their own, simple scheduling class:
+	 */
+	idle->sched_class = &idle_sched_class;
 }
 
 /*
@@ -5088,6 +4766,28 @@
  */
 cpumask_t nohz_cpu_mask = CPU_MASK_NONE;
 
+/*
+ * Increase the granularity value when there are more CPUs,
+ * because with more CPUs the 'effective latency' as visible
+ * to users decreases. But the relationship is not linear,
+ * so pick a second-best guess by going with the log2 of the
+ * number of CPUs.
+ *
+ * This idea comes from the SD scheduler of Con Kolivas:
+ */
+static inline void sched_init_granularity(void)
+{
+	unsigned int factor = 1 + ilog2(num_online_cpus());
+	const unsigned long gran_limit = 10000000;
+
+	sysctl_sched_granularity *= factor;
+	if (sysctl_sched_granularity > gran_limit)
+		sysctl_sched_granularity = gran_limit;
+
+	sysctl_sched_runtime_limit = sysctl_sched_granularity * 4;
+	sysctl_sched_wakeup_granularity = sysctl_sched_granularity / 2;
+}
+
 #ifdef CONFIG_SMP
 /*
  * This is how migration works:
@@ -5161,7 +4861,7 @@
 static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 {
 	struct rq *rq_dest, *rq_src;
-	int ret = 0;
+	int ret = 0, on_rq;
 
 	if (unlikely(cpu_is_offline(dest_cpu)))
 		return ret;
@@ -5177,20 +4877,13 @@
 	if (!cpu_isset(dest_cpu, p->cpus_allowed))
 		goto out;
 
+	on_rq = p->se.on_rq;
+	if (on_rq)
+		deactivate_task(rq_src, p, 0);
 	set_task_cpu(p, dest_cpu);
-	if (p->array) {
-		/*
-		 * Sync timestamp with rq_dest's before activating.
-		 * The same thing could be achieved by doing this step
-		 * afterwards, and pretending it was a local activate.
-		 * This way is cleaner and logically correct.
-		 */
-		p->timestamp = p->timestamp - rq_src->most_recent_timestamp
-				+ rq_dest->most_recent_timestamp;
-		deactivate_task(p, rq_src);
-		__activate_task(p, rq_dest);
-		if (TASK_PREEMPTS_CURR(p, rq_dest))
-			resched_task(rq_dest->curr);
+	if (on_rq) {
+		activate_task(rq_dest, p, 0);
+		check_preempt_curr(rq_dest, p);
 	}
 	ret = 1;
 out:
@@ -5342,7 +5035,8 @@
 	write_unlock_irq(&tasklist_lock);
 }
 
-/* Schedules idle task to be the next runnable task on current CPU.
+/*
+ * Schedules idle task to be the next runnable task on current CPU.
  * It does so by boosting its priority to highest possible and adding it to
  * the _front_ of the runqueue. Used by CPU offline code.
  */
@@ -5362,10 +5056,10 @@
 	 */
 	spin_lock_irqsave(&rq->lock, flags);
 
-	__setscheduler(p, SCHED_FIFO, MAX_RT_PRIO-1);
+	__setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
 
 	/* Add idle task to the _front_ of its priority queue: */
-	__activate_idle_task(p, rq);
+	activate_idle_task(p, rq);
 
 	spin_unlock_irqrestore(&rq->lock, flags);
 }
@@ -5415,16 +5109,15 @@
 static void migrate_dead_tasks(unsigned int dead_cpu)
 {
 	struct rq *rq = cpu_rq(dead_cpu);
-	unsigned int arr, i;
+	struct task_struct *next;
 
-	for (arr = 0; arr < 2; arr++) {
-		for (i = 0; i < MAX_PRIO; i++) {
-			struct list_head *list = &rq->arrays[arr].queue[i];
-
-			while (!list_empty(list))
-				migrate_dead(dead_cpu, list_entry(list->next,
-					     struct task_struct, run_list));
-		}
+	for ( ; ; ) {
+		if (!rq->nr_running)
+			break;
+		next = pick_next_task(rq, rq->curr, rq_clock(rq));
+		if (!next)
+			break;
+		migrate_dead(dead_cpu, next);
 	}
 }
 #endif /* CONFIG_HOTPLUG_CPU */
@@ -5448,14 +5141,14 @@
 
 	case CPU_UP_PREPARE:
 	case CPU_UP_PREPARE_FROZEN:
-		p = kthread_create(migration_thread, hcpu, "migration/%d",cpu);
+		p = kthread_create(migration_thread, hcpu, "migration/%d", cpu);
 		if (IS_ERR(p))
 			return NOTIFY_BAD;
 		p->flags |= PF_NOFREEZE;
 		kthread_bind(p, cpu);
 		/* Must be high prio: stop_machine expects to yield to it. */
 		rq = task_rq_lock(p, &flags);
-		__setscheduler(p, SCHED_FIFO, MAX_RT_PRIO-1);
+		__setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
 		task_rq_unlock(rq, &flags);
 		cpu_rq(cpu)->migration_thread = p;
 		break;
@@ -5486,9 +5179,10 @@
 		rq->migration_thread = NULL;
 		/* Idle task back to normal (off runqueue, low prio) */
 		rq = task_rq_lock(rq->idle, &flags);
-		deactivate_task(rq->idle, rq);
+		deactivate_task(rq, rq->idle, 0);
 		rq->idle->static_prio = MAX_PRIO;
-		__setscheduler(rq->idle, SCHED_NORMAL, 0);
+		__setscheduler(rq, rq->idle, SCHED_NORMAL, 0);
+		rq->idle->sched_class = &idle_sched_class;
 		migrate_dead_tasks(cpu);
 		task_rq_unlock(rq, &flags);
 		migrate_nr_uninterruptible(rq);
@@ -5797,483 +5491,6 @@
 
 #define SD_NODES_PER_DOMAIN 16
 
-/*
- * Self-tuning task migration cost measurement between source and target CPUs.
- *
- * This is done by measuring the cost of manipulating buffers of varying
- * sizes. For a given buffer-size here are the steps that are taken:
- *
- * 1) the source CPU reads+dirties a shared buffer
- * 2) the target CPU reads+dirties the same shared buffer
- *
- * We measure how long they take, in the following 4 scenarios:
- *
- *  - source: CPU1, target: CPU2 | cost1
- *  - source: CPU2, target: CPU1 | cost2
- *  - source: CPU1, target: CPU1 | cost3
- *  - source: CPU2, target: CPU2 | cost4
- *
- * We then calculate the cost3+cost4-cost1-cost2 difference - this is
- * the cost of migration.
- *
- * We then start off from a small buffer-size and iterate up to larger
- * buffer sizes, in 5% steps - measuring each buffer-size separately, and
- * doing a maximum search for the cost. (The maximum cost for a migration
- * normally occurs when the working set size is around the effective cache
- * size.)
- */
-#define SEARCH_SCOPE		2
-#define MIN_CACHE_SIZE		(64*1024U)
-#define DEFAULT_CACHE_SIZE	(5*1024*1024U)
-#define ITERATIONS		1
-#define SIZE_THRESH		130
-#define COST_THRESH		130
-
-/*
- * The migration cost is a function of 'domain distance'. Domain
- * distance is the number of steps a CPU has to iterate down its
- * domain tree to share a domain with the other CPU. The farther
- * two CPUs are from each other, the larger the distance gets.
- *
- * Note that we use the distance only to cache measurement results,
- * the distance value is not used numerically otherwise. When two
- * CPUs have the same distance it is assumed that the migration
- * cost is the same. (this is a simplification but quite practical)
- */
-#define MAX_DOMAIN_DISTANCE 32
-
-static unsigned long long migration_cost[MAX_DOMAIN_DISTANCE] =
-		{ [ 0 ... MAX_DOMAIN_DISTANCE-1 ] =
-/*
- * Architectures may override the migration cost and thus avoid
- * boot-time calibration. Unit is nanoseconds. Mostly useful for
- * virtualized hardware:
- */
-#ifdef CONFIG_DEFAULT_MIGRATION_COST
-			CONFIG_DEFAULT_MIGRATION_COST
-#else
-			-1LL
-#endif
-};
-
-/*
- * Allow override of migration cost - in units of microseconds.
- * E.g. migration_cost=1000,2000,3000 will set up a level-1 cost
- * of 1 msec, level-2 cost of 2 msecs and level3 cost of 3 msecs:
- */
-static int __init migration_cost_setup(char *str)
-{
-	int ints[MAX_DOMAIN_DISTANCE+1], i;
-
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-
-	printk("#ints: %d\n", ints[0]);
-	for (i = 1; i <= ints[0]; i++) {
-		migration_cost[i-1] = (unsigned long long)ints[i]*1000;
-		printk("migration_cost[%d]: %Ld\n", i-1, migration_cost[i-1]);
-	}
-	return 1;
-}
-
-__setup ("migration_cost=", migration_cost_setup);
-
-/*
- * Global multiplier (divisor) for migration-cutoff values,
- * in percentiles. E.g. use a value of 150 to get 1.5 times
- * longer cache-hot cutoff times.
- *
- * (We scale it from 100 to 128 to long long handling easier.)
- */
-
-#define MIGRATION_FACTOR_SCALE 128
-
-static unsigned int migration_factor = MIGRATION_FACTOR_SCALE;
-
-static int __init setup_migration_factor(char *str)
-{
-	get_option(&str, &migration_factor);
-	migration_factor = migration_factor * MIGRATION_FACTOR_SCALE / 100;
-	return 1;
-}
-
-__setup("migration_factor=", setup_migration_factor);
-
-/*
- * Estimated distance of two CPUs, measured via the number of domains
- * we have to pass for the two CPUs to be in the same span:
- */
-static unsigned long domain_distance(int cpu1, int cpu2)
-{
-	unsigned long distance = 0;
-	struct sched_domain *sd;
-
-	for_each_domain(cpu1, sd) {
-		WARN_ON(!cpu_isset(cpu1, sd->span));
-		if (cpu_isset(cpu2, sd->span))
-			return distance;
-		distance++;
-	}
-	if (distance >= MAX_DOMAIN_DISTANCE) {
-		WARN_ON(1);
-		distance = MAX_DOMAIN_DISTANCE-1;
-	}
-
-	return distance;
-}
-
-static unsigned int migration_debug;
-
-static int __init setup_migration_debug(char *str)
-{
-	get_option(&str, &migration_debug);
-	return 1;
-}
-
-__setup("migration_debug=", setup_migration_debug);
-
-/*
- * Maximum cache-size that the scheduler should try to measure.
- * Architectures with larger caches should tune this up during
- * bootup. Gets used in the domain-setup code (i.e. during SMP
- * bootup).
- */
-unsigned int max_cache_size;
-
-static int __init setup_max_cache_size(char *str)
-{
-	get_option(&str, &max_cache_size);
-	return 1;
-}
-
-__setup("max_cache_size=", setup_max_cache_size);
-
-/*
- * Dirty a big buffer in a hard-to-predict (for the L2 cache) way. This
- * is the operation that is timed, so we try to generate unpredictable
- * cachemisses that still end up filling the L2 cache:
- */
-static void touch_cache(void *__cache, unsigned long __size)
-{
-	unsigned long size = __size / sizeof(long);
-	unsigned long chunk1 = size / 3;
-	unsigned long chunk2 = 2 * size / 3;
-	unsigned long *cache = __cache;
-	int i;
-
-	for (i = 0; i < size/6; i += 8) {
-		switch (i % 6) {
-			case 0: cache[i]++;
-			case 1: cache[size-1-i]++;
-			case 2: cache[chunk1-i]++;
-			case 3: cache[chunk1+i]++;
-			case 4: cache[chunk2-i]++;
-			case 5: cache[chunk2+i]++;
-		}
-	}
-}
-
-/*
- * Measure the cache-cost of one task migration. Returns in units of nsec.
- */
-static unsigned long long
-measure_one(void *cache, unsigned long size, int source, int target)
-{
-	cpumask_t mask, saved_mask;
-	unsigned long long t0, t1, t2, t3, cost;
-
-	saved_mask = current->cpus_allowed;
-
-	/*
-	 * Flush source caches to RAM and invalidate them:
-	 */
-	sched_cacheflush();
-
-	/*
-	 * Migrate to the source CPU:
-	 */
-	mask = cpumask_of_cpu(source);
-	set_cpus_allowed(current, mask);
-	WARN_ON(smp_processor_id() != source);
-
-	/*
-	 * Dirty the working set:
-	 */
-	t0 = sched_clock();
-	touch_cache(cache, size);
-	t1 = sched_clock();
-
-	/*
-	 * Migrate to the target CPU, dirty the L2 cache and access
-	 * the shared buffer. (which represents the working set
-	 * of a migrated task.)
-	 */
-	mask = cpumask_of_cpu(target);
-	set_cpus_allowed(current, mask);
-	WARN_ON(smp_processor_id() != target);
-
-	t2 = sched_clock();
-	touch_cache(cache, size);
-	t3 = sched_clock();
-
-	cost = t1-t0 + t3-t2;
-
-	if (migration_debug >= 2)
-		printk("[%d->%d]: %8Ld %8Ld %8Ld => %10Ld.\n",
-			source, target, t1-t0, t1-t0, t3-t2, cost);
-	/*
-	 * Flush target caches to RAM and invalidate them:
-	 */
-	sched_cacheflush();
-
-	set_cpus_allowed(current, saved_mask);
-
-	return cost;
-}
-
-/*
- * Measure a series of task migrations and return the average
- * result. Since this code runs early during bootup the system
- * is 'undisturbed' and the average latency makes sense.
- *
- * The algorithm in essence auto-detects the relevant cache-size,
- * so it will properly detect different cachesizes for different
- * cache-hierarchies, depending on how the CPUs are connected.
- *
- * Architectures can prime the upper limit of the search range via
- * max_cache_size, otherwise the search range defaults to 20MB...64K.
- */
-static unsigned long long
-measure_cost(int cpu1, int cpu2, void *cache, unsigned int size)
-{
-	unsigned long long cost1, cost2;
-	int i;
-
-	/*
-	 * Measure the migration cost of 'size' bytes, over an
-	 * average of 10 runs:
-	 *
-	 * (We perturb the cache size by a small (0..4k)
-	 *  value to compensate size/alignment related artifacts.
-	 *  We also subtract the cost of the operation done on
-	 *  the same CPU.)
-	 */
-	cost1 = 0;
-
-	/*
-	 * dry run, to make sure we start off cache-cold on cpu1,
-	 * and to get any vmalloc pagefaults in advance:
-	 */
-	measure_one(cache, size, cpu1, cpu2);
-	for (i = 0; i < ITERATIONS; i++)
-		cost1 += measure_one(cache, size - i * 1024, cpu1, cpu2);
-
-	measure_one(cache, size, cpu2, cpu1);
-	for (i = 0; i < ITERATIONS; i++)
-		cost1 += measure_one(cache, size - i * 1024, cpu2, cpu1);
-
-	/*
-	 * (We measure the non-migrating [cached] cost on both
-	 *  cpu1 and cpu2, to handle CPUs with different speeds)
-	 */
-	cost2 = 0;
-
-	measure_one(cache, size, cpu1, cpu1);
-	for (i = 0; i < ITERATIONS; i++)
-		cost2 += measure_one(cache, size - i * 1024, cpu1, cpu1);
-
-	measure_one(cache, size, cpu2, cpu2);
-	for (i = 0; i < ITERATIONS; i++)
-		cost2 += measure_one(cache, size - i * 1024, cpu2, cpu2);
-
-	/*
-	 * Get the per-iteration migration cost:
-	 */
-	do_div(cost1, 2 * ITERATIONS);
-	do_div(cost2, 2 * ITERATIONS);
-
-	return cost1 - cost2;
-}
-
-static unsigned long long measure_migration_cost(int cpu1, int cpu2)
-{
-	unsigned long long max_cost = 0, fluct = 0, avg_fluct = 0;
-	unsigned int max_size, size, size_found = 0;
-	long long cost = 0, prev_cost;
-	void *cache;
-
-	/*
-	 * Search from max_cache_size*5 down to 64K - the real relevant
-	 * cachesize has to lie somewhere inbetween.
-	 */
-	if (max_cache_size) {
-		max_size = max(max_cache_size * SEARCH_SCOPE, MIN_CACHE_SIZE);
-		size = max(max_cache_size / SEARCH_SCOPE, MIN_CACHE_SIZE);
-	} else {
-		/*
-		 * Since we have no estimation about the relevant
-		 * search range
-		 */
-		max_size = DEFAULT_CACHE_SIZE * SEARCH_SCOPE;
-		size = MIN_CACHE_SIZE;
-	}
-
-	if (!cpu_online(cpu1) || !cpu_online(cpu2)) {
-		printk("cpu %d and %d not both online!\n", cpu1, cpu2);
-		return 0;
-	}
-
-	/*
-	 * Allocate the working set:
-	 */
-	cache = vmalloc(max_size);
-	if (!cache) {
-		printk("could not vmalloc %d bytes for cache!\n", 2 * max_size);
-		return 1000000; /* return 1 msec on very small boxen */
-	}
-
-	while (size <= max_size) {
-		prev_cost = cost;
-		cost = measure_cost(cpu1, cpu2, cache, size);
-
-		/*
-		 * Update the max:
-		 */
-		if (cost > 0) {
-			if (max_cost < cost) {
-				max_cost = cost;
-				size_found = size;
-			}
-		}
-		/*
-		 * Calculate average fluctuation, we use this to prevent
-		 * noise from triggering an early break out of the loop:
-		 */
-		fluct = abs(cost - prev_cost);
-		avg_fluct = (avg_fluct + fluct)/2;
-
-		if (migration_debug)
-			printk("-> [%d][%d][%7d] %3ld.%ld [%3ld.%ld] (%ld): "
-				"(%8Ld %8Ld)\n",
-				cpu1, cpu2, size,
-				(long)cost / 1000000,
-				((long)cost / 100000) % 10,
-				(long)max_cost / 1000000,
-				((long)max_cost / 100000) % 10,
-				domain_distance(cpu1, cpu2),
-				cost, avg_fluct);
-
-		/*
-		 * If we iterated at least 20% past the previous maximum,
-		 * and the cost has dropped by more than 20% already,
-		 * (taking fluctuations into account) then we assume to
-		 * have found the maximum and break out of the loop early:
-		 */
-		if (size_found && (size*100 > size_found*SIZE_THRESH))
-			if (cost+avg_fluct <= 0 ||
-				max_cost*100 > (cost+avg_fluct)*COST_THRESH) {
-
-				if (migration_debug)
-					printk("-> found max.\n");
-				break;
-			}
-		/*
-		 * Increase the cachesize in 10% steps:
-		 */
-		size = size * 10 / 9;
-	}
-
-	if (migration_debug)
-		printk("[%d][%d] working set size found: %d, cost: %Ld\n",
-			cpu1, cpu2, size_found, max_cost);
-
-	vfree(cache);
-
-	/*
-	 * A task is considered 'cache cold' if at least 2 times
-	 * the worst-case cost of migration has passed.
-	 *
-	 * (this limit is only listened to if the load-balancing
-	 * situation is 'nice' - if there is a large imbalance we
-	 * ignore it for the sake of CPU utilization and
-	 * processing fairness.)
-	 */
-	return 2 * max_cost * migration_factor / MIGRATION_FACTOR_SCALE;
-}
-
-static void calibrate_migration_costs(const cpumask_t *cpu_map)
-{
-	int cpu1 = -1, cpu2 = -1, cpu, orig_cpu = raw_smp_processor_id();
-	unsigned long j0, j1, distance, max_distance = 0;
-	struct sched_domain *sd;
-
-	j0 = jiffies;
-
-	/*
-	 * First pass - calculate the cacheflush times:
-	 */
-	for_each_cpu_mask(cpu1, *cpu_map) {
-		for_each_cpu_mask(cpu2, *cpu_map) {
-			if (cpu1 == cpu2)
-				continue;
-			distance = domain_distance(cpu1, cpu2);
-			max_distance = max(max_distance, distance);
-			/*
-			 * No result cached yet?
-			 */
-			if (migration_cost[distance] == -1LL)
-				migration_cost[distance] =
-					measure_migration_cost(cpu1, cpu2);
-		}
-	}
-	/*
-	 * Second pass - update the sched domain hierarchy with
-	 * the new cache-hot-time estimations:
-	 */
-	for_each_cpu_mask(cpu, *cpu_map) {
-		distance = 0;
-		for_each_domain(cpu, sd) {
-			sd->cache_hot_time = migration_cost[distance];
-			distance++;
-		}
-	}
-	/*
-	 * Print the matrix:
-	 */
-	if (migration_debug)
-		printk("migration: max_cache_size: %d, cpu: %d MHz:\n",
-			max_cache_size,
-#ifdef CONFIG_X86
-			cpu_khz/1000
-#else
-			-1
-#endif
-		);
-	if (system_state == SYSTEM_BOOTING && num_online_cpus() > 1) {
-		printk("migration_cost=");
-		for (distance = 0; distance <= max_distance; distance++) {
-			if (distance)
-				printk(",");
-			printk("%ld", (long)migration_cost[distance] / 1000);
-		}
-		printk("\n");
-	}
-	j1 = jiffies;
-	if (migration_debug)
-		printk("migration: %ld seconds\n", (j1-j0) / HZ);
-
-	/*
-	 * Move back to the original CPU. NUMA-Q gets confused
-	 * if we migrate to another quad during bootup.
-	 */
-	if (raw_smp_processor_id() != orig_cpu) {
-		cpumask_t mask = cpumask_of_cpu(orig_cpu),
-			saved_mask = current->cpus_allowed;
-
-		set_cpus_allowed(current, mask);
-		set_cpus_allowed(current, saved_mask);
-	}
-}
-
 #ifdef CONFIG_NUMA
 
 /**
@@ -6574,7 +5791,6 @@
 static int build_sched_domains(const cpumask_t *cpu_map)
 {
 	int i;
-	struct sched_domain *sd;
 #ifdef CONFIG_NUMA
 	struct sched_group **sched_group_nodes = NULL;
 	int sd_allnodes = 0;
@@ -6582,7 +5798,7 @@
 	/*
 	 * Allocate the per-node list of sched groups
 	 */
-	sched_group_nodes = kzalloc(sizeof(struct sched_group*)*MAX_NUMNODES,
+	sched_group_nodes = kzalloc(sizeof(struct sched_group *)*MAX_NUMNODES,
 					   GFP_KERNEL);
 	if (!sched_group_nodes) {
 		printk(KERN_WARNING "Can not alloc sched group node list\n");
@@ -6601,8 +5817,8 @@
 		cpus_and(nodemask, nodemask, *cpu_map);
 
 #ifdef CONFIG_NUMA
-		if (cpus_weight(*cpu_map)
-				> SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
+		if (cpus_weight(*cpu_map) >
+				SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
 			sd = &per_cpu(allnodes_domains, i);
 			*sd = SD_ALLNODES_INIT;
 			sd->span = *cpu_map;
@@ -6661,7 +5877,8 @@
 		if (i != first_cpu(this_sibling_map))
 			continue;
 
-		init_sched_build_groups(this_sibling_map, cpu_map, &cpu_to_cpu_group);
+		init_sched_build_groups(this_sibling_map, cpu_map,
+					&cpu_to_cpu_group);
 	}
 #endif
 
@@ -6672,11 +5889,11 @@
 		cpus_and(this_core_map, this_core_map, *cpu_map);
 		if (i != first_cpu(this_core_map))
 			continue;
-		init_sched_build_groups(this_core_map, cpu_map, &cpu_to_core_group);
+		init_sched_build_groups(this_core_map, cpu_map,
+					&cpu_to_core_group);
 	}
 #endif
 
-
 	/* Set up physical groups */
 	for (i = 0; i < MAX_NUMNODES; i++) {
 		cpumask_t nodemask = node_to_cpumask(i);
@@ -6691,7 +5908,8 @@
 #ifdef CONFIG_NUMA
 	/* Set up node groups */
 	if (sd_allnodes)
-		init_sched_build_groups(*cpu_map, cpu_map, &cpu_to_allnodes_group);
+		init_sched_build_groups(*cpu_map, cpu_map,
+					&cpu_to_allnodes_group);
 
 	for (i = 0; i < MAX_NUMNODES; i++) {
 		/* Set up node groups */
@@ -6719,6 +5937,7 @@
 		sched_group_nodes[i] = sg;
 		for_each_cpu_mask(j, nodemask) {
 			struct sched_domain *sd;
+
 			sd = &per_cpu(node_domains, j);
 			sd->groups = sg;
 		}
@@ -6763,19 +5982,22 @@
 	/* Calculate CPU power for physical packages and nodes */
 #ifdef CONFIG_SCHED_SMT
 	for_each_cpu_mask(i, *cpu_map) {
-		sd = &per_cpu(cpu_domains, i);
+		struct sched_domain *sd = &per_cpu(cpu_domains, i);
+
 		init_sched_groups_power(i, sd);
 	}
 #endif
 #ifdef CONFIG_SCHED_MC
 	for_each_cpu_mask(i, *cpu_map) {
-		sd = &per_cpu(core_domains, i);
+		struct sched_domain *sd = &per_cpu(core_domains, i);
+
 		init_sched_groups_power(i, sd);
 	}
 #endif
 
 	for_each_cpu_mask(i, *cpu_map) {
-		sd = &per_cpu(phys_domains, i);
+		struct sched_domain *sd = &per_cpu(phys_domains, i);
+
 		init_sched_groups_power(i, sd);
 	}
 
@@ -6803,10 +6025,6 @@
 #endif
 		cpu_attach_domain(sd, i);
 	}
-	/*
-	 * Tune cache-hot values:
-	 */
-	calibrate_migration_costs(cpu_map);
 
 	return 0;
 
@@ -7013,10 +6231,12 @@
 	/* Move init over to a non-isolated CPU */
 	if (set_cpus_allowed(current, non_isolated_cpus) < 0)
 		BUG();
+	sched_init_granularity();
 }
 #else
 void __init sched_init_smp(void)
 {
+	sched_init_granularity();
 }
 #endif /* CONFIG_SMP */
 
@@ -7030,28 +6250,51 @@
 		&& addr < (unsigned long)__sched_text_end);
 }
 
+static inline void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq)
+{
+	cfs_rq->tasks_timeline = RB_ROOT;
+	cfs_rq->fair_clock = 1;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+	cfs_rq->rq = rq;
+#endif
+}
+
 void __init sched_init(void)
 {
-	int i, j, k;
+	u64 now = sched_clock();
 	int highest_cpu = 0;
+	int i, j;
+
+	/*
+	 * Link up the scheduling class hierarchy:
+	 */
+	rt_sched_class.next = &fair_sched_class;
+	fair_sched_class.next = &idle_sched_class;
+	idle_sched_class.next = NULL;
 
 	for_each_possible_cpu(i) {
-		struct prio_array *array;
+		struct rt_prio_array *array;
 		struct rq *rq;
 
 		rq = cpu_rq(i);
 		spin_lock_init(&rq->lock);
 		lockdep_set_class(&rq->lock, &rq->rq_lock_key);
 		rq->nr_running = 0;
-		rq->active = rq->arrays;
-		rq->expired = rq->arrays + 1;
-		rq->best_expired_prio = MAX_PRIO;
+		rq->clock = 1;
+		init_cfs_rq(&rq->cfs, rq);
+#ifdef CONFIG_FAIR_GROUP_SCHED
+		INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
+		list_add(&rq->cfs.leaf_cfs_rq_list, &rq->leaf_cfs_rq_list);
+#endif
+		rq->ls.load_update_last = now;
+		rq->ls.load_update_start = now;
 
+		for (j = 0; j < CPU_LOAD_IDX_MAX; j++)
+			rq->cpu_load[j] = 0;
 #ifdef CONFIG_SMP
 		rq->sd = NULL;
-		for (j = 1; j < 3; j++)
-			rq->cpu_load[j] = 0;
 		rq->active_balance = 0;
+		rq->next_balance = jiffies;
 		rq->push_cpu = 0;
 		rq->cpu = i;
 		rq->migration_thread = NULL;
@@ -7059,16 +6302,14 @@
 #endif
 		atomic_set(&rq->nr_iowait, 0);
 
-		for (j = 0; j < 2; j++) {
-			array = rq->arrays + j;
-			for (k = 0; k < MAX_PRIO; k++) {
-				INIT_LIST_HEAD(array->queue + k);
-				__clear_bit(k, array->bitmap);
-			}
-			// delimiter for bitsearch
-			__set_bit(MAX_PRIO, array->bitmap);
+		array = &rq->rt.active;
+		for (j = 0; j < MAX_RT_PRIO; j++) {
+			INIT_LIST_HEAD(array->queue + j);
+			__clear_bit(j, array->bitmap);
 		}
 		highest_cpu = i;
+		/* delimiter for bitsearch: */
+		__set_bit(MAX_RT_PRIO, array->bitmap);
 	}
 
 	set_load_weight(&init_task);
@@ -7095,6 +6336,10 @@
 	 * when this runqueue becomes "idle".
 	 */
 	init_idle(current, smp_processor_id());
+	/*
+	 * During early bootup we pretend to be a normal task:
+	 */
+	current->sched_class = &fair_sched_class;
 }
 
 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
@@ -7125,29 +6370,55 @@
 #ifdef CONFIG_MAGIC_SYSRQ
 void normalize_rt_tasks(void)
 {
-	struct prio_array *array;
 	struct task_struct *g, *p;
 	unsigned long flags;
 	struct rq *rq;
+	int on_rq;
 
 	read_lock_irq(&tasklist_lock);
-
 	do_each_thread(g, p) {
-		if (!rt_task(p))
+		p->se.fair_key			= 0;
+		p->se.wait_runtime		= 0;
+		p->se.wait_start_fair		= 0;
+		p->se.wait_start		= 0;
+		p->se.exec_start		= 0;
+		p->se.sleep_start		= 0;
+		p->se.sleep_start_fair		= 0;
+		p->se.block_start		= 0;
+		task_rq(p)->cfs.fair_clock	= 0;
+		task_rq(p)->clock		= 0;
+
+		if (!rt_task(p)) {
+			/*
+			 * Renice negative nice level userspace
+			 * tasks back to 0:
+			 */
+			if (TASK_NICE(p) < 0 && p->mm)
+				set_user_nice(p, 0);
 			continue;
+		}
 
 		spin_lock_irqsave(&p->pi_lock, flags);
 		rq = __task_rq_lock(p);
+#ifdef CONFIG_SMP
+		/*
+		 * Do not touch the migration thread:
+		 */
+		if (p == rq->migration_thread)
+			goto out_unlock;
+#endif
 
-		array = p->array;
-		if (array)
-			deactivate_task(p, task_rq(p));
-		__setscheduler(p, SCHED_NORMAL, 0);
-		if (array) {
-			__activate_task(p, task_rq(p));
+		on_rq = p->se.on_rq;
+		if (on_rq)
+			deactivate_task(task_rq(p), p, 0);
+		__setscheduler(rq, p, SCHED_NORMAL, 0);
+		if (on_rq) {
+			activate_task(task_rq(p), p, 0);
 			resched_task(rq->curr);
 		}
-
+#ifdef CONFIG_SMP
+ out_unlock:
+#endif
 		__task_rq_unlock(rq);
 		spin_unlock_irqrestore(&p->pi_lock, flags);
 	} while_each_thread(g, p);
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
new file mode 100644
index 0000000..1baf87c
--- /dev/null
+++ b/kernel/sched_debug.c
@@ -0,0 +1,275 @@
+/*
+ * kernel/time/sched_debug.c
+ *
+ * Print the CFS rbtree
+ *
+ * Copyright(C) 2007, Red Hat, Inc., Ingo Molnar
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+#include <linux/utsname.h>
+
+/*
+ * This allows printing both to /proc/sched_debug and
+ * to the console
+ */
+#define SEQ_printf(m, x...)			\
+ do {						\
+	if (m)					\
+		seq_printf(m, x);		\
+	else					\
+		printk(x);			\
+ } while (0)
+
+static void
+print_task(struct seq_file *m, struct rq *rq, struct task_struct *p, u64 now)
+{
+	if (rq->curr == p)
+		SEQ_printf(m, "R");
+	else
+		SEQ_printf(m, " ");
+
+	SEQ_printf(m, "%15s %5d %15Ld %13Ld %13Ld %9Ld %5d "
+		      "%15Ld %15Ld %15Ld %15Ld %15Ld\n",
+		p->comm, p->pid,
+		(long long)p->se.fair_key,
+		(long long)(p->se.fair_key - rq->cfs.fair_clock),
+		(long long)p->se.wait_runtime,
+		(long long)(p->nvcsw + p->nivcsw),
+		p->prio,
+		(long long)p->se.sum_exec_runtime,
+		(long long)p->se.sum_wait_runtime,
+		(long long)p->se.sum_sleep_runtime,
+		(long long)p->se.wait_runtime_overruns,
+		(long long)p->se.wait_runtime_underruns);
+}
+
+static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu, u64 now)
+{
+	struct task_struct *g, *p;
+
+	SEQ_printf(m,
+	"\nrunnable tasks:\n"
+	"            task   PID        tree-key         delta       waiting"
+	"  switches  prio"
+	"        sum-exec        sum-wait       sum-sleep"
+	"    wait-overrun   wait-underrun\n"
+	"------------------------------------------------------------------"
+	"----------------"
+	"------------------------------------------------"
+	"--------------------------------\n");
+
+	read_lock_irq(&tasklist_lock);
+
+	do_each_thread(g, p) {
+		if (!p->se.on_rq || task_cpu(p) != rq_cpu)
+			continue;
+
+		print_task(m, rq, p, now);
+	} while_each_thread(g, p);
+
+	read_unlock_irq(&tasklist_lock);
+}
+
+static void
+print_cfs_rq_runtime_sum(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
+{
+	s64 wait_runtime_rq_sum = 0;
+	struct task_struct *p;
+	struct rb_node *curr;
+	unsigned long flags;
+	struct rq *rq = &per_cpu(runqueues, cpu);
+
+	spin_lock_irqsave(&rq->lock, flags);
+	curr = first_fair(cfs_rq);
+	while (curr) {
+		p = rb_entry(curr, struct task_struct, se.run_node);
+		wait_runtime_rq_sum += p->se.wait_runtime;
+
+		curr = rb_next(curr);
+	}
+	spin_unlock_irqrestore(&rq->lock, flags);
+
+	SEQ_printf(m, "  .%-30s: %Ld\n", "wait_runtime_rq_sum",
+		(long long)wait_runtime_rq_sum);
+}
+
+void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now)
+{
+	SEQ_printf(m, "\ncfs_rq %p\n", cfs_rq);
+
+#define P(x) \
+	SEQ_printf(m, "  .%-30s: %Ld\n", #x, (long long)(cfs_rq->x))
+
+	P(fair_clock);
+	P(exec_clock);
+	P(wait_runtime);
+	P(wait_runtime_overruns);
+	P(wait_runtime_underruns);
+	P(sleeper_bonus);
+#undef P
+
+	print_cfs_rq_runtime_sum(m, cpu, cfs_rq);
+}
+
+static void print_cpu(struct seq_file *m, int cpu, u64 now)
+{
+	struct rq *rq = &per_cpu(runqueues, cpu);
+
+#ifdef CONFIG_X86
+	{
+		unsigned int freq = cpu_khz ? : 1;
+
+		SEQ_printf(m, "\ncpu#%d, %u.%03u MHz\n",
+			   cpu, freq / 1000, (freq % 1000));
+	}
+#else
+	SEQ_printf(m, "\ncpu#%d\n", cpu);
+#endif
+
+#define P(x) \
+	SEQ_printf(m, "  .%-30s: %Ld\n", #x, (long long)(rq->x))
+
+	P(nr_running);
+	SEQ_printf(m, "  .%-30s: %lu\n", "load",
+		   rq->ls.load.weight);
+	P(ls.delta_fair);
+	P(ls.delta_exec);
+	P(nr_switches);
+	P(nr_load_updates);
+	P(nr_uninterruptible);
+	SEQ_printf(m, "  .%-30s: %lu\n", "jiffies", jiffies);
+	P(next_balance);
+	P(curr->pid);
+	P(clock);
+	P(prev_clock_raw);
+	P(clock_warps);
+	P(clock_overflows);
+	P(clock_unstable_events);
+	P(clock_max_delta);
+	P(cpu_load[0]);
+	P(cpu_load[1]);
+	P(cpu_load[2]);
+	P(cpu_load[3]);
+	P(cpu_load[4]);
+#undef P
+
+	print_cfs_stats(m, cpu, now);
+
+	print_rq(m, rq, cpu, now);
+}
+
+static int sched_debug_show(struct seq_file *m, void *v)
+{
+	u64 now = ktime_to_ns(ktime_get());
+	int cpu;
+
+	SEQ_printf(m, "Sched Debug Version: v0.04, cfs-v20, %s %.*s\n",
+		init_utsname()->release,
+		(int)strcspn(init_utsname()->version, " "),
+		init_utsname()->version);
+
+	SEQ_printf(m, "now at %Lu nsecs\n", (unsigned long long)now);
+
+	for_each_online_cpu(cpu)
+		print_cpu(m, cpu, now);
+
+	SEQ_printf(m, "\n");
+
+	return 0;
+}
+
+void sysrq_sched_debug_show(void)
+{
+	sched_debug_show(NULL, NULL);
+}
+
+static int sched_debug_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, sched_debug_show, NULL);
+}
+
+static struct file_operations sched_debug_fops = {
+	.open		= sched_debug_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static int __init init_sched_debug_procfs(void)
+{
+	struct proc_dir_entry *pe;
+
+	pe = create_proc_entry("sched_debug", 0644, NULL);
+	if (!pe)
+		return -ENOMEM;
+
+	pe->proc_fops = &sched_debug_fops;
+
+	return 0;
+}
+
+__initcall(init_sched_debug_procfs);
+
+void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
+{
+	unsigned long flags;
+	int num_threads = 1;
+
+	rcu_read_lock();
+	if (lock_task_sighand(p, &flags)) {
+		num_threads = atomic_read(&p->signal->count);
+		unlock_task_sighand(p, &flags);
+	}
+	rcu_read_unlock();
+
+	SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, p->pid, num_threads);
+	SEQ_printf(m, "----------------------------------------------\n");
+#define P(F) \
+	SEQ_printf(m, "%-25s:%20Ld\n", #F, (long long)p->F)
+
+	P(se.wait_start);
+	P(se.wait_start_fair);
+	P(se.exec_start);
+	P(se.sleep_start);
+	P(se.sleep_start_fair);
+	P(se.block_start);
+	P(se.sleep_max);
+	P(se.block_max);
+	P(se.exec_max);
+	P(se.wait_max);
+	P(se.wait_runtime);
+	P(se.wait_runtime_overruns);
+	P(se.wait_runtime_underruns);
+	P(se.sum_wait_runtime);
+	P(se.sum_exec_runtime);
+	SEQ_printf(m, "%-25s:%20Ld\n",
+		   "nr_switches", (long long)(p->nvcsw + p->nivcsw));
+	P(se.load.weight);
+	P(policy);
+	P(prio);
+#undef P
+
+	{
+		u64 t0, t1;
+
+		t0 = sched_clock();
+		t1 = sched_clock();
+		SEQ_printf(m, "%-25s:%20Ld\n",
+			   "clock-delta", (long long)(t1-t0));
+	}
+}
+
+void proc_sched_set_task(struct task_struct *p)
+{
+	p->se.sleep_max = p->se.block_max = p->se.exec_max = p->se.wait_max = 0;
+	p->se.wait_runtime_overruns = p->se.wait_runtime_underruns = 0;
+	p->se.sum_exec_runtime = 0;
+}
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
new file mode 100644
index 0000000..6971db0
--- /dev/null
+++ b/kernel/sched_fair.c
@@ -0,0 +1,1131 @@
+/*
+ * Completely Fair Scheduling (CFS) Class (SCHED_NORMAL/SCHED_BATCH)
+ *
+ *  Copyright (C) 2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ *  Interactivity improvements by Mike Galbraith
+ *  (C) 2007 Mike Galbraith <efault@gmx.de>
+ *
+ *  Various enhancements by Dmitry Adamushko.
+ *  (C) 2007 Dmitry Adamushko <dmitry.adamushko@gmail.com>
+ *
+ *  Group scheduling enhancements by Srivatsa Vaddagiri
+ *  Copyright IBM Corporation, 2007
+ *  Author: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
+ *
+ *  Scaled math optimizations by Thomas Gleixner
+ *  Copyright (C) 2007, Thomas Gleixner <tglx@linutronix.de>
+ */
+
+/*
+ * Preemption granularity:
+ * (default: 2 msec, units: nanoseconds)
+ *
+ * NOTE: this granularity value is not the same as the concept of
+ * 'timeslice length' - timeslices in CFS will typically be somewhat
+ * larger than this value. (to see the precise effective timeslice
+ * length of your workload, run vmstat and monitor the context-switches
+ * field)
+ *
+ * On SMP systems the value of this is multiplied by the log2 of the
+ * number of CPUs. (i.e. factor 2x on 2-way systems, 3x on 4-way
+ * systems, 4x on 8-way systems, 5x on 16-way systems, etc.)
+ */
+unsigned int sysctl_sched_granularity __read_mostly = 2000000000ULL/HZ;
+
+/*
+ * SCHED_BATCH wake-up granularity.
+ * (default: 10 msec, units: nanoseconds)
+ *
+ * This option delays the preemption effects of decoupled workloads
+ * and reduces their over-scheduling. Synchronous workloads will still
+ * have immediate wakeup/sleep latencies.
+ */
+unsigned int sysctl_sched_batch_wakeup_granularity __read_mostly =
+							10000000000ULL/HZ;
+
+/*
+ * SCHED_OTHER wake-up granularity.
+ * (default: 1 msec, units: nanoseconds)
+ *
+ * This option delays the preemption effects of decoupled workloads
+ * and reduces their over-scheduling. Synchronous workloads will still
+ * have immediate wakeup/sleep latencies.
+ */
+unsigned int sysctl_sched_wakeup_granularity __read_mostly = 1000000000ULL/HZ;
+
+unsigned int sysctl_sched_stat_granularity __read_mostly;
+
+/*
+ * Initialized in sched_init_granularity():
+ */
+unsigned int sysctl_sched_runtime_limit __read_mostly;
+
+/*
+ * Debugging: various feature bits
+ */
+enum {
+	SCHED_FEAT_FAIR_SLEEPERS	= 1,
+	SCHED_FEAT_SLEEPER_AVG		= 2,
+	SCHED_FEAT_SLEEPER_LOAD_AVG	= 4,
+	SCHED_FEAT_PRECISE_CPU_LOAD	= 8,
+	SCHED_FEAT_START_DEBIT		= 16,
+	SCHED_FEAT_SKIP_INITIAL		= 32,
+};
+
+unsigned int sysctl_sched_features __read_mostly =
+		SCHED_FEAT_FAIR_SLEEPERS	*1 |
+		SCHED_FEAT_SLEEPER_AVG		*1 |
+		SCHED_FEAT_SLEEPER_LOAD_AVG	*1 |
+		SCHED_FEAT_PRECISE_CPU_LOAD	*1 |
+		SCHED_FEAT_START_DEBIT		*1 |
+		SCHED_FEAT_SKIP_INITIAL		*0;
+
+extern struct sched_class fair_sched_class;
+
+/**************************************************************
+ * CFS operations on generic schedulable entities:
+ */
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+
+/* cpu runqueue to which this cfs_rq is attached */
+static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+{
+	return cfs_rq->rq;
+}
+
+/* currently running entity (if any) on this cfs_rq */
+static inline struct sched_entity *cfs_rq_curr(struct cfs_rq *cfs_rq)
+{
+	return cfs_rq->curr;
+}
+
+/* An entity is a task if it doesn't "own" a runqueue */
+#define entity_is_task(se)	(!se->my_q)
+
+static inline void
+set_cfs_rq_curr(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	cfs_rq->curr = se;
+}
+
+#else	/* CONFIG_FAIR_GROUP_SCHED */
+
+static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+{
+	return container_of(cfs_rq, struct rq, cfs);
+}
+
+static inline struct sched_entity *cfs_rq_curr(struct cfs_rq *cfs_rq)
+{
+	struct rq *rq = rq_of(cfs_rq);
+
+	if (unlikely(rq->curr->sched_class != &fair_sched_class))
+		return NULL;
+
+	return &rq->curr->se;
+}
+
+#define entity_is_task(se)	1
+
+static inline void
+set_cfs_rq_curr(struct cfs_rq *cfs_rq, struct sched_entity *se) { }
+
+#endif	/* CONFIG_FAIR_GROUP_SCHED */
+
+static inline struct task_struct *task_of(struct sched_entity *se)
+{
+	return container_of(se, struct task_struct, se);
+}
+
+
+/**************************************************************
+ * Scheduling class tree data structure manipulation methods:
+ */
+
+/*
+ * Enqueue an entity into the rb-tree:
+ */
+static inline void
+__enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	struct rb_node **link = &cfs_rq->tasks_timeline.rb_node;
+	struct rb_node *parent = NULL;
+	struct sched_entity *entry;
+	s64 key = se->fair_key;
+	int leftmost = 1;
+
+	/*
+	 * Find the right place in the rbtree:
+	 */
+	while (*link) {
+		parent = *link;
+		entry = rb_entry(parent, struct sched_entity, run_node);
+		/*
+		 * We dont care about collisions. Nodes with
+		 * the same key stay together.
+		 */
+		if (key - entry->fair_key < 0) {
+			link = &parent->rb_left;
+		} else {
+			link = &parent->rb_right;
+			leftmost = 0;
+		}
+	}
+
+	/*
+	 * Maintain a cache of leftmost tree entries (it is frequently
+	 * used):
+	 */
+	if (leftmost)
+		cfs_rq->rb_leftmost = &se->run_node;
+
+	rb_link_node(&se->run_node, parent, link);
+	rb_insert_color(&se->run_node, &cfs_rq->tasks_timeline);
+	update_load_add(&cfs_rq->load, se->load.weight);
+	cfs_rq->nr_running++;
+	se->on_rq = 1;
+}
+
+static inline void
+__dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	if (cfs_rq->rb_leftmost == &se->run_node)
+		cfs_rq->rb_leftmost = rb_next(&se->run_node);
+	rb_erase(&se->run_node, &cfs_rq->tasks_timeline);
+	update_load_sub(&cfs_rq->load, se->load.weight);
+	cfs_rq->nr_running--;
+	se->on_rq = 0;
+}
+
+static inline struct rb_node *first_fair(struct cfs_rq *cfs_rq)
+{
+	return cfs_rq->rb_leftmost;
+}
+
+static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq)
+{
+	return rb_entry(first_fair(cfs_rq), struct sched_entity, run_node);
+}
+
+/**************************************************************
+ * Scheduling class statistics methods:
+ */
+
+/*
+ * We rescale the rescheduling granularity of tasks according to their
+ * nice level, but only linearly, not exponentially:
+ */
+static long
+niced_granularity(struct sched_entity *curr, unsigned long granularity)
+{
+	u64 tmp;
+
+	/*
+	 * Negative nice levels get the same granularity as nice-0:
+	 */
+	if (likely(curr->load.weight >= NICE_0_LOAD))
+		return granularity;
+	/*
+	 * Positive nice level tasks get linearly finer
+	 * granularity:
+	 */
+	tmp = curr->load.weight * (u64)granularity;
+
+	/*
+	 * It will always fit into 'long':
+	 */
+	return (long) (tmp >> NICE_0_SHIFT);
+}
+
+static inline void
+limit_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+	long limit = sysctl_sched_runtime_limit;
+
+	/*
+	 * Niced tasks have the same history dynamic range as
+	 * non-niced tasks:
+	 */
+	if (unlikely(se->wait_runtime > limit)) {
+		se->wait_runtime = limit;
+		schedstat_inc(se, wait_runtime_overruns);
+		schedstat_inc(cfs_rq, wait_runtime_overruns);
+	}
+	if (unlikely(se->wait_runtime < -limit)) {
+		se->wait_runtime = -limit;
+		schedstat_inc(se, wait_runtime_underruns);
+		schedstat_inc(cfs_rq, wait_runtime_underruns);
+	}
+}
+
+static inline void
+__add_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se, long delta)
+{
+	se->wait_runtime += delta;
+	schedstat_add(se, sum_wait_runtime, delta);
+	limit_wait_runtime(cfs_rq, se);
+}
+
+static void
+add_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se, long delta)
+{
+	schedstat_add(cfs_rq, wait_runtime, -se->wait_runtime);
+	__add_wait_runtime(cfs_rq, se, delta);
+	schedstat_add(cfs_rq, wait_runtime, se->wait_runtime);
+}
+
+/*
+ * Update the current task's runtime statistics. Skip current tasks that
+ * are not in our scheduling class.
+ */
+static inline void
+__update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr, u64 now)
+{
+	unsigned long delta, delta_exec, delta_fair;
+	long delta_mine;
+	struct load_weight *lw = &cfs_rq->load;
+	unsigned long load = lw->weight;
+
+	if (unlikely(!load))
+		return;
+
+	delta_exec = curr->delta_exec;
+#ifdef CONFIG_SCHEDSTATS
+	if (unlikely(delta_exec > curr->exec_max))
+		curr->exec_max = delta_exec;
+#endif
+
+	curr->sum_exec_runtime += delta_exec;
+	cfs_rq->exec_clock += delta_exec;
+
+	delta_fair = calc_delta_fair(delta_exec, lw);
+	delta_mine = calc_delta_mine(delta_exec, curr->load.weight, lw);
+
+	if (cfs_rq->sleeper_bonus > sysctl_sched_stat_granularity) {
+		delta = calc_delta_mine(cfs_rq->sleeper_bonus,
+					curr->load.weight, lw);
+		if (unlikely(delta > cfs_rq->sleeper_bonus))
+			delta = cfs_rq->sleeper_bonus;
+
+		cfs_rq->sleeper_bonus -= delta;
+		delta_mine -= delta;
+	}
+
+	cfs_rq->fair_clock += delta_fair;
+	/*
+	 * We executed delta_exec amount of time on the CPU,
+	 * but we were only entitled to delta_mine amount of
+	 * time during that period (if nr_running == 1 then
+	 * the two values are equal)
+	 * [Note: delta_mine - delta_exec is negative]:
+	 */
+	add_wait_runtime(cfs_rq, curr, delta_mine - delta_exec);
+}
+
+static void update_curr(struct cfs_rq *cfs_rq, u64 now)
+{
+	struct sched_entity *curr = cfs_rq_curr(cfs_rq);
+	unsigned long delta_exec;
+
+	if (unlikely(!curr))
+		return;
+
+	/*
+	 * Get the amount of time the current task was running
+	 * since the last time we changed load (this cannot
+	 * overflow on 32 bits):
+	 */
+	delta_exec = (unsigned long)(now - curr->exec_start);
+
+	curr->delta_exec += delta_exec;
+
+	if (unlikely(curr->delta_exec > sysctl_sched_stat_granularity)) {
+		__update_curr(cfs_rq, curr, now);
+		curr->delta_exec = 0;
+	}
+	curr->exec_start = now;
+}
+
+static inline void
+update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	se->wait_start_fair = cfs_rq->fair_clock;
+	se->wait_start = now;
+}
+
+/*
+ * We calculate fair deltas here, so protect against the random effects
+ * of a multiplication overflow by capping it to the runtime limit:
+ */
+#if BITS_PER_LONG == 32
+static inline unsigned long
+calc_weighted(unsigned long delta, unsigned long weight, int shift)
+{
+	u64 tmp = (u64)delta * weight >> shift;
+
+	if (unlikely(tmp > sysctl_sched_runtime_limit*2))
+		return sysctl_sched_runtime_limit*2;
+	return tmp;
+}
+#else
+static inline unsigned long
+calc_weighted(unsigned long delta, unsigned long weight, int shift)
+{
+	return delta * weight >> shift;
+}
+#endif
+
+/*
+ * Task is being enqueued - update stats:
+ */
+static void
+update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	s64 key;
+
+	/*
+	 * Are we enqueueing a waiting task? (for current tasks
+	 * a dequeue/enqueue event is a NOP)
+	 */
+	if (se != cfs_rq_curr(cfs_rq))
+		update_stats_wait_start(cfs_rq, se, now);
+	/*
+	 * Update the key:
+	 */
+	key = cfs_rq->fair_clock;
+
+	/*
+	 * Optimize the common nice 0 case:
+	 */
+	if (likely(se->load.weight == NICE_0_LOAD)) {
+		key -= se->wait_runtime;
+	} else {
+		u64 tmp;
+
+		if (se->wait_runtime < 0) {
+			tmp = -se->wait_runtime;
+			key += (tmp * se->load.inv_weight) >>
+					(WMULT_SHIFT - NICE_0_SHIFT);
+		} else {
+			tmp = se->wait_runtime;
+			key -= (tmp * se->load.weight) >> NICE_0_SHIFT;
+		}
+	}
+
+	se->fair_key = key;
+}
+
+/*
+ * Note: must be called with a freshly updated rq->fair_clock.
+ */
+static inline void
+__update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	unsigned long delta_fair = se->delta_fair_run;
+
+#ifdef CONFIG_SCHEDSTATS
+	{
+		s64 delta_wait = now - se->wait_start;
+		if (unlikely(delta_wait > se->wait_max))
+			se->wait_max = delta_wait;
+	}
+#endif
+
+	if (unlikely(se->load.weight != NICE_0_LOAD))
+		delta_fair = calc_weighted(delta_fair, se->load.weight,
+							NICE_0_SHIFT);
+
+	add_wait_runtime(cfs_rq, se, delta_fair);
+}
+
+static void
+update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	unsigned long delta_fair;
+
+	delta_fair = (unsigned long)min((u64)(2*sysctl_sched_runtime_limit),
+			(u64)(cfs_rq->fair_clock - se->wait_start_fair));
+
+	se->delta_fair_run += delta_fair;
+	if (unlikely(abs(se->delta_fair_run) >=
+				sysctl_sched_stat_granularity)) {
+		__update_stats_wait_end(cfs_rq, se, now);
+		se->delta_fair_run = 0;
+	}
+
+	se->wait_start_fair = 0;
+	se->wait_start = 0;
+}
+
+static inline void
+update_stats_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	update_curr(cfs_rq, now);
+	/*
+	 * Mark the end of the wait period if dequeueing a
+	 * waiting task:
+	 */
+	if (se != cfs_rq_curr(cfs_rq))
+		update_stats_wait_end(cfs_rq, se, now);
+}
+
+/*
+ * We are picking a new current task - update its stats:
+ */
+static inline void
+update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	/*
+	 * We are starting a new run period:
+	 */
+	se->exec_start = now;
+}
+
+/*
+ * We are descheduling a task - update its stats:
+ */
+static inline void
+update_stats_curr_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	se->exec_start = 0;
+}
+
+/**************************************************
+ * Scheduling class queueing methods:
+ */
+
+static void
+__enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	unsigned long load = cfs_rq->load.weight, delta_fair;
+	long prev_runtime;
+
+	if (sysctl_sched_features & SCHED_FEAT_SLEEPER_LOAD_AVG)
+		load = rq_of(cfs_rq)->cpu_load[2];
+
+	delta_fair = se->delta_fair_sleep;
+
+	/*
+	 * Fix up delta_fair with the effect of us running
+	 * during the whole sleep period:
+	 */
+	if (sysctl_sched_features & SCHED_FEAT_SLEEPER_AVG)
+		delta_fair = div64_likely32((u64)delta_fair * load,
+						load + se->load.weight);
+
+	if (unlikely(se->load.weight != NICE_0_LOAD))
+		delta_fair = calc_weighted(delta_fair, se->load.weight,
+							NICE_0_SHIFT);
+
+	prev_runtime = se->wait_runtime;
+	__add_wait_runtime(cfs_rq, se, delta_fair);
+	delta_fair = se->wait_runtime - prev_runtime;
+
+	/*
+	 * Track the amount of bonus we've given to sleepers:
+	 */
+	cfs_rq->sleeper_bonus += delta_fair;
+
+	schedstat_add(cfs_rq, wait_runtime, se->wait_runtime);
+}
+
+static void
+enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	struct task_struct *tsk = task_of(se);
+	unsigned long delta_fair;
+
+	if ((entity_is_task(se) && tsk->policy == SCHED_BATCH) ||
+			 !(sysctl_sched_features & SCHED_FEAT_FAIR_SLEEPERS))
+		return;
+
+	delta_fair = (unsigned long)min((u64)(2*sysctl_sched_runtime_limit),
+		(u64)(cfs_rq->fair_clock - se->sleep_start_fair));
+
+	se->delta_fair_sleep += delta_fair;
+	if (unlikely(abs(se->delta_fair_sleep) >=
+				sysctl_sched_stat_granularity)) {
+		__enqueue_sleeper(cfs_rq, se, now);
+		se->delta_fair_sleep = 0;
+	}
+
+	se->sleep_start_fair = 0;
+
+#ifdef CONFIG_SCHEDSTATS
+	if (se->sleep_start) {
+		u64 delta = now - se->sleep_start;
+
+		if ((s64)delta < 0)
+			delta = 0;
+
+		if (unlikely(delta > se->sleep_max))
+			se->sleep_max = delta;
+
+		se->sleep_start = 0;
+		se->sum_sleep_runtime += delta;
+	}
+	if (se->block_start) {
+		u64 delta = now - se->block_start;
+
+		if ((s64)delta < 0)
+			delta = 0;
+
+		if (unlikely(delta > se->block_max))
+			se->block_max = delta;
+
+		se->block_start = 0;
+		se->sum_sleep_runtime += delta;
+	}
+#endif
+}
+
+static void
+enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
+	       int wakeup, u64 now)
+{
+	/*
+	 * Update the fair clock.
+	 */
+	update_curr(cfs_rq, now);
+
+	if (wakeup)
+		enqueue_sleeper(cfs_rq, se, now);
+
+	update_stats_enqueue(cfs_rq, se, now);
+	__enqueue_entity(cfs_rq, se);
+}
+
+static void
+dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
+	       int sleep, u64 now)
+{
+	update_stats_dequeue(cfs_rq, se, now);
+	if (sleep) {
+		se->sleep_start_fair = cfs_rq->fair_clock;
+#ifdef CONFIG_SCHEDSTATS
+		if (entity_is_task(se)) {
+			struct task_struct *tsk = task_of(se);
+
+			if (tsk->state & TASK_INTERRUPTIBLE)
+				se->sleep_start = now;
+			if (tsk->state & TASK_UNINTERRUPTIBLE)
+				se->block_start = now;
+		}
+		cfs_rq->wait_runtime -= se->wait_runtime;
+#endif
+	}
+	__dequeue_entity(cfs_rq, se);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void
+__check_preempt_curr_fair(struct cfs_rq *cfs_rq, struct sched_entity *se,
+			  struct sched_entity *curr, unsigned long granularity)
+{
+	s64 __delta = curr->fair_key - se->fair_key;
+
+	/*
+	 * Take scheduling granularity into account - do not
+	 * preempt the current task unless the best task has
+	 * a larger than sched_granularity fairness advantage:
+	 */
+	if (__delta > niced_granularity(curr, granularity))
+		resched_task(rq_of(cfs_rq)->curr);
+}
+
+static inline void
+set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+	/*
+	 * Any task has to be enqueued before it get to execute on
+	 * a CPU. So account for the time it spent waiting on the
+	 * runqueue. (note, here we rely on pick_next_task() having
+	 * done a put_prev_task_fair() shortly before this, which
+	 * updated rq->fair_clock - used by update_stats_wait_end())
+	 */
+	update_stats_wait_end(cfs_rq, se, now);
+	update_stats_curr_start(cfs_rq, se, now);
+	set_cfs_rq_curr(cfs_rq, se);
+}
+
+static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq, u64 now)
+{
+	struct sched_entity *se = __pick_next_entity(cfs_rq);
+
+	set_next_entity(cfs_rq, se, now);
+
+	return se;
+}
+
+static void
+put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev, u64 now)
+{
+	/*
+	 * If still on the runqueue then deactivate_task()
+	 * was not called and update_curr() has to be done:
+	 */
+	if (prev->on_rq)
+		update_curr(cfs_rq, now);
+
+	update_stats_curr_end(cfs_rq, prev, now);
+
+	if (prev->on_rq)
+		update_stats_wait_start(cfs_rq, prev, now);
+	set_cfs_rq_curr(cfs_rq, NULL);
+}
+
+static void entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
+{
+	struct rq *rq = rq_of(cfs_rq);
+	struct sched_entity *next;
+	u64 now = __rq_clock(rq);
+
+	/*
+	 * Dequeue and enqueue the task to update its
+	 * position within the tree:
+	 */
+	dequeue_entity(cfs_rq, curr, 0, now);
+	enqueue_entity(cfs_rq, curr, 0, now);
+
+	/*
+	 * Reschedule if another task tops the current one.
+	 */
+	next = __pick_next_entity(cfs_rq);
+	if (next == curr)
+		return;
+
+	__check_preempt_curr_fair(cfs_rq, next, curr, sysctl_sched_granularity);
+}
+
+/**************************************************
+ * CFS operations on tasks:
+ */
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+
+/* Walk up scheduling entities hierarchy */
+#define for_each_sched_entity(se) \
+		for (; se; se = se->parent)
+
+static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+{
+	return p->se.cfs_rq;
+}
+
+/* runqueue on which this entity is (to be) queued */
+static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+{
+	return se->cfs_rq;
+}
+
+/* runqueue "owned" by this group */
+static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+{
+	return grp->my_q;
+}
+
+/* Given a group's cfs_rq on one cpu, return its corresponding cfs_rq on
+ * another cpu ('this_cpu')
+ */
+static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+{
+	/* A later patch will take group into account */
+	return &cpu_rq(this_cpu)->cfs;
+}
+
+/* Iterate thr' all leaf cfs_rq's on a runqueue */
+#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+	list_for_each_entry(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list)
+
+/* Do the two (enqueued) tasks belong to the same group ? */
+static inline int is_same_group(struct task_struct *curr, struct task_struct *p)
+{
+	if (curr->se.cfs_rq == p->se.cfs_rq)
+		return 1;
+
+	return 0;
+}
+
+#else	/* CONFIG_FAIR_GROUP_SCHED */
+
+#define for_each_sched_entity(se) \
+		for (; se; se = NULL)
+
+static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+{
+	return &task_rq(p)->cfs;
+}
+
+static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+{
+	struct task_struct *p = task_of(se);
+	struct rq *rq = task_rq(p);
+
+	return &rq->cfs;
+}
+
+/* runqueue "owned" by this group */
+static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+{
+	return NULL;
+}
+
+static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+{
+	return &cpu_rq(this_cpu)->cfs;
+}
+
+#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+		for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL)
+
+static inline int is_same_group(struct task_struct *curr, struct task_struct *p)
+{
+	return 1;
+}
+
+#endif	/* CONFIG_FAIR_GROUP_SCHED */
+
+/*
+ * The enqueue_task method is called before nr_running is
+ * increased. Here we update the fair scheduling stats and
+ * then put the task into the rbtree:
+ */
+static void
+enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+	struct cfs_rq *cfs_rq;
+	struct sched_entity *se = &p->se;
+
+	for_each_sched_entity(se) {
+		if (se->on_rq)
+			break;
+		cfs_rq = cfs_rq_of(se);
+		enqueue_entity(cfs_rq, se, wakeup, now);
+	}
+}
+
+/*
+ * The dequeue_task method is called before nr_running is
+ * decreased. We remove the task from the rbtree and
+ * update the fair scheduling stats:
+ */
+static void
+dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+	struct cfs_rq *cfs_rq;
+	struct sched_entity *se = &p->se;
+
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+		dequeue_entity(cfs_rq, se, sleep, now);
+		/* Don't dequeue parent if it has other entities besides us */
+		if (cfs_rq->load.weight)
+			break;
+	}
+}
+
+/*
+ * sched_yield() support is very simple - we dequeue and enqueue
+ */
+static void yield_task_fair(struct rq *rq, struct task_struct *p)
+{
+	struct cfs_rq *cfs_rq = task_cfs_rq(p);
+	u64 now = __rq_clock(rq);
+
+	/*
+	 * Dequeue and enqueue the task to update its
+	 * position within the tree:
+	 */
+	dequeue_entity(cfs_rq, &p->se, 0, now);
+	enqueue_entity(cfs_rq, &p->se, 0, now);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void check_preempt_curr_fair(struct rq *rq, struct task_struct *p)
+{
+	struct task_struct *curr = rq->curr;
+	struct cfs_rq *cfs_rq = task_cfs_rq(curr);
+	unsigned long gran;
+
+	if (unlikely(rt_prio(p->prio))) {
+		update_curr(cfs_rq, rq_clock(rq));
+		resched_task(curr);
+		return;
+	}
+
+	gran = sysctl_sched_wakeup_granularity;
+	/*
+	 * Batch tasks prefer throughput over latency:
+	 */
+	if (unlikely(p->policy == SCHED_BATCH))
+		gran = sysctl_sched_batch_wakeup_granularity;
+
+	if (is_same_group(curr, p))
+		__check_preempt_curr_fair(cfs_rq, &p->se, &curr->se, gran);
+}
+
+static struct task_struct *pick_next_task_fair(struct rq *rq, u64 now)
+{
+	struct cfs_rq *cfs_rq = &rq->cfs;
+	struct sched_entity *se;
+
+	if (unlikely(!cfs_rq->nr_running))
+		return NULL;
+
+	do {
+		se = pick_next_entity(cfs_rq, now);
+		cfs_rq = group_cfs_rq(se);
+	} while (cfs_rq);
+
+	return task_of(se);
+}
+
+/*
+ * Account for a descheduled task:
+ */
+static void put_prev_task_fair(struct rq *rq, struct task_struct *prev, u64 now)
+{
+	struct sched_entity *se = &prev->se;
+	struct cfs_rq *cfs_rq;
+
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+		put_prev_entity(cfs_rq, se, now);
+	}
+}
+
+/**************************************************
+ * Fair scheduling class load-balancing methods:
+ */
+
+/*
+ * Load-balancing iterator. Note: while the runqueue stays locked
+ * during the whole iteration, the current task might be
+ * dequeued so the iterator has to be dequeue-safe. Here we
+ * achieve that by always pre-iterating before returning
+ * the current task:
+ */
+static inline struct task_struct *
+__load_balance_iterator(struct cfs_rq *cfs_rq, struct rb_node *curr)
+{
+	struct task_struct *p;
+
+	if (!curr)
+		return NULL;
+
+	p = rb_entry(curr, struct task_struct, se.run_node);
+	cfs_rq->rb_load_balance_curr = rb_next(curr);
+
+	return p;
+}
+
+static struct task_struct *load_balance_start_fair(void *arg)
+{
+	struct cfs_rq *cfs_rq = arg;
+
+	return __load_balance_iterator(cfs_rq, first_fair(cfs_rq));
+}
+
+static struct task_struct *load_balance_next_fair(void *arg)
+{
+	struct cfs_rq *cfs_rq = arg;
+
+	return __load_balance_iterator(cfs_rq, cfs_rq->rb_load_balance_curr);
+}
+
+static int cfs_rq_best_prio(struct cfs_rq *cfs_rq)
+{
+	struct sched_entity *curr;
+	struct task_struct *p;
+
+	if (!cfs_rq->nr_running)
+		return MAX_PRIO;
+
+	curr = __pick_next_entity(cfs_rq);
+	p = task_of(curr);
+
+	return p->prio;
+}
+
+static int
+load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
+			unsigned long max_nr_move, unsigned long max_load_move,
+			struct sched_domain *sd, enum cpu_idle_type idle,
+			int *all_pinned, unsigned long *total_load_moved)
+{
+	struct cfs_rq *busy_cfs_rq;
+	unsigned long load_moved, total_nr_moved = 0, nr_moved;
+	long rem_load_move = max_load_move;
+	struct rq_iterator cfs_rq_iterator;
+
+	cfs_rq_iterator.start = load_balance_start_fair;
+	cfs_rq_iterator.next = load_balance_next_fair;
+
+	for_each_leaf_cfs_rq(busiest, busy_cfs_rq) {
+		struct cfs_rq *this_cfs_rq;
+		long imbalance;
+		unsigned long maxload;
+		int this_best_prio, best_prio, best_prio_seen = 0;
+
+		this_cfs_rq = cpu_cfs_rq(busy_cfs_rq, this_cpu);
+
+		imbalance = busy_cfs_rq->load.weight -
+						 this_cfs_rq->load.weight;
+		/* Don't pull if this_cfs_rq has more load than busy_cfs_rq */
+		if (imbalance <= 0)
+			continue;
+
+		/* Don't pull more than imbalance/2 */
+		imbalance /= 2;
+		maxload = min(rem_load_move, imbalance);
+
+		this_best_prio = cfs_rq_best_prio(this_cfs_rq);
+		best_prio = cfs_rq_best_prio(busy_cfs_rq);
+
+		/*
+		 * Enable handling of the case where there is more than one task
+		 * with the best priority. If the current running task is one
+		 * of those with prio==best_prio we know it won't be moved
+		 * and therefore it's safe to override the skip (based on load)
+		 * of any task we find with that prio.
+		 */
+		if (cfs_rq_curr(busy_cfs_rq) == &busiest->curr->se)
+			best_prio_seen = 1;
+
+		/* pass busy_cfs_rq argument into
+		 * load_balance_[start|next]_fair iterators
+		 */
+		cfs_rq_iterator.arg = busy_cfs_rq;
+		nr_moved = balance_tasks(this_rq, this_cpu, busiest,
+				max_nr_move, maxload, sd, idle, all_pinned,
+				&load_moved, this_best_prio, best_prio,
+				best_prio_seen, &cfs_rq_iterator);
+
+		total_nr_moved += nr_moved;
+		max_nr_move -= nr_moved;
+		rem_load_move -= load_moved;
+
+		if (max_nr_move <= 0 || rem_load_move <= 0)
+			break;
+	}
+
+	*total_load_moved = max_load_move - rem_load_move;
+
+	return total_nr_moved;
+}
+
+/*
+ * scheduler tick hitting a task of our scheduling class:
+ */
+static void task_tick_fair(struct rq *rq, struct task_struct *curr)
+{
+	struct cfs_rq *cfs_rq;
+	struct sched_entity *se = &curr->se;
+
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+		entity_tick(cfs_rq, se);
+	}
+}
+
+/*
+ * Share the fairness runtime between parent and child, thus the
+ * total amount of pressure for CPU stays equal - new tasks
+ * get a chance to run but frequent forkers are not allowed to
+ * monopolize the CPU. Note: the parent runqueue is locked,
+ * the child is not running yet.
+ */
+static void task_new_fair(struct rq *rq, struct task_struct *p)
+{
+	struct cfs_rq *cfs_rq = task_cfs_rq(p);
+	struct sched_entity *se = &p->se;
+	u64 now = rq_clock(rq);
+
+	sched_info_queued(p);
+
+	update_stats_enqueue(cfs_rq, se, now);
+	/*
+	 * Child runs first: we let it run before the parent
+	 * until it reschedules once. We set up the key so that
+	 * it will preempt the parent:
+	 */
+	p->se.fair_key = current->se.fair_key -
+		niced_granularity(&rq->curr->se, sysctl_sched_granularity) - 1;
+	/*
+	 * The first wait is dominated by the child-runs-first logic,
+	 * so do not credit it with that waiting time yet:
+	 */
+	if (sysctl_sched_features & SCHED_FEAT_SKIP_INITIAL)
+		p->se.wait_start_fair = 0;
+
+	/*
+	 * The statistical average of wait_runtime is about
+	 * -granularity/2, so initialize the task with that:
+	 */
+	if (sysctl_sched_features & SCHED_FEAT_START_DEBIT)
+		p->se.wait_runtime = -(sysctl_sched_granularity / 2);
+
+	__enqueue_entity(cfs_rq, se);
+	inc_nr_running(p, rq, now);
+}
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/* Account for a task changing its policy or group.
+ *
+ * This routine is mostly called to set cfs_rq->curr field when a task
+ * migrates between groups/classes.
+ */
+static void set_curr_task_fair(struct rq *rq)
+{
+	struct task_struct *curr = rq->curr;
+	struct sched_entity *se = &curr->se;
+	u64 now = rq_clock(rq);
+	struct cfs_rq *cfs_rq;
+
+	for_each_sched_entity(se) {
+		cfs_rq = cfs_rq_of(se);
+		set_next_entity(cfs_rq, se, now);
+	}
+}
+#else
+static void set_curr_task_fair(struct rq *rq)
+{
+}
+#endif
+
+/*
+ * All the scheduling class methods:
+ */
+struct sched_class fair_sched_class __read_mostly = {
+	.enqueue_task		= enqueue_task_fair,
+	.dequeue_task		= dequeue_task_fair,
+	.yield_task		= yield_task_fair,
+
+	.check_preempt_curr	= check_preempt_curr_fair,
+
+	.pick_next_task		= pick_next_task_fair,
+	.put_prev_task		= put_prev_task_fair,
+
+	.load_balance		= load_balance_fair,
+
+	.set_curr_task          = set_curr_task_fair,
+	.task_tick		= task_tick_fair,
+	.task_new		= task_new_fair,
+};
+
+#ifdef CONFIG_SCHED_DEBUG
+void print_cfs_stats(struct seq_file *m, int cpu, u64 now)
+{
+	struct rq *rq = cpu_rq(cpu);
+	struct cfs_rq *cfs_rq;
+
+	for_each_leaf_cfs_rq(rq, cfs_rq)
+		print_cfs_rq(m, cpu, cfs_rq, now);
+}
+#endif
diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c
new file mode 100644
index 0000000..41841e7
--- /dev/null
+++ b/kernel/sched_idletask.c
@@ -0,0 +1,71 @@
+/*
+ * idle-task scheduling class.
+ *
+ * (NOTE: these are not related to SCHED_IDLE tasks which are
+ *  handled in sched_fair.c)
+ */
+
+/*
+ * Idle tasks are unconditionally rescheduled:
+ */
+static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p)
+{
+	resched_task(rq->idle);
+}
+
+static struct task_struct *pick_next_task_idle(struct rq *rq, u64 now)
+{
+	schedstat_inc(rq, sched_goidle);
+
+	return rq->idle;
+}
+
+/*
+ * It is not legal to sleep in the idle task - print a warning
+ * message if some code attempts to do it:
+ */
+static void
+dequeue_task_idle(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+	spin_unlock_irq(&rq->lock);
+	printk(KERN_ERR "bad: scheduling from the idle thread!\n");
+	dump_stack();
+	spin_lock_irq(&rq->lock);
+}
+
+static void put_prev_task_idle(struct rq *rq, struct task_struct *prev, u64 now)
+{
+}
+
+static int
+load_balance_idle(struct rq *this_rq, int this_cpu, struct rq *busiest,
+			unsigned long max_nr_move, unsigned long max_load_move,
+			struct sched_domain *sd, enum cpu_idle_type idle,
+			int *all_pinned, unsigned long *total_load_moved)
+{
+	return 0;
+}
+
+static void task_tick_idle(struct rq *rq, struct task_struct *curr)
+{
+}
+
+/*
+ * Simple, special scheduling class for the per-CPU idle tasks:
+ */
+static struct sched_class idle_sched_class __read_mostly = {
+	/* no enqueue/yield_task for idle tasks */
+
+	/* dequeue is not valid, we print a debug message there: */
+	.dequeue_task		= dequeue_task_idle,
+
+	.check_preempt_curr	= check_preempt_curr_idle,
+
+	.pick_next_task		= pick_next_task_idle,
+	.put_prev_task		= put_prev_task_idle,
+
+	.load_balance		= load_balance_idle,
+
+	.task_tick		= task_tick_idle,
+	/* no .task_new for idle tasks */
+};
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
new file mode 100644
index 0000000..1192a27
--- /dev/null
+++ b/kernel/sched_rt.c
@@ -0,0 +1,255 @@
+/*
+ * Real-Time Scheduling Class (mapped to the SCHED_FIFO and SCHED_RR
+ * policies)
+ */
+
+/*
+ * Update the current task's runtime statistics. Skip current tasks that
+ * are not in our scheduling class.
+ */
+static inline void update_curr_rt(struct rq *rq, u64 now)
+{
+	struct task_struct *curr = rq->curr;
+	u64 delta_exec;
+
+	if (!task_has_rt_policy(curr))
+		return;
+
+	delta_exec = now - curr->se.exec_start;
+	if (unlikely((s64)delta_exec < 0))
+		delta_exec = 0;
+	if (unlikely(delta_exec > curr->se.exec_max))
+		curr->se.exec_max = delta_exec;
+
+	curr->se.sum_exec_runtime += delta_exec;
+	curr->se.exec_start = now;
+}
+
+static void
+enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+	struct rt_prio_array *array = &rq->rt.active;
+
+	list_add_tail(&p->run_list, array->queue + p->prio);
+	__set_bit(p->prio, array->bitmap);
+}
+
+/*
+ * Adding/removing a task to/from a priority array:
+ */
+static void
+dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+	struct rt_prio_array *array = &rq->rt.active;
+
+	update_curr_rt(rq, now);
+
+	list_del(&p->run_list);
+	if (list_empty(array->queue + p->prio))
+		__clear_bit(p->prio, array->bitmap);
+}
+
+/*
+ * Put task to the end of the run list without the overhead of dequeue
+ * followed by enqueue.
+ */
+static void requeue_task_rt(struct rq *rq, struct task_struct *p)
+{
+	struct rt_prio_array *array = &rq->rt.active;
+
+	list_move_tail(&p->run_list, array->queue + p->prio);
+}
+
+static void
+yield_task_rt(struct rq *rq, struct task_struct *p)
+{
+	requeue_task_rt(rq, p);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p)
+{
+	if (p->prio < rq->curr->prio)
+		resched_task(rq->curr);
+}
+
+static struct task_struct *pick_next_task_rt(struct rq *rq, u64 now)
+{
+	struct rt_prio_array *array = &rq->rt.active;
+	struct task_struct *next;
+	struct list_head *queue;
+	int idx;
+
+	idx = sched_find_first_bit(array->bitmap);
+	if (idx >= MAX_RT_PRIO)
+		return NULL;
+
+	queue = array->queue + idx;
+	next = list_entry(queue->next, struct task_struct, run_list);
+
+	next->se.exec_start = now;
+
+	return next;
+}
+
+static void put_prev_task_rt(struct rq *rq, struct task_struct *p, u64 now)
+{
+	update_curr_rt(rq, now);
+	p->se.exec_start = 0;
+}
+
+/*
+ * Load-balancing iterator. Note: while the runqueue stays locked
+ * during the whole iteration, the current task might be
+ * dequeued so the iterator has to be dequeue-safe. Here we
+ * achieve that by always pre-iterating before returning
+ * the current task:
+ */
+static struct task_struct *load_balance_start_rt(void *arg)
+{
+	struct rq *rq = arg;
+	struct rt_prio_array *array = &rq->rt.active;
+	struct list_head *head, *curr;
+	struct task_struct *p;
+	int idx;
+
+	idx = sched_find_first_bit(array->bitmap);
+	if (idx >= MAX_RT_PRIO)
+		return NULL;
+
+	head = array->queue + idx;
+	curr = head->prev;
+
+	p = list_entry(curr, struct task_struct, run_list);
+
+	curr = curr->prev;
+
+	rq->rt.rt_load_balance_idx = idx;
+	rq->rt.rt_load_balance_head = head;
+	rq->rt.rt_load_balance_curr = curr;
+
+	return p;
+}
+
+static struct task_struct *load_balance_next_rt(void *arg)
+{
+	struct rq *rq = arg;
+	struct rt_prio_array *array = &rq->rt.active;
+	struct list_head *head, *curr;
+	struct task_struct *p;
+	int idx;
+
+	idx = rq->rt.rt_load_balance_idx;
+	head = rq->rt.rt_load_balance_head;
+	curr = rq->rt.rt_load_balance_curr;
+
+	/*
+	 * If we arrived back to the head again then
+	 * iterate to the next queue (if any):
+	 */
+	if (unlikely(head == curr)) {
+		int next_idx = find_next_bit(array->bitmap, MAX_RT_PRIO, idx+1);
+
+		if (next_idx >= MAX_RT_PRIO)
+			return NULL;
+
+		idx = next_idx;
+		head = array->queue + idx;
+		curr = head->prev;
+
+		rq->rt.rt_load_balance_idx = idx;
+		rq->rt.rt_load_balance_head = head;
+	}
+
+	p = list_entry(curr, struct task_struct, run_list);
+
+	curr = curr->prev;
+
+	rq->rt.rt_load_balance_curr = curr;
+
+	return p;
+}
+
+static int
+load_balance_rt(struct rq *this_rq, int this_cpu, struct rq *busiest,
+			unsigned long max_nr_move, unsigned long max_load_move,
+			struct sched_domain *sd, enum cpu_idle_type idle,
+			int *all_pinned, unsigned long *load_moved)
+{
+	int this_best_prio, best_prio, best_prio_seen = 0;
+	int nr_moved;
+	struct rq_iterator rt_rq_iterator;
+
+	best_prio = sched_find_first_bit(busiest->rt.active.bitmap);
+	this_best_prio = sched_find_first_bit(this_rq->rt.active.bitmap);
+
+	/*
+	 * Enable handling of the case where there is more than one task
+	 * with the best priority.   If the current running task is one
+	 * of those with prio==best_prio we know it won't be moved
+	 * and therefore it's safe to override the skip (based on load)
+	 * of any task we find with that prio.
+	 */
+	if (busiest->curr->prio == best_prio)
+		best_prio_seen = 1;
+
+	rt_rq_iterator.start = load_balance_start_rt;
+	rt_rq_iterator.next = load_balance_next_rt;
+	/* pass 'busiest' rq argument into
+	 * load_balance_[start|next]_rt iterators
+	 */
+	rt_rq_iterator.arg = busiest;
+
+	nr_moved = balance_tasks(this_rq, this_cpu, busiest, max_nr_move,
+			max_load_move, sd, idle, all_pinned, load_moved,
+			this_best_prio, best_prio, best_prio_seen,
+			&rt_rq_iterator);
+
+	return nr_moved;
+}
+
+static void task_tick_rt(struct rq *rq, struct task_struct *p)
+{
+	/*
+	 * RR tasks need a special form of timeslice management.
+	 * FIFO tasks have no timeslices.
+	 */
+	if (p->policy != SCHED_RR)
+		return;
+
+	if (--p->time_slice)
+		return;
+
+	p->time_slice = static_prio_timeslice(p->static_prio);
+	set_tsk_need_resched(p);
+
+	/* put it at the end of the queue: */
+	requeue_task_rt(rq, p);
+}
+
+/*
+ * No parent/child timeslice management necessary for RT tasks,
+ * just activate them:
+ */
+static void task_new_rt(struct rq *rq, struct task_struct *p)
+{
+	activate_task(rq, p, 1);
+}
+
+static struct sched_class rt_sched_class __read_mostly = {
+	.enqueue_task		= enqueue_task_rt,
+	.dequeue_task		= dequeue_task_rt,
+	.yield_task		= yield_task_rt,
+
+	.check_preempt_curr	= check_preempt_curr_rt,
+
+	.pick_next_task		= pick_next_task_rt,
+	.put_prev_task		= put_prev_task_rt,
+
+	.load_balance		= load_balance_rt,
+
+	.task_tick		= task_tick_rt,
+	.task_new		= task_new_rt,
+};
diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h
new file mode 100644
index 0000000..c63c38f
--- /dev/null
+++ b/kernel/sched_stats.h
@@ -0,0 +1,235 @@
+
+#ifdef CONFIG_SCHEDSTATS
+/*
+ * bump this up when changing the output format or the meaning of an existing
+ * format, so that tools can adapt (or abort)
+ */
+#define SCHEDSTAT_VERSION 14
+
+static int show_schedstat(struct seq_file *seq, void *v)
+{
+	int cpu;
+
+	seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
+	seq_printf(seq, "timestamp %lu\n", jiffies);
+	for_each_online_cpu(cpu) {
+		struct rq *rq = cpu_rq(cpu);
+#ifdef CONFIG_SMP
+		struct sched_domain *sd;
+		int dcnt = 0;
+#endif
+
+		/* runqueue-specific stats */
+		seq_printf(seq,
+		    "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %llu %llu %lu",
+		    cpu, rq->yld_both_empty,
+		    rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt,
+		    rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
+		    rq->ttwu_cnt, rq->ttwu_local,
+		    rq->rq_sched_info.cpu_time,
+		    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
+
+		seq_printf(seq, "\n");
+
+#ifdef CONFIG_SMP
+		/* domain-specific stats */
+		preempt_disable();
+		for_each_domain(cpu, sd) {
+			enum cpu_idle_type itype;
+			char mask_str[NR_CPUS];
+
+			cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
+			seq_printf(seq, "domain%d %s", dcnt++, mask_str);
+			for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
+					itype++) {
+				seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
+						"%lu",
+				    sd->lb_cnt[itype],
+				    sd->lb_balanced[itype],
+				    sd->lb_failed[itype],
+				    sd->lb_imbalance[itype],
+				    sd->lb_gained[itype],
+				    sd->lb_hot_gained[itype],
+				    sd->lb_nobusyq[itype],
+				    sd->lb_nobusyg[itype]);
+			}
+			seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
+			    " %lu %lu %lu\n",
+			    sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
+			    sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
+			    sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
+			    sd->ttwu_wake_remote, sd->ttwu_move_affine,
+			    sd->ttwu_move_balance);
+		}
+		preempt_enable();
+#endif
+	}
+	return 0;
+}
+
+static int schedstat_open(struct inode *inode, struct file *file)
+{
+	unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
+	char *buf = kmalloc(size, GFP_KERNEL);
+	struct seq_file *m;
+	int res;
+
+	if (!buf)
+		return -ENOMEM;
+	res = single_open(file, show_schedstat, NULL);
+	if (!res) {
+		m = file->private_data;
+		m->buf = buf;
+		m->size = size;
+	} else
+		kfree(buf);
+	return res;
+}
+
+const struct file_operations proc_schedstat_operations = {
+	.open    = schedstat_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+/*
+ * Expects runqueue lock to be held for atomicity of update
+ */
+static inline void
+rq_sched_info_arrive(struct rq *rq, unsigned long long delta)
+{
+	if (rq) {
+		rq->rq_sched_info.run_delay += delta;
+		rq->rq_sched_info.pcnt++;
+	}
+}
+
+/*
+ * Expects runqueue lock to be held for atomicity of update
+ */
+static inline void
+rq_sched_info_depart(struct rq *rq, unsigned long long delta)
+{
+	if (rq)
+		rq->rq_sched_info.cpu_time += delta;
+}
+# define schedstat_inc(rq, field)	do { (rq)->field++; } while (0)
+# define schedstat_add(rq, field, amt)	do { (rq)->field += (amt); } while (0)
+#else /* !CONFIG_SCHEDSTATS */
+static inline void
+rq_sched_info_arrive(struct rq *rq, unsigned long long delta)
+{}
+static inline void
+rq_sched_info_depart(struct rq *rq, unsigned long long delta)
+{}
+# define schedstat_inc(rq, field)	do { } while (0)
+# define schedstat_add(rq, field, amt)	do { } while (0)
+#endif
+
+#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
+/*
+ * Called when a process is dequeued from the active array and given
+ * the cpu.  We should note that with the exception of interactive
+ * tasks, the expired queue will become the active queue after the active
+ * queue is empty, without explicitly dequeuing and requeuing tasks in the
+ * expired queue.  (Interactive tasks may be requeued directly to the
+ * active queue, thus delaying tasks in the expired queue from running;
+ * see scheduler_tick()).
+ *
+ * This function is only called from sched_info_arrive(), rather than
+ * dequeue_task(). Even though a task may be queued and dequeued multiple
+ * times as it is shuffled about, we're really interested in knowing how
+ * long it was from the *first* time it was queued to the time that it
+ * finally hit a cpu.
+ */
+static inline void sched_info_dequeued(struct task_struct *t)
+{
+	t->sched_info.last_queued = 0;
+}
+
+/*
+ * Called when a task finally hits the cpu.  We can now calculate how
+ * long it was waiting to run.  We also note when it began so that we
+ * can keep stats on how long its timeslice is.
+ */
+static void sched_info_arrive(struct task_struct *t)
+{
+	unsigned long long now = sched_clock(), delta = 0;
+
+	if (t->sched_info.last_queued)
+		delta = now - t->sched_info.last_queued;
+	sched_info_dequeued(t);
+	t->sched_info.run_delay += delta;
+	t->sched_info.last_arrival = now;
+	t->sched_info.pcnt++;
+
+	rq_sched_info_arrive(task_rq(t), delta);
+}
+
+/*
+ * Called when a process is queued into either the active or expired
+ * array.  The time is noted and later used to determine how long we
+ * had to wait for us to reach the cpu.  Since the expired queue will
+ * become the active queue after active queue is empty, without dequeuing
+ * and requeuing any tasks, we are interested in queuing to either. It
+ * is unusual but not impossible for tasks to be dequeued and immediately
+ * requeued in the same or another array: this can happen in sched_yield(),
+ * set_user_nice(), and even load_balance() as it moves tasks from runqueue
+ * to runqueue.
+ *
+ * This function is only called from enqueue_task(), but also only updates
+ * the timestamp if it is already not set.  It's assumed that
+ * sched_info_dequeued() will clear that stamp when appropriate.
+ */
+static inline void sched_info_queued(struct task_struct *t)
+{
+	if (unlikely(sched_info_on()))
+		if (!t->sched_info.last_queued)
+			t->sched_info.last_queued = sched_clock();
+}
+
+/*
+ * Called when a process ceases being the active-running process, either
+ * voluntarily or involuntarily.  Now we can calculate how long we ran.
+ */
+static inline void sched_info_depart(struct task_struct *t)
+{
+	unsigned long long delta = sched_clock() - t->sched_info.last_arrival;
+
+	t->sched_info.cpu_time += delta;
+	rq_sched_info_depart(task_rq(t), delta);
+}
+
+/*
+ * Called when tasks are switched involuntarily due, typically, to expiring
+ * their time slice.  (This may also be called when switching to or from
+ * the idle task.)  We are only called when prev != next.
+ */
+static inline void
+__sched_info_switch(struct task_struct *prev, struct task_struct *next)
+{
+	struct rq *rq = task_rq(prev);
+
+	/*
+	 * prev now departs the cpu.  It's not interesting to record
+	 * stats about how efficient we were at scheduling the idle
+	 * process, however.
+	 */
+	if (prev != rq->idle)
+		sched_info_depart(prev);
+
+	if (next != rq->idle)
+		sched_info_arrive(next);
+}
+static inline void
+sched_info_switch(struct task_struct *prev, struct task_struct *next)
+{
+	if (unlikely(sched_info_on()))
+		__sched_info_switch(prev, next);
+}
+#else
+#define sched_info_queued(t)		do { } while (0)
+#define sched_info_switch(t, next)	do { } while (0)
+#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
+
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 0b9886a..73217a9 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -488,7 +488,6 @@
 
 static int ksoftirqd(void * __bind_cpu)
 {
-	set_user_nice(current, 19);
 	current->flags |= PF_NOFREEZE;
 
 	set_current_state(TASK_INTERRUPTIBLE);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 30ee462..51f5dac 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -206,7 +206,87 @@
 	{ .ctl_name = 0 }
 };
 
+#ifdef CONFIG_SCHED_DEBUG
+static unsigned long min_sched_granularity_ns = 100000;		/* 100 usecs */
+static unsigned long max_sched_granularity_ns = 1000000000;	/* 1 second */
+static unsigned long min_wakeup_granularity_ns;			/* 0 usecs */
+static unsigned long max_wakeup_granularity_ns = 1000000000;	/* 1 second */
+#endif
+
 static ctl_table kern_table[] = {
+#ifdef CONFIG_SCHED_DEBUG
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_granularity_ns",
+		.data		= &sysctl_sched_granularity,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &min_sched_granularity_ns,
+		.extra2		= &max_sched_granularity_ns,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_wakeup_granularity_ns",
+		.data		= &sysctl_sched_wakeup_granularity,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &min_wakeup_granularity_ns,
+		.extra2		= &max_wakeup_granularity_ns,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_batch_wakeup_granularity_ns",
+		.data		= &sysctl_sched_batch_wakeup_granularity,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &min_wakeup_granularity_ns,
+		.extra2		= &max_wakeup_granularity_ns,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_stat_granularity_ns",
+		.data		= &sysctl_sched_stat_granularity,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &min_wakeup_granularity_ns,
+		.extra2		= &max_wakeup_granularity_ns,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_runtime_limit_ns",
+		.data		= &sysctl_sched_runtime_limit,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &min_sched_granularity_ns,
+		.extra2		= &max_sched_granularity_ns,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_child_runs_first",
+		.data		= &sysctl_sched_child_runs_first,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "sched_features",
+		.data		= &sysctl_sched_features,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+#endif
 	{
 		.ctl_name	= KERN_PANIC,
 		.procname	= "panic",
diff --git a/lib/Kconfig b/lib/Kconfig
index 2e7ae6b..3eb29d5 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -64,6 +64,12 @@
 config ZLIB_DEFLATE
 	tristate
 
+config LZO_COMPRESS
+	tristate
+
+config LZO_DECOMPRESS
+	tristate
+
 #
 # Generic allocator support is selected if needed
 #
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index da95e10c..fab32a2 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -105,6 +105,15 @@
 	   can be detected via the NMI-watchdog, on platforms that
 	   support it.)
 
+config SCHED_DEBUG
+	bool "Collect scheduler debugging info"
+	depends on DEBUG_KERNEL && PROC_FS
+	default y
+	help
+	  If you say Y here, the /proc/sched_debug file will be provided
+	  that can help debug the scheduler. The runtime overhead of this
+	  option is minimal.
+
 config SCHEDSTATS
 	bool "Collect scheduler statistics"
 	depends on DEBUG_KERNEL && PROC_FS
diff --git a/lib/Makefile b/lib/Makefile
index c8c8e20..d1b366b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -49,6 +49,8 @@
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
 obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
 obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
+obj-$(CONFIG_LZO_COMPRESS) += lzo/
+obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
 
 obj-$(CONFIG_TEXTSEARCH) += textsearch.o
 obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile
new file mode 100644
index 0000000..e764116
--- /dev/null
+++ b/lib/lzo/Makefile
@@ -0,0 +1,5 @@
+lzo_compress-objs := lzo1x_compress.o
+lzo_decompress-objs := lzo1x_decompress.o
+
+obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o
+obj-$(CONFIG_LZO_DECOMPRESS) += lzo_decompress.o
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
new file mode 100644
index 0000000..c935f00
--- /dev/null
+++ b/lib/lzo/lzo1x_compress.c
@@ -0,0 +1,226 @@
+/*
+ *  LZO1X Compressor from MiniLZO
+ *
+ *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ *  The full LZO package can be found at:
+ *  http://www.oberhumer.com/opensource/lzo/
+ *
+ *  Changed for kernel use by:
+ *  Nitin Gupta <nitingupta910@gmail.com>
+ *  Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/lzo.h>
+#include <asm/unaligned.h>
+#include "lzodefs.h"
+
+static noinline size_t
+_lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+		unsigned char *out, size_t *out_len, void *wrkmem)
+{
+	const unsigned char * const in_end = in + in_len;
+	const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5;
+	const unsigned char ** const dict = wrkmem;
+	const unsigned char *ip = in, *ii = ip;
+	const unsigned char *end, *m, *m_pos;
+	size_t m_off, m_len, dindex;
+	unsigned char *op = out;
+
+	ip += 4;
+
+	for (;;) {
+		dindex = ((0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
+		m_pos = dict[dindex];
+
+		if (m_pos < in)
+			goto literal;
+
+		if (ip == m_pos || (ip - m_pos) > M4_MAX_OFFSET)
+			goto literal;
+
+		m_off = ip - m_pos;
+		if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+			goto try_match;
+
+		dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f);
+		m_pos = dict[dindex];
+
+		if (m_pos < in)
+			goto literal;
+
+		if (ip == m_pos || (ip - m_pos) > M4_MAX_OFFSET)
+			goto literal;
+
+		m_off = ip - m_pos;
+		if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+			goto try_match;
+
+		goto literal;
+
+try_match:
+		if (get_unaligned((const unsigned short *)m_pos)
+				== get_unaligned((const unsigned short *)ip)) {
+			if (likely(m_pos[2] == ip[2]))
+					goto match;
+		}
+
+literal:
+		dict[dindex] = ip;
+		++ip;
+		if (unlikely(ip >= ip_end))
+			break;
+		continue;
+
+match:
+		dict[dindex] = ip;
+		if (ip != ii) {
+			size_t t = ip - ii;
+
+			if (t <= 3) {
+				op[-2] |= t;
+			} else if (t <= 18) {
+				*op++ = (t - 3);
+			} else {
+				size_t tt = t - 18;
+
+				*op++ = 0;
+				while (tt > 255) {
+					tt -= 255;
+					*op++ = 0;
+				}
+				*op++ = tt;
+			}
+			do {
+				*op++ = *ii++;
+			} while (--t > 0);
+		}
+
+		ip += 3;
+		if (m_pos[3] != *ip++ || m_pos[4] != *ip++
+				|| m_pos[5] != *ip++ || m_pos[6] != *ip++
+				|| m_pos[7] != *ip++ || m_pos[8] != *ip++) {
+			--ip;
+			m_len = ip - ii;
+
+			if (m_off <= M2_MAX_OFFSET) {
+				m_off -= 1;
+				*op++ = (((m_len - 1) << 5)
+						| ((m_off & 7) << 2));
+				*op++ = (m_off >> 3);
+			} else if (m_off <= M3_MAX_OFFSET) {
+				m_off -= 1;
+				*op++ = (M3_MARKER | (m_len - 2));
+				goto m3_m4_offset;
+			} else {
+				m_off -= 0x4000;
+
+				*op++ = (M4_MARKER | ((m_off & 0x4000) >> 11)
+						| (m_len - 2));
+				goto m3_m4_offset;
+			}
+		} else {
+			end = in_end;
+			m = m_pos + M2_MAX_LEN + 1;
+
+			while (ip < end && *m == *ip) {
+				m++;
+				ip++;
+			}
+			m_len = ip - ii;
+
+			if (m_off <= M3_MAX_OFFSET) {
+				m_off -= 1;
+				if (m_len <= 33) {
+					*op++ = (M3_MARKER | (m_len - 2));
+				} else {
+					m_len -= 33;
+					*op++ = M3_MARKER | 0;
+					goto m3_m4_len;
+				}
+			} else {
+				m_off -= 0x4000;
+				if (m_len <= M4_MAX_LEN) {
+					*op++ = (M4_MARKER
+						| ((m_off & 0x4000) >> 11)
+						| (m_len - 2));
+				} else {
+					m_len -= M4_MAX_LEN;
+					*op++ = (M4_MARKER
+						| ((m_off & 0x4000) >> 11));
+m3_m4_len:
+					while (m_len > 255) {
+						m_len -= 255;
+						*op++ = 0;
+					}
+
+					*op++ = (m_len);
+				}
+			}
+m3_m4_offset:
+			*op++ = ((m_off & 63) << 2);
+			*op++ = (m_off >> 6);
+		}
+
+		ii = ip;
+		if (unlikely(ip >= ip_end))
+			break;
+	}
+
+	*out_len = op - out;
+	return in_end - ii;
+}
+
+int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
+			size_t *out_len, void *wrkmem)
+{
+	const unsigned char *ii;
+	unsigned char *op = out;
+	size_t t;
+
+	if (unlikely(in_len <= M2_MAX_LEN + 5)) {
+		t = in_len;
+	} else {
+		t = _lzo1x_1_do_compress(in, in_len, op, out_len, wrkmem);
+		op += *out_len;
+	}
+
+	if (t > 0) {
+		ii = in + in_len - t;
+
+		if (op == out && t <= 238) {
+			*op++ = (17 + t);
+		} else if (t <= 3) {
+			op[-2] |= t;
+		} else if (t <= 18) {
+			*op++ = (t - 3);
+		} else {
+			size_t tt = t - 18;
+
+			*op++ = 0;
+			while (tt > 255) {
+				tt -= 255;
+				*op++ = 0;
+			}
+
+			*op++ = tt;
+		}
+		do {
+			*op++ = *ii++;
+		} while (--t > 0);
+	}
+
+	*op++ = M4_MARKER | 1;
+	*op++ = 0;
+	*op++ = 0;
+
+	*out_len = op - out;
+	return LZO_E_OK;
+}
+EXPORT_SYMBOL_GPL(lzo1x_1_compress);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO1X-1 Compressor");
+
diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c
new file mode 100644
index 0000000..9dc7056
--- /dev/null
+++ b/lib/lzo/lzo1x_decompress.c
@@ -0,0 +1,254 @@
+/*
+ *  LZO1X Decompressor from MiniLZO
+ *
+ *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ *  The full LZO package can be found at:
+ *  http://www.oberhumer.com/opensource/lzo/
+ *
+ *  Changed for kernel use by:
+ *  Nitin Gupta <nitingupta910@gmail.com>
+ *  Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/lzo.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+#include "lzodefs.h"
+
+#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
+#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
+#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
+
+#define COPY4(dst, src)	\
+		put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+
+int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
+			unsigned char *out, size_t *out_len)
+{
+	const unsigned char * const ip_end = in + in_len;
+	unsigned char * const op_end = out + *out_len;
+	const unsigned char *ip = in, *m_pos;
+	unsigned char *op = out;
+	size_t t;
+
+	*out_len = 0;
+
+	if (*ip > 17) {
+		t = *ip++ - 17;
+		if (t < 4)
+			goto match_next;
+		if (HAVE_OP(t, op_end, op))
+			goto output_overrun;
+		if (HAVE_IP(t + 1, ip_end, ip))
+			goto input_overrun;
+		do {
+			*op++ = *ip++;
+		} while (--t > 0);
+		goto first_literal_run;
+	}
+
+	while ((ip < ip_end)) {
+		t = *ip++;
+		if (t >= 16)
+			goto match;
+		if (t == 0) {
+			if (HAVE_IP(1, ip_end, ip))
+				goto input_overrun;
+			while (*ip == 0) {
+				t += 255;
+				ip++;
+				if (HAVE_IP(1, ip_end, ip))
+					goto input_overrun;
+			}
+			t += 15 + *ip++;
+		}
+		if (HAVE_OP(t + 3, op_end, op))
+			goto output_overrun;
+		if (HAVE_IP(t + 4, ip_end, ip))
+			goto input_overrun;
+
+		COPY4(op, ip);
+		op += 4;
+		ip += 4;
+		if (--t > 0) {
+			if (t >= 4) {
+				do {
+					COPY4(op, ip);
+					op += 4;
+					ip += 4;
+					t -= 4;
+				} while (t >= 4);
+				if (t > 0) {
+					do {
+						*op++ = *ip++;
+					} while (--t > 0);
+				}
+			} else {
+				do {
+					*op++ = *ip++;
+				} while (--t > 0);
+			}
+		}
+
+first_literal_run:
+		t = *ip++;
+		if (t >= 16)
+			goto match;
+		m_pos = op - (1 + M2_MAX_OFFSET);
+		m_pos -= t >> 2;
+		m_pos -= *ip++ << 2;
+
+		if (HAVE_LB(m_pos, out, op))
+			goto lookbehind_overrun;
+
+		if (HAVE_OP(3, op_end, op))
+			goto output_overrun;
+		*op++ = *m_pos++;
+		*op++ = *m_pos++;
+		*op++ = *m_pos;
+
+		goto match_done;
+
+		do {
+match:
+			if (t >= 64) {
+				m_pos = op - 1;
+				m_pos -= (t >> 2) & 7;
+				m_pos -= *ip++ << 3;
+				t = (t >> 5) - 1;
+				if (HAVE_LB(m_pos, out, op))
+					goto lookbehind_overrun;
+				if (HAVE_OP(t + 3 - 1, op_end, op))
+					goto output_overrun;
+				goto copy_match;
+			} else if (t >= 32) {
+				t &= 31;
+				if (t == 0) {
+					if (HAVE_IP(1, ip_end, ip))
+						goto input_overrun;
+					while (*ip == 0) {
+						t += 255;
+						ip++;
+						if (HAVE_IP(1, ip_end, ip))
+							goto input_overrun;
+					}
+					t += 31 + *ip++;
+				}
+				m_pos = op - 1;
+				m_pos -= le16_to_cpu(get_unaligned(
+					(const unsigned short *)ip)) >> 2;
+				ip += 2;
+			} else if (t >= 16) {
+				m_pos = op;
+				m_pos -= (t & 8) << 11;
+
+				t &= 7;
+				if (t == 0) {
+					if (HAVE_IP(1, ip_end, ip))
+						goto input_overrun;
+					while (*ip == 0) {
+						t += 255;
+						ip++;
+						if (HAVE_IP(1, ip_end, ip))
+							goto input_overrun;
+					}
+					t += 7 + *ip++;
+				}
+				m_pos -= le16_to_cpu(get_unaligned(
+					(const unsigned short *)ip) >> 2);
+				ip += 2;
+				if (m_pos == op)
+					goto eof_found;
+				m_pos -= 0x4000;
+			} else {
+				m_pos = op - 1;
+				m_pos -= t >> 2;
+				m_pos -= *ip++ << 2;
+
+				if (HAVE_LB(m_pos, out, op))
+					goto lookbehind_overrun;
+				if (HAVE_OP(2, op_end, op))
+					goto output_overrun;
+
+				*op++ = *m_pos++;
+				*op++ = *m_pos;
+				goto match_done;
+			}
+
+			if (HAVE_LB(m_pos, out, op))
+				goto lookbehind_overrun;
+			if (HAVE_OP(t + 3 - 1, op_end, op))
+				goto output_overrun;
+
+			if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
+				COPY4(op, m_pos);
+				op += 4;
+				m_pos += 4;
+				t -= 4 - (3 - 1);
+				do {
+					COPY4(op, m_pos);
+					op += 4;
+					m_pos += 4;
+					t -= 4;
+				} while (t >= 4);
+				if (t > 0)
+					do {
+						*op++ = *m_pos++;
+					} while (--t > 0);
+			} else {
+copy_match:
+				*op++ = *m_pos++;
+				*op++ = *m_pos++;
+				do {
+					*op++ = *m_pos++;
+				} while (--t > 0);
+			}
+match_done:
+			t = ip[-2] & 3;
+			if (t == 0)
+				break;
+match_next:
+			if (HAVE_OP(t, op_end, op))
+				goto output_overrun;
+			if (HAVE_IP(t + 1, ip_end, ip))
+				goto input_overrun;
+
+			*op++ = *ip++;
+			if (t > 1) {
+				*op++ = *ip++;
+				if (t > 2)
+					*op++ = *ip++;
+			}
+
+			t = *ip++;
+		} while (ip < ip_end);
+	}
+
+	*out_len = op - out;
+	return LZO_E_EOF_NOT_FOUND;
+
+eof_found:
+	*out_len = op - out;
+	return (ip == ip_end ? LZO_E_OK :
+		(ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+input_overrun:
+	*out_len = op - out;
+	return LZO_E_INPUT_OVERRUN;
+
+output_overrun:
+	*out_len = op - out;
+	return LZO_E_OUTPUT_OVERRUN;
+
+lookbehind_overrun:
+	*out_len = op - out;
+	return LZO_E_LOOKBEHIND_OVERRUN;
+}
+
+EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO1X Decompressor");
+
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
new file mode 100644
index 0000000..b6d482c
--- /dev/null
+++ b/lib/lzo/lzodefs.h
@@ -0,0 +1,43 @@
+/*
+ *  lzodefs.h -- architecture, OS and compiler specific defines
+ *
+ *  Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ *  The full LZO package can be found at:
+ *  http://www.oberhumer.com/opensource/lzo/
+ *
+ *  Changed for kernel use by:
+ *  Nitin Gupta <nitingupta910@gmail.com>
+ *  Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#define LZO_VERSION		0x2020
+#define LZO_VERSION_STRING	"2.02"
+#define LZO_VERSION_DATE	"Oct 17 2005"
+
+#define M1_MAX_OFFSET	0x0400
+#define M2_MAX_OFFSET	0x0800
+#define M3_MAX_OFFSET	0x4000
+#define M4_MAX_OFFSET	0xbfff
+
+#define M1_MIN_LEN	2
+#define M1_MAX_LEN	2
+#define M2_MIN_LEN	3
+#define M2_MAX_LEN	8
+#define M3_MIN_LEN	3
+#define M3_MAX_LEN	33
+#define M4_MIN_LEN	3
+#define M4_MAX_LEN	9
+
+#define M1_MARKER	0
+#define M2_MARKER	64
+#define M3_MARKER	32
+#define M4_MARKER	16
+
+#define D_BITS		14
+#define D_MASK		((1u << D_BITS) - 1)
+#define D_HIGH		((D_MASK >> 1) + 1)
+
+#define DX2(p, s1, s2)	(((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \
+							<< (s1)) ^ (p)[0])
+#define DX3(p, s1, s2, s3)	((DX2((p)+1, s2, s3) << (s1)) ^ (p)[0])
diff --git a/mm/filemap.c b/mm/filemap.c
index d1d9814..c6ebd9f 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1245,26 +1245,6 @@
 	return written;
 }
 
-ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos,
-			 size_t count, read_actor_t actor, void *target)
-{
-	read_descriptor_t desc;
-
-	if (!count)
-		return 0;
-
-	desc.written = 0;
-	desc.count = count;
-	desc.arg.data = target;
-	desc.error = 0;
-
-	do_generic_file_read(in_file, ppos, &desc, actor);
-	if (desc.written)
-		return desc.written;
-	return desc.error;
-}
-EXPORT_SYMBOL(generic_file_sendfile);
-
 static ssize_t
 do_readahead(struct address_space *mapping, struct file *filp,
 	     unsigned long index, unsigned long nr)
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index fa360e5..65ffc32 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -159,28 +159,6 @@
 }
 EXPORT_SYMBOL_GPL(xip_file_read);
 
-ssize_t
-xip_file_sendfile(struct file *in_file, loff_t *ppos,
-	     size_t count, read_actor_t actor, void *target)
-{
-	read_descriptor_t desc;
-
-	if (!count)
-		return 0;
-
-	desc.written = 0;
-	desc.count = count;
-	desc.arg.data = target;
-	desc.error = 0;
-
-	do_xip_mapping_read(in_file->f_mapping, &in_file->f_ra, in_file,
-			    ppos, &desc, actor);
-	if (desc.written)
-		return desc.written;
-	return desc.error;
-}
-EXPORT_SYMBOL_GPL(xip_file_sendfile);
-
 /*
  * __xip_unmap is invoked from xip_unmap and
  * xip_write
diff --git a/mm/shmem.c b/mm/shmem.c
index b6aae2b..0493e4d 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1100,9 +1100,9 @@
 	 * Normally, filepage is NULL on entry, and either found
 	 * uptodate immediately, or allocated and zeroed, or read
 	 * in under swappage, which is then assigned to filepage.
-	 * But shmem_prepare_write passes in a locked filepage,
-	 * which may be found not uptodate by other callers too,
-	 * and may need to be copied from the swappage read in.
+	 * But shmem_readpage and shmem_prepare_write pass in a locked
+	 * filepage, which may be found not uptodate by other callers
+	 * too, and may need to be copied from the swappage read in.
 	 */
 repeat:
 	if (!filepage)
@@ -1485,9 +1485,18 @@
 static const struct inode_operations shmem_symlink_inline_operations;
 
 /*
- * Normally tmpfs makes no use of shmem_prepare_write, but it
- * lets a tmpfs file be used read-write below the loop driver.
+ * Normally tmpfs avoids the use of shmem_readpage and shmem_prepare_write;
+ * but providing them allows a tmpfs file to be used for splice, sendfile, and
+ * below the loop driver, in the generic fashion that many filesystems support.
  */
+static int shmem_readpage(struct file *file, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	int error = shmem_getpage(inode, page->index, &page, SGP_CACHE, NULL);
+	unlock_page(page);
+	return error;
+}
+
 static int
 shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
@@ -1711,25 +1720,6 @@
 	return desc.error;
 }
 
-static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos,
-			 size_t count, read_actor_t actor, void *target)
-{
-	read_descriptor_t desc;
-
-	if (!count)
-		return 0;
-
-	desc.written = 0;
-	desc.count = count;
-	desc.arg.data = target;
-	desc.error = 0;
-
-	do_shmem_file_read(in_file, ppos, &desc, actor);
-	if (desc.written)
-		return desc.written;
-	return desc.error;
-}
-
 static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
@@ -2386,6 +2376,7 @@
 	.writepage	= shmem_writepage,
 	.set_page_dirty	= __set_page_dirty_no_writeback,
 #ifdef CONFIG_TMPFS
+	.readpage	= shmem_readpage,
 	.prepare_write	= shmem_prepare_write,
 	.commit_write	= simple_commit_write,
 #endif
@@ -2399,7 +2390,8 @@
 	.read		= shmem_file_read,
 	.write		= shmem_file_write,
 	.fsync		= simple_sync_file,
-	.sendfile	= shmem_file_sendfile,
+	.splice_read	= generic_file_splice_read,
+	.splice_write	= generic_file_splice_write,
 #endif
 };
 
diff --git a/net/802/tr.c b/net/802/tr.c
index 0ba1946..e56e61a 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -567,7 +567,7 @@
 }
 
 
-static struct seq_operations rif_seq_ops = {
+static const struct seq_operations rif_seq_ops = {
 	.start = rif_seq_start,
 	.next  = rif_seq_next,
 	.stop  = rif_seq_stop,
diff --git a/net/8021q/Makefile b/net/8021q/Makefile
index 97feb44..10ca7f4 100644
--- a/net/8021q/Makefile
+++ b/net/8021q/Makefile
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_VLAN_8021Q) += 8021q.o
 
-8021q-objs := vlan.o vlan_dev.o
+8021q-objs := vlan.o vlan_dev.o vlan_netlink.o
 
 ifeq ($(CONFIG_PROC_FS),y)
 8021q-objs += vlanproc.o
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index de78c9d..e7583ee 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -97,15 +97,22 @@
 
 	/* Register us to receive netdevice events */
 	err = register_netdevice_notifier(&vlan_notifier_block);
-	if (err < 0) {
-		dev_remove_pack(&vlan_packet_type);
-		vlan_proc_cleanup();
-		return err;
-	}
+	if (err < 0)
+		goto err1;
+
+	err = vlan_netlink_init();
+	if (err < 0)
+		goto err2;
 
 	vlan_ioctl_set(vlan_ioctl_handler);
-
 	return 0;
+
+err2:
+	unregister_netdevice_notifier(&vlan_notifier_block);
+err1:
+	vlan_proc_cleanup();
+	dev_remove_pack(&vlan_packet_type);
+	return err;
 }
 
 /* Cleanup all vlan devices
@@ -136,6 +143,7 @@
 {
 	int i;
 
+	vlan_netlink_fini();
 	vlan_ioctl_set(NULL);
 
 	/* Un-register us from receiving netdevice events */
@@ -197,6 +205,34 @@
 	kfree(grp);
 }
 
+static struct vlan_group *vlan_group_alloc(int ifindex)
+{
+	struct vlan_group *grp;
+	unsigned int size;
+	unsigned int i;
+
+	grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
+	if (!grp)
+		return NULL;
+
+	size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
+
+	for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
+		grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
+		if (!grp->vlan_devices_arrays[i])
+			goto err;
+	}
+
+	grp->real_dev_ifindex = ifindex;
+	hlist_add_head_rcu(&grp->hlist,
+			   &vlan_group_hash[vlan_grp_hashfn(ifindex)]);
+	return grp;
+
+err:
+	vlan_group_free(grp);
+	return NULL;
+}
+
 static void vlan_rcu_free(struct rcu_head *rcu)
 {
 	vlan_group_free(container_of(rcu, struct vlan_group, rcu));
@@ -278,47 +314,62 @@
 	return ret;
 }
 
-static int unregister_vlan_device(const char *vlan_IF_name)
+int unregister_vlan_device(struct net_device *dev)
 {
-	struct net_device *dev = NULL;
 	int ret;
 
+	ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
+				  VLAN_DEV_INFO(dev)->vlan_id);
+	unregister_netdevice(dev);
 
-	dev = dev_get_by_name(vlan_IF_name);
-	ret = -EINVAL;
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			rtnl_lock();
-
-			ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
-						  VLAN_DEV_INFO(dev)->vlan_id);
-
-			dev_put(dev);
-			unregister_netdevice(dev);
-
-			rtnl_unlock();
-
-			if (ret == 1)
-				ret = 0;
-		} else {
-			printk(VLAN_ERR
-			       "%s: ERROR:	Tried to remove a non-vlan device "
-			       "with VLAN code, name: %s  priv_flags: %hX\n",
-			       __FUNCTION__, dev->name, dev->priv_flags);
-			dev_put(dev);
-			ret = -EPERM;
-		}
-	} else {
-#ifdef VLAN_DEBUG
-		printk(VLAN_DBG "%s: WARNING: Could not find dev.\n", __FUNCTION__);
-#endif
-		ret = -EINVAL;
-	}
-
+	if (ret == 1)
+		ret = 0;
 	return ret;
 }
 
-static void vlan_setup(struct net_device *new_dev)
+/*
+ * vlan network devices have devices nesting below it, and are a special
+ * "super class" of normal network devices; split their locks off into a
+ * separate class since they always nest.
+ */
+static struct lock_class_key vlan_netdev_xmit_lock_key;
+
+static int vlan_dev_init(struct net_device *dev)
+{
+	struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
+
+	/* IFF_BROADCAST|IFF_MULTICAST; ??? */
+	dev->flags  = real_dev->flags & ~IFF_UP;
+	dev->iflink = real_dev->ifindex;
+	dev->state  = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
+					  (1<<__LINK_STATE_DORMANT))) |
+		      (1<<__LINK_STATE_PRESENT);
+
+	/* TODO: maybe just assign it to be ETHERNET? */
+	dev->type = real_dev->type;
+
+	memcpy(dev->broadcast, real_dev->broadcast, real_dev->addr_len);
+	memcpy(dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
+	dev->addr_len = real_dev->addr_len;
+
+	if (real_dev->features & NETIF_F_HW_VLAN_TX) {
+		dev->hard_header     = real_dev->hard_header;
+		dev->hard_header_len = real_dev->hard_header_len;
+		dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
+		dev->rebuild_header  = real_dev->rebuild_header;
+	} else {
+		dev->hard_header     = vlan_dev_hard_header;
+		dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
+		dev->hard_start_xmit = vlan_dev_hard_start_xmit;
+		dev->rebuild_header  = vlan_dev_rebuild_header;
+	}
+	dev->hard_header_parse = real_dev->hard_header_parse;
+
+	lockdep_set_class(&dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
+	return 0;
+}
+
+void vlan_setup(struct net_device *new_dev)
 {
 	SET_MODULE_OWNER(new_dev);
 
@@ -338,6 +389,7 @@
 
 	/* set up method calls */
 	new_dev->change_mtu = vlan_dev_change_mtu;
+	new_dev->init = vlan_dev_init;
 	new_dev->open = vlan_dev_open;
 	new_dev->stop = vlan_dev_stop;
 	new_dev->set_mac_address = vlan_dev_set_mac_address;
@@ -366,26 +418,97 @@
 	}
 }
 
-/*
- * vlan network devices have devices nesting below it, and are a special
- * "super class" of normal network devices; split their locks off into a
- * separate class since they always nest.
- */
-static struct lock_class_key vlan_netdev_xmit_lock_key;
+int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id)
+{
+	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
+		printk(VLAN_DBG "%s: VLANs not supported on %s.\n",
+			__FUNCTION__, real_dev->name);
+		return -EOPNOTSUPP;
+	}
 
+	if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&
+	    !real_dev->vlan_rx_register) {
+		printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
+			__FUNCTION__, real_dev->name);
+		return -EOPNOTSUPP;
+	}
+
+	if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+	    (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) {
+		printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
+			__FUNCTION__, real_dev->name);
+		return -EOPNOTSUPP;
+	}
+
+	/* The real device must be up and operating in order to
+	 * assosciate a VLAN device with it.
+	 */
+	if (!(real_dev->flags & IFF_UP))
+		return -ENETDOWN;
+
+	if (__find_vlan_dev(real_dev, vlan_id) != NULL) {
+		/* was already registered. */
+		printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__);
+		return -EEXIST;
+	}
+
+	return 0;
+}
+
+int register_vlan_dev(struct net_device *dev)
+{
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+	struct net_device *real_dev = vlan->real_dev;
+	unsigned short vlan_id = vlan->vlan_id;
+	struct vlan_group *grp, *ngrp = NULL;
+	int err;
+
+	grp = __vlan_find_group(real_dev->ifindex);
+	if (!grp) {
+		ngrp = grp = vlan_group_alloc(real_dev->ifindex);
+		if (!grp)
+			return -ENOBUFS;
+	}
+
+	err = register_netdevice(dev);
+	if (err < 0)
+		goto out_free_group;
+
+	/* Account for reference in struct vlan_dev_info */
+	dev_hold(real_dev);
+
+	vlan_transfer_operstate(real_dev, dev);
+	linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */
+
+	/* So, got the sucker initialized, now lets place
+	 * it into our local structure.
+	 */
+	vlan_group_set_device(grp, vlan_id, dev);
+	if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
+		real_dev->vlan_rx_register(real_dev, ngrp);
+	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
+		real_dev->vlan_rx_add_vid(real_dev, vlan_id);
+
+	if (vlan_proc_add_dev(dev) < 0)
+		printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
+		       dev->name);
+	return 0;
+
+out_free_group:
+	if (ngrp)
+		vlan_group_free(ngrp);
+	return err;
+}
 
 /*  Attach a VLAN device to a mac address (ie Ethernet Card).
- *  Returns the device that was created, or NULL if there was
- *  an error of some kind.
+ *  Returns 0 if the device was created or a negative error code otherwise.
  */
-static struct net_device *register_vlan_device(const char *eth_IF_name,
-					       unsigned short VLAN_ID)
+static int register_vlan_device(struct net_device *real_dev,
+				unsigned short VLAN_ID)
 {
-	struct vlan_group *grp;
 	struct net_device *new_dev;
-	struct net_device *real_dev; /* the ethernet device */
 	char name[IFNAMSIZ];
-	int i;
+	int err;
 
 #ifdef VLAN_DEBUG
 	printk(VLAN_DBG "%s: if_name -:%s:-	vid: %i\n",
@@ -393,49 +516,11 @@
 #endif
 
 	if (VLAN_ID >= VLAN_VID_MASK)
-		goto out_ret_null;
+		return -ERANGE;
 
-	/* find the device relating to eth_IF_name. */
-	real_dev = dev_get_by_name(eth_IF_name);
-	if (!real_dev)
-		goto out_ret_null;
-
-	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
-		printk(VLAN_DBG "%s: VLANs not supported on %s.\n",
-			__FUNCTION__, real_dev->name);
-		goto out_put_dev;
-	}
-
-	if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&
-	    !real_dev->vlan_rx_register) {
-		printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
-			__FUNCTION__, real_dev->name);
-		goto out_put_dev;
-	}
-
-	if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
-	    (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) {
-		printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
-			__FUNCTION__, real_dev->name);
-		goto out_put_dev;
-	}
-
-	/* From this point on, all the data structures must remain
-	 * consistent.
-	 */
-	rtnl_lock();
-
-	/* The real device must be up and operating in order to
-	 * assosciate a VLAN device with it.
-	 */
-	if (!(real_dev->flags & IFF_UP))
-		goto out_unlock;
-
-	if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) {
-		/* was already registered. */
-		printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__);
-		goto out_unlock;
-	}
+	err = vlan_check_real_dev(real_dev, VLAN_ID);
+	if (err < 0)
+		return err;
 
 	/* Gotta set up the fields for the device. */
 #ifdef VLAN_DEBUG
@@ -471,138 +556,40 @@
 			       vlan_setup);
 
 	if (new_dev == NULL)
-		goto out_unlock;
-
-#ifdef VLAN_DEBUG
-	printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
-#endif
-	/* IFF_BROADCAST|IFF_MULTICAST; ??? */
-	new_dev->flags = real_dev->flags;
-	new_dev->flags &= ~IFF_UP;
-
-	new_dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
-					     (1<<__LINK_STATE_DORMANT))) |
-			 (1<<__LINK_STATE_PRESENT);
+		return -ENOBUFS;
 
 	/* need 4 bytes for extra VLAN header info,
 	 * hope the underlying device can handle it.
 	 */
 	new_dev->mtu = real_dev->mtu;
 
-	/* TODO: maybe just assign it to be ETHERNET? */
-	new_dev->type = real_dev->type;
-
-	new_dev->hard_header_len = real_dev->hard_header_len;
-	if (!(real_dev->features & NETIF_F_HW_VLAN_TX)) {
-		/* Regular ethernet + 4 bytes (18 total). */
-		new_dev->hard_header_len += VLAN_HLEN;
-	}
-
+#ifdef VLAN_DEBUG
+	printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
 	VLAN_MEM_DBG("new_dev->priv malloc, addr: %p  size: %i\n",
 		     new_dev->priv,
 		     sizeof(struct vlan_dev_info));
-
-	memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len);
-	memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
-	new_dev->addr_len = real_dev->addr_len;
-
-	if (real_dev->features & NETIF_F_HW_VLAN_TX) {
-		new_dev->hard_header = real_dev->hard_header;
-		new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
-		new_dev->rebuild_header = real_dev->rebuild_header;
-	} else {
-		new_dev->hard_header = vlan_dev_hard_header;
-		new_dev->hard_start_xmit = vlan_dev_hard_start_xmit;
-		new_dev->rebuild_header = vlan_dev_rebuild_header;
-	}
-	new_dev->hard_header_parse = real_dev->hard_header_parse;
+#endif
 
 	VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */
 	VLAN_DEV_INFO(new_dev)->real_dev = real_dev;
 	VLAN_DEV_INFO(new_dev)->dent = NULL;
-	VLAN_DEV_INFO(new_dev)->flags = 1;
+	VLAN_DEV_INFO(new_dev)->flags = VLAN_FLAG_REORDER_HDR;
 
-#ifdef VLAN_DEBUG
-	printk(VLAN_DBG "About to go find the group for idx: %i\n",
-	       real_dev->ifindex);
-#endif
-
-	if (register_netdevice(new_dev))
+	new_dev->rtnl_link_ops = &vlan_link_ops;
+	err = register_vlan_dev(new_dev);
+	if (err < 0)
 		goto out_free_newdev;
 
-	lockdep_set_class(&new_dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
-
-	new_dev->iflink = real_dev->ifindex;
-	vlan_transfer_operstate(real_dev, new_dev);
-	linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */
-
-	/* So, got the sucker initialized, now lets place
-	 * it into our local structure.
-	 */
-	grp = __vlan_find_group(real_dev->ifindex);
-
-	/* Note, we are running under the RTNL semaphore
-	 * so it cannot "appear" on us.
-	 */
-	if (!grp) { /* need to add a new group */
-		grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
-		if (!grp)
-			goto out_free_unregister;
-
-		for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
-			grp->vlan_devices_arrays[i] = kzalloc(
-				sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN,
-				GFP_KERNEL);
-
-			if (!grp->vlan_devices_arrays[i])
-				goto out_free_arrays;
-		}
-
-		/* printk(KERN_ALERT "VLAN REGISTER:  Allocated new group.\n"); */
-		grp->real_dev_ifindex = real_dev->ifindex;
-
-		hlist_add_head_rcu(&grp->hlist,
-				   &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
-
-		if (real_dev->features & NETIF_F_HW_VLAN_RX)
-			real_dev->vlan_rx_register(real_dev, grp);
-	}
-
-	vlan_group_set_device(grp, VLAN_ID, new_dev);
-
-	if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */
-		printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
-							 new_dev->name);
-
-	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
-		real_dev->vlan_rx_add_vid(real_dev, VLAN_ID);
-
-	rtnl_unlock();
-
-
+	/* Account for reference in struct vlan_dev_info */
+	dev_hold(real_dev);
 #ifdef VLAN_DEBUG
 	printk(VLAN_DBG "Allocated new device successfully, returning.\n");
 #endif
-	return new_dev;
-
-out_free_arrays:
-	vlan_group_free(grp);
-
-out_free_unregister:
-	unregister_netdev(new_dev);
-	goto out_unlock;
+	return 0;
 
 out_free_newdev:
 	free_netdev(new_dev);
-
-out_unlock:
-	rtnl_unlock();
-
-out_put_dev:
-	dev_put(real_dev);
-
-out_ret_null:
-	return NULL;
+	return err;
 }
 
 static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
@@ -693,9 +680,10 @@
  */
 static int vlan_ioctl_handler(void __user *arg)
 {
-	int err = 0;
+	int err;
 	unsigned short vid = 0;
 	struct vlan_ioctl_args args;
+	struct net_device *dev = NULL;
 
 	if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
 		return -EFAULT;
@@ -708,35 +696,61 @@
 	printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd);
 #endif
 
+	rtnl_lock();
+
 	switch (args.cmd) {
 	case SET_VLAN_INGRESS_PRIORITY_CMD:
+	case SET_VLAN_EGRESS_PRIORITY_CMD:
+	case SET_VLAN_FLAG_CMD:
+	case ADD_VLAN_CMD:
+	case DEL_VLAN_CMD:
+	case GET_VLAN_REALDEV_NAME_CMD:
+	case GET_VLAN_VID_CMD:
+		err = -ENODEV;
+		dev = __dev_get_by_name(args.device1);
+		if (!dev)
+			goto out;
+
+		err = -EINVAL;
+		if (args.cmd != ADD_VLAN_CMD &&
+		    !(dev->priv_flags & IFF_802_1Q_VLAN))
+			goto out;
+	}
+
+	switch (args.cmd) {
+	case SET_VLAN_INGRESS_PRIORITY_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		err = vlan_dev_set_ingress_priority(args.device1,
-						    args.u.skb_priority,
-						    args.vlan_qos);
+			break;
+		vlan_dev_set_ingress_priority(dev,
+					      args.u.skb_priority,
+					      args.vlan_qos);
 		break;
 
 	case SET_VLAN_EGRESS_PRIORITY_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		err = vlan_dev_set_egress_priority(args.device1,
+			break;
+		err = vlan_dev_set_egress_priority(dev,
 						   args.u.skb_priority,
 						   args.vlan_qos);
 		break;
 
 	case SET_VLAN_FLAG_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		err = vlan_dev_set_vlan_flag(args.device1,
+			break;
+		err = vlan_dev_set_vlan_flag(dev,
 					     args.u.flag,
 					     args.vlan_qos);
 		break;
 
 	case SET_VLAN_NAME_TYPE_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) {
+		if ((args.u.name_type >= 0) &&
+		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
 			vlan_name_type = args.u.name_type;
 			err = 0;
 		} else {
@@ -745,26 +759,17 @@
 		break;
 
 	case ADD_VLAN_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		/* we have been given the name of the Ethernet Device we want to
-		 * talk to:  args.dev1	 We also have the
-		 * VLAN ID:  args.u.VID
-		 */
-		if (register_vlan_device(args.device1, args.u.VID)) {
-			err = 0;
-		} else {
-			err = -EINVAL;
-		}
+			break;
+		err = register_vlan_device(dev, args.u.VID);
 		break;
 
 	case DEL_VLAN_CMD:
+		err = -EPERM;
 		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		/* Here, the args.dev1 is the actual VLAN we want
-		 * to get rid of.
-		 */
-		err = unregister_vlan_device(args.device1);
+			break;
+		err = unregister_vlan_device(dev);
 		break;
 
 	case GET_VLAN_INGRESS_PRIORITY_CMD:
@@ -788,9 +793,7 @@
 		err = -EINVAL;
 		break;
 	case GET_VLAN_REALDEV_NAME_CMD:
-		err = vlan_dev_get_realdev_name(args.device1, args.u.device2);
-		if (err)
-			goto out;
+		vlan_dev_get_realdev_name(dev, args.u.device2);
 		if (copy_to_user(arg, &args,
 				 sizeof(struct vlan_ioctl_args))) {
 			err = -EFAULT;
@@ -798,9 +801,7 @@
 		break;
 
 	case GET_VLAN_VID_CMD:
-		err = vlan_dev_get_vid(args.device1, &vid);
-		if (err)
-			goto out;
+		vlan_dev_get_vid(dev, &vid);
 		args.u.VID = vid;
 		if (copy_to_user(arg, &args,
 				 sizeof(struct vlan_ioctl_args))) {
@@ -812,9 +813,11 @@
 		/* pass on to underlying device instead?? */
 		printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",
 			__FUNCTION__, args.cmd);
-		return -EINVAL;
+		err = -EINVAL;
+		break;
 	}
 out:
+	rtnl_unlock();
 	return err;
 }
 
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 1976cdb..fe6bb0f 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -62,11 +62,24 @@
 int vlan_dev_open(struct net_device* dev);
 int vlan_dev_stop(struct net_device* dev);
 int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd);
-int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
-int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
-int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
-int vlan_dev_get_realdev_name(const char* dev_name, char* result);
-int vlan_dev_get_vid(const char* dev_name, unsigned short* result);
+void vlan_dev_set_ingress_priority(const struct net_device *dev,
+				   u32 skb_prio, short vlan_prio);
+int vlan_dev_set_egress_priority(const struct net_device *dev,
+				 u32 skb_prio, short vlan_prio);
+int vlan_dev_set_vlan_flag(const struct net_device *dev,
+			   u32 flag, short flag_val);
+void vlan_dev_get_realdev_name(const struct net_device *dev, char *result);
+void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result);
 void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
 
+int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id);
+void vlan_setup(struct net_device *dev);
+int register_vlan_dev(struct net_device *dev);
+int unregister_vlan_device(struct net_device *dev);
+
+int vlan_netlink_init(void);
+void vlan_netlink_fini(void);
+
+extern struct rtnl_link_ops vlan_link_ops;
+
 #endif /* !(__BEN_VLAN_802_1Q_INC__) */
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index ec46084..95afe38 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -73,7 +73,7 @@
 
 static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb)
 {
-	if (VLAN_DEV_INFO(skb->dev)->flags & 1) {
+	if (VLAN_DEV_INFO(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) {
 		if (skb_shared(skb) || skb_cloned(skb)) {
 			struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
 			kfree_skb(skb);
@@ -350,7 +350,8 @@
 	 * header shuffling in the hard_start_xmit.  Users can turn off this
 	 * REORDER behaviour with the vconfig tool.
 	 */
-	build_vlan_header = ((VLAN_DEV_INFO(dev)->flags & 1) == 0);
+	if (!(VLAN_DEV_INFO(dev)->flags & VLAN_FLAG_REORDER_HDR))
+		build_vlan_header = 1;
 
 	if (build_vlan_header) {
 		vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN);
@@ -534,136 +535,83 @@
 	return 0;
 }
 
-int vlan_dev_set_ingress_priority(char *dev_name, __u32 skb_prio, short vlan_prio)
+void vlan_dev_set_ingress_priority(const struct net_device *dev,
+				   u32 skb_prio, short vlan_prio)
 {
-	struct net_device *dev = dev_get_by_name(dev_name);
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
 
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			/* see if a priority mapping exists.. */
-			VLAN_DEV_INFO(dev)->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
-			dev_put(dev);
-			return 0;
-		}
+	if (vlan->ingress_priority_map[vlan_prio & 0x7] && !skb_prio)
+		vlan->nr_ingress_mappings--;
+	else if (!vlan->ingress_priority_map[vlan_prio & 0x7] && skb_prio)
+		vlan->nr_ingress_mappings++;
 
-		dev_put(dev);
-	}
-	return -EINVAL;
+	vlan->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
 }
 
-int vlan_dev_set_egress_priority(char *dev_name, __u32 skb_prio, short vlan_prio)
+int vlan_dev_set_egress_priority(const struct net_device *dev,
+				 u32 skb_prio, short vlan_prio)
 {
-	struct net_device *dev = dev_get_by_name(dev_name);
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
 	struct vlan_priority_tci_mapping *mp = NULL;
 	struct vlan_priority_tci_mapping *np;
+	u32 vlan_qos = (vlan_prio << 13) & 0xE000;
 
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			/* See if a priority mapping exists.. */
-			mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF];
-			while (mp) {
-				if (mp->priority == skb_prio) {
-					mp->vlan_qos = ((vlan_prio << 13) & 0xE000);
-					dev_put(dev);
-					return 0;
-				}
-				mp = mp->next;
-			}
-
-			/* Create a new mapping then. */
-			mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF];
-			np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL);
-			if (np) {
-				np->next = mp;
-				np->priority = skb_prio;
-				np->vlan_qos = ((vlan_prio << 13) & 0xE000);
-				VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF] = np;
-				dev_put(dev);
-				return 0;
-			} else {
-				dev_put(dev);
-				return -ENOBUFS;
-			}
+	/* See if a priority mapping exists.. */
+	mp = vlan->egress_priority_map[skb_prio & 0xF];
+	while (mp) {
+		if (mp->priority == skb_prio) {
+			if (mp->vlan_qos && !vlan_qos)
+				vlan->nr_egress_mappings--;
+			else if (!mp->vlan_qos && vlan_qos)
+				vlan->nr_egress_mappings++;
+			mp->vlan_qos = vlan_qos;
+			return 0;
 		}
-		dev_put(dev);
+		mp = mp->next;
 	}
+
+	/* Create a new mapping then. */
+	mp = vlan->egress_priority_map[skb_prio & 0xF];
+	np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL);
+	if (!np)
+		return -ENOBUFS;
+
+	np->next = mp;
+	np->priority = skb_prio;
+	np->vlan_qos = vlan_qos;
+	vlan->egress_priority_map[skb_prio & 0xF] = np;
+	if (vlan_qos)
+		vlan->nr_egress_mappings++;
+	return 0;
+}
+
+/* Flags are defined in the vlan_flags enum in include/linux/if_vlan.h file. */
+int vlan_dev_set_vlan_flag(const struct net_device *dev,
+			   u32 flag, short flag_val)
+{
+	/* verify flag is supported */
+	if (flag == VLAN_FLAG_REORDER_HDR) {
+		if (flag_val) {
+			VLAN_DEV_INFO(dev)->flags |= VLAN_FLAG_REORDER_HDR;
+		} else {
+			VLAN_DEV_INFO(dev)->flags &= ~VLAN_FLAG_REORDER_HDR;
+		}
+		return 0;
+	}
+	printk(KERN_ERR "%s: flag %i is not valid.\n", __FUNCTION__, flag);
 	return -EINVAL;
 }
 
-/* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */
-int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val)
+void vlan_dev_get_realdev_name(const struct net_device *dev, char *result)
 {
-	struct net_device *dev = dev_get_by_name(dev_name);
-
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			/* verify flag is supported */
-			if (flag == 1) {
-				if (flag_val) {
-					VLAN_DEV_INFO(dev)->flags |= 1;
-				} else {
-					VLAN_DEV_INFO(dev)->flags &= ~1;
-				}
-				dev_put(dev);
-				return 0;
-			} else {
-				printk(KERN_ERR  "%s: flag %i is not valid.\n",
-					__FUNCTION__, (int)(flag));
-				dev_put(dev);
-				return -EINVAL;
-			}
-		} else {
-			printk(KERN_ERR
-			       "%s: %s is not a vlan device, priv_flags: %hX.\n",
-			       __FUNCTION__, dev->name, dev->priv_flags);
-			dev_put(dev);
-		}
-	} else {
-		printk(KERN_ERR  "%s: Could not find device: %s\n",
-			__FUNCTION__, dev_name);
-	}
-
-	return -EINVAL;
+	strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
 }
 
-
-int vlan_dev_get_realdev_name(const char *dev_name, char* result)
+void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result)
 {
-	struct net_device *dev = dev_get_by_name(dev_name);
-	int rv = 0;
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
-			rv = 0;
-		} else {
-			rv = -EINVAL;
-		}
-		dev_put(dev);
-	} else {
-		rv = -ENODEV;
-	}
-	return rv;
+	*result = VLAN_DEV_INFO(dev)->vlan_id;
 }
 
-int vlan_dev_get_vid(const char *dev_name, unsigned short* result)
-{
-	struct net_device *dev = dev_get_by_name(dev_name);
-	int rv = 0;
-	if (dev) {
-		if (dev->priv_flags & IFF_802_1Q_VLAN) {
-			*result = VLAN_DEV_INFO(dev)->vlan_id;
-			rv = 0;
-		} else {
-			rv = -EINVAL;
-		}
-		dev_put(dev);
-	} else {
-		rv = -ENODEV;
-	}
-	return rv;
-}
-
-
 int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
 {
 	struct sockaddr *addr = (struct sockaddr *)(addr_struct_p);
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
new file mode 100644
index 0000000..844c7e4
--- /dev/null
+++ b/net/8021q/vlan_netlink.c
@@ -0,0 +1,236 @@
+/*
+ *	VLAN netlink control interface
+ *
+ * 	Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <net/netlink.h>
+#include <net/rtnetlink.h>
+#include "vlan.h"
+
+
+static const struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = {
+	[IFLA_VLAN_ID]		= { .type = NLA_U16 },
+	[IFLA_VLAN_FLAGS]	= { .len = sizeof(struct ifla_vlan_flags) },
+	[IFLA_VLAN_EGRESS_QOS]	= { .type = NLA_NESTED },
+	[IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy vlan_map_policy[IFLA_VLAN_QOS_MAX + 1] = {
+	[IFLA_VLAN_QOS_MAPPING] = { .len = sizeof(struct ifla_vlan_qos_mapping) },
+};
+
+
+static inline int vlan_validate_qos_map(struct nlattr *attr)
+{
+	if (!attr)
+		return 0;
+	return nla_validate_nested(attr, IFLA_VLAN_QOS_MAX, vlan_map_policy);
+}
+
+static int vlan_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+	struct ifla_vlan_flags *flags;
+	u16 id;
+	int err;
+
+	if (!data)
+		return -EINVAL;
+
+	if (data[IFLA_VLAN_ID]) {
+		id = nla_get_u16(data[IFLA_VLAN_ID]);
+		if (id >= VLAN_VID_MASK)
+			return -ERANGE;
+	}
+	if (data[IFLA_VLAN_FLAGS]) {
+		flags = nla_data(data[IFLA_VLAN_FLAGS]);
+		if ((flags->flags & flags->mask) & ~VLAN_FLAG_REORDER_HDR)
+			return -EINVAL;
+	}
+
+	err = vlan_validate_qos_map(data[IFLA_VLAN_INGRESS_QOS]);
+	if (err < 0)
+		return err;
+	err = vlan_validate_qos_map(data[IFLA_VLAN_EGRESS_QOS]);
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+static int vlan_changelink(struct net_device *dev,
+			   struct nlattr *tb[], struct nlattr *data[])
+{
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+	struct ifla_vlan_flags *flags;
+	struct ifla_vlan_qos_mapping *m;
+	struct nlattr *attr;
+	int rem;
+
+	if (data[IFLA_VLAN_FLAGS]) {
+		flags = nla_data(data[IFLA_VLAN_FLAGS]);
+		vlan->flags = (vlan->flags & ~flags->mask) |
+			      (flags->flags & flags->mask);
+	}
+	if (data[IFLA_VLAN_INGRESS_QOS]) {
+		nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
+			m = nla_data(attr);
+			vlan_dev_set_ingress_priority(dev, m->to, m->from);
+		}
+	}
+	if (data[IFLA_VLAN_EGRESS_QOS]) {
+		nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
+			m = nla_data(attr);
+			vlan_dev_set_egress_priority(dev, m->from, m->to);
+		}
+	}
+	return 0;
+}
+
+static int vlan_newlink(struct net_device *dev,
+			struct nlattr *tb[], struct nlattr *data[])
+{
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+	struct net_device *real_dev;
+	int err;
+
+	if (!data[IFLA_VLAN_ID])
+		return -EINVAL;
+
+	if (!tb[IFLA_LINK])
+		return -EINVAL;
+	real_dev = __dev_get_by_index(nla_get_u32(tb[IFLA_LINK]));
+	if (!real_dev)
+		return -ENODEV;
+
+	vlan->vlan_id  = nla_get_u16(data[IFLA_VLAN_ID]);
+	vlan->real_dev = real_dev;
+	vlan->flags    = VLAN_FLAG_REORDER_HDR;
+
+	err = vlan_check_real_dev(real_dev, vlan->vlan_id);
+	if (err < 0)
+		return err;
+
+	if (!tb[IFLA_MTU])
+		dev->mtu = real_dev->mtu;
+	else if (dev->mtu > real_dev->mtu)
+		return -EINVAL;
+
+	err = vlan_changelink(dev, tb, data);
+	if (err < 0)
+		return err;
+
+	return register_vlan_dev(dev);
+}
+
+static void vlan_dellink(struct net_device *dev)
+{
+	unregister_vlan_device(dev);
+}
+
+static inline size_t vlan_qos_map_size(unsigned int n)
+{
+	if (n == 0)
+		return 0;
+	/* IFLA_VLAN_{EGRESS,INGRESS}_QOS + n * IFLA_VLAN_QOS_MAPPING */
+	return nla_total_size(sizeof(struct nlattr)) +
+	       nla_total_size(sizeof(struct ifla_vlan_qos_mapping)) * n;
+}
+
+static size_t vlan_get_size(const struct net_device *dev)
+{
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+
+	return nla_total_size(2) +	/* IFLA_VLAN_ID */
+	       vlan_qos_map_size(vlan->nr_ingress_mappings) +
+	       vlan_qos_map_size(vlan->nr_egress_mappings);
+}
+
+static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+	struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+	struct vlan_priority_tci_mapping *pm;
+	struct ifla_vlan_flags f;
+	struct ifla_vlan_qos_mapping m;
+	struct nlattr *nest;
+	unsigned int i;
+
+	NLA_PUT_U16(skb, IFLA_VLAN_ID, VLAN_DEV_INFO(dev)->vlan_id);
+	if (vlan->flags) {
+		f.flags = vlan->flags;
+		f.mask  = ~0;
+		NLA_PUT(skb, IFLA_VLAN_FLAGS, sizeof(f), &f);
+	}
+	if (vlan->nr_ingress_mappings) {
+		nest = nla_nest_start(skb, IFLA_VLAN_INGRESS_QOS);
+		if (nest == NULL)
+			goto nla_put_failure;
+
+		for (i = 0; i < ARRAY_SIZE(vlan->ingress_priority_map); i++) {
+			if (!vlan->ingress_priority_map[i])
+				continue;
+
+			m.from = i;
+			m.to   = vlan->ingress_priority_map[i];
+			NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING,
+				sizeof(m), &m);
+		}
+		nla_nest_end(skb, nest);
+	}
+
+	if (vlan->nr_egress_mappings) {
+		nest = nla_nest_start(skb, IFLA_VLAN_EGRESS_QOS);
+		if (nest == NULL)
+			goto nla_put_failure;
+
+		for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
+			for (pm = vlan->egress_priority_map[i]; pm;
+			     pm = pm->next) {
+				if (!pm->vlan_qos)
+					continue;
+
+				m.from = pm->priority;
+				m.to   = (pm->vlan_qos >> 13) & 0x7;
+				NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING,
+					sizeof(m), &m);
+			}
+		}
+		nla_nest_end(skb, nest);
+	}
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+struct rtnl_link_ops vlan_link_ops __read_mostly = {
+	.kind		= "vlan",
+	.maxtype	= IFLA_VLAN_MAX,
+	.policy		= vlan_policy,
+	.priv_size	= sizeof(struct vlan_dev_info),
+	.setup		= vlan_setup,
+	.validate	= vlan_validate,
+	.newlink	= vlan_newlink,
+	.changelink	= vlan_changelink,
+	.dellink	= vlan_dellink,
+	.get_size	= vlan_get_size,
+	.fill_info	= vlan_fill_info,
+};
+
+int __init vlan_netlink_init(void)
+{
+	return rtnl_link_register(&vlan_link_ops);
+}
+
+void __exit vlan_netlink_fini(void)
+{
+	rtnl_link_unregister(&vlan_link_ops);
+}
+
+MODULE_ALIAS_RTNL_LINK("vlan");
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index d216a64..c0040c9 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -69,7 +69,7 @@
  *	Generic /proc/net/vlan/<file> file and inode operations
  */
 
-static struct seq_operations vlan_seq_ops = {
+static const struct seq_operations vlan_seq_ops = {
 	.start = vlan_seq_start,
 	.next = vlan_seq_next,
 	.stop = vlan_seq_stop,
@@ -342,7 +342,7 @@
 	seq_printf(seq, "Device: %s", dev_info->real_dev->name);
 	/* now show all PRIORITY mappings relating to this VLAN */
 	seq_printf(seq,
-		       "\nINGRESS priority mappings: 0:%lu  1:%lu  2:%lu  3:%lu  4:%lu  5:%lu  6:%lu 7:%lu\n",
+		       "\nINGRESS priority mappings: 0:%u  1:%u  2:%u  3:%u  4:%u  5:%u  6:%u 7:%u\n",
 		       dev_info->ingress_priority_map[0],
 		       dev_info->ingress_priority_map[1],
 		       dev_info->ingress_priority_map[2],
@@ -357,7 +357,7 @@
 		const struct vlan_priority_tci_mapping *mp
 			= dev_info->egress_priority_map[i];
 		while (mp) {
-			seq_printf(seq, "%lu:%hu ",
+			seq_printf(seq, "%u:%hu ",
 				   mp->priority, ((mp->vlan_qos >> 13) & 0x7));
 			mp = mp->next;
 		}
diff --git a/net/Makefile b/net/Makefile
index 34e5b2d..a87a889 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -37,7 +37,6 @@
 obj-$(CONFIG_IRDA)		+= irda/
 obj-$(CONFIG_BT)		+= bluetooth/
 obj-$(CONFIG_SUNRPC)		+= sunrpc/
-obj-$(CONFIG_RXRPC)		+= rxrpc/
 obj-$(CONFIG_AF_RXRPC)		+= rxrpc/
 obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_DECNET)		+= decnet/
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 5ef6a23..3d1655f 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -1024,7 +1024,7 @@
 	return 0;
 }
 
-static struct seq_operations aarp_seq_ops = {
+static const struct seq_operations aarp_seq_ops = {
 	.start  = aarp_seq_start,
 	.next   = aarp_seq_next,
 	.stop   = aarp_seq_stop,
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c
index 57ff812..87a582c 100644
--- a/net/appletalk/atalk_proc.c
+++ b/net/appletalk/atalk_proc.c
@@ -204,21 +204,21 @@
 	return 0;
 }
 
-static struct seq_operations atalk_seq_interface_ops = {
+static const struct seq_operations atalk_seq_interface_ops = {
 	.start  = atalk_seq_interface_start,
 	.next   = atalk_seq_interface_next,
 	.stop   = atalk_seq_interface_stop,
 	.show   = atalk_seq_interface_show,
 };
 
-static struct seq_operations atalk_seq_route_ops = {
+static const struct seq_operations atalk_seq_route_ops = {
 	.start  = atalk_seq_route_start,
 	.next   = atalk_seq_route_next,
 	.stop   = atalk_seq_route_stop,
 	.show   = atalk_seq_route_show,
 };
 
-static struct seq_operations atalk_seq_socket_ops = {
+static const struct seq_operations atalk_seq_socket_ops = {
 	.start  = atalk_seq_socket_start,
 	.next   = atalk_seq_socket_next,
 	.stop   = atalk_seq_socket_stop,
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 0e9f00c..faa6aaf 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -699,28 +699,13 @@
 #ifdef CONFIG_PROC_FS
 static void *br2684_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	loff_t offs = 0;
-	struct br2684_dev *brd;
-
 	read_lock(&devs_lock);
-
-	list_for_each_entry(brd, &br2684_devs, br2684_devs) {
-		if (offs == *pos)
-			return brd;
-		++offs;
-	}
-	return NULL;
+	return seq_list_start(&br2684_devs, *pos);
 }
 
 static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct br2684_dev *brd = v;
-
-	++*pos;
-
-	brd = list_entry(brd->br2684_devs.next,
-			 struct br2684_dev, br2684_devs);
-	return (&brd->br2684_devs != &br2684_devs) ? brd : NULL;
+	return seq_list_next(v, &br2684_devs, pos);
 }
 
 static void br2684_seq_stop(struct seq_file *seq, void *v)
@@ -730,7 +715,8 @@
 
 static int br2684_seq_show(struct seq_file *seq, void *v)
 {
-	const struct br2684_dev *brdev = v;
+	const struct br2684_dev *brdev = list_entry(v, struct br2684_dev,
+			br2684_devs);
 	const struct net_device *net_dev = brdev->net_dev;
 	const struct br2684_vcc *brvcc;
 
@@ -772,7 +758,7 @@
 	return 0;
 }
 
-static struct seq_operations br2684_seq_ops = {
+static const struct seq_operations br2684_seq_ops = {
 	.start = br2684_seq_start,
 	.next  = br2684_seq_next,
 	.stop  = br2684_seq_stop,
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 876b77f..ecf0f79 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -928,7 +928,7 @@
 	return 0;
 }
 
-static struct seq_operations arp_seq_ops = {
+static const struct seq_operations arp_seq_ops = {
 	.start	= clip_seq_start,
 	.next	= neigh_seq_next,
 	.stop	= neigh_seq_stop,
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 4dc5f2b..2770fb4 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -1174,7 +1174,7 @@
 	return 0;
 }
 
-static struct seq_operations lec_seq_ops = {
+static const struct seq_operations lec_seq_ops = {
 	.start = lec_seq_start,
 	.next = lec_seq_next,
 	.stop = lec_seq_stop,
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
index 4b05cbe..91f3ffc 100644
--- a/net/atm/mpoa_proc.c
+++ b/net/atm/mpoa_proc.c
@@ -177,7 +177,7 @@
 	return 0;
 }
 
-static struct seq_operations mpc_op = {
+static const struct seq_operations mpc_op = {
 	.start =	mpc_start,
 	.next =		mpc_next,
 	.stop =		mpc_stop,
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 9e61e51..88154da 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -260,7 +260,7 @@
 	return 0;
 }
 
-static struct seq_operations atm_dev_seq_ops = {
+static const struct seq_operations atm_dev_seq_ops = {
 	.start	= atm_dev_seq_start,
 	.next	= atm_dev_seq_next,
 	.stop	= atm_dev_seq_stop,
@@ -295,7 +295,7 @@
 	return 0;
 }
 
-static struct seq_operations pvc_seq_ops = {
+static const struct seq_operations pvc_seq_ops = {
 	.start	= vcc_seq_start,
 	.next	= vcc_seq_next,
 	.stop	= vcc_seq_stop,
@@ -329,7 +329,7 @@
 	return 0;
 }
 
-static struct seq_operations vcc_seq_ops = {
+static const struct seq_operations vcc_seq_ops = {
 	.start	= vcc_seq_start,
 	.next	= vcc_seq_next,
 	.stop	= vcc_seq_stop,
@@ -364,7 +364,7 @@
 	return 0;
 }
 
-static struct seq_operations svc_seq_ops = {
+static const struct seq_operations svc_seq_ops = {
 	.start	= vcc_seq_start,
 	.next	= vcc_seq_next,
 	.stop	= vcc_seq_stop,
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 429e13a..c83cf843 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1924,7 +1924,7 @@
 	return 0;
 }
 
-static struct seq_operations ax25_info_seqops = {
+static const struct seq_operations ax25_info_seqops = {
 	.start = ax25_info_start,
 	.next = ax25_info_next,
 	.stop = ax25_info_stop,
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index d65b8e2..9ecf6f1 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -320,7 +320,7 @@
 	return 0;
 }
 
-static struct seq_operations ax25_rt_seqops = {
+static const struct seq_operations ax25_rt_seqops = {
 	.start = ax25_rt_seq_start,
 	.next = ax25_rt_seq_next,
 	.stop = ax25_rt_seq_stop,
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index 75c7664..ce0b13d 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -185,7 +185,7 @@
 	return 0;
 }
 
-static struct seq_operations ax25_uid_seqops = {
+static const struct seq_operations ax25_uid_seqops = {
 	.start = ax25_uid_seq_start,
 	.next = ax25_uid_seq_next,
 	.stop = ax25_uid_seq_stop,
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 849deaf..7b4ce91 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -368,10 +368,18 @@
 	list_for_each_entry(p, &br->port_list, list) {
 		unsigned long feature = p->dev->features;
 
+		/* if device needs checksumming, downgrade to hw checksumming */
 		if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM))
 			checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
+
+		/* if device can't do all checksum, downgrade to ipv4/ipv6 */
 		if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM))
-			checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
+			checksum ^= NETIF_F_HW_CSUM
+				| NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+
+		if (checksum & NETIF_F_IPV6_CSUM && !(feature & NETIF_F_IPV6_CSUM))
+			checksum &= ~NETIF_F_IPV6_CSUM;
+
 		if (!(feature & NETIF_F_IP_CSUM))
 			checksum = 0;
 
diff --git a/net/core/dev.c b/net/core/dev.c
index ee051bb..4221dcd 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -942,7 +942,7 @@
 		/*
 		 *	Initialize multicasting status
 		 */
-		dev_mc_upload(dev);
+		dev_set_rx_mode(dev);
 
 		/*
 		 *	Wakeup transmit queue engine
@@ -1429,7 +1429,9 @@
 			skb->next = nskb;
 			return rc;
 		}
-		if (unlikely(netif_queue_stopped(dev) && skb->next))
+		if (unlikely((netif_queue_stopped(dev) ||
+			     netif_subqueue_stopped(dev, skb->queue_mapping)) &&
+			     skb->next))
 			return NETDEV_TX_BUSY;
 	} while (skb->next);
 
@@ -1510,8 +1512,10 @@
 					      skb_headroom(skb));
 
 		if (!(dev->features & NETIF_F_GEN_CSUM) &&
-		    (!(dev->features & NETIF_F_IP_CSUM) ||
-		     skb->protocol != htons(ETH_P_IP)))
+		    !((dev->features & NETIF_F_IP_CSUM) &&
+		      skb->protocol == htons(ETH_P_IP)) &&
+		    !((dev->features & NETIF_F_IPV6_CSUM) &&
+		      skb->protocol == htons(ETH_P_IPV6)))
 			if (skb_checksum_help(skb))
 				goto out_kfree_skb;
 	}
@@ -1545,6 +1549,8 @@
 		spin_lock(&dev->queue_lock);
 		q = dev->qdisc;
 		if (q->enqueue) {
+			/* reset queue_mapping to zero */
+			skb->queue_mapping = 0;
 			rc = q->enqueue(skb, q);
 			qdisc_run(dev);
 			spin_unlock(&dev->queue_lock);
@@ -1574,7 +1580,8 @@
 
 			HARD_TX_LOCK(dev, cpu);
 
-			if (!netif_queue_stopped(dev)) {
+			if (!netif_queue_stopped(dev) &&
+			    !netif_subqueue_stopped(dev, skb->queue_mapping)) {
 				rc = 0;
 				if (!dev_hard_start_xmit(skb, dev)) {
 					HARD_TX_UNLOCK(dev);
@@ -2496,6 +2503,27 @@
 	return 0;
 }
 
+static void __dev_set_promiscuity(struct net_device *dev, int inc)
+{
+	unsigned short old_flags = dev->flags;
+
+	if ((dev->promiscuity += inc) == 0)
+		dev->flags &= ~IFF_PROMISC;
+	else
+		dev->flags |= IFF_PROMISC;
+	if (dev->flags != old_flags) {
+		printk(KERN_INFO "device %s %s promiscuous mode\n",
+		       dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
+							       "left");
+		audit_log(current->audit_context, GFP_ATOMIC,
+			AUDIT_ANOM_PROMISCUOUS,
+			"dev=%s prom=%d old_prom=%d auid=%u",
+			dev->name, (dev->flags & IFF_PROMISC),
+			(old_flags & IFF_PROMISC),
+			audit_get_loginuid(current->audit_context));
+	}
+}
+
 /**
  *	dev_set_promiscuity	- update promiscuity count on a device
  *	@dev: device
@@ -2510,22 +2538,9 @@
 {
 	unsigned short old_flags = dev->flags;
 
-	if ((dev->promiscuity += inc) == 0)
-		dev->flags &= ~IFF_PROMISC;
-	else
-		dev->flags |= IFF_PROMISC;
-	if (dev->flags != old_flags) {
-		dev_mc_upload(dev);
-		printk(KERN_INFO "device %s %s promiscuous mode\n",
-		       dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
-							       "left");
-		audit_log(current->audit_context, GFP_ATOMIC,
-			AUDIT_ANOM_PROMISCUOUS,
-			"dev=%s prom=%d old_prom=%d auid=%u",
-			dev->name, (dev->flags & IFF_PROMISC),
-			(old_flags & IFF_PROMISC),
-			audit_get_loginuid(current->audit_context));
-	}
+	__dev_set_promiscuity(dev, inc);
+	if (dev->flags != old_flags)
+		dev_set_rx_mode(dev);
 }
 
 /**
@@ -2548,7 +2563,176 @@
 	if ((dev->allmulti += inc) == 0)
 		dev->flags &= ~IFF_ALLMULTI;
 	if (dev->flags ^ old_flags)
-		dev_mc_upload(dev);
+		dev_set_rx_mode(dev);
+}
+
+/*
+ *	Upload unicast and multicast address lists to device and
+ *	configure RX filtering. When the device doesn't support unicast
+ *	filtering it is put in promiscous mode while unicast addresses
+ *	are present.
+ */
+void __dev_set_rx_mode(struct net_device *dev)
+{
+	/* dev_open will call this function so the list will stay sane. */
+	if (!(dev->flags&IFF_UP))
+		return;
+
+	if (!netif_device_present(dev))
+	        return;
+
+	if (dev->set_rx_mode)
+		dev->set_rx_mode(dev);
+	else {
+		/* Unicast addresses changes may only happen under the rtnl,
+		 * therefore calling __dev_set_promiscuity here is safe.
+		 */
+		if (dev->uc_count > 0 && !dev->uc_promisc) {
+			__dev_set_promiscuity(dev, 1);
+			dev->uc_promisc = 1;
+		} else if (dev->uc_count == 0 && dev->uc_promisc) {
+			__dev_set_promiscuity(dev, -1);
+			dev->uc_promisc = 0;
+		}
+
+		if (dev->set_multicast_list)
+			dev->set_multicast_list(dev);
+	}
+}
+
+void dev_set_rx_mode(struct net_device *dev)
+{
+	netif_tx_lock_bh(dev);
+	__dev_set_rx_mode(dev);
+	netif_tx_unlock_bh(dev);
+}
+
+int __dev_addr_delete(struct dev_addr_list **list, int *count,
+		      void *addr, int alen, int glbl)
+{
+	struct dev_addr_list *da;
+
+	for (; (da = *list) != NULL; list = &da->next) {
+		if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
+		    alen == da->da_addrlen) {
+			if (glbl) {
+				int old_glbl = da->da_gusers;
+				da->da_gusers = 0;
+				if (old_glbl == 0)
+					break;
+			}
+			if (--da->da_users)
+				return 0;
+
+			*list = da->next;
+			kfree(da);
+			(*count)--;
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+int __dev_addr_add(struct dev_addr_list **list, int *count,
+		   void *addr, int alen, int glbl)
+{
+	struct dev_addr_list *da;
+
+	for (da = *list; da != NULL; da = da->next) {
+		if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
+		    da->da_addrlen == alen) {
+			if (glbl) {
+				int old_glbl = da->da_gusers;
+				da->da_gusers = 1;
+				if (old_glbl)
+					return 0;
+			}
+			da->da_users++;
+			return 0;
+		}
+	}
+
+	da = kmalloc(sizeof(*da), GFP_ATOMIC);
+	if (da == NULL)
+		return -ENOMEM;
+	memcpy(da->da_addr, addr, alen);
+	da->da_addrlen = alen;
+	da->da_users = 1;
+	da->da_gusers = glbl ? 1 : 0;
+	da->next = *list;
+	*list = da;
+	(*count)++;
+	return 0;
+}
+
+void __dev_addr_discard(struct dev_addr_list **list)
+{
+	struct dev_addr_list *tmp;
+
+	while (*list != NULL) {
+		tmp = *list;
+		*list = tmp->next;
+		if (tmp->da_users > tmp->da_gusers)
+			printk("__dev_addr_discard: address leakage! "
+			       "da_users=%d\n", tmp->da_users);
+		kfree(tmp);
+	}
+}
+
+/**
+ *	dev_unicast_delete	- Release secondary unicast address.
+ *	@dev: device
+ *
+ *	Release reference to a secondary unicast address and remove it
+ *	from the device if the reference count drop to zero.
+ *
+ * 	The caller must hold the rtnl_mutex.
+ */
+int dev_unicast_delete(struct net_device *dev, void *addr, int alen)
+{
+	int err;
+
+	ASSERT_RTNL();
+
+	netif_tx_lock_bh(dev);
+	err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0);
+	if (!err)
+		__dev_set_rx_mode(dev);
+	netif_tx_unlock_bh(dev);
+	return err;
+}
+EXPORT_SYMBOL(dev_unicast_delete);
+
+/**
+ *	dev_unicast_add		- add a secondary unicast address
+ *	@dev: device
+ *
+ *	Add a secondary unicast address to the device or increase
+ *	the reference count if it already exists.
+ *
+ *	The caller must hold the rtnl_mutex.
+ */
+int dev_unicast_add(struct net_device *dev, void *addr, int alen)
+{
+	int err;
+
+	ASSERT_RTNL();
+
+	netif_tx_lock_bh(dev);
+	err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0);
+	if (!err)
+		__dev_set_rx_mode(dev);
+	netif_tx_unlock_bh(dev);
+	return err;
+}
+EXPORT_SYMBOL(dev_unicast_add);
+
+static void dev_unicast_discard(struct net_device *dev)
+{
+	netif_tx_lock_bh(dev);
+	__dev_addr_discard(&dev->uc_list);
+	dev->uc_count = 0;
+	netif_tx_unlock_bh(dev);
 }
 
 unsigned dev_get_flags(const struct net_device *dev)
@@ -2594,7 +2778,7 @@
 	 *	Load in the correct multicast list now the flags have changed.
 	 */
 
-	dev_mc_upload(dev);
+	dev_set_rx_mode(dev);
 
 	/*
 	 *	Have we downed the interface. We handle IFF_UP ourselves
@@ -2607,7 +2791,7 @@
 		ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
 
 		if (!ret)
-			dev_mc_upload(dev);
+			dev_set_rx_mode(dev);
 	}
 
 	if (dev->flags & IFF_UP &&
@@ -3107,6 +3291,22 @@
 		}
 	}
 
+	/* Fix illegal checksum combinations */
+	if ((dev->features & NETIF_F_HW_CSUM) &&
+	    (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+		printk(KERN_NOTICE "%s: mixed HW and IP checksum settings.\n",
+		       dev->name);
+		dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
+	}
+
+	if ((dev->features & NETIF_F_NO_CSUM) &&
+	    (dev->features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+		printk(KERN_NOTICE "%s: mixed no checksumming and other settings.\n",
+		       dev->name);
+		dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
+	}
+
+
 	/* Fix illegal SG+CSUM combinations. */
 	if ((dev->features & NETIF_F_SG) &&
 	    !(dev->features & NETIF_F_ALL_CSUM)) {
@@ -3343,16 +3543,18 @@
 }
 
 /**
- *	alloc_netdev - allocate network device
+ *	alloc_netdev_mq - allocate network device
  *	@sizeof_priv:	size of private data to allocate space for
  *	@name:		device name format string
  *	@setup:		callback to initialize device
+ *	@queue_count:	the number of subqueues to allocate
  *
  *	Allocates a struct net_device with private data area for driver use
- *	and performs basic initialization.
+ *	and performs basic initialization.  Also allocates subquue structs
+ *	for each queue on the device at the end of the netdevice.
  */
-struct net_device *alloc_netdev(int sizeof_priv, const char *name,
-		void (*setup)(struct net_device *))
+struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+		void (*setup)(struct net_device *), unsigned int queue_count)
 {
 	void *p;
 	struct net_device *dev;
@@ -3361,7 +3563,9 @@
 	BUG_ON(strlen(name) >= sizeof(dev->name));
 
 	/* ensure 32-byte alignment of both the device and private area */
-	alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
+	alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST +
+		     (sizeof(struct net_device_subqueue) * queue_count)) &
+		     ~NETDEV_ALIGN_CONST;
 	alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
 
 	p = kzalloc(alloc_size, GFP_KERNEL);
@@ -3374,15 +3578,22 @@
 		(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
 	dev->padded = (char *)dev - (char *)p;
 
-	if (sizeof_priv)
-		dev->priv = netdev_priv(dev);
+	if (sizeof_priv) {
+		dev->priv = ((char *)dev +
+			     ((sizeof(struct net_device) +
+			       (sizeof(struct net_device_subqueue) *
+				queue_count) + NETDEV_ALIGN_CONST)
+			      & ~NETDEV_ALIGN_CONST));
+	}
+
+	dev->egress_subqueue_count = queue_count;
 
 	dev->get_stats = internal_stats;
 	setup(dev);
 	strcpy(dev->name, name);
 	return dev;
 }
-EXPORT_SYMBOL(alloc_netdev);
+EXPORT_SYMBOL(alloc_netdev_mq);
 
 /**
  *	free_netdev - free network device
@@ -3471,8 +3682,9 @@
 	raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
 
 	/*
-	 *	Flush the multicast chain
+	 *	Flush the unicast and multicast chains
 	 */
+	dev_unicast_discard(dev);
 	dev_mc_discard(dev);
 
 	if (dev->uninit)
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 5a54053..aa38100 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -64,85 +64,24 @@
  */
 
 /*
- *	Update the multicast list into the physical NIC controller.
- */
-
-static void __dev_mc_upload(struct net_device *dev)
-{
-	/* Don't do anything till we up the interface
-	 * [dev_open will call this function so the list will
-	 * stay sane]
-	 */
-
-	if (!(dev->flags&IFF_UP))
-		return;
-
-	/*
-	 *	Devices with no set multicast or which have been
-	 *	detached don't get set.
-	 */
-
-	if (dev->set_multicast_list == NULL ||
-	    !netif_device_present(dev))
-		return;
-
-	dev->set_multicast_list(dev);
-}
-
-void dev_mc_upload(struct net_device *dev)
-{
-	netif_tx_lock_bh(dev);
-	__dev_mc_upload(dev);
-	netif_tx_unlock_bh(dev);
-}
-
-/*
  *	Delete a device level multicast
  */
 
 int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
 {
-	int err = 0;
-	struct dev_mc_list *dmi, **dmip;
+	int err;
 
 	netif_tx_lock_bh(dev);
-
-	for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) {
+	err = __dev_addr_delete(&dev->mc_list, &dev->mc_count,
+				addr, alen, glbl);
+	if (!err) {
 		/*
-		 *	Find the entry we want to delete. The device could
-		 *	have variable length entries so check these too.
+		 *	We have altered the list, so the card
+		 *	loaded filter is now wrong. Fix it
 		 */
-		if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
-		    alen == dmi->dmi_addrlen) {
-			if (glbl) {
-				int old_glbl = dmi->dmi_gusers;
-				dmi->dmi_gusers = 0;
-				if (old_glbl == 0)
-					break;
-			}
-			if (--dmi->dmi_users)
-				goto done;
 
-			/*
-			 *	Last user. So delete the entry.
-			 */
-			*dmip = dmi->next;
-			dev->mc_count--;
-
-			kfree(dmi);
-
-			/*
-			 *	We have altered the list, so the card
-			 *	loaded filter is now wrong. Fix it
-			 */
-			__dev_mc_upload(dev);
-
-			netif_tx_unlock_bh(dev);
-			return 0;
-		}
+		__dev_set_rx_mode(dev);
 	}
-	err = -ENOENT;
-done:
 	netif_tx_unlock_bh(dev);
 	return err;
 }
@@ -153,46 +92,13 @@
 
 int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
 {
-	int err = 0;
-	struct dev_mc_list *dmi, *dmi1;
-
-	dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
+	int err;
 
 	netif_tx_lock_bh(dev);
-	for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
-		if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
-		    dmi->dmi_addrlen == alen) {
-			if (glbl) {
-				int old_glbl = dmi->dmi_gusers;
-				dmi->dmi_gusers = 1;
-				if (old_glbl)
-					goto done;
-			}
-			dmi->dmi_users++;
-			goto done;
-		}
-	}
-
-	if ((dmi = dmi1) == NULL) {
-		netif_tx_unlock_bh(dev);
-		return -ENOMEM;
-	}
-	memcpy(dmi->dmi_addr, addr, alen);
-	dmi->dmi_addrlen = alen;
-	dmi->next = dev->mc_list;
-	dmi->dmi_users = 1;
-	dmi->dmi_gusers = glbl ? 1 : 0;
-	dev->mc_list = dmi;
-	dev->mc_count++;
-
-	__dev_mc_upload(dev);
-
+	err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl);
+	if (!err)
+		__dev_set_rx_mode(dev);
 	netif_tx_unlock_bh(dev);
-	return 0;
-
-done:
-	netif_tx_unlock_bh(dev);
-	kfree(dmi1);
 	return err;
 }
 
@@ -203,16 +109,8 @@
 void dev_mc_discard(struct net_device *dev)
 {
 	netif_tx_lock_bh(dev);
-
-	while (dev->mc_list != NULL) {
-		struct dev_mc_list *tmp = dev->mc_list;
-		dev->mc_list = tmp->next;
-		if (tmp->dmi_users > tmp->dmi_gusers)
-			printk("dev_mc_discard: multicast leakage! dmi_users=%d\n", tmp->dmi_users);
-		kfree(tmp);
-	}
+	__dev_addr_discard(&dev->mc_list);
 	dev->mc_count = 0;
-
 	netif_tx_unlock_bh(dev);
 }
 
@@ -244,7 +142,7 @@
 
 static int dev_mc_seq_show(struct seq_file *seq, void *v)
 {
-	struct dev_mc_list *m;
+	struct dev_addr_list *m;
 	struct net_device *dev = v;
 
 	netif_tx_lock_bh(dev);
@@ -292,4 +190,3 @@
 
 EXPORT_SYMBOL(dev_mc_add);
 EXPORT_SYMBOL(dev_mc_delete);
-EXPORT_SYMBOL(dev_mc_upload);
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index 17daf4c..cc84d8d 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -128,7 +128,8 @@
 		spin_unlock(e->stats_lock);
 	}
 
-	mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
+	if (elist[idx].list != NULL)
+		mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
 	read_unlock(&est_lock);
 }
 
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index a0efdd7..d1264e9 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -66,8 +66,9 @@
 
 		local_irq_save(flags);
 		netif_tx_lock(dev);
-		if (netif_queue_stopped(dev) ||
-		    dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
+		if ((netif_queue_stopped(dev) ||
+		     netif_subqueue_stopped(dev, skb->queue_mapping)) ||
+		     dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
 			skb_queue_head(&npinfo->txq, skb);
 			netif_tx_unlock(dev);
 			local_irq_restore(flags);
@@ -123,6 +124,13 @@
 	if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) &&
 	    npinfo->poll_owner != smp_processor_id() &&
 	    spin_trylock(&npinfo->poll_lock)) {
+		/* When calling dev->poll from poll_napi, we may end up in
+		 * netif_rx_complete. However, only the CPU to which the
+		 * device was queued is allowed to remove it from poll_list.
+		 * Setting POLL_LIST_FROZEN tells netif_rx_complete
+		 * to leave the NAPI state alone.
+		 */
+		set_bit(__LINK_STATE_POLL_LIST_FROZEN, &np->dev->state);
 		npinfo->rx_flags |= NETPOLL_RX_DROP;
 		atomic_inc(&trapped);
 
@@ -130,6 +138,7 @@
 
 		atomic_dec(&trapped);
 		npinfo->rx_flags &= ~NETPOLL_RX_DROP;
+		clear_bit(__LINK_STATE_POLL_LIST_FROZEN, &np->dev->state);
 		spin_unlock(&npinfo->poll_lock);
 	}
 }
@@ -254,7 +263,8 @@
 		for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
 		     tries > 0; --tries) {
 			if (netif_tx_trylock(dev)) {
-				if (!netif_queue_stopped(dev))
+				if (!netif_queue_stopped(dev) &&
+				    !netif_subqueue_stopped(dev, skb->queue_mapping))
 					status = dev->hard_start_xmit(skb, dev);
 				netif_tx_unlock(dev);
 
@@ -781,7 +791,6 @@
 				spin_unlock_irqrestore(&npinfo->rx_lock, flags);
 			}
 
-			np->dev->npinfo = NULL;
 			if (atomic_dec_and_test(&npinfo->refcnt)) {
 				skb_queue_purge(&npinfo->arp_tx);
 				skb_queue_purge(&npinfo->txq);
@@ -794,6 +803,7 @@
 					kfree_skb(skb);
 				}
 				kfree(npinfo);
+				np->dev->npinfo = NULL;
 			}
 		}
 
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 9cd3a1c..7521533 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -152,6 +152,9 @@
 #include <net/checksum.h>
 #include <net/ipv6.h>
 #include <net/addrconf.h>
+#ifdef CONFIG_XFRM
+#include <net/xfrm.h>
+#endif
 #include <asm/byteorder.h>
 #include <linux/rcupdate.h>
 #include <asm/bitops.h>
@@ -181,6 +184,8 @@
 #define F_MPLS_RND    (1<<8)	/* Random MPLS labels */
 #define F_VID_RND     (1<<9)	/* Random VLAN ID */
 #define F_SVID_RND    (1<<10)	/* Random SVLAN ID */
+#define F_FLOW_SEQ    (1<<11)	/* Sequential flows */
+#define F_IPSEC_ON    (1<<12)	/* ipsec on for flows */
 
 /* Thread control flag bits */
 #define T_TERMINATE   (1<<0)
@@ -207,8 +212,15 @@
 struct flow_state {
 	__be32 cur_daddr;
 	int count;
+#ifdef CONFIG_XFRM
+	struct xfrm_state *x;
+#endif
+	__u32 flags;
 };
 
+/* flow flag bits */
+#define F_INIT   (1<<0)		/* flow has been initialized */
+
 struct pktgen_dev {
 	/*
 	 * Try to keep frequent/infrequent used vars. separated.
@@ -228,6 +240,7 @@
 
 	int min_pkt_size;	/* = ETH_ZLEN; */
 	int max_pkt_size;	/* = ETH_ZLEN; */
+	int pkt_overhead;	/* overhead for MPLS, VLANs, IPSEC etc */
 	int nfrags;
 	__u32 delay_us;		/* Default delay */
 	__u32 delay_ns;
@@ -341,7 +354,11 @@
 	unsigned cflows;	/* Concurrent flows (config) */
 	unsigned lflow;		/* Flow length  (config) */
 	unsigned nflows;	/* accumulated flows (stats) */
-
+	unsigned curfl;		/* current sequenced flow (state)*/
+#ifdef CONFIG_XFRM
+	__u8	ipsmode;		/* IPSEC mode (config) */
+	__u8	ipsproto;		/* IPSEC type (config) */
+#endif
 	char result[512];
 };
 
@@ -690,6 +707,18 @@
 	if (pkt_dev->flags & F_MPLS_RND)
 		seq_printf(seq,  "MPLS_RND  ");
 
+	if (pkt_dev->cflows) {
+		if (pkt_dev->flags & F_FLOW_SEQ)
+			seq_printf(seq,  "FLOW_SEQ  "); /*in sequence flows*/
+		else
+			seq_printf(seq,  "FLOW_RND  ");
+	}
+
+#ifdef CONFIG_XFRM
+	if (pkt_dev->flags & F_IPSEC_ON)
+		seq_printf(seq,  "IPSEC  ");
+#endif
+
 	if (pkt_dev->flags & F_MACSRC_RND)
 		seq_printf(seq, "MACSRC_RND  ");
 
@@ -1181,6 +1210,14 @@
 		else if (strcmp(f, "!SVID_RND") == 0)
 			pkt_dev->flags &= ~F_SVID_RND;
 
+		else if (strcmp(f, "FLOW_SEQ") == 0)
+			pkt_dev->flags |= F_FLOW_SEQ;
+
+#ifdef CONFIG_XFRM
+		else if (strcmp(f, "IPSEC") == 0)
+			pkt_dev->flags |= F_IPSEC_ON;
+#endif
+
 		else if (strcmp(f, "!IPV6") == 0)
 			pkt_dev->flags &= ~F_IPV6;
 
@@ -1189,7 +1226,7 @@
 				"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
 				f,
 				"IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, "
-				"MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND\n");
+				"MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC\n");
 			return count;
 		}
 		sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags);
@@ -2075,6 +2112,70 @@
 	pkt_dev->idle_acc += now - start;
 }
 
+static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
+{
+	pkt_dev->pkt_overhead = 0;
+	pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof(u32);
+	pkt_dev->pkt_overhead += VLAN_TAG_SIZE(pkt_dev);
+	pkt_dev->pkt_overhead += SVLAN_TAG_SIZE(pkt_dev);
+}
+
+static inline int f_seen(struct pktgen_dev *pkt_dev, int flow)
+{
+
+	if (pkt_dev->flows[flow].flags & F_INIT)
+		return 1;
+	else
+		return 0;
+}
+
+static inline int f_pick(struct pktgen_dev *pkt_dev)
+{
+	int flow = pkt_dev->curfl;
+
+	if (pkt_dev->flags & F_FLOW_SEQ) {
+		if (pkt_dev->flows[flow].count >= pkt_dev->lflow) {
+			/* reset time */
+			pkt_dev->flows[flow].count = 0;
+			pkt_dev->curfl += 1;
+			if (pkt_dev->curfl >= pkt_dev->cflows)
+				pkt_dev->curfl = 0; /*reset */
+		}
+	} else {
+		flow = random32() % pkt_dev->cflows;
+
+		if (pkt_dev->flows[flow].count > pkt_dev->lflow)
+			pkt_dev->flows[flow].count = 0;
+	}
+
+	return pkt_dev->curfl;
+}
+
+
+#ifdef CONFIG_XFRM
+/* If there was already an IPSEC SA, we keep it as is, else
+ * we go look for it ...
+*/
+inline
+void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
+{
+	struct xfrm_state *x = pkt_dev->flows[flow].x;
+	if (!x) {
+		/*slow path: we dont already have xfrm_state*/
+		x = xfrm_stateonly_find((xfrm_address_t *)&pkt_dev->cur_daddr,
+					(xfrm_address_t *)&pkt_dev->cur_saddr,
+					AF_INET,
+					pkt_dev->ipsmode,
+					pkt_dev->ipsproto, 0);
+		if (x) {
+			pkt_dev->flows[flow].x = x;
+			set_pkt_overhead(pkt_dev);
+			pkt_dev->pkt_overhead+=x->props.header_len;
+		}
+
+	}
+}
+#endif
 /* Increment/randomize headers according to flags and current values
  * for IP src/dest, UDP src/dst port, MAC-Addr src/dst
  */
@@ -2084,12 +2185,8 @@
 	__u32 imx;
 	int flow = 0;
 
-	if (pkt_dev->cflows) {
-		flow = random32() % pkt_dev->cflows;
-
-		if (pkt_dev->flows[flow].count > pkt_dev->lflow)
-			pkt_dev->flows[flow].count = 0;
-	}
+	if (pkt_dev->cflows)
+		flow = f_pick(pkt_dev);
 
 	/*  Deal with source MAC */
 	if (pkt_dev->src_mac_count > 1) {
@@ -2205,7 +2302,7 @@
 			pkt_dev->cur_saddr = htonl(t);
 		}
 
-		if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) {
+		if (pkt_dev->cflows && f_seen(pkt_dev, flow)) {
 			pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr;
 		} else {
 			imn = ntohl(pkt_dev->daddr_min);
@@ -2235,8 +2332,13 @@
 				}
 			}
 			if (pkt_dev->cflows) {
+				pkt_dev->flows[flow].flags |= F_INIT;
 				pkt_dev->flows[flow].cur_daddr =
 				    pkt_dev->cur_daddr;
+#ifdef CONFIG_XFRM
+				if (pkt_dev->flags & F_IPSEC_ON)
+					get_ipsec_sa(pkt_dev, flow);
+#endif
 				pkt_dev->nflows++;
 			}
 		}
@@ -2277,6 +2379,91 @@
 	pkt_dev->flows[flow].count++;
 }
 
+
+#ifdef CONFIG_XFRM
+static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
+{
+	struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
+	int err = 0;
+	struct iphdr *iph;
+
+	if (!x)
+		return 0;
+	/* XXX: we dont support tunnel mode for now until
+	 * we resolve the dst issue */
+	if (x->props.mode != XFRM_MODE_TRANSPORT)
+		return 0;
+
+	spin_lock(&x->lock);
+	iph = ip_hdr(skb);
+
+	err = x->mode->output(x, skb);
+	if (err)
+		goto error;
+	err = x->type->output(x, skb);
+	if (err)
+		goto error;
+
+	x->curlft.bytes +=skb->len;
+	x->curlft.packets++;
+	spin_unlock(&x->lock);
+
+error:
+	spin_unlock(&x->lock);
+	return err;
+}
+
+static inline void free_SAs(struct pktgen_dev *pkt_dev)
+{
+	if (pkt_dev->cflows) {
+		/* let go of the SAs if we have them */
+		int i = 0;
+		for (;  i < pkt_dev->nflows; i++){
+			struct xfrm_state *x = pkt_dev->flows[i].x;
+			if (x) {
+				xfrm_state_put(x);
+				pkt_dev->flows[i].x = NULL;
+			}
+		}
+	}
+}
+
+static inline int process_ipsec(struct pktgen_dev *pkt_dev,
+			      struct sk_buff *skb, __be16 protocol)
+{
+	if (pkt_dev->flags & F_IPSEC_ON) {
+		struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
+		int nhead = 0;
+		if (x) {
+			int ret;
+			__u8 *eth;
+			nhead = x->props.header_len - skb_headroom(skb);
+			if (nhead >0) {
+				ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
+				if (ret < 0) {
+					printk("Error expanding ipsec packet %d\n",ret);
+					return 0;
+				}
+			}
+
+			/* ipsec is not expecting ll header */
+			skb_pull(skb, ETH_HLEN);
+			ret = pktgen_output_ipsec(skb, pkt_dev);
+			if (ret) {
+				printk("Error creating ipsec packet %d\n",ret);
+				kfree_skb(skb);
+				return 0;
+			}
+			/* restore ll */
+			eth = (__u8 *) skb_push(skb, ETH_HLEN);
+			memcpy(eth, pkt_dev->hh, 12);
+			*(u16 *) & eth[12] = protocol;
+		}
+	}
+	return 1;
+}
+#endif
+
 static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev)
 {
 	unsigned i;
@@ -2323,9 +2510,7 @@
 
 	datalen = (odev->hard_header_len + 16) & ~0xf;
 	skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen +
-			pkt_dev->nr_labels*sizeof(u32) +
-			VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev),
-			GFP_ATOMIC);
+			pkt_dev->pkt_overhead, GFP_ATOMIC);
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
 		return NULL;
@@ -2368,7 +2553,7 @@
 
 	/* Eth + IPh + UDPh + mpls */
 	datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
-		  pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
+		  pkt_dev->pkt_overhead;
 	if (datalen < sizeof(struct pktgen_hdr))
 		datalen = sizeof(struct pktgen_hdr);
 
@@ -2391,8 +2576,7 @@
 	iph->check = ip_fast_csum((void *)iph, iph->ihl);
 	skb->protocol = protocol;
 	skb->mac_header = (skb->network_header - ETH_HLEN -
-			   pkt_dev->nr_labels * sizeof(u32) -
-			   VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev));
+			   pkt_dev->pkt_overhead);
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
 
@@ -2463,6 +2647,11 @@
 		pgh->tv_usec = htonl(timestamp.tv_usec);
 	}
 
+#ifdef CONFIG_XFRM
+	if (!process_ipsec(pkt_dev, skb, protocol))
+		return NULL;
+#endif
+
 	return skb;
 }
 
@@ -2662,9 +2851,7 @@
 	mod_cur_headers(pkt_dev);
 
 	skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 +
-			pkt_dev->nr_labels*sizeof(u32) +
-			VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev),
-			GFP_ATOMIC);
+			pkt_dev->pkt_overhead, GFP_ATOMIC);
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
 		return NULL;
@@ -2708,7 +2895,7 @@
 	/* Eth + IPh + UDPh + mpls */
 	datalen = pkt_dev->cur_pkt_size - 14 -
 		  sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
-		  pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
+		  pkt_dev->pkt_overhead;
 
 	if (datalen < sizeof(struct pktgen_hdr)) {
 		datalen = sizeof(struct pktgen_hdr);
@@ -2738,8 +2925,7 @@
 	ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
 
 	skb->mac_header = (skb->network_header - ETH_HLEN -
-			   pkt_dev->nr_labels * sizeof(u32) -
-			   VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev));
+			   pkt_dev->pkt_overhead);
 	skb->protocol = protocol;
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
@@ -2857,6 +3043,7 @@
 			pkt_dev->started_at = getCurUs();
 			pkt_dev->next_tx_us = getCurUs();	/* Transmit immediately */
 			pkt_dev->next_tx_ns = 0;
+			set_pkt_overhead(pkt_dev);
 
 			strcpy(pkt_dev->result, "Starting");
 			started++;
@@ -3139,7 +3326,9 @@
 		}
 	}
 
-	if (netif_queue_stopped(odev) || need_resched()) {
+	if ((netif_queue_stopped(odev) ||
+	     netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) ||
+	     need_resched()) {
 		idle_start = getCurUs();
 
 		if (!netif_running(odev)) {
@@ -3154,7 +3343,8 @@
 
 		pkt_dev->idle_acc += getCurUs() - idle_start;
 
-		if (netif_queue_stopped(odev)) {
+		if (netif_queue_stopped(odev) ||
+		    netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) {
 			pkt_dev->next_tx_us = getCurUs();	/* TODO */
 			pkt_dev->next_tx_ns = 0;
 			goto out;	/* Try the next interface */
@@ -3181,7 +3371,8 @@
 	}
 
 	netif_tx_lock_bh(odev);
-	if (!netif_queue_stopped(odev)) {
+	if (!netif_queue_stopped(odev) &&
+	    !netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) {
 
 		atomic_inc(&(pkt_dev->skb->users));
 	      retry_now:
@@ -3446,11 +3637,18 @@
 	}
 	pkt_dev->entry->proc_fops = &pktgen_if_fops;
 	pkt_dev->entry->data = pkt_dev;
+#ifdef CONFIG_XFRM
+	pkt_dev->ipsmode = XFRM_MODE_TRANSPORT;
+	pkt_dev->ipsproto = IPPROTO_ESP;
+#endif
 
 	return add_dev_to_thread(t, pkt_dev);
 out2:
 	dev_put(pkt_dev->odev);
 out1:
+#ifdef CONFIG_XFRM
+	free_SAs(pkt_dev);
+#endif
 	if (pkt_dev->flows)
 		vfree(pkt_dev->flows);
 	kfree(pkt_dev);
@@ -3545,6 +3743,9 @@
 	if (pkt_dev->entry)
 		remove_proc_entry(pkt_dev->entry->name, pg_proc_dir);
 
+#ifdef CONFIG_XFRM
+	free_SAs(pkt_dev);
+#endif
 	if (pkt_dev->flows)
 		vfree(pkt_dev->flows);
 	kfree(pkt_dev);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 02e8bf0..54c17e4 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -97,6 +97,19 @@
 	return 0;
 }
 
+int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
+			         struct rtattr *rta, int len)
+{
+	if (RTA_PAYLOAD(rta) < len)
+		return -1;
+	if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) {
+		rta = RTA_DATA(rta) + RTA_ALIGN(len);
+		return rtattr_parse_nested(tb, maxattr, rta);
+	}
+	memset(tb, 0, sizeof(struct rtattr *) * maxattr);
+	return 0;
+}
+
 static struct rtnl_link *rtnl_msg_handlers[NPROTO];
 
 static inline int rtm_msgindex(int msgtype)
@@ -243,6 +256,143 @@
 
 EXPORT_SYMBOL_GPL(rtnl_unregister_all);
 
+static LIST_HEAD(link_ops);
+
+/**
+ * __rtnl_link_register - Register rtnl_link_ops with rtnetlink.
+ * @ops: struct rtnl_link_ops * to register
+ *
+ * The caller must hold the rtnl_mutex. This function should be used
+ * by drivers that create devices during module initialization. It
+ * must be called before registering the devices.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int __rtnl_link_register(struct rtnl_link_ops *ops)
+{
+	list_add_tail(&ops->list, &link_ops);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(__rtnl_link_register);
+
+/**
+ * rtnl_link_register - Register rtnl_link_ops with rtnetlink.
+ * @ops: struct rtnl_link_ops * to register
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int rtnl_link_register(struct rtnl_link_ops *ops)
+{
+	int err;
+
+	rtnl_lock();
+	err = __rtnl_link_register(ops);
+	rtnl_unlock();
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(rtnl_link_register);
+
+/**
+ * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
+ * @ops: struct rtnl_link_ops * to unregister
+ *
+ * The caller must hold the rtnl_mutex. This function should be used
+ * by drivers that unregister devices during module unloading. It must
+ * be called after unregistering the devices.
+ */
+void __rtnl_link_unregister(struct rtnl_link_ops *ops)
+{
+	list_del(&ops->list);
+}
+
+EXPORT_SYMBOL_GPL(__rtnl_link_unregister);
+
+/**
+ * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
+ * @ops: struct rtnl_link_ops * to unregister
+ */
+void rtnl_link_unregister(struct rtnl_link_ops *ops)
+{
+	rtnl_lock();
+	__rtnl_link_unregister(ops);
+	rtnl_unlock();
+}
+
+EXPORT_SYMBOL_GPL(rtnl_link_unregister);
+
+static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind)
+{
+	const struct rtnl_link_ops *ops;
+
+	list_for_each_entry(ops, &link_ops, list) {
+		if (!strcmp(ops->kind, kind))
+			return ops;
+	}
+	return NULL;
+}
+
+static size_t rtnl_link_get_size(const struct net_device *dev)
+{
+	const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
+	size_t size;
+
+	if (!ops)
+		return 0;
+
+	size = nlmsg_total_size(sizeof(struct nlattr)) + /* IFLA_LINKINFO */
+	       nlmsg_total_size(strlen(ops->kind) + 1);	 /* IFLA_INFO_KIND */
+
+	if (ops->get_size)
+		/* IFLA_INFO_DATA + nested data */
+		size += nlmsg_total_size(sizeof(struct nlattr)) +
+			ops->get_size(dev);
+
+	if (ops->get_xstats_size)
+		size += ops->get_xstats_size(dev);	/* IFLA_INFO_XSTATS */
+
+	return size;
+}
+
+static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
+{
+	const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
+	struct nlattr *linkinfo, *data;
+	int err = -EMSGSIZE;
+
+	linkinfo = nla_nest_start(skb, IFLA_LINKINFO);
+	if (linkinfo == NULL)
+		goto out;
+
+	if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0)
+		goto err_cancel_link;
+	if (ops->fill_xstats) {
+		err = ops->fill_xstats(skb, dev);
+		if (err < 0)
+			goto err_cancel_link;
+	}
+	if (ops->fill_info) {
+		data = nla_nest_start(skb, IFLA_INFO_DATA);
+		if (data == NULL)
+			goto err_cancel_link;
+		err = ops->fill_info(skb, dev);
+		if (err < 0)
+			goto err_cancel_data;
+		nla_nest_end(skb, data);
+	}
+
+	nla_nest_end(skb, linkinfo);
+	return 0;
+
+err_cancel_data:
+	nla_nest_cancel(skb, data);
+err_cancel_link:
+	nla_nest_cancel(skb, linkinfo);
+out:
+	return err;
+}
+
 static const int rtm_min[RTM_NR_FAMILIES] =
 {
 	[RTM_FAM(RTM_NEWLINK)]      = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
@@ -437,7 +587,7 @@
 	a->tx_compressed = b->tx_compressed;
 };
 
-static inline size_t if_nlmsg_size(void)
+static inline size_t if_nlmsg_size(const struct net_device *dev)
 {
 	return NLMSG_ALIGN(sizeof(struct ifinfomsg))
 	       + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
@@ -452,7 +602,8 @@
 	       + nla_total_size(4) /* IFLA_LINK */
 	       + nla_total_size(4) /* IFLA_MASTER */
 	       + nla_total_size(1) /* IFLA_OPERSTATE */
-	       + nla_total_size(1); /* IFLA_LINKMODE */
+	       + nla_total_size(1) /* IFLA_LINKMODE */
+	       + rtnl_link_get_size(dev); /* IFLA_LINKINFO */
 }
 
 static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
@@ -522,6 +673,11 @@
 		}
 	}
 
+	if (dev->rtnl_link_ops) {
+		if (rtnl_link_fill(skb, dev) < 0)
+			goto nla_put_failure;
+	}
+
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
@@ -553,6 +709,8 @@
 
 static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_IFNAME]		= { .type = NLA_STRING, .len = IFNAMSIZ-1 },
+	[IFLA_ADDRESS]		= { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
+	[IFLA_BROADCAST]	= { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
 	[IFLA_MAP]		= { .len = sizeof(struct rtnl_link_ifmap) },
 	[IFLA_MTU]		= { .type = NLA_U32 },
 	[IFLA_TXQLEN]		= { .type = NLA_U32 },
@@ -561,11 +719,145 @@
 	[IFLA_LINKMODE]		= { .type = NLA_U8 },
 };
 
+static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
+	[IFLA_INFO_KIND]	= { .type = NLA_STRING },
+	[IFLA_INFO_DATA]	= { .type = NLA_NESTED },
+};
+
+static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
+		      struct nlattr **tb, char *ifname, int modified)
+{
+	int send_addr_notify = 0;
+	int err;
+
+	if (tb[IFLA_MAP]) {
+		struct rtnl_link_ifmap *u_map;
+		struct ifmap k_map;
+
+		if (!dev->set_config) {
+			err = -EOPNOTSUPP;
+			goto errout;
+		}
+
+		if (!netif_device_present(dev)) {
+			err = -ENODEV;
+			goto errout;
+		}
+
+		u_map = nla_data(tb[IFLA_MAP]);
+		k_map.mem_start = (unsigned long) u_map->mem_start;
+		k_map.mem_end = (unsigned long) u_map->mem_end;
+		k_map.base_addr = (unsigned short) u_map->base_addr;
+		k_map.irq = (unsigned char) u_map->irq;
+		k_map.dma = (unsigned char) u_map->dma;
+		k_map.port = (unsigned char) u_map->port;
+
+		err = dev->set_config(dev, &k_map);
+		if (err < 0)
+			goto errout;
+
+		modified = 1;
+	}
+
+	if (tb[IFLA_ADDRESS]) {
+		struct sockaddr *sa;
+		int len;
+
+		if (!dev->set_mac_address) {
+			err = -EOPNOTSUPP;
+			goto errout;
+		}
+
+		if (!netif_device_present(dev)) {
+			err = -ENODEV;
+			goto errout;
+		}
+
+		len = sizeof(sa_family_t) + dev->addr_len;
+		sa = kmalloc(len, GFP_KERNEL);
+		if (!sa) {
+			err = -ENOMEM;
+			goto errout;
+		}
+		sa->sa_family = dev->type;
+		memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
+		       dev->addr_len);
+		err = dev->set_mac_address(dev, sa);
+		kfree(sa);
+		if (err)
+			goto errout;
+		send_addr_notify = 1;
+		modified = 1;
+	}
+
+	if (tb[IFLA_MTU]) {
+		err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
+		if (err < 0)
+			goto errout;
+		modified = 1;
+	}
+
+	/*
+	 * Interface selected by interface index but interface
+	 * name provided implies that a name change has been
+	 * requested.
+	 */
+	if (ifm->ifi_index > 0 && ifname[0]) {
+		err = dev_change_name(dev, ifname);
+		if (err < 0)
+			goto errout;
+		modified = 1;
+	}
+
+	if (tb[IFLA_BROADCAST]) {
+		nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
+		send_addr_notify = 1;
+	}
+
+	if (ifm->ifi_flags || ifm->ifi_change) {
+		unsigned int flags = ifm->ifi_flags;
+
+		/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
+		if (ifm->ifi_change)
+			flags = (flags & ifm->ifi_change) |
+				(dev->flags & ~ifm->ifi_change);
+		dev_change_flags(dev, flags);
+	}
+
+	if (tb[IFLA_TXQLEN])
+		dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
+
+	if (tb[IFLA_WEIGHT])
+		dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
+
+	if (tb[IFLA_OPERSTATE])
+		set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
+
+	if (tb[IFLA_LINKMODE]) {
+		write_lock_bh(&dev_base_lock);
+		dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
+		write_unlock_bh(&dev_base_lock);
+	}
+
+	err = 0;
+
+errout:
+	if (err < 0 && modified && net_ratelimit())
+		printk(KERN_WARNING "A link change request failed with "
+		       "some changes comitted already. Interface %s may "
+		       "have been left with an inconsistent configuration, "
+		       "please check.\n", dev->name);
+
+	if (send_addr_notify)
+		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+	return err;
+}
+
 static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct ifinfomsg *ifm;
 	struct net_device *dev;
-	int err, send_addr_notify = 0, modified = 0;
+	int err;
 	struct nlattr *tb[IFLA_MAX+1];
 	char ifname[IFNAMSIZ];
 
@@ -600,133 +892,189 @@
 	    nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
 		goto errout_dev;
 
-	if (tb[IFLA_MAP]) {
-		struct rtnl_link_ifmap *u_map;
-		struct ifmap k_map;
-
-		if (!dev->set_config) {
-			err = -EOPNOTSUPP;
-			goto errout_dev;
-		}
-
-		if (!netif_device_present(dev)) {
-			err = -ENODEV;
-			goto errout_dev;
-		}
-
-		u_map = nla_data(tb[IFLA_MAP]);
-		k_map.mem_start = (unsigned long) u_map->mem_start;
-		k_map.mem_end = (unsigned long) u_map->mem_end;
-		k_map.base_addr = (unsigned short) u_map->base_addr;
-		k_map.irq = (unsigned char) u_map->irq;
-		k_map.dma = (unsigned char) u_map->dma;
-		k_map.port = (unsigned char) u_map->port;
-
-		err = dev->set_config(dev, &k_map);
-		if (err < 0)
-			goto errout_dev;
-
-		modified = 1;
-	}
-
-	if (tb[IFLA_ADDRESS]) {
-		struct sockaddr *sa;
-		int len;
-
-		if (!dev->set_mac_address) {
-			err = -EOPNOTSUPP;
-			goto errout_dev;
-		}
-
-		if (!netif_device_present(dev)) {
-			err = -ENODEV;
-			goto errout_dev;
-		}
-
-		len = sizeof(sa_family_t) + dev->addr_len;
-		sa = kmalloc(len, GFP_KERNEL);
-		if (!sa) {
-			err = -ENOMEM;
-			goto errout_dev;
-		}
-		sa->sa_family = dev->type;
-		memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
-		       dev->addr_len);
-		err = dev->set_mac_address(dev, sa);
-		kfree(sa);
-		if (err)
-			goto errout_dev;
-		send_addr_notify = 1;
-		modified = 1;
-	}
-
-	if (tb[IFLA_MTU]) {
-		err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
-		if (err < 0)
-			goto errout_dev;
-		modified = 1;
-	}
-
-	/*
-	 * Interface selected by interface index but interface
-	 * name provided implies that a name change has been
-	 * requested.
-	 */
-	if (ifm->ifi_index > 0 && ifname[0]) {
-		err = dev_change_name(dev, ifname);
-		if (err < 0)
-			goto errout_dev;
-		modified = 1;
-	}
-
-	if (tb[IFLA_BROADCAST]) {
-		nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
-		send_addr_notify = 1;
-	}
-
-
-	if (ifm->ifi_flags || ifm->ifi_change) {
-		unsigned int flags = ifm->ifi_flags;
-
-		/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
-		if (ifm->ifi_change)
-			flags = (flags & ifm->ifi_change) |
-				(dev->flags & ~ifm->ifi_change);
-		dev_change_flags(dev, flags);
-	}
-
-	if (tb[IFLA_TXQLEN])
-		dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
-
-	if (tb[IFLA_WEIGHT])
-		dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
-
-	if (tb[IFLA_OPERSTATE])
-		set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
-
-	if (tb[IFLA_LINKMODE]) {
-		write_lock_bh(&dev_base_lock);
-		dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
-		write_unlock_bh(&dev_base_lock);
-	}
-
-	err = 0;
-
+	err = do_setlink(dev, ifm, tb, ifname, 0);
 errout_dev:
-	if (err < 0 && modified && net_ratelimit())
-		printk(KERN_WARNING "A link change request failed with "
-		       "some changes comitted already. Interface %s may "
-		       "have been left with an inconsistent configuration, "
-		       "please check.\n", dev->name);
-
-	if (send_addr_notify)
-		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
-
 	dev_put(dev);
 errout:
 	return err;
 }
 
+static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+	const struct rtnl_link_ops *ops;
+	struct net_device *dev;
+	struct ifinfomsg *ifm;
+	char ifname[IFNAMSIZ];
+	struct nlattr *tb[IFLA_MAX+1];
+	int err;
+
+	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+	if (err < 0)
+		return err;
+
+	if (tb[IFLA_IFNAME])
+		nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+
+	ifm = nlmsg_data(nlh);
+	if (ifm->ifi_index > 0)
+		dev = __dev_get_by_index(ifm->ifi_index);
+	else if (tb[IFLA_IFNAME])
+		dev = __dev_get_by_name(ifname);
+	else
+		return -EINVAL;
+
+	if (!dev)
+		return -ENODEV;
+
+	ops = dev->rtnl_link_ops;
+	if (!ops)
+		return -EOPNOTSUPP;
+
+	ops->dellink(dev);
+	return 0;
+}
+
+static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+	const struct rtnl_link_ops *ops;
+	struct net_device *dev;
+	struct ifinfomsg *ifm;
+	char kind[MODULE_NAME_LEN];
+	char ifname[IFNAMSIZ];
+	struct nlattr *tb[IFLA_MAX+1];
+	struct nlattr *linkinfo[IFLA_INFO_MAX+1];
+	int err;
+
+replay:
+	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+	if (err < 0)
+		return err;
+
+	if (tb[IFLA_IFNAME])
+		nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+	else
+		ifname[0] = '\0';
+
+	ifm = nlmsg_data(nlh);
+	if (ifm->ifi_index > 0)
+		dev = __dev_get_by_index(ifm->ifi_index);
+	else if (ifname[0])
+		dev = __dev_get_by_name(ifname);
+	else
+		dev = NULL;
+
+	if (tb[IFLA_LINKINFO]) {
+		err = nla_parse_nested(linkinfo, IFLA_INFO_MAX,
+				       tb[IFLA_LINKINFO], ifla_info_policy);
+		if (err < 0)
+			return err;
+	} else
+		memset(linkinfo, 0, sizeof(linkinfo));
+
+	if (linkinfo[IFLA_INFO_KIND]) {
+		nla_strlcpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind));
+		ops = rtnl_link_ops_get(kind);
+	} else {
+		kind[0] = '\0';
+		ops = NULL;
+	}
+
+	if (1) {
+		struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL;
+
+		if (ops) {
+			if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) {
+				err = nla_parse_nested(attr, ops->maxtype,
+						       linkinfo[IFLA_INFO_DATA],
+						       ops->policy);
+				if (err < 0)
+					return err;
+				data = attr;
+			}
+			if (ops->validate) {
+				err = ops->validate(tb, data);
+				if (err < 0)
+					return err;
+			}
+		}
+
+		if (dev) {
+			int modified = 0;
+
+			if (nlh->nlmsg_flags & NLM_F_EXCL)
+				return -EEXIST;
+			if (nlh->nlmsg_flags & NLM_F_REPLACE)
+				return -EOPNOTSUPP;
+
+			if (linkinfo[IFLA_INFO_DATA]) {
+				if (!ops || ops != dev->rtnl_link_ops ||
+				    !ops->changelink)
+					return -EOPNOTSUPP;
+
+				err = ops->changelink(dev, tb, data);
+				if (err < 0)
+					return err;
+				modified = 1;
+			}
+
+			return do_setlink(dev, ifm, tb, ifname, modified);
+		}
+
+		if (!(nlh->nlmsg_flags & NLM_F_CREATE))
+			return -ENODEV;
+
+		if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change)
+			return -EOPNOTSUPP;
+		if (tb[IFLA_ADDRESS] || tb[IFLA_BROADCAST] || tb[IFLA_MAP] ||
+		    tb[IFLA_MASTER] || tb[IFLA_PROTINFO])
+			return -EOPNOTSUPP;
+
+		if (!ops) {
+#ifdef CONFIG_KMOD
+			if (kind[0]) {
+				__rtnl_unlock();
+				request_module("rtnl-link-%s", kind);
+				rtnl_lock();
+				ops = rtnl_link_ops_get(kind);
+				if (ops)
+					goto replay;
+			}
+#endif
+			return -EOPNOTSUPP;
+		}
+
+		if (!ifname[0])
+			snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
+		dev = alloc_netdev(ops->priv_size, ifname, ops->setup);
+		if (!dev)
+			return -ENOMEM;
+
+		if (strchr(dev->name, '%')) {
+			err = dev_alloc_name(dev, dev->name);
+			if (err < 0)
+				goto err_free;
+		}
+		dev->rtnl_link_ops = ops;
+
+		if (tb[IFLA_MTU])
+			dev->mtu = nla_get_u32(tb[IFLA_MTU]);
+		if (tb[IFLA_TXQLEN])
+			dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
+		if (tb[IFLA_WEIGHT])
+			dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
+		if (tb[IFLA_OPERSTATE])
+			set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
+		if (tb[IFLA_LINKMODE])
+			dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
+
+		err = ops->newlink(dev, tb, data);
+err_free:
+		if (err < 0)
+			free_netdev(dev);
+		return err;
+	}
+}
+
 static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
 	struct ifinfomsg *ifm;
@@ -747,7 +1095,7 @@
 	} else
 		return -EINVAL;
 
-	nskb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL);
+	nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
 	if (nskb == NULL) {
 		err = -ENOBUFS;
 		goto errout;
@@ -797,7 +1145,7 @@
 	struct sk_buff *skb;
 	int err = -ENOBUFS;
 
-	skb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL);
+	skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
 	if (skb == NULL)
 		goto errout;
 
@@ -952,6 +1300,8 @@
 
 	rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo);
 	rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL);
+	rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL);
+	rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL);
 
 	rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all);
 	rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all);
@@ -960,6 +1310,7 @@
 EXPORT_SYMBOL(__rta_fill);
 EXPORT_SYMBOL(rtattr_strlcpy);
 EXPORT_SYMBOL(rtattr_parse);
+EXPORT_SYMBOL(__rtattr_parse_nested_compat);
 EXPORT_SYMBOL(rtnetlink_put_metrics);
 EXPORT_SYMBOL(rtnl_lock);
 EXPORT_SYMBOL(rtnl_trylock);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3943c3a..0583e84 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -415,9 +415,11 @@
 	C(csum);
 	C(local_df);
 	n->cloned = 1;
+	n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
 	n->nohdr = 0;
 	C(pkt_type);
 	C(ip_summed);
+	skb_copy_queue_mapping(n, skb);
 	C(priority);
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	C(ipvs_property);
@@ -426,6 +428,10 @@
 	n->destructor = NULL;
 	C(mark);
 	__nf_copy(n, skb);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	C(nf_trace);
+#endif
 #ifdef CONFIG_NET_SCHED
 	C(tc_index);
 #ifdef CONFIG_NET_CLS_ACT
@@ -459,6 +465,7 @@
 #endif
 	new->sk		= NULL;
 	new->dev	= old->dev;
+	skb_copy_queue_mapping(new, old);
 	new->priority	= old->priority;
 	new->protocol	= old->protocol;
 	new->dst	= dst_clone(old->dst);
@@ -482,6 +489,10 @@
 	new->destructor = NULL;
 	new->mark	= old->mark;
 	__nf_copy(new, old);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	new->nf_trace	= old->nf_trace;
+#endif
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	new->ipvs_property = old->ipvs_property;
 #endif
@@ -676,6 +687,7 @@
 	skb->network_header   += off;
 	skb->mac_header	      += off;
 	skb->cloned   = 0;
+	skb->hdr_len  = 0;
 	skb->nohdr    = 0;
 	atomic_set(&skb_shinfo(skb)->dataref, 1);
 	return 0;
@@ -1930,6 +1942,7 @@
 		tail = nskb;
 
 		nskb->dev = skb->dev;
+		skb_copy_queue_mapping(nskb, skb);
 		nskb->priority = skb->priority;
 		nskb->protocol = skb->protocol;
 		nskb->dst = dst_clone(skb->dst);
diff --git a/net/core/sock.c b/net/core/sock.c
index c14ce01..091032a 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -210,7 +210,8 @@
 		return -EDOM;
 
 	if (tv.tv_sec < 0) {
-		static int warned = 0;
+		static int warned __read_mostly;
+
 		*timeo_p = 0;
 		if (warned < 10 && net_ratelimit())
 			warned++;
@@ -1851,46 +1852,15 @@
 EXPORT_SYMBOL(proto_unregister);
 
 #ifdef CONFIG_PROC_FS
-static inline struct proto *__proto_head(void)
-{
-	return list_entry(proto_list.next, struct proto, node);
-}
-
-static inline struct proto *proto_head(void)
-{
-	return list_empty(&proto_list) ? NULL : __proto_head();
-}
-
-static inline struct proto *proto_next(struct proto *proto)
-{
-	return proto->node.next == &proto_list ? NULL :
-		list_entry(proto->node.next, struct proto, node);
-}
-
-static inline struct proto *proto_get_idx(loff_t pos)
-{
-	struct proto *proto;
-	loff_t i = 0;
-
-	list_for_each_entry(proto, &proto_list, node)
-		if (i++ == pos)
-			goto out;
-
-	proto = NULL;
-out:
-	return proto;
-}
-
 static void *proto_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	read_lock(&proto_list_lock);
-	return *pos ? proto_get_idx(*pos - 1) : SEQ_START_TOKEN;
+	return seq_list_start_head(&proto_list, *pos);
 }
 
 static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	++*pos;
-	return v == SEQ_START_TOKEN ? proto_head() : proto_next(v);
+	return seq_list_next(v, &proto_list, pos);
 }
 
 static void proto_seq_stop(struct seq_file *seq, void *v)
@@ -1938,7 +1908,7 @@
 
 static int proto_seq_show(struct seq_file *seq, void *v)
 {
-	if (v == SEQ_START_TOKEN)
+	if (v == &proto_list)
 		seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s",
 			   "protocol",
 			   "size",
@@ -1950,7 +1920,7 @@
 			   "module",
 			   "cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n");
 	else
-		proto_seq_printf(seq, v);
+		proto_seq_printf(seq, list_entry(v, struct proto, node));
 	return 0;
 }
 
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index ec7fa4d..e91c2b9 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -1,8 +1,8 @@
 /*
  *  net/dccp/ccids/ccid3.c
  *
- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
+ *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+ *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *
  *  An implementation of the DCCP protocol
  *
@@ -49,7 +49,6 @@
 
 static struct dccp_tx_hist *ccid3_tx_hist;
 static struct dccp_rx_hist *ccid3_rx_hist;
-static struct dccp_li_hist *ccid3_li_hist;
 
 /*
  *	Transmitter Half-Connection Routines
@@ -194,25 +193,20 @@
  *	The algorithm is not applicable if RTT < 4 microseconds.
  */
 static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx,
-						struct timeval *now)
+						ktime_t now)
 {
-	suseconds_t delta;
 	u32 quarter_rtts;
 
 	if (unlikely(hctx->ccid3hctx_rtt < 4))	/* avoid divide-by-zero */
 		return;
 
-	delta = timeval_delta(now, &hctx->ccid3hctx_t_last_win_count);
-	DCCP_BUG_ON(delta < 0);
-
-	quarter_rtts = (u32)delta / (hctx->ccid3hctx_rtt / 4);
+	quarter_rtts = ktime_us_delta(now, hctx->ccid3hctx_t_last_win_count);
+	quarter_rtts /= hctx->ccid3hctx_rtt / 4;
 
 	if (quarter_rtts > 0) {
-		hctx->ccid3hctx_t_last_win_count = *now;
+		hctx->ccid3hctx_t_last_win_count = now;
 		hctx->ccid3hctx_last_win_count	+= min_t(u32, quarter_rtts, 5);
 		hctx->ccid3hctx_last_win_count	&= 0xF;		/* mod 16 */
-
-		ccid3_pr_debug("now at %#X\n", hctx->ccid3hctx_last_win_count);
 	}
 }
 
@@ -312,8 +306,8 @@
 {
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
-	struct timeval now;
-	suseconds_t delay;
+	ktime_t now = ktime_get_real();
+	s64 delay;
 
 	BUG_ON(hctx == NULL);
 
@@ -325,8 +319,6 @@
 	if (unlikely(skb->len == 0))
 		return -EBADMSG;
 
-	dccp_timestamp(sk, &now);
-
 	switch (hctx->ccid3hctx_state) {
 	case TFRC_SSTATE_NO_SENT:
 		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
@@ -349,7 +341,7 @@
 			ccid3_pr_debug("SYN RTT = %uus\n", dp->dccps_syn_rtt);
 			hctx->ccid3hctx_rtt  = dp->dccps_syn_rtt;
 			hctx->ccid3hctx_x    = rfc3390_initial_rate(sk);
-			hctx->ccid3hctx_t_ld = now;
+			hctx->ccid3hctx_t_ld = ktime_to_timeval(now);
 		} else {
 			/* Sender does not have RTT sample: X = MSS/second */
 			hctx->ccid3hctx_x = dp->dccps_mss_cache;
@@ -361,7 +353,7 @@
 		break;
 	case TFRC_SSTATE_NO_FBACK:
 	case TFRC_SSTATE_FBACK:
-		delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
+		delay = ktime_us_delta(hctx->ccid3hctx_t_nom, now);
 		ccid3_pr_debug("delay=%ld\n", (long)delay);
 		/*
 		 *	Scheduling of packet transmissions [RFC 3448, 4.6]
@@ -371,10 +363,10 @@
 		 * else
 		 *       // send the packet in (t_nom - t_now) milliseconds.
 		 */
-		if (delay - (suseconds_t)hctx->ccid3hctx_delta >= 0)
-			return delay / 1000L;
+		if (delay - (s64)hctx->ccid3hctx_delta >= 1000)
+			return (u32)delay / 1000L;
 
-		ccid3_hc_tx_update_win_count(hctx, &now);
+		ccid3_hc_tx_update_win_count(hctx, now);
 		break;
 	case TFRC_SSTATE_TERM:
 		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
@@ -387,8 +379,8 @@
 	hctx->ccid3hctx_idle = 0;
 
 	/* set the nominal send time for the next following packet */
-	timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
-
+	hctx->ccid3hctx_t_nom = ktime_add_us(hctx->ccid3hctx_t_nom,
+					     hctx->ccid3hctx_t_ipi);
 	return 0;
 }
 
@@ -819,154 +811,6 @@
 	return 0;
 }
 
-/* calculate first loss interval
- *
- * returns estimated loss interval in usecs */
-
-static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
-{
-	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
-	struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
-	u32 x_recv, p;
-	suseconds_t rtt, delta;
-	struct timeval tstamp = { 0, };
-	int interval = 0;
-	int win_count = 0;
-	int step = 0;
-	u64 fval;
-
-	list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
-				 dccphrx_node) {
-		if (dccp_rx_hist_entry_data_packet(entry)) {
-			tail = entry;
-
-			switch (step) {
-			case 0:
-				tstamp	  = entry->dccphrx_tstamp;
-				win_count = entry->dccphrx_ccval;
-				step = 1;
-				break;
-			case 1:
-				interval = win_count - entry->dccphrx_ccval;
-				if (interval < 0)
-					interval += TFRC_WIN_COUNT_LIMIT;
-				if (interval > 4)
-					goto found;
-				break;
-			}
-		}
-	}
-
-	if (unlikely(step == 0)) {
-		DCCP_WARN("%s(%p), packet history has no data packets!\n",
-			  dccp_role(sk), sk);
-		return ~0;
-	}
-
-	if (unlikely(interval == 0)) {
-		DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
-			  "Defaulting to 1\n", dccp_role(sk), sk);
-		interval = 1;
-	}
-found:
-	if (!tail) {
-		DCCP_CRIT("tail is null\n");
-		return ~0;
-	}
-
-	delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
-	DCCP_BUG_ON(delta < 0);
-
-	rtt = delta * 4 / interval;
-	ccid3_pr_debug("%s(%p), approximated RTT to %dus\n",
-		       dccp_role(sk), sk, (int)rtt);
-
-	/*
-	 * Determine the length of the first loss interval via inverse lookup.
-	 * Assume that X_recv can be computed by the throughput equation
-	 *		    s
-	 *	X_recv = --------
-	 *		 R * fval
-	 * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
-	 */
-	if (rtt == 0) {			/* would result in divide-by-zero */
-		DCCP_WARN("RTT==0\n");
-		return ~0;
-	}
-
-	dccp_timestamp(sk, &tstamp);
-	delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
-	DCCP_BUG_ON(delta <= 0);
-
-	x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
-	if (x_recv == 0) {		/* would also trigger divide-by-zero */
-		DCCP_WARN("X_recv==0\n");
-		if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) {
-			DCCP_BUG("stored value of X_recv is zero");
-			return ~0;
-		}
-	}
-
-	fval = scaled_div(hcrx->ccid3hcrx_s, rtt);
-	fval = scaled_div32(fval, x_recv);
-	p = tfrc_calc_x_reverse_lookup(fval);
-
-	ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
-		       "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
-
-	if (p == 0)
-		return ~0;
-	else
-		return 1000000 / p;
-}
-
-static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
-{
-	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
-	struct dccp_li_hist_entry *head;
-	u64 seq_temp;
-
-	if (list_empty(&hcrx->ccid3hcrx_li_hist)) {
-		if (!dccp_li_hist_interval_new(ccid3_li_hist,
-		   &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss))
-			return;
-
-		head = list_entry(hcrx->ccid3hcrx_li_hist.next,
-		   struct dccp_li_hist_entry, dccplih_node);
-		head->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
-	} else {
-		struct dccp_li_hist_entry *entry;
-		struct list_head *tail;
-
-		head = list_entry(hcrx->ccid3hcrx_li_hist.next,
-		   struct dccp_li_hist_entry, dccplih_node);
-		/* FIXME win count check removed as was wrong */
-		/* should make this check with receive history */
-		/* and compare there as per section 10.2 of RFC4342 */
-
-		/* new loss event detected */
-		/* calculate last interval length */
-		seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
-		entry = dccp_li_hist_entry_new(ccid3_li_hist, GFP_ATOMIC);
-
-		if (entry == NULL) {
-			DCCP_BUG("out of memory - can not allocate entry");
-			return;
-		}
-
-		list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist);
-
-		tail = hcrx->ccid3hcrx_li_hist.prev;
-		list_del(tail);
-		kmem_cache_free(ccid3_li_hist->dccplih_slab, tail);
-
-		/* Create the newest interval */
-		entry->dccplih_seqno = seq_loss;
-		entry->dccplih_interval = seq_temp;
-		entry->dccplih_win_count = win_loss;
-	}
-}
-
 static int ccid3_hc_rx_detect_loss(struct sock *sk,
 				    struct dccp_rx_hist_entry *packet)
 {
@@ -992,8 +836,15 @@
 	while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)
 	   > TFRC_RECV_NUM_LATE_LOSS) {
 		loss = 1;
-		ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss,
-		   hcrx->ccid3hcrx_ccval_nonloss);
+		dccp_li_update_li(sk,
+				  &hcrx->ccid3hcrx_li_hist,
+				  &hcrx->ccid3hcrx_hist,
+				  &hcrx->ccid3hcrx_tstamp_last_feedback,
+				  hcrx->ccid3hcrx_s,
+				  hcrx->ccid3hcrx_bytes_recv,
+				  hcrx->ccid3hcrx_x_recv,
+				  hcrx->ccid3hcrx_seqno_nonloss,
+				  hcrx->ccid3hcrx_ccval_nonloss);
 		tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
 		dccp_inc_seqno(&tmp_seqno);
 		hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
@@ -1152,7 +1003,7 @@
 	dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
 
 	/* Empty loss interval history */
-	dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
+	dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist);
 }
 
 static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
@@ -1236,19 +1087,12 @@
 	if (ccid3_tx_hist == NULL)
 		goto out_free_rx;
 
-	ccid3_li_hist = dccp_li_hist_new("ccid3");
-	if (ccid3_li_hist == NULL)
-		goto out_free_tx;
-
 	rc = ccid_register(&ccid3);
 	if (rc != 0)
-		goto out_free_loss_interval_history;
+		goto out_free_tx;
 out:
 	return rc;
 
-out_free_loss_interval_history:
-	dccp_li_hist_delete(ccid3_li_hist);
-	ccid3_li_hist = NULL;
 out_free_tx:
 	dccp_tx_hist_delete(ccid3_tx_hist);
 	ccid3_tx_hist = NULL;
@@ -1271,10 +1115,6 @@
 		dccp_rx_hist_delete(ccid3_rx_hist);
 		ccid3_rx_hist = NULL;
 	}
-	if (ccid3_li_hist != NULL) {
-		dccp_li_hist_delete(ccid3_li_hist);
-		ccid3_li_hist = NULL;
-	}
 }
 module_exit(ccid3_module_exit);
 
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 8d31b38..51d4b80 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -36,6 +36,7 @@
 #ifndef _DCCP_CCID3_H_
 #define _DCCP_CCID3_H_
 
+#include <linux/ktime.h>
 #include <linux/list.h>
 #include <linux/time.h>
 #include <linux/types.h>
@@ -108,10 +109,10 @@
 	enum ccid3_hc_tx_states		ccid3hctx_state:8;
 	u8				ccid3hctx_last_win_count;
 	u8				ccid3hctx_idle;
-	struct timeval			ccid3hctx_t_last_win_count;
+	ktime_t				ccid3hctx_t_last_win_count;
 	struct timer_list		ccid3hctx_no_feedback_timer;
 	struct timeval			ccid3hctx_t_ld;
-	struct timeval			ccid3hctx_t_nom;
+	ktime_t				ccid3hctx_t_nom;
 	u32				ccid3hctx_delta;
 	struct list_head		ccid3hctx_hist;
 	struct ccid3_options_received	ccid3hctx_options_received;
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 372d7e7..515225f 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -1,8 +1,8 @@
 /*
  *  net/dccp/ccids/lib/loss_interval.c
  *
- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
+ *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+ *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -15,58 +15,38 @@
 #include <net/sock.h>
 #include "../../dccp.h"
 #include "loss_interval.h"
+#include "packet_history.h"
+#include "tfrc.h"
 
-struct dccp_li_hist *dccp_li_hist_new(const char *name)
+#define DCCP_LI_HIST_IVAL_F_LENGTH  8
+
+struct dccp_li_hist_entry {
+	struct list_head dccplih_node;
+	u64		 dccplih_seqno:48,
+			 dccplih_win_count:4;
+	u32		 dccplih_interval;
+};
+
+static struct kmem_cache *dccp_li_cachep __read_mostly;
+
+static inline struct dccp_li_hist_entry *dccp_li_hist_entry_new(const gfp_t prio)
 {
-	struct dccp_li_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
-	static const char dccp_li_hist_mask[] = "li_hist_%s";
-	char *slab_name;
-
-	if (hist == NULL)
-		goto out;
-
-	slab_name = kmalloc(strlen(name) + sizeof(dccp_li_hist_mask) - 1,
-			    GFP_ATOMIC);
-	if (slab_name == NULL)
-		goto out_free_hist;
-
-	sprintf(slab_name, dccp_li_hist_mask, name);
-	hist->dccplih_slab = kmem_cache_create(slab_name,
-					     sizeof(struct dccp_li_hist_entry),
-					       0, SLAB_HWCACHE_ALIGN,
-					       NULL, NULL);
-	if (hist->dccplih_slab == NULL)
-		goto out_free_slab_name;
-out:
-	return hist;
-out_free_slab_name:
-	kfree(slab_name);
-out_free_hist:
-	kfree(hist);
-	hist = NULL;
-	goto out;
+	return kmem_cache_alloc(dccp_li_cachep, prio);
 }
 
-EXPORT_SYMBOL_GPL(dccp_li_hist_new);
-
-void dccp_li_hist_delete(struct dccp_li_hist *hist)
+static inline void dccp_li_hist_entry_delete(struct dccp_li_hist_entry *entry)
 {
-	const char* name = kmem_cache_name(hist->dccplih_slab);
-
-	kmem_cache_destroy(hist->dccplih_slab);
-	kfree(name);
-	kfree(hist);
+	if (entry != NULL)
+		kmem_cache_free(dccp_li_cachep, entry);
 }
 
-EXPORT_SYMBOL_GPL(dccp_li_hist_delete);
-
-void dccp_li_hist_purge(struct dccp_li_hist *hist, struct list_head *list)
+void dccp_li_hist_purge(struct list_head *list)
 {
 	struct dccp_li_hist_entry *entry, *next;
 
 	list_for_each_entry_safe(entry, next, list, dccplih_node) {
 		list_del_init(&entry->dccplih_node);
-		kmem_cache_free(hist->dccplih_slab, entry);
+		kmem_cache_free(dccp_li_cachep, entry);
 	}
 }
 
@@ -118,16 +98,16 @@
 
 EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
 
-int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
-   struct list_head *list, const u64 seq_loss, const u8 win_loss)
+static int dccp_li_hist_interval_new(struct list_head *list,
+				     const u64 seq_loss, const u8 win_loss)
 {
 	struct dccp_li_hist_entry *entry;
 	int i;
 
 	for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) {
-		entry = dccp_li_hist_entry_new(hist, GFP_ATOMIC);
+		entry = dccp_li_hist_entry_new(GFP_ATOMIC);
 		if (entry == NULL) {
-			dccp_li_hist_purge(hist, list);
+			dccp_li_hist_purge(list);
 			DCCP_BUG("loss interval list entry is NULL");
 			return 0;
 		}
@@ -140,4 +120,176 @@
 	return 1;
 }
 
-EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new);
+/* calculate first loss interval
+ *
+ * returns estimated loss interval in usecs */
+static u32 dccp_li_calc_first_li(struct sock *sk,
+				 struct list_head *hist_list,
+				 struct timeval *last_feedback,
+				 u16 s, u32 bytes_recv,
+				 u32 previous_x_recv)
+{
+	struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
+	u32 x_recv, p;
+	suseconds_t rtt, delta;
+	struct timeval tstamp = { 0, 0 };
+	int interval = 0;
+	int win_count = 0;
+	int step = 0;
+	u64 fval;
+
+	list_for_each_entry_safe(entry, next, hist_list, dccphrx_node) {
+		if (dccp_rx_hist_entry_data_packet(entry)) {
+			tail = entry;
+
+			switch (step) {
+			case 0:
+				tstamp	  = entry->dccphrx_tstamp;
+				win_count = entry->dccphrx_ccval;
+				step = 1;
+				break;
+			case 1:
+				interval = win_count - entry->dccphrx_ccval;
+				if (interval < 0)
+					interval += TFRC_WIN_COUNT_LIMIT;
+				if (interval > 4)
+					goto found;
+				break;
+			}
+		}
+	}
+
+	if (unlikely(step == 0)) {
+		DCCP_WARN("%s(%p), packet history has no data packets!\n",
+			  dccp_role(sk), sk);
+		return ~0;
+	}
+
+	if (unlikely(interval == 0)) {
+		DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
+			  "Defaulting to 1\n", dccp_role(sk), sk);
+		interval = 1;
+	}
+found:
+	if (!tail) {
+		DCCP_CRIT("tail is null\n");
+		return ~0;
+	}
+
+	delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
+	DCCP_BUG_ON(delta < 0);
+
+	rtt = delta * 4 / interval;
+	dccp_pr_debug("%s(%p), approximated RTT to %dus\n",
+		      dccp_role(sk), sk, (int)rtt);
+
+	/*
+	 * Determine the length of the first loss interval via inverse lookup.
+	 * Assume that X_recv can be computed by the throughput equation
+	 *		    s
+	 *	X_recv = --------
+	 *		 R * fval
+	 * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
+	 */
+	if (rtt == 0) {			/* would result in divide-by-zero */
+		DCCP_WARN("RTT==0\n");
+		return ~0;
+	}
+
+	dccp_timestamp(sk, &tstamp);
+	delta = timeval_delta(&tstamp, last_feedback);
+	DCCP_BUG_ON(delta <= 0);
+
+	x_recv = scaled_div32(bytes_recv, delta);
+	if (x_recv == 0) {		/* would also trigger divide-by-zero */
+		DCCP_WARN("X_recv==0\n");
+		if (previous_x_recv == 0) {
+			DCCP_BUG("stored value of X_recv is zero");
+			return ~0;
+		}
+		x_recv = previous_x_recv;
+	}
+
+	fval = scaled_div(s, rtt);
+	fval = scaled_div32(fval, x_recv);
+	p = tfrc_calc_x_reverse_lookup(fval);
+
+	dccp_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
+		      "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
+
+	if (p == 0)
+		return ~0;
+	else
+		return 1000000 / p;
+}
+
+void dccp_li_update_li(struct sock *sk,
+		       struct list_head *li_hist_list,
+		       struct list_head *hist_list,
+		       struct timeval *last_feedback, u16 s, u32 bytes_recv,
+                       u32 previous_x_recv, u64 seq_loss, u8 win_loss)
+{
+	struct dccp_li_hist_entry *head;
+	u64 seq_temp;
+
+	if (list_empty(li_hist_list)) {
+		if (!dccp_li_hist_interval_new(li_hist_list, seq_loss,
+					       win_loss))
+			return;
+
+		head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
+				  dccplih_node);
+		head->dccplih_interval = dccp_li_calc_first_li(sk, hist_list,
+							       last_feedback,
+							       s, bytes_recv,
+							       previous_x_recv);
+	} else {
+		struct dccp_li_hist_entry *entry;
+		struct list_head *tail;
+
+		head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
+				  dccplih_node);
+		/* FIXME win count check removed as was wrong */
+		/* should make this check with receive history */
+		/* and compare there as per section 10.2 of RFC4342 */
+
+		/* new loss event detected */
+		/* calculate last interval length */
+		seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
+		entry = dccp_li_hist_entry_new(GFP_ATOMIC);
+
+		if (entry == NULL) {
+			DCCP_BUG("out of memory - can not allocate entry");
+			return;
+		}
+
+		list_add(&entry->dccplih_node, li_hist_list);
+
+		tail = li_hist_list->prev;
+		list_del(tail);
+		kmem_cache_free(dccp_li_cachep, tail);
+
+		/* Create the newest interval */
+		entry->dccplih_seqno = seq_loss;
+		entry->dccplih_interval = seq_temp;
+		entry->dccplih_win_count = win_loss;
+	}
+}
+
+EXPORT_SYMBOL_GPL(dccp_li_update_li);
+
+static __init int dccp_li_init(void)
+{
+	dccp_li_cachep = kmem_cache_create("dccp_li_hist",
+					   sizeof(struct dccp_li_hist_entry),
+					   0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+	return dccp_li_cachep == NULL ? -ENOBUFS : 0;
+}
+
+static __exit void dccp_li_exit(void)
+{
+	kmem_cache_destroy(dccp_li_cachep);
+}
+
+module_init(dccp_li_init);
+module_exit(dccp_li_exit);
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
index eb25701..906c806 100644
--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -3,8 +3,8 @@
 /*
  *  net/dccp/ccids/lib/loss_interval.h
  *
- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
+ *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+ *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
  *  This program is free software; you can redistribute it and/or modify it
@@ -14,44 +14,16 @@
  */
 
 #include <linux/list.h>
-#include <linux/slab.h>
 #include <linux/time.h>
 
-#define DCCP_LI_HIST_IVAL_F_LENGTH  8
-
-struct dccp_li_hist {
-	struct kmem_cache *dccplih_slab;
-};
-
-extern struct dccp_li_hist *dccp_li_hist_new(const char *name);
-extern void dccp_li_hist_delete(struct dccp_li_hist *hist);
-
-struct dccp_li_hist_entry {
-	struct list_head dccplih_node;
-	u64		 dccplih_seqno:48,
-			 dccplih_win_count:4;
-	u32		 dccplih_interval;
-};
-
-static inline struct dccp_li_hist_entry *
-		dccp_li_hist_entry_new(struct dccp_li_hist *hist,
-				       const gfp_t prio)
-{
-	return kmem_cache_alloc(hist->dccplih_slab, prio);
-}
-
-static inline void dccp_li_hist_entry_delete(struct dccp_li_hist *hist,
-					     struct dccp_li_hist_entry *entry)
-{
-	if (entry != NULL)
-		kmem_cache_free(hist->dccplih_slab, entry);
-}
-
-extern void dccp_li_hist_purge(struct dccp_li_hist *hist,
-			       struct list_head *list);
+extern void dccp_li_hist_purge(struct list_head *list);
 
 extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
 
-extern int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
-   struct list_head *list, const u64 seq_loss, const u8 win_loss);
+extern void dccp_li_update_li(struct sock *sk,
+			      struct list_head *li_hist_list,
+			      struct list_head *hist_list,
+			      struct timeval *last_feedback, u16 s,
+			      u32 bytes_recv, u32 previous_x_recv,
+			      u64 seq_loss, u8 win_loss);
 #endif /* _DCCP_LI_HIST_ */
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index d8ad27b..e2d74cd 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -184,7 +184,7 @@
 /*
  * 	Checksumming routines
  */
-static inline int dccp_csum_coverage(const struct sk_buff *skb)
+static inline unsigned int dccp_csum_coverage(const struct sk_buff *skb)
 {
 	const struct dccp_hdr* dh = dccp_hdr(skb);
 
@@ -195,7 +195,7 @@
 
 static inline void dccp_csum_outgoing(struct sk_buff *skb)
 {
-	int cov = dccp_csum_coverage(skb);
+	unsigned int cov = dccp_csum_coverage(skb);
 
 	if (cov >= skb->len)
 		dccp_hdr(skb)->dccph_cscov = 0;
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 31737cd..b158c66 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -253,17 +253,6 @@
 
 	if (dst == NULL) {
 		opt = np->opt;
-		if (opt == NULL &&
-		    np->rxopt.bits.osrcrt == 2 &&
-		    ireq6->pktopts) {
-			struct sk_buff *pktopts = ireq6->pktopts;
-			struct inet6_skb_parm *rxopt = IP6CB(pktopts);
-
-			if (rxopt->srcrt)
-				opt = ipv6_invert_rthdr(sk,
-			  (struct ipv6_rt_hdr *)(skb_network_header(pktopts) +
-						 rxopt->srcrt));
-		}
 
 		if (opt != NULL && opt->srcrt != NULL) {
 			const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
@@ -570,15 +559,6 @@
 	if (sk_acceptq_is_full(sk))
 		goto out_overflow;
 
-	if (np->rxopt.bits.osrcrt == 2 && opt == NULL && ireq6->pktopts) {
-		const struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts);
-
-		if (rxopt->srcrt)
-			opt = ipv6_invert_rthdr(sk,
-		   (struct ipv6_rt_hdr *)(skb_network_header(ireq6->pktopts) +
-					  rxopt->srcrt));
-	}
-
 	if (dst == NULL) {
 		struct in6_addr *final_p = NULL, final;
 		struct flowi fl;
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index bfa910b..ed76d4a 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -2304,7 +2304,7 @@
 	return 0;
 }
 
-static struct seq_operations dn_socket_seq_ops = {
+static const struct seq_operations dn_socket_seq_ops = {
 	.start	= dn_socket_seq_start,
 	.next	= dn_socket_seq_next,
 	.stop	= dn_socket_seq_stop,
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index ab41c18..fa6604f 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -461,7 +461,6 @@
 		if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) {
 			dn_dn2eth(mac_addr, ifa->ifa_local);
 			dev_mc_add(dev, mac_addr, ETH_ALEN, 0);
-			dev_mc_upload(dev);
 		}
 	}
 
@@ -1064,8 +1063,6 @@
 	else
 		dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0);
 
-	dev_mc_upload(dev);
-
 	dn_db->use_long = 1;
 
 	return 0;
@@ -1419,7 +1416,7 @@
 	return 0;
 }
 
-static struct seq_operations dn_dev_seq_ops = {
+static const struct seq_operations dn_dev_seq_ops = {
 	.start	= dn_dev_seq_start,
 	.next	= dn_dev_seq_next,
 	.stop	= dn_dev_seq_stop,
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 4bf066c..174d8a7 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -569,7 +569,7 @@
 			       NEIGH_SEQ_NEIGH_ONLY);
 }
 
-static struct seq_operations dn_neigh_seq_ops = {
+static const struct seq_operations dn_neigh_seq_ops = {
 	.start = dn_neigh_seq_start,
 	.next  = neigh_seq_next,
 	.stop  = neigh_seq_stop,
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index a8bf106..82622fb 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -1726,7 +1726,7 @@
 	return 0;
 }
 
-static struct seq_operations dn_rt_cache_seq_ops = {
+static const struct seq_operations dn_rt_cache_seq_ops = {
 	.start	= dn_rt_cache_seq_start,
 	.next	= dn_rt_cache_seq_next,
 	.stop	= dn_rt_cache_seq_stop,
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 0ac2524..1387e54 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -316,9 +316,10 @@
 EXPORT_SYMBOL(ether_setup);
 
 /**
- * alloc_etherdev - Allocates and sets up an Ethernet device
+ * alloc_etherdev_mq - Allocates and sets up an Ethernet device
  * @sizeof_priv: Size of additional driver-private structure to be allocated
  *	for this Ethernet device
+ * @queue_count: The number of queues this device has.
  *
  * Fill in the fields of the device structure with Ethernet-generic
  * values. Basically does everything except registering the device.
@@ -328,8 +329,8 @@
  * this private data area.
  */
 
-struct net_device *alloc_etherdev(int sizeof_priv)
+struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count)
 {
-	return alloc_netdev(sizeof_priv, "eth%d", ether_setup);
+	return alloc_netdev_mq(sizeof_priv, "eth%d", ether_setup, queue_count);
 }
-EXPORT_SYMBOL(alloc_etherdev);
+EXPORT_SYMBOL(alloc_etherdev_mq);
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index c308756..6398e6e 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -456,18 +456,13 @@
 ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
 	struct ieee80211softmac_network *add_net)
 {
-	struct list_head *list_ptr;
-	struct ieee80211softmac_network *softmac_net = NULL;
+	struct ieee80211softmac_network *softmac_net;
 
-	list_for_each(list_ptr, &mac->network_list) {
-		softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+	list_for_each_entry(softmac_net, &mac->network_list, list) {
 		if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
-			break;
-		else
-			softmac_net = NULL;
+			return;
 	}
-	if(softmac_net == NULL)
-		list_add(&(add_net->list), &mac->network_list);
+	list_add(&(add_net->list), &mac->network_list);
 }
 
 /* Add a network to the list, with locking */
@@ -506,16 +501,13 @@
 ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
 	u8 *bssid)
 {
-	struct list_head *list_ptr;
-	struct ieee80211softmac_network *softmac_net = NULL;
-	list_for_each(list_ptr, &mac->network_list) {
-		softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+	struct ieee80211softmac_network *softmac_net;
+
+	list_for_each_entry(softmac_net, &mac->network_list, list) {
 		if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
-			break;
-		else
-			softmac_net = NULL;
+			return softmac_net;
 	}
-	return softmac_net;
+	return NULL;
 }
 
 /* Get a network from the list by BSSID with locking */
@@ -537,11 +529,9 @@
 ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
 	struct ieee80211softmac_essid *essid)
 {
-	struct list_head *list_ptr;
-	struct ieee80211softmac_network *softmac_net = NULL;
+	struct ieee80211softmac_network *softmac_net;
 
-	list_for_each(list_ptr, &mac->network_list) {
-		softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+	list_for_each_entry(softmac_net, &mac->network_list, list) {
 		if (softmac_net->essid.len == essid->len &&
 			!memcmp(softmac_net->essid.data, essid->data, essid->len))
 			return softmac_net;
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 010fbb2..fb79097 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -116,48 +116,6 @@
 	  equal "cost" and chooses one of them in a non-deterministic fashion
 	  if a matching packet arrives.
 
-config IP_ROUTE_MULTIPATH_CACHED
-	bool "IP: equal cost multipath with caching support (EXPERIMENTAL)"
-	depends on IP_ROUTE_MULTIPATH
-	help
-	  Normally, equal cost multipath routing is not supported by the
-	  routing cache. If you say Y here, alternative routes are cached
-	  and on cache lookup a route is chosen in a configurable fashion.
-
-	  If unsure, say N.
-
-config IP_ROUTE_MULTIPATH_RR
-	tristate "MULTIPATH: round robin algorithm"
-	depends on IP_ROUTE_MULTIPATH_CACHED
-	help
-	  Multipath routes are chosen according to Round Robin
-
-config IP_ROUTE_MULTIPATH_RANDOM
-	tristate "MULTIPATH: random algorithm"
-	depends on IP_ROUTE_MULTIPATH_CACHED
-	help
-	  Multipath routes are chosen in a random fashion. Actually,
-	  there is no weight for a route. The advantage of this policy
-	  is that it is implemented stateless and therefore introduces only
-	  a very small delay.
-
-config IP_ROUTE_MULTIPATH_WRANDOM
-	tristate "MULTIPATH: weighted random algorithm"
-	depends on IP_ROUTE_MULTIPATH_CACHED
-	help
-	  Multipath routes are chosen in a weighted random fashion. 
-	  The per route weights are the weights visible via ip route 2. As the
-	  corresponding state management introduces some overhead routing delay
-	  is increased.
-
-config IP_ROUTE_MULTIPATH_DRR
-	tristate "MULTIPATH: interface round robin algorithm"
-	depends on IP_ROUTE_MULTIPATH_CACHED
-	help
-	  Connections are distributed in a round robin fashion over the
-	  available interfaces. This policy makes sense if the connections 
-	  should be primarily distributed on interfaces and not on routes. 
-
 config IP_ROUTE_VERBOSE
 	bool "IP: verbose route monitoring"
 	depends on IP_ADVANCED_ROUTER
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 4ff6c15..fbf1674 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -29,14 +29,9 @@
 obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
 obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
 obj-$(CONFIG_IP_PNP) += ipconfig.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_DRR) += multipath_drr.o
 obj-$(CONFIG_NETFILTER)	+= netfilter.o netfilter/
 obj-$(CONFIG_IP_VS) += ipvs/
 obj-$(CONFIG_INET_DIAG) += inet_diag.o 
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
 obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
 obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
 obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 041fba3..06c08e5 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1170,6 +1170,9 @@
 	int ihl;
 	int id;
 
+	if (!(features & NETIF_F_V4_CSUM))
+		features &= ~NETIF_F_SG;
+
 	if (unlikely(skb_shinfo(skb)->gso_type &
 		     ~(SKB_GSO_TCPV4 |
 		       SKB_GSO_UDP |
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 6da8ff5..7a23e59 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -339,3 +339,4 @@
 module_init(ah4_init);
 module_exit(ah4_fini);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_AH);
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 47c95e8..98767a4 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -481,3 +481,4 @@
 module_init(esp4_init);
 module_exit(esp4_fini);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_ESP);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 311d633..2eb909b 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -453,7 +453,6 @@
 	[RTA_MULTIPATH]		= { .len = sizeof(struct rtnexthop) },
 	[RTA_PROTOINFO]		= { .type = NLA_U32 },
 	[RTA_FLOW]		= { .type = NLA_U32 },
-	[RTA_MP_ALGO]		= { .type = NLA_U32 },
 };
 
 static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -515,9 +514,6 @@
 		case RTA_FLOW:
 			cfg->fc_flow = nla_get_u32(attr);
 			break;
-		case RTA_MP_ALGO:
-			cfg->fc_mp_alg = nla_get_u32(attr);
-			break;
 		case RTA_TABLE:
 			cfg->fc_table = nla_get_u32(attr);
 			break;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index bb94550..c434119 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -42,7 +42,6 @@
 #include <net/tcp.h>
 #include <net/sock.h>
 #include <net/ip_fib.h>
-#include <net/ip_mp_alg.h>
 #include <net/netlink.h>
 #include <net/nexthop.h>
 
@@ -697,13 +696,6 @@
 			goto err_inval;
 	}
 #endif
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	if (cfg->fc_mp_alg) {
-		if (cfg->fc_mp_alg < IP_MP_ALG_NONE ||
-		    cfg->fc_mp_alg > IP_MP_ALG_MAX)
-			goto err_inval;
-	}
-#endif
 
 	err = -ENOBUFS;
 	if (fib_info_cnt >= fib_hash_size) {
@@ -791,10 +783,6 @@
 #endif
 	}
 
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	fi->fib_mp_alg = cfg->fc_mp_alg;
-#endif
-
 	if (fib_props[cfg->fc_type].error) {
 		if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
 			goto err_inval;
@@ -940,10 +928,6 @@
 	res->type = fa->fa_type;
 	res->scope = fa->fa_scope;
 	res->fi = fa->fa_info;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	res->netmask = mask;
-	res->network = zone & inet_make_mask(prefixlen);
-#endif
 	atomic_inc(&res->fi->fib_clntref);
 	return 0;
 }
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 6328293..5c14ed6 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -809,7 +809,8 @@
 
 	max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen;
 
-	if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+	if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
+	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 		if (!new_skb) {
 			ip_rt_put(rt);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 34ea454..c9e2b5e 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -399,6 +399,10 @@
 	to->tc_index = from->tc_index;
 #endif
 	nf_copy(to, from);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	to->nf_trace = from->nf_trace;
+#endif
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	to->ipvs_property = from->ipvs_property;
 #endif
@@ -837,7 +841,7 @@
 	 */
 	if (transhdrlen &&
 	    length + fragheaderlen <= mtu &&
-	    rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
+	    rt->u.dst.dev->features & NETIF_F_V4_CSUM &&
 	    !exthdrlen)
 		csummode = CHECKSUM_PARTIAL;
 
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index ab86137..e787044 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -485,3 +485,4 @@
 MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173");
 MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
 
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_COMP);
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index ebd2f2d..3964372 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -595,7 +595,8 @@
 	 */
 	max_headroom = (LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr));
 
-	if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+	if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
+	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 		if (!new_skb) {
 			ip_rt_put(rt);
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index 15ad5dd..8d6901d 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -549,7 +549,7 @@
 	return 0;
 }
 
-static struct seq_operations ip_vs_app_seq_ops = {
+static const struct seq_operations ip_vs_app_seq_ops = {
 	.start = ip_vs_app_seq_start,
 	.next  = ip_vs_app_seq_next,
 	.stop  = ip_vs_app_seq_stop,
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index 7018f97..3b446b1 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -745,7 +745,7 @@
 	return 0;
 }
 
-static struct seq_operations ip_vs_conn_seq_ops = {
+static const struct seq_operations ip_vs_conn_seq_ops = {
 	.start = ip_vs_conn_seq_start,
 	.next  = ip_vs_conn_seq_next,
 	.stop  = ip_vs_conn_seq_stop,
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 68fe1d4..e1052bc 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -1783,7 +1783,7 @@
 	return 0;
 }
 
-static struct seq_operations ip_vs_info_seq_ops = {
+static const struct seq_operations ip_vs_info_seq_ops = {
 	.start = ip_vs_info_seq_start,
 	.next  = ip_vs_info_seq_next,
 	.stop  = ip_vs_info_seq_stop,
diff --git a/net/ipv4/multipath.c b/net/ipv4/multipath.c
deleted file mode 100644
index 4e9ca7c..0000000
--- a/net/ipv4/multipath.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* multipath.c: IPV4 multipath algorithm support.
- *
- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/spinlock.h>
-
-#include <net/ip_mp_alg.h>
-
-static DEFINE_SPINLOCK(alg_table_lock);
-struct ip_mp_alg_ops *ip_mp_alg_table[IP_MP_ALG_MAX + 1];
-
-int multipath_alg_register(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
-{
-	struct ip_mp_alg_ops **slot;
-	int err;
-
-	if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX ||
-	    !ops->mp_alg_select_route)
-		return -EINVAL;
-
-	spin_lock(&alg_table_lock);
-	slot = &ip_mp_alg_table[n];
-	if (*slot != NULL) {
-		err = -EBUSY;
-	} else {
-		*slot = ops;
-		err = 0;
-	}
-	spin_unlock(&alg_table_lock);
-
-	return err;
-}
-EXPORT_SYMBOL(multipath_alg_register);
-
-void multipath_alg_unregister(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
-{
-	struct ip_mp_alg_ops **slot;
-
-	if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX)
-		return;
-
-	spin_lock(&alg_table_lock);
-	slot = &ip_mp_alg_table[n];
-	if (*slot == ops)
-		*slot = NULL;
-	spin_unlock(&alg_table_lock);
-
-	synchronize_net();
-}
-EXPORT_SYMBOL(multipath_alg_unregister);
diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c
deleted file mode 100644
index b03c5ca..0000000
--- a/net/ipv4/multipath_drr.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- *              Device round robin policy for multipath.
- *
- *
- * Version:	$Id: multipath_drr.c,v 1.1.2.1 2004/09/16 07:42:34 elueck Exp $
- *
- * Authors:	Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_mp_alg.h>
-
-struct multipath_device {
-	int		ifi; /* interface index of device */
-	atomic_t	usecount;
-	int 		allocated;
-};
-
-#define MULTIPATH_MAX_DEVICECANDIDATES 10
-
-static struct multipath_device state[MULTIPATH_MAX_DEVICECANDIDATES];
-static DEFINE_SPINLOCK(state_lock);
-
-static int inline __multipath_findslot(void)
-{
-	int i;
-
-	for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
-		if (state[i].allocated == 0)
-			return i;
-	}
-	return -1;
-}
-
-static int inline __multipath_finddev(int ifindex)
-{
-	int i;
-
-	for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
-		if (state[i].allocated != 0 &&
-		    state[i].ifi == ifindex)
-			return i;
-	}
-	return -1;
-}
-
-static int drr_dev_event(struct notifier_block *this,
-			 unsigned long event, void *ptr)
-{
-	struct net_device *dev = ptr;
-	int devidx;
-
-	switch (event) {
-	case NETDEV_UNREGISTER:
-	case NETDEV_DOWN:
-		spin_lock_bh(&state_lock);
-
-		devidx = __multipath_finddev(dev->ifindex);
-		if (devidx != -1) {
-			state[devidx].allocated = 0;
-			state[devidx].ifi = 0;
-			atomic_set(&state[devidx].usecount, 0);
-		}
-
-		spin_unlock_bh(&state_lock);
-		break;
-	}
-
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block drr_dev_notifier = {
-	.notifier_call	= drr_dev_event,
-};
-
-
-static void drr_safe_inc(atomic_t *usecount)
-{
-	int n;
-
-	atomic_inc(usecount);
-
-	n = atomic_read(usecount);
-	if (n <= 0) {
-		int i;
-
-		spin_lock_bh(&state_lock);
-
-		for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++)
-			atomic_set(&state[i].usecount, 0);
-
-		spin_unlock_bh(&state_lock);
-	}
-}
-
-static void drr_select_route(const struct flowi *flp,
-			     struct rtable *first, struct rtable **rp)
-{
-	struct rtable *nh, *result, *cur_min;
-	int min_usecount = -1;
-	int devidx = -1;
-	int cur_min_devidx = -1;
-
-	/* 1. make sure all alt. nexthops have the same GC related data */
-	/* 2. determine the new candidate to be returned */
-	result = NULL;
-	cur_min = NULL;
-	for (nh = rcu_dereference(first); nh;
-	     nh = rcu_dereference(nh->u.dst.rt_next)) {
-		if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
-		    multipath_comparekeys(&nh->fl, flp)) {
-			int nh_ifidx = nh->u.dst.dev->ifindex;
-
-			nh->u.dst.lastuse = jiffies;
-			nh->u.dst.__use++;
-			if (result != NULL)
-				continue;
-
-			/* search for the output interface */
-
-			/* this is not SMP safe, only add/remove are
-			 * SMP safe as wrong usecount updates have no big
-			 * impact
-			 */
-			devidx = __multipath_finddev(nh_ifidx);
-			if (devidx == -1) {
-				/* add the interface to the array
-				 * SMP safe
-				 */
-				spin_lock_bh(&state_lock);
-
-				/* due to SMP: search again */
-				devidx = __multipath_finddev(nh_ifidx);
-				if (devidx == -1) {
-					/* add entry for device */
-					devidx = __multipath_findslot();
-					if (devidx == -1) {
-						/* unlikely but possible */
-						continue;
-					}
-
-					state[devidx].allocated = 1;
-					state[devidx].ifi = nh_ifidx;
-					atomic_set(&state[devidx].usecount, 0);
-					min_usecount = 0;
-				}
-
-				spin_unlock_bh(&state_lock);
-			}
-
-			if (min_usecount == 0) {
-				/* if the device has not been used it is
-				 * the primary target
-				 */
-				drr_safe_inc(&state[devidx].usecount);
-				result = nh;
-			} else {
-				int count =
-					atomic_read(&state[devidx].usecount);
-
-				if (min_usecount == -1 ||
-				    count < min_usecount) {
-					cur_min = nh;
-					cur_min_devidx = devidx;
-					min_usecount = count;
-				}
-			}
-		}
-	}
-
-	if (!result) {
-		if (cur_min) {
-			drr_safe_inc(&state[cur_min_devidx].usecount);
-			result = cur_min;
-		} else {
-			result = first;
-		}
-	}
-
-	*rp = result;
-}
-
-static struct ip_mp_alg_ops drr_ops = {
-	.mp_alg_select_route	=	drr_select_route,
-};
-
-static int __init drr_init(void)
-{
-	int err = register_netdevice_notifier(&drr_dev_notifier);
-
-	if (err)
-		return err;
-
-	err = multipath_alg_register(&drr_ops, IP_MP_ALG_DRR);
-	if (err)
-		goto fail;
-
-	return 0;
-
-fail:
-	unregister_netdevice_notifier(&drr_dev_notifier);
-	return err;
-}
-
-static void __exit drr_exit(void)
-{
-	unregister_netdevice_notifier(&drr_dev_notifier);
-	multipath_alg_unregister(&drr_ops, IP_MP_ALG_DRR);
-}
-
-module_init(drr_init);
-module_exit(drr_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_random.c b/net/ipv4/multipath_random.c
deleted file mode 100644
index c312785..0000000
--- a/net/ipv4/multipath_random.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- *              Random policy for multipath.
- *
- *
- * Version:	$Id: multipath_random.c,v 1.1.2.3 2004/09/21 08:42:11 elueck Exp $
- *
- * Authors:	Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_mp_alg.h>
-
-#define MULTIPATH_MAX_CANDIDATES 40
-
-static void random_select_route(const struct flowi *flp,
-				struct rtable *first,
-				struct rtable **rp)
-{
-	struct rtable *rt;
-	struct rtable *decision;
-	unsigned char candidate_count = 0;
-
-	/* count all candidate */
-	for (rt = rcu_dereference(first); rt;
-	     rt = rcu_dereference(rt->u.dst.rt_next)) {
-		if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
-		    multipath_comparekeys(&rt->fl, flp))
-			++candidate_count;
-	}
-
-	/* choose a random candidate */
-	decision = first;
-	if (candidate_count > 1) {
-		unsigned char i = 0;
-		unsigned char candidate_no = (unsigned char)
-			(random32() % candidate_count);
-
-		/* find chosen candidate and adjust GC data for all candidates
-		 * to ensure they stay in cache
-		 */
-		for (rt = first; rt; rt = rt->u.dst.rt_next) {
-			if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
-			    multipath_comparekeys(&rt->fl, flp)) {
-				rt->u.dst.lastuse = jiffies;
-
-				if (i == candidate_no)
-					decision = rt;
-
-				if (i >= candidate_count)
-					break;
-
-				i++;
-			}
-		}
-	}
-
-	decision->u.dst.__use++;
-	*rp = decision;
-}
-
-static struct ip_mp_alg_ops random_ops = {
-	.mp_alg_select_route	=	random_select_route,
-};
-
-static int __init random_init(void)
-{
-	return multipath_alg_register(&random_ops, IP_MP_ALG_RANDOM);
-}
-
-static void __exit random_exit(void)
-{
-	multipath_alg_unregister(&random_ops, IP_MP_ALG_RANDOM);
-}
-
-module_init(random_init);
-module_exit(random_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_rr.c b/net/ipv4/multipath_rr.c
deleted file mode 100644
index 0ad2252..0000000
--- a/net/ipv4/multipath_rr.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *              Round robin policy for multipath.
- *
- *
- * Version:	$Id: multipath_rr.c,v 1.1.2.2 2004/09/16 07:42:34 elueck Exp $
- *
- * Authors:	Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_mp_alg.h>
-
-static void rr_select_route(const struct flowi *flp,
-			    struct rtable *first, struct rtable **rp)
-{
-	struct rtable *nh, *result, *min_use_cand = NULL;
-	int min_use = -1;
-
-	/* 1. make sure all alt. nexthops have the same GC related data
-	 * 2. determine the new candidate to be returned
-	 */
-	result = NULL;
-	for (nh = rcu_dereference(first); nh;
-	     nh = rcu_dereference(nh->u.dst.rt_next)) {
-		if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
-		    multipath_comparekeys(&nh->fl, flp)) {
-			nh->u.dst.lastuse = jiffies;
-
-			if (min_use == -1 || nh->u.dst.__use < min_use) {
-				min_use = nh->u.dst.__use;
-				min_use_cand = nh;
-			}
-		}
-	}
-	result = min_use_cand;
-	if (!result)
-		result = first;
-
-	result->u.dst.__use++;
-	*rp = result;
-}
-
-static struct ip_mp_alg_ops rr_ops = {
-	.mp_alg_select_route	=	rr_select_route,
-};
-
-static int __init rr_init(void)
-{
-	return multipath_alg_register(&rr_ops, IP_MP_ALG_RR);
-}
-
-static void __exit rr_exit(void)
-{
-	multipath_alg_unregister(&rr_ops, IP_MP_ALG_RR);
-}
-
-module_init(rr_init);
-module_exit(rr_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c
deleted file mode 100644
index 57c5036..0000000
--- a/net/ipv4/multipath_wrandom.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- *              Weighted random policy for multipath.
- *
- *
- * Version:	$Id: multipath_wrandom.c,v 1.1.2.3 2004/09/22 07:51:40 elueck Exp $
- *
- * Authors:	Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_fib.h>
-#include <net/ip_mp_alg.h>
-
-#define MULTIPATH_STATE_SIZE 15
-
-struct multipath_candidate {
-	struct multipath_candidate	*next;
-	int				power;
-	struct rtable			*rt;
-};
-
-struct multipath_dest {
-	struct list_head	list;
-
-	const struct fib_nh	*nh_info;
-	__be32			netmask;
-	__be32			network;
-	unsigned char		prefixlen;
-
-	struct rcu_head		rcu;
-};
-
-struct multipath_bucket {
-	struct list_head	head;
-	spinlock_t		lock;
-};
-
-struct multipath_route {
-	struct list_head	list;
-
-	int			oif;
-	__be32			gw;
-	struct list_head	dests;
-
-	struct rcu_head		rcu;
-};
-
-/* state: primarily weight per route information */
-static struct multipath_bucket state[MULTIPATH_STATE_SIZE];
-
-static unsigned char __multipath_lookup_weight(const struct flowi *fl,
-					       const struct rtable *rt)
-{
-	const int state_idx = rt->idev->dev->ifindex % MULTIPATH_STATE_SIZE;
-	struct multipath_route *r;
-	struct multipath_route *target_route = NULL;
-	struct multipath_dest *d;
-	int weight = 1;
-
-	/* lookup the weight information for a certain route */
-	rcu_read_lock();
-
-	/* find state entry for gateway or add one if necessary */
-	list_for_each_entry_rcu(r, &state[state_idx].head, list) {
-		if (r->gw == rt->rt_gateway &&
-		    r->oif == rt->idev->dev->ifindex) {
-			target_route = r;
-			break;
-		}
-	}
-
-	if (!target_route) {
-		/* this should not happen... but we are prepared */
-		printk( KERN_CRIT"%s: missing state for gateway: %u and " \
-			"device %d\n", __FUNCTION__, rt->rt_gateway,
-			rt->idev->dev->ifindex);
-		goto out;
-	}
-
-	/* find state entry for destination */
-	list_for_each_entry_rcu(d, &target_route->dests, list) {
-		__be32 targetnetwork = fl->fl4_dst &
-			inet_make_mask(d->prefixlen);
-
-		if ((targetnetwork & d->netmask) == d->network) {
-			weight = d->nh_info->nh_weight;
-			goto out;
-		}
-	}
-
-out:
-	rcu_read_unlock();
-	return weight;
-}
-
-static void wrandom_init_state(void)
-{
-	int i;
-
-	for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
-		INIT_LIST_HEAD(&state[i].head);
-		spin_lock_init(&state[i].lock);
-	}
-}
-
-static void wrandom_select_route(const struct flowi *flp,
-				 struct rtable *first,
-				 struct rtable **rp)
-{
-	struct rtable *rt;
-	struct rtable *decision;
-	struct multipath_candidate *first_mpc = NULL;
-	struct multipath_candidate *mpc, *last_mpc = NULL;
-	int power = 0;
-	int last_power;
-	int selector;
-	const size_t size_mpc = sizeof(struct multipath_candidate);
-
-	/* collect all candidates and identify their weights */
-	for (rt = rcu_dereference(first); rt;
-	     rt = rcu_dereference(rt->u.dst.rt_next)) {
-		if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
-		    multipath_comparekeys(&rt->fl, flp)) {
-			struct multipath_candidate* mpc =
-				(struct multipath_candidate*)
-				kmalloc(size_mpc, GFP_ATOMIC);
-
-			if (!mpc)
-				return;
-
-			power += __multipath_lookup_weight(flp, rt) * 10000;
-
-			mpc->power = power;
-			mpc->rt = rt;
-			mpc->next = NULL;
-
-			if (!first_mpc)
-				first_mpc = mpc;
-			else
-				last_mpc->next = mpc;
-
-			last_mpc = mpc;
-		}
-	}
-
-	/* choose a weighted random candidate */
-	decision = first;
-	selector = random32() % power;
-	last_power = 0;
-
-	/* select candidate, adjust GC data and cleanup local state */
-	decision = first;
-	last_mpc = NULL;
-	for (mpc = first_mpc; mpc; mpc = mpc->next) {
-		mpc->rt->u.dst.lastuse = jiffies;
-		if (last_power <= selector && selector < mpc->power)
-			decision = mpc->rt;
-
-		last_power = mpc->power;
-		kfree(last_mpc);
-		last_mpc = mpc;
-	}
-
-	/* concurrent __multipath_flush may lead to !last_mpc */
-	kfree(last_mpc);
-
-	decision->u.dst.__use++;
-	*rp = decision;
-}
-
-static void wrandom_set_nhinfo(__be32 network,
-			       __be32 netmask,
-			       unsigned char prefixlen,
-			       const struct fib_nh *nh)
-{
-	const int state_idx = nh->nh_oif % MULTIPATH_STATE_SIZE;
-	struct multipath_route *r, *target_route = NULL;
-	struct multipath_dest *d, *target_dest = NULL;
-
-	/* store the weight information for a certain route */
-	spin_lock_bh(&state[state_idx].lock);
-
-	/* find state entry for gateway or add one if necessary */
-	list_for_each_entry_rcu(r, &state[state_idx].head, list) {
-		if (r->gw == nh->nh_gw && r->oif == nh->nh_oif) {
-			target_route = r;
-			break;
-		}
-	}
-
-	if (!target_route) {
-		const size_t size_rt = sizeof(struct multipath_route);
-		target_route = (struct multipath_route *)
-			kmalloc(size_rt, GFP_ATOMIC);
-
-		target_route->gw = nh->nh_gw;
-		target_route->oif = nh->nh_oif;
-		memset(&target_route->rcu, 0, sizeof(struct rcu_head));
-		INIT_LIST_HEAD(&target_route->dests);
-
-		list_add_rcu(&target_route->list, &state[state_idx].head);
-	}
-
-	/* find state entry for destination or add one if necessary */
-	list_for_each_entry_rcu(d, &target_route->dests, list) {
-		if (d->nh_info == nh) {
-			target_dest = d;
-			break;
-		}
-	}
-
-	if (!target_dest) {
-		const size_t size_dst = sizeof(struct multipath_dest);
-		target_dest = (struct multipath_dest*)
-			kmalloc(size_dst, GFP_ATOMIC);
-
-		target_dest->nh_info = nh;
-		target_dest->network = network;
-		target_dest->netmask = netmask;
-		target_dest->prefixlen = prefixlen;
-		memset(&target_dest->rcu, 0, sizeof(struct rcu_head));
-
-		list_add_rcu(&target_dest->list, &target_route->dests);
-	}
-	/* else: we already stored this info for another destination =>
-	 * we are finished
-	 */
-
-	spin_unlock_bh(&state[state_idx].lock);
-}
-
-static void __multipath_free(struct rcu_head *head)
-{
-	struct multipath_route *rt = container_of(head, struct multipath_route,
-						  rcu);
-	kfree(rt);
-}
-
-static void __multipath_free_dst(struct rcu_head *head)
-{
-	struct multipath_dest *dst = container_of(head,
-						  struct multipath_dest,
-						  rcu);
-	kfree(dst);
-}
-
-static void wrandom_flush(void)
-{
-	int i;
-
-	/* defere delete to all entries */
-	for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
-		struct multipath_route *r;
-
-		spin_lock_bh(&state[i].lock);
-		list_for_each_entry_rcu(r, &state[i].head, list) {
-			struct multipath_dest *d;
-			list_for_each_entry_rcu(d, &r->dests, list) {
-				list_del_rcu(&d->list);
-				call_rcu(&d->rcu,
-					 __multipath_free_dst);
-			}
-			list_del_rcu(&r->list);
-			call_rcu(&r->rcu,
-				 __multipath_free);
-		}
-
-		spin_unlock_bh(&state[i].lock);
-	}
-}
-
-static struct ip_mp_alg_ops wrandom_ops = {
-	.mp_alg_select_route	=	wrandom_select_route,
-	.mp_alg_flush		=	wrandom_flush,
-	.mp_alg_set_nhinfo	=	wrandom_set_nhinfo,
-};
-
-static int __init wrandom_init(void)
-{
-	wrandom_init_state();
-
-	return multipath_alg_register(&wrandom_ops, IP_MP_ALG_WRANDOM);
-}
-
-static void __exit wrandom_exit(void)
-{
-	multipath_alg_unregister(&wrandom_ops, IP_MP_ALG_WRANDOM);
-}
-
-module_init(wrandom_init);
-module_exit(wrandom_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 46509fa..fa97947 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -230,7 +230,7 @@
 	  To compile it as a module, choose M here.  If unsure, say N.
 
 config IP_NF_TARGET_SAME
-	tristate "SAME target support"
+	tristate "SAME target support (OBSOLETE)"
 	depends on NF_NAT
 	help
 	  This option adds a `SAME' target, which works like the standard SNAT
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index cae4121..e981232 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -224,7 +224,7 @@
 	static const char nulldevname[IFNAMSIZ];
 	unsigned int verdict = NF_DROP;
 	struct arphdr *arp;
-	int hotdrop = 0;
+	bool hotdrop = false;
 	struct arpt_entry *e, *back;
 	const char *indev, *outdev;
 	void *table_base;
@@ -1140,13 +1140,13 @@
 }
 
 /* The built-in targets: standard (NULL) and error. */
-static struct arpt_target arpt_standard_target = {
+static struct arpt_target arpt_standard_target __read_mostly = {
 	.name		= ARPT_STANDARD_TARGET,
 	.targetsize	= sizeof(int),
 	.family		= NF_ARP,
 };
 
-static struct arpt_target arpt_error_target = {
+static struct arpt_target arpt_error_target __read_mostly = {
 	.name		= ARPT_ERROR_TARGET,
 	.target		= arpt_error,
 	.targetsize	= ARPT_FUNCTION_MAXNAMELEN,
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index 6298d40..c4bdab4 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -65,7 +65,7 @@
 	return mangle->target;
 }
 
-static int
+static bool
 checkentry(const char *tablename, const void *e, const struct xt_target *target,
 	   void *targinfo, unsigned int hook_mask)
 {
@@ -73,15 +73,15 @@
 
 	if (mangle->flags & ~ARPT_MANGLE_MASK ||
 	    !(mangle->flags & ARPT_MANGLE_MASK))
-		return 0;
+		return false;
 
 	if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT &&
 	   mangle->target != ARPT_CONTINUE)
-		return 0;
-	return 1;
+		return false;
+	return true;
 }
 
-static struct arpt_target arpt_mangle_reg = {
+static struct arpt_target arpt_mangle_reg __read_mostly = {
 	.name		= "mangle",
 	.target		= target,
 	.targetsize	= sizeof(struct arpt_mangle),
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 9bacf1a0..e1b402c 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -152,20 +152,20 @@
 	return 1;
 }
 
-static inline int
+static inline bool
 ip_checkentry(const struct ipt_ip *ip)
 {
 	if (ip->flags & ~IPT_F_MASK) {
 		duprintf("Unknown flag bits set: %08X\n",
 			 ip->flags & ~IPT_F_MASK);
-		return 0;
+		return false;
 	}
 	if (ip->invflags & ~IPT_INV_MASK) {
 		duprintf("Unknown invflag bits set: %08X\n",
 			 ip->invflags & ~IPT_INV_MASK);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -183,19 +183,19 @@
 }
 
 static inline
-int do_match(struct ipt_entry_match *m,
-	     const struct sk_buff *skb,
-	     const struct net_device *in,
-	     const struct net_device *out,
-	     int offset,
-	     int *hotdrop)
+bool do_match(struct ipt_entry_match *m,
+	      const struct sk_buff *skb,
+	      const struct net_device *in,
+	      const struct net_device *out,
+	      int offset,
+	      bool *hotdrop)
 {
 	/* Stop iteration if it doesn't match */
 	if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
 				      offset, ip_hdrlen(skb), hotdrop))
-		return 1;
+		return true;
 	else
-		return 0;
+		return false;
 }
 
 static inline struct ipt_entry *
@@ -204,6 +204,112 @@
 	return (struct ipt_entry *)(base + offset);
 }
 
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ipt_ip *ip)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
+		if (((__u32 *)ip)[i])
+			return 0;
+
+	return 1;
+}
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+static const char *hooknames[] = {
+	[NF_IP_PRE_ROUTING]		= "PREROUTING",
+	[NF_IP_LOCAL_IN]		= "INPUT",
+	[NF_IP_FORWARD]			= "FORWARD",
+	[NF_IP_LOCAL_OUT]		= "OUTPUT",
+	[NF_IP_POST_ROUTING]		= "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+	NF_IP_TRACE_COMMENT_RULE,
+	NF_IP_TRACE_COMMENT_RETURN,
+	NF_IP_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+	[NF_IP_TRACE_COMMENT_RULE]	= "rule",
+	[NF_IP_TRACE_COMMENT_RETURN]	= "return",
+	[NF_IP_TRACE_COMMENT_POLICY]	= "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+	.type = NF_LOG_TYPE_LOG,
+	.u = {
+		.log = {
+			.level = 4,
+			.logflags = NF_LOG_MASK,
+		},
+	},
+};
+
+static inline int
+get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
+		      char *hookname, char **chainname,
+		      char **comment, unsigned int *rulenum)
+{
+	struct ipt_standard_target *t = (void *)ipt_get_target(s);
+
+	if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
+		/* Head of user chain: ERROR target with chainname */
+		*chainname = t->target.data;
+		(*rulenum) = 0;
+	} else if (s == e) {
+		(*rulenum)++;
+
+		if (s->target_offset == sizeof(struct ipt_entry)
+		   && strcmp(t->target.u.kernel.target->name,
+			     IPT_STANDARD_TARGET) == 0
+		   && t->verdict < 0
+		   && unconditional(&s->ip)) {
+			/* Tail of chains: STANDARD target (return/policy) */
+			*comment = *chainname == hookname
+				? (char *)comments[NF_IP_TRACE_COMMENT_POLICY]
+				: (char *)comments[NF_IP_TRACE_COMMENT_RETURN];
+		}
+		return 1;
+	} else
+		(*rulenum)++;
+
+	return 0;
+}
+
+static void trace_packet(struct sk_buff *skb,
+			 unsigned int hook,
+			 const struct net_device *in,
+			 const struct net_device *out,
+			 char *tablename,
+			 struct xt_table_info *private,
+			 struct ipt_entry *e)
+{
+	void *table_base;
+	struct ipt_entry *root;
+	char *hookname, *chainname, *comment;
+	unsigned int rulenum = 0;
+
+	table_base = (void *)private->entries[smp_processor_id()];
+	root = get_entry(table_base, private->hook_entry[hook]);
+
+	hookname = chainname = (char *)hooknames[hook];
+	comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE];
+
+	IPT_ENTRY_ITERATE(root,
+			  private->size - private->hook_entry[hook],
+			  get_chainname_rulenum,
+			  e, hookname, &chainname, &comment, &rulenum);
+
+	nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
+		      "TRACE: %s:%s:%s:%u ",
+		      tablename, chainname, comment, rulenum);
+}
+#endif
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ipt_do_table(struct sk_buff **pskb,
@@ -216,7 +322,7 @@
 	u_int16_t offset;
 	struct iphdr *ip;
 	u_int16_t datalen;
-	int hotdrop = 0;
+	bool hotdrop = false;
 	/* Initializing verdict to NF_DROP keeps gcc happy. */
 	unsigned int verdict = NF_DROP;
 	const char *indev, *outdev;
@@ -261,6 +367,14 @@
 
 			t = ipt_get_target(e);
 			IP_NF_ASSERT(t->u.kernel.target);
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+			/* The packet is traced: log it */
+			if (unlikely((*pskb)->nf_trace))
+				trace_packet(*pskb, hook, in, out,
+					     table->name, private, e);
+#endif
 			/* Standard target? */
 			if (!t->u.kernel.target->target) {
 				int v;
@@ -341,19 +455,6 @@
 #endif
 }
 
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ipt_ip *ip)
-{
-	unsigned int i;
-
-	for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
-		if (((__u32 *)ip)[i])
-			return 0;
-
-	return 1;
-}
-
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
@@ -2105,16 +2206,16 @@
 }
 
 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
-static inline int
+static inline bool
 icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
 		     u_int8_t type, u_int8_t code,
-		     int invert)
+		     bool invert)
 {
 	return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code))
 		^ invert;
 }
 
-static int
+static bool
 icmp_match(const struct sk_buff *skb,
 	   const struct net_device *in,
 	   const struct net_device *out,
@@ -2122,14 +2223,14 @@
 	   const void *matchinfo,
 	   int offset,
 	   unsigned int protoff,
-	   int *hotdrop)
+	   bool *hotdrop)
 {
 	struct icmphdr _icmph, *ic;
 	const struct ipt_icmp *icmpinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
 	if (ic == NULL) {
@@ -2137,8 +2238,8 @@
 		 * can't.  Hence, no choice but to drop.
 		 */
 		duprintf("Dropping evil ICMP tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return icmp_type_code_match(icmpinfo->type,
@@ -2149,7 +2250,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 icmp_checkentry(const char *tablename,
 	   const void *info,
 	   const struct xt_match *match,
@@ -2163,7 +2264,7 @@
 }
 
 /* The built-in targets: standard (NULL) and error. */
-static struct xt_target ipt_standard_target = {
+static struct xt_target ipt_standard_target __read_mostly = {
 	.name		= IPT_STANDARD_TARGET,
 	.targetsize	= sizeof(int),
 	.family		= AF_INET,
@@ -2174,7 +2275,7 @@
 #endif
 };
 
-static struct xt_target ipt_error_target = {
+static struct xt_target ipt_error_target __read_mostly = {
 	.name		= IPT_ERROR_TARGET,
 	.target		= ipt_error,
 	.targetsize	= IPT_FUNCTION_MAXNAMELEN,
@@ -2197,7 +2298,7 @@
 #endif
 };
 
-static struct xt_match icmp_matchstruct = {
+static struct xt_match icmp_matchstruct __read_mostly = {
 	.name		= "icmp",
 	.match		= icmp_match,
 	.matchsize	= sizeof(struct ipt_icmp),
@@ -2230,7 +2331,7 @@
 	if (ret < 0)
 		goto err5;
 
-	printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
+	printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
 	return 0;
 
 err5:
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 40e2734..dcc12b1 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -30,14 +30,6 @@
 
 #define CLUSTERIP_VERSION "0.8"
 
-#define DEBUG_CLUSTERIP
-
-#ifdef DEBUG_CLUSTERIP
-#define DEBUGP	printk
-#else
-#define DEBUGP
-#endif
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("iptables target for CLUSTERIP");
@@ -122,9 +114,8 @@
 	list_for_each(pos, &clusterip_configs) {
 		struct clusterip_config *c = list_entry(pos,
 					struct clusterip_config, list);
-		if (c->clusterip == clusterip) {
+		if (c->clusterip == clusterip)
 			return c;
-		}
 	}
 
 	return NULL;
@@ -155,9 +146,8 @@
 {
 	int n;
 
-	for (n = 0; n < i->num_local_nodes; n++) {
+	for (n = 0; n < i->num_local_nodes; n++)
 		set_bit(i->local_nodes[n] - 1, &c->local_nodes);
-	}
 }
 
 static struct clusterip_config *
@@ -220,27 +210,28 @@
 	return 0;
 }
 
-static int
+static bool
 clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum)
 {
 	if (nodenum == 0 ||
 	    nodenum > c->num_total_nodes)
-		return 1;
+		return true;
 
 	if (test_and_clear_bit(nodenum - 1, &c->local_nodes))
-		return 0;
+		return false;
 
-	return 1;
+	return true;
 }
 #endif
 
 static inline u_int32_t
-clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
+clusterip_hashfn(const struct sk_buff *skb,
+		 const struct clusterip_config *config)
 {
-	struct iphdr *iph = ip_hdr(skb);
+	const struct iphdr *iph = ip_hdr(skb);
 	unsigned long hashval;
 	u_int16_t sport, dport;
-	u_int16_t *ports;
+	const u_int16_t *ports;
 
 	switch (iph->protocol) {
 	case IPPROTO_TCP:
@@ -249,15 +240,14 @@
 	case IPPROTO_SCTP:
 	case IPPROTO_DCCP:
 	case IPPROTO_ICMP:
-		ports = (void *)iph+iph->ihl*4;
+		ports = (const void *)iph+iph->ihl*4;
 		sport = ports[0];
 		dport = ports[1];
 		break;
 	default:
-		if (net_ratelimit()) {
+		if (net_ratelimit())
 			printk(KERN_NOTICE "CLUSTERIP: unknown protocol `%u'\n",
 				iph->protocol);
-		}
 		sport = dport = 0;
 	}
 
@@ -285,11 +275,11 @@
 	}
 
 	/* node numbers are 1..n, not 0..n */
-	return ((hashval % config->num_total_nodes)+1);
+	return (hashval % config->num_total_nodes) + 1;
 }
 
 static inline int
-clusterip_responsible(struct clusterip_config *config, u_int32_t hash)
+clusterip_responsible(const struct clusterip_config *config, u_int32_t hash)
 {
 	return test_bit(hash - 1, &config->local_nodes);
 }
@@ -353,15 +343,15 @@
 			break;
 	}
 
-#ifdef DEBUG_CLUSTERP
+#ifdef DEBUG
 	DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 #endif
-	DEBUGP("hash=%u ct_hash=%u ", hash, ct->mark);
+	pr_debug("hash=%u ct_hash=%u ", hash, ct->mark);
 	if (!clusterip_responsible(cipinfo->config, hash)) {
-		DEBUGP("not responsible\n");
+		pr_debug("not responsible\n");
 		return NF_DROP;
 	}
-	DEBUGP("responsible\n");
+	pr_debug("responsible\n");
 
 	/* despite being received via linklayer multicast, this is
 	 * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */
@@ -370,7 +360,7 @@
 	return XT_CONTINUE;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *e_void,
 	   const struct xt_target *target,
@@ -387,50 +377,34 @@
 	    cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
 		printk(KERN_WARNING "CLUSTERIP: unknown mode `%u'\n",
 			cipinfo->hash_mode);
-		return 0;
+		return false;
 
 	}
 	if (e->ip.dmsk.s_addr != htonl(0xffffffff)
 	    || e->ip.dst.s_addr == 0) {
 		printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n");
-		return 0;
+		return false;
 	}
 
 	/* FIXME: further sanity checks */
 
 	config = clusterip_config_find_get(e->ip.dst.s_addr, 1);
-	if (config) {
-		if (cipinfo->config != NULL) {
-			/* Case A: This is an entry that gets reloaded, since
-			 * it still has a cipinfo->config pointer. Simply
-			 * increase the entry refcount and return */
-			if (cipinfo->config != config) {
-				printk(KERN_ERR "CLUSTERIP: Reloaded entry "
-				       "has invalid config pointer!\n");
-				return 0;
-			}
-		} else {
-			/* Case B: This is a new rule referring to an existing
-			 * clusterip config. */
-			cipinfo->config = config;
-		}
-	} else {
-		/* Case C: This is a completely new clusterip config */
+	if (!config) {
 		if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
 			printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr));
-			return 0;
+			return false;
 		} else {
 			struct net_device *dev;
 
 			if (e->ip.iniface[0] == '\0') {
 				printk(KERN_WARNING "CLUSTERIP: Please specify an interface name\n");
-				return 0;
+				return false;
 			}
 
 			dev = dev_get_by_name(e->ip.iniface);
 			if (!dev) {
 				printk(KERN_WARNING "CLUSTERIP: no such interface %s\n", e->ip.iniface);
-				return 0;
+				return false;
 			}
 
 			config = clusterip_config_init(cipinfo,
@@ -438,20 +412,20 @@
 			if (!config) {
 				printk(KERN_WARNING "CLUSTERIP: cannot allocate config\n");
 				dev_put(dev);
-				return 0;
+				return false;
 			}
 			dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0);
 		}
-		cipinfo->config = config;
 	}
+	cipinfo->config = config;
 
 	if (nf_ct_l3proto_try_module_get(target->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", target->family);
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
 /* drop reference count of cluster config when rule is deleted */
@@ -468,13 +442,30 @@
 	nf_ct_l3proto_module_put(target->family);
 }
 
-static struct xt_target clusterip_tgt = {
+#ifdef CONFIG_COMPAT
+struct compat_ipt_clusterip_tgt_info
+{
+	u_int32_t	flags;
+	u_int8_t	clustermac[6];
+	u_int16_t	num_total_nodes;
+	u_int16_t	num_local_nodes;
+	u_int16_t	local_nodes[CLUSTERIP_MAX_NODES];
+	u_int32_t	hash_mode;
+	u_int32_t	hash_initval;
+	compat_uptr_t	config;
+};
+#endif /* CONFIG_COMPAT */
+
+static struct xt_target clusterip_tgt __read_mostly = {
 	.name		= "CLUSTERIP",
 	.family		= AF_INET,
 	.target		= target,
-	.targetsize	= sizeof(struct ipt_clusterip_tgt_info),
 	.checkentry	= checkentry,
 	.destroy	= destroy,
+	.targetsize	= sizeof(struct ipt_clusterip_tgt_info),
+#ifdef CONFIG_COMPAT
+	.compatsize	= sizeof(struct compat_ipt_clusterip_tgt_info),
+#endif /* CONFIG_COMPAT */
 	.me		= THIS_MODULE
 };
 
@@ -491,7 +482,7 @@
 	__be32 dst_ip;
 } __attribute__ ((packed));
 
-#ifdef CLUSTERIP_DEBUG
+#ifdef DEBUG
 static void arp_print(struct arp_payload *payload)
 {
 #define HBUFFERLEN 30
@@ -547,8 +538,9 @@
 	 * this wouldn't work, since we didn't subscribe the mcast group on
 	 * other interfaces */
 	if (c->dev != out) {
-		DEBUGP("CLUSTERIP: not mangling arp reply on different "
-		       "interface: cip'%s'-skb'%s'\n", c->dev->name, out->name);
+		pr_debug("CLUSTERIP: not mangling arp reply on different "
+			 "interface: cip'%s'-skb'%s'\n",
+			 c->dev->name, out->name);
 		clusterip_config_put(c);
 		return NF_ACCEPT;
 	}
@@ -556,8 +548,8 @@
 	/* mangle reply hardware address */
 	memcpy(payload->src_hw, c->clustermac, arp->ar_hln);
 
-#ifdef CLUSTERIP_DEBUG
-	DEBUGP(KERN_DEBUG "CLUSTERIP mangled arp reply: ");
+#ifdef DEBUG
+	pr_debug(KERN_DEBUG "CLUSTERIP mangled arp reply: ");
 	arp_print(payload);
 #endif
 
@@ -647,7 +639,7 @@
 	return 0;
 }
 
-static struct seq_operations clusterip_seq_ops = {
+static const struct seq_operations clusterip_seq_ops = {
 	.start	= clusterip_seq_start,
 	.next	= clusterip_seq_next,
 	.stop	= clusterip_seq_stop,
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 918ca92..f1253bd 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -24,8 +24,8 @@
 MODULE_DESCRIPTION("iptables ECN modification module");
 
 /* set ECT codepoint from IP header.
- * 	return 0 if there was an error. */
-static inline int
+ * 	return false if there was an error. */
+static inline bool
 set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
 {
 	struct iphdr *iph = ip_hdr(*pskb);
@@ -33,18 +33,18 @@
 	if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
 		__u8 oldtos;
 		if (!skb_make_writable(pskb, sizeof(struct iphdr)))
-			return 0;
+			return false;
 		iph = ip_hdr(*pskb);
 		oldtos = iph->tos;
 		iph->tos &= ~IPT_ECN_IP_MASK;
 		iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
 		nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
 	}
-	return 1;
+	return true;
 }
 
-/* Return 0 if there was an error. */
-static inline int
+/* Return false if there was an error. */
+static inline bool
 set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
 {
 	struct tcphdr _tcph, *tcph;
@@ -54,16 +54,16 @@
 	tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
 				  sizeof(_tcph), &_tcph);
 	if (!tcph)
-		return 0;
+		return false;
 
 	if ((!(einfo->operation & IPT_ECN_OP_SET_ECE) ||
 	     tcph->ece == einfo->proto.tcp.ece) &&
-	    ((!(einfo->operation & IPT_ECN_OP_SET_CWR) ||
-	     tcph->cwr == einfo->proto.tcp.cwr)))
-		return 1;
+	    (!(einfo->operation & IPT_ECN_OP_SET_CWR) ||
+	     tcph->cwr == einfo->proto.tcp.cwr))
+		return true;
 
 	if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
-		return 0;
+		return false;
 	tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb);
 
 	oldval = ((__be16 *)tcph)[6];
@@ -74,7 +74,7 @@
 
 	nf_proto_csum_replace2(&tcph->check, *pskb,
 				oldval, ((__be16 *)tcph)[6], 0);
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -99,7 +99,7 @@
 	return XT_CONTINUE;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *e_void,
 	   const struct xt_target *target,
@@ -112,23 +112,23 @@
 	if (einfo->operation & IPT_ECN_OP_MASK) {
 		printk(KERN_WARNING "ECN: unsupported ECN operation %x\n",
 			einfo->operation);
-		return 0;
+		return false;
 	}
 	if (einfo->ip_ect & ~IPT_ECN_IP_MASK) {
 		printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n",
 			einfo->ip_ect);
-		return 0;
+		return false;
 	}
 	if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR))
 	    && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) {
 		printk(KERN_WARNING "ECN: cannot use TCP operations on a "
 		       "non-tcp rule\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ipt_ecn_reg = {
+static struct xt_target ipt_ecn_reg __read_mostly = {
 	.name		= "ECN",
 	.family		= AF_INET,
 	.target		= target,
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index a42c5cd..5937ad1 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -27,12 +27,6 @@
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("iptables syslog logging module");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Use lock to serialize, so printks don't overlap */
 static DEFINE_SPINLOCK(log_lock);
 
@@ -41,7 +35,8 @@
 			const struct sk_buff *skb,
 			unsigned int iphoff)
 {
-	struct iphdr _iph, *ih;
+	struct iphdr _iph;
+	const struct iphdr *ih;
 	unsigned int logflags;
 
 	if (info->type == NF_LOG_TYPE_LOG)
@@ -100,7 +95,8 @@
 
 	switch (ih->protocol) {
 	case IPPROTO_TCP: {
-		struct tcphdr _tcph, *th;
+		struct tcphdr _tcph;
+		const struct tcphdr *th;
 
 		/* Max length: 10 "PROTO=TCP " */
 		printk("PROTO=TCP ");
@@ -151,7 +147,7 @@
 		if ((logflags & IPT_LOG_TCPOPT)
 		    && th->doff * 4 > sizeof(struct tcphdr)) {
 			unsigned char _opt[4 * 15 - sizeof(struct tcphdr)];
-			unsigned char *op;
+			const unsigned char *op;
 			unsigned int i, optsize;
 
 			optsize = th->doff * 4 - sizeof(struct tcphdr);
@@ -173,7 +169,8 @@
 	}
 	case IPPROTO_UDP:
 	case IPPROTO_UDPLITE: {
-		struct udphdr _udph, *uh;
+		struct udphdr _udph;
+		const struct udphdr *uh;
 
 		if (ih->protocol == IPPROTO_UDP)
 			/* Max length: 10 "PROTO=UDP "     */
@@ -200,7 +197,8 @@
 		break;
 	}
 	case IPPROTO_ICMP: {
-		struct icmphdr _icmph, *ich;
+		struct icmphdr _icmph;
+		const struct icmphdr *ich;
 		static const size_t required_len[NR_ICMP_TYPES+1]
 			= { [ICMP_ECHOREPLY] = 4,
 			    [ICMP_DEST_UNREACH]
@@ -285,7 +283,8 @@
 	}
 	/* Max Length */
 	case IPPROTO_AH: {
-		struct ip_auth_hdr _ahdr, *ah;
+		struct ip_auth_hdr _ahdr;
+		const struct ip_auth_hdr *ah;
 
 		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
@@ -307,7 +306,8 @@
 		break;
 	}
 	case IPPROTO_ESP: {
-		struct ip_esp_hdr _esph, *eh;
+		struct ip_esp_hdr _esph;
+		const struct ip_esp_hdr *eh;
 
 		/* Max length: 10 "PROTO=ESP " */
 		printk("PROTO=ESP ");
@@ -385,11 +385,13 @@
 	       out ? out->name : "");
 #ifdef CONFIG_BRIDGE_NETFILTER
 	if (skb->nf_bridge) {
-		struct net_device *physindev = skb->nf_bridge->physindev;
-		struct net_device *physoutdev = skb->nf_bridge->physoutdev;
+		const struct net_device *physindev;
+		const struct net_device *physoutdev;
 
+		physindev = skb->nf_bridge->physindev;
 		if (physindev && in != physindev)
 			printk("PHYSIN=%s ", physindev->name);
+		physoutdev = skb->nf_bridge->physoutdev;
 		if (physoutdev && out != physoutdev)
 			printk("PHYSOUT=%s ", physoutdev->name);
 	}
@@ -435,27 +437,27 @@
 	return XT_CONTINUE;
 }
 
-static int ipt_log_checkentry(const char *tablename,
-			      const void *e,
-			      const struct xt_target *target,
-			      void *targinfo,
-			      unsigned int hook_mask)
+static bool ipt_log_checkentry(const char *tablename,
+			       const void *e,
+			       const struct xt_target *target,
+			       void *targinfo,
+			       unsigned int hook_mask)
 {
 	const struct ipt_log_info *loginfo = targinfo;
 
 	if (loginfo->level >= 8) {
-		DEBUGP("LOG: level %u >= 8\n", loginfo->level);
-		return 0;
+		pr_debug("LOG: level %u >= 8\n", loginfo->level);
+		return false;
 	}
 	if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
-		DEBUGP("LOG: prefix term %i\n",
-		       loginfo->prefix[sizeof(loginfo->prefix)-1]);
-		return 0;
+		pr_debug("LOG: prefix term %i\n",
+			 loginfo->prefix[sizeof(loginfo->prefix)-1]);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ipt_log_reg = {
+static struct xt_target ipt_log_reg __read_mostly = {
 	.name		= "LOG",
 	.family		= AF_INET,
 	.target		= ipt_log_target,
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index d4f2d77..7c4e4be 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -27,17 +27,11 @@
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("iptables MASQUERADE target module");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Lock protects masq region inside conntrack */
 static DEFINE_RWLOCK(masq_lock);
 
 /* FIXME: Multiple targets. --RR */
-static int
+static bool
 masquerade_check(const char *tablename,
 		 const void *e,
 		 const struct xt_target *target,
@@ -47,14 +41,14 @@
 	const struct nf_nat_multi_range_compat *mr = targinfo;
 
 	if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
-		DEBUGP("masquerade_check: bad MAP_IPS.\n");
-		return 0;
+		pr_debug("masquerade_check: bad MAP_IPS.\n");
+		return false;
 	}
 	if (mr->rangesize != 1) {
-		DEBUGP("masquerade_check: bad rangesize %u.\n", mr->rangesize);
-		return 0;
+		pr_debug("masquerade_check: bad rangesize %u\n", mr->rangesize);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -70,7 +64,7 @@
 	enum ip_conntrack_info ctinfo;
 	struct nf_nat_range newrange;
 	const struct nf_nat_multi_range_compat *mr;
-	struct rtable *rt;
+	const struct rtable *rt;
 	__be32 newsrc;
 
 	NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
@@ -109,10 +103,10 @@
 	return nf_nat_setup_info(ct, &newrange, hooknum);
 }
 
-static inline int
+static int
 device_cmp(struct nf_conn *i, void *ifindex)
 {
-	struct nf_conn_nat *nat = nfct_nat(i);
+	const struct nf_conn_nat *nat = nfct_nat(i);
 	int ret;
 
 	if (!nat)
@@ -129,7 +123,7 @@
 			     unsigned long event,
 			     void *ptr)
 {
-	struct net_device *dev = ptr;
+	const struct net_device *dev = ptr;
 
 	if (event == NETDEV_DOWN) {
 		/* Device was downed.  Search entire table for
@@ -147,7 +141,7 @@
 			   unsigned long event,
 			   void *ptr)
 {
-	struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
+	const struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
 
 	if (event == NETDEV_DOWN) {
 		/* IP address was deleted.  Search entire table for
@@ -169,7 +163,7 @@
 	.notifier_call	= masq_inet_event,
 };
 
-static struct xt_target masquerade = {
+static struct xt_target masquerade __read_mostly = {
 	.name		= "MASQUERADE",
 	.family		= AF_INET,
 	.target		= masquerade_target,
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index 068c69b..41a011d 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -18,18 +18,11 @@
 #include <linux/netfilter/x_tables.h>
 #include <net/netfilter/nf_nat_rule.h>
 
-#define MODULENAME "NETMAP"
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>");
 MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-static int
+static bool
 check(const char *tablename,
       const void *e,
       const struct xt_target *target,
@@ -39,14 +32,14 @@
 	const struct nf_nat_multi_range_compat *mr = targinfo;
 
 	if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
-		DEBUGP(MODULENAME":check: bad MAP_IPS.\n");
-		return 0;
+		pr_debug("NETMAP:check: bad MAP_IPS.\n");
+		return false;
 	}
 	if (mr->rangesize != 1) {
-		DEBUGP(MODULENAME":check: bad rangesize %u.\n", mr->rangesize);
-		return 0;
+		pr_debug("NETMAP:check: bad rangesize %u.\n", mr->rangesize);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -85,8 +78,8 @@
 	return nf_nat_setup_info(ct, &newrange, hooknum);
 }
 
-static struct xt_target target_module = {
-	.name 		= MODULENAME,
+static struct xt_target target_module __read_mostly = {
+	.name 		= "NETMAP",
 	.family		= AF_INET,
 	.target 	= target,
 	.targetsize	= sizeof(struct nf_nat_multi_range_compat),
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 68cc76a1..6ac7a23 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -25,14 +25,8 @@
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("iptables REDIRECT target module");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* FIXME: Take multiple ranges --RR */
-static int
+static bool
 redirect_check(const char *tablename,
 	       const void *e,
 	       const struct xt_target *target,
@@ -42,14 +36,14 @@
 	const struct nf_nat_multi_range_compat *mr = targinfo;
 
 	if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
-		DEBUGP("redirect_check: bad MAP_IPS.\n");
-		return 0;
+		pr_debug("redirect_check: bad MAP_IPS.\n");
+		return false;
 	}
 	if (mr->rangesize != 1) {
-		DEBUGP("redirect_check: bad rangesize %u.\n", mr->rangesize);
-		return 0;
+		pr_debug("redirect_check: bad rangesize %u.\n", mr->rangesize);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -101,7 +95,7 @@
 	return nf_nat_setup_info(ct, &newrange, hooknum);
 }
 
-static struct xt_target redirect_reg = {
+static struct xt_target redirect_reg __read_mostly = {
 	.name		= "REDIRECT",
 	.family		= AF_INET,
 	.target		= redirect_target,
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 9041e07..cb038c8 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -31,12 +31,6 @@
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("iptables REJECT target module");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Send RST reply */
 static void send_reset(struct sk_buff *oldskb, int hook)
 {
@@ -122,7 +116,7 @@
 	tcph->check = 0;
 	tcph->check = tcp_v4_check(sizeof(struct tcphdr),
 				   niph->saddr, niph->daddr,
-				   csum_partial((char *)tcph,
+				   csum_partial(tcph,
 						sizeof(struct tcphdr), 0));
 
 	/* Set DF, id = 0 */
@@ -217,30 +211,30 @@
 	return NF_DROP;
 }
 
-static int check(const char *tablename,
-		 const void *e_void,
-		 const struct xt_target *target,
-		 void *targinfo,
-		 unsigned int hook_mask)
+static bool check(const char *tablename,
+		  const void *e_void,
+		  const struct xt_target *target,
+		  void *targinfo,
+		  unsigned int hook_mask)
 {
 	const struct ipt_reject_info *rejinfo = targinfo;
 	const struct ipt_entry *e = e_void;
 
 	if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
-		printk("REJECT: ECHOREPLY no longer supported.\n");
-		return 0;
+		printk("ipt_REJECT: ECHOREPLY no longer supported.\n");
+		return false;
 	} else if (rejinfo->with == IPT_TCP_RESET) {
 		/* Must specify that it's a TCP packet */
 		if (e->ip.proto != IPPROTO_TCP
 		    || (e->ip.invflags & XT_INV_PROTO)) {
-			DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n");
-			return 0;
+			printk("ipt_REJECT: TCP_RESET invalid for non-tcp\n");
+			return false;
 		}
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ipt_reject_reg = {
+static struct xt_target ipt_reject_reg __read_mostly = {
 	.name		= "REJECT",
 	.family		= AF_INET,
 	.target		= reject,
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 511e5ff..97641f1 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -27,13 +27,7 @@
 MODULE_AUTHOR("Martin Josefsson <gandalf@wlug.westbo.se>");
 MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-static int
+static bool
 same_check(const char *tablename,
 	      const void *e,
 	      const struct xt_target *target,
@@ -46,58 +40,56 @@
 	mr->ipnum = 0;
 
 	if (mr->rangesize < 1) {
-		DEBUGP("same_check: need at least one dest range.\n");
-		return 0;
+		pr_debug("same_check: need at least one dest range.\n");
+		return false;
 	}
 	if (mr->rangesize > IPT_SAME_MAX_RANGE) {
-		DEBUGP("same_check: too many ranges specified, maximum "
-				"is %u ranges\n",
-				IPT_SAME_MAX_RANGE);
-		return 0;
+		pr_debug("same_check: too many ranges specified, maximum "
+			 "is %u ranges\n", IPT_SAME_MAX_RANGE);
+		return false;
 	}
 	for (count = 0; count < mr->rangesize; count++) {
 		if (ntohl(mr->range[count].min_ip) >
 				ntohl(mr->range[count].max_ip)) {
-			DEBUGP("same_check: min_ip is larger than max_ip in "
-				"range `%u.%u.%u.%u-%u.%u.%u.%u'.\n",
-				NIPQUAD(mr->range[count].min_ip),
-				NIPQUAD(mr->range[count].max_ip));
-			return 0;
+			pr_debug("same_check: min_ip is larger than max_ip in "
+				 "range `%u.%u.%u.%u-%u.%u.%u.%u'.\n",
+				 NIPQUAD(mr->range[count].min_ip),
+				 NIPQUAD(mr->range[count].max_ip));
+			return false;
 		}
 		if (!(mr->range[count].flags & IP_NAT_RANGE_MAP_IPS)) {
-			DEBUGP("same_check: bad MAP_IPS.\n");
-			return 0;
+			pr_debug("same_check: bad MAP_IPS.\n");
+			return false;
 		}
 		rangeip = (ntohl(mr->range[count].max_ip) -
 					ntohl(mr->range[count].min_ip) + 1);
 		mr->ipnum += rangeip;
 
-		DEBUGP("same_check: range %u, ipnum = %u\n", count, rangeip);
+		pr_debug("same_check: range %u, ipnum = %u\n", count, rangeip);
 	}
-	DEBUGP("same_check: total ipaddresses = %u\n", mr->ipnum);
+	pr_debug("same_check: total ipaddresses = %u\n", mr->ipnum);
 
 	mr->iparray = kmalloc((sizeof(u_int32_t) * mr->ipnum), GFP_KERNEL);
 	if (!mr->iparray) {
-		DEBUGP("same_check: Couldn't allocate %u bytes "
-			"for %u ipaddresses!\n",
-			(sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
-		return 0;
+		pr_debug("same_check: Couldn't allocate %Zu bytes "
+			 "for %u ipaddresses!\n",
+			 (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
+		return false;
 	}
-	DEBUGP("same_check: Allocated %u bytes for %u ipaddresses.\n",
-			(sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
+	pr_debug("same_check: Allocated %Zu bytes for %u ipaddresses.\n",
+		 (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
 
 	for (count = 0; count < mr->rangesize; count++) {
 		for (countess = ntohl(mr->range[count].min_ip);
 				countess <= ntohl(mr->range[count].max_ip);
 					countess++) {
 			mr->iparray[index] = countess;
-			DEBUGP("same_check: Added ipaddress `%u.%u.%u.%u' "
-				"in index %u.\n",
-				HIPQUAD(countess), index);
+			pr_debug("same_check: Added ipaddress `%u.%u.%u.%u' "
+				 "in index %u.\n", HIPQUAD(countess), index);
 			index++;
 		}
 	}
-	return 1;
+	return true;
 }
 
 static void
@@ -107,8 +99,8 @@
 
 	kfree(mr->iparray);
 
-	DEBUGP("same_destroy: Deallocated %u bytes for %u ipaddresses.\n",
-			(sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
+	pr_debug("same_destroy: Deallocated %Zu bytes for %u ipaddresses.\n",
+		 (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
 }
 
 static unsigned int
@@ -146,10 +138,9 @@
 
 	new_ip = htonl(same->iparray[aindex]);
 
-	DEBUGP("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, "
-			"new src=%u.%u.%u.%u\n",
-			NIPQUAD(t->src.ip), NIPQUAD(t->dst.ip),
-			NIPQUAD(new_ip));
+	pr_debug("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, "
+		 "new src=%u.%u.%u.%u\n",
+		 NIPQUAD(t->src.u3.ip), NIPQUAD(t->dst.u3.ip), NIPQUAD(new_ip));
 
 	/* Transfer from original range. */
 	newrange = ((struct nf_nat_range)
@@ -161,7 +152,7 @@
 	return nf_nat_setup_info(ct, &newrange, hooknum);
 }
 
-static struct xt_target same_reg = {
+static struct xt_target same_reg __read_mostly = {
 	.name		= "SAME",
 	.family		= AF_INET,
 	.target		= same_target,
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 0ad02f2..25f5d0b 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -43,7 +43,7 @@
 	return XT_CONTINUE;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *e_void,
 	   const struct xt_target *target,
@@ -58,12 +58,12 @@
 	    && tos != IPTOS_MINCOST
 	    && tos != IPTOS_NORMALSVC) {
 		printk(KERN_WARNING "TOS: bad tos value %#x\n", tos);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ipt_tos_reg = {
+static struct xt_target ipt_tos_reg __read_mostly = {
 	.name		= "TOS",
 	.family		= AF_INET,
 	.target		= target,
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index a991ec7..2b54e7b 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -62,25 +62,25 @@
 	return XT_CONTINUE;
 }
 
-static int ipt_ttl_checkentry(const char *tablename,
+static bool ipt_ttl_checkentry(const char *tablename,
 		const void *e,
 		const struct xt_target *target,
 		void *targinfo,
 		unsigned int hook_mask)
 {
-	struct ipt_TTL_info *info = targinfo;
+	const struct ipt_TTL_info *info = targinfo;
 
 	if (info->mode > IPT_TTL_MAXMODE) {
 		printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
 			info->mode);
-		return 0;
+		return false;
 	}
-	if ((info->mode != IPT_TTL_SET) && (info->ttl == 0))
-		return 0;
-	return 1;
+	if (info->mode != IPT_TTL_SET && info->ttl == 0)
+		return false;
+	return true;
 }
 
-static struct xt_target ipt_TTL = {
+static struct xt_target ipt_TTL __read_mostly = {
 	.name 		= "TTL",
 	.family		= AF_INET,
 	.target 	= ipt_ttl_target,
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 23b607b..6ca43e4 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -55,13 +55,6 @@
 #define ULOG_NL_EVENT		111		/* Harald's favorite number */
 #define ULOG_MAXNLGROUPS	32		/* numer of nlgroups */
 
-#if 0
-#define DEBUGP(format, args...) printk("%s:%s:" format, \
-				       __FILE__, __FUNCTION__ , ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
 #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0)
 
 static unsigned int nlbufsiz = NLMSG_GOODSIZE;
@@ -96,12 +89,12 @@
 	ulog_buff_t *ub = &ulog_buffers[nlgroupnum];
 
 	if (timer_pending(&ub->timer)) {
-		DEBUGP("ipt_ULOG: ulog_send: timer was pending, deleting\n");
+		pr_debug("ipt_ULOG: ulog_send: timer was pending, deleting\n");
 		del_timer(&ub->timer);
 	}
 
 	if (!ub->skb) {
-		DEBUGP("ipt_ULOG: ulog_send: nothing to send\n");
+		pr_debug("ipt_ULOG: ulog_send: nothing to send\n");
 		return;
 	}
 
@@ -110,8 +103,8 @@
 		ub->lastnlh->nlmsg_type = NLMSG_DONE;
 
 	NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1;
-	DEBUGP("ipt_ULOG: throwing %d packets to netlink group %u\n",
-		ub->qlen, nlgroupnum + 1);
+	pr_debug("ipt_ULOG: throwing %d packets to netlink group %u\n",
+		 ub->qlen, nlgroupnum + 1);
 	netlink_broadcast(nflognl, ub->skb, 0, nlgroupnum + 1, GFP_ATOMIC);
 
 	ub->qlen = 0;
@@ -123,7 +116,7 @@
 /* timer function to flush queue in flushtimeout time */
 static void ulog_timer(unsigned long data)
 {
-	DEBUGP("ipt_ULOG: timer function called, calling ulog_send\n");
+	pr_debug("ipt_ULOG: timer function called, calling ulog_send\n");
 
 	/* lock to protect against somebody modifying our structure
 	 * from ipt_ulog_target at the same time */
@@ -179,12 +172,10 @@
 	unsigned int groupnum = ffs(loginfo->nl_group) - 1;
 
 	/* calculate the size of the skb needed */
-	if ((loginfo->copy_range == 0) ||
-	    (loginfo->copy_range > skb->len)) {
+	if (loginfo->copy_range == 0 || loginfo->copy_range > skb->len)
 		copy_len = skb->len;
-	} else {
+	else
 		copy_len = loginfo->copy_range;
-	}
 
 	size = NLMSG_SPACE(sizeof(*pm) + copy_len);
 
@@ -206,8 +197,8 @@
 			goto alloc_failure;
 	}
 
-	DEBUGP("ipt_ULOG: qlen %d, qthreshold %d\n", ub->qlen,
-		loginfo->qthreshold);
+	pr_debug("ipt_ULOG: qlen %d, qthreshold %Zu\n", ub->qlen,
+		 loginfo->qthreshold);
 
 	/* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */
 	nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT,
@@ -257,9 +248,8 @@
 		BUG();
 
 	/* check if we are building multi-part messages */
-	if (ub->qlen > 1) {
+	if (ub->qlen > 1)
 		ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
-	}
 
 	ub->lastnlh = nlh;
 
@@ -328,25 +318,25 @@
 	ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
 }
 
-static int ipt_ulog_checkentry(const char *tablename,
-			       const void *e,
-			       const struct xt_target *target,
-			       void *targinfo,
-			       unsigned int hookmask)
+static bool ipt_ulog_checkentry(const char *tablename,
+				const void *e,
+				const struct xt_target *target,
+				void *targinfo,
+				unsigned int hookmask)
 {
-	struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
+	const struct ipt_ulog_info *loginfo = targinfo;
 
 	if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
-		DEBUGP("ipt_ULOG: prefix term %i\n",
-		       loginfo->prefix[sizeof(loginfo->prefix) - 1]);
-		return 0;
+		pr_debug("ipt_ULOG: prefix term %i\n",
+			 loginfo->prefix[sizeof(loginfo->prefix) - 1]);
+		return false;
 	}
 	if (loginfo->qthreshold > ULOG_MAX_QLEN) {
-		DEBUGP("ipt_ULOG: queue threshold %i > MAX_QLEN\n",
-			loginfo->qthreshold);
-		return 0;
+		pr_debug("ipt_ULOG: queue threshold %Zu > MAX_QLEN\n",
+			 loginfo->qthreshold);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 #ifdef CONFIG_COMPAT
@@ -359,7 +349,7 @@
 
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_ipt_ulog_info *cl = src;
+	const struct compat_ipt_ulog_info *cl = src;
 	struct ipt_ulog_info l = {
 		.nl_group	= cl->nl_group,
 		.copy_range	= cl->copy_range,
@@ -372,7 +362,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct ipt_ulog_info *l = src;
+	const struct ipt_ulog_info *l = src;
 	struct compat_ipt_ulog_info cl = {
 		.nl_group	= l->nl_group,
 		.copy_range	= l->copy_range,
@@ -384,7 +374,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_target ipt_ulog_reg = {
+static struct xt_target ipt_ulog_reg __read_mostly = {
 	.name		= "ULOG",
 	.family		= AF_INET,
 	.target		= ipt_ulog_target,
@@ -408,7 +398,7 @@
 {
 	int ret, i;
 
-	DEBUGP("ipt_ULOG: init module\n");
+	pr_debug("ipt_ULOG: init module\n");
 
 	if (nlbufsiz > 128*1024) {
 		printk("Netlink buffer has to be <= 128kB\n");
@@ -440,7 +430,7 @@
 	ulog_buff_t *ub;
 	int i;
 
-	DEBUGP("ipt_ULOG: cleanup_module\n");
+	pr_debug("ipt_ULOG: cleanup_module\n");
 
 	if (nflog)
 		nf_log_unregister(&ipt_ulog_logger);
@@ -451,7 +441,7 @@
 	for (i = 0; i < ULOG_MAXNLGROUPS; i++) {
 		ub = &ulog_buffers[i];
 		if (timer_pending(&ub->timer)) {
-			DEBUGP("timer was pending, deleting\n");
+			pr_debug("timer was pending, deleting\n");
 			del_timer(&ub->timer);
 		}
 
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index a652a14..59f01f7 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -22,19 +22,19 @@
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_DESCRIPTION("iptables addrtype match");
 
-static inline int match_type(__be32 addr, u_int16_t mask)
+static inline bool match_type(__be32 addr, u_int16_t mask)
 {
 	return !!(mask & (1 << inet_addr_type(addr)));
 }
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in, const struct net_device *out,
-		 const struct xt_match *match, const void *matchinfo,
-		 int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in, const struct net_device *out,
+		  const struct xt_match *match, const void *matchinfo,
+		  int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ipt_addrtype_info *info = matchinfo;
 	const struct iphdr *iph = ip_hdr(skb);
-	int ret = 1;
+	bool ret = true;
 
 	if (info->source)
 		ret &= match_type(iph->saddr, info->source)^info->invert_source;
@@ -44,7 +44,7 @@
 	return ret;
 }
 
-static struct xt_match addrtype_match = {
+static struct xt_match addrtype_match __read_mostly = {
 	.name		= "addrtype",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index 18a1678..61b017f 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -25,10 +25,10 @@
 #endif
 
 /* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
+static inline bool
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
 {
-	int r=0;
+	bool r;
 	duprintf("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
 		min,spi,max);
 	r=(spi >= min && spi <= max) ^ invert;
@@ -36,7 +36,7 @@
 	return r;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -44,14 +44,15 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
-	struct ip_auth_hdr _ahdr, *ah;
+	struct ip_auth_hdr _ahdr;
+	const struct ip_auth_hdr *ah;
 	const struct ipt_ah *ahinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	ah = skb_header_pointer(skb, protoff,
 				sizeof(_ahdr), &_ahdr);
@@ -60,7 +61,7 @@
 		 * can't.  Hence, no choice but to drop.
 		 */
 		duprintf("Dropping evil AH tinygram.\n");
-		*hotdrop = 1;
+		*hotdrop = true;
 		return 0;
 	}
 
@@ -70,7 +71,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip_void,
 	   const struct xt_match *match,
@@ -82,12 +83,12 @@
 	/* Must specify no unknown invflags */
 	if (ahinfo->invflags & ~IPT_AH_INV_MASK) {
 		duprintf("ipt_ah: unknown flags %X\n", ahinfo->invflags);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match ah_match = {
+static struct xt_match ah_match __read_mostly = {
 	.name		= "ah",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index 2621812..d6925c6 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -22,95 +22,96 @@
 MODULE_DESCRIPTION("iptables ECN matching module");
 MODULE_LICENSE("GPL");
 
-static inline int match_ip(const struct sk_buff *skb,
-			   const struct ipt_ecn_info *einfo)
+static inline bool match_ip(const struct sk_buff *skb,
+			    const struct ipt_ecn_info *einfo)
 {
 	return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect;
 }
 
-static inline int match_tcp(const struct sk_buff *skb,
-			    const struct ipt_ecn_info *einfo,
-			    int *hotdrop)
+static inline bool match_tcp(const struct sk_buff *skb,
+			     const struct ipt_ecn_info *einfo,
+			     bool *hotdrop)
 {
-	struct tcphdr _tcph, *th;
+	struct tcphdr _tcph;
+	const struct tcphdr *th;
 
 	/* In practice, TCP match does this, so can't fail.  But let's
 	 * be good citizens.
 	 */
 	th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph);
 	if (th == NULL) {
-		*hotdrop = 0;
-		return 0;
+		*hotdrop = false;
+		return false;
 	}
 
 	if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
 		if (einfo->invert & IPT_ECN_OP_MATCH_ECE) {
 			if (th->ece == 1)
-				return 0;
+				return false;
 		} else {
 			if (th->ece == 0)
-				return 0;
+				return false;
 		}
 	}
 
 	if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
 		if (einfo->invert & IPT_ECN_OP_MATCH_CWR) {
 			if (th->cwr == 1)
-				return 0;
+				return false;
 		} else {
 			if (th->cwr == 0)
-				return 0;
+				return false;
 		}
 	}
 
-	return 1;
+	return true;
 }
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in, const struct net_device *out,
-		 const struct xt_match *match, const void *matchinfo,
-		 int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in, const struct net_device *out,
+		  const struct xt_match *match, const void *matchinfo,
+		  int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ipt_ecn_info *info = matchinfo;
 
 	if (info->operation & IPT_ECN_OP_MATCH_IP)
 		if (!match_ip(skb, info))
-			return 0;
+			return false;
 
 	if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) {
 		if (ip_hdr(skb)->protocol != IPPROTO_TCP)
-			return 0;
+			return false;
 		if (!match_tcp(skb, info, hotdrop))
-			return 0;
+			return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static int checkentry(const char *tablename, const void *ip_void,
-		      const struct xt_match *match,
-		      void *matchinfo, unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *ip_void,
+		       const struct xt_match *match,
+		       void *matchinfo, unsigned int hook_mask)
 {
 	const struct ipt_ecn_info *info = matchinfo;
 	const struct ipt_ip *ip = ip_void;
 
 	if (info->operation & IPT_ECN_OP_MATCH_MASK)
-		return 0;
+		return false;
 
 	if (info->invert & IPT_ECN_OP_MATCH_MASK)
-		return 0;
+		return false;
 
 	if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)
 	    && ip->proto != IPPROTO_TCP) {
 		printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for"
 		       " non-tcp packets\n");
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static struct xt_match ecn_match = {
+static struct xt_match ecn_match __read_mostly = {
 	.name		= "ecn",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index 33af9e9..0106dc9 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -17,53 +17,47 @@
 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
 MODULE_DESCRIPTION("iptables arbitrary IP range match module");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
       const struct xt_match *match,
       const void *matchinfo,
-      int offset, unsigned int protoff, int *hotdrop)
+      int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ipt_iprange_info *info = matchinfo;
 	const struct iphdr *iph = ip_hdr(skb);
 
 	if (info->flags & IPRANGE_SRC) {
-		if (((ntohl(iph->saddr) < ntohl(info->src.min_ip))
-			  || (ntohl(iph->saddr) > ntohl(info->src.max_ip)))
+		if ((ntohl(iph->saddr) < ntohl(info->src.min_ip)
+			  || ntohl(iph->saddr) > ntohl(info->src.max_ip))
 			 ^ !!(info->flags & IPRANGE_SRC_INV)) {
-			DEBUGP("src IP %u.%u.%u.%u NOT in range %s"
-			       "%u.%u.%u.%u-%u.%u.%u.%u\n",
-				NIPQUAD(iph->saddr),
-				info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
-				NIPQUAD(info->src.min_ip),
-				NIPQUAD(info->src.max_ip));
-			return 0;
+			pr_debug("src IP %u.%u.%u.%u NOT in range %s"
+				 "%u.%u.%u.%u-%u.%u.%u.%u\n",
+				 NIPQUAD(iph->saddr),
+				 info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
+				 NIPQUAD(info->src.min_ip),
+				 NIPQUAD(info->src.max_ip));
+			return false;
 		}
 	}
 	if (info->flags & IPRANGE_DST) {
-		if (((ntohl(iph->daddr) < ntohl(info->dst.min_ip))
-			  || (ntohl(iph->daddr) > ntohl(info->dst.max_ip)))
+		if ((ntohl(iph->daddr) < ntohl(info->dst.min_ip)
+			  || ntohl(iph->daddr) > ntohl(info->dst.max_ip))
 			 ^ !!(info->flags & IPRANGE_DST_INV)) {
-			DEBUGP("dst IP %u.%u.%u.%u NOT in range %s"
-			       "%u.%u.%u.%u-%u.%u.%u.%u\n",
-				NIPQUAD(iph->daddr),
-				info->flags & IPRANGE_DST_INV ? "(INV) " : "",
-				NIPQUAD(info->dst.min_ip),
-				NIPQUAD(info->dst.max_ip));
-			return 0;
+			pr_debug("dst IP %u.%u.%u.%u NOT in range %s"
+				 "%u.%u.%u.%u-%u.%u.%u.%u\n",
+				 NIPQUAD(iph->daddr),
+				 info->flags & IPRANGE_DST_INV ? "(INV) " : "",
+				 NIPQUAD(info->dst.min_ip),
+				 NIPQUAD(info->dst.max_ip));
+			return false;
 		}
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match iprange_match = {
+static struct xt_match iprange_match __read_mostly = {
 	.name		= "iprange",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 7fae9aa..b14e77d 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -21,7 +21,7 @@
 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
 MODULE_DESCRIPTION("iptables owner match");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -29,29 +29,29 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct ipt_owner_info *info = matchinfo;
 
 	if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
-		return 0;
+		return false;
 
 	if(info->match & IPT_OWNER_UID) {
 		if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
 		    !!(info->invert & IPT_OWNER_UID))
-			return 0;
+			return false;
 	}
 
 	if(info->match & IPT_OWNER_GID) {
 		if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
 		    !!(info->invert & IPT_OWNER_GID))
-			return 0;
+			return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip,
 	   const struct xt_match *match,
@@ -63,12 +63,12 @@
 	if (info->match & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) {
 		printk("ipt_owner: pid, sid and command matching "
 		       "not supported anymore\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match owner_match = {
+static struct xt_match owner_match __read_mostly = {
 	.name		= "owner",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 15a9e8b..3218043 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -163,24 +163,23 @@
 	struct recent_entry *e, *next;
 	unsigned int i;
 
-	for (i = 0; i < ip_list_hash_size; i++) {
+	for (i = 0; i < ip_list_hash_size; i++)
 		list_for_each_entry_safe(e, next, &t->iphash[i], list)
 			recent_entry_remove(t, e);
-	}
 }
 
-static int
+static bool
 ipt_recent_match(const struct sk_buff *skb,
 		 const struct net_device *in, const struct net_device *out,
 		 const struct xt_match *match, const void *matchinfo,
-		 int offset, unsigned int protoff, int *hotdrop)
+		 int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ipt_recent_info *info = matchinfo;
 	struct recent_table *t;
 	struct recent_entry *e;
 	__be32 addr;
 	u_int8_t ttl;
-	int ret = info->invert;
+	bool ret = info->invert;
 
 	if (info->side == IPT_RECENT_DEST)
 		addr = ip_hdr(skb)->daddr;
@@ -201,16 +200,16 @@
 			goto out;
 		e = recent_entry_init(t, addr, ttl);
 		if (e == NULL)
-			*hotdrop = 1;
-		ret ^= 1;
+			*hotdrop = true;
+		ret = !ret;
 		goto out;
 	}
 
 	if (info->check_set & IPT_RECENT_SET)
-		ret ^= 1;
+		ret = !ret;
 	else if (info->check_set & IPT_RECENT_REMOVE) {
 		recent_entry_remove(t, e);
-		ret ^= 1;
+		ret = !ret;
 	} else if (info->check_set & (IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) {
 		unsigned long t = jiffies - info->seconds * HZ;
 		unsigned int i, hits = 0;
@@ -219,7 +218,7 @@
 			if (info->seconds && time_after(t, e->stamps[i]))
 				continue;
 			if (++hits >= info->hit_count) {
-				ret ^= 1;
+				ret = !ret;
 				break;
 			}
 		}
@@ -235,7 +234,7 @@
 	return ret;
 }
 
-static int
+static bool
 ipt_recent_checkentry(const char *tablename, const void *ip,
 		      const struct xt_match *match, void *matchinfo,
 		      unsigned int hook_mask)
@@ -243,24 +242,24 @@
 	const struct ipt_recent_info *info = matchinfo;
 	struct recent_table *t;
 	unsigned i;
-	int ret = 0;
+	bool ret = false;
 
 	if (hweight8(info->check_set &
 		     (IPT_RECENT_SET | IPT_RECENT_REMOVE |
 		      IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) != 1)
-		return 0;
+		return false;
 	if ((info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE)) &&
 	    (info->seconds || info->hit_count))
-		return 0;
+		return false;
 	if (info->name[0] == '\0' ||
 	    strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
-		return 0;
+		return false;
 
 	mutex_lock(&recent_mutex);
 	t = recent_table_lookup(info->name);
 	if (t != NULL) {
 		t->refcnt++;
-		ret = 1;
+		ret = true;
 		goto out;
 	}
 
@@ -287,7 +286,7 @@
 	spin_lock_bh(&recent_lock);
 	list_add_tail(&t->list, &tables);
 	spin_unlock_bh(&recent_lock);
-	ret = 1;
+	ret = true;
 out:
 	mutex_unlock(&recent_mutex);
 	return ret;
@@ -323,18 +322,16 @@
 static void *recent_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	struct recent_iter_state *st = seq->private;
-	struct recent_table *t = st->table;
+	const struct recent_table *t = st->table;
 	struct recent_entry *e;
 	loff_t p = *pos;
 
 	spin_lock_bh(&recent_lock);
 
-	for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++) {
-		list_for_each_entry(e, &t->iphash[st->bucket], list) {
+	for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++)
+		list_for_each_entry(e, &t->iphash[st->bucket], list)
 			if (p-- == 0)
 				return e;
-		}
-	}
 	return NULL;
 }
 
@@ -373,7 +370,7 @@
 	return 0;
 }
 
-static struct seq_operations recent_seq_ops = {
+static const struct seq_operations recent_seq_ops = {
 	.start		= recent_seq_start,
 	.next		= recent_seq_next,
 	.stop		= recent_seq_stop,
@@ -463,7 +460,7 @@
 };
 #endif /* CONFIG_PROC_FS */
 
-static struct xt_match recent_match = {
+static struct xt_match recent_match __read_mostly = {
 	.name		= "recent",
 	.family		= AF_INET,
 	.match		= ipt_recent_match,
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index d314844..e740441 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -18,7 +18,7 @@
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("iptables TOS match module");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -26,14 +26,14 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct ipt_tos_info *info = matchinfo;
 
 	return (ip_hdr(skb)->tos == info->tos) ^ info->invert;
 }
 
-static struct xt_match tos_match = {
+static struct xt_match tos_match __read_mostly = {
 	.name		= "tos",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index ab02d9e..a439900 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -18,37 +18,33 @@
 MODULE_DESCRIPTION("IP tables TTL matching module");
 MODULE_LICENSE("GPL");
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in, const struct net_device *out,
-		 const struct xt_match *match, const void *matchinfo,
-		 int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in, const struct net_device *out,
+		  const struct xt_match *match, const void *matchinfo,
+		  int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ipt_ttl_info *info = matchinfo;
 	const u8 ttl = ip_hdr(skb)->ttl;
 
 	switch (info->mode) {
 		case IPT_TTL_EQ:
-			return (ttl == info->ttl);
-			break;
+			return ttl == info->ttl;
 		case IPT_TTL_NE:
-			return (!(ttl == info->ttl));
-			break;
+			return ttl != info->ttl;
 		case IPT_TTL_LT:
-			return (ttl < info->ttl);
-			break;
+			return ttl < info->ttl;
 		case IPT_TTL_GT:
-			return (ttl > info->ttl);
-			break;
+			return ttl > info->ttl;
 		default:
 			printk(KERN_WARNING "ipt_ttl: unknown mode %d\n",
 				info->mode);
-			return 0;
+			return false;
 	}
 
-	return 0;
+	return false;
 }
 
-static struct xt_match ttl_match = {
+static struct xt_match ttl_match __read_mostly = {
 	.name		= "ttl",
 	.family		= AF_INET,
 	.match		= match,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 6dc72a8..3c56299 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -24,12 +24,6 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
 			     struct nf_conntrack_tuple *tuple)
 {
@@ -103,17 +97,6 @@
 	return NF_ACCEPT;
 }
 
-int nf_nat_module_is_loaded = 0;
-EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded);
-
-static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple)
-{
-	if (nf_nat_module_is_loaded)
-		return NF_CT_F_NAT;
-
-	return NF_CT_F_BASIC;
-}
-
 static unsigned int ipv4_confirm(unsigned int hooknum,
 				 struct sk_buff **pskb,
 				 const struct net_device *in,
@@ -335,17 +318,17 @@
 
 	/* We only do TCP at the moment: is there a better way? */
 	if (strcmp(sk->sk_prot->name, "TCP")) {
-		DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n");
+		pr_debug("SO_ORIGINAL_DST: Not a TCP socket\n");
 		return -ENOPROTOOPT;
 	}
 
 	if ((unsigned int) *len < sizeof(struct sockaddr_in)) {
-		DEBUGP("SO_ORIGINAL_DST: len %u not %u\n",
-		       *len, sizeof(struct sockaddr_in));
+		pr_debug("SO_ORIGINAL_DST: len %d not %Zu\n",
+			 *len, sizeof(struct sockaddr_in));
 		return -EINVAL;
 	}
 
-	h = nf_conntrack_find_get(&tuple, NULL);
+	h = nf_conntrack_find_get(&tuple);
 	if (h) {
 		struct sockaddr_in sin;
 		struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
@@ -357,17 +340,17 @@
 			.tuple.dst.u3.ip;
 		memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
 
-		DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
-		       NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+		pr_debug("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
+			 NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
 		nf_ct_put(ct);
 		if (copy_to_user(user, &sin, sizeof(sin)) != 0)
 			return -EFAULT;
 		else
 			return 0;
 	}
-	DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n",
-	       NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port),
-	       NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port));
+	pr_debug("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n",
+		 NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port),
+		 NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port));
 	return -ENOENT;
 }
 
@@ -425,7 +408,6 @@
 	.print_tuple	 = ipv4_print_tuple,
 	.print_conntrack = ipv4_print_conntrack,
 	.prepare	 = ipv4_prepare,
-	.get_features	 = ipv4_get_features,
 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
 	.tuple_to_nfattr = ipv4_tuple_to_nfattr,
 	.nfattr_to_tuple = ipv4_nfattr_to_tuple,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 89f933e..3da9d73 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -18,12 +18,6 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_expect.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 #ifdef CONFIG_NF_CT_ACCT
 static unsigned int
 seq_print_counters(struct seq_file *s,
@@ -41,35 +35,36 @@
 	unsigned int bucket;
 };
 
-static struct list_head *ct_get_first(struct seq_file *seq)
+static struct hlist_node *ct_get_first(struct seq_file *seq)
 {
 	struct ct_iter_state *st = seq->private;
 
 	for (st->bucket = 0;
 	     st->bucket < nf_conntrack_htable_size;
 	     st->bucket++) {
-		if (!list_empty(&nf_conntrack_hash[st->bucket]))
-			return nf_conntrack_hash[st->bucket].next;
+		if (!hlist_empty(&nf_conntrack_hash[st->bucket]))
+			return nf_conntrack_hash[st->bucket].first;
 	}
 	return NULL;
 }
 
-static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
+static struct hlist_node *ct_get_next(struct seq_file *seq,
+				      struct hlist_node *head)
 {
 	struct ct_iter_state *st = seq->private;
 
 	head = head->next;
-	while (head == &nf_conntrack_hash[st->bucket]) {
+	while (head == NULL) {
 		if (++st->bucket >= nf_conntrack_htable_size)
 			return NULL;
-		head = nf_conntrack_hash[st->bucket].next;
+		head = nf_conntrack_hash[st->bucket].first;
 	}
 	return head;
 }
 
-static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
+static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos)
 {
-	struct list_head *head = ct_get_first(seq);
+	struct hlist_node *head = ct_get_first(seq);
 
 	if (head)
 		while (pos && (head = ct_get_next(seq, head)))
@@ -169,7 +164,7 @@
 	return 0;
 }
 
-static struct seq_operations ct_seq_ops = {
+static const struct seq_operations ct_seq_ops = {
 	.start = ct_seq_start,
 	.next  = ct_seq_next,
 	.stop  = ct_seq_stop,
@@ -206,47 +201,68 @@
 };
 
 /* expects */
-static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+struct ct_expect_iter_state {
+	unsigned int bucket;
+};
+
+static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
 {
-	struct list_head *e = &nf_conntrack_expect_list;
-	loff_t i;
+	struct ct_expect_iter_state *st = seq->private;
 
-	/* strange seq_file api calls stop even if we fail,
-	 * thus we need to grab lock since stop unlocks */
-	read_lock_bh(&nf_conntrack_lock);
-
-	if (list_empty(e))
-		return NULL;
-
-	for (i = 0; i <= *pos; i++) {
-		e = e->next;
-		if (e == &nf_conntrack_expect_list)
-			return NULL;
+	for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
+		if (!hlist_empty(&nf_ct_expect_hash[st->bucket]))
+			return nf_ct_expect_hash[st->bucket].first;
 	}
-	return e;
+	return NULL;
 }
 
-static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
+					     struct hlist_node *head)
 {
-	struct list_head *e = v;
+	struct ct_expect_iter_state *st = seq->private;
 
-	++*pos;
-	e = e->next;
-
-	if (e == &nf_conntrack_expect_list)
-		return NULL;
-
-	return e;
+	head = head->next;
+	while (head == NULL) {
+		if (++st->bucket >= nf_ct_expect_hsize)
+			return NULL;
+		head = nf_ct_expect_hash[st->bucket].first;
+	}
+	return head;
 }
 
-static void exp_seq_stop(struct seq_file *s, void *v)
+static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct hlist_node *head = ct_expect_get_first(seq);
+
+	if (head)
+		while (pos && (head = ct_expect_get_next(seq, head)))
+			pos--;
+	return pos ? NULL : head;
+}
+
+static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock_bh(&nf_conntrack_lock);
+	return ct_expect_get_idx(seq, *pos);
+}
+
+static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return ct_expect_get_next(seq, v);
+}
+
+static void exp_seq_stop(struct seq_file *seq, void *v)
 {
 	read_unlock_bh(&nf_conntrack_lock);
 }
 
 static int exp_seq_show(struct seq_file *s, void *v)
 {
-	struct nf_conntrack_expect *exp = v;
+	struct nf_conntrack_expect *exp;
+	struct hlist_node *n = v;
+
+	exp = hlist_entry(n, struct nf_conntrack_expect, hnode);
 
 	if (exp->tuple.src.l3num != AF_INET)
 		return 0;
@@ -266,7 +282,7 @@
 	return seq_putc(s, '\n');
 }
 
-static struct seq_operations exp_seq_ops = {
+static const struct seq_operations exp_seq_ops = {
 	.start = exp_seq_start,
 	.next = exp_seq_next,
 	.stop = exp_seq_stop,
@@ -275,7 +291,23 @@
 
 static int exp_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &exp_seq_ops);
+	struct seq_file *seq;
+	struct ct_expect_iter_state *st;
+	int ret;
+
+	st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL);
+	if (st == NULL)
+		return -ENOMEM;
+	ret = seq_open(file, &exp_seq_ops);
+	if (ret)
+		goto out_free;
+	seq          = file->private_data;
+	seq->private = st;
+	memset(st, 0, sizeof(struct ct_expect_iter_state));
+	return ret;
+out_free:
+	kfree(st);
+	return ret;
 }
 
 static const struct file_operations ip_exp_file_ops = {
@@ -283,7 +315,7 @@
 	.open    = exp_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = seq_release
+	.release = seq_release_private,
 };
 
 static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
@@ -354,7 +386,7 @@
 	return 0;
 }
 
-static struct seq_operations ct_cpu_seq_ops = {
+static const struct seq_operations ct_cpu_seq_ops = {
 	.start  = ct_cpu_seq_start,
 	.next   = ct_cpu_seq_next,
 	.stop   = ct_cpu_seq_stop,
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index f4fc657..0fe8fb0 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -21,12 +21,6 @@
 
 static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int icmp_pkt_to_tuple(const struct sk_buff *skb,
 			     unsigned int dataoff,
 			     struct nf_conntrack_tuple *tuple)
@@ -125,8 +119,8 @@
 	if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
 	    || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
 		/* Can't create a new ICMP `conn' with this. */
-		DEBUGP("icmp: can't create new conn with type %u\n",
-		       conntrack->tuplehash[0].tuple.dst.u.icmp.type);
+		pr_debug("icmp: can't create new conn with type %u\n",
+			 conntrack->tuplehash[0].tuple.dst.u.icmp.type);
 		NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
 		return 0;
 	}
@@ -159,8 +153,8 @@
 
 	/* Ignore ICMP's containing fragments (shouldn't happen) */
 	if (inside->ip.frag_off & htons(IP_OFFSET)) {
-		DEBUGP("icmp_error_message: fragment of proto %u\n",
-		       inside->ip.protocol);
+		pr_debug("icmp_error_message: fragment of proto %u\n",
+			 inside->ip.protocol);
 		return -NF_ACCEPT;
 	}
 
@@ -172,8 +166,8 @@
 	if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
 			     inside->ip.protocol, &origtuple,
 			     &nf_conntrack_l3proto_ipv4, innerproto)) {
-		DEBUGP("icmp_error_message: ! get_tuple p=%u",
-		       inside->ip.protocol);
+		pr_debug("icmp_error_message: ! get_tuple p=%u",
+			 inside->ip.protocol);
 		return -NF_ACCEPT;
 	}
 
@@ -181,22 +175,22 @@
 	   been preserved inside the ICMP. */
 	if (!nf_ct_invert_tuple(&innertuple, &origtuple,
 				&nf_conntrack_l3proto_ipv4, innerproto)) {
-		DEBUGP("icmp_error_message: no match\n");
+		pr_debug("icmp_error_message: no match\n");
 		return -NF_ACCEPT;
 	}
 
 	*ctinfo = IP_CT_RELATED;
 
-	h = nf_conntrack_find_get(&innertuple, NULL);
+	h = nf_conntrack_find_get(&innertuple);
 	if (!h) {
 		/* Locally generated ICMPs will match inverted if they
 		   haven't been SNAT'ed yet */
 		/* FIXME: NAT code has to handle half-done double NAT --RR */
 		if (hooknum == NF_IP_LOCAL_OUT)
-			h = nf_conntrack_find_get(&origtuple, NULL);
+			h = nf_conntrack_find_get(&origtuple);
 
 		if (!h) {
-			DEBUGP("icmp_error_message: no match\n");
+			pr_debug("icmp_error_message: no match\n");
 			return -NF_ACCEPT;
 		}
 
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c
index 0f17098..bd93a1d 100644
--- a/net/ipv4/netfilter/nf_nat_amanda.c
+++ b/net/ipv4/netfilter/nf_nat_amanda.c
@@ -45,7 +45,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
 		exp->tuple.dst.u.tcp.port = htons(port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -57,7 +57,7 @@
 				       matchoff, matchlen,
 				       buffer, strlen(buffer));
 	if (ret != NF_ACCEPT)
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 	return ret;
 }
 
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index ea02f00..e848d8d 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -12,7 +12,6 @@
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/skbuff.h>
-#include <linux/vmalloc.h>
 #include <net/checksum.h>
 #include <net/icmp.h>
 #include <net/ip.h>
@@ -32,20 +31,15 @@
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static DEFINE_RWLOCK(nf_nat_lock);
 
 static struct nf_conntrack_l3proto *l3proto = NULL;
 
 /* Calculated at init based on memory size */
 static unsigned int nf_nat_htable_size;
+static int nf_nat_vmalloced;
 
-static struct list_head *bysource;
+static struct hlist_head *bysource;
 
 #define MAX_IP_NAT_PROTO 256
 static struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO];
@@ -87,19 +81,6 @@
 			    tuple->dst.protonum, 0) % nf_nat_htable_size;
 }
 
-/* Noone using conntrack by the time this called. */
-static void nf_nat_cleanup_conntrack(struct nf_conn *conn)
-{
-	struct nf_conn_nat *nat;
-	if (!(conn->status & IPS_NAT_DONE_MASK))
-		return;
-
-	nat = nfct_nat(conn);
-	write_lock_bh(&nf_nat_lock);
-	list_del(&nat->info.bysource);
-	write_unlock_bh(&nf_nat_lock);
-}
-
 /* Is this tuple already taken? (not by us) */
 int
 nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
@@ -166,10 +147,11 @@
 	unsigned int h = hash_by_src(tuple);
 	struct nf_conn_nat *nat;
 	struct nf_conn *ct;
+	struct hlist_node *n;
 
 	read_lock_bh(&nf_nat_lock);
-	list_for_each_entry(nat, &bysource[h], info.bysource) {
-		ct = (struct nf_conn *)((char *)nat - offsetof(struct nf_conn, data));
+	hlist_for_each_entry(nat, n, &bysource[h], bysource) {
+		ct = nat->ct;
 		if (same_src(ct, tuple)) {
 			/* Copy source part from reply tuple. */
 			nf_ct_invert_tuplepr(result,
@@ -254,7 +236,7 @@
 	   manips not an issue.  */
 	if (maniptype == IP_NAT_MANIP_SRC) {
 		if (find_appropriate_src(orig_tuple, tuple, range)) {
-			DEBUGP("get_unique_tuple: Found current src map\n");
+			pr_debug("get_unique_tuple: Found current src map\n");
 			if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
 				if (!nf_nat_used_tuple(tuple, ct))
 					return;
@@ -296,11 +278,20 @@
 		  unsigned int hooknum)
 {
 	struct nf_conntrack_tuple curr_tuple, new_tuple;
-	struct nf_conn_nat *nat = nfct_nat(ct);
-	struct nf_nat_info *info = &nat->info;
+	struct nf_conn_nat *nat;
 	int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK);
 	enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
 
+	/* nat helper or nfctnetlink also setup binding */
+	nat = nfct_nat(ct);
+	if (!nat) {
+		nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
+		if (nat == NULL) {
+			pr_debug("failed to add NAT extension\n");
+			return NF_ACCEPT;
+		}
+	}
+
 	NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
 		     hooknum == NF_IP_POST_ROUTING ||
 		     hooknum == NF_IP_LOCAL_IN ||
@@ -337,7 +328,10 @@
 
 		srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 		write_lock_bh(&nf_nat_lock);
-		list_add(&info->bysource, &bysource[srchash]);
+		/* nf_conntrack_alter_reply might re-allocate exntension aera */
+		nat = nfct_nat(ct);
+		nat->ct = ct;
+		hlist_add_head(&nat->bysource, &bysource[srchash]);
 		write_unlock_bh(&nf_nat_lock);
 	}
 
@@ -462,8 +456,9 @@
 			return 0;
 	}
 
-	DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n",
-	       *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
+	pr_debug("icmp_reply_translation: translating error %p manip %u "
+		 "dir %s\n", *pskb, manip,
+		 dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
 
 	/* rcu_read_lock()ed by nf_hook_slow */
 	l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
@@ -590,17 +585,69 @@
 EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr);
 #endif
 
+/* Noone using conntrack by the time this called. */
+static void nf_nat_cleanup_conntrack(struct nf_conn *ct)
+{
+	struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT);
+
+	if (nat == NULL || nat->ct == NULL)
+		return;
+
+	NF_CT_ASSERT(nat->ct->status & IPS_NAT_DONE_MASK);
+
+	write_lock_bh(&nf_nat_lock);
+	hlist_del(&nat->bysource);
+	nat->ct = NULL;
+	write_unlock_bh(&nf_nat_lock);
+}
+
+static void nf_nat_move_storage(struct nf_conn *conntrack, void *old)
+{
+	struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT);
+	struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old;
+	struct nf_conn *ct = old_nat->ct;
+	unsigned int srchash;
+
+	if (!(ct->status & IPS_NAT_DONE_MASK))
+		return;
+
+	srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+
+	write_lock_bh(&nf_nat_lock);
+	hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource);
+	new_nat->ct = ct;
+	write_unlock_bh(&nf_nat_lock);
+}
+
+static struct nf_ct_ext_type nat_extend __read_mostly = {
+	.len		= sizeof(struct nf_conn_nat),
+	.align		= __alignof__(struct nf_conn_nat),
+	.destroy	= nf_nat_cleanup_conntrack,
+	.move		= nf_nat_move_storage,
+	.id		= NF_CT_EXT_NAT,
+	.flags		= NF_CT_EXT_F_PREALLOC,
+};
+
 static int __init nf_nat_init(void)
 {
 	size_t i;
+	int ret;
+
+	ret = nf_ct_extend_register(&nat_extend);
+	if (ret < 0) {
+		printk(KERN_ERR "nf_nat_core: Unable to register extension\n");
+		return ret;
+	}
 
 	/* Leave them the same for the moment. */
 	nf_nat_htable_size = nf_conntrack_htable_size;
 
-	/* One vmalloc for both hash tables */
-	bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size);
-	if (!bysource)
-		return -ENOMEM;
+	bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size,
+					 &nf_nat_vmalloced);
+	if (!bysource) {
+		ret = -ENOMEM;
+		goto cleanup_extend;
+	}
 
 	/* Sew in builtin protocols. */
 	write_lock_bh(&nf_nat_lock);
@@ -612,18 +659,18 @@
 	write_unlock_bh(&nf_nat_lock);
 
 	for (i = 0; i < nf_nat_htable_size; i++) {
-		INIT_LIST_HEAD(&bysource[i]);
+		INIT_HLIST_HEAD(&bysource[i]);
 	}
 
-	/* FIXME: Man, this is a hack.  <SIGH> */
-	NF_CT_ASSERT(rcu_dereference(nf_conntrack_destroyed) == NULL);
-	rcu_assign_pointer(nf_conntrack_destroyed, nf_nat_cleanup_conntrack);
-
 	/* Initialize fake conntrack so that NAT will skip it */
 	nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
 
 	l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
 	return 0;
+
+ cleanup_extend:
+	nf_ct_extend_unregister(&nat_extend);
+	return ret;
 }
 
 /* Clear NAT section of all conntracks, in case we're loaded again. */
@@ -641,10 +688,10 @@
 static void __exit nf_nat_cleanup(void)
 {
 	nf_ct_iterate_cleanup(&clean_nat, NULL);
-	rcu_assign_pointer(nf_conntrack_destroyed, NULL);
 	synchronize_rcu();
-	vfree(bysource);
+	nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size);
 	nf_ct_l3proto_put(l3proto);
+	nf_ct_extend_unregister(&nat_extend);
 }
 
 MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c
index e6bc8e5..3663bd8 100644
--- a/net/ipv4/netfilter/nf_nat_ftp.c
+++ b/net/ipv4/netfilter/nf_nat_ftp.c
@@ -25,12 +25,6 @@
 MODULE_DESCRIPTION("ftp NAT helper");
 MODULE_ALIAS("ip_nat_ftp");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* FIXME: Time out? --RR */
 
 static int
@@ -47,7 +41,7 @@
 	sprintf(buffer, "%u,%u,%u,%u,%u,%u",
 		NIPQUAD(newip), port>>8, port&0xFF);
 
-	DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+	pr_debug("calling nf_nat_mangle_tcp_packet\n");
 
 	return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
 					matchlen, buffer, strlen(buffer));
@@ -67,7 +61,7 @@
 
 	sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port);
 
-	DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+	pr_debug("calling nf_nat_mangle_tcp_packet\n");
 
 	return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
 					matchlen, buffer, strlen(buffer));
@@ -87,7 +81,7 @@
 
 	sprintf(buffer, "|||%u|", port);
 
-	DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+	pr_debug("calling nf_nat_mangle_tcp_packet\n");
 
 	return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
 					matchlen, buffer, strlen(buffer));
@@ -117,7 +111,7 @@
 	int dir = CTINFO2DIR(ctinfo);
 	struct nf_conn *ct = exp->master;
 
-	DEBUGP("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen);
+	pr_debug("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen);
 
 	/* Connection will come from wherever this packet goes, hence !dir */
 	newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
@@ -131,7 +125,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
 		exp->tuple.dst.u.tcp.port = htons(port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -139,7 +133,7 @@
 		return NF_DROP;
 
 	if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo)) {
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		return NF_DROP;
 	}
 	return NF_ACCEPT;
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index c5d2a2d..c1b059a 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -21,12 +21,6 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <linux/netfilter/nf_conntrack_h323.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /****************************************************************************/
 static int set_addr(struct sk_buff **pskb,
 		    unsigned char **data, int dataoff,
@@ -126,12 +120,11 @@
 				    (ntohl(addr.ip) & 0xff000000) == 0x7f000000)
 					i = 0;
 
-				DEBUGP
-				    ("nf_nat_ras: set signal address "
-				     "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-				     NIPQUAD(ip), port,
-				     NIPQUAD(ct->tuplehash[!dir].tuple.dst.
-					     ip), info->sig_port[!dir]);
+				pr_debug("nf_nat_ras: set signal address "
+					 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+					 NIPQUAD(addr.ip), port,
+					 NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
+					 info->sig_port[!dir]);
 				return set_h225_addr(pskb, data, 0, &taddr[i],
 						     &ct->tuplehash[!dir].
 						     tuple.dst.u3,
@@ -139,12 +132,11 @@
 			} else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
 				   port == info->sig_port[dir]) {
 				/* GK->GW */
-				DEBUGP
-				    ("nf_nat_ras: set signal address "
-				     "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-				     NIPQUAD(ip), port,
-				     NIPQUAD(ct->tuplehash[!dir].tuple.src.
-					     ip), info->sig_port[!dir]);
+				pr_debug("nf_nat_ras: set signal address "
+					 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+					 NIPQUAD(addr.ip), port,
+					 NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip),
+					 info->sig_port[!dir]);
 				return set_h225_addr(pskb, data, 0, &taddr[i],
 						     &ct->tuplehash[!dir].
 						     tuple.src.u3,
@@ -171,12 +163,11 @@
 		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
 		    addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
 		    port == ct->tuplehash[dir].tuple.src.u.udp.port) {
-			DEBUGP("nf_nat_ras: set rasAddress "
-			       "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-			       NIPQUAD(ip), ntohs(port),
-			       NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
-			       ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
-				     port));
+			pr_debug("nf_nat_ras: set rasAddress "
+				 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+				 NIPQUAD(addr.ip), ntohs(port),
+				 NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
+				 ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));
 			return set_h225_addr(pskb, data, 0, &taddr[i],
 					     &ct->tuplehash[!dir].tuple.dst.u3,
 					     ct->tuplehash[!dir].tuple.
@@ -237,12 +228,12 @@
 	for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
 	     nated_port != 0; nated_port += 2) {
 		rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
-		if (nf_conntrack_expect_related(rtp_exp) == 0) {
+		if (nf_ct_expect_related(rtp_exp) == 0) {
 			rtcp_exp->tuple.dst.u.udp.port =
 			    htons(nated_port + 1);
-			if (nf_conntrack_expect_related(rtcp_exp) == 0)
+			if (nf_ct_expect_related(rtcp_exp) == 0)
 				break;
-			nf_conntrack_unexpect_related(rtp_exp);
+			nf_ct_unexpect_related(rtp_exp);
 		}
 	}
 
@@ -261,22 +252,22 @@
 		info->rtp_port[i][dir] = rtp_port;
 		info->rtp_port[i][!dir] = htons(nated_port);
 	} else {
-		nf_conntrack_unexpect_related(rtp_exp);
-		nf_conntrack_unexpect_related(rtcp_exp);
+		nf_ct_unexpect_related(rtp_exp);
+		nf_ct_unexpect_related(rtcp_exp);
 		return -1;
 	}
 
 	/* Success */
-	DEBUGP("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(rtp_exp->tuple.src.ip),
-	       ntohs(rtp_exp->tuple.src.u.udp.port),
-	       NIPQUAD(rtp_exp->tuple.dst.ip),
-	       ntohs(rtp_exp->tuple.dst.u.udp.port));
-	DEBUGP("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(rtcp_exp->tuple.src.ip),
-	       ntohs(rtcp_exp->tuple.src.u.udp.port),
-	       NIPQUAD(rtcp_exp->tuple.dst.ip),
-	       ntohs(rtcp_exp->tuple.dst.u.udp.port));
+	pr_debug("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(rtp_exp->tuple.src.u3.ip),
+		 ntohs(rtp_exp->tuple.src.u.udp.port),
+		 NIPQUAD(rtp_exp->tuple.dst.u3.ip),
+		 ntohs(rtp_exp->tuple.dst.u.udp.port));
+	pr_debug("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(rtcp_exp->tuple.src.u3.ip),
+		 ntohs(rtcp_exp->tuple.src.u.udp.port),
+		 NIPQUAD(rtcp_exp->tuple.dst.u3.ip),
+		 ntohs(rtcp_exp->tuple.dst.u.udp.port));
 
 	return 0;
 }
@@ -299,7 +290,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (; nated_port != 0; nated_port++) {
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -313,13 +304,15 @@
 	if (set_h245_addr(pskb, data, dataoff, taddr,
 			  &ct->tuplehash[!dir].tuple.dst.u3,
 			  htons(nated_port)) < 0) {
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		return -1;
 	}
 
-	DEBUGP("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
-	       NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+	pr_debug("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(exp->tuple.src.u3.ip),
+		 ntohs(exp->tuple.src.u.tcp.port),
+		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
 }
@@ -347,7 +340,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (; nated_port != 0; nated_port++) {
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -365,13 +358,15 @@
 		info->sig_port[dir] = port;
 		info->sig_port[!dir] = htons(nated_port);
 	} else {
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		return -1;
 	}
 
-	DEBUGP("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
-	       NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+	pr_debug("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(exp->tuple.src.u3.ip),
+		 ntohs(exp->tuple.src.u.tcp.port),
+		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
 }
@@ -433,7 +428,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (; nated_port != 0; nated_port++) {
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -460,14 +455,16 @@
 				      info->sig_port[!dir]);
 		}
 	} else {
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		return -1;
 	}
 
 	/* Success */
-	DEBUGP("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
-	       NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+	pr_debug("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(exp->tuple.src.u3.ip),
+		 ntohs(exp->tuple.src.u.tcp.port),
+		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
 }
@@ -517,7 +514,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
 		exp->tuple.dst.u.tcp.port = htons(nated_port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -531,15 +528,17 @@
 	if (!set_h225_addr(pskb, data, dataoff, taddr,
 			   &ct->tuplehash[!dir].tuple.dst.u3,
 			   htons(nated_port)) == 0) {
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		return -1;
 	}
 
 	/* Success */
-	DEBUGP("nf_nat_q931: expect Call Forwarding "
-	       "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
-	       NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
-	       NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+	pr_debug("nf_nat_q931: expect Call Forwarding "
+		 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+		 NIPQUAD(exp->tuple.src.u3.ip),
+		 ntohs(exp->tuple.src.u.tcp.port),
+		 NIPQUAD(exp->tuple.dst.u3.ip),
+		 ntohs(exp->tuple.dst.u.tcp.port));
 
 	return 0;
 }
@@ -566,8 +565,6 @@
 	rcu_assign_pointer(nat_h245_hook, nat_h245);
 	rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
 	rcu_assign_pointer(nat_q931_hook, nat_q931);
-
-	DEBUGP("nf_nat_h323: init success\n");
 	return 0;
 }
 
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 15b6e5c..93d8a0a 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -26,13 +26,9 @@
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_helper.h>
 
-#if 0
-#define DEBUGP printk
-#define DUMP_OFFSET(x)	printk("offset_before=%d, offset_after=%d, correction_pos=%u\n", x->offset_before, x->offset_after, x->correction_pos);
-#else
-#define DEBUGP(format, args...)
-#define DUMP_OFFSET(x)
-#endif
+#define DUMP_OFFSET(x) \
+	pr_debug("offset_before=%d, offset_after=%d, correction_pos=%u\n", \
+		 x->offset_before, x->offset_after, x->correction_pos);
 
 static DEFINE_SPINLOCK(nf_nat_seqofs_lock);
 
@@ -47,15 +43,15 @@
 	struct nf_nat_seq *this_way, *other_way;
 	struct nf_conn_nat *nat = nfct_nat(ct);
 
-	DEBUGP("nf_nat_resize_packet: old_size = %u, new_size = %u\n",
-		(*skb)->len, new_size);
+	pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n",
+		 ntohl(seq), seq);
 
 	dir = CTINFO2DIR(ctinfo);
 
-	this_way = &nat->info.seq[dir];
-	other_way = &nat->info.seq[!dir];
+	this_way = &nat->seq[dir];
+	other_way = &nat->seq[!dir];
 
-	DEBUGP("nf_nat_resize_packet: Seq_offset before: ");
+	pr_debug("nf_nat_resize_packet: Seq_offset before: ");
 	DUMP_OFFSET(this_way);
 
 	spin_lock_bh(&nf_nat_seqofs_lock);
@@ -72,7 +68,7 @@
 	}
 	spin_unlock_bh(&nf_nat_seqofs_lock);
 
-	DEBUGP("nf_nat_resize_packet: Seq_offset after: ");
+	pr_debug("nf_nat_resize_packet: Seq_offset after: ");
 	DUMP_OFFSET(this_way);
 }
 
@@ -100,14 +96,12 @@
 
 	/* update skb info */
 	if (rep_len > match_len) {
-		DEBUGP("nf_nat_mangle_packet: Extending packet by "
-		       "%u from %u bytes\n", rep_len - match_len,
-		       skb->len);
+		pr_debug("nf_nat_mangle_packet: Extending packet by "
+			 "%u from %u bytes\n", rep_len - match_len, skb->len);
 		skb_put(skb, rep_len - match_len);
 	} else {
-		DEBUGP("nf_nat_mangle_packet: Shrinking packet from "
-		       "%u from %u bytes\n", match_len - rep_len,
-		       skb->len);
+		pr_debug("nf_nat_mangle_packet: Shrinking packet from "
+			 "%u from %u bytes\n", match_len - rep_len, skb->len);
 		__skb_trim(skb, skb->len + rep_len - match_len);
 	}
 
@@ -178,7 +172,7 @@
 	datalen = (*pskb)->len - iph->ihl*4;
 	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
 		if (!(rt->rt_flags & RTCF_LOCAL) &&
-		    (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
+		    (*pskb)->dev->features & NETIF_F_V4_CSUM) {
 			(*pskb)->ip_summed = CHECKSUM_PARTIAL;
 			(*pskb)->csum_start = skb_headroom(*pskb) +
 					      skb_network_offset(*pskb) +
@@ -190,7 +184,7 @@
 			tcph->check = 0;
 			tcph->check = tcp_v4_check(datalen,
 						   iph->saddr, iph->daddr,
-						   csum_partial((char *)tcph,
+						   csum_partial(tcph,
 								datalen, 0));
 		}
 	} else
@@ -265,7 +259,7 @@
 
 	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
 		if (!(rt->rt_flags & RTCF_LOCAL) &&
-		    (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
+		    (*pskb)->dev->features & NETIF_F_V4_CSUM) {
 			(*pskb)->ip_summed = CHECKSUM_PARTIAL;
 			(*pskb)->csum_start = skb_headroom(*pskb) +
 					      skb_network_offset(*pskb) +
@@ -278,7 +272,7 @@
 			udph->check = 0;
 			udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
 							datalen, IPPROTO_UDP,
-							csum_partial((char *)udph,
+							csum_partial(udph,
 								     datalen, 0));
 			if (!udph->check)
 				udph->check = CSUM_MANGLED_0;
@@ -320,9 +314,9 @@
 			new_end_seq = htonl(ntohl(sack->end_seq)
 				      - natseq->offset_before);
 
-		DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
-			ntohl(sack->start_seq), new_start_seq,
-			ntohl(sack->end_seq), new_end_seq);
+		pr_debug("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
+			 ntohl(sack->start_seq), new_start_seq,
+			 ntohl(sack->end_seq), new_end_seq);
 
 		nf_proto_csum_replace4(&tcph->check, skb,
 				       sack->start_seq, new_start_seq, 0);
@@ -372,8 +366,7 @@
 			    op[1] >= 2+TCPOLEN_SACK_PERBLOCK &&
 			    ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0)
 				sack_adjust(*pskb, tcph, optoff+2,
-					    optoff+op[1],
-					    &nat->info.seq[!dir]);
+					    optoff+op[1], &nat->seq[!dir]);
 			optoff += op[1];
 		}
 	}
@@ -394,8 +387,8 @@
 
 	dir = CTINFO2DIR(ctinfo);
 
-	this_way = &nat->info.seq[dir];
-	other_way = &nat->info.seq[!dir];
+	this_way = &nat->seq[dir];
+	other_way = &nat->seq[!dir];
 
 	if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
 		return 0;
@@ -415,9 +408,9 @@
 	nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
 	nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);
 
-	DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
-		ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
-		ntohl(newack));
+	pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n",
+		 ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
+		 ntohl(newack));
 
 	tcph->seq = newseq;
 	tcph->ack_seq = newack;
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c
index 9b8c0da..bcf274b 100644
--- a/net/ipv4/netfilter/nf_nat_irc.c
+++ b/net/ipv4/netfilter/nf_nat_irc.c
@@ -22,12 +22,6 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <linux/netfilter/nf_conntrack_irc.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
 MODULE_DESCRIPTION("IRC (DCC) NAT helper");
 MODULE_LICENSE("GPL");
@@ -44,9 +38,6 @@
 	u_int16_t port;
 	unsigned int ret;
 
-	DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
-	       expect->seq, exp_irc_info->len, ntohl(tcph->seq));
-
 	/* Reply comes from server. */
 	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
 	exp->dir = IP_CT_DIR_REPLY;
@@ -55,7 +46,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
 		exp->tuple.dst.u.tcp.port = htons(port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -64,14 +55,14 @@
 
 	ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
 	sprintf(buffer, "%u %u", ip, port);
-	DEBUGP("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
-	       buffer, NIPQUAD(ip), port);
+	pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
+		 buffer, NIPQUAD(ip), port);
 
 	ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
 				       matchoff, matchlen, buffer,
 				       strlen(buffer));
 	if (ret != NF_ACCEPT)
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 	return ret;
 }
 
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index a668887..984ec83 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -37,14 +37,6 @@
 MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
 MODULE_ALIAS("ip_nat_pptp");
 
-#if 0
-extern const char *pptp_msg_name[];
-#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
-				       __FUNCTION__, ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static void pptp_nat_expected(struct nf_conn *ct,
 			      struct nf_conntrack_expect *exp)
 {
@@ -60,7 +52,7 @@
 
 	/* And here goes the grand finale of corrosion... */
 	if (exp->dir == IP_CT_DIR_ORIGINAL) {
-		DEBUGP("we are PNS->PAC\n");
+		pr_debug("we are PNS->PAC\n");
 		/* therefore, build tuple for PAC->PNS */
 		t.src.l3num = AF_INET;
 		t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip;
@@ -69,7 +61,7 @@
 		t.dst.u.gre.key = ct_pptp_info->pns_call_id;
 		t.dst.protonum = IPPROTO_GRE;
 	} else {
-		DEBUGP("we are PAC->PNS\n");
+		pr_debug("we are PAC->PNS\n");
 		/* build tuple for PNS->PAC */
 		t.src.l3num = AF_INET;
 		t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip;
@@ -79,15 +71,15 @@
 		t.dst.protonum = IPPROTO_GRE;
 	}
 
-	DEBUGP("trying to unexpect other dir: ");
+	pr_debug("trying to unexpect other dir: ");
 	NF_CT_DUMP_TUPLE(&t);
-	other_exp = nf_conntrack_expect_find_get(&t);
+	other_exp = nf_ct_expect_find_get(&t);
 	if (other_exp) {
-		nf_conntrack_unexpect_related(other_exp);
-		nf_conntrack_expect_put(other_exp);
-		DEBUGP("success\n");
+		nf_ct_unexpect_related(other_exp);
+		nf_ct_expect_put(other_exp);
+		pr_debug("success\n");
 	} else {
-		DEBUGP("not found!\n");
+		pr_debug("not found!\n");
 	}
 
 	/* This must be a fresh one. */
@@ -161,9 +153,9 @@
 		cid_off = offsetof(union pptp_ctrl_union, clrreq.callID);
 		break;
 	default:
-		DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
-		      (msg <= PPTP_MSG_MAX)?
-		      pptp_msg_name[msg]:pptp_msg_name[0]);
+		pr_debug("unknown outbound packet 0x%04x:%s\n", msg,
+			 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] :
+					       pptp_msg_name[0]);
 		/* fall through */
 	case PPTP_SET_LINK_INFO:
 		/* only need to NAT in case PAC is behind NAT box */
@@ -179,8 +171,8 @@
 
 	/* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
 	 * down to here */
-	DEBUGP("altering call id from 0x%04x to 0x%04x\n",
-		ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
+	pr_debug("altering call id from 0x%04x to 0x%04x\n",
+		 ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
 
 	/* mangle packet */
 	if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
@@ -255,8 +247,9 @@
 		pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID);
 		break;
 	default:
-		DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)?
-			pptp_msg_name[msg]:pptp_msg_name[0]);
+		pr_debug("unknown inbound packet %s\n",
+			 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] :
+					       pptp_msg_name[0]);
 		/* fall through */
 	case PPTP_START_SESSION_REQUEST:
 	case PPTP_START_SESSION_REPLY:
@@ -272,8 +265,8 @@
 	 * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */
 
 	/* mangle packet */
-	DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
-		ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
+	pr_debug("altering peer call id from 0x%04x to 0x%04x\n",
+		 ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
 
 	if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
 				     pcid_off + sizeof(struct pptp_pkt_hdr) +
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
index c3908bc..2e40cc8 100644
--- a/net/ipv4/netfilter/nf_nat_proto_gre.c
+++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
@@ -36,13 +36,6 @@
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
 MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
 
-#if 0
-#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
-				       __FUNCTION__, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
 /* is key in given range between min and max */
 static int
 gre_in_range(const struct nf_conntrack_tuple *tuple,
@@ -83,7 +76,7 @@
 		keyptr = &tuple->dst.u.gre.key;
 
 	if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
-		DEBUGP("%p: NATing GRE PPTP\n", conntrack);
+		pr_debug("%p: NATing GRE PPTP\n", conntrack);
 		min = 1;
 		range_size = 0xffff;
 	} else {
@@ -91,7 +84,7 @@
 		range_size = ntohs(range->max.gre.key) - min + 1;
 	}
 
-	DEBUGP("min = %u, range_size = %u\n", min, range_size);
+	pr_debug("min = %u, range_size = %u\n", min, range_size);
 
 	for (i = 0; i < range_size; i++, key++) {
 		*keyptr = htons(min + key % range_size);
@@ -99,7 +92,7 @@
 			return 1;
 	}
 
-	DEBUGP("%p: no NAT mapping\n", conntrack);
+	pr_debug("%p: no NAT mapping\n", conntrack);
 	return 0;
 }
 
@@ -132,11 +125,11 @@
 		 * Try to behave like "nf_nat_proto_unknown" */
 		break;
 	case GRE_VERSION_PPTP:
-		DEBUGP("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
+		pr_debug("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
 		pgreh->call_id = tuple->dst.u.gre.key;
 		break;
 	default:
-		DEBUGP("can't nat unknown GRE version\n");
+		pr_debug("can't nat unknown GRE version\n");
 		return 0;
 	}
 	return 1;
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 6740736..0f45427 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -24,12 +24,6 @@
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_rule.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 #define NAT_VALID_HOOKS ((1<<NF_IP_PRE_ROUTING) | (1<<NF_IP_POST_ROUTING) | (1<<NF_IP_LOCAL_OUT))
 
 static struct
@@ -140,39 +134,39 @@
 	return nf_nat_setup_info(ct, &mr->range[0], hooknum);
 }
 
-static int ipt_snat_checkentry(const char *tablename,
-			       const void *entry,
-			       const struct xt_target *target,
-			       void *targinfo,
-			       unsigned int hook_mask)
+static bool ipt_snat_checkentry(const char *tablename,
+				const void *entry,
+				const struct xt_target *target,
+				void *targinfo,
+				unsigned int hook_mask)
 {
 	struct nf_nat_multi_range_compat *mr = targinfo;
 
 	/* Must be a valid range */
 	if (mr->rangesize != 1) {
 		printk("SNAT: multiple ranges no longer supported\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static int ipt_dnat_checkentry(const char *tablename,
-			       const void *entry,
-			       const struct xt_target *target,
-			       void *targinfo,
-			       unsigned int hook_mask)
+static bool ipt_dnat_checkentry(const char *tablename,
+				const void *entry,
+				const struct xt_target *target,
+				void *targinfo,
+				unsigned int hook_mask)
 {
 	struct nf_nat_multi_range_compat *mr = targinfo;
 
 	/* Must be a valid range */
 	if (mr->rangesize != 1) {
 		printk("DNAT: multiple ranges no longer supported\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-inline unsigned int
+unsigned int
 alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
 {
 	/* Force range to this IP; let proto decide mapping for
@@ -186,8 +180,8 @@
 	struct nf_nat_range range
 		= { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } };
 
-	DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n",
-	       ct, NIPQUAD(ip));
+	pr_debug("Allocating NULL binding for %p (%u.%u.%u.%u)\n",
+		 ct, NIPQUAD(ip));
 	return nf_nat_setup_info(ct, &range, hooknum);
 }
 
@@ -205,8 +199,8 @@
 	struct nf_nat_range range
 		= { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
 
-	DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
-	       ct, NIPQUAD(ip));
+	pr_debug("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
+		 ct, NIPQUAD(ip));
 	return nf_nat_setup_info(ct, &range, hooknum);
 }
 
@@ -228,7 +222,7 @@
 	return ret;
 }
 
-static struct xt_target ipt_snat_reg = {
+static struct xt_target ipt_snat_reg __read_mostly = {
 	.name		= "SNAT",
 	.target		= ipt_snat_target,
 	.targetsize	= sizeof(struct nf_nat_multi_range_compat),
@@ -238,7 +232,7 @@
 	.family		= AF_INET,
 };
 
-static struct xt_target ipt_dnat_reg = {
+static struct xt_target ipt_dnat_reg __read_mostly = {
 	.name		= "DNAT",
 	.target		= ipt_dnat_target,
 	.targetsize	= sizeof(struct nf_nat_multi_range_compat),
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index fac97cf..a889ec3 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -26,12 +26,6 @@
 MODULE_DESCRIPTION("SIP NAT helper");
 MODULE_ALIAS("ip_nat_sip");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 struct addr_map {
 	struct {
 		char		src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
@@ -257,10 +251,12 @@
 	__be32 newip;
 	u_int16_t port;
 
-	DEBUGP("ip_nat_sdp():\n");
-
 	/* Connection will come from reply */
-	newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+	if (ct->tuplehash[dir].tuple.src.u3.ip ==
+	    ct->tuplehash[!dir].tuple.dst.u3.ip)
+		newip = exp->tuple.dst.u3.ip;
+	else
+		newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
 
 	exp->saved_ip = exp->tuple.dst.u3.ip;
 	exp->tuple.dst.u3.ip = newip;
@@ -274,7 +270,7 @@
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
 		exp->tuple.dst.u.udp.port = htons(port);
-		if (nf_conntrack_expect_related(exp) == 0)
+		if (nf_ct_expect_related(exp) == 0)
 			break;
 	}
 
@@ -282,7 +278,7 @@
 		return NF_DROP;
 
 	if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		return NF_DROP;
 	}
 	return NF_ACCEPT;
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index 6e88505..6bfcd3a 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -1276,9 +1276,6 @@
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.udp.port	= __constant_htons(SNMP_PORT),
 	.tuple.dst.protonum	= IPPROTO_UDP,
-	.mask.src.l3num		= 0xFFFF,
-	.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-	.mask.dst.protonum	= 0xFF,
 };
 
 static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
@@ -1290,9 +1287,6 @@
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.udp.port	= __constant_htons(SNMP_TRAP_PORT),
 	.tuple.dst.protonum	= IPPROTO_UDP,
-	.mask.src.l3num		= 0xFFFF,
-	.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-	.mask.dst.protonum	= 0xFF,
 };
 
 /*****************************************************************************
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 55dac36..332814d 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -19,6 +19,7 @@
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 #include <net/netfilter/nf_nat.h>
 #include <net/netfilter/nf_nat_rule.h>
 #include <net/netfilter/nf_nat_protocol.h>
@@ -26,12 +27,6 @@
 #include <net/netfilter/nf_nat_helper.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 #ifdef CONFIG_XFRM
 static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
 {
@@ -113,8 +108,13 @@
 		return NF_ACCEPT;
 
 	nat = nfct_nat(ct);
-	if (!nat)
-		return NF_ACCEPT;
+	if (!nat) {
+		nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
+		if (nat == NULL) {
+			pr_debug("failed to add NAT extension\n");
+			return NF_ACCEPT;
+		}
+	}
 
 	switch (ctinfo) {
 	case IP_CT_RELATED:
@@ -148,9 +148,9 @@
 				return ret;
 			}
 		} else
-			DEBUGP("Already setup manip %s for ct %p\n",
-			       maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
-			       ct);
+			pr_debug("Already setup manip %s for ct %p\n",
+				 maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
+				 ct);
 		break;
 
 	default:
@@ -264,7 +264,7 @@
 
 	ct = nf_ct_get(*pskb, &ctinfo);
 	if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
-		DEBUGP("nf_nat_standalone: adjusting sequence number\n");
+		pr_debug("nf_nat_standalone: adjusting sequence number\n");
 		if (!nf_nat_seq_adjust(pskb, ct, ctinfo))
 			return NF_DROP;
 	}
@@ -326,26 +326,10 @@
 
 static int __init nf_nat_standalone_init(void)
 {
-	int size, ret = 0;
+	int ret = 0;
 
 	need_conntrack();
 
-	size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) +
-	       sizeof(struct nf_conn_nat);
-	ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size);
-	if (ret < 0) {
-		printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
-		return ret;
-	}
-
-	size = ALIGN(size, __alignof__(struct nf_conn_help)) +
-	       sizeof(struct nf_conn_help);
-	ret = nf_conntrack_register_cache(NF_CT_F_NAT|NF_CT_F_HELP,
-					  "nf_nat:help", size);
-	if (ret < 0) {
-		printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
-		goto cleanup_register_cache;
-	}
 #ifdef CONFIG_XFRM
 	BUG_ON(ip_nat_decode_session != NULL);
 	ip_nat_decode_session = nat_decode_session;
@@ -360,7 +344,6 @@
 		printk("nf_nat_init: can't register hooks.\n");
 		goto cleanup_rule_init;
 	}
-	nf_nat_module_is_loaded = 1;
 	return ret;
 
  cleanup_rule_init:
@@ -370,9 +353,6 @@
 	ip_nat_decode_session = NULL;
 	synchronize_net();
 #endif
-	nf_conntrack_unregister_cache(NF_CT_F_NAT|NF_CT_F_HELP);
- cleanup_register_cache:
-	nf_conntrack_unregister_cache(NF_CT_F_NAT);
 	return ret;
 }
 
@@ -380,7 +360,6 @@
 {
 	nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
 	nf_nat_rule_cleanup();
-	nf_nat_module_is_loaded = 0;
 #ifdef CONFIG_XFRM
 	ip_nat_decode_session = NULL;
 	synchronize_net();
diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c
index 2566b79..04dfeae 100644
--- a/net/ipv4/netfilter/nf_nat_tftp.c
+++ b/net/ipv4/netfilter/nf_nat_tftp.c
@@ -30,7 +30,7 @@
 		= ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
 	exp->dir = IP_CT_DIR_REPLY;
 	exp->expectfn = nf_nat_follow_master;
-	if (nf_conntrack_expect_related(exp) != 0)
+	if (nf_ct_expect_related(exp) != 0)
 		return NF_DROP;
 	return NF_ACCEPT;
 }
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 29ca63e..88fa648 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -101,7 +101,6 @@
 #include <net/tcp.h>
 #include <net/icmp.h>
 #include <net/xfrm.h>
-#include <net/ip_mp_alg.h>
 #include <net/netevent.h>
 #include <net/rtnetlink.h>
 #ifdef CONFIG_SYSCTL
@@ -168,7 +167,7 @@
 
 #define ECN_OR_COST(class)	TC_PRIO_##class
 
-__u8 ip_tos2prio[16] = {
+const __u8 ip_tos2prio[16] = {
 	TC_PRIO_BESTEFFORT,
 	ECN_OR_COST(FILLER),
 	TC_PRIO_BESTEFFORT,
@@ -495,13 +494,11 @@
 
 static __inline__ void rt_free(struct rtable *rt)
 {
-	multipath_remove(rt);
 	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
 static __inline__ void rt_drop(struct rtable *rt)
 {
-	multipath_remove(rt);
 	ip_rt_put(rt);
 	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
@@ -574,52 +571,6 @@
 		(fl1->iif ^ fl2->iif)) == 0;
 }
 
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-static struct rtable **rt_remove_balanced_route(struct rtable **chain_head,
-						struct rtable *expentry,
-						int *removed_count)
-{
-	int passedexpired = 0;
-	struct rtable **nextstep = NULL;
-	struct rtable **rthp = chain_head;
-	struct rtable *rth;
-
-	if (removed_count)
-		*removed_count = 0;
-
-	while ((rth = *rthp) != NULL) {
-		if (rth == expentry)
-			passedexpired = 1;
-
-		if (((*rthp)->u.dst.flags & DST_BALANCED) != 0  &&
-		    compare_keys(&(*rthp)->fl, &expentry->fl)) {
-			if (*rthp == expentry) {
-				*rthp = rth->u.dst.rt_next;
-				continue;
-			} else {
-				*rthp = rth->u.dst.rt_next;
-				rt_free(rth);
-				if (removed_count)
-					++(*removed_count);
-			}
-		} else {
-			if (!((*rthp)->u.dst.flags & DST_BALANCED) &&
-			    passedexpired && !nextstep)
-				nextstep = &rth->u.dst.rt_next;
-
-			rthp = &rth->u.dst.rt_next;
-		}
-	}
-
-	rt_free(expentry);
-	if (removed_count)
-		++(*removed_count);
-
-	return nextstep;
-}
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
-
-
 /* This runs via a timer and thus is always in BH context. */
 static void rt_check_expire(unsigned long dummy)
 {
@@ -658,22 +609,8 @@
 			}
 
 			/* Cleanup aged off entries. */
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-			/* remove all related balanced entries if necessary */
-			if (rth->u.dst.flags & DST_BALANCED) {
-				rthp = rt_remove_balanced_route(
-					&rt_hash_table[i].chain,
-					rth, NULL);
-				if (!rthp)
-					break;
-			} else {
-				*rthp = rth->u.dst.rt_next;
-				rt_free(rth);
-			}
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
 			*rthp = rth->u.dst.rt_next;
 			rt_free(rth);
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
 		}
 		spin_unlock(rt_hash_lock_addr(i));
 
@@ -721,9 +658,6 @@
 	if (delay < 0)
 		delay = ip_rt_min_delay;
 
-	/* flush existing multipath state*/
-	multipath_flush();
-
 	spin_lock_bh(&rt_flush_lock);
 
 	if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) {
@@ -842,30 +776,9 @@
 					rthp = &rth->u.dst.rt_next;
 					continue;
 				}
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-				/* remove all related balanced entries
-				 * if necessary
-				 */
-				if (rth->u.dst.flags & DST_BALANCED) {
-					int r;
-
-					rthp = rt_remove_balanced_route(
-						&rt_hash_table[k].chain,
-						rth,
-						&r);
-					goal -= r;
-					if (!rthp)
-						break;
-				} else {
-					*rthp = rth->u.dst.rt_next;
-					rt_free(rth);
-					goal--;
-				}
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
 				*rthp = rth->u.dst.rt_next;
 				rt_free(rth);
 				goal--;
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
 			}
 			spin_unlock_bh(rt_hash_lock_addr(k));
 			if (goal <= 0)
@@ -939,12 +852,7 @@
 
 	spin_lock_bh(rt_hash_lock_addr(hash));
 	while ((rth = *rthp) != NULL) {
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-		if (!(rth->u.dst.flags & DST_BALANCED) &&
-		    compare_keys(&rth->fl, &rt->fl)) {
-#else
 		if (compare_keys(&rth->fl, &rt->fl)) {
-#endif
 			/* Put it first */
 			*rthp = rth->u.dst.rt_next;
 			/*
@@ -1774,10 +1682,6 @@
 
 	atomic_set(&rth->u.dst.__refcnt, 1);
 	rth->u.dst.flags= DST_HOST;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	if (res->fi->fib_nhs > 1)
-		rth->u.dst.flags |= DST_BALANCED;
-#endif
 	if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
 		rth->u.dst.flags |= DST_NOPOLICY;
 	if (IN_DEV_CONF_GET(out_dev, NOXFRM))
@@ -1812,11 +1716,11 @@
 	return err;
 }
 
-static inline int ip_mkroute_input_def(struct sk_buff *skb,
-				       struct fib_result* res,
-				       const struct flowi *fl,
-				       struct in_device *in_dev,
-				       __be32 daddr, __be32 saddr, u32 tos)
+static inline int ip_mkroute_input(struct sk_buff *skb,
+				   struct fib_result* res,
+				   const struct flowi *fl,
+				   struct in_device *in_dev,
+				   __be32 daddr, __be32 saddr, u32 tos)
 {
 	struct rtable* rth = NULL;
 	int err;
@@ -1837,63 +1741,6 @@
 	return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
 }
 
-static inline int ip_mkroute_input(struct sk_buff *skb,
-				   struct fib_result* res,
-				   const struct flowi *fl,
-				   struct in_device *in_dev,
-				   __be32 daddr, __be32 saddr, u32 tos)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	struct rtable* rth = NULL, *rtres;
-	unsigned char hop, hopcount;
-	int err = -EINVAL;
-	unsigned int hash;
-
-	if (res->fi)
-		hopcount = res->fi->fib_nhs;
-	else
-		hopcount = 1;
-
-	/* distinguish between multipath and singlepath */
-	if (hopcount < 2)
-		return ip_mkroute_input_def(skb, res, fl, in_dev, daddr,
-					    saddr, tos);
-
-	/* add all alternatives to the routing cache */
-	for (hop = 0; hop < hopcount; hop++) {
-		res->nh_sel = hop;
-
-		/* put reference to previous result */
-		if (hop)
-			ip_rt_put(rtres);
-
-		/* create a routing cache entry */
-		err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos,
-				      &rth);
-		if (err)
-			return err;
-
-		/* put it into the cache */
-		hash = rt_hash(daddr, saddr, fl->iif);
-		err = rt_intern_hash(hash, rth, &rtres);
-		if (err)
-			return err;
-
-		/* forward hop information to multipath impl. */
-		multipath_set_nhinfo(rth,
-				     FIB_RES_NETWORK(*res),
-				     FIB_RES_NETMASK(*res),
-				     res->prefixlen,
-				     &FIB_RES_NH(*res));
-	}
-	skb->dst = &rtres->u.dst;
-	return err;
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED  */
-	return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED  */
-}
-
-
 /*
  *	NOTE. We drop all the packets that has local source
  *	addresses, because every properly looped back packet
@@ -2211,13 +2058,6 @@
 
 	atomic_set(&rth->u.dst.__refcnt, 1);
 	rth->u.dst.flags= DST_HOST;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	if (res->fi) {
-		rth->rt_multipath_alg = res->fi->fib_mp_alg;
-		if (res->fi->fib_nhs > 1)
-			rth->u.dst.flags |= DST_BALANCED;
-	}
-#endif
 	if (IN_DEV_CONF_GET(in_dev, NOXFRM))
 		rth->u.dst.flags |= DST_NOXFRM;
 	if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
@@ -2277,12 +2117,12 @@
 	return err;
 }
 
-static inline int ip_mkroute_output_def(struct rtable **rp,
-					struct fib_result* res,
-					const struct flowi *fl,
-					const struct flowi *oldflp,
-					struct net_device *dev_out,
-					unsigned flags)
+static inline int ip_mkroute_output(struct rtable **rp,
+				    struct fib_result* res,
+				    const struct flowi *fl,
+				    const struct flowi *oldflp,
+				    struct net_device *dev_out,
+				    unsigned flags)
 {
 	struct rtable *rth = NULL;
 	int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
@@ -2295,68 +2135,6 @@
 	return err;
 }
 
-static inline int ip_mkroute_output(struct rtable** rp,
-				    struct fib_result* res,
-				    const struct flowi *fl,
-				    const struct flowi *oldflp,
-				    struct net_device *dev_out,
-				    unsigned flags)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	unsigned char hop;
-	unsigned hash;
-	int err = -EINVAL;
-	struct rtable *rth = NULL;
-
-	if (res->fi && res->fi->fib_nhs > 1) {
-		unsigned char hopcount = res->fi->fib_nhs;
-
-		for (hop = 0; hop < hopcount; hop++) {
-			struct net_device *dev2nexthop;
-
-			res->nh_sel = hop;
-
-			/* hold a work reference to the output device */
-			dev2nexthop = FIB_RES_DEV(*res);
-			dev_hold(dev2nexthop);
-
-			/* put reference to previous result */
-			if (hop)
-				ip_rt_put(*rp);
-
-			err = __mkroute_output(&rth, res, fl, oldflp,
-					       dev2nexthop, flags);
-
-			if (err != 0)
-				goto cleanup;
-
-			hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src,
-					oldflp->oif);
-			err = rt_intern_hash(hash, rth, rp);
-
-			/* forward hop information to multipath impl. */
-			multipath_set_nhinfo(rth,
-					     FIB_RES_NETWORK(*res),
-					     FIB_RES_NETMASK(*res),
-					     res->prefixlen,
-					     &FIB_RES_NH(*res));
-		cleanup:
-			/* release work reference to output device */
-			dev_put(dev2nexthop);
-
-			if (err != 0)
-				return err;
-		}
-		return err;
-	} else {
-		return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out,
-					     flags);
-	}
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
-	return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags);
-#endif
-}
-
 /*
  * Major route resolver routine.
  */
@@ -2570,17 +2348,6 @@
 		    rth->fl.mark == flp->mark &&
 		    !((rth->fl.fl4_tos ^ flp->fl4_tos) &
 			    (IPTOS_RT_MASK | RTO_ONLINK))) {
-
-			/* check for multipath routes and choose one if
-			 * necessary
-			 */
-			if (multipath_select_route(flp, rth, rp)) {
-				dst_hold(&(*rp)->u.dst);
-				RT_CACHE_STAT_INC(out_hit);
-				rcu_read_unlock_bh();
-				return 0;
-			}
-
 			rth->u.dst.lastuse = jiffies;
 			dst_hold(&rth->u.dst);
 			rth->u.dst.__use++;
@@ -2729,10 +2496,6 @@
 	if (rt->u.dst.tclassid)
 		NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid);
 #endif
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	if (rt->rt_multipath_alg != IP_MP_ALG_NONE)
-		NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg);
-#endif
 	if (rt->fl.iif)
 		NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst);
 	else if (rt->rt_src != rt->fl.fl4_src)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 354721d..3f5f742 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2045,10 +2045,7 @@
 		struct hlist_node *node;
 		struct inet_timewait_sock *tw;
 
-		/* We can reschedule _before_ having picked the target: */
-		cond_resched_softirq();
-
-		read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+		read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
 		sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
 			if (sk->sk_family != st->family) {
 				continue;
@@ -2065,7 +2062,7 @@
 			rc = tw;
 			goto out;
 		}
-		read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
+		read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
 		st->state = TCP_SEQ_STATE_ESTABLISHED;
 	}
 out:
@@ -2092,14 +2089,11 @@
 			cur = tw;
 			goto out;
 		}
-		read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
+		read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
 		st->state = TCP_SEQ_STATE_ESTABLISHED;
 
-		/* We can reschedule between buckets: */
-		cond_resched_softirq();
-
 		if (++st->bucket < tcp_hashinfo.ehash_size) {
-			read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+			read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
 			sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
 		} else {
 			cur = NULL;
@@ -2144,7 +2138,6 @@
 
 	if (!rc) {
 		inet_listen_unlock(&tcp_hashinfo);
-		local_bh_disable();
 		st->state = TCP_SEQ_STATE_ESTABLISHED;
 		rc	  = established_get_idx(seq, pos);
 	}
@@ -2177,7 +2170,6 @@
 		rc = listening_get_next(seq, v);
 		if (!rc) {
 			inet_listen_unlock(&tcp_hashinfo);
-			local_bh_disable();
 			st->state = TCP_SEQ_STATE_ESTABLISHED;
 			rc	  = established_get_first(seq);
 		}
@@ -2209,8 +2201,7 @@
 	case TCP_SEQ_STATE_TIME_WAIT:
 	case TCP_SEQ_STATE_ESTABLISHED:
 		if (v)
-			read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
-		local_bh_enable();
+			read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
 		break;
 	}
 }
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 53232dd..20aea15 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -699,6 +699,14 @@
 			tp->fackets_out -= diff;
 			if ((int)tp->fackets_out < 0)
 				tp->fackets_out = 0;
+			/* SACK fastpath might overwrite it unless dealt with */
+			if (tp->fastpath_skb_hint != NULL &&
+			    after(TCP_SKB_CB(tp->fastpath_skb_hint)->seq,
+				  TCP_SKB_CB(skb)->seq)) {
+				tp->fastpath_cnt_hint -= diff;
+				if ((int)tp->fastpath_cnt_hint < 0)
+					tp->fastpath_cnt_hint = 0;
+			}
 		}
 	}
 
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index facb7e2..2835535 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -70,6 +70,7 @@
  *	Alexey Kuznetsov:		allow both IPv4 and IPv6 sockets to bind
  *					a single port at the same time.
  *	Derek Atkins <derek@ihtfp.com>: Add Encapulation Support
+ *	James Chapman		:	Add L2TP encapsulation type.
  *
  *
  *		This program is free software; you can redistribute it and/or
@@ -919,104 +920,6 @@
 	return 0;
 }
 
-/* return:
- * 	1  if the UDP system should process it
- *	0  if we should drop this packet
- * 	-1 if it should get processed by xfrm4_rcv_encap
- */
-static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
-{
-#ifndef CONFIG_XFRM
-	return 1;
-#else
-	struct udp_sock *up = udp_sk(sk);
-	struct udphdr *uh;
-	struct iphdr *iph;
-	int iphlen, len;
-
-	__u8 *udpdata;
-	__be32 *udpdata32;
-	__u16 encap_type = up->encap_type;
-
-	/* if we're overly short, let UDP handle it */
-	len = skb->len - sizeof(struct udphdr);
-	if (len <= 0)
-		return 1;
-
-	/* if this is not encapsulated socket, then just return now */
-	if (!encap_type)
-		return 1;
-
-	/* If this is a paged skb, make sure we pull up
-	 * whatever data we need to look at. */
-	if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
-		return 1;
-
-	/* Now we can get the pointers */
-	uh = udp_hdr(skb);
-	udpdata = (__u8 *)uh + sizeof(struct udphdr);
-	udpdata32 = (__be32 *)udpdata;
-
-	switch (encap_type) {
-	default:
-	case UDP_ENCAP_ESPINUDP:
-		/* Check if this is a keepalive packet.  If so, eat it. */
-		if (len == 1 && udpdata[0] == 0xff) {
-			return 0;
-		} else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) {
-			/* ESP Packet without Non-ESP header */
-			len = sizeof(struct udphdr);
-		} else
-			/* Must be an IKE packet.. pass it through */
-			return 1;
-		break;
-	case UDP_ENCAP_ESPINUDP_NON_IKE:
-		/* Check if this is a keepalive packet.  If so, eat it. */
-		if (len == 1 && udpdata[0] == 0xff) {
-			return 0;
-		} else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&
-			   udpdata32[0] == 0 && udpdata32[1] == 0) {
-
-			/* ESP Packet with Non-IKE marker */
-			len = sizeof(struct udphdr) + 2 * sizeof(u32);
-		} else
-			/* Must be an IKE packet.. pass it through */
-			return 1;
-		break;
-	}
-
-	/* At this point we are sure that this is an ESPinUDP packet,
-	 * so we need to remove 'len' bytes from the packet (the UDP
-	 * header and optional ESP marker bytes) and then modify the
-	 * protocol to ESP, and then call into the transform receiver.
-	 */
-	if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
-		return 0;
-
-	/* Now we can update and verify the packet length... */
-	iph = ip_hdr(skb);
-	iphlen = iph->ihl << 2;
-	iph->tot_len = htons(ntohs(iph->tot_len) - len);
-	if (skb->len < iphlen + len) {
-		/* packet is too small!?! */
-		return 0;
-	}
-
-	/* pull the data buffer up to the ESP header and set the
-	 * transport header to point to ESP.  Keep UDP on the stack
-	 * for later.
-	 */
-	__skb_pull(skb, len);
-	skb_reset_transport_header(skb);
-
-	/* modify the protocol (it's ESP!) */
-	iph->protocol = IPPROTO_ESP;
-
-	/* and let the caller know to send this into the ESP processor... */
-	return -1;
-#endif
-}
-
 /* returns:
  *  -1: error
  *   0: success
@@ -1039,28 +942,28 @@
 
 	if (up->encap_type) {
 		/*
-		 * This is an encapsulation socket, so let's see if this is
-		 * an encapsulated packet.
-		 * If it's a keepalive packet, then just eat it.
-		 * If it's an encapsulateed packet, then pass it to the
-		 * IPsec xfrm input and return the response
-		 * appropriately.  Otherwise, just fall through and
-		 * pass this up the UDP socket.
+		 * This is an encapsulation socket so pass the skb to
+		 * the socket's udp_encap_rcv() hook. Otherwise, just
+		 * fall through and pass this up the UDP socket.
+		 * up->encap_rcv() returns the following value:
+		 * =0 if skb was successfully passed to the encap
+		 *    handler or was discarded by it.
+		 * >0 if skb should be passed on to UDP.
+		 * <0 if skb should be resubmitted as proto -N
 		 */
-		int ret;
 
-		ret = udp_encap_rcv(sk, skb);
-		if (ret == 0) {
-			/* Eat the packet .. */
-			kfree_skb(skb);
-			return 0;
+		/* if we're overly short, let UDP handle it */
+		if (skb->len > sizeof(struct udphdr) &&
+		    up->encap_rcv != NULL) {
+			int ret;
+
+			ret = (*up->encap_rcv)(sk, skb);
+			if (ret <= 0) {
+				UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
+				return -ret;
+			}
 		}
-		if (ret < 0) {
-			/* process the ESP packet */
-			ret = xfrm4_rcv_encap(skb, up->encap_type);
-			UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
-			return -ret;
-		}
+
 		/* FALLTHROUGH -- it's a UDP Packet */
 	}
 
@@ -1349,6 +1252,9 @@
 		case 0:
 		case UDP_ENCAP_ESPINUDP:
 		case UDP_ENCAP_ESPINUDP_NON_IKE:
+			up->encap_rcv = xfrm4_udp_encap_rcv;
+			/* FALLTHROUGH */
+		case UDP_ENCAP_L2TPINUDP:
 			up->encap_type = val;
 			break;
 		default:
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index fa1902d..2fa1082 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -16,13 +16,6 @@
 #include <net/ip.h>
 #include <net/xfrm.h>
 
-int xfrm4_rcv(struct sk_buff *skb)
-{
-	return xfrm4_rcv_encap(skb, 0);
-}
-
-EXPORT_SYMBOL(xfrm4_rcv);
-
 static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
 {
 	switch (nexthdr) {
@@ -53,7 +46,7 @@
 }
 #endif
 
-int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
+static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
 {
 	__be32 spi, seq;
 	struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
@@ -167,3 +160,108 @@
 	kfree_skb(skb);
 	return 0;
 }
+
+/* If it's a keepalive packet, then just eat it.
+ * If it's an encapsulated packet, then pass it to the
+ * IPsec xfrm input.
+ * Returns 0 if skb passed to xfrm or was dropped.
+ * Returns >0 if skb should be passed to UDP.
+ * Returns <0 if skb should be resubmitted (-ret is protocol)
+ */
+int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
+{
+	struct udp_sock *up = udp_sk(sk);
+	struct udphdr *uh;
+	struct iphdr *iph;
+	int iphlen, len;
+	int ret;
+
+	__u8 *udpdata;
+	__be32 *udpdata32;
+	__u16 encap_type = up->encap_type;
+
+	/* if this is not encapsulated socket, then just return now */
+	if (!encap_type)
+		return 1;
+
+	/* If this is a paged skb, make sure we pull up
+	 * whatever data we need to look at. */
+	len = skb->len - sizeof(struct udphdr);
+	if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
+		return 1;
+
+	/* Now we can get the pointers */
+	uh = udp_hdr(skb);
+	udpdata = (__u8 *)uh + sizeof(struct udphdr);
+	udpdata32 = (__be32 *)udpdata;
+
+	switch (encap_type) {
+	default:
+	case UDP_ENCAP_ESPINUDP:
+		/* Check if this is a keepalive packet.  If so, eat it. */
+		if (len == 1 && udpdata[0] == 0xff) {
+			goto drop;
+		} else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) {
+			/* ESP Packet without Non-ESP header */
+			len = sizeof(struct udphdr);
+		} else
+			/* Must be an IKE packet.. pass it through */
+			return 1;
+		break;
+	case UDP_ENCAP_ESPINUDP_NON_IKE:
+		/* Check if this is a keepalive packet.  If so, eat it. */
+		if (len == 1 && udpdata[0] == 0xff) {
+			goto drop;
+		} else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&
+			   udpdata32[0] == 0 && udpdata32[1] == 0) {
+
+			/* ESP Packet with Non-IKE marker */
+			len = sizeof(struct udphdr) + 2 * sizeof(u32);
+		} else
+			/* Must be an IKE packet.. pass it through */
+			return 1;
+		break;
+	}
+
+	/* At this point we are sure that this is an ESPinUDP packet,
+	 * so we need to remove 'len' bytes from the packet (the UDP
+	 * header and optional ESP marker bytes) and then modify the
+	 * protocol to ESP, and then call into the transform receiver.
+	 */
+	if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		goto drop;
+
+	/* Now we can update and verify the packet length... */
+	iph = ip_hdr(skb);
+	iphlen = iph->ihl << 2;
+	iph->tot_len = htons(ntohs(iph->tot_len) - len);
+	if (skb->len < iphlen + len) {
+		/* packet is too small!?! */
+		goto drop;
+	}
+
+	/* pull the data buffer up to the ESP header and set the
+	 * transport header to point to ESP.  Keep UDP on the stack
+	 * for later.
+	 */
+	__skb_pull(skb, len);
+	skb_reset_transport_header(skb);
+
+	/* modify the protocol (it's ESP!) */
+	iph->protocol = IPPROTO_ESP;
+
+	/* process ESP */
+	ret = xfrm4_rcv_encap(skb, encap_type);
+	return ret;
+
+drop:
+	kfree_skb(skb);
+	return 0;
+}
+
+int xfrm4_rcv(struct sk_buff *skb)
+{
+	return xfrm4_rcv_encap(skb, 0);
+}
+
+EXPORT_SYMBOL(xfrm4_rcv);
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 5685103..9275c79 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -109,3 +109,4 @@
 module_init(ipip_init);
 module_exit(ipip_fini);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP);
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 8e5d54f..eb0b808 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -109,7 +109,7 @@
 	  If unsure, say Y.
 
 config IPV6_MIP6
-	bool "IPv6: Mobility (EXPERIMENTAL)"
+	tristate "IPv6: Mobility (EXPERIMENTAL)"
 	depends on IPV6 && EXPERIMENTAL
 	select XFRM
 	---help---
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index bb3330904..87c23a7 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -14,7 +14,6 @@
 	xfrm6_output.o
 ipv6-$(CONFIG_NETFILTER) += netfilter.o
 ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
-ipv6-$(CONFIG_IPV6_MIP6) += mip6.o
 ipv6-$(CONFIG_PROC_FS) += proc.o
 
 ipv6-objs += $(ipv6-y)
@@ -28,6 +27,7 @@
 obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
 obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
 obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
+obj-$(CONFIG_IPV6_MIP6) += mip6.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 
 obj-$(CONFIG_IPV6_SIT) += sit.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index f96ed76..24424c3 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1034,7 +1034,7 @@
 			}
 
 			/* Rule 4: Prefer home address */
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 			if (hiscore.rule < 4) {
 				if (ifa_result->flags & IFA_F_HOMEADDRESS)
 					hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
@@ -2268,6 +2268,9 @@
 		break;
 	case NETDEV_UP:
 	case NETDEV_CHANGE:
+		if (dev->flags & IFF_SLAVE)
+			break;
+
 		if (event == NETDEV_UP) {
 			if (!netif_carrier_ok(dev)) {
 				/* device is not ready yet. */
@@ -2782,7 +2785,7 @@
 	return 0;
 }
 
-static struct seq_operations if6_seq_ops = {
+static const struct seq_operations if6_seq_ops = {
 	.start	= if6_seq_start,
 	.next	= if6_seq_next,
 	.show	= if6_seq_show,
@@ -2832,7 +2835,7 @@
 }
 #endif	/* CONFIG_PROC_FS */
 
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 /* Check if address is a home address configured on any interface. */
 int ipv6_chk_home_addr(struct in6_addr *addr)
 {
@@ -4240,7 +4243,6 @@
 void __exit addrconf_cleanup(void)
 {
 	struct net_device *dev;
-	struct inet6_dev *idev;
 	struct inet6_ifaddr *ifa;
 	int i;
 
@@ -4258,7 +4260,7 @@
 	 */
 
 	for_each_netdev(dev) {
-		if ((idev = __in6_dev_get(dev)) == NULL)
+		if (__in6_dev_get(dev) == NULL)
 			continue;
 		addrconf_ifdown(dev, 1);
 	}
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 6dd3772..eed0937 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -58,9 +58,6 @@
 #ifdef CONFIG_IPV6_TUNNEL
 #include <net/ip6_tunnel.h>
 #endif
-#ifdef CONFIG_IPV6_MIP6
-#include <net/mip6.h>
-#endif
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -853,9 +850,6 @@
 	ipv6_frag_init();
 	ipv6_nodata_init();
 	ipv6_destopt_init();
-#ifdef CONFIG_IPV6_MIP6
-	mip6_init();
-#endif
 
 	/* Init v6 transport protocols. */
 	udpv6_init();
@@ -921,9 +915,7 @@
 
 	/* Cleanup code parts. */
 	ipv6_packet_cleanup();
-#ifdef CONFIG_IPV6_MIP6
-	mip6_fini();
-#endif
+
 	addrconf_cleanup();
 	ip6_flowlabel_cleanup();
 	ip6_route_cleanup();
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 128f94c..53f46ab 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -74,7 +74,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 /**
  *	ipv6_rearrange_destopt - rearrange IPv6 destination options header
  *	@iph: IPv6 header
@@ -132,6 +132,8 @@
 bad:
 	return;
 }
+#else
+static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) {}
 #endif
 
 /**
@@ -189,10 +191,8 @@
 	while (exthdr.raw < end) {
 		switch (nexthdr) {
 		case NEXTHDR_DEST:
-#ifdef CONFIG_IPV6_MIP6
 			if (dir == XFRM_POLICY_OUT)
 				ipv6_rearrange_destopt(iph, exthdr.opth);
-#endif
 		case NEXTHDR_HOP:
 			if (!zero_out_mutable_opts(exthdr.opth)) {
 				LIMIT_NETDEBUG(
@@ -228,7 +228,7 @@
 	u8 nexthdr;
 	char tmp_base[8];
 	struct {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		struct in6_addr saddr;
 #endif
 		struct in6_addr daddr;
@@ -255,7 +255,7 @@
 			err = -ENOMEM;
 			goto error;
 		}
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		memcpy(tmp_ext, &top_iph->saddr, extlen);
 #else
 		memcpy(tmp_ext, &top_iph->daddr, extlen);
@@ -294,7 +294,7 @@
 
 	memcpy(top_iph, tmp_base, sizeof(tmp_base));
 	if (tmp_ext) {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		memcpy(&top_iph->saddr, tmp_ext, extlen);
 #else
 		memcpy(&top_iph->daddr, tmp_ext, extlen);
@@ -554,3 +554,4 @@
 module_exit(ah6_fini);
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH);
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 9b81264..b8c533f 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -539,7 +539,7 @@
 	return 0;
 }
 
-static struct seq_operations ac6_seq_ops = {
+static const struct seq_operations ac6_seq_ops = {
 	.start	=	ac6_seq_start,
 	.next	=	ac6_seq_next,
 	.stop	=	ac6_seq_stop,
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index b1fe7ac..fe0f490 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -657,11 +657,10 @@
 			rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg);
 
 			switch (rthdr->type) {
-			case IPV6_SRCRT_TYPE_0:
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 			case IPV6_SRCRT_TYPE_2:
-#endif
 				break;
+#endif
 			default:
 				err = -EINVAL;
 				goto exit_f;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 7107bb7..2db31ce 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -421,3 +421,4 @@
 module_exit(esp6_fini);
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 14be0b9..c82d4d4 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -42,7 +42,7 @@
 #include <net/ndisc.h>
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 #include <net/xfrm.h>
 #endif
 
@@ -90,6 +90,7 @@
  bad:
 	return -1;
 }
+EXPORT_SYMBOL_GPL(ipv6_find_tlv);
 
 /*
  *	Parsing tlv encoded headers.
@@ -196,7 +197,7 @@
   Destination options header.
  *****************************/
 
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
 {
 	struct sk_buff *skb = *skbp;
@@ -270,7 +271,7 @@
 #endif
 
 static struct tlvtype_proc tlvprocdestopt_lst[] = {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	{
 		.type	= IPV6_TLV_HAO,
 		.func	= ipv6_dest_hao,
@@ -283,7 +284,7 @@
 {
 	struct sk_buff *skb = *skbp;
 	struct inet6_skb_parm *opt = IP6CB(skb);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	__u16 dstbuf;
 #endif
 	struct dst_entry *dst;
@@ -298,7 +299,7 @@
 	}
 
 	opt->lastopt = opt->dst1 = skb_network_header_len(skb);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	dstbuf = opt->dst1;
 #endif
 
@@ -308,7 +309,7 @@
 		skb = *skbp;
 		skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
 		opt = IP6CB(skb);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		opt->nhoff = dstbuf;
 #else
 		opt->nhoff = opt->dst1;
@@ -371,22 +372,13 @@
 	struct rt0_hdr *rthdr;
 	int accept_source_route = ipv6_devconf.accept_source_route;
 
-	if (accept_source_route < 0 ||
-	    ((idev = in6_dev_get(skb->dev)) == NULL)) {
-		kfree_skb(skb);
-		return -1;
-	}
-	if (idev->cnf.accept_source_route < 0) {
+	idev = in6_dev_get(skb->dev);
+	if (idev) {
+		if (accept_source_route > idev->cnf.accept_source_route)
+			accept_source_route = idev->cnf.accept_source_route;
 		in6_dev_put(idev);
-		kfree_skb(skb);
-		return -1;
 	}
 
-	if (accept_source_route > idev->cnf.accept_source_route)
-		accept_source_route = idev->cnf.accept_source_route;
-
-	in6_dev_put(idev);
-
 	if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
 	    !pskb_may_pull(skb, (skb_transport_offset(skb) +
 				 ((skb_transport_header(skb)[1] + 1) << 3)))) {
@@ -398,24 +390,6 @@
 
 	hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
 
-	switch (hdr->type) {
-#ifdef CONFIG_IPV6_MIP6
-	case IPV6_SRCRT_TYPE_2:
-		break;
-#endif
-	case IPV6_SRCRT_TYPE_0:
-		if (accept_source_route > 0)
-			break;
-		kfree_skb(skb);
-		return -1;
-	default:
-		IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
-				 IPSTATS_MIB_INHDRERRORS);
-		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
-				  (&hdr->type) - skb_network_header(skb));
-		return -1;
-	}
-
 	if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
 	    skb->pkt_type != PACKET_HOST) {
 		IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
@@ -427,7 +401,7 @@
 looped_back:
 	if (hdr->segments_left == 0) {
 		switch (hdr->type) {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		case IPV6_SRCRT_TYPE_2:
 			/* Silently discard type 2 header unless it was
 			 * processed by own
@@ -453,18 +427,10 @@
 	}
 
 	switch (hdr->type) {
-	case IPV6_SRCRT_TYPE_0:
-		if (hdr->hdrlen & 0x01) {
-			IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
-					 IPSTATS_MIB_INHDRERRORS);
-			icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
-					  ((&hdr->hdrlen) -
-					   skb_network_header(skb)));
-			return -1;
-		}
-		break;
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	case IPV6_SRCRT_TYPE_2:
+		if (accept_source_route < 0)
+			goto unknown_rh;
 		/* Silently discard invalid RTH type 2 */
 		if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
 			IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
@@ -474,6 +440,8 @@
 		}
 		break;
 #endif
+	default:
+		goto unknown_rh;
 	}
 
 	/*
@@ -520,7 +488,7 @@
 	addr += i - 1;
 
 	switch (hdr->type) {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	case IPV6_SRCRT_TYPE_2:
 		if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
 				     (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
@@ -577,6 +545,12 @@
 	skb_push(skb, skb->data - skb_network_header(skb));
 	dst_input(skb);
 	return -1;
+
+unknown_rh:
+	IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
+	icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
+			  (&hdr->type) - skb_network_header(skb));
+	return -1;
 }
 
 static struct inet6_protocol rthdr_protocol = {
@@ -590,72 +564,6 @@
 		printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
 };
 
-/*
-   This function inverts received rthdr.
-   NOTE: specs allow to make it automatically only if
-   packet authenticated.
-
-   I will not discuss it here (though, I am really pissed off at
-   this stupid requirement making rthdr idea useless)
-
-   Actually, it creates severe problems  for us.
-   Embryonic requests has no associated sockets,
-   so that user have no control over it and
-   cannot not only to set reply options, but
-   even to know, that someone wants to connect
-   without success. :-(
-
-   For now we need to test the engine, so that I created
-   temporary (or permanent) backdoor.
-   If listening socket set IPV6_RTHDR to 2, then we invert header.
-						   --ANK (980729)
- */
-
-struct ipv6_txoptions *
-ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
-{
-	/* Received rthdr:
-
-	   [ H1 -> H2 -> ... H_prev ]  daddr=ME
-
-	   Inverted result:
-	   [ H_prev -> ... -> H1 ] daddr =sender
-
-	   Note, that IP output engine will rewrite this rthdr
-	   by rotating it left by one addr.
-	 */
-
-	int n, i;
-	struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
-	struct rt0_hdr *irthdr;
-	struct ipv6_txoptions *opt;
-	int hdrlen = ipv6_optlen(hdr);
-
-	if (hdr->segments_left ||
-	    hdr->type != IPV6_SRCRT_TYPE_0 ||
-	    hdr->hdrlen & 0x01)
-		return NULL;
-
-	n = hdr->hdrlen >> 1;
-	opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
-	if (opt == NULL)
-		return NULL;
-	memset(opt, 0, sizeof(*opt));
-	opt->tot_len = sizeof(*opt) + hdrlen;
-	opt->srcrt = (void*)(opt+1);
-	opt->opt_nflen = hdrlen;
-
-	memcpy(opt->srcrt, hdr, sizeof(*hdr));
-	irthdr = (struct rt0_hdr*)opt->srcrt;
-	irthdr->reserved = 0;
-	opt->srcrt->segments_left = n;
-	for (i=0; i<n; i++)
-		memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
-	return opt;
-}
-
-EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
-
 /**********************************
   Hop-by-hop options.
  **********************************/
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index e9bcce9..4765a29 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -272,7 +272,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 static void mip6_addr_swap(struct sk_buff *skb)
 {
 	struct ipv6hdr *iph = ipv6_hdr(skb);
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index c206a15..413a4eb 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -648,7 +648,7 @@
 	return 0;
 }
 
-static struct seq_operations ip6fl_seq_ops = {
+static const struct seq_operations ip6fl_seq_ops = {
 	.start	=	ip6fl_seq_start,
 	.next	=	ip6fl_seq_next,
 	.stop	=	ip6fl_seq_stop,
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 4704b5f..50d86e9 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -521,6 +521,10 @@
 	to->tc_index = from->tc_index;
 #endif
 	nf_copy(to, from);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+	to->nf_trace = from->nf_trace;
+#endif
 	skb_copy_secmark(to, from);
 }
 
@@ -543,7 +547,7 @@
 			found_rhdr = 1;
 			break;
 		case NEXTHDR_DEST:
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 			if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
 				break;
 #endif
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index a0902fb..281aee4 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -883,8 +883,8 @@
 	 */
 	max_headroom += LL_RESERVED_SPACE(tdev);
 
-	if (skb_headroom(skb) < max_headroom ||
-	    skb_cloned(skb) || skb_shared(skb)) {
+	if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
+	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
 		struct sk_buff *new_skb;
 
 		if (!(new_skb = skb_realloc_headroom(skb, max_headroom)))
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 1ee50b5..473f165 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -500,4 +500,4 @@
 MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) for IPv6 - RFC3173");
 MODULE_AUTHOR("Mitsuru KANDA <mk@linux-ipv6.org>");
 
-
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_COMP);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index aa3d07c..d684639 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -123,7 +123,7 @@
 	struct ipv6hdr *ipv6h;
 	struct inet6_protocol *ops;
 
-	if (!(features & NETIF_F_HW_CSUM))
+	if (!(features & NETIF_F_V6_CSUM))
 		features &= ~NETIF_F_SG;
 
 	if (unlikely(skb_shinfo(skb)->gso_type &
@@ -336,16 +336,12 @@
 		break;
 
 	case IPV6_RECVRTHDR:
-		if (val < 0 || val > 2)
-			goto e_inval;
-		np->rxopt.bits.srcrt = val;
+		np->rxopt.bits.srcrt = valbool;
 		retv = 0;
 		break;
 
 	case IPV6_2292RTHDR:
-		if (val < 0 || val > 2)
-			goto e_inval;
-		np->rxopt.bits.osrcrt = val;
+		np->rxopt.bits.osrcrt = valbool;
 		retv = 0;
 		break;
 
@@ -416,11 +412,10 @@
 		if (optname == IPV6_RTHDR && opt && opt->srcrt) {
 			struct ipv6_rt_hdr *rthdr = opt->srcrt;
 			switch (rthdr->type) {
-			case IPV6_SRCRT_TYPE_0:
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 			case IPV6_SRCRT_TYPE_2:
-#endif
 				break;
+#endif
 			default:
 				goto sticky_done;
 			}
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 3e308fb..ae98818 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2423,7 +2423,7 @@
 	return 0;
 }
 
-static struct seq_operations igmp6_mc_seq_ops = {
+static const struct seq_operations igmp6_mc_seq_ops = {
 	.start	=	igmp6_mc_seq_start,
 	.next	=	igmp6_mc_seq_next,
 	.stop	=	igmp6_mc_seq_stop,
@@ -2597,7 +2597,7 @@
 	return 0;
 }
 
-static struct seq_operations igmp6_mcf_seq_ops = {
+static const struct seq_operations igmp6_mcf_seq_ops = {
 	.start	=	igmp6_mcf_seq_start,
 	.next	=	igmp6_mcf_seq_next,
 	.stop	=	igmp6_mcf_seq_stop,
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 13b7160..8a1399c 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -30,6 +30,7 @@
 #include <net/sock.h>
 #include <net/ipv6.h>
 #include <net/ip6_checksum.h>
+#include <net/rawv6.h>
 #include <net/xfrm.h>
 #include <net/mip6.h>
 
@@ -86,7 +87,7 @@
 	return len;
 }
 
-int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
+static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
 {
 	struct ip6_mh *mh;
 
@@ -471,7 +472,7 @@
 	.remote_addr	= mip6_xfrm_addr,
 };
 
-int __init mip6_init(void)
+static int __init mip6_init(void)
 {
 	printk(KERN_INFO "Mobile IPv6\n");
 
@@ -483,18 +484,35 @@
 		printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
 		goto mip6_rthdr_xfrm_fail;
 	}
+	if (rawv6_mh_filter_register(mip6_mh_filter) < 0) {
+		printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__);
+		goto mip6_rawv6_mh_fail;
+	}
+
+
 	return 0;
 
+ mip6_rawv6_mh_fail:
+	xfrm_unregister_type(&mip6_rthdr_type, AF_INET6);
  mip6_rthdr_xfrm_fail:
 	xfrm_unregister_type(&mip6_destopt_type, AF_INET6);
  mip6_destopt_xfrm_fail:
 	return -EAGAIN;
 }
 
-void __exit mip6_fini(void)
+static void __exit mip6_fini(void)
 {
+	if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0)
+		printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__);
 	if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
 		printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
 	if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
 		printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
 }
+
+module_init(mip6_init);
+module_exit(mip6_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_DSTOPTS);
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ROUTING);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 9aa6240..254c769 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -96,13 +96,13 @@
 }
 
 /* Returns whether matches rule or not. */
-static inline int
+static inline bool
 ip6_packet_match(const struct sk_buff *skb,
 		 const char *indev,
 		 const char *outdev,
 		 const struct ip6t_ip6 *ip6info,
 		 unsigned int *protoff,
-		 int *fragoff, int *hotdrop)
+		 int *fragoff, bool *hotdrop)
 {
 	size_t i;
 	unsigned long ret;
@@ -122,7 +122,7 @@
 		dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr,
 			ipinfo->dmsk.s_addr, ipinfo->dst.s_addr,
 			ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/
-		return 0;
+		return false;
 	}
 
 	/* Look for ifname matches; this should unroll nicely. */
@@ -136,7 +136,7 @@
 		dprintf("VIA in mismatch (%s vs %s).%s\n",
 			indev, ip6info->iniface,
 			ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":"");
-		return 0;
+		return false;
 	}
 
 	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
@@ -149,7 +149,7 @@
 		dprintf("VIA out mismatch (%s vs %s).%s\n",
 			outdev, ip6info->outiface,
 			ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":"");
-		return 0;
+		return false;
 	}
 
 /* ... might want to do something with class and flowlabel here ... */
@@ -162,8 +162,8 @@
 		protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
 		if (protohdr < 0) {
 			if (_frag_off == 0)
-				*hotdrop = 1;
-			return 0;
+				*hotdrop = true;
+			return false;
 		}
 		*fragoff = _frag_off;
 
@@ -174,34 +174,34 @@
 
 		if (ip6info->proto == protohdr) {
 			if(ip6info->invflags & IP6T_INV_PROTO) {
-				return 0;
+				return false;
 			}
-			return 1;
+			return true;
 		}
 
 		/* We need match for the '-p all', too! */
 		if ((ip6info->proto != 0) &&
 			!(ip6info->invflags & IP6T_INV_PROTO))
-			return 0;
+			return false;
 	}
-	return 1;
+	return true;
 }
 
 /* should be ip6 safe */
-static inline int
+static inline bool
 ip6_checkentry(const struct ip6t_ip6 *ipv6)
 {
 	if (ipv6->flags & ~IP6T_F_MASK) {
 		duprintf("Unknown flag bits set: %08X\n",
 			 ipv6->flags & ~IP6T_F_MASK);
-		return 0;
+		return false;
 	}
 	if (ipv6->invflags & ~IP6T_INV_MASK) {
 		duprintf("Unknown invflag bits set: %08X\n",
 			 ipv6->invflags & ~IP6T_INV_MASK);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static unsigned int
@@ -219,20 +219,20 @@
 }
 
 static inline
-int do_match(struct ip6t_entry_match *m,
-	     const struct sk_buff *skb,
-	     const struct net_device *in,
-	     const struct net_device *out,
-	     int offset,
-	     unsigned int protoff,
-	     int *hotdrop)
+bool do_match(struct ip6t_entry_match *m,
+	      const struct sk_buff *skb,
+	      const struct net_device *in,
+	      const struct net_device *out,
+	      int offset,
+	      unsigned int protoff,
+	      bool *hotdrop)
 {
 	/* Stop iteration if it doesn't match */
 	if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
 				      offset, protoff, hotdrop))
-		return 1;
+		return true;
 	else
-		return 0;
+		return false;
 }
 
 static inline struct ip6t_entry *
@@ -241,6 +241,113 @@
 	return (struct ip6t_entry *)(base + offset);
 }
 
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ip6t_ip6 *ipv6)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(*ipv6); i++)
+		if (((char *)ipv6)[i])
+			break;
+
+	return (i == sizeof(*ipv6));
+}
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+/* This cries for unification! */
+static const char *hooknames[] = {
+	[NF_IP6_PRE_ROUTING]		= "PREROUTING",
+	[NF_IP6_LOCAL_IN]		= "INPUT",
+	[NF_IP6_FORWARD]		= "FORWARD",
+	[NF_IP6_LOCAL_OUT]		= "OUTPUT",
+	[NF_IP6_POST_ROUTING]		= "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+	NF_IP6_TRACE_COMMENT_RULE,
+	NF_IP6_TRACE_COMMENT_RETURN,
+	NF_IP6_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+	[NF_IP6_TRACE_COMMENT_RULE]	= "rule",
+	[NF_IP6_TRACE_COMMENT_RETURN]	= "return",
+	[NF_IP6_TRACE_COMMENT_POLICY]	= "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+	.type = NF_LOG_TYPE_LOG,
+	.u = {
+		.log = {
+			.level = 4,
+			.logflags = NF_LOG_MASK,
+		},
+	},
+};
+
+static inline int
+get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
+		      char *hookname, char **chainname,
+		      char **comment, unsigned int *rulenum)
+{
+	struct ip6t_standard_target *t = (void *)ip6t_get_target(s);
+
+	if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
+		/* Head of user chain: ERROR target with chainname */
+		*chainname = t->target.data;
+		(*rulenum) = 0;
+	} else if (s == e) {
+		(*rulenum)++;
+
+		if (s->target_offset == sizeof(struct ip6t_entry)
+		   && strcmp(t->target.u.kernel.target->name,
+			     IP6T_STANDARD_TARGET) == 0
+		   && t->verdict < 0
+		   && unconditional(&s->ipv6)) {
+			/* Tail of chains: STANDARD target (return/policy) */
+			*comment = *chainname == hookname
+				? (char *)comments[NF_IP6_TRACE_COMMENT_POLICY]
+				: (char *)comments[NF_IP6_TRACE_COMMENT_RETURN];
+		}
+		return 1;
+	} else
+		(*rulenum)++;
+
+	return 0;
+}
+
+static void trace_packet(struct sk_buff *skb,
+			 unsigned int hook,
+			 const struct net_device *in,
+			 const struct net_device *out,
+			 char *tablename,
+			 struct xt_table_info *private,
+			 struct ip6t_entry *e)
+{
+	void *table_base;
+	struct ip6t_entry *root;
+	char *hookname, *chainname, *comment;
+	unsigned int rulenum = 0;
+
+	table_base = (void *)private->entries[smp_processor_id()];
+	root = get_entry(table_base, private->hook_entry[hook]);
+
+	hookname = chainname = (char *)hooknames[hook];
+	comment = (char *)comments[NF_IP6_TRACE_COMMENT_RULE];
+
+	IP6T_ENTRY_ITERATE(root,
+			   private->size - private->hook_entry[hook],
+			   get_chainname_rulenum,
+			   e, hookname, &chainname, &comment, &rulenum);
+
+	nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,
+		      "TRACE: %s:%s:%s:%u ",
+		      tablename, chainname, comment, rulenum);
+}
+#endif
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ip6t_do_table(struct sk_buff **pskb,
@@ -252,7 +359,7 @@
 	static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
 	int offset = 0;
 	unsigned int protoff = 0;
-	int hotdrop = 0;
+	bool hotdrop = false;
 	/* Initializing verdict to NF_DROP keeps gcc happy. */
 	unsigned int verdict = NF_DROP;
 	const char *indev, *outdev;
@@ -298,6 +405,14 @@
 
 			t = ip6t_get_target(e);
 			IP_NF_ASSERT(t->u.kernel.target);
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+			/* The packet is traced: log it */
+			if (unlikely((*pskb)->nf_trace))
+				trace_packet(*pskb, hook, in, out,
+					     table->name, private, e);
+#endif
 			/* Standard target? */
 			if (!t->u.kernel.target->target) {
 				int v;
@@ -377,19 +492,6 @@
 #endif
 }
 
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ip6t_ip6 *ipv6)
-{
-	unsigned int i;
-
-	for (i = 0; i < sizeof(*ipv6); i++)
-		if (((char *)ipv6)[i])
-			break;
-
-	return (i == sizeof(*ipv6));
-}
-
 /* Figures out from what hook each rule can be called: returns 0 if
    there are loops.  Puts hook bitmask in comefrom. */
 static int
@@ -1282,16 +1384,16 @@
 }
 
 /* Returns 1 if the type and code is matched by the range, 0 otherwise */
-static inline int
+static inline bool
 icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
 		     u_int8_t type, u_int8_t code,
-		     int invert)
+		     bool invert)
 {
 	return (type == test_type && code >= min_code && code <= max_code)
 		^ invert;
 }
 
-static int
+static bool
 icmp6_match(const struct sk_buff *skb,
 	   const struct net_device *in,
 	   const struct net_device *out,
@@ -1299,22 +1401,22 @@
 	   const void *matchinfo,
 	   int offset,
 	   unsigned int protoff,
-	   int *hotdrop)
+	   bool *hotdrop)
 {
 	struct icmp6hdr _icmp, *ic;
 	const struct ip6t_icmp *icmpinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp);
 	if (ic == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil ICMP tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return icmp6_type_code_match(icmpinfo->type,
@@ -1325,7 +1427,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 icmp6_checkentry(const char *tablename,
 	   const void *entry,
 	   const struct xt_match *match,
@@ -1339,13 +1441,13 @@
 }
 
 /* The built-in targets: standard (NULL) and error. */
-static struct xt_target ip6t_standard_target = {
+static struct xt_target ip6t_standard_target __read_mostly = {
 	.name		= IP6T_STANDARD_TARGET,
 	.targetsize	= sizeof(int),
 	.family		= AF_INET6,
 };
 
-static struct xt_target ip6t_error_target = {
+static struct xt_target ip6t_error_target __read_mostly = {
 	.name		= IP6T_ERROR_TARGET,
 	.target		= ip6t_error,
 	.targetsize	= IP6T_FUNCTION_MAXNAMELEN,
@@ -1362,7 +1464,7 @@
 	.get		= do_ip6t_get_ctl,
 };
 
-static struct xt_match icmp6_matchstruct = {
+static struct xt_match icmp6_matchstruct __read_mostly = {
 	.name		= "icmp6",
 	.match		= &icmp6_match,
 	.matchsize	= sizeof(struct ip6t_icmp),
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index 4115a57..ad4d943 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -58,28 +58,28 @@
 	return XT_CONTINUE;
 }
 
-static int ip6t_hl_checkentry(const char *tablename,
+static bool ip6t_hl_checkentry(const char *tablename,
 		const void *entry,
 		const struct xt_target *target,
 		void *targinfo,
 		unsigned int hook_mask)
 {
-	struct ip6t_HL_info *info = targinfo;
+	const struct ip6t_HL_info *info = targinfo;
 
 	if (info->mode > IP6T_HL_MAXMODE) {
 		printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
 			info->mode);
-		return 0;
+		return false;
 	}
-	if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
+	if (info->mode != IP6T_HL_SET && info->hop_limit == 0) {
 		printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't "
 			"make sense with value 0\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ip6t_HL = {
+static struct xt_target ip6t_HL __read_mostly = {
 	.name 		= "HL",
 	.family		= AF_INET6,
 	.target		= ip6t_hl_target,
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 5bb9cd3..b05327e 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -32,12 +32,6 @@
 #include <net/route.h>
 #include <linux/netfilter_ipv6/ip6t_LOG.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Use lock to serialize, so printks don't overlap */
 static DEFINE_SPINLOCK(log_lock);
 
@@ -48,7 +42,8 @@
 {
 	u_int8_t currenthdr;
 	int fragment;
-	struct ipv6hdr _ip6h, *ih;
+	struct ipv6hdr _ip6h;
+	const struct ipv6hdr *ih;
 	unsigned int ptr;
 	unsigned int hdrlen = 0;
 	unsigned int logflags;
@@ -78,7 +73,8 @@
 	ptr = ip6hoff + sizeof(struct ipv6hdr);
 	currenthdr = ih->nexthdr;
 	while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
-		struct ipv6_opt_hdr _hdr, *hp;
+		struct ipv6_opt_hdr _hdr;
+		const struct ipv6_opt_hdr *hp;
 
 		hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
 		if (hp == NULL) {
@@ -92,7 +88,8 @@
 
 		switch (currenthdr) {
 		case IPPROTO_FRAGMENT: {
-			struct frag_hdr _fhdr, *fh;
+			struct frag_hdr _fhdr;
+			const struct frag_hdr *fh;
 
 			printk("FRAG:");
 			fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
@@ -131,7 +128,8 @@
 		/* Max Length */
 		case IPPROTO_AH:
 			if (logflags & IP6T_LOG_IPOPT) {
-				struct ip_auth_hdr _ahdr, *ah;
+				struct ip_auth_hdr _ahdr;
+				const struct ip_auth_hdr *ah;
 
 				/* Max length: 3 "AH " */
 				printk("AH ");
@@ -162,7 +160,8 @@
 			break;
 		case IPPROTO_ESP:
 			if (logflags & IP6T_LOG_IPOPT) {
-				struct ip_esp_hdr _esph, *eh;
+				struct ip_esp_hdr _esph;
+				const struct ip_esp_hdr *eh;
 
 				/* Max length: 4 "ESP " */
 				printk("ESP ");
@@ -202,7 +201,8 @@
 
 	switch (currenthdr) {
 	case IPPROTO_TCP: {
-		struct tcphdr _tcph, *th;
+		struct tcphdr _tcph;
+		const struct tcphdr *th;
 
 		/* Max length: 10 "PROTO=TCP " */
 		printk("PROTO=TCP ");
@@ -250,7 +250,8 @@
 
 		if ((logflags & IP6T_LOG_TCPOPT)
 		    && th->doff * 4 > sizeof(struct tcphdr)) {
-			u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
+			u_int8_t _opt[60 - sizeof(struct tcphdr)];
+			const u_int8_t *op;
 			unsigned int i;
 			unsigned int optsize = th->doff * 4
 					       - sizeof(struct tcphdr);
@@ -273,7 +274,8 @@
 	}
 	case IPPROTO_UDP:
 	case IPPROTO_UDPLITE: {
-		struct udphdr _udph, *uh;
+		struct udphdr _udph;
+		const struct udphdr *uh;
 
 		if (currenthdr == IPPROTO_UDP)
 			/* Max length: 10 "PROTO=UDP "     */
@@ -298,7 +300,8 @@
 		break;
 	}
 	case IPPROTO_ICMPV6: {
-		struct icmp6hdr _icmp6h, *ic;
+		struct icmp6hdr _icmp6h;
+		const struct icmp6hdr *ic;
 
 		/* Max length: 13 "PROTO=ICMPv6 " */
 		printk("PROTO=ICMPv6 ");
@@ -448,27 +451,27 @@
 }
 
 
-static int ip6t_log_checkentry(const char *tablename,
-			       const void *entry,
-			       const struct xt_target *target,
-			       void *targinfo,
-			       unsigned int hook_mask)
+static bool ip6t_log_checkentry(const char *tablename,
+				const void *entry,
+				const struct xt_target *target,
+				void *targinfo,
+				unsigned int hook_mask)
 {
 	const struct ip6t_log_info *loginfo = targinfo;
 
 	if (loginfo->level >= 8) {
-		DEBUGP("LOG: level %u >= 8\n", loginfo->level);
-		return 0;
+		pr_debug("LOG: level %u >= 8\n", loginfo->level);
+		return false;
 	}
 	if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
-		DEBUGP("LOG: prefix term %i\n",
-		       loginfo->prefix[sizeof(loginfo->prefix)-1]);
-		return 0;
+		pr_debug("LOG: prefix term %i\n",
+			 loginfo->prefix[sizeof(loginfo->prefix)-1]);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ip6t_log_reg = {
+static struct xt_target ip6t_log_reg __read_mostly = {
 	.name 		= "LOG",
 	.family		= AF_INET6,
 	.target 	= ip6t_log_target,
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index cb3d241..2f487cd 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -34,12 +34,6 @@
 MODULE_DESCRIPTION("IP6 tables REJECT target module");
 MODULE_LICENSE("GPL");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Send RST reply */
 static void send_reset(struct sk_buff *oldskb)
 {
@@ -54,7 +48,7 @@
 
 	if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
 	    (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
-		DEBUGP("ip6t_REJECT: addr is not unicast.\n");
+		pr_debug("ip6t_REJECT: addr is not unicast.\n");
 		return;
 	}
 
@@ -62,16 +56,17 @@
 	tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto);
 
 	if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
-		DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
+		pr_debug("ip6t_REJECT: Can't get TCP header.\n");
 		return;
 	}
 
 	otcplen = oldskb->len - tcphoff;
 
 	/* IP header checks: fragment, too short. */
-	if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
-		DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
-			proto, otcplen);
+	if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) {
+		pr_debug("ip6t_REJECT: proto(%d) != IPPROTO_TCP, "
+			 "or too short. otcplen = %d\n",
+			 proto, otcplen);
 		return;
 	}
 
@@ -80,14 +75,14 @@
 
 	/* No RST for RST. */
 	if (otcph.rst) {
-		DEBUGP("ip6t_REJECT: RST is set\n");
+		pr_debug("ip6t_REJECT: RST is set\n");
 		return;
 	}
 
 	/* Check checksum. */
 	if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
 			    skb_checksum(oldskb, tcphoff, otcplen, 0))) {
-		DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
+		pr_debug("ip6t_REJECT: TCP checksum is invalid\n");
 		return;
 	}
 
@@ -159,7 +154,7 @@
 	tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr,
 				      &ipv6_hdr(nskb)->daddr,
 				      sizeof(struct tcphdr), IPPROTO_TCP,
-				      csum_partial((char *)tcph,
+				      csum_partial(tcph,
 						   sizeof(struct tcphdr), 0));
 
 	nf_ct_attach(nskb, oldskb);
@@ -186,7 +181,7 @@
 {
 	const struct ip6t_reject_info *reject = targinfo;
 
-	DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
+	pr_debug("%s: medium point\n", __FUNCTION__);
 	/* WARNING: This code causes reentry within ip6tables.
 	   This means that the ip6tables jump stack is now crap.  We
 	   must return an absolute verdict. --RR */
@@ -221,30 +216,30 @@
 	return NF_DROP;
 }
 
-static int check(const char *tablename,
-		 const void *entry,
-		 const struct xt_target *target,
-		 void *targinfo,
-		 unsigned int hook_mask)
+static bool check(const char *tablename,
+		  const void *entry,
+		  const struct xt_target *target,
+		  void *targinfo,
+		  unsigned int hook_mask)
 {
 	const struct ip6t_reject_info *rejinfo = targinfo;
 	const struct ip6t_entry *e = entry;
 
 	if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
 		printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
-		return 0;
+		return false;
 	} else if (rejinfo->with == IP6T_TCP_RESET) {
 		/* Must specify that it's a TCP packet */
 		if (e->ipv6.proto != IPPROTO_TCP
 		    || (e->ipv6.invflags & XT_INV_PROTO)) {
-			DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
-			return 0;
+			printk("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
+			return false;
 		}
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target ip6t_reject_reg = {
+static struct xt_target ip6t_reject_reg __read_mostly = {
 	.name		= "REJECT",
 	.family		= AF_INET6,
 	.target		= reject6_target,
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index d3c1543..2a25fe25 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -23,25 +23,20 @@
 MODULE_DESCRIPTION("IPv6 AH match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
+static inline bool
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
 {
-	int r=0;
-	DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
-	       min,spi,max);
+	bool r;
+
+	pr_debug("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",
+		 invert ? '!' : ' ', min, spi, max);
 	r = (spi >= min && spi <= max) ^ invert;
-	DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
+	pr_debug(" result %s\n", r ? "PASS" : "FAILED");
 	return r;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -49,9 +44,10 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
-	struct ip_auth_hdr *ah, _ah;
+	struct ip_auth_hdr _ah;
+	const struct ip_auth_hdr *ah;
 	const struct ip6t_ah *ahinfo = matchinfo;
 	unsigned int ptr;
 	unsigned int hdrlen = 0;
@@ -60,40 +56,40 @@
 	err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL);
 	if (err < 0) {
 		if (err != -ENOENT)
-			*hotdrop = 1;
-		return 0;
+			*hotdrop = true;
+		return false;
 	}
 
 	ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
 	if (ah == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	hdrlen = (ah->hdrlen + 2) << 2;
 
-	DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
-	DEBUGP("RES %04X ", ah->reserved);
-	DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
+	pr_debug("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
+	pr_debug("RES %04X ", ah->reserved);
+	pr_debug("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
 
-	DEBUGP("IPv6 AH spi %02X ",
-	       (spi_match(ahinfo->spis[0], ahinfo->spis[1],
-			  ntohl(ah->spi),
-			  !!(ahinfo->invflags & IP6T_AH_INV_SPI))));
-	DEBUGP("len %02X %04X %02X ",
-	       ahinfo->hdrlen, hdrlen,
-	       (!ahinfo->hdrlen ||
-		(ahinfo->hdrlen == hdrlen) ^
-		!!(ahinfo->invflags & IP6T_AH_INV_LEN)));
-	DEBUGP("res %02X %04X %02X\n",
-	       ahinfo->hdrres, ah->reserved,
-	       !(ahinfo->hdrres && ah->reserved));
+	pr_debug("IPv6 AH spi %02X ",
+		 spi_match(ahinfo->spis[0], ahinfo->spis[1],
+			   ntohl(ah->spi),
+			   !!(ahinfo->invflags & IP6T_AH_INV_SPI)));
+	pr_debug("len %02X %04X %02X ",
+		 ahinfo->hdrlen, hdrlen,
+		 (!ahinfo->hdrlen ||
+		  (ahinfo->hdrlen == hdrlen) ^
+		  !!(ahinfo->invflags & IP6T_AH_INV_LEN)));
+	pr_debug("res %02X %04X %02X\n",
+		 ahinfo->hdrres, ah->reserved,
+		 !(ahinfo->hdrres && ah->reserved));
 
 	return (ah != NULL)
 	       &&
-	       (spi_match(ahinfo->spis[0], ahinfo->spis[1],
-			  ntohl(ah->spi),
-			  !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
+	       spi_match(ahinfo->spis[0], ahinfo->spis[1],
+			 ntohl(ah->spi),
+			 !!(ahinfo->invflags & IP6T_AH_INV_SPI))
 	       &&
 	       (!ahinfo->hdrlen ||
 		(ahinfo->hdrlen == hdrlen) ^
@@ -103,7 +99,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	  const void *entry,
 	  const struct xt_match *match,
@@ -113,13 +109,13 @@
 	const struct ip6t_ah *ahinfo = matchinfo;
 
 	if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
-		DEBUGP("ip6t_ah: unknown flags %X\n", ahinfo->invflags);
-		return 0;
+		pr_debug("ip6t_ah: unknown flags %X\n", ahinfo->invflags);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match ah_match = {
+static struct xt_match ah_match __read_mostly = {
 	.name		= "ah",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 0f3dd93..34ba150 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -19,7 +19,7 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -27,16 +27,16 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	unsigned char eui64[8];
 	int i = 0;
 
 	if (!(skb_mac_header(skb) >= skb->head &&
-	      (skb_mac_header(skb) + ETH_HLEN) <= skb->data) &&
+	      skb_mac_header(skb) + ETH_HLEN <= skb->data) &&
 	    offset != 0) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	memset(eui64, 0, sizeof(eui64));
@@ -50,19 +50,19 @@
 			eui64[0] |= 0x02;
 
 			i = 0;
-			while ((ipv6_hdr(skb)->saddr.s6_addr[8 + i] == eui64[i])
-			       && (i < 8))
+			while (ipv6_hdr(skb)->saddr.s6_addr[8 + i] == eui64[i]
+			       && i < 8)
 				i++;
 
 			if (i == 8)
-				return 1;
+				return true;
 		}
 	}
 
-	return 0;
+	return false;
 }
 
-static struct xt_match eui64_match = {
+static struct xt_match eui64_match __read_mostly = {
 	.name		= "eui64",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 5a5da71..968aeba 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -22,25 +22,19 @@
 MODULE_DESCRIPTION("IPv6 FRAG match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Returns 1 if the id is matched by the range, 0 otherwise */
-static inline int
-id_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
+static inline bool
+id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert)
 {
-	int r = 0;
-	DEBUGP("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
-	       min, id, max);
+	bool r;
+	pr_debug("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
+		 min, id, max);
 	r = (id >= min && id <= max) ^ invert;
-	DEBUGP(" result %s\n", r ? "PASS" : "FAILED");
+	pr_debug(" result %s\n", r ? "PASS" : "FAILED");
 	return r;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -48,9 +42,10 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
-	struct frag_hdr _frag, *fh;
+	struct frag_hdr _frag;
+	const struct frag_hdr *fh;
 	const struct ip6t_frag *fraginfo = matchinfo;
 	unsigned int ptr;
 	int err;
@@ -58,53 +53,53 @@
 	err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL);
 	if (err < 0) {
 		if (err != -ENOENT)
-			*hotdrop = 1;
-		return 0;
+			*hotdrop = true;
+		return false;
 	}
 
 	fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
 	if (fh == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
-	DEBUGP("INFO %04X ", fh->frag_off);
-	DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
-	DEBUGP("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6);
-	DEBUGP("MF %04X ", fh->frag_off & htons(IP6_MF));
-	DEBUGP("ID %u %08X\n", ntohl(fh->identification),
-	       ntohl(fh->identification));
+	pr_debug("INFO %04X ", fh->frag_off);
+	pr_debug("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
+	pr_debug("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6);
+	pr_debug("MF %04X ", fh->frag_off & htons(IP6_MF));
+	pr_debug("ID %u %08X\n", ntohl(fh->identification),
+		 ntohl(fh->identification));
 
-	DEBUGP("IPv6 FRAG id %02X ",
-	       (id_match(fraginfo->ids[0], fraginfo->ids[1],
-			 ntohl(fh->identification),
-			 !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))));
-	DEBUGP("res %02X %02X%04X %02X ",
-	       (fraginfo->flags & IP6T_FRAG_RES), fh->reserved,
-	       ntohs(fh->frag_off) & 0x6,
-	       !((fraginfo->flags & IP6T_FRAG_RES)
-		 && (fh->reserved || (ntohs(fh->frag_off) & 0x06))));
-	DEBUGP("first %02X %02X %02X ",
-	       (fraginfo->flags & IP6T_FRAG_FST),
-	       ntohs(fh->frag_off) & ~0x7,
-	       !((fraginfo->flags & IP6T_FRAG_FST)
-		 && (ntohs(fh->frag_off) & ~0x7)));
-	DEBUGP("mf %02X %02X %02X ",
-	       (fraginfo->flags & IP6T_FRAG_MF),
-	       ntohs(fh->frag_off) & IP6_MF,
-	       !((fraginfo->flags & IP6T_FRAG_MF)
-		 && !((ntohs(fh->frag_off) & IP6_MF))));
-	DEBUGP("last %02X %02X %02X\n",
-	       (fraginfo->flags & IP6T_FRAG_NMF),
-	       ntohs(fh->frag_off) & IP6_MF,
-	       !((fraginfo->flags & IP6T_FRAG_NMF)
-		 && (ntohs(fh->frag_off) & IP6_MF)));
+	pr_debug("IPv6 FRAG id %02X ",
+		 id_match(fraginfo->ids[0], fraginfo->ids[1],
+			  ntohl(fh->identification),
+			  !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)));
+	pr_debug("res %02X %02X%04X %02X ",
+		 fraginfo->flags & IP6T_FRAG_RES, fh->reserved,
+		 ntohs(fh->frag_off) & 0x6,
+		 !((fraginfo->flags & IP6T_FRAG_RES)
+		   && (fh->reserved || (ntohs(fh->frag_off) & 0x06))));
+	pr_debug("first %02X %02X %02X ",
+		 fraginfo->flags & IP6T_FRAG_FST,
+		 ntohs(fh->frag_off) & ~0x7,
+		 !((fraginfo->flags & IP6T_FRAG_FST)
+		   && (ntohs(fh->frag_off) & ~0x7)));
+	pr_debug("mf %02X %02X %02X ",
+		 fraginfo->flags & IP6T_FRAG_MF,
+		 ntohs(fh->frag_off) & IP6_MF,
+		 !((fraginfo->flags & IP6T_FRAG_MF)
+		   && !((ntohs(fh->frag_off) & IP6_MF))));
+	pr_debug("last %02X %02X %02X\n",
+		 fraginfo->flags & IP6T_FRAG_NMF,
+		 ntohs(fh->frag_off) & IP6_MF,
+		 !((fraginfo->flags & IP6T_FRAG_NMF)
+		   && (ntohs(fh->frag_off) & IP6_MF)));
 
 	return (fh != NULL)
 	       &&
-	       (id_match(fraginfo->ids[0], fraginfo->ids[1],
-			 ntohl(fh->identification),
-			 !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))
+	       id_match(fraginfo->ids[0], fraginfo->ids[1],
+			ntohl(fh->identification),
+			!!(fraginfo->invflags & IP6T_FRAG_INV_IDS))
 	       &&
 	       !((fraginfo->flags & IP6T_FRAG_RES)
 		 && (fh->reserved || (ntohs(fh->frag_off) & 0x6)))
@@ -120,7 +115,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip,
 	   const struct xt_match *match,
@@ -130,13 +125,13 @@
 	const struct ip6t_frag *fraginfo = matchinfo;
 
 	if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) {
-		DEBUGP("ip6t_frag: unknown flags %X\n", fraginfo->invflags);
-		return 0;
+		pr_debug("ip6t_frag: unknown flags %X\n", fraginfo->invflags);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match frag_match = {
+static struct xt_match frag_match __read_mostly = {
 	.name		= "frag",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index d2373c7..e6ca601 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -25,12 +25,6 @@
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 MODULE_ALIAS("ip6t_dst");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /*
  *  (Type & 0xC0) >> 6
  *	0	-> ignorable
@@ -47,7 +41,7 @@
  *	5	-> RTALERT 2 x x
  */
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -55,45 +49,48 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
-	struct ipv6_opt_hdr _optsh, *oh;
+	struct ipv6_opt_hdr _optsh;
+	const struct ipv6_opt_hdr *oh;
 	const struct ip6t_opts *optinfo = matchinfo;
 	unsigned int temp;
 	unsigned int ptr;
 	unsigned int hdrlen = 0;
-	unsigned int ret = 0;
-	u8 _opttype, *tp = NULL;
-	u8 _optlen, *lp = NULL;
+	bool ret = false;
+	u8 _opttype;
+	u8 _optlen;
+	const u_int8_t *tp = NULL;
+	const u_int8_t *lp = NULL;
 	unsigned int optlen;
 	int err;
 
 	err = ipv6_find_hdr(skb, &ptr, match->data, NULL);
 	if (err < 0) {
 		if (err != -ENOENT)
-			*hotdrop = 1;
-		return 0;
+			*hotdrop = true;
+		return false;
 	}
 
 	oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
 	if (oh == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	hdrlen = ipv6_optlen(oh);
 	if (skb->len - ptr < hdrlen) {
 		/* Packet smaller than it's length field */
-		return 0;
+		return false;
 	}
 
-	DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
+	pr_debug("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
 
-	DEBUGP("len %02X %04X %02X ",
-	       optinfo->hdrlen, hdrlen,
-	       (!(optinfo->flags & IP6T_OPTS_LEN) ||
-		((optinfo->hdrlen == hdrlen) ^
-		 !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
+	pr_debug("len %02X %04X %02X ",
+		 optinfo->hdrlen, hdrlen,
+		 (!(optinfo->flags & IP6T_OPTS_LEN) ||
+		  ((optinfo->hdrlen == hdrlen) ^
+		   !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
 
 	ret = (oh != NULL) &&
 	      (!(optinfo->flags & IP6T_OPTS_LEN) ||
@@ -105,10 +102,10 @@
 	if (!(optinfo->flags & IP6T_OPTS_OPTS)) {
 		return ret;
 	} else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
-		DEBUGP("Not strict - not implemented");
+		pr_debug("Not strict - not implemented");
 	} else {
-		DEBUGP("Strict ");
-		DEBUGP("#%d ", optinfo->optsnr);
+		pr_debug("Strict ");
+		pr_debug("#%d ", optinfo->optsnr);
 		for (temp = 0; temp < optinfo->optsnr; temp++) {
 			/* type field exists ? */
 			if (hdrlen < 1)
@@ -120,12 +117,11 @@
 
 			/* Type check */
 			if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) {
-				DEBUGP("Tbad %02X %02X\n",
-				       *tp,
-				       (optinfo->opts[temp] & 0xFF00) >> 8);
-				return 0;
+				pr_debug("Tbad %02X %02X\n", *tp,
+					 (optinfo->opts[temp] & 0xFF00) >> 8);
+				return false;
 			} else {
-				DEBUGP("Tok ");
+				pr_debug("Tok ");
 			}
 			/* Length check */
 			if (*tp) {
@@ -142,23 +138,23 @@
 				spec_len = optinfo->opts[temp] & 0x00FF;
 
 				if (spec_len != 0x00FF && spec_len != *lp) {
-					DEBUGP("Lbad %02X %04X\n", *lp,
-					       spec_len);
-					return 0;
+					pr_debug("Lbad %02X %04X\n", *lp,
+						 spec_len);
+					return false;
 				}
-				DEBUGP("Lok ");
+				pr_debug("Lok ");
 				optlen = *lp + 2;
 			} else {
-				DEBUGP("Pad1\n");
+				pr_debug("Pad1\n");
 				optlen = 1;
 			}
 
 			/* Step to the next */
-			DEBUGP("len%04X \n", optlen);
+			pr_debug("len%04X \n", optlen);
 
 			if ((ptr > skb->len - optlen || hdrlen < optlen) &&
-			    (temp < optinfo->optsnr - 1)) {
-				DEBUGP("new pointer is too large! \n");
+			    temp < optinfo->optsnr - 1) {
+				pr_debug("new pointer is too large! \n");
 				break;
 			}
 			ptr += optlen;
@@ -167,14 +163,14 @@
 		if (temp == optinfo->optsnr)
 			return ret;
 		else
-			return 0;
+			return false;
 	}
 
-	return 0;
+	return false;
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *entry,
 	   const struct xt_match *match,
@@ -184,13 +180,13 @@
 	const struct ip6t_opts *optsinfo = matchinfo;
 
 	if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
-		DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
-		return 0;
+		pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match opts_match[] = {
+static struct xt_match opts_match[] __read_mostly = {
 	{
 		.name		= "hbh",
 		.family		= AF_INET6,
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index d606c0e..ca29ec0 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -19,37 +19,37 @@
 MODULE_DESCRIPTION("IP tables Hop Limit matching module");
 MODULE_LICENSE("GPL");
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in, const struct net_device *out,
-		 const struct xt_match *match, const void *matchinfo,
-		 int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in, const struct net_device *out,
+		  const struct xt_match *match, const void *matchinfo,
+		  int offset, unsigned int protoff, bool *hotdrop)
 {
 	const struct ip6t_hl_info *info = matchinfo;
 	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
 
 	switch (info->mode) {
 		case IP6T_HL_EQ:
-			return (ip6h->hop_limit == info->hop_limit);
+			return ip6h->hop_limit == info->hop_limit;
 			break;
 		case IP6T_HL_NE:
-			return (!(ip6h->hop_limit == info->hop_limit));
+			return ip6h->hop_limit != info->hop_limit;
 			break;
 		case IP6T_HL_LT:
-			return (ip6h->hop_limit < info->hop_limit);
+			return ip6h->hop_limit < info->hop_limit;
 			break;
 		case IP6T_HL_GT:
-			return (ip6h->hop_limit > info->hop_limit);
+			return ip6h->hop_limit > info->hop_limit;
 			break;
 		default:
 			printk(KERN_WARNING "ip6t_hl: unknown mode %d\n",
 				info->mode);
-			return 0;
+			return false;
 	}
 
-	return 0;
+	return false;
 }
 
-static struct xt_match hl_match = {
+static struct xt_match hl_match __read_mostly = {
 	.name		= "hl",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index fd6a086..2c65c2f 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -26,7 +26,7 @@
 MODULE_DESCRIPTION("IPv6 headers match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 
-static int
+static bool
 ipv6header_match(const struct sk_buff *skb,
 		 const struct net_device *in,
 		 const struct net_device *out,
@@ -34,7 +34,7 @@
 		 const void *matchinfo,
 		 int offset,
 		 unsigned int protoff,
-		 int *hotdrop)
+		 bool *hotdrop)
 {
 	const struct ip6t_ipv6header_info *info = matchinfo;
 	unsigned int temp;
@@ -58,7 +58,7 @@
 
 		/* Is there enough space for the next ext header? */
 		if (len < (int)sizeof(struct ipv6_opt_hdr))
-			return 0;
+			return false;
 		/* No more exthdr -> evaluate */
 		if (nexthdr == NEXTHDR_NONE) {
 			temp |= MASK_NONE;
@@ -74,9 +74,9 @@
 		BUG_ON(hp == NULL);
 
 		/* Calculate the header length */
-		if (nexthdr == NEXTHDR_FRAGMENT) {
+		if (nexthdr == NEXTHDR_FRAGMENT)
 			hdrlen = 8;
-		} else if (nexthdr == NEXTHDR_AUTH)
+		else if (nexthdr == NEXTHDR_AUTH)
 			hdrlen = (hp->hdrlen + 2) << 2;
 		else
 			hdrlen = ipv6_optlen(hp);
@@ -99,7 +99,7 @@
 			temp |= MASK_DSTOPTS;
 			break;
 		default:
-			return 0;
+			return false;
 			break;
 		}
 
@@ -110,7 +110,7 @@
 			break;
 	}
 
-	if ((nexthdr != NEXTHDR_NONE) && (nexthdr != NEXTHDR_ESP))
+	if (nexthdr != NEXTHDR_NONE && nexthdr != NEXTHDR_ESP)
 		temp |= MASK_PROTO;
 
 	if (info->modeflag)
@@ -124,7 +124,7 @@
 	}
 }
 
-static int
+static bool
 ipv6header_checkentry(const char *tablename,
 		      const void *ip,
 		      const struct xt_match *match,
@@ -136,12 +136,12 @@
 	/* invflags is 0 or 0xff in hard mode */
 	if ((!info->modeflag) && info->invflags != 0x00 &&
 	    info->invflags != 0xFF)
-		return 0;
+		return false;
 
-	return 1;
+	return true;
 }
 
-static struct xt_match ip6t_ipv6header_match = {
+static struct xt_match ip6t_ipv6header_match __read_mostly = {
 	.name		= "ipv6header",
 	.family		= AF_INET6,
 	.match		= &ipv6header_match,
diff --git a/net/ipv6/netfilter/ip6t_mh.c b/net/ipv6/netfilter/ip6t_mh.c
index c2a9098..0fa7140 100644
--- a/net/ipv6/netfilter/ip6t_mh.c
+++ b/net/ipv6/netfilter/ip6t_mh.c
@@ -31,16 +31,13 @@
 #endif
 
 /* Returns 1 if the type is matched by the range, 0 otherwise */
-static inline int
-type_match(u_int8_t min, u_int8_t max, u_int8_t type, int invert)
+static inline bool
+type_match(u_int8_t min, u_int8_t max, u_int8_t type, bool invert)
 {
-	int ret;
-
-	ret = (type >= min && type <= max) ^ invert;
-	return ret;
+	return (type >= min && type <= max) ^ invert;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
 	 const struct net_device *in,
 	 const struct net_device *out,
@@ -48,29 +45,30 @@
 	 const void *matchinfo,
 	 int offset,
 	 unsigned int protoff,
-	 int *hotdrop)
+	 bool *hotdrop)
 {
-	struct ip6_mh _mh, *mh;
+	struct ip6_mh _mh;
+	const struct ip6_mh *mh;
 	const struct ip6t_mh *mhinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	mh = skb_header_pointer(skb, protoff, sizeof(_mh), &_mh);
 	if (mh == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil MH tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	if (mh->ip6mh_proto != IPPROTO_NONE) {
 		duprintf("Dropping invalid MH Payload Proto: %u\n",
 			 mh->ip6mh_proto);
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return type_match(mhinfo->types[0], mhinfo->types[1], mh->ip6mh_type,
@@ -78,7 +76,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 mh_checkentry(const char *tablename,
 	      const void *entry,
 	      const struct xt_match *match,
@@ -91,7 +89,7 @@
 	return !(mhinfo->invflags & ~IP6T_MH_INV_MASK);
 }
 
-static struct xt_match mh_match = {
+static struct xt_match mh_match __read_mostly = {
 	.name		= "mh",
 	.family		= AF_INET6,
 	.checkentry	= mh_checkentry,
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 43738bb..6036613 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -23,7 +23,7 @@
 MODULE_LICENSE("GPL");
 
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -31,29 +31,27 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct ip6t_owner_info *info = matchinfo;
 
 	if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
-		return 0;
+		return false;
 
-	if (info->match & IP6T_OWNER_UID) {
+	if (info->match & IP6T_OWNER_UID)
 		if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
 		    !!(info->invert & IP6T_OWNER_UID))
-			return 0;
-	}
+			return false;
 
-	if (info->match & IP6T_OWNER_GID) {
+	if (info->match & IP6T_OWNER_GID)
 		if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
 		    !!(info->invert & IP6T_OWNER_GID))
-			return 0;
-	}
+			return false;
 
-	return 1;
+	return true;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip,
 	   const struct xt_match *match,
@@ -65,12 +63,12 @@
 	if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) {
 		printk("ipt_owner: pid and sid matching "
 		       "not supported anymore\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match owner_match = {
+static struct xt_match owner_match __read_mostly = {
 	.name		= "owner",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 81ab00d..357cea7 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -24,25 +24,19 @@
 MODULE_DESCRIPTION("IPv6 RT match");
 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Returns 1 if the id is matched by the range, 0 otherwise */
-static inline int
-segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
+static inline bool
+segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert)
 {
-	int r = 0;
-	DEBUGP("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x",
-	       invert ? '!' : ' ', min, id, max);
+	bool r;
+	pr_debug("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x",
+		 invert ? '!' : ' ', min, id, max);
 	r = (id >= min && id <= max) ^ invert;
-	DEBUGP(" result %s\n", r ? "PASS" : "FAILED");
+	pr_debug(" result %s\n", r ? "PASS" : "FAILED");
 	return r;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -50,59 +44,61 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
-	struct ipv6_rt_hdr _route, *rh;
+	struct ipv6_rt_hdr _route;
+	const struct ipv6_rt_hdr *rh;
 	const struct ip6t_rt *rtinfo = matchinfo;
 	unsigned int temp;
 	unsigned int ptr;
 	unsigned int hdrlen = 0;
-	unsigned int ret = 0;
-	struct in6_addr *ap, _addr;
+	bool ret = false;
+	struct in6_addr _addr;
+	const struct in6_addr *ap;
 	int err;
 
 	err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL);
 	if (err < 0) {
 		if (err != -ENOENT)
-			*hotdrop = 1;
-		return 0;
+			*hotdrop = true;
+		return false;
 	}
 
 	rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
 	if (rh == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	hdrlen = ipv6_optlen(rh);
 	if (skb->len - ptr < hdrlen) {
 		/* Pcket smaller than its length field */
-		return 0;
+		return false;
 	}
 
-	DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
-	DEBUGP("TYPE %04X ", rh->type);
-	DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
+	pr_debug("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
+	pr_debug("TYPE %04X ", rh->type);
+	pr_debug("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
 
-	DEBUGP("IPv6 RT segsleft %02X ",
-	       (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
-			       rh->segments_left,
-			       !!(rtinfo->invflags & IP6T_RT_INV_SGS))));
-	DEBUGP("type %02X %02X %02X ",
-	       rtinfo->rt_type, rh->type,
-	       (!(rtinfo->flags & IP6T_RT_TYP) ||
-		((rtinfo->rt_type == rh->type) ^
-		 !!(rtinfo->invflags & IP6T_RT_INV_TYP))));
-	DEBUGP("len %02X %04X %02X ",
-	       rtinfo->hdrlen, hdrlen,
-	       (!(rtinfo->flags & IP6T_RT_LEN) ||
-		((rtinfo->hdrlen == hdrlen) ^
-		 !!(rtinfo->invflags & IP6T_RT_INV_LEN))));
-	DEBUGP("res %02X %02X %02X ",
-	       (rtinfo->flags & IP6T_RT_RES),
-	       ((struct rt0_hdr *)rh)->reserved,
-	       !((rtinfo->flags & IP6T_RT_RES) &&
-		 (((struct rt0_hdr *)rh)->reserved)));
+	pr_debug("IPv6 RT segsleft %02X ",
+		 segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
+				rh->segments_left,
+				!!(rtinfo->invflags & IP6T_RT_INV_SGS)));
+	pr_debug("type %02X %02X %02X ",
+		 rtinfo->rt_type, rh->type,
+		 (!(rtinfo->flags & IP6T_RT_TYP) ||
+		  ((rtinfo->rt_type == rh->type) ^
+		   !!(rtinfo->invflags & IP6T_RT_INV_TYP))));
+	pr_debug("len %02X %04X %02X ",
+		 rtinfo->hdrlen, hdrlen,
+		 !(rtinfo->flags & IP6T_RT_LEN) ||
+		  ((rtinfo->hdrlen == hdrlen) ^
+		   !!(rtinfo->invflags & IP6T_RT_INV_LEN)));
+	pr_debug("res %02X %02X %02X ",
+		 rtinfo->flags & IP6T_RT_RES,
+		 ((const struct rt0_hdr *)rh)->reserved,
+		 !((rtinfo->flags & IP6T_RT_RES) &&
+		   (((const struct rt0_hdr *)rh)->reserved)));
 
 	ret = (rh != NULL)
 	      &&
@@ -129,18 +125,18 @@
 		ret = (*rp == 0);
 	}
 
-	DEBUGP("#%d ", rtinfo->addrnr);
+	pr_debug("#%d ", rtinfo->addrnr);
 	if (!(rtinfo->flags & IP6T_RT_FST)) {
 		return ret;
 	} else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) {
-		DEBUGP("Not strict ");
+		pr_debug("Not strict ");
 		if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) {
-			DEBUGP("There isn't enough space\n");
-			return 0;
+			pr_debug("There isn't enough space\n");
+			return false;
 		} else {
 			unsigned int i = 0;
 
-			DEBUGP("#%d ", rtinfo->addrnr);
+			pr_debug("#%d ", rtinfo->addrnr);
 			for (temp = 0;
 			     temp < (unsigned int)((hdrlen - 8) / 16);
 			     temp++) {
@@ -154,25 +150,25 @@
 				BUG_ON(ap == NULL);
 
 				if (ipv6_addr_equal(ap, &rtinfo->addrs[i])) {
-					DEBUGP("i=%d temp=%d;\n", i, temp);
+					pr_debug("i=%d temp=%d;\n", i, temp);
 					i++;
 				}
 				if (i == rtinfo->addrnr)
 					break;
 			}
-			DEBUGP("i=%d #%d\n", i, rtinfo->addrnr);
+			pr_debug("i=%d #%d\n", i, rtinfo->addrnr);
 			if (i == rtinfo->addrnr)
 				return ret;
 			else
-				return 0;
+				return false;
 		}
 	} else {
-		DEBUGP("Strict ");
+		pr_debug("Strict ");
 		if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) {
-			DEBUGP("There isn't enough space\n");
-			return 0;
+			pr_debug("There isn't enough space\n");
+			return false;
 		} else {
-			DEBUGP("#%d ", rtinfo->addrnr);
+			pr_debug("#%d ", rtinfo->addrnr);
 			for (temp = 0; temp < rtinfo->addrnr; temp++) {
 				ap = skb_header_pointer(skb,
 							ptr
@@ -185,20 +181,20 @@
 				if (!ipv6_addr_equal(ap, &rtinfo->addrs[temp]))
 					break;
 			}
-			DEBUGP("temp=%d #%d\n", temp, rtinfo->addrnr);
-			if ((temp == rtinfo->addrnr) &&
-			    (temp == (unsigned int)((hdrlen - 8) / 16)))
+			pr_debug("temp=%d #%d\n", temp, rtinfo->addrnr);
+			if (temp == rtinfo->addrnr &&
+			    temp == (unsigned int)((hdrlen - 8) / 16))
 				return ret;
 			else
-				return 0;
+				return false;
 		}
 	}
 
-	return 0;
+	return false;
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *entry,
 	   const struct xt_match *match,
@@ -208,21 +204,21 @@
 	const struct ip6t_rt *rtinfo = matchinfo;
 
 	if (rtinfo->invflags & ~IP6T_RT_INV_MASK) {
-		DEBUGP("ip6t_rt: unknown flags %X\n", rtinfo->invflags);
-		return 0;
+		pr_debug("ip6t_rt: unknown flags %X\n", rtinfo->invflags);
+		return false;
 	}
 	if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) &&
 	    (!(rtinfo->flags & IP6T_RT_TYP) ||
 	     (rtinfo->rt_type != 0) ||
 	     (rtinfo->invflags & IP6T_RT_INV_TYP))) {
-		DEBUGP("`--rt-type 0' required before `--rt-0-*'");
-		return 0;
+		pr_debug("`--rt-type 0' required before `--rt-0-*'");
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static struct xt_match rt_match = {
+static struct xt_match rt_match __read_mostly = {
 	.name		= "rt",
 	.family		= AF_INET6,
 	.match		= match,
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index f2d2649..f0a9efa 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -21,12 +21,6 @@
 			    (1 << NF_IP6_LOCAL_OUT) | \
 			    (1 << NF_IP6_POST_ROUTING))
 
-#if 0
-#define DEBUGP(x, args...)	printk(KERN_DEBUG x, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
 static struct
 {
 	struct ip6t_replace repl;
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 0acda45..ec290e4 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -8,12 +8,6 @@
 
 #define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
 
-#if 0
-#define DEBUGP(x, args...)	printk(KERN_DEBUG x, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
 static struct
 {
 	struct ip6t_replace repl;
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 1b1797f..89e20ab 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -26,12 +26,6 @@
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
 			     struct nf_conntrack_tuple *tuple)
 {
@@ -136,7 +130,7 @@
 	 * except of IPv6 & ext headers. but it's tracked anyway. - YK
 	 */
 	if ((protoff < 0) || (protoff > (*pskb)->len)) {
-		DEBUGP("ip6_conntrack_core: can't find proto in pkt\n");
+		pr_debug("ip6_conntrack_core: can't find proto in pkt\n");
 		NF_CT_STAT_INC_ATOMIC(error);
 		NF_CT_STAT_INC_ATOMIC(invalid);
 		return -NF_ACCEPT;
@@ -147,11 +141,6 @@
 	return NF_ACCEPT;
 }
 
-static u_int32_t ipv6_get_features(const struct nf_conntrack_tuple *tuple)
-{
-	return NF_CT_F_BASIC;
-}
-
 static unsigned int ipv6_confirm(unsigned int hooknum,
 				 struct sk_buff **pskb,
 				 const struct net_device *in,
@@ -183,7 +172,7 @@
 	protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
 					 (*pskb)->len - extoff);
 	if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) {
-		DEBUGP("proto header not found\n");
+		pr_debug("proto header not found\n");
 		return NF_ACCEPT;
 	}
 
@@ -397,7 +386,6 @@
 	.ctl_table_path		= nf_net_netfilter_sysctl_path,
 	.ctl_table		= nf_ct_ipv6_sysctl_table,
 #endif
-	.get_features		= ipv6_get_features,
 	.me			= THIS_MODULE,
 };
 
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 8814b95..9defc7e 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -27,12 +27,6 @@
 
 static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int icmpv6_pkt_to_tuple(const struct sk_buff *skb,
 			       unsigned int dataoff,
 			       struct nf_conntrack_tuple *tuple)
@@ -125,8 +119,8 @@
 
 	if (type < 0 || type >= sizeof(valid_new) || !valid_new[type]) {
 		/* Can't create a new ICMPv6 `conn' with this. */
-		DEBUGP("icmpv6: can't create new conn with type %u\n",
-		       type + 128);
+		pr_debug("icmpv6: can't create new conn with type %u\n",
+			 type + 128);
 		NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
 		return 0;
 	}
@@ -152,14 +146,15 @@
 
 	hp = skb_header_pointer(skb, icmp6off, sizeof(_hdr), &_hdr);
 	if (hp == NULL) {
-		DEBUGP("icmpv6_error: Can't get ICMPv6 hdr.\n");
+		pr_debug("icmpv6_error: Can't get ICMPv6 hdr.\n");
 		return -NF_ACCEPT;
 	}
 
 	inip6off = icmp6off + sizeof(_hdr);
 	if (skb_copy_bits(skb, inip6off+offsetof(struct ipv6hdr, nexthdr),
 			  &inprotonum, sizeof(inprotonum)) != 0) {
-		DEBUGP("icmpv6_error: Can't get nexthdr in inner IPv6 header.\n");
+		pr_debug("icmpv6_error: Can't get nexthdr in inner IPv6 "
+			 "header.\n");
 		return -NF_ACCEPT;
 	}
 	inprotoff = nf_ct_ipv6_skip_exthdr(skb,
@@ -169,7 +164,8 @@
 						    - sizeof(struct ipv6hdr));
 
 	if ((inprotoff > skb->len) || (inprotonum == NEXTHDR_FRAGMENT)) {
-		DEBUGP("icmpv6_error: Can't get protocol header in ICMPv6 payload.\n");
+		pr_debug("icmpv6_error: Can't get protocol header in ICMPv6 "
+			 "payload.\n");
 		return -NF_ACCEPT;
 	}
 
@@ -179,7 +175,7 @@
 	/* Are they talking about one of our connections? */
 	if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum,
 			     &origtuple, &nf_conntrack_l3proto_ipv6, inproto)) {
-		DEBUGP("icmpv6_error: Can't get tuple\n");
+		pr_debug("icmpv6_error: Can't get tuple\n");
 		return -NF_ACCEPT;
 	}
 
@@ -187,15 +183,15 @@
 	   been preserved inside the ICMP. */
 	if (!nf_ct_invert_tuple(&intuple, &origtuple,
 				&nf_conntrack_l3proto_ipv6, inproto)) {
-		DEBUGP("icmpv6_error: Can't invert tuple\n");
+		pr_debug("icmpv6_error: Can't invert tuple\n");
 		return -NF_ACCEPT;
 	}
 
 	*ctinfo = IP_CT_RELATED;
 
-	h = nf_conntrack_find_get(&intuple, NULL);
+	h = nf_conntrack_find_get(&intuple);
 	if (!h) {
-		DEBUGP("icmpv6_error: no match\n");
+		pr_debug("icmpv6_error: no match\n");
 		return -NF_ACCEPT;
 	} else {
 		if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 347ab76..25442a8 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -44,12 +44,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 #define NF_CT_FRAG6_HIGH_THRESH 262144 /* == 256*1024 */
 #define NF_CT_FRAG6_LOW_THRESH 196608  /* == 192*1024 */
 #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT
@@ -343,7 +337,7 @@
 	struct nf_ct_frag6_queue *fq;
 
 	if ((fq = frag_alloc_queue()) == NULL) {
-		DEBUGP("Can't alloc new queue\n");
+		pr_debug("Can't alloc new queue\n");
 		goto oom;
 	}
 
@@ -393,7 +387,7 @@
 	int offset, end;
 
 	if (fq->last_in & COMPLETE) {
-		DEBUGP("Allready completed\n");
+		pr_debug("Allready completed\n");
 		goto err;
 	}
 
@@ -402,7 +396,7 @@
 			((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1)));
 
 	if ((unsigned int)end > IPV6_MAXPLEN) {
-		DEBUGP("offset is too large.\n");
+		pr_debug("offset is too large.\n");
 		return -1;
 	}
 
@@ -420,7 +414,7 @@
 		 */
 		if (end < fq->len ||
 		    ((fq->last_in & LAST_IN) && end != fq->len)) {
-			DEBUGP("already received last fragment\n");
+			pr_debug("already received last fragment\n");
 			goto err;
 		}
 		fq->last_in |= LAST_IN;
@@ -433,13 +427,13 @@
 			/* RFC2460 says always send parameter problem in
 			 * this case. -DaveM
 			 */
-			DEBUGP("the end of this fragment is not rounded to 8 bytes.\n");
+			pr_debug("end of fragment not rounded to 8 bytes.\n");
 			return -1;
 		}
 		if (end > fq->len) {
 			/* Some bits beyond end -> corruption. */
 			if (fq->last_in & LAST_IN) {
-				DEBUGP("last packet already reached.\n");
+				pr_debug("last packet already reached.\n");
 				goto err;
 			}
 			fq->len = end;
@@ -451,11 +445,11 @@
 
 	/* Point into the IP datagram 'data' part. */
 	if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data)) {
-		DEBUGP("queue: message is too short.\n");
+		pr_debug("queue: message is too short.\n");
 		goto err;
 	}
 	if (pskb_trim_rcsum(skb, end - offset)) {
-		DEBUGP("Can't trim\n");
+		pr_debug("Can't trim\n");
 		goto err;
 	}
 
@@ -480,11 +474,11 @@
 		if (i > 0) {
 			offset += i;
 			if (end <= offset) {
-				DEBUGP("overlap\n");
+				pr_debug("overlap\n");
 				goto err;
 			}
 			if (!pskb_pull(skb, i)) {
-				DEBUGP("Can't pull\n");
+				pr_debug("Can't pull\n");
 				goto err;
 			}
 			if (skb->ip_summed != CHECKSUM_UNNECESSARY)
@@ -503,7 +497,7 @@
 			/* Eat head of the next overlapped fragment
 			 * and leave the loop. The next ones cannot overlap.
 			 */
-			DEBUGP("Eat head of the overlapped parts.: %d", i);
+			pr_debug("Eat head of the overlapped parts.: %d", i);
 			if (!pskb_pull(next, i))
 				goto err;
 
@@ -586,13 +580,13 @@
 		       sizeof(struct ipv6hdr) + fq->len -
 		       sizeof(struct frag_hdr));
 	if (payload_len > IPV6_MAXPLEN) {
-		DEBUGP("payload len is too large.\n");
+		pr_debug("payload len is too large.\n");
 		goto out_oversize;
 	}
 
 	/* Head of list must not be cloned. */
 	if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC)) {
-		DEBUGP("skb is cloned but can't expand head");
+		pr_debug("skb is cloned but can't expand head");
 		goto out_oom;
 	}
 
@@ -604,7 +598,7 @@
 		int i, plen = 0;
 
 		if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL) {
-			DEBUGP("Can't alloc skb\n");
+			pr_debug("Can't alloc skb\n");
 			goto out_oom;
 		}
 		clone->next = head->next;
@@ -719,11 +713,11 @@
 			return -1;
 		}
 		if (len < (int)sizeof(struct ipv6_opt_hdr)) {
-			DEBUGP("too short\n");
+			pr_debug("too short\n");
 			return -1;
 		}
 		if (nexthdr == NEXTHDR_NONE) {
-			DEBUGP("next header is none\n");
+			pr_debug("next header is none\n");
 			return -1;
 		}
 		if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
@@ -764,7 +758,7 @@
 
 	/* Jumbo payload inhibits frag. header */
 	if (ipv6_hdr(skb)->payload_len == 0) {
-		DEBUGP("payload len = 0\n");
+		pr_debug("payload len = 0\n");
 		return skb;
 	}
 
@@ -773,14 +767,14 @@
 
 	clone = skb_clone(skb, GFP_ATOMIC);
 	if (clone == NULL) {
-		DEBUGP("Can't clone skb\n");
+		pr_debug("Can't clone skb\n");
 		return skb;
 	}
 
 	NFCT_FRAG6_CB(clone)->orig = skb;
 
 	if (!pskb_may_pull(clone, fhoff + sizeof(*fhdr))) {
-		DEBUGP("message is too short.\n");
+		pr_debug("message is too short.\n");
 		goto ret_orig;
 	}
 
@@ -789,7 +783,7 @@
 	fhdr = (struct frag_hdr *)skb_transport_header(clone);
 
 	if (!(fhdr->frag_off & htons(0xFFF9))) {
-		DEBUGP("Invalid fragment offset\n");
+		pr_debug("Invalid fragment offset\n");
 		/* It is not a fragmented frame */
 		goto ret_orig;
 	}
@@ -799,7 +793,7 @@
 
 	fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr);
 	if (fq == NULL) {
-		DEBUGP("Can't find and can't create new queue\n");
+		pr_debug("Can't find and can't create new queue\n");
 		goto ret_orig;
 	}
 
@@ -807,7 +801,7 @@
 
 	if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) {
 		spin_unlock(&fq->lock);
-		DEBUGP("Can't insert skb to queue\n");
+		pr_debug("Can't insert skb to queue\n");
 		fq_put(fq, NULL);
 		goto ret_orig;
 	}
@@ -815,7 +809,7 @@
 	if (fq->last_in == (FIRST_IN|LAST_IN) && fq->meat == fq->len) {
 		ret_skb = nf_ct_frag6_reasm(fq, dev);
 		if (ret_skb == NULL)
-			DEBUGP("Can't reassemble fragmented packets\n");
+			pr_debug("Can't reassemble fragmented packets\n");
 	}
 	spin_unlock(&fq->lock);
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index a58459a..e27383d 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -49,7 +49,7 @@
 #include <net/udp.h>
 #include <net/inet_common.h>
 #include <net/tcp_states.h>
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 #include <net/mip6.h>
 #endif
 
@@ -137,6 +137,28 @@
 	return 0;
 }
 
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+static int (*mh_filter)(struct sock *sock, struct sk_buff *skb);
+
+int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
+					   struct sk_buff *skb))
+{
+	rcu_assign_pointer(mh_filter, filter);
+	return 0;
+}
+EXPORT_SYMBOL(rawv6_mh_filter_register);
+
+int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
+					     struct sk_buff *skb))
+{
+	rcu_assign_pointer(mh_filter, NULL);
+	synchronize_rcu();
+	return 0;
+}
+EXPORT_SYMBOL(rawv6_mh_filter_unregister);
+
+#endif
+
 /*
  *	demultiplex raw sockets.
  *	(should consider queueing the skb in the sock receive_queue
@@ -178,16 +200,22 @@
 		case IPPROTO_ICMPV6:
 			filtered = icmpv6_filter(sk, skb);
 			break;
-#ifdef CONFIG_IPV6_MIP6
+
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		case IPPROTO_MH:
+		{
 			/* XXX: To validate MH only once for each packet,
 			 * this is placed here. It should be after checking
 			 * xfrm policy, however it doesn't. The checking xfrm
 			 * policy is placed in rawv6_rcv() because it is
 			 * required for each socket.
 			 */
-			filtered = mip6_mh_filter(sk, skb);
+			int (*filter)(struct sock *sock, struct sk_buff *skb);
+
+			filter = rcu_dereference(mh_filter);
+			filtered = filter ? filter(sk, skb) : 0;
 			break;
+		}
 #endif
 		default:
 			filtered = 0;
@@ -611,9 +639,7 @@
 	struct iovec *iov;
 	u8 __user *type = NULL;
 	u8 __user *code = NULL;
-#ifdef CONFIG_IPV6_MIP6
 	u8 len = 0;
-#endif
 	int probed = 0;
 	int i;
 
@@ -646,7 +672,6 @@
 				probed = 1;
 			}
 			break;
-#ifdef CONFIG_IPV6_MIP6
 		case IPPROTO_MH:
 			if (iov->iov_base && iov->iov_len < 1)
 				break;
@@ -660,7 +685,6 @@
 				len += iov->iov_len;
 
 			break;
-#endif
 		default:
 			probed = 1;
 			break;
@@ -1256,7 +1280,7 @@
 	return 0;
 }
 
-static struct seq_operations raw6_seq_ops = {
+static const struct seq_operations raw6_seq_ops = {
 	.start =	raw6_seq_start,
 	.next =		raw6_seq_next,
 	.stop =		raw6_seq_stop,
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 1efa95a..eb20bb6 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -532,7 +532,8 @@
 	 */
 	max_headroom = LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr);
 
-	if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+	if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
+	    (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
 		struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
 		if (!new_skb) {
 			ip_rt_put(rt);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 193d9d6..d67fb1e 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -484,17 +484,6 @@
 
 	if (dst == NULL) {
 		opt = np->opt;
-		if (opt == NULL &&
-		    np->rxopt.bits.osrcrt == 2 &&
-		    treq->pktopts) {
-			struct sk_buff *pktopts = treq->pktopts;
-			struct inet6_skb_parm *rxopt = IP6CB(pktopts);
-			if (rxopt->srcrt)
-				opt = ipv6_invert_rthdr(sk,
-			  (struct ipv6_rt_hdr *)(skb_network_header(pktopts) +
-						 rxopt->srcrt));
-		}
-
 		if (opt && opt->srcrt) {
 			struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
 			ipv6_addr_copy(&final, &fl.fl6_dst);
@@ -1391,15 +1380,6 @@
 	if (sk_acceptq_is_full(sk))
 		goto out_overflow;
 
-	if (np->rxopt.bits.osrcrt == 2 &&
-	    opt == NULL && treq->pktopts) {
-		struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts);
-		if (rxopt->srcrt)
-			opt = ipv6_invert_rthdr(sk,
-		   (struct ipv6_rt_hdr *)(skb_network_header(treq->pktopts) +
-					  rxopt->srcrt));
-	}
-
 	if (dst == NULL) {
 		struct in6_addr *final_p = NULL, final;
 		struct flowi fl;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 1faa2ea..3ec0c47 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -18,7 +18,7 @@
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 #include <net/mip6.h>
 #endif
 
@@ -318,7 +318,7 @@
 			fl->proto = nexthdr;
 			return;
 
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 		case IPPROTO_MH:
 			if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
 				struct ip6_mh *mh;
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index baa461b..cdadb48 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -65,7 +65,7 @@
 		goto end;
 
 	/* Rule 2: select MIPv6 RO or inbound trigger */
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	for (i = 0; i < n; i++) {
 		if (src[i] &&
 		    (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION ||
@@ -130,7 +130,7 @@
 		goto end;
 
 	/* Rule 2: select MIPv6 RO or inbound trigger */
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
 	for (i = 0; i < n; i++) {
 		if (src[i] &&
 		    (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION ||
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 5502cc94..6f87dd5 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -379,3 +379,4 @@
 module_init(xfrm6_tunnel_init);
 module_exit(xfrm6_tunnel_fini);
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_IPV6);
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c
index db32ac8..4226e71 100644
--- a/net/ipx/ipx_proc.c
+++ b/net/ipx/ipx_proc.c
@@ -286,21 +286,21 @@
 	return 0;
 }
 
-static struct seq_operations ipx_seq_interface_ops = {
+static const struct seq_operations ipx_seq_interface_ops = {
 	.start  = ipx_seq_interface_start,
 	.next   = ipx_seq_interface_next,
 	.stop   = ipx_seq_interface_stop,
 	.show   = ipx_seq_interface_show,
 };
 
-static struct seq_operations ipx_seq_route_ops = {
+static const struct seq_operations ipx_seq_route_ops = {
 	.start  = ipx_seq_route_start,
 	.next   = ipx_seq_route_next,
 	.stop   = ipx_seq_route_stop,
 	.show   = ipx_seq_route_show,
 };
 
-static struct seq_operations ipx_seq_socket_ops = {
+static const struct seq_operations ipx_seq_socket_ops = {
 	.start  = ipx_seq_socket_start,
 	.next   = ipx_seq_socket_next,
 	.stop   = ipx_seq_interface_stop,
diff --git a/net/irda/Makefile b/net/irda/Makefile
index d1366c2..187f6c5 100644
--- a/net/irda/Makefile
+++ b/net/irda/Makefile
@@ -10,6 +10,6 @@
 irda-y := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \
           irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \
           irttp.o irda_device.o irias_object.o wrapper.o af_irda.o \
-	  discovery.o parameters.o irmod.o
+	  discovery.o parameters.o irnetlink.o irmod.o
 irda-$(CONFIG_PROC_FS) += irproc.o
 irda-$(CONFIG_SYSCTL) += irsysctl.o
diff --git a/net/irda/discovery.c b/net/irda/discovery.c
index f097341..af0cea7 100644
--- a/net/irda/discovery.c
+++ b/net/irda/discovery.c
@@ -395,7 +395,7 @@
 	return 0;
 }
 
-static struct seq_operations discovery_seq_ops = {
+static const struct seq_operations discovery_seq_ops = {
 	.start  = discovery_seq_start,
 	.next   = discovery_seq_next,
 	.stop   = discovery_seq_stop,
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
index 4749f8f..2d63fa8 100644
--- a/net/irda/ircomm/ircomm_core.c
+++ b/net/irda/ircomm/ircomm_core.c
@@ -562,7 +562,7 @@
 	return 0;
 }
 
-static struct seq_operations ircomm_seq_ops = {
+static const struct seq_operations ircomm_seq_ops = {
 	.start  = ircomm_seq_start,
 	.next   = ircomm_seq_next,
 	.stop   = ircomm_seq_stop,
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 915d938..774eb70 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -1066,7 +1066,7 @@
 	return 0;
 }
 
-static struct seq_operations irias_seq_ops = {
+static const struct seq_operations irias_seq_ops = {
 	.start  = irias_seq_start,
 	.next   = irias_seq_next,
 	.stop   = irias_seq_stop,
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index ed69773..f5778ef 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -1217,7 +1217,7 @@
 	return 0;
 }
 
-static struct seq_operations irlan_seq_ops = {
+static const struct seq_operations irlan_seq_ops = {
 	.start = irlan_seq_start,
 	.next  = irlan_seq_next,
 	.stop  = irlan_seq_stop,
diff --git a/net/irda/irlap.c b/net/irda/irlap.c
index d93ebd1..2fc9f51 100644
--- a/net/irda/irlap.c
+++ b/net/irda/irlap.c
@@ -1210,7 +1210,7 @@
 	return 0;
 }
 
-static struct seq_operations irlap_seq_ops = {
+static const struct seq_operations irlap_seq_ops = {
 	.start  = irlap_seq_start,
 	.next   = irlap_seq_next,
 	.stop   = irlap_seq_stop,
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
index 3013c49a..25a3444 100644
--- a/net/irda/irlap_frame.c
+++ b/net/irda/irlap_frame.c
@@ -101,6 +101,13 @@
 
 	irlap_insert_info(self, skb);
 
+	if (unlikely(self->mode & IRDA_MODE_MONITOR)) {
+		IRDA_DEBUG(3, "%s(): %s is in monitor mode\n", __FUNCTION__,
+			   self->netdev->name);
+		dev_kfree_skb(skb);
+		return;
+	}
+
 	dev_queue_xmit(skb);
 }
 
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 9df0461..24a5e3f 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -1994,7 +1994,7 @@
 	return 0;
 }
 
-static struct seq_operations irlmp_seq_ops = {
+static const struct seq_operations irlmp_seq_ops = {
 	.start  = irlmp_seq_start,
 	.next   = irlmp_seq_next,
 	.stop   = irlmp_seq_stop,
diff --git a/net/irda/irmod.c b/net/irda/irmod.c
index c7fad2c..1900937 100644
--- a/net/irda/irmod.c
+++ b/net/irda/irmod.c
@@ -88,16 +88,23 @@
  */
 static int __init irda_init(void)
 {
+	int ret = 0;
+
 	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
 
 	/* Lower layer of the stack */
 	irlmp_init();
 	irlap_init();
 
+	/* Driver/dongle support */
+	irda_device_init();
+
 	/* Higher layers of the stack */
 	iriap_init();
 	irttp_init();
-	irsock_init();
+	ret = irsock_init();
+	if (ret < 0)
+		goto out_err_1;
 
 	/* Add IrDA packet type (Start receiving packets) */
 	dev_add_pack(&irda_packet_type);
@@ -107,13 +114,44 @@
 	irda_proc_register();
 #endif
 #ifdef CONFIG_SYSCTL
-	irda_sysctl_register();
+	ret = irda_sysctl_register();
+	if (ret < 0)
+		goto out_err_2;
 #endif
 
-	/* Driver/dongle support */
-	irda_device_init();
+	ret = irda_nl_register();
+	if (ret < 0)
+		goto out_err_3;
 
 	return 0;
+
+ out_err_3:
+#ifdef CONFIG_SYSCTL
+	irda_sysctl_unregister();
+#endif
+ out_err_2:
+#ifdef CONFIG_PROC_FS
+	irda_proc_unregister();
+#endif
+
+	/* Remove IrDA packet type (stop receiving packets) */
+	dev_remove_pack(&irda_packet_type);
+
+	/* Remove higher layers */
+	irsock_cleanup();
+ out_err_1:
+	irttp_cleanup();
+	iriap_cleanup();
+
+	/* Remove lower layers */
+	irda_device_cleanup();
+	irlap_cleanup(); /* Must be done before irlmp_cleanup()! DB */
+
+	/* Remove middle layer */
+	irlmp_cleanup();
+
+
+	return ret;
 }
 
 /*
@@ -125,6 +163,8 @@
 static void __exit irda_cleanup(void)
 {
 	/* Remove External APIs */
+	irda_nl_unregister();
+
 #ifdef CONFIG_SYSCTL
 	irda_sysctl_unregister();
 #endif
diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c
new file mode 100644
index 0000000..db71658
--- /dev/null
+++ b/net/irda/irnetlink.c
@@ -0,0 +1,170 @@
+/*
+ * IrDA netlink layer, for stack configuration.
+ *
+ * Copyright (c) 2007 Samuel Ortiz <samuel@sortiz>
+ *
+ * Partly based on the 802.11 nelink implementation
+ * (see net/wireless/nl80211.c) which is:
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/socket.h>
+#include <linux/irda.h>
+#include <net/sock.h>
+#include <net/irda/irda.h>
+#include <net/irda/irlap.h>
+#include <net/genetlink.h>
+
+
+
+static struct genl_family irda_nl_family = {
+	.id = GENL_ID_GENERATE,
+	.name = IRDA_NL_NAME,
+	.hdrsize = 0,
+	.version = IRDA_NL_VERSION,
+	.maxattr = IRDA_NL_CMD_MAX,
+};
+
+static struct net_device * ifname_to_netdev(struct genl_info *info)
+{
+	char * ifname;
+
+	if (!info->attrs[IRDA_NL_ATTR_IFNAME])
+		return NULL;
+
+	ifname = nla_data(info->attrs[IRDA_NL_ATTR_IFNAME]);
+
+	IRDA_DEBUG(5, "%s(): Looking for %s\n", __FUNCTION__, ifname);
+
+	return dev_get_by_name(ifname);
+}
+
+static int irda_nl_set_mode(struct sk_buff *skb, struct genl_info *info)
+{
+	struct net_device * dev;
+	struct irlap_cb * irlap;
+	u32 mode;
+
+	if (!info->attrs[IRDA_NL_ATTR_MODE])
+		return -EINVAL;
+
+	mode = nla_get_u32(info->attrs[IRDA_NL_ATTR_MODE]);
+
+	IRDA_DEBUG(5, "%s(): Switching to mode: %d\n", __FUNCTION__, mode);
+
+	dev = ifname_to_netdev(info);
+	if (!dev)
+		return -ENODEV;
+
+	irlap = (struct irlap_cb *)dev->atalk_ptr;
+	if (!irlap) {
+		dev_put(dev);
+		return -ENODEV;
+	}
+
+	irlap->mode = mode;
+
+	dev_put(dev);
+
+	return 0;
+}
+
+static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info)
+{
+	struct net_device * dev;
+	struct irlap_cb * irlap;
+	struct sk_buff *msg;
+	void *hdr;
+	int ret = -ENOBUFS;
+
+	dev = ifname_to_netdev(info);
+	if (!dev)
+		return -ENODEV;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg) {
+		dev_put(dev);
+		return -ENOMEM;
+	}
+
+	irlap = (struct irlap_cb *)dev->atalk_ptr;
+	if (!irlap) {
+		ret = -ENODEV;
+		goto err_out;
+	}
+
+	hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
+			  &irda_nl_family, 0,  IRDA_NL_CMD_GET_MODE);
+	if (IS_ERR(hdr)) {
+		ret = PTR_ERR(hdr);
+		goto err_out;
+	}
+
+	if(nla_put_string(msg, IRDA_NL_ATTR_IFNAME,
+			  dev->name));
+		goto err_out;
+
+	if(nla_put_u32(msg, IRDA_NL_ATTR_MODE, irlap->mode))
+		goto err_out;
+
+	genlmsg_end(msg, hdr);
+
+	return genlmsg_unicast(msg, info->snd_pid);
+
+ err_out:
+	nlmsg_free(msg);
+	dev_put(dev);
+
+	return ret;
+}
+
+static struct nla_policy irda_nl_policy[IRDA_NL_ATTR_MAX + 1] = {
+	[IRDA_NL_ATTR_IFNAME] = { .type = NLA_NUL_STRING,
+				  .len = IFNAMSIZ-1 },
+	[IRDA_NL_ATTR_MODE] = { .type = NLA_U32 },
+};
+
+static struct genl_ops irda_nl_ops[] = {
+	{
+		.cmd = IRDA_NL_CMD_SET_MODE,
+		.doit = irda_nl_set_mode,
+		.policy = irda_nl_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
+	{
+		.cmd = IRDA_NL_CMD_GET_MODE,
+		.doit = irda_nl_get_mode,
+		.policy = irda_nl_policy,
+		/* can be retrieved by unprivileged users */
+	},
+
+};
+
+int irda_nl_register(void)
+{
+	int err, i;
+
+	err = genl_register_family(&irda_nl_family);
+	if (err)
+		return err;
+
+	for (i = 0; i < ARRAY_SIZE(irda_nl_ops); i++) {
+		err = genl_register_ops(&irda_nl_family, &irda_nl_ops[i]);
+		if (err)
+			goto err_out;
+	}
+	return 0;
+ err_out:
+	genl_unregister_family(&irda_nl_family);
+	return err;
+}
+
+void irda_nl_unregister(void)
+{
+	genl_unregister_family(&irda_nl_family);
+}
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 7069e4a..7f50832a 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -369,6 +369,20 @@
 /* Everything is happily mixed up. Waiting for next clean up - Jean II */
 
 /*
+ * Initialization, that has to be done on new tsap
+ * instance allocation and on duplication
+ */
+static void irttp_init_tsap(struct tsap_cb *tsap)
+{
+	spin_lock_init(&tsap->lock);
+	init_timer(&tsap->todo_timer);
+
+	skb_queue_head_init(&tsap->rx_queue);
+	skb_queue_head_init(&tsap->tx_queue);
+	skb_queue_head_init(&tsap->rx_fragments);
+}
+
+/*
  * Function irttp_open_tsap (stsap, notify)
  *
  *    Create TSAP connection endpoint,
@@ -395,10 +409,11 @@
 		IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __FUNCTION__);
 		return NULL;
 	}
-	spin_lock_init(&self->lock);
+
+	/* Initialize internal objects */
+	irttp_init_tsap(self);
 
 	/* Initialise todo timer */
-	init_timer(&self->todo_timer);
 	self->todo_timer.data     = (unsigned long) self;
 	self->todo_timer.function = &irttp_todo_expired;
 
@@ -418,9 +433,6 @@
 	self->magic = TTP_TSAP_MAGIC;
 	self->connected = FALSE;
 
-	skb_queue_head_init(&self->rx_queue);
-	skb_queue_head_init(&self->tx_queue);
-	skb_queue_head_init(&self->rx_fragments);
 	/*
 	 *  Create LSAP at IrLMP layer
 	 */
@@ -1455,12 +1467,9 @@
 
 	/* Not everything should be copied */
 	new->notify.instance = instance;
-	spin_lock_init(&new->lock);
-	init_timer(&new->todo_timer);
 
-	skb_queue_head_init(&new->rx_queue);
-	skb_queue_head_init(&new->tx_queue);
-	skb_queue_head_init(&new->rx_fragments);
+	/* Initialize internal objects */
+	irttp_init_tsap(new);
 
 	/* This is locked */
 	hashbin_insert(irttp->tsaps, (irda_queue_t *) new, (long) new, NULL);
@@ -1866,7 +1875,7 @@
 	return 0;
 }
 
-static struct seq_operations irttp_seq_ops = {
+static const struct seq_operations irttp_seq_ops = {
 	.start  = irttp_seq_start,
 	.next   = irttp_seq_next,
 	.stop   = irttp_seq_stop,
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c
index 3ab9d9f..49be6c9 100644
--- a/net/llc/llc_proc.c
+++ b/net/llc/llc_proc.c
@@ -184,14 +184,14 @@
 	return 0;
 }
 
-static struct seq_operations llc_seq_socket_ops = {
+static const struct seq_operations llc_seq_socket_ops = {
 	.start  = llc_seq_start,
 	.next   = llc_seq_next,
 	.stop   = llc_seq_stop,
 	.show   = llc_seq_socket_show,
 };
 
-static struct seq_operations llc_seq_core_ops = {
+static const struct seq_operations llc_seq_core_ops = {
 	.start  = llc_seq_start,
 	.next   = llc_seq_next,
 	.stop   = llc_seq_stop,
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 352f03b..66e8a97 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -838,6 +838,29 @@
 }
 
 
+static int ieee80211_ioctl_giwrate(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_param *rate, char *extra)
+{
+	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	struct sta_info *sta;
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	if (sdata->type == IEEE80211_IF_TYPE_STA)
+		sta = sta_info_get(local, sdata->u.sta.bssid);
+	else
+		return -EOPNOTSUPP;
+	if (!sta)
+		return -ENODEV;
+	if (sta->txrate < local->oper_hw_mode->num_rates)
+		rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
+	else
+		rate->value = 0;
+	sta_info_put(sta);
+	return 0;
+}
+
 static int ieee80211_ioctl_siwrts(struct net_device *dev,
 				  struct iw_request_info *info,
 				  struct iw_param *rts, char *extra)
@@ -1779,7 +1802,7 @@
 	(iw_handler) NULL,				/* -- hole -- */
 	(iw_handler) NULL,				/* -- hole -- */
 	(iw_handler) NULL,				/* SIOCSIWRATE */
-	(iw_handler) NULL,				/* SIOCGIWRATE */
+	(iw_handler) ieee80211_ioctl_giwrate,		/* SIOCGIWRATE */
 	(iw_handler) ieee80211_ioctl_siwrts,		/* SIOCSIWRTS */
 	(iw_handler) ieee80211_ioctl_giwrts,		/* SIOCGIWRTS */
 	(iw_handler) ieee80211_ioctl_siwfrag,		/* SIOCSIWFRAG */
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
index 2048cfd..5ae7fc4 100644
--- a/net/mac80211/rc80211_simple.c
+++ b/net/mac80211/rc80211_simple.c
@@ -283,14 +283,16 @@
 	int i;
 	sta->txrate = 0;
 	mode = local->oper_hw_mode;
-	/* TODO: what is a good starting rate for STA? About middle? Maybe not
-	 * the lowest or the highest rate.. Could consider using RSSI from
-	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
-	 * after assoc.. */
+	/* TODO: This routine should consider using RSSI from previous packets
+	 * as we need to have IEEE 802.1X auth succeed immediately after assoc..
+	 * Until that method is implemented, we will use the lowest supported rate
+	 * as a workaround, */
 	for (i = 0; i < mode->num_rates; i++) {
 		if ((sta->supp_rates & BIT(i)) &&
-		    (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
+		    (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) {
 			sta->txrate = i;
+			break;
+		}
 	}
 }
 
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index a567dae..df5e8da 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -343,6 +343,18 @@
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_TARGET_TRACE
+	tristate  '"TRACE" target support'
+	depends on NETFILTER_XTABLES
+	depends on IP_NF_RAW || IP6_NF_RAW
+	help
+	  The TRACE target allows you to mark packets so that the kernel
+	  will log every rule which match the packets as those traverse
+	  the tables, chains, rules.
+
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `N'.
+
 config NETFILTER_XT_TARGET_SECMARK
 	tristate '"SECMARK" target support'
 	depends on NETFILTER_XTABLES && NETWORK_SECMARK
@@ -635,6 +647,19 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_U32
+	tristate '"u32" match support'
+	depends on NETFILTER_XTABLES
+	---help---
+	  u32 allows you to extract quantities of up to 4 bytes from a packet,
+	  AND them with specified masks, shift them by specified amounts and
+	  test whether the results are in any of a set of specified ranges.
+	  The specification of what to extract is general enough to skip over
+	  headers with lengths stored in the packet, as in IP or TCP header
+	  lengths.
+
+	  Details and examples are in the kernel module source.
+
 config NETFILTER_XT_MATCH_HASHLIMIT
 	tristate '"hashlimit" match support'
 	depends on NETFILTER_XTABLES && (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index b2b5c75..58b4245 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,6 +1,6 @@
 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
 
-nf_conntrack-y	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
+nf_conntrack-y	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o
 nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
 
 obj-$(CONFIG_NETFILTER) = netfilter.o
@@ -44,6 +44,7 @@
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
@@ -72,4 +73,5 @@
 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index a84478e..381a77c 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -203,7 +203,9 @@
 		return 0;
 
 	/* Not exclusive use of packet?  Must copy. */
-	if (skb_shared(*pskb) || skb_cloned(*pskb))
+	if (skb_cloned(*pskb) && !skb_clone_writable(*pskb, writable_len))
+		goto copy_skb;
+	if (skb_shared(*pskb))
 		goto copy_skb;
 
 	return pskb_may_pull(*pskb, writable_len);
@@ -229,13 +231,13 @@
 {
 	__be32 diff[] = { ~from, to };
 	if (skb->ip_summed != CHECKSUM_PARTIAL) {
-		*sum = csum_fold(csum_partial((char *)diff, sizeof(diff),
+		*sum = csum_fold(csum_partial(diff, sizeof(diff),
 				~csum_unfold(*sum)));
 		if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
-			skb->csum = ~csum_partial((char *)diff, sizeof(diff),
+			skb->csum = ~csum_partial(diff, sizeof(diff),
 						~skb->csum);
 	} else if (pseudohdr)
-		*sum = ~csum_fold(csum_partial((char *)diff, sizeof(diff),
+		*sum = ~csum_fold(csum_partial(diff, sizeof(diff),
 				csum_unfold(*sum)));
 }
 EXPORT_SYMBOL(nf_proto_csum_replace4);
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
index 0568f2e86..e42ab23 100644
--- a/net/netfilter/nf_conntrack_amanda.c
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -142,23 +142,22 @@
 		if (port == 0 || len > 5)
 			break;
 
-		exp = nf_conntrack_expect_alloc(ct);
+		exp = nf_ct_expect_alloc(ct);
 		if (exp == NULL) {
 			ret = NF_DROP;
 			goto out;
 		}
 		tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
-		nf_conntrack_expect_init(exp, family,
-					 &tuple->src.u3, &tuple->dst.u3,
-					 IPPROTO_TCP, NULL, &port);
+		nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+				  IPPROTO_TCP, NULL, &port);
 
 		nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
 		if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
 			ret = nf_nat_amanda(pskb, ctinfo, off - dataoff,
 					    len, exp);
-		else if (nf_conntrack_expect_related(exp) != 0)
+		else if (nf_ct_expect_related(exp) != 0)
 			ret = NF_DROP;
-		nf_conntrack_expect_put(exp);
+		nf_ct_expect_put(exp);
 	}
 
 out:
@@ -175,9 +174,6 @@
 		.tuple.src.l3num	= AF_INET,
 		.tuple.src.u.udp.port	= __constant_htons(10080),
 		.tuple.dst.protonum	= IPPROTO_UDP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 	},
 	{
 		.name			= "amanda",
@@ -188,9 +184,6 @@
 		.tuple.src.l3num	= AF_INET6,
 		.tuple.src.u.udp.port	= __constant_htons(10080),
 		.tuple.dst.protonum	= IPPROTO_UDP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 	},
 };
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 7a15e30..3d14110 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -36,15 +36,10 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 
 #define NF_CONNTRACK_VERSION	"0.5.0"
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 DEFINE_RWLOCK(nf_conntrack_lock);
 EXPORT_SYMBOL_GPL(nf_conntrack_lock);
 
@@ -52,57 +47,27 @@
 atomic_t nf_conntrack_count = ATOMIC_INIT(0);
 EXPORT_SYMBOL_GPL(nf_conntrack_count);
 
-void (*nf_conntrack_destroyed)(struct nf_conn *conntrack);
-EXPORT_SYMBOL_GPL(nf_conntrack_destroyed);
-
 unsigned int nf_conntrack_htable_size __read_mostly;
 EXPORT_SYMBOL_GPL(nf_conntrack_htable_size);
 
 int nf_conntrack_max __read_mostly;
 EXPORT_SYMBOL_GPL(nf_conntrack_max);
 
-struct list_head *nf_conntrack_hash __read_mostly;
+struct hlist_head *nf_conntrack_hash __read_mostly;
 EXPORT_SYMBOL_GPL(nf_conntrack_hash);
 
 struct nf_conn nf_conntrack_untracked __read_mostly;
 EXPORT_SYMBOL_GPL(nf_conntrack_untracked);
 
 unsigned int nf_ct_log_invalid __read_mostly;
-LIST_HEAD(unconfirmed);
+HLIST_HEAD(unconfirmed);
 static int nf_conntrack_vmalloc __read_mostly;
-
+static struct kmem_cache *nf_conntrack_cachep __read_mostly;
 static unsigned int nf_conntrack_next_id;
 
 DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
 EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat);
 
-/*
- * This scheme offers various size of "struct nf_conn" dependent on
- * features(helper, nat, ...)
- */
-
-#define NF_CT_FEATURES_NAMELEN	256
-static struct {
-	/* name of slab cache. printed in /proc/slabinfo */
-	char *name;
-
-	/* size of slab cache */
-	size_t size;
-
-	/* slab cache pointer */
-	struct kmem_cache *cachep;
-
-	/* allocated slab cache + modules which uses this slab cache */
-	int use;
-
-} nf_ct_cache[NF_CT_F_NUM];
-
-/* protect members of nf_ct_cache except of "use" */
-DEFINE_RWLOCK(nf_ct_cache_lock);
-
-/* This avoids calling kmem_cache_create() with same name simultaneously */
-static DEFINE_MUTEX(nf_ct_cache_mutex);
-
 static int nf_conntrack_hash_rnd_initted;
 static unsigned int nf_conntrack_hash_rnd;
 
@@ -125,122 +90,6 @@
 				nf_conntrack_hash_rnd);
 }
 
-int nf_conntrack_register_cache(u_int32_t features, const char *name,
-				size_t size)
-{
-	int ret = 0;
-	char *cache_name;
-	struct kmem_cache *cachep;
-
-	DEBUGP("nf_conntrack_register_cache: features=0x%x, name=%s, size=%d\n",
-	       features, name, size);
-
-	if (features < NF_CT_F_BASIC || features >= NF_CT_F_NUM) {
-		DEBUGP("nf_conntrack_register_cache: invalid features.: 0x%x\n",
-			features);
-		return -EINVAL;
-	}
-
-	mutex_lock(&nf_ct_cache_mutex);
-
-	write_lock_bh(&nf_ct_cache_lock);
-	/* e.g: multiple helpers are loaded */
-	if (nf_ct_cache[features].use > 0) {
-		DEBUGP("nf_conntrack_register_cache: already resisterd.\n");
-		if ((!strncmp(nf_ct_cache[features].name, name,
-			      NF_CT_FEATURES_NAMELEN))
-		    && nf_ct_cache[features].size == size) {
-			DEBUGP("nf_conntrack_register_cache: reusing.\n");
-			nf_ct_cache[features].use++;
-			ret = 0;
-		} else
-			ret = -EBUSY;
-
-		write_unlock_bh(&nf_ct_cache_lock);
-		mutex_unlock(&nf_ct_cache_mutex);
-		return ret;
-	}
-	write_unlock_bh(&nf_ct_cache_lock);
-
-	/*
-	 * The memory space for name of slab cache must be alive until
-	 * cache is destroyed.
-	 */
-	cache_name = kmalloc(sizeof(char)*NF_CT_FEATURES_NAMELEN, GFP_ATOMIC);
-	if (cache_name == NULL) {
-		DEBUGP("nf_conntrack_register_cache: can't alloc cache_name\n");
-		ret = -ENOMEM;
-		goto out_up_mutex;
-	}
-
-	if (strlcpy(cache_name, name, NF_CT_FEATURES_NAMELEN)
-						>= NF_CT_FEATURES_NAMELEN) {
-		printk("nf_conntrack_register_cache: name too long\n");
-		ret = -EINVAL;
-		goto out_free_name;
-	}
-
-	cachep = kmem_cache_create(cache_name, size, 0, 0,
-				   NULL, NULL);
-	if (!cachep) {
-		printk("nf_conntrack_register_cache: Can't create slab cache "
-		       "for the features = 0x%x\n", features);
-		ret = -ENOMEM;
-		goto out_free_name;
-	}
-
-	write_lock_bh(&nf_ct_cache_lock);
-	nf_ct_cache[features].use = 1;
-	nf_ct_cache[features].size = size;
-	nf_ct_cache[features].cachep = cachep;
-	nf_ct_cache[features].name = cache_name;
-	write_unlock_bh(&nf_ct_cache_lock);
-
-	goto out_up_mutex;
-
-out_free_name:
-	kfree(cache_name);
-out_up_mutex:
-	mutex_unlock(&nf_ct_cache_mutex);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(nf_conntrack_register_cache);
-
-/* FIXME: In the current, only nf_conntrack_cleanup() can call this function. */
-void nf_conntrack_unregister_cache(u_int32_t features)
-{
-	struct kmem_cache *cachep;
-	char *name;
-
-	/*
-	 * This assures that kmem_cache_create() isn't called before destroying
-	 * slab cache.
-	 */
-	DEBUGP("nf_conntrack_unregister_cache: 0x%04x\n", features);
-	mutex_lock(&nf_ct_cache_mutex);
-
-	write_lock_bh(&nf_ct_cache_lock);
-	if (--nf_ct_cache[features].use > 0) {
-		write_unlock_bh(&nf_ct_cache_lock);
-		mutex_unlock(&nf_ct_cache_mutex);
-		return;
-	}
-	cachep = nf_ct_cache[features].cachep;
-	name = nf_ct_cache[features].name;
-	nf_ct_cache[features].cachep = NULL;
-	nf_ct_cache[features].name = NULL;
-	nf_ct_cache[features].size = 0;
-	write_unlock_bh(&nf_ct_cache_lock);
-
-	synchronize_net();
-
-	kmem_cache_destroy(cachep);
-	kfree(name);
-
-	mutex_unlock(&nf_ct_cache_mutex);
-}
-EXPORT_SYMBOL_GPL(nf_conntrack_unregister_cache);
-
 int
 nf_ct_get_tuple(const struct sk_buff *skb,
 		unsigned int nhoff,
@@ -286,9 +135,9 @@
 static void
 clean_from_lists(struct nf_conn *ct)
 {
-	DEBUGP("clean_from_lists(%p)\n", ct);
-	list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
-	list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
+	pr_debug("clean_from_lists(%p)\n", ct);
+	hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode);
+	hlist_del(&ct->tuplehash[IP_CT_DIR_REPLY].hnode);
 
 	/* Destroy all pending expectations */
 	nf_ct_remove_expectations(ct);
@@ -299,9 +148,8 @@
 {
 	struct nf_conn *ct = (struct nf_conn *)nfct;
 	struct nf_conntrack_l4proto *l4proto;
-	typeof(nf_conntrack_destroyed) destroyed;
 
-	DEBUGP("destroy_conntrack(%p)\n", ct);
+	pr_debug("destroy_conntrack(%p)\n", ct);
 	NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
 	NF_CT_ASSERT(!timer_pending(&ct->timeout));
 
@@ -317,9 +165,7 @@
 	if (l4proto && l4proto->destroy)
 		l4proto->destroy(ct);
 
-	destroyed = rcu_dereference(nf_conntrack_destroyed);
-	if (destroyed)
-		destroyed(ct);
+	nf_ct_ext_destroy(ct);
 
 	rcu_read_unlock();
 
@@ -332,8 +178,8 @@
 
 	/* We overload first tuple to link into unconfirmed list. */
 	if (!nf_ct_is_confirmed(ct)) {
-		BUG_ON(list_empty(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list));
-		list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
+		BUG_ON(hlist_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode));
+		hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode);
 	}
 
 	NF_CT_STAT_INC(delete);
@@ -342,7 +188,7 @@
 	if (ct->master)
 		nf_ct_put(ct->master);
 
-	DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
+	pr_debug("destroy_conntrack: returning ct=%p to slab\n", ct);
 	nf_conntrack_free(ct);
 }
 
@@ -374,9 +220,10 @@
 		    const struct nf_conn *ignored_conntrack)
 {
 	struct nf_conntrack_tuple_hash *h;
+	struct hlist_node *n;
 	unsigned int hash = hash_conntrack(tuple);
 
-	list_for_each_entry(h, &nf_conntrack_hash[hash], list) {
+	hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) {
 		if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack &&
 		    nf_ct_tuple_equal(tuple, &h->tuple)) {
 			NF_CT_STAT_INC(found);
@@ -391,13 +238,12 @@
 
 /* Find a connection corresponding to a tuple. */
 struct nf_conntrack_tuple_hash *
-nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
-		      const struct nf_conn *ignored_conntrack)
+nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_tuple_hash *h;
 
 	read_lock_bh(&nf_conntrack_lock);
-	h = __nf_conntrack_find(tuple, ignored_conntrack);
+	h = __nf_conntrack_find(tuple, NULL);
 	if (h)
 		atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use);
 	read_unlock_bh(&nf_conntrack_lock);
@@ -411,10 +257,10 @@
 				       unsigned int repl_hash)
 {
 	ct->id = ++nf_conntrack_next_id;
-	list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list,
-		 &nf_conntrack_hash[hash]);
-	list_add(&ct->tuplehash[IP_CT_DIR_REPLY].list,
-		 &nf_conntrack_hash[repl_hash]);
+	hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode,
+		       &nf_conntrack_hash[hash]);
+	hlist_add_head(&ct->tuplehash[IP_CT_DIR_REPLY].hnode,
+		       &nf_conntrack_hash[repl_hash]);
 }
 
 void nf_conntrack_hash_insert(struct nf_conn *ct)
@@ -438,6 +284,7 @@
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conn *ct;
 	struct nf_conn_help *help;
+	struct hlist_node *n;
 	enum ip_conntrack_info ctinfo;
 
 	ct = nf_ct_get(*pskb, &ctinfo);
@@ -460,24 +307,24 @@
 	/* No external references means noone else could have
 	   confirmed us. */
 	NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
-	DEBUGP("Confirming conntrack %p\n", ct);
+	pr_debug("Confirming conntrack %p\n", ct);
 
 	write_lock_bh(&nf_conntrack_lock);
 
 	/* See if there's one in the list already, including reverse:
 	   NAT could have grabbed it without realizing, since we're
 	   not in the hash.  If there is, we lost race. */
-	list_for_each_entry(h, &nf_conntrack_hash[hash], list)
+	hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode)
 		if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
 				      &h->tuple))
 			goto out;
-	list_for_each_entry(h, &nf_conntrack_hash[repl_hash], list)
+	hlist_for_each_entry(h, n, &nf_conntrack_hash[repl_hash], hnode)
 		if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
 				      &h->tuple))
 			goto out;
 
 	/* Remove from unconfirmed list */
-	list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
+	hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode);
 
 	__nf_conntrack_hash_insert(ct, hash, repl_hash);
 	/* Timer relative to confirmation time, not original
@@ -524,24 +371,33 @@
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken);
 
+#define NF_CT_EVICTION_RANGE	8
+
 /* There's a small race here where we may free a just-assured
    connection.  Too bad: we're in trouble anyway. */
-static int early_drop(struct list_head *chain)
+static int early_drop(unsigned int hash)
 {
-	/* Traverse backwards: gives us oldest, which is roughly LRU */
+	/* Use oldest entry, which is roughly LRU */
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conn *ct = NULL, *tmp;
+	struct hlist_node *n;
+	unsigned int i, cnt = 0;
 	int dropped = 0;
 
 	read_lock_bh(&nf_conntrack_lock);
-	list_for_each_entry_reverse(h, chain, list) {
-		tmp = nf_ct_tuplehash_to_ctrack(h);
-		if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) {
-			ct = tmp;
-			atomic_inc(&ct->ct_general.use);
-			break;
+	for (i = 0; i < nf_conntrack_htable_size; i++) {
+		hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) {
+			tmp = nf_ct_tuplehash_to_ctrack(h);
+			if (!test_bit(IPS_ASSURED_BIT, &tmp->status))
+				ct = tmp;
+			cnt++;
 		}
+		if (ct || cnt >= NF_CT_EVICTION_RANGE)
+			break;
+		hash = (hash + 1) % nf_conntrack_htable_size;
 	}
+	if (ct)
+		atomic_inc(&ct->ct_general.use);
 	read_unlock_bh(&nf_conntrack_lock);
 
 	if (!ct)
@@ -556,14 +412,10 @@
 	return dropped;
 }
 
-static struct nf_conn *
-__nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
-		     const struct nf_conntrack_tuple *repl,
-		     const struct nf_conntrack_l3proto *l3proto,
-		     u_int32_t features)
+struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
+				   const struct nf_conntrack_tuple *repl)
 {
 	struct nf_conn *conntrack = NULL;
-	struct nf_conntrack_helper *helper;
 
 	if (unlikely(!nf_conntrack_hash_rnd_initted)) {
 		get_random_bytes(&nf_conntrack_hash_rnd, 4);
@@ -576,8 +428,7 @@
 	if (nf_conntrack_max
 	    && atomic_read(&nf_conntrack_count) > nf_conntrack_max) {
 		unsigned int hash = hash_conntrack(orig);
-		/* Try dropping from this hash chain. */
-		if (!early_drop(&nf_conntrack_hash[hash])) {
+		if (!early_drop(hash)) {
 			atomic_dec(&nf_conntrack_count);
 			if (net_ratelimit())
 				printk(KERN_WARNING
@@ -587,72 +438,28 @@
 		}
 	}
 
-	/*  find features needed by this conntrack. */
-	features |= l3proto->get_features(orig);
-
-	/* FIXME: protect helper list per RCU */
-	read_lock_bh(&nf_conntrack_lock);
-	helper = __nf_ct_helper_find(repl);
-	/* NAT might want to assign a helper later */
-	if (helper || features & NF_CT_F_NAT)
-		features |= NF_CT_F_HELP;
-	read_unlock_bh(&nf_conntrack_lock);
-
-	DEBUGP("nf_conntrack_alloc: features=0x%x\n", features);
-
-	read_lock_bh(&nf_ct_cache_lock);
-
-	if (unlikely(!nf_ct_cache[features].use)) {
-		DEBUGP("nf_conntrack_alloc: not supported features = 0x%x\n",
-			features);
-		goto out;
-	}
-
-	conntrack = kmem_cache_alloc(nf_ct_cache[features].cachep, GFP_ATOMIC);
+	conntrack = kmem_cache_zalloc(nf_conntrack_cachep, GFP_ATOMIC);
 	if (conntrack == NULL) {
-		DEBUGP("nf_conntrack_alloc: Can't alloc conntrack from cache\n");
-		goto out;
+		pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n");
+		atomic_dec(&nf_conntrack_count);
+		return ERR_PTR(-ENOMEM);
 	}
 
-	memset(conntrack, 0, nf_ct_cache[features].size);
-	conntrack->features = features;
 	atomic_set(&conntrack->ct_general.use, 1);
 	conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
 	conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *repl;
 	/* Don't set timer yet: wait for confirmation */
 	setup_timer(&conntrack->timeout, death_by_timeout,
 		    (unsigned long)conntrack);
-	read_unlock_bh(&nf_ct_cache_lock);
 
 	return conntrack;
-out:
-	read_unlock_bh(&nf_ct_cache_lock);
-	atomic_dec(&nf_conntrack_count);
-	return conntrack;
-}
-
-struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
-				   const struct nf_conntrack_tuple *repl)
-{
-	struct nf_conntrack_l3proto *l3proto;
-	struct nf_conn *ct;
-
-	rcu_read_lock();
-	l3proto = __nf_ct_l3proto_find(orig->src.l3num);
-	ct = __nf_conntrack_alloc(orig, repl, l3proto, 0);
-	rcu_read_unlock();
-
-	return ct;
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_alloc);
 
 void nf_conntrack_free(struct nf_conn *conntrack)
 {
-	u_int32_t features = conntrack->features;
-	NF_CT_ASSERT(features >= NF_CT_F_BASIC && features < NF_CT_F_NUM);
-	DEBUGP("nf_conntrack_free: features = 0x%x, conntrack=%p\n", features,
-	       conntrack);
-	kmem_cache_free(nf_ct_cache[features].cachep, conntrack);
+	nf_ct_ext_free(conntrack);
+	kmem_cache_free(nf_conntrack_cachep, conntrack);
 	atomic_dec(&nf_conntrack_count);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_free);
@@ -670,43 +477,38 @@
 	struct nf_conn_help *help;
 	struct nf_conntrack_tuple repl_tuple;
 	struct nf_conntrack_expect *exp;
-	u_int32_t features = 0;
 
 	if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) {
-		DEBUGP("Can't invert tuple.\n");
+		pr_debug("Can't invert tuple.\n");
 		return NULL;
 	}
 
-	read_lock_bh(&nf_conntrack_lock);
-	exp = __nf_conntrack_expect_find(tuple);
-	if (exp && exp->helper)
-		features = NF_CT_F_HELP;
-	read_unlock_bh(&nf_conntrack_lock);
-
-	conntrack = __nf_conntrack_alloc(tuple, &repl_tuple, l3proto, features);
+	conntrack = nf_conntrack_alloc(tuple, &repl_tuple);
 	if (conntrack == NULL || IS_ERR(conntrack)) {
-		DEBUGP("Can't allocate conntrack.\n");
+		pr_debug("Can't allocate conntrack.\n");
 		return (struct nf_conntrack_tuple_hash *)conntrack;
 	}
 
 	if (!l4proto->new(conntrack, skb, dataoff)) {
 		nf_conntrack_free(conntrack);
-		DEBUGP("init conntrack: can't track with proto module\n");
+		pr_debug("init conntrack: can't track with proto module\n");
 		return NULL;
 	}
 
 	write_lock_bh(&nf_conntrack_lock);
-	exp = find_expectation(tuple);
-
-	help = nfct_help(conntrack);
+	exp = nf_ct_find_expectation(tuple);
 	if (exp) {
-		DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
-			conntrack, exp);
+		pr_debug("conntrack: expectation arrives ct=%p exp=%p\n",
+			 conntrack, exp);
 		/* Welcome, Mr. Bond.  We've been expecting you... */
 		__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
 		conntrack->master = exp->master;
-		if (exp->helper)
-			rcu_assign_pointer(help->helper, exp->helper);
+		if (exp->helper) {
+			help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC);
+			if (help)
+				rcu_assign_pointer(help->helper, exp->helper);
+		}
+
 #ifdef CONFIG_NF_CONNTRACK_MARK
 		conntrack->mark = exp->master->mark;
 #endif
@@ -716,23 +518,27 @@
 		nf_conntrack_get(&conntrack->master->ct_general);
 		NF_CT_STAT_INC(expect_new);
 	} else {
-		if (help) {
-			/* not in hash table yet, so not strictly necessary */
-			rcu_assign_pointer(help->helper,
-					   __nf_ct_helper_find(&repl_tuple));
+		struct nf_conntrack_helper *helper;
+
+		helper = __nf_ct_helper_find(&repl_tuple);
+		if (helper) {
+			help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC);
+			if (help)
+				rcu_assign_pointer(help->helper, helper);
 		}
 		NF_CT_STAT_INC(new);
 	}
 
 	/* Overload tuple linked list to put us in unconfirmed list. */
-	list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);
+	hlist_add_head(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].hnode,
+		       &unconfirmed);
 
 	write_unlock_bh(&nf_conntrack_lock);
 
 	if (exp) {
 		if (exp->expectfn)
 			exp->expectfn(conntrack, exp);
-		nf_conntrack_expect_put(exp);
+		nf_ct_expect_put(exp);
 	}
 
 	return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
@@ -756,12 +562,12 @@
 	if (!nf_ct_get_tuple(skb, skb_network_offset(skb),
 			     dataoff, l3num, protonum, &tuple, l3proto,
 			     l4proto)) {
-		DEBUGP("resolve_normal_ct: Can't get tuple\n");
+		pr_debug("resolve_normal_ct: Can't get tuple\n");
 		return NULL;
 	}
 
 	/* look for tuple match */
-	h = nf_conntrack_find_get(&tuple, NULL);
+	h = nf_conntrack_find_get(&tuple);
 	if (!h) {
 		h = init_conntrack(&tuple, l3proto, l4proto, skb, dataoff);
 		if (!h)
@@ -779,13 +585,14 @@
 	} else {
 		/* Once we've had two way comms, always ESTABLISHED. */
 		if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
-			DEBUGP("nf_conntrack_in: normal packet for %p\n", ct);
+			pr_debug("nf_conntrack_in: normal packet for %p\n", ct);
 			*ctinfo = IP_CT_ESTABLISHED;
 		} else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
-			DEBUGP("nf_conntrack_in: related packet for %p\n", ct);
+			pr_debug("nf_conntrack_in: related packet for %p\n",
+				 ct);
 			*ctinfo = IP_CT_RELATED;
 		} else {
-			DEBUGP("nf_conntrack_in: new packet for %p\n", ct);
+			pr_debug("nf_conntrack_in: new packet for %p\n", ct);
 			*ctinfo = IP_CT_NEW;
 		}
 		*set_reply = 0;
@@ -817,7 +624,7 @@
 	l3proto = __nf_ct_l3proto_find((u_int16_t)pf);
 
 	if ((ret = l3proto->prepare(pskb, hooknum, &dataoff, &protonum)) <= 0) {
-		DEBUGP("not prepared to track yet or error occured\n");
+		pr_debug("not prepared to track yet or error occured\n");
 		return -ret;
 	}
 
@@ -853,7 +660,7 @@
 	if (ret < 0) {
 		/* Invalid: inverse of the return code tells
 		 * the netfilter core what to do */
-		DEBUGP("nf_conntrack_in: Can't track with proto module\n");
+		pr_debug("nf_conntrack_in: Can't track with proto module\n");
 		nf_conntrack_put((*pskb)->nfct);
 		(*pskb)->nfct = NULL;
 		NF_CT_STAT_INC_ATOMIC(invalid);
@@ -888,23 +695,36 @@
 			      const struct nf_conntrack_tuple *newreply)
 {
 	struct nf_conn_help *help = nfct_help(ct);
+	struct nf_conntrack_helper *helper;
 
 	write_lock_bh(&nf_conntrack_lock);
 	/* Should be unconfirmed, so not in hash table yet */
 	NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
 
-	DEBUGP("Altering reply tuple of %p to ", ct);
+	pr_debug("Altering reply tuple of %p to ", ct);
 	NF_CT_DUMP_TUPLE(newreply);
 
 	ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
-	if (!ct->master && help && help->expecting == 0) {
-		struct nf_conntrack_helper *helper;
-		helper = __nf_ct_helper_find(newreply);
-		if (helper)
-			memset(&help->help, 0, sizeof(help->help));
-		/* not in hash table yet, so not strictly necessary */
-		rcu_assign_pointer(help->helper, helper);
+	if (ct->master || (help && help->expecting != 0))
+		goto out;
+
+	helper = __nf_ct_helper_find(newreply);
+	if (helper == NULL) {
+		if (help)
+			rcu_assign_pointer(help->helper, NULL);
+		goto out;
 	}
+
+	if (help == NULL) {
+		help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
+		if (help == NULL)
+			goto out;
+	} else {
+		memset(&help->help, 0, sizeof(help->help));
+	}
+
+	rcu_assign_pointer(help->helper, helper);
+out:
 	write_unlock_bh(&nf_conntrack_lock);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
@@ -1048,16 +868,17 @@
 {
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conn *ct;
+	struct hlist_node *n;
 
 	write_lock_bh(&nf_conntrack_lock);
 	for (; *bucket < nf_conntrack_htable_size; (*bucket)++) {
-		list_for_each_entry(h, &nf_conntrack_hash[*bucket], list) {
+		hlist_for_each_entry(h, n, &nf_conntrack_hash[*bucket], hnode) {
 			ct = nf_ct_tuplehash_to_ctrack(h);
 			if (iter(ct, data))
 				goto found;
 		}
 	}
-	list_for_each_entry(h, &unconfirmed, list) {
+	hlist_for_each_entry(h, n, &unconfirmed, hnode) {
 		ct = nf_ct_tuplehash_to_ctrack(h);
 		if (iter(ct, data))
 			set_bit(IPS_DYING_BIT, &ct->status);
@@ -1092,14 +913,15 @@
 	return 1;
 }
 
-static void free_conntrack_hash(struct list_head *hash, int vmalloced, int size)
+void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, int size)
 {
 	if (vmalloced)
 		vfree(hash);
 	else
 		free_pages((unsigned long)hash,
-			   get_order(sizeof(struct list_head) * size));
+			   get_order(sizeof(struct hlist_head) * size));
 }
+EXPORT_SYMBOL_GPL(nf_ct_free_hashtable);
 
 void nf_conntrack_flush(void)
 {
@@ -1111,8 +933,6 @@
    supposed to kill the mall. */
 void nf_conntrack_cleanup(void)
 {
-	int i;
-
 	rcu_assign_pointer(ip_ct_attach, NULL);
 
 	/* This makes sure all current packets have passed through
@@ -1133,49 +953,46 @@
 
 	rcu_assign_pointer(nf_ct_destroy, NULL);
 
-	for (i = 0; i < NF_CT_F_NUM; i++) {
-		if (nf_ct_cache[i].use == 0)
-			continue;
-
-		NF_CT_ASSERT(nf_ct_cache[i].use == 1);
-		nf_ct_cache[i].use = 1;
-		nf_conntrack_unregister_cache(i);
-	}
-	kmem_cache_destroy(nf_conntrack_expect_cachep);
-	free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc,
-			    nf_conntrack_htable_size);
+	kmem_cache_destroy(nf_conntrack_cachep);
+	nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc,
+			     nf_conntrack_htable_size);
 
 	nf_conntrack_proto_fini();
+	nf_conntrack_helper_fini();
+	nf_conntrack_expect_fini();
 }
 
-static struct list_head *alloc_hashtable(int size, int *vmalloced)
+struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced)
 {
-	struct list_head *hash;
-	unsigned int i;
+	struct hlist_head *hash;
+	unsigned int size, i;
 
 	*vmalloced = 0;
+
+	size = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_head));
 	hash = (void*)__get_free_pages(GFP_KERNEL,
-				       get_order(sizeof(struct list_head)
+				       get_order(sizeof(struct hlist_head)
 						 * size));
 	if (!hash) {
 		*vmalloced = 1;
 		printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n");
-		hash = vmalloc(sizeof(struct list_head) * size);
+		hash = vmalloc(sizeof(struct hlist_head) * size);
 	}
 
 	if (hash)
 		for (i = 0; i < size; i++)
-			INIT_LIST_HEAD(&hash[i]);
+			INIT_HLIST_HEAD(&hash[i]);
 
 	return hash;
 }
+EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable);
 
 int set_hashsize(const char *val, struct kernel_param *kp)
 {
 	int i, bucket, hashsize, vmalloced;
 	int old_vmalloced, old_size;
 	int rnd;
-	struct list_head *hash, *old_hash;
+	struct hlist_head *hash, *old_hash;
 	struct nf_conntrack_tuple_hash *h;
 
 	/* On boot, we can set this without any fancy locking. */
@@ -1186,7 +1003,7 @@
 	if (!hashsize)
 		return -EINVAL;
 
-	hash = alloc_hashtable(hashsize, &vmalloced);
+	hash = nf_ct_alloc_hashtable(&hashsize, &vmalloced);
 	if (!hash)
 		return -ENOMEM;
 
@@ -1196,12 +1013,12 @@
 
 	write_lock_bh(&nf_conntrack_lock);
 	for (i = 0; i < nf_conntrack_htable_size; i++) {
-		while (!list_empty(&nf_conntrack_hash[i])) {
-			h = list_entry(nf_conntrack_hash[i].next,
-				       struct nf_conntrack_tuple_hash, list);
-			list_del(&h->list);
+		while (!hlist_empty(&nf_conntrack_hash[i])) {
+			h = hlist_entry(nf_conntrack_hash[i].first,
+					struct nf_conntrack_tuple_hash, hnode);
+			hlist_del(&h->hnode);
 			bucket = __hash_conntrack(&h->tuple, hashsize, rnd);
-			list_add_tail(&h->list, &hash[bucket]);
+			hlist_add_head(&h->hnode, &hash[bucket]);
 		}
 	}
 	old_size = nf_conntrack_htable_size;
@@ -1214,7 +1031,7 @@
 	nf_conntrack_hash_rnd = rnd;
 	write_unlock_bh(&nf_conntrack_lock);
 
-	free_conntrack_hash(old_hash, old_vmalloced, old_size);
+	nf_ct_free_hashtable(old_hash, old_vmalloced, old_size);
 	return 0;
 }
 
@@ -1223,50 +1040,58 @@
 
 int __init nf_conntrack_init(void)
 {
+	int max_factor = 8;
 	int ret;
 
 	/* Idea from tcp.c: use 1/16384 of memory.  On i386: 32MB
-	 * machine has 256 buckets.  >= 1GB machines have 8192 buckets. */
+	 * machine has 512 buckets. >= 1GB machines have 16384 buckets. */
 	if (!nf_conntrack_htable_size) {
 		nf_conntrack_htable_size
 			= (((num_physpages << PAGE_SHIFT) / 16384)
-			   / sizeof(struct list_head));
+			   / sizeof(struct hlist_head));
 		if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
-			nf_conntrack_htable_size = 8192;
-		if (nf_conntrack_htable_size < 16)
-			nf_conntrack_htable_size = 16;
+			nf_conntrack_htable_size = 16384;
+		if (nf_conntrack_htable_size < 32)
+			nf_conntrack_htable_size = 32;
+
+		/* Use a max. factor of four by default to get the same max as
+		 * with the old struct list_heads. When a table size is given
+		 * we use the old value of 8 to avoid reducing the max.
+		 * entries. */
+		max_factor = 4;
 	}
-	nf_conntrack_max = 8 * nf_conntrack_htable_size;
-
-	printk("nf_conntrack version %s (%u buckets, %d max)\n",
-	       NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
-	       nf_conntrack_max);
-
-	nf_conntrack_hash = alloc_hashtable(nf_conntrack_htable_size,
-					    &nf_conntrack_vmalloc);
+	nf_conntrack_hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size,
+						  &nf_conntrack_vmalloc);
 	if (!nf_conntrack_hash) {
 		printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
 		goto err_out;
 	}
 
-	ret = nf_conntrack_register_cache(NF_CT_F_BASIC, "nf_conntrack:basic",
-					  sizeof(struct nf_conn));
-	if (ret < 0) {
+	nf_conntrack_max = max_factor * nf_conntrack_htable_size;
+
+	printk("nf_conntrack version %s (%u buckets, %d max)\n",
+	       NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
+	       nf_conntrack_max);
+
+	nf_conntrack_cachep = kmem_cache_create("nf_conntrack",
+						sizeof(struct nf_conn),
+						0, 0, NULL, NULL);
+	if (!nf_conntrack_cachep) {
 		printk(KERN_ERR "Unable to create nf_conn slab cache\n");
 		goto err_free_hash;
 	}
 
-	nf_conntrack_expect_cachep = kmem_cache_create("nf_conntrack_expect",
-					sizeof(struct nf_conntrack_expect),
-					0, 0, NULL, NULL);
-	if (!nf_conntrack_expect_cachep) {
-		printk(KERN_ERR "Unable to create nf_expect slab cache\n");
-		goto err_free_conntrack_slab;
-	}
-
 	ret = nf_conntrack_proto_init();
 	if (ret < 0)
-		goto out_free_expect_slab;
+		goto err_free_conntrack_slab;
+
+	ret = nf_conntrack_expect_init();
+	if (ret < 0)
+		goto out_fini_proto;
+
+	ret = nf_conntrack_helper_init();
+	if (ret < 0)
+		goto out_fini_expect;
 
 	/* For use by REJECT target */
 	rcu_assign_pointer(ip_ct_attach, __nf_conntrack_attach);
@@ -1280,13 +1105,15 @@
 
 	return ret;
 
-out_free_expect_slab:
-	kmem_cache_destroy(nf_conntrack_expect_cachep);
+out_fini_expect:
+	nf_conntrack_expect_fini();
+out_fini_proto:
+	nf_conntrack_proto_fini();
 err_free_conntrack_slab:
-	nf_conntrack_unregister_cache(NF_CT_F_BASIC);
+	kmem_cache_destroy(nf_conntrack_cachep);
 err_free_hash:
-	free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc,
-			    nf_conntrack_htable_size);
+	nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc,
+			     nf_conntrack_htable_size);
 err_out:
 	return -ENOMEM;
 }
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index 6bd421d..83c41ac 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -26,8 +26,8 @@
 ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
 EXPORT_SYMBOL_GPL(nf_conntrack_chain);
 
-ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_chain);
+ATOMIC_NOTIFIER_HEAD(nf_ct_expect_chain);
+EXPORT_SYMBOL_GPL(nf_ct_expect_chain);
 
 DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
 EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache);
@@ -103,14 +103,14 @@
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
 
-int nf_conntrack_expect_register_notifier(struct notifier_block *nb)
+int nf_ct_expect_register_notifier(struct notifier_block *nb)
 {
-	return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb);
+	return atomic_notifier_chain_register(&nf_ct_expect_chain, nb);
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_register_notifier);
+EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier);
 
-int nf_conntrack_expect_unregister_notifier(struct notifier_block *nb)
+int nf_ct_expect_unregister_notifier(struct notifier_block *nb)
 {
-	return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain, nb);
+	return atomic_notifier_chain_unregister(&nf_ct_expect_chain, nb);
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_unregister_notifier);
+EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 504fb6c..2191fe0 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -19,6 +19,7 @@
 #include <linux/err.h>
 #include <linux/percpu.h>
 #include <linux/kernel.h>
+#include <linux/jhash.h>
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_core.h>
@@ -26,11 +27,20 @@
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_tuple.h>
 
-LIST_HEAD(nf_conntrack_expect_list);
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_list);
+struct hlist_head *nf_ct_expect_hash __read_mostly;
+EXPORT_SYMBOL_GPL(nf_ct_expect_hash);
 
-struct kmem_cache *nf_conntrack_expect_cachep __read_mostly;
-static unsigned int nf_conntrack_expect_next_id;
+unsigned int nf_ct_expect_hsize __read_mostly;
+EXPORT_SYMBOL_GPL(nf_ct_expect_hsize);
+
+static unsigned int nf_ct_expect_hash_rnd __read_mostly;
+static unsigned int nf_ct_expect_count;
+unsigned int nf_ct_expect_max __read_mostly;
+static int nf_ct_expect_hash_rnd_initted __read_mostly;
+static int nf_ct_expect_vmalloc;
+
+static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
+static unsigned int nf_ct_expect_next_id;
 
 /* nf_conntrack_expect helper functions */
 void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
@@ -40,60 +50,83 @@
 	NF_CT_ASSERT(master_help);
 	NF_CT_ASSERT(!timer_pending(&exp->timeout));
 
-	list_del(&exp->list);
-	NF_CT_STAT_INC(expect_delete);
+	hlist_del(&exp->hnode);
+	nf_ct_expect_count--;
+
+	hlist_del(&exp->lnode);
 	master_help->expecting--;
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
+
+	NF_CT_STAT_INC(expect_delete);
 }
 EXPORT_SYMBOL_GPL(nf_ct_unlink_expect);
 
-static void expectation_timed_out(unsigned long ul_expect)
+static void nf_ct_expectation_timed_out(unsigned long ul_expect)
 {
 	struct nf_conntrack_expect *exp = (void *)ul_expect;
 
 	write_lock_bh(&nf_conntrack_lock);
 	nf_ct_unlink_expect(exp);
 	write_unlock_bh(&nf_conntrack_lock);
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
+}
+
+static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple)
+{
+	if (unlikely(!nf_ct_expect_hash_rnd_initted)) {
+		get_random_bytes(&nf_ct_expect_hash_rnd, 4);
+		nf_ct_expect_hash_rnd_initted = 1;
+	}
+
+	return jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all),
+		      (((tuple->dst.protonum ^ tuple->src.l3num) << 16) |
+		       tuple->dst.u.all) ^ nf_ct_expect_hash_rnd) %
+	       nf_ct_expect_hsize;
 }
 
 struct nf_conntrack_expect *
-__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
+__nf_ct_expect_find(const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_expect *i;
+	struct hlist_node *n;
+	unsigned int h;
 
-	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+	if (!nf_ct_expect_count)
+		return NULL;
+
+	h = nf_ct_expect_dst_hash(tuple);
+	hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
 		if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
 			return i;
 	}
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(__nf_conntrack_expect_find);
+EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
 
 /* Just find a expectation corresponding to a tuple. */
 struct nf_conntrack_expect *
-nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple)
+nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_expect *i;
 
 	read_lock_bh(&nf_conntrack_lock);
-	i = __nf_conntrack_expect_find(tuple);
+	i = __nf_ct_expect_find(tuple);
 	if (i)
 		atomic_inc(&i->use);
 	read_unlock_bh(&nf_conntrack_lock);
 
 	return i;
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get);
+EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
 
 /* If an expectation for this connection is found, it gets delete from
  * global list then returned. */
 struct nf_conntrack_expect *
-find_expectation(const struct nf_conntrack_tuple *tuple)
+nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_expect *exp;
 
-	exp = __nf_conntrack_expect_find(tuple);
+	exp = __nf_ct_expect_find(tuple);
 	if (!exp)
 		return NULL;
 
@@ -119,17 +152,18 @@
 /* delete all expectations for this conntrack */
 void nf_ct_remove_expectations(struct nf_conn *ct)
 {
-	struct nf_conntrack_expect *i, *tmp;
 	struct nf_conn_help *help = nfct_help(ct);
+	struct nf_conntrack_expect *exp;
+	struct hlist_node *n, *next;
 
 	/* Optimization: most connection never expect any others. */
 	if (!help || help->expecting == 0)
 		return;
 
-	list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) {
-		if (i->master == ct && del_timer(&i->timeout)) {
-			nf_ct_unlink_expect(i);
-			nf_conntrack_expect_put(i);
+	hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
+		if (del_timer(&exp->timeout)) {
+			nf_ct_unlink_expect(exp);
+			nf_ct_expect_put(exp);
 		}
 	}
 }
@@ -141,25 +175,16 @@
 {
 	/* Part covered by intersection of masks must be unequal,
 	   otherwise they clash */
-	struct nf_conntrack_tuple intersect_mask;
+	struct nf_conntrack_tuple_mask intersect_mask;
 	int count;
 
-	intersect_mask.src.l3num = a->mask.src.l3num & b->mask.src.l3num;
 	intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all;
-	intersect_mask.dst.u.all = a->mask.dst.u.all & b->mask.dst.u.all;
-	intersect_mask.dst.protonum = a->mask.dst.protonum
-					& b->mask.dst.protonum;
 
 	for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
 		intersect_mask.src.u3.all[count] =
 			a->mask.src.u3.all[count] & b->mask.src.u3.all[count];
 	}
 
-	for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
-		intersect_mask.dst.u3.all[count] =
-			a->mask.dst.u3.all[count] & b->mask.dst.u3.all[count];
-	}
-
 	return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask);
 }
 
@@ -168,36 +193,29 @@
 {
 	return a->master == b->master
 		&& nf_ct_tuple_equal(&a->tuple, &b->tuple)
-		&& nf_ct_tuple_equal(&a->mask, &b->mask);
+		&& nf_ct_tuple_mask_equal(&a->mask, &b->mask);
 }
 
 /* Generally a bad idea to call this: could have matched already. */
-void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp)
+void nf_ct_unexpect_related(struct nf_conntrack_expect *exp)
 {
-	struct nf_conntrack_expect *i;
-
 	write_lock_bh(&nf_conntrack_lock);
-	/* choose the oldest expectation to evict */
-	list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
-		if (expect_matches(i, exp) && del_timer(&i->timeout)) {
-			nf_ct_unlink_expect(i);
-			write_unlock_bh(&nf_conntrack_lock);
-			nf_conntrack_expect_put(i);
-			return;
-		}
+	if (del_timer(&exp->timeout)) {
+		nf_ct_unlink_expect(exp);
+		nf_ct_expect_put(exp);
 	}
 	write_unlock_bh(&nf_conntrack_lock);
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_unexpect_related);
+EXPORT_SYMBOL_GPL(nf_ct_unexpect_related);
 
 /* We don't increase the master conntrack refcount for non-fulfilled
  * conntracks. During the conntrack destruction, the expectations are
  * always killed before the conntrack itself */
-struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me)
+struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
 {
 	struct nf_conntrack_expect *new;
 
-	new = kmem_cache_alloc(nf_conntrack_expect_cachep, GFP_ATOMIC);
+	new = kmem_cache_alloc(nf_ct_expect_cachep, GFP_ATOMIC);
 	if (!new)
 		return NULL;
 
@@ -205,12 +223,12 @@
 	atomic_set(&new->use, 1);
 	return new;
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_alloc);
+EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
 
-void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family,
-			      union nf_conntrack_address *saddr,
-			      union nf_conntrack_address *daddr,
-			      u_int8_t proto, __be16 *src, __be16 *dst)
+void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family,
+		       union nf_conntrack_address *saddr,
+		       union nf_conntrack_address *daddr,
+		       u_int8_t proto, __be16 *src, __be16 *dst)
 {
 	int len;
 
@@ -224,8 +242,6 @@
 	exp->helper = NULL;
 	exp->tuple.src.l3num = family;
 	exp->tuple.dst.protonum = proto;
-	exp->mask.src.l3num = 0xFFFF;
-	exp->mask.dst.protonum = 0xFF;
 
 	if (saddr) {
 		memcpy(&exp->tuple.src.u3, saddr, len);
@@ -242,21 +258,6 @@
 		memset(&exp->mask.src.u3, 0x00, sizeof(exp->mask.src.u3));
 	}
 
-	if (daddr) {
-		memcpy(&exp->tuple.dst.u3, daddr, len);
-		if (sizeof(exp->tuple.dst.u3) > len)
-			/* address needs to be cleared for nf_ct_tuple_equal */
-			memset((void *)&exp->tuple.dst.u3 + len, 0x00,
-			       sizeof(exp->tuple.dst.u3) - len);
-		memset(&exp->mask.dst.u3, 0xFF, len);
-		if (sizeof(exp->mask.dst.u3) > len)
-			memset((void *)&exp->mask.dst.u3 + len, 0x00,
-			       sizeof(exp->mask.dst.u3) - len);
-	} else {
-		memset(&exp->tuple.dst.u3, 0x00, sizeof(exp->tuple.dst.u3));
-		memset(&exp->mask.dst.u3, 0x00, sizeof(exp->mask.dst.u3));
-	}
-
 	if (src) {
 		exp->tuple.src.u.all = (__force u16)*src;
 		exp->mask.src.u.all = 0xFFFF;
@@ -265,36 +266,42 @@
 		exp->mask.src.u.all = 0;
 	}
 
-	if (dst) {
-		exp->tuple.dst.u.all = (__force u16)*dst;
-		exp->mask.dst.u.all = 0xFFFF;
-	} else {
-		exp->tuple.dst.u.all = 0;
-		exp->mask.dst.u.all = 0;
-	}
-}
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_init);
+	memcpy(&exp->tuple.dst.u3, daddr, len);
+	if (sizeof(exp->tuple.dst.u3) > len)
+		/* address needs to be cleared for nf_ct_tuple_equal */
+		memset((void *)&exp->tuple.dst.u3 + len, 0x00,
+		       sizeof(exp->tuple.dst.u3) - len);
 
-void nf_conntrack_expect_put(struct nf_conntrack_expect *exp)
+	exp->tuple.dst.u.all = (__force u16)*dst;
+}
+EXPORT_SYMBOL_GPL(nf_ct_expect_init);
+
+void nf_ct_expect_put(struct nf_conntrack_expect *exp)
 {
 	if (atomic_dec_and_test(&exp->use))
-		kmem_cache_free(nf_conntrack_expect_cachep, exp);
+		kmem_cache_free(nf_ct_expect_cachep, exp);
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_put);
+EXPORT_SYMBOL_GPL(nf_ct_expect_put);
 
-static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
+static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
 {
 	struct nf_conn_help *master_help = nfct_help(exp->master);
+	unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
 
 	atomic_inc(&exp->use);
-	master_help->expecting++;
-	list_add(&exp->list, &nf_conntrack_expect_list);
 
-	setup_timer(&exp->timeout, expectation_timed_out, (unsigned long)exp);
+	hlist_add_head(&exp->lnode, &master_help->expectations);
+	master_help->expecting++;
+
+	hlist_add_head(&exp->hnode, &nf_ct_expect_hash[h]);
+	nf_ct_expect_count++;
+
+	setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
+		    (unsigned long)exp);
 	exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
 	add_timer(&exp->timeout);
 
-	exp->id = ++nf_conntrack_expect_next_id;
+	exp->id = ++nf_ct_expect_next_id;
 	atomic_inc(&exp->use);
 	NF_CT_STAT_INC(expect_create);
 }
@@ -302,16 +309,16 @@
 /* Race with expectations being used means we could have none to find; OK. */
 static void evict_oldest_expect(struct nf_conn *master)
 {
-	struct nf_conntrack_expect *i;
+	struct nf_conn_help *master_help = nfct_help(master);
+	struct nf_conntrack_expect *exp = NULL;
+	struct hlist_node *n;
 
-	list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
-		if (i->master == master) {
-			if (del_timer(&i->timeout)) {
-				nf_ct_unlink_expect(i);
-				nf_conntrack_expect_put(i);
-			}
-			break;
-		}
+	hlist_for_each_entry(exp, n, &master_help->expectations, lnode)
+		; /* nothing */
+
+	if (exp && del_timer(&exp->timeout)) {
+		nf_ct_unlink_expect(exp);
+		nf_ct_expect_put(exp);
 	}
 }
 
@@ -327,11 +334,13 @@
 	return 1;
 }
 
-int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
+int nf_ct_expect_related(struct nf_conntrack_expect *expect)
 {
 	struct nf_conntrack_expect *i;
 	struct nf_conn *master = expect->master;
 	struct nf_conn_help *master_help = nfct_help(master);
+	struct hlist_node *n;
+	unsigned int h;
 	int ret;
 
 	NF_CT_ASSERT(master_help);
@@ -341,7 +350,8 @@
 		ret = -ESHUTDOWN;
 		goto out;
 	}
-	list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+	h = nf_ct_expect_dst_hash(&expect->tuple);
+	hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
 		if (expect_matches(i, expect)) {
 			/* Refresh timer: if it's dying, ignore.. */
 			if (refresh_timer(i)) {
@@ -358,57 +368,86 @@
 	    master_help->expecting >= master_help->helper->max_expected)
 		evict_oldest_expect(master);
 
-	nf_conntrack_expect_insert(expect);
-	nf_conntrack_expect_event(IPEXP_NEW, expect);
+	if (nf_ct_expect_count >= nf_ct_expect_max) {
+		if (net_ratelimit())
+			printk(KERN_WARNING
+			       "nf_conntrack: expectation table full");
+		ret = -EMFILE;
+		goto out;
+	}
+
+	nf_ct_expect_insert(expect);
+	nf_ct_expect_event(IPEXP_NEW, expect);
 	ret = 0;
 out:
 	write_unlock_bh(&nf_conntrack_lock);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_related);
+EXPORT_SYMBOL_GPL(nf_ct_expect_related);
 
 #ifdef CONFIG_PROC_FS
-static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+struct ct_expect_iter_state {
+	unsigned int bucket;
+};
+
+static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
 {
-	struct list_head *e = &nf_conntrack_expect_list;
-	loff_t i;
+	struct ct_expect_iter_state *st = seq->private;
 
-	/* strange seq_file api calls stop even if we fail,
-	 * thus we need to grab lock since stop unlocks */
-	read_lock_bh(&nf_conntrack_lock);
-
-	if (list_empty(e))
-		return NULL;
-
-	for (i = 0; i <= *pos; i++) {
-		e = e->next;
-		if (e == &nf_conntrack_expect_list)
-			return NULL;
+	for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
+		if (!hlist_empty(&nf_ct_expect_hash[st->bucket]))
+			return nf_ct_expect_hash[st->bucket].first;
 	}
-	return e;
+	return NULL;
 }
 
-static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
+					     struct hlist_node *head)
 {
-	struct list_head *e = v;
+	struct ct_expect_iter_state *st = seq->private;
 
-	++*pos;
-	e = e->next;
-
-	if (e == &nf_conntrack_expect_list)
-		return NULL;
-
-	return e;
+	head = head->next;
+	while (head == NULL) {
+		if (++st->bucket >= nf_ct_expect_hsize)
+			return NULL;
+		head = nf_ct_expect_hash[st->bucket].first;
+	}
+	return head;
 }
 
-static void exp_seq_stop(struct seq_file *s, void *v)
+static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct hlist_node *head = ct_expect_get_first(seq);
+
+	if (head)
+		while (pos && (head = ct_expect_get_next(seq, head)))
+			pos--;
+	return pos ? NULL : head;
+}
+
+static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	read_lock_bh(&nf_conntrack_lock);
+	return ct_expect_get_idx(seq, *pos);
+}
+
+static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return ct_expect_get_next(seq, v);
+}
+
+static void exp_seq_stop(struct seq_file *seq, void *v)
 {
 	read_unlock_bh(&nf_conntrack_lock);
 }
 
 static int exp_seq_show(struct seq_file *s, void *v)
 {
-	struct nf_conntrack_expect *expect = v;
+	struct nf_conntrack_expect *expect;
+	struct hlist_node *n = v;
+
+	expect = hlist_entry(n, struct nf_conntrack_expect, hnode);
 
 	if (expect->timeout.function)
 		seq_printf(s, "%ld ", timer_pending(&expect->timeout)
@@ -425,7 +464,7 @@
 	return seq_putc(s, '\n');
 }
 
-static struct seq_operations exp_seq_ops = {
+static const struct seq_operations exp_seq_ops = {
 	.start = exp_seq_start,
 	.next = exp_seq_next,
 	.stop = exp_seq_stop,
@@ -434,14 +473,96 @@
 
 static int exp_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &exp_seq_ops);
+	struct seq_file *seq;
+	struct ct_expect_iter_state *st;
+	int ret;
+
+	st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL);
+	if (st == NULL)
+		return -ENOMEM;
+	ret = seq_open(file, &exp_seq_ops);
+	if (ret)
+		goto out_free;
+	seq          = file->private_data;
+	seq->private = st;
+	memset(st, 0, sizeof(struct ct_expect_iter_state));
+	return ret;
+out_free:
+	kfree(st);
+	return ret;
 }
 
-const struct file_operations exp_file_ops = {
+static const struct file_operations exp_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = exp_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = seq_release
+	.release = seq_release_private,
 };
 #endif /* CONFIG_PROC_FS */
+
+static int __init exp_proc_init(void)
+{
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *proc;
+
+	proc = proc_net_fops_create("nf_conntrack_expect", 0440, &exp_file_ops);
+	if (!proc)
+		return -ENOMEM;
+#endif /* CONFIG_PROC_FS */
+	return 0;
+}
+
+static void exp_proc_remove(void)
+{
+#ifdef CONFIG_PROC_FS
+	proc_net_remove("nf_conntrack_expect");
+#endif /* CONFIG_PROC_FS */
+}
+
+module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600);
+
+int __init nf_conntrack_expect_init(void)
+{
+	int err = -ENOMEM;
+
+	if (!nf_ct_expect_hsize) {
+		nf_ct_expect_hsize = nf_conntrack_htable_size / 256;
+		if (!nf_ct_expect_hsize)
+			nf_ct_expect_hsize = 1;
+	}
+	nf_ct_expect_max = nf_ct_expect_hsize * 4;
+
+	nf_ct_expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize,
+						  &nf_ct_expect_vmalloc);
+	if (nf_ct_expect_hash == NULL)
+		goto err1;
+
+	nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
+					sizeof(struct nf_conntrack_expect),
+					0, 0, NULL, NULL);
+	if (!nf_ct_expect_cachep)
+		goto err2;
+
+	err = exp_proc_init();
+	if (err < 0)
+		goto err3;
+
+	return 0;
+
+err3:
+	nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc,
+			     nf_ct_expect_hsize);
+err2:
+	kmem_cache_destroy(nf_ct_expect_cachep);
+err1:
+	return err;
+}
+
+void nf_conntrack_expect_fini(void)
+{
+	exp_proc_remove();
+	kmem_cache_destroy(nf_ct_expect_cachep);
+	nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc,
+			     nf_ct_expect_hsize);
+}
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
new file mode 100644
index 0000000..a1a65a1
--- /dev/null
+++ b/net/netfilter/nf_conntrack_extend.c
@@ -0,0 +1,195 @@
+/* Structure dynamic extension infrastructure
+ * Copyright (C) 2004 Rusty Russell IBM Corporation
+ * Copyright (C) 2007 Netfilter Core Team <coreteam@netfilter.org>
+ * Copyright (C) 2007 USAGI/WIDE Project <http://www.linux-ipv6.org>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/rcupdate.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+static struct nf_ct_ext_type *nf_ct_ext_types[NF_CT_EXT_NUM];
+static DEFINE_MUTEX(nf_ct_ext_type_mutex);
+
+/* Horrible trick to figure out smallest amount worth kmallocing. */
+#define CACHE(x) (x) + 0 *
+enum {
+	NF_CT_EXT_MIN_SIZE =
+#include <linux/kmalloc_sizes.h>
+	1 };
+#undef CACHE
+
+void __nf_ct_ext_destroy(struct nf_conn *ct)
+{
+	unsigned int i;
+	struct nf_ct_ext_type *t;
+
+	for (i = 0; i < NF_CT_EXT_NUM; i++) {
+		if (!nf_ct_ext_exist(ct, i))
+			continue;
+
+		rcu_read_lock();
+		t = rcu_dereference(nf_ct_ext_types[i]);
+
+		/* Here the nf_ct_ext_type might have been unregisterd.
+		 * I.e., it has responsible to cleanup private
+		 * area in all conntracks when it is unregisterd.
+		 */
+		if (t && t->destroy)
+			t->destroy(ct);
+		rcu_read_unlock();
+	}
+}
+EXPORT_SYMBOL(__nf_ct_ext_destroy);
+
+static void *
+nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)
+{
+	unsigned int off, len, real_len;
+	struct nf_ct_ext_type *t;
+
+	rcu_read_lock();
+	t = rcu_dereference(nf_ct_ext_types[id]);
+	BUG_ON(t == NULL);
+	off = ALIGN(sizeof(struct nf_ct_ext), t->align);
+	len = off + t->len;
+	real_len = t->alloc_size;
+	rcu_read_unlock();
+
+	*ext = kzalloc(real_len, gfp);
+	if (!*ext)
+		return NULL;
+
+	(*ext)->offset[id] = off;
+	(*ext)->len = len;
+	(*ext)->real_len = real_len;
+
+	return (void *)(*ext) + off;
+}
+
+void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
+{
+	struct nf_ct_ext *new;
+	int i, newlen, newoff;
+	struct nf_ct_ext_type *t;
+
+	if (!ct->ext)
+		return nf_ct_ext_create(&ct->ext, id, gfp);
+
+	if (nf_ct_ext_exist(ct, id))
+		return NULL;
+
+	rcu_read_lock();
+	t = rcu_dereference(nf_ct_ext_types[id]);
+	BUG_ON(t == NULL);
+
+	newoff = ALIGN(ct->ext->len, t->align);
+	newlen = newoff + t->len;
+	rcu_read_unlock();
+
+	if (newlen >= ct->ext->real_len) {
+		new = kmalloc(newlen, gfp);
+		if (!new)
+			return NULL;
+
+		memcpy(new, ct->ext, ct->ext->len);
+
+		for (i = 0; i < NF_CT_EXT_NUM; i++) {
+			if (!nf_ct_ext_exist(ct, i))
+				continue;
+
+			rcu_read_lock();
+			t = rcu_dereference(nf_ct_ext_types[i]);
+			if (t && t->move)
+				t->move(ct, ct->ext + ct->ext->offset[id]);
+			rcu_read_unlock();
+		}
+		kfree(ct->ext);
+		new->real_len = newlen;
+		ct->ext = new;
+	}
+
+	ct->ext->offset[id] = newoff;
+	ct->ext->len = newlen;
+	memset((void *)ct->ext + newoff, 0, newlen - newoff);
+	return (void *)ct->ext + newoff;
+}
+EXPORT_SYMBOL(__nf_ct_ext_add);
+
+static void update_alloc_size(struct nf_ct_ext_type *type)
+{
+	int i, j;
+	struct nf_ct_ext_type *t1, *t2;
+	enum nf_ct_ext_id min = 0, max = NF_CT_EXT_NUM - 1;
+
+	/* unnecessary to update all types */
+	if ((type->flags & NF_CT_EXT_F_PREALLOC) == 0) {
+		min = type->id;
+		max = type->id;
+	}
+
+	/* This assumes that extended areas in conntrack for the types
+	   whose NF_CT_EXT_F_PREALLOC bit set are allocated in order */
+	for (i = min; i <= max; i++) {
+		t1 = nf_ct_ext_types[i];
+		if (!t1)
+			continue;
+
+		t1->alloc_size = sizeof(struct nf_ct_ext)
+				 + ALIGN(sizeof(struct nf_ct_ext), t1->align)
+				 + t1->len;
+		for (j = 0; j < NF_CT_EXT_NUM; j++) {
+			t2 = nf_ct_ext_types[j];
+			if (t2 == NULL || t2 == t1 ||
+			    (t2->flags & NF_CT_EXT_F_PREALLOC) == 0)
+				continue;
+
+			t1->alloc_size = ALIGN(t1->alloc_size, t2->align)
+					 + t2->len;
+		}
+		if (t1->alloc_size < NF_CT_EXT_MIN_SIZE)
+			t1->alloc_size = NF_CT_EXT_MIN_SIZE;
+	}
+}
+
+/* This MUST be called in process context. */
+int nf_ct_extend_register(struct nf_ct_ext_type *type)
+{
+	int ret = 0;
+
+	mutex_lock(&nf_ct_ext_type_mutex);
+	if (nf_ct_ext_types[type->id]) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* This ensures that nf_ct_ext_create() can allocate enough area
+	   before updating alloc_size */
+	type->alloc_size = ALIGN(sizeof(struct nf_ct_ext), type->align)
+			   + type->len;
+	rcu_assign_pointer(nf_ct_ext_types[type->id], type);
+	update_alloc_size(type);
+out:
+	mutex_unlock(&nf_ct_ext_type_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(nf_ct_extend_register);
+
+/* This MUST be called in process context. */
+void nf_ct_extend_unregister(struct nf_ct_ext_type *type)
+{
+	mutex_lock(&nf_ct_ext_type_mutex);
+	rcu_assign_pointer(nf_ct_ext_types[type->id], NULL);
+	update_alloc_size(type);
+	mutex_unlock(&nf_ct_ext_type_mutex);
+	synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(nf_ct_extend_unregister);
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 82db2aa..c763ee7 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -51,12 +51,6 @@
 				struct nf_conntrack_expect *exp);
 EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char);
 static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char);
 static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
@@ -138,13 +132,13 @@
 			if (*data == term && i == array_size - 1)
 				return len;
 
-			DEBUGP("Char %u (got %u nums) `%u' unexpected\n",
-			       len, i, *data);
+			pr_debug("Char %u (got %u nums) `%u' unexpected\n",
+				 len, i, *data);
 			return 0;
 		}
 	}
-	DEBUGP("Failed to fill %u numbers separated by %c\n", array_size, sep);
-
+	pr_debug("Failed to fill %u numbers separated by %c\n",
+		 array_size, sep);
 	return 0;
 }
 
@@ -178,13 +172,13 @@
 			if (tmp_port == 0)
 				break;
 			*port = htons(tmp_port);
-			DEBUGP("get_port: return %d\n", tmp_port);
+			pr_debug("get_port: return %d\n", tmp_port);
 			return i + 1;
 		}
 		else if (data[i] >= '0' && data[i] <= '9')
 			tmp_port = tmp_port*10 + data[i] - '0';
 		else { /* Some other crap */
-			DEBUGP("get_port: invalid char.\n");
+			pr_debug("get_port: invalid char.\n");
 			break;
 		}
 	}
@@ -201,22 +195,22 @@
 	/* First character is delimiter, then "1" for IPv4 or "2" for IPv6,
 	   then delimiter again. */
 	if (dlen <= 3) {
-		DEBUGP("EPRT: too short\n");
+		pr_debug("EPRT: too short\n");
 		return 0;
 	}
 	delim = data[0];
 	if (isdigit(delim) || delim < 33 || delim > 126 || data[2] != delim) {
-		DEBUGP("try_eprt: invalid delimitter.\n");
+		pr_debug("try_eprt: invalid delimitter.\n");
 		return 0;
 	}
 
 	if ((cmd->l3num == PF_INET && data[1] != '1') ||
 	    (cmd->l3num == PF_INET6 && data[1] != '2')) {
-		DEBUGP("EPRT: invalid protocol number.\n");
+		pr_debug("EPRT: invalid protocol number.\n");
 		return 0;
 	}
 
-	DEBUGP("EPRT: Got %c%c%c\n", delim, data[1], delim);
+	pr_debug("EPRT: Got %c%c%c\n", delim, data[1], delim);
 
 	if (data[1] == '1') {
 		u_int32_t array[4];
@@ -234,7 +228,7 @@
 
 	if (length == 0)
 		return 0;
-	DEBUGP("EPRT: Got IP address!\n");
+	pr_debug("EPRT: Got IP address!\n");
 	/* Start offset includes initial "|1|", and trailing delimiter */
 	return get_port(data, 3 + length + 1, dlen, delim, &cmd->u.tcp.port);
 }
@@ -267,7 +261,7 @@
 {
 	size_t i;
 
-	DEBUGP("find_pattern `%s': dlen = %u\n", pattern, dlen);
+	pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen);
 	if (dlen == 0)
 		return 0;
 
@@ -282,17 +276,17 @@
 #if 0
 		size_t i;
 
-		DEBUGP("ftp: string mismatch\n");
+		pr_debug("ftp: string mismatch\n");
 		for (i = 0; i < plen; i++) {
-			DEBUGP("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
-				i, data[i], data[i],
-				pattern[i], pattern[i]);
+			pr_debug("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
+				 i, data[i], data[i],
+				 pattern[i], pattern[i]);
 		}
 #endif
 		return 0;
 	}
 
-	DEBUGP("Pattern matches!\n");
+	pr_debug("Pattern matches!\n");
 	/* Now we've found the constant string, try to skip
 	   to the 'skip' character */
 	for (i = plen; data[i] != skip; i++)
@@ -301,14 +295,14 @@
 	/* Skip over the last character */
 	i++;
 
-	DEBUGP("Skipped up to `%c'!\n", skip);
+	pr_debug("Skipped up to `%c'!\n", skip);
 
 	*numoff = i;
 	*numlen = getnum(data + i, dlen - i, cmd, term);
 	if (!*numlen)
 		return -1;
 
-	DEBUGP("Match succeeded!\n");
+	pr_debug("Match succeeded!\n");
 	return 1;
 }
 
@@ -364,6 +358,7 @@
 	unsigned int matchlen, matchoff;
 	struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info;
 	struct nf_conntrack_expect *exp;
+	union nf_conntrack_address *daddr;
 	struct nf_conntrack_man cmd = {};
 	unsigned int i;
 	int found = 0, ends_in_nl;
@@ -372,7 +367,7 @@
 	/* Until there's been traffic both ways, don't look in packets. */
 	if (ctinfo != IP_CT_ESTABLISHED
 	    && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
-		DEBUGP("ftp: Conntrackinfo = %u\n", ctinfo);
+		pr_debug("ftp: Conntrackinfo = %u\n", ctinfo);
 		return NF_ACCEPT;
 	}
 
@@ -383,8 +378,8 @@
 	dataoff = protoff + th->doff * 4;
 	/* No data? */
 	if (dataoff >= (*pskb)->len) {
-		DEBUGP("ftp: dataoff(%u) >= skblen(%u)\n", dataoff,
-			(*pskb)->len);
+		pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff,
+			 (*pskb)->len);
 		return NF_ACCEPT;
 	}
 	datalen = (*pskb)->len - dataoff;
@@ -399,11 +394,11 @@
 	/* Look up to see if we're just after a \n. */
 	if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) {
 		/* Now if this ends in \n, update ftp info. */
-		DEBUGP("nf_conntrack_ftp_help: wrong seq pos %s(%u) or %s(%u)\n",
-		       ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)",
-		       ct_ftp_info->seq_aft_nl[dir][0],
-		       ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)",
-		       ct_ftp_info->seq_aft_nl[dir][1]);
+		pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n",
+			 ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)",
+			 ct_ftp_info->seq_aft_nl[dir][0],
+			 ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)",
+			 ct_ftp_info->seq_aft_nl[dir][1]);
 		ret = NF_ACCEPT;
 		goto out_update_nl;
 	}
@@ -441,11 +436,11 @@
 		goto out_update_nl;
 	}
 
-	DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
-	       (int)matchlen, fb_ptr + matchoff,
-	       matchlen, ntohl(th->seq) + matchoff);
+	pr_debug("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
+		 matchlen, fb_ptr + matchoff,
+		 matchlen, ntohl(th->seq) + matchoff);
 
-	exp = nf_conntrack_expect_alloc(ct);
+	exp = nf_ct_expect_alloc(ct);
 	if (exp == NULL) {
 		ret = NF_DROP;
 		goto out;
@@ -454,7 +449,7 @@
 	/* We refer to the reverse direction ("!dir") tuples here,
 	 * because we're expecting something in the other direction.
 	 * Doesn't matter unless NAT is happening.  */
-	exp->tuple.dst.u3 = ct->tuplehash[!dir].tuple.dst.u3;
+	daddr = &ct->tuplehash[!dir].tuple.dst.u3;
 
 	/* Update the ftp info */
 	if ((cmd.l3num == ct->tuplehash[dir].tuple.src.l3num) &&
@@ -465,14 +460,16 @@
 		   different IP address.  Simply don't record it for
 		   NAT. */
 		if (cmd.l3num == PF_INET) {
-			DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n",
-			       NIPQUAD(cmd.u3.ip),
-			       NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip));
+			pr_debug("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT
+				 " != " NIPQUAD_FMT "\n",
+				 NIPQUAD(cmd.u3.ip),
+				 NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip));
 		} else {
-			DEBUGP("conntrack_ftp: NOT RECORDING: " NIP6_FMT " != " NIP6_FMT "\n",
-			       NIP6(*((struct in6_addr *)cmd.u3.ip6)),
-			       NIP6(*((struct in6_addr *)ct->tuplehash[dir]
-							.tuple.src.u3.ip6)));
+			pr_debug("conntrack_ftp: NOT RECORDING: " NIP6_FMT
+				 " != " NIP6_FMT "\n",
+				 NIP6(*((struct in6_addr *)cmd.u3.ip6)),
+				 NIP6(*((struct in6_addr *)
+					ct->tuplehash[dir].tuple.src.u3.ip6)));
 		}
 
 		/* Thanks to Cristiano Lincoln Mattos
@@ -483,37 +480,12 @@
 			ret = NF_ACCEPT;
 			goto out_put_expect;
 		}
-		memcpy(&exp->tuple.dst.u3, &cmd.u3.all,
-		       sizeof(exp->tuple.dst.u3));
+		daddr = &cmd.u3;
 	}
 
-	exp->tuple.src.u3 = ct->tuplehash[!dir].tuple.src.u3;
-	exp->tuple.src.l3num = cmd.l3num;
-	exp->tuple.src.u.tcp.port = 0;
-	exp->tuple.dst.u.tcp.port = cmd.u.tcp.port;
-	exp->tuple.dst.protonum = IPPROTO_TCP;
-
-	exp->mask = (struct nf_conntrack_tuple)
-		    { .src = { .l3num = 0xFFFF,
-			       .u = { .tcp = { 0 }},
-			     },
-		      .dst = { .protonum = 0xFF,
-			       .u = { .tcp = { __constant_htons(0xFFFF) }},
-			     },
-		    };
-	if (cmd.l3num == PF_INET) {
-		exp->mask.src.u3.ip = htonl(0xFFFFFFFF);
-		exp->mask.dst.u3.ip = htonl(0xFFFFFFFF);
-	} else {
-		memset(exp->mask.src.u3.ip6, 0xFF,
-		       sizeof(exp->mask.src.u3.ip6));
-		memset(exp->mask.dst.u3.ip6, 0xFF,
-		       sizeof(exp->mask.src.u3.ip6));
-	}
-
-	exp->expectfn = NULL;
-	exp->helper = NULL;
-	exp->flags = 0;
+	nf_ct_expect_init(exp, cmd.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3, daddr,
+			  IPPROTO_TCP, NULL, &cmd.u.tcp.port);
 
 	/* Now, NAT might want to mangle the packet, and register the
 	 * (possibly changed) expectation itself. */
@@ -523,14 +495,14 @@
 				 matchoff, matchlen, exp);
 	else {
 		/* Can't expect this?  Best to drop packet now. */
-		if (nf_conntrack_expect_related(exp) != 0)
+		if (nf_ct_expect_related(exp) != 0)
 			ret = NF_DROP;
 		else
 			ret = NF_ACCEPT;
 	}
 
 out_put_expect:
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 out_update_nl:
 	/* Now if this ends in \n, update ftp info.  Seq may have been
@@ -542,8 +514,8 @@
 	return ret;
 }
 
-static struct nf_conntrack_helper ftp[MAX_PORTS][2];
-static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")];
+static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly;
+static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")] __read_mostly;
 
 /* don't make this __exit, since it's called from __init ! */
 static void nf_conntrack_ftp_fini(void)
@@ -554,9 +526,9 @@
 			if (ftp[i][j].me == NULL)
 				continue;
 
-			DEBUGP("nf_ct_ftp: unregistering helper for pf: %d "
-			       "port: %d\n",
-				ftp[i][j].tuple.src.l3num, ports[i]);
+			pr_debug("nf_ct_ftp: unregistering helper for pf: %d "
+				 "port: %d\n",
+				 ftp[i][j].tuple.src.l3num, ports[i]);
 			nf_conntrack_helper_unregister(&ftp[i][j]);
 		}
 	}
@@ -584,9 +556,6 @@
 		for (j = 0; j < 2; j++) {
 			ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]);
 			ftp[i][j].tuple.dst.protonum = IPPROTO_TCP;
-			ftp[i][j].mask.src.l3num = 0xFFFF;
-			ftp[i][j].mask.src.u.tcp.port = htons(0xFFFF);
-			ftp[i][j].mask.dst.protonum = 0xFF;
 			ftp[i][j].max_expected = 1;
 			ftp[i][j].timeout = 5 * 60;	/* 5 Minutes */
 			ftp[i][j].me = THIS_MODULE;
@@ -598,9 +567,9 @@
 				sprintf(tmpname, "ftp-%d", ports[i]);
 			ftp[i][j].name = tmpname;
 
-			DEBUGP("nf_ct_ftp: registering helper for pf: %d "
-			       "port: %d\n",
-				ftp[i][j].tuple.src.l3num, ports[i]);
+			pr_debug("nf_ct_ftp: registering helper for pf: %d "
+				 "port: %d\n",
+				 ftp[i][j].tuple.src.l3num, ports[i]);
 			ret = nf_conntrack_helper_register(&ftp[i][j]);
 			if (ret) {
 				printk("nf_ct_ftp: failed to register helper "
diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c
index 6b7eaa0..a869403 100644
--- a/net/netfilter/nf_conntrack_h323_asn1.c
+++ b/net/netfilter/nf_conntrack_h323_asn1.c
@@ -555,15 +555,6 @@
 
 	/* Decode the extension components */
 	for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
-		if (i < f->ub && son->attr & STOP) {
-			PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
-			      son->name);
-			return H323_ERROR_STOP;
-		}
-
-		if (!((0x80000000 >> opt) & bmp2))	/* Not present */
-			continue;
-
 		/* Check Range */
 		if (i >= f->ub) {	/* Newer Version? */
 			CHECK_BOUND(bs, 2);
@@ -573,6 +564,15 @@
 			continue;
 		}
 
+		if (son->attr & STOP) {
+			PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
+			      son->name);
+			return H323_ERROR_STOP;
+		}
+
+		if (!((0x80000000 >> opt) & bmp2))	/* Not present */
+			continue;
+
 		CHECK_BOUND(bs, 2);
 		len = get_len(bs);
 		CHECK_BOUND(bs, len);
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index a1b95ac..a8a9dfb 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -31,12 +31,6 @@
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <linux/netfilter/nf_conntrack_h323.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Parameters */
 static unsigned int default_rrq_ttl __read_mostly = 300;
 module_param(default_rrq_ttl, uint, 0600);
@@ -150,9 +144,9 @@
 		if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
 			/* Netmeeting sends TPKT header and data separately */
 			if (info->tpkt_len[dir] > 0) {
-				DEBUGP("nf_ct_h323: previous packet "
-				       "indicated separate TPKT data of %hu "
-				       "bytes\n", info->tpkt_len[dir]);
+				pr_debug("nf_ct_h323: previous packet "
+					 "indicated separate TPKT data of %hu "
+					 "bytes\n", info->tpkt_len[dir]);
 				if (info->tpkt_len[dir] <= tcpdatalen) {
 					/* Yes, there was a TPKT header
 					 * received */
@@ -163,9 +157,7 @@
 				}
 
 				/* Fragmented TPKT */
-				if (net_ratelimit())
-					printk("nf_ct_h323: "
-					       "fragmented TPKT\n");
+				pr_debug("nf_ct_h323: fragmented TPKT\n");
 				goto clear_out;
 			}
 
@@ -192,9 +184,9 @@
 	if (tpktlen > tcpdatalen) {
 		if (tcpdatalen == 4) {	/* Separate TPKT header */
 			/* Netmeeting sends TPKT header and data separately */
-			DEBUGP("nf_ct_h323: separate TPKT header indicates "
-			       "there will be TPKT data of %hu bytes\n",
-			       tpktlen - 4);
+			pr_debug("nf_ct_h323: separate TPKT header indicates "
+				 "there will be TPKT data of %hu bytes\n",
+				 tpktlen - 4);
 			info->tpkt_len[dir] = tpktlen - 4;
 			return 0;
 		}
@@ -282,22 +274,22 @@
 	rtcp_port = htons(ntohs(port) + 1);
 
 	/* Create expect for RTP */
-	if ((rtp_exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((rtp_exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3,
-				 &ct->tuplehash[!dir].tuple.dst.u3,
-				 IPPROTO_UDP, NULL, &rtp_port);
+	nf_ct_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3,
+			  &ct->tuplehash[!dir].tuple.dst.u3,
+			  IPPROTO_UDP, NULL, &rtp_port);
 
 	/* Create expect for RTCP */
-	if ((rtcp_exp = nf_conntrack_expect_alloc(ct)) == NULL) {
-		nf_conntrack_expect_put(rtp_exp);
+	if ((rtcp_exp = nf_ct_expect_alloc(ct)) == NULL) {
+		nf_ct_expect_put(rtp_exp);
 		return -1;
 	}
-	nf_conntrack_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3,
-				 &ct->tuplehash[!dir].tuple.dst.u3,
-				 IPPROTO_UDP, NULL, &rtcp_port);
+	nf_ct_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3,
+			  &ct->tuplehash[!dir].tuple.dst.u3,
+			  IPPROTO_UDP, NULL, &rtcp_port);
 
 	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
 		   &ct->tuplehash[!dir].tuple.dst.u3,
@@ -308,22 +300,22 @@
 		ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
 				   taddr, port, rtp_port, rtp_exp, rtcp_exp);
 	} else {		/* Conntrack only */
-		if (nf_conntrack_expect_related(rtp_exp) == 0) {
-			if (nf_conntrack_expect_related(rtcp_exp) == 0) {
-				DEBUGP("nf_ct_h323: expect RTP ");
+		if (nf_ct_expect_related(rtp_exp) == 0) {
+			if (nf_ct_expect_related(rtcp_exp) == 0) {
+				pr_debug("nf_ct_h323: expect RTP ");
 				NF_CT_DUMP_TUPLE(&rtp_exp->tuple);
-				DEBUGP("nf_ct_h323: expect RTCP ");
+				pr_debug("nf_ct_h323: expect RTCP ");
 				NF_CT_DUMP_TUPLE(&rtcp_exp->tuple);
 			} else {
-				nf_conntrack_unexpect_related(rtp_exp);
+				nf_ct_unexpect_related(rtp_exp);
 				ret = -1;
 			}
 		} else
 			ret = -1;
 	}
 
-	nf_conntrack_expect_put(rtp_exp);
-	nf_conntrack_expect_put(rtcp_exp);
+	nf_ct_expect_put(rtp_exp);
+	nf_ct_expect_put(rtcp_exp);
 
 	return ret;
 }
@@ -349,12 +341,12 @@
 		return 0;
 
 	/* Create expect for T.120 connections */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3,
-				 &ct->tuplehash[!dir].tuple.dst.u3,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3,
+			  &ct->tuplehash[!dir].tuple.dst.u3,
+			  IPPROTO_TCP, NULL, &port);
 	exp->flags = NF_CT_EXPECT_PERMANENT;	/* Accept multiple channels */
 
 	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -366,14 +358,14 @@
 		ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr,
 			       port, exp);
 	} else {		/* Conntrack only */
-		if (nf_conntrack_expect_related(exp) == 0) {
-			DEBUGP("nf_ct_h323: expect T.120 ");
+		if (nf_ct_expect_related(exp) == 0) {
+			pr_debug("nf_ct_h323: expect T.120 ");
 			NF_CT_DUMP_TUPLE(&exp->tuple);
 		} else
 			ret = -1;
 	}
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -415,7 +407,7 @@
 {
 	int ret;
 
-	DEBUGP("nf_ct_h323: OpenLogicalChannel\n");
+	pr_debug("nf_ct_h323: OpenLogicalChannel\n");
 
 	if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
 	    eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
@@ -475,7 +467,7 @@
 	H2250LogicalChannelAckParameters *ack;
 	int ret;
 
-	DEBUGP("nf_ct_h323: OpenLogicalChannelAck\n");
+	pr_debug("nf_ct_h323: OpenLogicalChannelAck\n");
 
 	if ((olca->options &
 	     eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
@@ -546,8 +538,8 @@
 			return process_olc(pskb, ct, ctinfo, data, dataoff,
 					   &mscm->request.openLogicalChannel);
 		}
-		DEBUGP("nf_ct_h323: H.245 Request %d\n",
-		       mscm->request.choice);
+		pr_debug("nf_ct_h323: H.245 Request %d\n",
+			 mscm->request.choice);
 		break;
 	case eMultimediaSystemControlMessage_response:
 		if (mscm->response.choice ==
@@ -556,11 +548,11 @@
 					    &mscm->response.
 					    openLogicalChannelAck);
 		}
-		DEBUGP("nf_ct_h323: H.245 Response %d\n",
-		       mscm->response.choice);
+		pr_debug("nf_ct_h323: H.245 Response %d\n",
+			 mscm->response.choice);
 		break;
 	default:
-		DEBUGP("nf_ct_h323: H.245 signal %d\n", mscm->choice);
+		pr_debug("nf_ct_h323: H.245 signal %d\n", mscm->choice);
 		break;
 	}
 
@@ -582,24 +574,23 @@
 	    ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
 		return NF_ACCEPT;
 	}
-	DEBUGP("nf_ct_h245: skblen = %u\n", (*pskb)->len);
+	pr_debug("nf_ct_h245: skblen = %u\n", (*pskb)->len);
 
 	spin_lock_bh(&nf_h323_lock);
 
 	/* Process each TPKT */
 	while (get_tpkt_data(pskb, protoff, ct, ctinfo,
 			     &data, &datalen, &dataoff)) {
-		DEBUGP("nf_ct_h245: TPKT len=%d ", datalen);
+		pr_debug("nf_ct_h245: TPKT len=%d ", datalen);
 		NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
 
 		/* Decode H.245 signal */
 		ret = DecodeMultimediaSystemControlMessage(data, datalen,
 							   &mscm);
 		if (ret < 0) {
-			if (net_ratelimit())
-				printk("nf_ct_h245: decoding error: %s\n",
-				       ret == H323_ERROR_BOUND ?
-				       "out of bound" : "out of range");
+			pr_debug("nf_ct_h245: decoding error: %s\n",
+				 ret == H323_ERROR_BOUND ?
+				 "out of bound" : "out of range");
 			/* We don't drop when decoding error */
 			break;
 		}
@@ -626,8 +617,6 @@
 	.max_expected		= H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
 	.timeout		= 240,
 	.tuple.dst.protonum	= IPPROTO_UDP,
-	.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-	.mask.dst.protonum	= 0xFF,
 	.help			= h245_help
 };
 
@@ -684,12 +673,12 @@
 		return 0;
 
 	/* Create expect for h245 connection */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3,
-				 &ct->tuplehash[!dir].tuple.dst.u3,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3,
+			  &ct->tuplehash[!dir].tuple.dst.u3,
+			  IPPROTO_TCP, NULL, &port);
 	exp->helper = &nf_conntrack_helper_h245;
 
 	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -701,14 +690,14 @@
 		ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr,
 			       port, exp);
 	} else {		/* Conntrack only */
-		if (nf_conntrack_expect_related(exp) == 0) {
-			DEBUGP("nf_ct_q931: expect H.245 ");
+		if (nf_ct_expect_related(exp) == 0) {
+			pr_debug("nf_ct_q931: expect H.245 ");
 			NF_CT_DUMP_TUPLE(&exp->tuple);
 		} else
 			ret = -1;
 	}
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -791,16 +780,16 @@
 	if (callforward_filter &&
 	    callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3,
 				  ct->tuplehash[!dir].tuple.src.l3num)) {
-		DEBUGP("nf_ct_q931: Call Forwarding not tracked\n");
+		pr_debug("nf_ct_q931: Call Forwarding not tracked\n");
 		return 0;
 	}
 
 	/* Create expect for the second call leg */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3, &addr,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+			  IPPROTO_TCP, NULL, &port);
 	exp->helper = nf_conntrack_helper_q931;
 
 	if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -812,14 +801,14 @@
 		ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff,
 					 taddr, port, exp);
 	} else {		/* Conntrack only */
-		if (nf_conntrack_expect_related(exp) == 0) {
-			DEBUGP("nf_ct_q931: expect Call Forwarding ");
+		if (nf_ct_expect_related(exp) == 0) {
+			pr_debug("nf_ct_q931: expect Call Forwarding ");
 			NF_CT_DUMP_TUPLE(&exp->tuple);
 		} else
 			ret = -1;
 	}
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -837,7 +826,7 @@
 	union nf_conntrack_address addr;
 	typeof(set_h225_addr_hook) set_h225_addr;
 
-	DEBUGP("nf_ct_q931: Setup\n");
+	pr_debug("nf_ct_q931: Setup\n");
 
 	if (setup->options & eSetup_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -852,11 +841,11 @@
 	    get_h225_addr(ct, *data, &setup->destCallSignalAddress,
 			  &addr, &port) &&
 	    memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
-		DEBUGP("nf_ct_q931: set destCallSignalAddress "
-		       NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
-		       NIP6(*(struct in6_addr *)&addr), ntohs(port),
-		       NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3),
-		       ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
+		pr_debug("nf_ct_q931: set destCallSignalAddress "
+			 NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
+			 NIP6(*(struct in6_addr *)&addr), ntohs(port),
+			 NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3),
+			 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
 		ret = set_h225_addr(pskb, data, dataoff,
 				    &setup->destCallSignalAddress,
 				    &ct->tuplehash[!dir].tuple.src.u3,
@@ -870,11 +859,11 @@
 	    get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
 			  &addr, &port) &&
 	    memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
-		DEBUGP("nf_ct_q931: set sourceCallSignalAddress "
-		       NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
-		       NIP6(*(struct in6_addr *)&addr), ntohs(port),
-		       NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3),
-		       ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
+		pr_debug("nf_ct_q931: set sourceCallSignalAddress "
+			 NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
+			 NIP6(*(struct in6_addr *)&addr), ntohs(port),
+			 NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3),
+			 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
 		ret = set_h225_addr(pskb, data, dataoff,
 				    &setup->sourceCallSignalAddress,
 				    &ct->tuplehash[!dir].tuple.dst.u3,
@@ -905,7 +894,7 @@
 	int ret;
 	int i;
 
-	DEBUGP("nf_ct_q931: CallProceeding\n");
+	pr_debug("nf_ct_q931: CallProceeding\n");
 
 	if (callproc->options & eCallProceeding_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -935,7 +924,7 @@
 	int ret;
 	int i;
 
-	DEBUGP("nf_ct_q931: Connect\n");
+	pr_debug("nf_ct_q931: Connect\n");
 
 	if (connect->options & eConnect_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -965,7 +954,7 @@
 	int ret;
 	int i;
 
-	DEBUGP("nf_ct_q931: Alerting\n");
+	pr_debug("nf_ct_q931: Alerting\n");
 
 	if (alert->options & eAlerting_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -995,7 +984,7 @@
 	int ret;
 	int i;
 
-	DEBUGP("nf_ct_q931: Facility\n");
+	pr_debug("nf_ct_q931: Facility\n");
 
 	if (facility->reason.choice == eFacilityReason_callForwarded) {
 		if (facility->options & eFacility_UUIE_alternativeAddress)
@@ -1034,7 +1023,7 @@
 	int ret;
 	int i;
 
-	DEBUGP("nf_ct_q931: Progress\n");
+	pr_debug("nf_ct_q931: Progress\n");
 
 	if (progress->options & eProgress_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -1091,8 +1080,8 @@
 				       &pdu->h323_message_body.progress);
 		break;
 	default:
-		DEBUGP("nf_ct_q931: Q.931 signal %d\n",
-		       pdu->h323_message_body.choice);
+		pr_debug("nf_ct_q931: Q.931 signal %d\n",
+			 pdu->h323_message_body.choice);
 		break;
 	}
 
@@ -1126,23 +1115,22 @@
 	    ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
 		return NF_ACCEPT;
 	}
-	DEBUGP("nf_ct_q931: skblen = %u\n", (*pskb)->len);
+	pr_debug("nf_ct_q931: skblen = %u\n", (*pskb)->len);
 
 	spin_lock_bh(&nf_h323_lock);
 
 	/* Process each TPKT */
 	while (get_tpkt_data(pskb, protoff, ct, ctinfo,
 			     &data, &datalen, &dataoff)) {
-		DEBUGP("nf_ct_q931: TPKT len=%d ", datalen);
+		pr_debug("nf_ct_q931: TPKT len=%d ", datalen);
 		NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
 
 		/* Decode Q.931 signal */
 		ret = DecodeQ931(data, datalen, &q931);
 		if (ret < 0) {
-			if (net_ratelimit())
-				printk("nf_ct_q931: decoding error: %s\n",
-				       ret == H323_ERROR_BOUND ?
-				       "out of bound" : "out of range");
+			pr_debug("nf_ct_q931: decoding error: %s\n",
+				 ret == H323_ERROR_BOUND ?
+				 "out of bound" : "out of range");
 			/* We don't drop when decoding error */
 			break;
 		}
@@ -1173,9 +1161,6 @@
 		.tuple.src.l3num	= AF_INET,
 		.tuple.src.u.tcp.port	= __constant_htons(Q931_PORT),
 		.tuple.dst.protonum	= IPPROTO_TCP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.tcp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 		.help			= q931_help
 	},
 	{
@@ -1187,9 +1172,6 @@
 		.tuple.src.l3num	= AF_INET6,
 		.tuple.src.u.tcp.port	= __constant_htons(Q931_PORT),
 		.tuple.dst.protonum	= IPPROTO_TCP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.tcp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 		.help			= q931_help
 	},
 };
@@ -1225,7 +1207,7 @@
 	tuple.dst.u.tcp.port = port;
 	tuple.dst.protonum = IPPROTO_TCP;
 
-	exp = __nf_conntrack_expect_find(&tuple);
+	exp = __nf_ct_expect_find(&tuple);
 	if (exp && exp->master == ct)
 		return exp;
 	return NULL;
@@ -1271,14 +1253,13 @@
 		return 0;
 
 	/* Create expect for Q.931 */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 gkrouted_only ? /* only accept calls from GK? */
-					&ct->tuplehash[!dir].tuple.src.u3 :
-					NULL,
-				 &ct->tuplehash[!dir].tuple.dst.u3,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  gkrouted_only ? /* only accept calls from GK? */
+				&ct->tuplehash[!dir].tuple.src.u3 : NULL,
+			  &ct->tuplehash[!dir].tuple.dst.u3,
+			  IPPROTO_TCP, NULL, &port);
 	exp->helper = nf_conntrack_helper_q931;
 	exp->flags = NF_CT_EXPECT_PERMANENT;	/* Accept multiple calls */
 
@@ -1286,8 +1267,8 @@
 	if (nat_q931 && ct->status & IPS_NAT_MASK) {	/* Need NAT */
 		ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp);
 	} else {		/* Conntrack only */
-		if (nf_conntrack_expect_related(exp) == 0) {
-			DEBUGP("nf_ct_ras: expect Q.931 ");
+		if (nf_ct_expect_related(exp) == 0) {
+			pr_debug("nf_ct_ras: expect Q.931 ");
 			NF_CT_DUMP_TUPLE(&exp->tuple);
 
 			/* Save port for looking up expect in processing RCF */
@@ -1296,7 +1277,7 @@
 			ret = -1;
 	}
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -1308,7 +1289,7 @@
 {
 	typeof(set_ras_addr_hook) set_ras_addr;
 
-	DEBUGP("nf_ct_ras: GRQ\n");
+	pr_debug("nf_ct_ras: GRQ\n");
 
 	set_ras_addr = rcu_dereference(set_ras_addr_hook);
 	if (set_ras_addr && ct->status & IPS_NAT_MASK)	/* NATed */
@@ -1328,7 +1309,7 @@
 	union nf_conntrack_address addr;
 	struct nf_conntrack_expect *exp;
 
-	DEBUGP("nf_ct_ras: GCF\n");
+	pr_debug("nf_ct_ras: GCF\n");
 
 	if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port))
 		return 0;
@@ -1343,20 +1324,20 @@
 		return 0;
 
 	/* Need new expect */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3, &addr,
-				 IPPROTO_UDP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+			  IPPROTO_UDP, NULL, &port);
 	exp->helper = nf_conntrack_helper_ras;
 
-	if (nf_conntrack_expect_related(exp) == 0) {
-		DEBUGP("nf_ct_ras: expect RAS ");
+	if (nf_ct_expect_related(exp) == 0) {
+		pr_debug("nf_ct_ras: expect RAS ");
 		NF_CT_DUMP_TUPLE(&exp->tuple);
 	} else
 		ret = -1;
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -1370,7 +1351,7 @@
 	int ret;
 	typeof(set_ras_addr_hook) set_ras_addr;
 
-	DEBUGP("nf_ct_ras: RRQ\n");
+	pr_debug("nf_ct_ras: RRQ\n");
 
 	ret = expect_q931(pskb, ct, ctinfo, data,
 			  rrq->callSignalAddress.item,
@@ -1388,7 +1369,7 @@
 	}
 
 	if (rrq->options & eRegistrationRequest_timeToLive) {
-		DEBUGP("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
+		pr_debug("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
 		info->timeout = rrq->timeToLive;
 	} else
 		info->timeout = default_rrq_ttl;
@@ -1407,7 +1388,7 @@
 	struct nf_conntrack_expect *exp;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	DEBUGP("nf_ct_ras: RCF\n");
+	pr_debug("nf_ct_ras: RCF\n");
 
 	set_sig_addr = rcu_dereference(set_sig_addr_hook);
 	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
@@ -1419,14 +1400,13 @@
 	}
 
 	if (rcf->options & eRegistrationConfirm_timeToLive) {
-		DEBUGP("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
+		pr_debug("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
 		info->timeout = rcf->timeToLive;
 	}
 
 	if (info->timeout > 0) {
-		DEBUGP
-		    ("nf_ct_ras: set RAS connection timeout to %u seconds\n",
-		     info->timeout);
+		pr_debug("nf_ct_ras: set RAS connection timeout to "
+			 "%u seconds\n", info->timeout);
 		nf_ct_refresh(ct, *pskb, info->timeout * HZ);
 
 		/* Set expect timeout */
@@ -1434,9 +1414,9 @@
 		exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3,
 				  info->sig_port[!dir]);
 		if (exp) {
-			DEBUGP("nf_ct_ras: set Q.931 expect "
-			       "timeout to %u seconds for",
-			       info->timeout);
+			pr_debug("nf_ct_ras: set Q.931 expect "
+				 "timeout to %u seconds for",
+				 info->timeout);
 			NF_CT_DUMP_TUPLE(&exp->tuple);
 			set_expect_timeout(exp, info->timeout);
 		}
@@ -1456,7 +1436,7 @@
 	int ret;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	DEBUGP("nf_ct_ras: URQ\n");
+	pr_debug("nf_ct_ras: URQ\n");
 
 	set_sig_addr = rcu_dereference(set_sig_addr_hook);
 	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
@@ -1489,7 +1469,7 @@
 	union nf_conntrack_address addr;
 	typeof(set_h225_addr_hook) set_h225_addr;
 
-	DEBUGP("nf_ct_ras: ARQ\n");
+	pr_debug("nf_ct_ras: ARQ\n");
 
 	set_h225_addr = rcu_dereference(set_h225_addr_hook);
 	if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
@@ -1532,7 +1512,7 @@
 	struct nf_conntrack_expect *exp;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	DEBUGP("nf_ct_ras: ACF\n");
+	pr_debug("nf_ct_ras: ACF\n");
 
 	if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress,
 			   &addr, &port))
@@ -1548,21 +1528,21 @@
 	}
 
 	/* Need new expect */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3, &addr,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+			  IPPROTO_TCP, NULL, &port);
 	exp->flags = NF_CT_EXPECT_PERMANENT;
 	exp->helper = nf_conntrack_helper_q931;
 
-	if (nf_conntrack_expect_related(exp) == 0) {
-		DEBUGP("nf_ct_ras: expect Q.931 ");
+	if (nf_ct_expect_related(exp) == 0) {
+		pr_debug("nf_ct_ras: expect Q.931 ");
 		NF_CT_DUMP_TUPLE(&exp->tuple);
 	} else
 		ret = -1;
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -1574,7 +1554,7 @@
 {
 	typeof(set_ras_addr_hook) set_ras_addr;
 
-	DEBUGP("nf_ct_ras: LRQ\n");
+	pr_debug("nf_ct_ras: LRQ\n");
 
 	set_ras_addr = rcu_dereference(set_ras_addr_hook);
 	if (set_ras_addr && ct->status & IPS_NAT_MASK)
@@ -1594,28 +1574,28 @@
 	union nf_conntrack_address addr;
 	struct nf_conntrack_expect *exp;
 
-	DEBUGP("nf_ct_ras: LCF\n");
+	pr_debug("nf_ct_ras: LCF\n");
 
 	if (!get_h225_addr(ct, *data, &lcf->callSignalAddress,
 			   &addr, &port))
 		return 0;
 
 	/* Need new expect for call signal */
-	if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
 		return -1;
-	nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
-				 &ct->tuplehash[!dir].tuple.src.u3, &addr,
-				 IPPROTO_TCP, NULL, &port);
+	nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
+			  IPPROTO_TCP, NULL, &port);
 	exp->flags = NF_CT_EXPECT_PERMANENT;
 	exp->helper = nf_conntrack_helper_q931;
 
-	if (nf_conntrack_expect_related(exp) == 0) {
-		DEBUGP("nf_ct_ras: expect Q.931 ");
+	if (nf_ct_expect_related(exp) == 0) {
+		pr_debug("nf_ct_ras: expect Q.931 ");
 		NF_CT_DUMP_TUPLE(&exp->tuple);
 	} else
 		ret = -1;
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	/* Ignore rasAddress */
 
@@ -1631,7 +1611,7 @@
 	typeof(set_ras_addr_hook) set_ras_addr;
 	typeof(set_sig_addr_hook) set_sig_addr;
 
-	DEBUGP("nf_ct_ras: IRR\n");
+	pr_debug("nf_ct_ras: IRR\n");
 
 	set_ras_addr = rcu_dereference(set_ras_addr_hook);
 	if (set_ras_addr && ct->status & IPS_NAT_MASK) {
@@ -1690,7 +1670,7 @@
 		return process_irr(pskb, ct, ctinfo, data,
 				   &ras->infoRequestResponse);
 	default:
-		DEBUGP("nf_ct_ras: RAS message %d\n", ras->choice);
+		pr_debug("nf_ct_ras: RAS message %d\n", ras->choice);
 		break;
 	}
 
@@ -1706,7 +1686,7 @@
 	int datalen = 0;
 	int ret;
 
-	DEBUGP("nf_ct_ras: skblen = %u\n", (*pskb)->len);
+	pr_debug("nf_ct_ras: skblen = %u\n", (*pskb)->len);
 
 	spin_lock_bh(&nf_h323_lock);
 
@@ -1714,16 +1694,15 @@
 	data = get_udp_data(pskb, protoff, &datalen);
 	if (data == NULL)
 		goto accept;
-	DEBUGP("nf_ct_ras: RAS message len=%d ", datalen);
+	pr_debug("nf_ct_ras: RAS message len=%d ", datalen);
 	NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
 
 	/* Decode RAS message */
 	ret = DecodeRasMessage(data, datalen, &ras);
 	if (ret < 0) {
-		if (net_ratelimit())
-			printk("nf_ct_ras: decoding error: %s\n",
-			       ret == H323_ERROR_BOUND ?
-			       "out of bound" : "out of range");
+		pr_debug("nf_ct_ras: decoding error: %s\n",
+			 ret == H323_ERROR_BOUND ?
+			 "out of bound" : "out of range");
 		goto accept;
 	}
 
@@ -1752,9 +1731,6 @@
 		.tuple.src.l3num	= AF_INET,
 		.tuple.src.u.udp.port	= __constant_htons(RAS_PORT),
 		.tuple.dst.protonum	= IPPROTO_UDP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 		.help			= ras_help,
 	},
 	{
@@ -1765,9 +1741,6 @@
 		.tuple.src.l3num	= AF_INET6,
 		.tuple.src.u.udp.port	= __constant_htons(RAS_PORT),
 		.tuple.dst.protonum	= IPPROTO_UDP,
-		.mask.src.l3num		= 0xFFFF,
-		.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-		.mask.dst.protonum	= 0xFF,
 		.help			= ras_help,
 	},
 };
@@ -1780,7 +1753,7 @@
 	nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]);
 	nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
 	kfree(h323_buffer);
-	DEBUGP("nf_ct_h323: fini\n");
+	pr_debug("nf_ct_h323: fini\n");
 }
 
 /****************************************************************************/
@@ -1803,7 +1776,7 @@
 	ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]);
 	if (ret < 0)
 		goto err4;
-	DEBUGP("nf_ct_h323: init success\n");
+	pr_debug("nf_ct_h323: init success\n");
 	return 0;
 
 err4:
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index f868b7f..b1179dd 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -26,23 +26,43 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_extend.h>
 
-static __read_mostly LIST_HEAD(helpers);
+static struct hlist_head *nf_ct_helper_hash __read_mostly;
+static unsigned int nf_ct_helper_hsize __read_mostly;
+static unsigned int nf_ct_helper_count __read_mostly;
+static int nf_ct_helper_vmalloc;
+
+
+/* Stupid hash, but collision free for the default registrations of the
+ * helpers currently in the kernel. */
+static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple)
+{
+	return (((tuple->src.l3num << 8) | tuple->dst.protonum) ^
+		tuple->src.u.all) % nf_ct_helper_hsize;
+}
 
 struct nf_conntrack_helper *
 __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
 {
-	struct nf_conntrack_helper *h;
+	struct nf_conntrack_helper *helper;
+	struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) };
+	struct hlist_node *n;
+	unsigned int h;
 
-	list_for_each_entry(h, &helpers, list) {
-		if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask))
-			return h;
+	if (!nf_ct_helper_count)
+		return NULL;
+
+	h = helper_hash(tuple);
+	hlist_for_each_entry(helper, n, &nf_ct_helper_hash[h], hnode) {
+		if (nf_ct_tuple_src_mask_cmp(tuple, &helper->tuple, &mask))
+			return helper;
 	}
 	return NULL;
 }
 
 struct nf_conntrack_helper *
-nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple)
+nf_ct_helper_find_get(const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_helper *helper;
 
@@ -75,16 +95,32 @@
 __nf_conntrack_helper_find_byname(const char *name)
 {
 	struct nf_conntrack_helper *h;
+	struct hlist_node *n;
+	unsigned int i;
 
-	list_for_each_entry(h, &helpers, list) {
-		if (!strcmp(h->name, name))
-			return h;
+	for (i = 0; i < nf_ct_helper_hsize; i++) {
+		hlist_for_each_entry(h, n, &nf_ct_helper_hash[i], hnode) {
+			if (!strcmp(h->name, name))
+				return h;
+		}
 	}
-
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname);
 
+struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
+{
+	struct nf_conn_help *help;
+
+	help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, gfp);
+	if (help)
+		INIT_HLIST_HEAD(&help->expectations);
+	else
+		pr_debug("failed to add helper extension area");
+	return help;
+}
+EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
+
 static inline int unhelp(struct nf_conntrack_tuple_hash *i,
 			 const struct nf_conntrack_helper *me)
 {
@@ -100,20 +136,13 @@
 
 int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 {
-	int size, ret;
+	unsigned int h = helper_hash(&me->tuple);
 
 	BUG_ON(me->timeout == 0);
 
-	size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_help)) +
-	       sizeof(struct nf_conn_help);
-	ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help",
-					  size);
-	if (ret < 0) {
-		printk(KERN_ERR "nf_conntrack_helper_register: Unable to create slab cache for conntracks\n");
-		return ret;
-	}
 	write_lock_bh(&nf_conntrack_lock);
-	list_add(&me->list, &helpers);
+	hlist_add_head(&me->hnode, &nf_ct_helper_hash[h]);
+	nf_ct_helper_count++;
 	write_unlock_bh(&nf_conntrack_lock);
 
 	return 0;
@@ -122,29 +151,34 @@
 
 void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
 {
-	unsigned int i;
 	struct nf_conntrack_tuple_hash *h;
-	struct nf_conntrack_expect *exp, *tmp;
+	struct nf_conntrack_expect *exp;
+	struct hlist_node *n, *next;
+	unsigned int i;
 
 	/* Need write lock here, to delete helper. */
 	write_lock_bh(&nf_conntrack_lock);
-	list_del(&me->list);
+	hlist_del(&me->hnode);
+	nf_ct_helper_count--;
 
 	/* Get rid of expectations */
-	list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
-		struct nf_conn_help *help = nfct_help(exp->master);
-		if ((help->helper == me || exp->helper == me) &&
-		    del_timer(&exp->timeout)) {
-			nf_ct_unlink_expect(exp);
-			nf_conntrack_expect_put(exp);
+	for (i = 0; i < nf_ct_expect_hsize; i++) {
+		hlist_for_each_entry_safe(exp, n, next,
+					  &nf_ct_expect_hash[i], hnode) {
+			struct nf_conn_help *help = nfct_help(exp->master);
+			if ((help->helper == me || exp->helper == me) &&
+			    del_timer(&exp->timeout)) {
+				nf_ct_unlink_expect(exp);
+				nf_ct_expect_put(exp);
+			}
 		}
 	}
 
 	/* Get rid of expecteds, set helpers to NULL. */
-	list_for_each_entry(h, &unconfirmed, list)
+	hlist_for_each_entry(h, n, &unconfirmed, hnode)
 		unhelp(h, me);
 	for (i = 0; i < nf_conntrack_htable_size; i++) {
-		list_for_each_entry(h, &nf_conntrack_hash[i], list)
+		hlist_for_each_entry(h, n, &nf_conntrack_hash[i], hnode)
 			unhelp(h, me);
 	}
 	write_unlock_bh(&nf_conntrack_lock);
@@ -153,3 +187,38 @@
 	synchronize_net();
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
+
+static struct nf_ct_ext_type helper_extend __read_mostly = {
+	.len	= sizeof(struct nf_conn_help),
+	.align	= __alignof__(struct nf_conn_help),
+	.id	= NF_CT_EXT_HELPER,
+};
+
+int nf_conntrack_helper_init()
+{
+	int err;
+
+	nf_ct_helper_hsize = 1; /* gets rounded up to use one page */
+	nf_ct_helper_hash = nf_ct_alloc_hashtable(&nf_ct_helper_hsize,
+						  &nf_ct_helper_vmalloc);
+	if (!nf_ct_helper_hash)
+		return -ENOMEM;
+
+	err = nf_ct_extend_register(&helper_extend);
+	if (err < 0)
+		goto err1;
+
+	return 0;
+
+err1:
+	nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc,
+			     nf_ct_helper_hsize);
+	return err;
+}
+
+void nf_conntrack_helper_fini()
+{
+	nf_ct_extend_unregister(&helper_extend);
+	nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc,
+			     nf_ct_helper_hsize);
+}
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 43ccd0e..1562ca9 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -12,6 +12,7 @@
 #include <linux/moduleparam.h>
 #include <linux/skbuff.h>
 #include <linux/in.h>
+#include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/netfilter.h>
 
@@ -55,13 +56,6 @@
 
 #define MINMATCHLEN	5
 
-#if 0
-#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s:" format, \
-				       __FILE__, __FUNCTION__ , ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* tries to get the ip_addr and port out of a dcc command
  * return value: -1 on failure, 0 on success
  *	data		pointer to first byte of DCC command data
@@ -99,6 +93,7 @@
 		struct nf_conn *ct, enum ip_conntrack_info ctinfo)
 {
 	unsigned int dataoff;
+	struct iphdr *iph;
 	struct tcphdr _tcph, *th;
 	char *data, *data_limit, *ib_ptr;
 	int dir = CTINFO2DIR(ctinfo);
@@ -148,9 +143,10 @@
 		data += 5;
 		/* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
 
-		DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
-			NIPQUAD(iph->saddr), ntohs(th->source),
-			NIPQUAD(iph->daddr), ntohs(th->dest));
+		iph = ip_hdr(*pskb);
+		pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n",
+			 NIPQUAD(iph->saddr), ntohs(th->source),
+			 NIPQUAD(iph->daddr), ntohs(th->dest));
 
 		for (i = 0; i < ARRAY_SIZE(dccprotos); i++) {
 			if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) {
@@ -158,18 +154,18 @@
 				continue;
 			}
 			data += strlen(dccprotos[i]);
-			DEBUGP("DCC %s detected\n", dccprotos[i]);
+			pr_debug("DCC %s detected\n", dccprotos[i]);
 
 			/* we have at least
 			 * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
 			 * data left (== 14/13 bytes) */
 			if (parse_dcc((char *)data, data_limit, &dcc_ip,
 				       &dcc_port, &addr_beg_p, &addr_end_p)) {
-				DEBUGP("unable to parse dcc command\n");
+				pr_debug("unable to parse dcc command\n");
 				continue;
 			}
-			DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n",
-				HIPQUAD(dcc_ip), dcc_port);
+			pr_debug("DCC bound ip/port: %u.%u.%u.%u:%u\n",
+				 HIPQUAD(dcc_ip), dcc_port);
 
 			/* dcc_ip can be the internal OR external (NAT'ed) IP */
 			tuple = &ct->tuplehash[dir].tuple;
@@ -184,16 +180,16 @@
 				continue;
 			}
 
-			exp = nf_conntrack_expect_alloc(ct);
+			exp = nf_ct_expect_alloc(ct);
 			if (exp == NULL) {
 				ret = NF_DROP;
 				goto out;
 			}
 			tuple = &ct->tuplehash[!dir].tuple;
 			port = htons(dcc_port);
-			nf_conntrack_expect_init(exp, tuple->src.l3num,
-						 NULL, &tuple->dst.u3,
-						 IPPROTO_TCP, NULL, &port);
+			nf_ct_expect_init(exp, tuple->src.l3num,
+					  NULL, &tuple->dst.u3,
+					  IPPROTO_TCP, NULL, &port);
 
 			nf_nat_irc = rcu_dereference(nf_nat_irc_hook);
 			if (nf_nat_irc && ct->status & IPS_NAT_MASK)
@@ -201,9 +197,9 @@
 						 addr_beg_p - ib_ptr,
 						 addr_end_p - addr_beg_p,
 						 exp);
-			else if (nf_conntrack_expect_related(exp) != 0)
+			else if (nf_ct_expect_related(exp) != 0)
 				ret = NF_DROP;
-			nf_conntrack_expect_put(exp);
+			nf_ct_expect_put(exp);
 			goto out;
 		}
 	}
@@ -239,9 +235,6 @@
 		irc[i].tuple.src.l3num = AF_INET;
 		irc[i].tuple.src.u.tcp.port = htons(ports[i]);
 		irc[i].tuple.dst.protonum = IPPROTO_TCP;
-		irc[i].mask.src.l3num = 0xFFFF;
-		irc[i].mask.src.u.tcp.port = htons(0xFFFF);
-		irc[i].mask.dst.protonum = 0xFF;
 		irc[i].max_expected = max_dcc_channels;
 		irc[i].timeout = dcc_timeout;
 		irc[i].me = THIS_MODULE;
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index cbd96f3..b1bfa20 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -31,12 +31,6 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
 				struct nf_conntrack_tuple *tuple)
 {
@@ -76,12 +70,6 @@
 }
 
 
-static u_int32_t generic_get_features(const struct nf_conntrack_tuple *tuple)
-
-{
-	return NF_CT_F_BASIC;
-}
-
 struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = {
 	.l3proto	 = PF_UNSPEC,
 	.name		 = "unknown",
@@ -90,6 +78,5 @@
 	.print_tuple	 = generic_print_tuple,
 	.print_conntrack = generic_print_conntrack,
 	.prepare	 = generic_prepare,
-	.get_features	 = generic_get_features,
 };
 EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic);
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
index 1093478..1d59fab 100644
--- a/net/netfilter/nf_conntrack_netbios_ns.c
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -74,7 +74,7 @@
 	if (mask == 0)
 		goto out;
 
-	exp = nf_conntrack_expect_alloc(ct);
+	exp = nf_ct_expect_alloc(ct);
 	if (exp == NULL)
 		goto out;
 
@@ -83,16 +83,13 @@
 
 	exp->mask.src.u3.ip       = mask;
 	exp->mask.src.u.udp.port  = htons(0xFFFF);
-	exp->mask.dst.u3.ip       = htonl(0xFFFFFFFF);
-	exp->mask.dst.u.udp.port  = htons(0xFFFF);
-	exp->mask.dst.protonum    = 0xFF;
 
 	exp->expectfn             = NULL;
 	exp->flags                = NF_CT_EXPECT_PERMANENT;
 	exp->helper               = NULL;
 
-	nf_conntrack_expect_related(exp);
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_related(exp);
+	nf_ct_expect_put(exp);
 
 	nf_ct_refresh(ct, *pskb, timeout * HZ);
 out:
@@ -104,9 +101,6 @@
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.udp.port	= __constant_htons(NMBD_PORT),
 	.tuple.dst.protonum	= IPPROTO_UDP,
-	.mask.src.l3num		= 0xFFFF,
-	.mask.src.u.udp.port	= __constant_htons(0xFFFF),
-	.mask.dst.protonum	= 0xFF,
 	.max_expected		= 1,
 	.me			= THIS_MODULE,
 	.help			= help,
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index d0fe3d7..6f89b10 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -428,7 +428,7 @@
 {
 	struct nf_conn *ct, *last;
 	struct nf_conntrack_tuple_hash *h;
-	struct list_head *i;
+	struct hlist_node *n;
 	struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
 	u_int8_t l3proto = nfmsg->nfgen_family;
 
@@ -436,8 +436,8 @@
 	last = (struct nf_conn *)cb->args[1];
 	for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
 restart:
-		list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
-			h = (struct nf_conntrack_tuple_hash *) i;
+		hlist_for_each_entry(h, n, &nf_conntrack_hash[cb->args[0]],
+				     hnode) {
 			if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
 				continue;
 			ct = nf_ct_tuplehash_to_ctrack(h);
@@ -689,7 +689,7 @@
 	if (err < 0)
 		return err;
 
-	h = nf_conntrack_find_get(&tuple, NULL);
+	h = nf_conntrack_find_get(&tuple);
 	if (!h)
 		return -ENOENT;
 
@@ -744,7 +744,7 @@
 	if (err < 0)
 		return err;
 
-	h = nf_conntrack_find_get(&tuple, NULL);
+	h = nf_conntrack_find_get(&tuple);
 	if (!h)
 		return -ENOENT;
 
@@ -856,23 +856,23 @@
 		return 0;
 	}
 
-	if (!help) {
-		/* FIXME: we need to reallocate and rehash */
-		return -EBUSY;
-	}
-
 	helper = __nf_conntrack_helper_find_byname(helpname);
 	if (helper == NULL)
 		return -EINVAL;
 
-	if (help->helper == helper)
-		return 0;
+	if (help) {
+		if (help->helper == helper)
+			return 0;
+		if (help->helper)
+			return -EBUSY;
+		/* need to zero data of old helper */
+		memset(&help->help, 0, sizeof(help->help));
+	} else {
+		help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
+		if (help == NULL)
+			return -ENOMEM;
+	}
 
-	if (help->helper)
-		return -EBUSY;
-
-	/* need to zero data of old helper */
-	memset(&help->help, 0, sizeof(help->help));
 	rcu_assign_pointer(help->helper, helper);
 
 	return 0;
@@ -957,7 +957,7 @@
 	struct nf_conn *ct;
 	int err = -EINVAL;
 	struct nf_conn_help *help;
-	struct nf_conntrack_helper *helper = NULL;
+	struct nf_conntrack_helper *helper;
 
 	ct = nf_conntrack_alloc(otuple, rtuple);
 	if (ct == NULL || IS_ERR(ct))
@@ -987,9 +987,14 @@
 		ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
 #endif
 
-	help = nfct_help(ct);
-	if (help) {
-		helper = nf_ct_helper_find_get(rtuple);
+	helper = nf_ct_helper_find_get(rtuple);
+	if (helper) {
+		help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
+		if (help == NULL) {
+			nf_ct_helper_put(helper);
+			err = -ENOMEM;
+			goto err;
+		}
 		/* not in hash table yet so not strictly necessary */
 		rcu_assign_pointer(help->helper, helper);
 	}
@@ -1089,22 +1094,29 @@
 static inline int
 ctnetlink_exp_dump_mask(struct sk_buff *skb,
 			const struct nf_conntrack_tuple *tuple,
-			const struct nf_conntrack_tuple *mask)
+			const struct nf_conntrack_tuple_mask *mask)
 {
 	int ret;
 	struct nf_conntrack_l3proto *l3proto;
 	struct nf_conntrack_l4proto *l4proto;
-	struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
+	struct nf_conntrack_tuple m;
+	struct nfattr *nest_parms;
+
+	memset(&m, 0xFF, sizeof(m));
+	m.src.u.all = mask->src.u.all;
+	memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3));
+
+	nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
 
 	l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
-	ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto);
+	ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto);
 	nf_ct_l3proto_put(l3proto);
 
 	if (unlikely(ret < 0))
 		goto nfattr_failure;
 
 	l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
-	ret = ctnetlink_dump_tuples_proto(skb, mask, l4proto);
+	ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto);
 	nf_ct_l4proto_put(l4proto);
 	if (unlikely(ret < 0))
 		goto nfattr_failure;
@@ -1223,32 +1235,52 @@
 	return NOTIFY_DONE;
 }
 #endif
+static int ctnetlink_exp_done(struct netlink_callback *cb)
+{
+	if (cb->args[1])
+		nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]);
+	return 0;
+}
 
 static int
 ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	struct nf_conntrack_expect *exp = NULL;
-	struct list_head *i;
-	u_int32_t *id = (u_int32_t *) &cb->args[0];
+	struct nf_conntrack_expect *exp, *last;
 	struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
+	struct hlist_node *n;
 	u_int8_t l3proto = nfmsg->nfgen_family;
 
 	read_lock_bh(&nf_conntrack_lock);
-	list_for_each_prev(i, &nf_conntrack_expect_list) {
-		exp = (struct nf_conntrack_expect *) i;
-		if (l3proto && exp->tuple.src.l3num != l3proto)
-			continue;
-		if (exp->id <= *id)
-			continue;
-		if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
-					    cb->nlh->nlmsg_seq,
-					    IPCTNL_MSG_EXP_NEW,
-					    1, exp) < 0)
-			goto out;
-		*id = exp->id;
+	last = (struct nf_conntrack_expect *)cb->args[1];
+	for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) {
+restart:
+		hlist_for_each_entry(exp, n, &nf_ct_expect_hash[cb->args[0]],
+				     hnode) {
+			if (l3proto && exp->tuple.src.l3num != l3proto)
+				continue;
+			if (cb->args[1]) {
+				if (exp != last)
+					continue;
+				cb->args[1] = 0;
+			}
+			if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
+						    cb->nlh->nlmsg_seq,
+						    IPCTNL_MSG_EXP_NEW,
+						    1, exp) < 0) {
+				atomic_inc(&exp->use);
+				cb->args[1] = (unsigned long)exp;
+				goto out;
+			}
+		}
+		if (cb->args[1]) {
+			cb->args[1] = 0;
+			goto restart;
+		}
 	}
 out:
 	read_unlock_bh(&nf_conntrack_lock);
+	if (last)
+		nf_ct_expect_put(last);
 
 	return skb->len;
 }
@@ -1275,7 +1307,7 @@
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		return netlink_dump_start(ctnl, skb, nlh,
 					  ctnetlink_exp_dump_table,
-					  ctnetlink_done);
+					  ctnetlink_exp_done);
 	}
 
 	if (cda[CTA_EXPECT_MASTER-1])
@@ -1286,14 +1318,14 @@
 	if (err < 0)
 		return err;
 
-	exp = nf_conntrack_expect_find_get(&tuple);
+	exp = nf_ct_expect_find_get(&tuple);
 	if (!exp)
 		return -ENOENT;
 
 	if (cda[CTA_EXPECT_ID-1]) {
 		__be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
 		if (exp->id != ntohl(id)) {
-			nf_conntrack_expect_put(exp);
+			nf_ct_expect_put(exp);
 			return -ENOENT;
 		}
 	}
@@ -1309,14 +1341,14 @@
 	if (err <= 0)
 		goto free;
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
 
 free:
 	kfree_skb(skb2);
 out:
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 	return err;
 }
 
@@ -1324,11 +1356,13 @@
 ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
 		     struct nlmsghdr *nlh, struct nfattr *cda[])
 {
-	struct nf_conntrack_expect *exp, *tmp;
+	struct nf_conntrack_expect *exp;
 	struct nf_conntrack_tuple tuple;
 	struct nf_conntrack_helper *h;
 	struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+	struct hlist_node *n, *next;
 	u_int8_t u3 = nfmsg->nfgen_family;
+	unsigned int i;
 	int err;
 
 	if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
@@ -1341,25 +1375,26 @@
 			return err;
 
 		/* bump usage count to 2 */
-		exp = nf_conntrack_expect_find_get(&tuple);
+		exp = nf_ct_expect_find_get(&tuple);
 		if (!exp)
 			return -ENOENT;
 
 		if (cda[CTA_EXPECT_ID-1]) {
 			__be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
 			if (exp->id != ntohl(id)) {
-				nf_conntrack_expect_put(exp);
+				nf_ct_expect_put(exp);
 				return -ENOENT;
 			}
 		}
 
 		/* after list removal, usage count == 1 */
-		nf_conntrack_unexpect_related(exp);
+		nf_ct_unexpect_related(exp);
 		/* have to put what we 'get' above.
 		 * after this line usage count == 0 */
-		nf_conntrack_expect_put(exp);
+		nf_ct_expect_put(exp);
 	} else if (cda[CTA_EXPECT_HELP_NAME-1]) {
 		char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]);
+		struct nf_conn_help *m_help;
 
 		/* delete all expectations for this helper */
 		write_lock_bh(&nf_conntrack_lock);
@@ -1368,24 +1403,30 @@
 			write_unlock_bh(&nf_conntrack_lock);
 			return -EINVAL;
 		}
-		list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
-					 list) {
-			struct nf_conn_help *m_help = nfct_help(exp->master);
-			if (m_help->helper == h
-			    && del_timer(&exp->timeout)) {
-				nf_ct_unlink_expect(exp);
-				nf_conntrack_expect_put(exp);
+		for (i = 0; i < nf_ct_expect_hsize; i++) {
+			hlist_for_each_entry_safe(exp, n, next,
+						  &nf_ct_expect_hash[i],
+						  hnode) {
+				m_help = nfct_help(exp->master);
+				if (m_help->helper == h
+				    && del_timer(&exp->timeout)) {
+					nf_ct_unlink_expect(exp);
+					nf_ct_expect_put(exp);
+				}
 			}
 		}
 		write_unlock_bh(&nf_conntrack_lock);
 	} else {
 		/* This basically means we have to flush everything*/
 		write_lock_bh(&nf_conntrack_lock);
-		list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
-					 list) {
-			if (del_timer(&exp->timeout)) {
-				nf_ct_unlink_expect(exp);
-				nf_conntrack_expect_put(exp);
+		for (i = 0; i < nf_ct_expect_hsize; i++) {
+			hlist_for_each_entry_safe(exp, n, next,
+						  &nf_ct_expect_hash[i],
+						  hnode) {
+				if (del_timer(&exp->timeout)) {
+					nf_ct_unlink_expect(exp);
+					nf_ct_expect_put(exp);
+				}
 			}
 		}
 		write_unlock_bh(&nf_conntrack_lock);
@@ -1421,7 +1462,7 @@
 		return err;
 
 	/* Look for master conntrack of this expectation */
-	h = nf_conntrack_find_get(&master_tuple, NULL);
+	h = nf_conntrack_find_get(&master_tuple);
 	if (!h)
 		return -ENOENT;
 	ct = nf_ct_tuplehash_to_ctrack(h);
@@ -1433,7 +1474,7 @@
 		goto out;
 	}
 
-	exp = nf_conntrack_expect_alloc(ct);
+	exp = nf_ct_expect_alloc(ct);
 	if (!exp) {
 		err = -ENOMEM;
 		goto out;
@@ -1444,10 +1485,11 @@
 	exp->master = ct;
 	exp->helper = NULL;
 	memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
-	memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple));
+	memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3));
+	exp->mask.src.u.all = mask.src.u.all;
 
-	err = nf_conntrack_expect_related(exp);
-	nf_conntrack_expect_put(exp);
+	err = nf_ct_expect_related(exp);
+	nf_ct_expect_put(exp);
 
 out:
 	nf_ct_put(nf_ct_tuplehash_to_ctrack(h));
@@ -1477,7 +1519,7 @@
 		return err;
 
 	write_lock_bh(&nf_conntrack_lock);
-	exp = __nf_conntrack_expect_find(&tuple);
+	exp = __nf_ct_expect_find(&tuple);
 
 	if (!exp) {
 		write_unlock_bh(&nf_conntrack_lock);
@@ -1567,7 +1609,7 @@
 		goto err_unreg_exp_subsys;
 	}
 
-	ret = nf_conntrack_expect_register_notifier(&ctnl_notifier_exp);
+	ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp);
 	if (ret < 0) {
 		printk("ctnetlink_init: cannot expect register notifier.\n");
 		goto err_unreg_notifier;
@@ -1593,7 +1635,7 @@
 	printk("ctnetlink: unregistering from nfnetlink.\n");
 
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
-	nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
+	nf_ct_expect_unregister_notifier(&ctnl_notifier_exp);
 	nf_conntrack_unregister_notifier(&ctnl_notifier);
 #endif
 
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 115bcb5..b080419 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -65,7 +65,7 @@
 			     struct nf_conntrack_expect *exp) __read_mostly;
 EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn);
 
-#if 0
+#ifdef DEBUG
 /* PptpControlMessageType names */
 const char *pptp_msg_name[] = {
 	"UNKNOWN_MESSAGE",
@@ -86,9 +86,6 @@
 	"SET_LINK_INFO"
 };
 EXPORT_SYMBOL(pptp_msg_name);
-#define DEBUGP(format, args...)	printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
-#else
-#define DEBUGP(format, args...)
 #endif
 
 #define SECS *HZ
@@ -102,7 +99,7 @@
 			 struct nf_conntrack_expect *exp)
 {
 	typeof(nf_nat_pptp_hook_expectfn) nf_nat_pptp_expectfn;
-	DEBUGP("increasing timeouts\n");
+	pr_debug("increasing timeouts\n");
 
 	/* increase timeout of GRE data channel conntrack entry */
 	ct->proto.gre.timeout	     = PPTP_GRE_TIMEOUT;
@@ -121,17 +118,17 @@
 
 		/* obviously this tuple inversion only works until you do NAT */
 		nf_ct_invert_tuplepr(&inv_t, &exp->tuple);
-		DEBUGP("trying to unexpect other dir: ");
+		pr_debug("trying to unexpect other dir: ");
 		NF_CT_DUMP_TUPLE(&inv_t);
 
-		exp_other = nf_conntrack_expect_find_get(&inv_t);
+		exp_other = nf_ct_expect_find_get(&inv_t);
 		if (exp_other) {
 			/* delete other expectation.  */
-			DEBUGP("found\n");
-			nf_conntrack_unexpect_related(exp_other);
-			nf_conntrack_expect_put(exp_other);
+			pr_debug("found\n");
+			nf_ct_unexpect_related(exp_other);
+			nf_ct_expect_put(exp_other);
 		} else {
-			DEBUGP("not found\n");
+			pr_debug("not found\n");
 		}
 	}
 	rcu_read_unlock();
@@ -143,13 +140,13 @@
 	struct nf_conntrack_expect *exp;
 	struct nf_conn *sibling;
 
-	DEBUGP("trying to timeout ct or exp for tuple ");
+	pr_debug("trying to timeout ct or exp for tuple ");
 	NF_CT_DUMP_TUPLE(t);
 
-	h = nf_conntrack_find_get(t, NULL);
+	h = nf_conntrack_find_get(t);
 	if (h)  {
 		sibling = nf_ct_tuplehash_to_ctrack(h);
-		DEBUGP("setting timeout of conntrack %p to 0\n", sibling);
+		pr_debug("setting timeout of conntrack %p to 0\n", sibling);
 		sibling->proto.gre.timeout	  = 0;
 		sibling->proto.gre.stream_timeout = 0;
 		if (del_timer(&sibling->timeout))
@@ -157,11 +154,11 @@
 		nf_ct_put(sibling);
 		return 1;
 	} else {
-		exp = nf_conntrack_expect_find_get(t);
+		exp = nf_ct_expect_find_get(t);
 		if (exp) {
-			DEBUGP("unexpect_related of expect %p\n", exp);
-			nf_conntrack_unexpect_related(exp);
-			nf_conntrack_expect_put(exp);
+			pr_debug("unexpect_related of expect %p\n", exp);
+			nf_ct_unexpect_related(exp);
+			nf_ct_expect_put(exp);
 			return 1;
 		}
 	}
@@ -182,7 +179,7 @@
 	t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id;
 	t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id;
 	if (!destroy_sibling_or_exp(&t))
-		DEBUGP("failed to timeout original pns->pac ct/exp\n");
+		pr_debug("failed to timeout original pns->pac ct/exp\n");
 
 	/* try reply (pac->pns) tuple */
 	memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
@@ -190,7 +187,7 @@
 	t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id;
 	t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id;
 	if (!destroy_sibling_or_exp(&t))
-		DEBUGP("failed to timeout reply pac->pns ct/exp\n");
+		pr_debug("failed to timeout reply pac->pns ct/exp\n");
 }
 
 /* expect GRE connections (PNS->PAC and PAC->PNS direction) */
@@ -201,36 +198,36 @@
 	int ret = 1;
 	typeof(nf_nat_pptp_hook_exp_gre) nf_nat_pptp_exp_gre;
 
-	exp_orig = nf_conntrack_expect_alloc(ct);
+	exp_orig = nf_ct_expect_alloc(ct);
 	if (exp_orig == NULL)
 		goto out;
 
-	exp_reply = nf_conntrack_expect_alloc(ct);
+	exp_reply = nf_ct_expect_alloc(ct);
 	if (exp_reply == NULL)
 		goto out_put_orig;
 
 	/* original direction, PNS->PAC */
 	dir = IP_CT_DIR_ORIGINAL;
-	nf_conntrack_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num,
-				 &ct->tuplehash[dir].tuple.src.u3,
-				 &ct->tuplehash[dir].tuple.dst.u3,
-				 IPPROTO_GRE, &peer_callid, &callid);
+	nf_ct_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num,
+			  &ct->tuplehash[dir].tuple.src.u3,
+			  &ct->tuplehash[dir].tuple.dst.u3,
+			  IPPROTO_GRE, &peer_callid, &callid);
 	exp_orig->expectfn = pptp_expectfn;
 
 	/* reply direction, PAC->PNS */
 	dir = IP_CT_DIR_REPLY;
-	nf_conntrack_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num,
-				 &ct->tuplehash[dir].tuple.src.u3,
-				 &ct->tuplehash[dir].tuple.dst.u3,
-				 IPPROTO_GRE, &callid, &peer_callid);
+	nf_ct_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num,
+			  &ct->tuplehash[dir].tuple.src.u3,
+			  &ct->tuplehash[dir].tuple.dst.u3,
+			  IPPROTO_GRE, &callid, &peer_callid);
 	exp_reply->expectfn = pptp_expectfn;
 
 	nf_nat_pptp_exp_gre = rcu_dereference(nf_nat_pptp_hook_exp_gre);
 	if (nf_nat_pptp_exp_gre && ct->status & IPS_NAT_MASK)
 		nf_nat_pptp_exp_gre(exp_orig, exp_reply);
-	if (nf_conntrack_expect_related(exp_orig) != 0)
+	if (nf_ct_expect_related(exp_orig) != 0)
 		goto out_put_both;
-	if (nf_conntrack_expect_related(exp_reply) != 0)
+	if (nf_ct_expect_related(exp_reply) != 0)
 		goto out_unexpect_orig;
 
 	/* Add GRE keymap entries */
@@ -243,16 +240,16 @@
 	ret = 0;
 
 out_put_both:
-	nf_conntrack_expect_put(exp_reply);
+	nf_ct_expect_put(exp_reply);
 out_put_orig:
-	nf_conntrack_expect_put(exp_orig);
+	nf_ct_expect_put(exp_orig);
 out:
 	return ret;
 
 out_unexpect_both:
-	nf_conntrack_unexpect_related(exp_reply);
+	nf_ct_unexpect_related(exp_reply);
 out_unexpect_orig:
-	nf_conntrack_unexpect_related(exp_orig);
+	nf_ct_unexpect_related(exp_orig);
 	goto out_put_both;
 }
 
@@ -270,7 +267,7 @@
 	typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound;
 
 	msg = ntohs(ctlh->messageType);
-	DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
+	pr_debug("inbound control message %s\n", pptp_msg_name[msg]);
 
 	switch (msg) {
 	case PPTP_START_SESSION_REPLY:
@@ -305,8 +302,8 @@
 		pcid = pptpReq->ocack.peersCallID;
 		if (info->pns_call_id != pcid)
 			goto invalid;
-		DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
-			ntohs(cid), ntohs(pcid));
+		pr_debug("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
+			 ntohs(cid), ntohs(pcid));
 
 		if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) {
 			info->cstate = PPTP_CALL_OUT_CONF;
@@ -322,7 +319,7 @@
 			goto invalid;
 
 		cid = pptpReq->icreq.callID;
-		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+		pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
 		info->cstate = PPTP_CALL_IN_REQ;
 		info->pac_call_id = cid;
 		break;
@@ -341,7 +338,7 @@
 		if (info->pns_call_id != pcid)
 			goto invalid;
 
-		DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid));
+		pr_debug("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid));
 		info->cstate = PPTP_CALL_IN_CONF;
 
 		/* we expect a GRE connection from PAC to PNS */
@@ -351,7 +348,7 @@
 	case PPTP_CALL_DISCONNECT_NOTIFY:
 		/* server confirms disconnect */
 		cid = pptpReq->disc.callID;
-		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+		pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
 		info->cstate = PPTP_CALL_NONE;
 
 		/* untrack this call id, unexpect GRE packets */
@@ -374,11 +371,11 @@
 	return NF_ACCEPT;
 
 invalid:
-	DEBUGP("invalid %s: type=%d cid=%u pcid=%u "
-	       "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
-	       msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
-	       msg, ntohs(cid), ntohs(pcid),  info->cstate, info->sstate,
-	       ntohs(info->pns_call_id), ntohs(info->pac_call_id));
+	pr_debug("invalid %s: type=%d cid=%u pcid=%u "
+		 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
+		 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
+		 msg, ntohs(cid), ntohs(pcid),  info->cstate, info->sstate,
+		 ntohs(info->pns_call_id), ntohs(info->pac_call_id));
 	return NF_ACCEPT;
 }
 
@@ -396,7 +393,7 @@
 	typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound;
 
 	msg = ntohs(ctlh->messageType);
-	DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
+	pr_debug("outbound control message %s\n", pptp_msg_name[msg]);
 
 	switch (msg) {
 	case PPTP_START_SESSION_REQUEST:
@@ -418,7 +415,7 @@
 		info->cstate = PPTP_CALL_OUT_REQ;
 		/* track PNS call id */
 		cid = pptpReq->ocreq.callID;
-		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+		pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
 		info->pns_call_id = cid;
 		break;
 
@@ -432,8 +429,8 @@
 		pcid = pptpReq->icack.peersCallID;
 		if (info->pac_call_id != pcid)
 			goto invalid;
-		DEBUGP("%s, CID=%X PCID=%X\n", pptp_msg_name[msg],
-		       ntohs(cid), ntohs(pcid));
+		pr_debug("%s, CID=%X PCID=%X\n", pptp_msg_name[msg],
+			 ntohs(cid), ntohs(pcid));
 
 		if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) {
 			/* part two of the three-way handshake */
@@ -469,11 +466,11 @@
 	return NF_ACCEPT;
 
 invalid:
-	DEBUGP("invalid %s: type=%d cid=%u pcid=%u "
-	       "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
-	       msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
-	       msg, ntohs(cid), ntohs(pcid),  info->cstate, info->sstate,
-	       ntohs(info->pns_call_id), ntohs(info->pac_call_id));
+	pr_debug("invalid %s: type=%d cid=%u pcid=%u "
+		 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
+		 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
+		 msg, ntohs(cid), ntohs(pcid),  info->cstate, info->sstate,
+		 ntohs(info->pns_call_id), ntohs(info->pac_call_id));
 	return NF_ACCEPT;
 }
 
@@ -524,7 +521,7 @@
 
 	pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
 	if (!pptph) {
-		DEBUGP("no full PPTP header, can't track\n");
+		pr_debug("no full PPTP header, can't track\n");
 		return NF_ACCEPT;
 	}
 	nexthdr_off += sizeof(_pptph);
@@ -533,7 +530,7 @@
 	/* if it's not a control message we can't do anything with it */
 	if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
 	    ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
-		DEBUGP("not a control packet\n");
+		pr_debug("not a control packet\n");
 		return NF_ACCEPT;
 	}
 
@@ -569,8 +566,8 @@
 		/* server -> client (PAC -> PNS) */
 		ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
 				       ctinfo);
-	DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
-		oldsstate, info->sstate, oldcstate, info->cstate);
+	pr_debug("sstate: %d->%d, cstate: %d->%d\n",
+		 oldsstate, info->sstate, oldcstate, info->cstate);
 	spin_unlock_bh(&nf_pptp_lock);
 
 	return ret;
@@ -585,9 +582,6 @@
 	.tuple.src.l3num	= AF_INET,
 	.tuple.src.u.tcp.port	= __constant_htons(PPTP_CONTROL_PORT),
 	.tuple.dst.protonum	= IPPROTO_TCP,
-	.mask.src.l3num		= 0xffff,
-	.mask.src.u.tcp.port	= __constant_htons(0xffff),
-	.mask.dst.protonum	= 0xff,
 	.help			= conntrack_pptp_help,
 	.destroy		= pptp_destroy_siblings,
 };
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 339c397..771c4c2 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -40,12 +40,6 @@
 #define GRE_TIMEOUT		(30 * HZ)
 #define GRE_STREAM_TIMEOUT	(180 * HZ)
 
-#if 0
-#define DEBUGP(format, args...)	printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
 static DEFINE_RWLOCK(nf_ct_gre_lock);
 static LIST_HEAD(gre_keymap_list);
 
@@ -87,7 +81,7 @@
 	}
 	read_unlock_bh(&nf_ct_gre_lock);
 
-	DEBUGP("lookup src key 0x%x for ", key);
+	pr_debug("lookup src key 0x%x for ", key);
 	NF_CT_DUMP_TUPLE(t);
 
 	return key;
@@ -107,8 +101,8 @@
 			if (gre_key_cmpfn(km, t) && km == *kmp)
 				return 0;
 		}
-		DEBUGP("trying to override keymap_%s for ct %p\n",
-			dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
+		pr_debug("trying to override keymap_%s for ct %p\n",
+			 dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
 		return -EEXIST;
 	}
 
@@ -118,7 +112,7 @@
 	memcpy(&km->tuple, t, sizeof(*t));
 	*kmp = km;
 
-	DEBUGP("adding new entry %p: ", km);
+	pr_debug("adding new entry %p: ", km);
 	NF_CT_DUMP_TUPLE(&km->tuple);
 
 	write_lock_bh(&nf_ct_gre_lock);
@@ -135,13 +129,13 @@
 	struct nf_conn_help *help = nfct_help(ct);
 	enum ip_conntrack_dir dir;
 
-	DEBUGP("entering for ct %p\n", ct);
+	pr_debug("entering for ct %p\n", ct);
 
 	write_lock_bh(&nf_ct_gre_lock);
 	for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) {
 		if (help->help.ct_pptp_info.keymap[dir]) {
-			DEBUGP("removing %p from list\n",
-				help->help.ct_pptp_info.keymap[dir]);
+			pr_debug("removing %p from list\n",
+				 help->help.ct_pptp_info.keymap[dir]);
 			list_del(&help->help.ct_pptp_info.keymap[dir]->list);
 			kfree(help->help.ct_pptp_info.keymap[dir]);
 			help->help.ct_pptp_info.keymap[dir] = NULL;
@@ -186,7 +180,7 @@
 		return 1;
 
 	if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
-		DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
+		pr_debug("GRE_VERSION_PPTP but unknown proto\n");
 		return 0;
 	}
 
@@ -242,7 +236,7 @@
 static int gre_new(struct nf_conn *ct, const struct sk_buff *skb,
 		   unsigned int dataoff)
 {
-	DEBUGP(": ");
+	pr_debug(": ");
 	NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 
 	/* initialize to sane value.  Ideally a conntrack helper
@@ -258,10 +252,10 @@
 static void gre_destroy(struct nf_conn *ct)
 {
 	struct nf_conn *master = ct->master;
-	DEBUGP(" entering\n");
+	pr_debug(" entering\n");
 
 	if (!master)
-		DEBUGP("no master !?!\n");
+		pr_debug("no master !?!\n");
 	else
 		nf_ct_gre_keymap_destroy(master);
 }
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 0d3254b..debfe61 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -25,12 +25,6 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 
-#if 0
-#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Protects conntrack->proto.sctp */
 static DEFINE_RWLOCK(sctp_lock);
 
@@ -151,9 +145,6 @@
 {
 	sctp_sctphdr_t _hdr, *hp;
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	/* Actually only need first 8 bytes. */
 	hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
 	if (hp == NULL)
@@ -167,9 +158,6 @@
 static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
 			     const struct nf_conntrack_tuple *orig)
 {
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	tuple->src.u.sctp.port = orig->dst.u.sctp.port;
 	tuple->dst.u.sctp.port = orig->src.u.sctp.port;
 	return 1;
@@ -179,9 +167,6 @@
 static int sctp_print_tuple(struct seq_file *s,
 			    const struct nf_conntrack_tuple *tuple)
 {
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	return seq_printf(s, "sport=%hu dport=%hu ",
 			  ntohs(tuple->src.u.sctp.port),
 			  ntohs(tuple->dst.u.sctp.port));
@@ -193,9 +178,6 @@
 {
 	enum sctp_conntrack state;
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	read_lock_bh(&sctp_lock);
 	state = conntrack->proto.sctp.state;
 	read_unlock_bh(&sctp_lock);
@@ -219,13 +201,10 @@
 	sctp_chunkhdr_t _sch, *sch;
 	int flag;
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	flag = 0;
 
 	for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
-		DEBUGP("Chunk Num: %d  Type: %d\n", count, sch->type);
+		pr_debug("Chunk Num: %d  Type: %d\n", count, sch->type);
 
 		if (sch->type == SCTP_CID_INIT
 			|| sch->type == SCTP_CID_INIT_ACK
@@ -242,7 +221,7 @@
 			|| sch->type == SCTP_CID_COOKIE_ECHO
 			|| flag)
 		      && count !=0) || !sch->length) {
-			DEBUGP("Basic checks failed\n");
+			pr_debug("Basic checks failed\n");
 			return 1;
 		}
 
@@ -251,7 +230,7 @@
 		}
 	}
 
-	DEBUGP("Basic checks passed\n");
+	pr_debug("Basic checks passed\n");
 	return count == 0;
 }
 
@@ -261,50 +240,47 @@
 {
 	int i;
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
-	DEBUGP("Chunk type: %d\n", chunk_type);
+	pr_debug("Chunk type: %d\n", chunk_type);
 
 	switch (chunk_type) {
 		case SCTP_CID_INIT:
-			DEBUGP("SCTP_CID_INIT\n");
+			pr_debug("SCTP_CID_INIT\n");
 			i = 0; break;
 		case SCTP_CID_INIT_ACK:
-			DEBUGP("SCTP_CID_INIT_ACK\n");
+			pr_debug("SCTP_CID_INIT_ACK\n");
 			i = 1; break;
 		case SCTP_CID_ABORT:
-			DEBUGP("SCTP_CID_ABORT\n");
+			pr_debug("SCTP_CID_ABORT\n");
 			i = 2; break;
 		case SCTP_CID_SHUTDOWN:
-			DEBUGP("SCTP_CID_SHUTDOWN\n");
+			pr_debug("SCTP_CID_SHUTDOWN\n");
 			i = 3; break;
 		case SCTP_CID_SHUTDOWN_ACK:
-			DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
+			pr_debug("SCTP_CID_SHUTDOWN_ACK\n");
 			i = 4; break;
 		case SCTP_CID_ERROR:
-			DEBUGP("SCTP_CID_ERROR\n");
+			pr_debug("SCTP_CID_ERROR\n");
 			i = 5; break;
 		case SCTP_CID_COOKIE_ECHO:
-			DEBUGP("SCTP_CID_COOKIE_ECHO\n");
+			pr_debug("SCTP_CID_COOKIE_ECHO\n");
 			i = 6; break;
 		case SCTP_CID_COOKIE_ACK:
-			DEBUGP("SCTP_CID_COOKIE_ACK\n");
+			pr_debug("SCTP_CID_COOKIE_ACK\n");
 			i = 7; break;
 		case SCTP_CID_SHUTDOWN_COMPLETE:
-			DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
+			pr_debug("SCTP_CID_SHUTDOWN_COMPLETE\n");
 			i = 8; break;
 		default:
 			/* Other chunks like DATA, SACK, HEARTBEAT and
 			its ACK do not cause a change in state */
-			DEBUGP("Unknown chunk type, Will stay in %s\n",
-						sctp_conntrack_names[cur_state]);
+			pr_debug("Unknown chunk type, Will stay in %s\n",
+				 sctp_conntrack_names[cur_state]);
 			return cur_state;
 	}
 
-	DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n",
-			dir, sctp_conntrack_names[cur_state], chunk_type,
-			sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
+	pr_debug("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n",
+		 dir, sctp_conntrack_names[cur_state], chunk_type,
+		 sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
 
 	return sctp_conntracks[dir][i][cur_state];
 }
@@ -323,9 +299,6 @@
 	u_int32_t offset, count;
 	char map[256 / sizeof (char)] = {0};
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
 	if (sh == NULL)
 		return -1;
@@ -340,7 +313,7 @@
 		&& !test_bit(SCTP_CID_ABORT, (void *)map)
 		&& !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
 		&& (sh->vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
-		DEBUGP("Verification tag check failed\n");
+		pr_debug("Verification tag check failed\n");
 		return -1;
 	}
 
@@ -385,8 +358,9 @@
 
 		/* Invalid */
 		if (newconntrack == SCTP_CONNTRACK_MAX) {
-			DEBUGP("nf_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
-			       CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
+			pr_debug("nf_conntrack_sctp: Invalid dir=%i ctype=%u "
+				 "conntrack=%u\n",
+				 CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
 			write_unlock_bh(&sctp_lock);
 			return -1;
 		}
@@ -402,8 +376,8 @@
 					write_unlock_bh(&sctp_lock);
 					return -1;
 			}
-			DEBUGP("Setting vtag %x for dir %d\n",
-					ih->init_tag, !CTINFO2DIR(ctinfo));
+			pr_debug("Setting vtag %x for dir %d\n",
+				 ih->init_tag, !CTINFO2DIR(ctinfo));
 			conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag;
 		}
 
@@ -418,7 +392,7 @@
 	if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
 		&& CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
 		&& newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
-		DEBUGP("Setting assured bit\n");
+		pr_debug("Setting assured bit\n");
 		set_bit(IPS_ASSURED_BIT, &conntrack->status);
 		nf_conntrack_event_cache(IPCT_STATUS, skb);
 	}
@@ -436,9 +410,6 @@
 	u_int32_t offset, count;
 	char map[256 / sizeof (char)] = {0};
 
-	DEBUGP(__FUNCTION__);
-	DEBUGP("\n");
-
 	sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
 	if (sh == NULL)
 		return 0;
@@ -460,8 +431,9 @@
 					 SCTP_CONNTRACK_NONE, sch->type);
 
 		/* Invalid: delete conntrack */
-		if (newconntrack == SCTP_CONNTRACK_MAX) {
-			DEBUGP("nf_conntrack_sctp: invalid new deleting.\n");
+		if (newconntrack == SCTP_CONNTRACK_NONE ||
+		    newconntrack == SCTP_CONNTRACK_MAX) {
+			pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
 			return 0;
 		}
 
@@ -475,8 +447,8 @@
 				if (ih == NULL)
 					return 0;
 
-				DEBUGP("Setting vtag %x for new conn\n",
-					ih->init_tag);
+				pr_debug("Setting vtag %x for new conn\n",
+					 ih->init_tag);
 
 				conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
 								ih->init_tag;
@@ -488,8 +460,8 @@
 		/* If it is a shutdown ack OOTB packet, we expect a return
 		   shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
 		else {
-			DEBUGP("Setting vtag %x for new conn OOTB\n",
-				sh->vtag);
+			pr_debug("Setting vtag %x for new conn OOTB\n",
+				 sh->vtag);
 			conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
 		}
 
@@ -688,8 +660,6 @@
  cleanup_sctp4:
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
  out:
-	DEBUGP("SCTP conntrack module loading %s\n",
-					ret ? "failed": "succeeded");
 	return ret;
 }
 
@@ -697,7 +667,6 @@
 {
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
 	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
-	DEBUGP("SCTP conntrack module unloaded\n");
 }
 
 module_init(nf_conntrack_proto_sctp_init);
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index ccdd5d2..1c8206e 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -26,13 +26,6 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 
-#if 0
-#define DEBUGP printk
-#define DEBUGP_VARS
-#else
-#define DEBUGP(format, args...)
-#endif
-
 /* Protects conntrack->proto.tcp */
 static DEFINE_RWLOCK(tcp_lock);
 
@@ -496,7 +489,8 @@
 	}
 }
 
-static int tcp_in_window(struct ip_ct_tcp *state,
+static int tcp_in_window(struct nf_conn *ct,
+			 struct ip_ct_tcp *state,
 			 enum ip_conntrack_dir dir,
 			 unsigned int index,
 			 const struct sk_buff *skb,
@@ -506,6 +500,7 @@
 {
 	struct ip_ct_tcp_state *sender = &state->seen[dir];
 	struct ip_ct_tcp_state *receiver = &state->seen[!dir];
+	struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
 	__u32 seq, ack, sack, end, win, swin;
 	int res;
 
@@ -520,18 +515,17 @@
 	if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
 		tcp_sack(skb, dataoff, tcph, &sack);
 
-	DEBUGP("tcp_in_window: START\n");
-	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
-	       "seq=%u ack=%u sack=%u win=%u end=%u\n",
-		NIPQUAD(iph->saddr), ntohs(tcph->source),
-		NIPQUAD(iph->daddr), ntohs(tcph->dest),
-		seq, ack, sack, win, end);
-	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
-	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale,
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
-		receiver->td_scale);
+	pr_debug("tcp_in_window: START\n");
+	pr_debug("tcp_in_window: ");
+	NF_CT_DUMP_TUPLE(tuple);
+	pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n",
+		 seq, ack, sack, win, end);
+	pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		 sender->td_end, sender->td_maxend, sender->td_maxwin,
+		 sender->td_scale,
+		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		 receiver->td_scale);
 
 	if (sender->td_end == 0) {
 		/*
@@ -609,23 +603,22 @@
 		 */
 		seq = end = sender->td_end;
 
-	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
-	       "seq=%u ack=%u sack =%u win=%u end=%u\n",
-		NIPQUAD(iph->saddr), ntohs(tcph->source),
-		NIPQUAD(iph->daddr), ntohs(tcph->dest),
-		seq, ack, sack, win, end);
-	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
-	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale,
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
-		receiver->td_scale);
+	pr_debug("tcp_in_window: ");
+	NF_CT_DUMP_TUPLE(tuple);
+	pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n",
+		 seq, ack, sack, win, end);
+	pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		 sender->td_end, sender->td_maxend, sender->td_maxwin,
+		 sender->td_scale,
+		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		 receiver->td_scale);
 
-	DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
-		before(seq, sender->td_maxend + 1),
-		after(end, sender->td_end - receiver->td_maxwin - 1),
-		before(sack, receiver->td_end + 1),
-		after(ack, receiver->td_end - MAXACKWINDOW(sender)));
+	pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
+		 before(seq, sender->td_maxend + 1),
+		 after(end, sender->td_end - receiver->td_maxwin - 1),
+		 before(sack, receiver->td_end + 1),
+		 after(ack, receiver->td_end - MAXACKWINDOW(sender)));
 
 	if (before(seq, sender->td_maxend + 1) &&
 	    after(end, sender->td_end - receiver->td_maxwin - 1) &&
@@ -694,10 +687,10 @@
 			: "SEQ is over the upper bound (over the window of the receiver)");
 	}
 
-	DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
-	       "receiver end=%u maxend=%u maxwin=%u\n",
-		res, sender->td_end, sender->td_maxend, sender->td_maxwin,
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
+	pr_debug("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
+		 "receiver end=%u maxend=%u maxwin=%u\n",
+		 res, sender->td_end, sender->td_maxend, sender->td_maxwin,
+		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
 
 	return res;
 }
@@ -711,11 +704,9 @@
 			     int dir)
 {
 	struct tcphdr *tcph = (void *)skb->data + dataoff;
-	__u32 end;
-#ifdef DEBUGP_VARS
 	struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[dir];
 	struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[!dir];
-#endif
+	__u32 end;
 
 	end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph);
 
@@ -727,12 +718,12 @@
 		conntrack->proto.tcp.seen[dir].td_end = end;
 	conntrack->proto.tcp.last_end = end;
 	write_unlock_bh(&tcp_lock);
-	DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
-	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale,
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
-		receiver->td_scale);
+	pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
+		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		 sender->td_end, sender->td_maxend, sender->td_maxwin,
+		 sender->td_scale,
+		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		 receiver->td_scale);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update);
 #endif
@@ -823,6 +814,7 @@
 		      int pf,
 		      unsigned int hooknum)
 {
+	struct nf_conntrack_tuple *tuple;
 	enum tcp_conntrack new_state, old_state;
 	enum ip_conntrack_dir dir;
 	struct tcphdr *th, _tcph;
@@ -837,6 +829,7 @@
 	dir = CTINFO2DIR(ctinfo);
 	index = get_conntrack_index(th);
 	new_state = tcp_conntracks[dir][index][old_state];
+	tuple = &conntrack->tuplehash[dir].tuple;
 
 	switch (new_state) {
 	case TCP_CONNTRACK_IGNORE:
@@ -880,9 +873,8 @@
 		return NF_ACCEPT;
 	case TCP_CONNTRACK_MAX:
 		/* Invalid packet */
-		DEBUGP("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
-		       dir, get_conntrack_index(th),
-		       old_state);
+		pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
+			 dir, get_conntrack_index(th), old_state);
 		write_unlock_bh(&tcp_lock);
 		if (LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
@@ -933,7 +925,7 @@
 		break;
 	}
 
-	if (!tcp_in_window(&conntrack->proto.tcp, dir, index,
+	if (!tcp_in_window(conntrack, &conntrack->proto.tcp, dir, index,
 			   skb, dataoff, th, pf)) {
 		write_unlock_bh(&tcp_lock);
 		return -NF_ACCEPT;
@@ -942,13 +934,12 @@
 	/* From now on we have got in-window packets */
 	conntrack->proto.tcp.last_index = index;
 
-	DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
-	       "syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
-		NIPQUAD(iph->saddr), ntohs(th->source),
-		NIPQUAD(iph->daddr), ntohs(th->dest),
-		(th->syn ? 1 : 0), (th->ack ? 1 : 0),
-		(th->fin ? 1 : 0), (th->rst ? 1 : 0),
-		old_state, new_state);
+	pr_debug("tcp_conntracks: ");
+	NF_CT_DUMP_TUPLE(tuple);
+	pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
+		 (th->syn ? 1 : 0), (th->ack ? 1 : 0),
+		 (th->fin ? 1 : 0), (th->rst ? 1 : 0),
+		 old_state, new_state);
 
 	conntrack->proto.tcp.state = new_state;
 	if (old_state != new_state
@@ -997,10 +988,8 @@
 {
 	enum tcp_conntrack new_state;
 	struct tcphdr *th, _tcph;
-#ifdef DEBUGP_VARS
 	struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0];
 	struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1];
-#endif
 
 	th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
 	BUG_ON(th == NULL);
@@ -1012,7 +1001,7 @@
 
 	/* Invalid: delete conntrack */
 	if (new_state >= TCP_CONNTRACK_MAX) {
-		DEBUGP("nf_ct_tcp: invalid new deleting.\n");
+		pr_debug("nf_ct_tcp: invalid new deleting.\n");
 		return 0;
 	}
 
@@ -1065,12 +1054,12 @@
 	conntrack->proto.tcp.state = TCP_CONNTRACK_NONE;
 	conntrack->proto.tcp.last_index = TCP_NONE_SET;
 
-	DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
-	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
-		sender->td_end, sender->td_maxend, sender->td_maxwin,
-		sender->td_scale,
-		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
-		receiver->td_scale);
+	pr_debug("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
+		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		 sender->td_end, sender->td_maxend, sender->td_maxwin,
+		 sender->td_scale,
+		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		 receiver->td_scale);
 	return 1;
 }
 
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
index eb2d1dc..355d371 100644
--- a/net/netfilter/nf_conntrack_sane.c
+++ b/net/netfilter/nf_conntrack_sane.c
@@ -40,12 +40,6 @@
 static unsigned int ports_c;
 module_param_array(ports, ushort, &ports_c, 0400);
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 struct sane_request {
 	__be32 RPC_code;
 #define SANE_NET_START      7   /* RPC code */
@@ -125,15 +119,15 @@
 	ct_sane_info->state = SANE_STATE_NORMAL;
 
 	if (datalen < sizeof(struct sane_reply_net_start)) {
-		DEBUGP("nf_ct_sane: NET_START reply too short\n");
+		pr_debug("nf_ct_sane: NET_START reply too short\n");
 		goto out;
 	}
 
 	reply = (struct sane_reply_net_start *)sb_ptr;
 	if (reply->status != htonl(SANE_STATUS_SUCCESS)) {
 		/* saned refused the command */
-		DEBUGP("nf_ct_sane: unsuccessful SANE_STATUS = %u\n",
-			ntohl(reply->status));
+		pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n",
+			 ntohl(reply->status));
 		goto out;
 	}
 
@@ -141,35 +135,32 @@
 	if (reply->zero != 0)
 		goto out;
 
-	exp = nf_conntrack_expect_alloc(ct);
+	exp = nf_ct_expect_alloc(ct);
 	if (exp == NULL) {
 		ret = NF_DROP;
 		goto out;
 	}
 
 	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
-	nf_conntrack_expect_init(exp, family,
-				 &tuple->src.u3, &tuple->dst.u3,
-				 IPPROTO_TCP,
-				 NULL, &reply->port);
+	nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+			  IPPROTO_TCP, NULL, &reply->port);
 
-	DEBUGP("nf_ct_sane: expect: ");
+	pr_debug("nf_ct_sane: expect: ");
 	NF_CT_DUMP_TUPLE(&exp->tuple);
-	NF_CT_DUMP_TUPLE(&exp->mask);
 
 	/* Can't expect this?  Best to drop packet now. */
-	if (nf_conntrack_expect_related(exp) != 0)
+	if (nf_ct_expect_related(exp) != 0)
 		ret = NF_DROP;
 
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 out:
 	spin_unlock_bh(&nf_sane_lock);
 	return ret;
 }
 
-static struct nf_conntrack_helper sane[MAX_PORTS][2];
-static char sane_names[MAX_PORTS][2][sizeof("sane-65535")];
+static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly;
+static char sane_names[MAX_PORTS][2][sizeof("sane-65535")] __read_mostly;
 
 /* don't make this __exit, since it's called from __init ! */
 static void nf_conntrack_sane_fini(void)
@@ -178,9 +169,9 @@
 
 	for (i = 0; i < ports_c; i++) {
 		for (j = 0; j < 2; j++) {
-			DEBUGP("nf_ct_sane: unregistering helper for pf: %d "
-			       "port: %d\n",
-				sane[i][j].tuple.src.l3num, ports[i]);
+			pr_debug("nf_ct_sane: unregistering helper for pf: %d "
+				 "port: %d\n",
+				 sane[i][j].tuple.src.l3num, ports[i]);
 			nf_conntrack_helper_unregister(&sane[i][j]);
 		}
 	}
@@ -208,8 +199,6 @@
 		for (j = 0; j < 2; j++) {
 			sane[i][j].tuple.src.u.tcp.port = htons(ports[i]);
 			sane[i][j].tuple.dst.protonum = IPPROTO_TCP;
-			sane[i][j].mask.src.u.tcp.port = 0xFFFF;
-			sane[i][j].mask.dst.protonum = 0xFF;
 			sane[i][j].max_expected = 1;
 			sane[i][j].timeout = 5 * 60;	/* 5 Minutes */
 			sane[i][j].me = THIS_MODULE;
@@ -221,9 +210,9 @@
 				sprintf(tmpname, "sane-%d", ports[i]);
 			sane[i][j].name = tmpname;
 
-			DEBUGP("nf_ct_sane: registering helper for pf: %d "
-			       "port: %d\n",
-				sane[i][j].tuple.src.l3num, ports[i]);
+			pr_debug("nf_ct_sane: registering helper for pf: %d "
+				 "port: %d\n",
+				 sane[i][j].tuple.src.l3num, ports[i]);
 			ret = nf_conntrack_helper_register(&sane[i][j]);
 			if (ret) {
 				printk(KERN_ERR "nf_ct_sane: failed to "
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 1b5c6c1..1276a44 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -21,12 +21,6 @@
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <linux/netfilter/nf_conntrack_sip.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
 MODULE_DESCRIPTION("SIP connection tracking helper");
@@ -285,7 +279,7 @@
 	const char *aux = dptr;
 
 	if (!parse_addr(ct, dptr, &dptr, &addr, limit)) {
-		DEBUGP("ip: %s parse failed.!\n", dptr);
+		pr_debug("ip: %s parse failed.!\n", dptr);
 		return 0;
 	}
 
@@ -344,8 +338,8 @@
 				    ct_sip_lnlen(dptr, limit),
 				    hnfo->case_sensitive);
 		if (!aux) {
-			DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
-			       hnfo->lname);
+			pr_debug("'%s' not found in '%s'.\n", hnfo->ln_str,
+				 hnfo->lname);
 			return -1;
 		}
 		aux += hnfo->ln_strlen;
@@ -356,11 +350,11 @@
 
 		*matchoff = (aux - k) + shift;
 
-		DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname,
-		       *matchlen);
+		pr_debug("%s match succeeded! - len: %u\n", hnfo->lname,
+			 *matchlen);
 		return 1;
 	}
-	DEBUGP("%s header not found.\n", hnfo->lname);
+	pr_debug("%s header not found.\n", hnfo->lname);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ct_sip_get_info);
@@ -378,23 +372,23 @@
 	int ret;
 	typeof(nf_nat_sdp_hook) nf_nat_sdp;
 
-	exp = nf_conntrack_expect_alloc(ct);
+	exp = nf_ct_expect_alloc(ct);
 	if (exp == NULL)
 		return NF_DROP;
-	nf_conntrack_expect_init(exp, family,
-				 &ct->tuplehash[!dir].tuple.src.u3, addr,
-				 IPPROTO_UDP, NULL, &port);
+	nf_ct_expect_init(exp, family,
+			  &ct->tuplehash[!dir].tuple.src.u3, addr,
+			  IPPROTO_UDP, NULL, &port);
 
 	nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
 	if (nf_nat_sdp && ct->status & IPS_NAT_MASK)
 		ret = nf_nat_sdp(pskb, ctinfo, exp, dptr);
 	else {
-		if (nf_conntrack_expect_related(exp) != 0)
+		if (nf_ct_expect_related(exp) != 0)
 			ret = NF_DROP;
 		else
 			ret = NF_ACCEPT;
 	}
-	nf_conntrack_expect_put(exp);
+	nf_ct_expect_put(exp);
 
 	return ret;
 }
@@ -424,7 +418,7 @@
 	if (!skb_is_nonlinear(*pskb))
 		dptr = (*pskb)->data + dataoff;
 	else {
-		DEBUGP("Copy of skbuff not supported yet.\n");
+		pr_debug("Copy of skbuff not supported yet.\n");
 		goto out;
 	}
 
@@ -506,9 +500,6 @@
 		for (j = 0; j < 2; j++) {
 			sip[i][j].tuple.dst.protonum = IPPROTO_UDP;
 			sip[i][j].tuple.src.u.udp.port = htons(ports[i]);
-			sip[i][j].mask.src.l3num = 0xFFFF;
-			sip[i][j].mask.src.u.udp.port = htons(0xFFFF);
-			sip[i][j].mask.dst.protonum = 0xFF;
 			sip[i][j].max_expected = 2;
 			sip[i][j].timeout = 3 * 60; /* 3 minutes */
 			sip[i][j].me = THIS_MODULE;
@@ -521,7 +512,7 @@
 				sprintf(tmpname, "sip-%u", i);
 			sip[i][j].name = tmpname;
 
-			DEBUGP("port #%u: %u\n", i, ports[i]);
+			pr_debug("port #%u: %u\n", i, ports[i]);
 
 			ret = nf_conntrack_helper_register(&sip[i][j]);
 			if (ret) {
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 45baeb0..ffb6ff8 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -25,12 +25,6 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_PROC_FS
@@ -60,35 +54,36 @@
 	unsigned int bucket;
 };
 
-static struct list_head *ct_get_first(struct seq_file *seq)
+static struct hlist_node *ct_get_first(struct seq_file *seq)
 {
 	struct ct_iter_state *st = seq->private;
 
 	for (st->bucket = 0;
 	     st->bucket < nf_conntrack_htable_size;
 	     st->bucket++) {
-		if (!list_empty(&nf_conntrack_hash[st->bucket]))
-			return nf_conntrack_hash[st->bucket].next;
+		if (!hlist_empty(&nf_conntrack_hash[st->bucket]))
+			return nf_conntrack_hash[st->bucket].first;
 	}
 	return NULL;
 }
 
-static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
+static struct hlist_node *ct_get_next(struct seq_file *seq,
+				      struct hlist_node *head)
 {
 	struct ct_iter_state *st = seq->private;
 
 	head = head->next;
-	while (head == &nf_conntrack_hash[st->bucket]) {
+	while (head == NULL) {
 		if (++st->bucket >= nf_conntrack_htable_size)
 			return NULL;
-		head = nf_conntrack_hash[st->bucket].next;
+		head = nf_conntrack_hash[st->bucket].first;
 	}
 	return head;
 }
 
-static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
+static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos)
 {
-	struct list_head *head = ct_get_first(seq);
+	struct hlist_node *head = ct_get_first(seq);
 
 	if (head)
 		while (pos && (head = ct_get_next(seq, head)))
@@ -190,7 +185,7 @@
 	return 0;
 }
 
-static struct seq_operations ct_seq_ops = {
+static const struct seq_operations ct_seq_ops = {
 	.start = ct_seq_start,
 	.next  = ct_seq_next,
 	.stop  = ct_seq_stop,
@@ -294,7 +289,7 @@
 	return 0;
 }
 
-static struct seq_operations ct_cpu_seq_ops = {
+static const struct seq_operations ct_cpu_seq_ops = {
 	.start	= ct_cpu_seq_start,
 	.next	= ct_cpu_seq_next,
 	.stop	= ct_cpu_seq_stop,
@@ -371,7 +366,14 @@
 		.extra1		= &log_invalid_proto_min,
 		.extra2		= &log_invalid_proto_max,
 	},
-
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "nf_conntrack_expect_max",
+		.data		= &nf_ct_expect_max,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 	{ .ctl_name = 0 }
 };
 
@@ -410,7 +412,7 @@
 static int __init nf_conntrack_standalone_init(void)
 {
 #ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+	struct proc_dir_entry *proc, *proc_stat;
 #endif
 	int ret = 0;
 
@@ -422,13 +424,9 @@
 	proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
 	if (!proc) goto cleanup_init;
 
-	proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
-					&exp_file_ops);
-	if (!proc_exp) goto cleanup_proc;
-
 	proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
 	if (!proc_stat)
-		goto cleanup_proc_exp;
+		goto cleanup_proc;
 
 	proc_stat->proc_fops = &ct_cpu_seq_fops;
 	proc_stat->owner = THIS_MODULE;
@@ -448,8 +446,6 @@
 #endif
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("nf_conntrack", proc_net_stat);
- cleanup_proc_exp:
-	proc_net_remove("nf_conntrack_expect");
  cleanup_proc:
 	proc_net_remove("nf_conntrack");
  cleanup_init:
@@ -465,7 +461,6 @@
 #endif
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("nf_conntrack", proc_net_stat);
-	proc_net_remove("nf_conntrack_expect");
 	proc_net_remove("nf_conntrack");
 #endif /* CNFIG_PROC_FS */
 	nf_conntrack_cleanup();
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
index 37c4542..cc19506 100644
--- a/net/netfilter/nf_conntrack_tftp.c
+++ b/net/netfilter/nf_conntrack_tftp.c
@@ -29,13 +29,6 @@
 module_param_array(ports, ushort, &ports_c, 0400);
 MODULE_PARM_DESC(ports, "Port numbers of TFTP servers");
 
-#if 0
-#define DEBUGP(format, args...) printk("%s:%s:" format, \
-				       __FILE__, __FUNCTION__ , ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
 unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb,
 				 enum ip_conntrack_info ctinfo,
 				 struct nf_conntrack_expect *exp) __read_mostly;
@@ -62,39 +55,35 @@
 	case TFTP_OPCODE_READ:
 	case TFTP_OPCODE_WRITE:
 		/* RRQ and WRQ works the same way */
-		DEBUGP("");
 		NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 		NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
 
-		exp = nf_conntrack_expect_alloc(ct);
+		exp = nf_ct_expect_alloc(ct);
 		if (exp == NULL)
 			return NF_DROP;
 		tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-		nf_conntrack_expect_init(exp, family,
-					 &tuple->src.u3, &tuple->dst.u3,
-					 IPPROTO_UDP,
-					 NULL, &tuple->dst.u.udp.port);
+		nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+				  IPPROTO_UDP, NULL, &tuple->dst.u.udp.port);
 
-		DEBUGP("expect: ");
+		pr_debug("expect: ");
 		NF_CT_DUMP_TUPLE(&exp->tuple);
-		NF_CT_DUMP_TUPLE(&exp->mask);
 
 		nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
 		if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
 			ret = nf_nat_tftp(pskb, ctinfo, exp);
-		else if (nf_conntrack_expect_related(exp) != 0)
+		else if (nf_ct_expect_related(exp) != 0)
 			ret = NF_DROP;
-		nf_conntrack_expect_put(exp);
+		nf_ct_expect_put(exp);
 		break;
 	case TFTP_OPCODE_DATA:
 	case TFTP_OPCODE_ACK:
-		DEBUGP("Data/ACK opcode\n");
+		pr_debug("Data/ACK opcode\n");
 		break;
 	case TFTP_OPCODE_ERROR:
-		DEBUGP("Error opcode\n");
+		pr_debug("Error opcode\n");
 		break;
 	default:
-		DEBUGP("Unknown opcode\n");
+		pr_debug("Unknown opcode\n");
 	}
 	return ret;
 }
@@ -128,9 +117,6 @@
 		for (j = 0; j < 2; j++) {
 			tftp[i][j].tuple.dst.protonum = IPPROTO_UDP;
 			tftp[i][j].tuple.src.u.udp.port = htons(ports[i]);
-			tftp[i][j].mask.src.l3num = 0xFFFF;
-			tftp[i][j].mask.dst.protonum = 0xFF;
-			tftp[i][j].mask.src.u.udp.port = htons(0xFFFF);
 			tftp[i][j].max_expected = 1;
 			tftp[i][j].timeout = 5 * 60; /* 5 minutes */
 			tftp[i][j].me = THIS_MODULE;
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 91b220c..9498579 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -140,7 +140,7 @@
 	return seq_printf(s, "%2lld %s\n", *pos, logger->name);
 }
 
-static struct seq_operations nflog_seq_ops = {
+static const struct seq_operations nflog_seq_ops = {
 	.start	= seq_start,
 	.next	= seq_next,
 	.stop	= seq_stop,
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index b1f2ace..a481a34 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -17,7 +17,7 @@
  */
 static struct nf_queue_handler *queue_handler[NPROTO];
 
-static DEFINE_RWLOCK(queue_handler_lock);
+static DEFINE_MUTEX(queue_handler_mutex);
 
 /* return EBUSY when somebody else is registered, return EEXIST if the
  * same handler is registered, return 0 in case of success. */
@@ -28,30 +28,37 @@
 	if (pf >= NPROTO)
 		return -EINVAL;
 
-	write_lock_bh(&queue_handler_lock);
+	mutex_lock(&queue_handler_mutex);
 	if (queue_handler[pf] == qh)
 		ret = -EEXIST;
 	else if (queue_handler[pf])
 		ret = -EBUSY;
 	else {
-		queue_handler[pf] = qh;
+		rcu_assign_pointer(queue_handler[pf], qh);
 		ret = 0;
 	}
-	write_unlock_bh(&queue_handler_lock);
+	mutex_unlock(&queue_handler_mutex);
 
 	return ret;
 }
 EXPORT_SYMBOL(nf_register_queue_handler);
 
 /* The caller must flush their queue before this */
-int nf_unregister_queue_handler(int pf)
+int nf_unregister_queue_handler(int pf, struct nf_queue_handler *qh)
 {
 	if (pf >= NPROTO)
 		return -EINVAL;
 
-	write_lock_bh(&queue_handler_lock);
-	queue_handler[pf] = NULL;
-	write_unlock_bh(&queue_handler_lock);
+	mutex_lock(&queue_handler_mutex);
+	if (queue_handler[pf] != qh) {
+		mutex_unlock(&queue_handler_mutex);
+		return -EINVAL;
+	}
+
+	rcu_assign_pointer(queue_handler[pf], NULL);
+	mutex_unlock(&queue_handler_mutex);
+
+	synchronize_rcu();
 
 	return 0;
 }
@@ -61,12 +68,14 @@
 {
 	int pf;
 
-	write_lock_bh(&queue_handler_lock);
+	mutex_lock(&queue_handler_mutex);
 	for (pf = 0; pf < NPROTO; pf++)  {
 		if (queue_handler[pf] == qh)
-			queue_handler[pf] = NULL;
+			rcu_assign_pointer(queue_handler[pf], NULL);
 	}
-	write_unlock_bh(&queue_handler_lock);
+	mutex_unlock(&queue_handler_mutex);
+
+	synchronize_rcu();
 }
 EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
 
@@ -89,18 +98,21 @@
 	struct net_device *physoutdev = NULL;
 #endif
 	struct nf_afinfo *afinfo;
+	struct nf_queue_handler *qh;
 
 	/* QUEUE == DROP if noone is waiting, to be safe. */
-	read_lock(&queue_handler_lock);
-	if (!queue_handler[pf]) {
-		read_unlock(&queue_handler_lock);
+	rcu_read_lock();
+
+	qh = rcu_dereference(queue_handler[pf]);
+	if (!qh) {
+		rcu_read_unlock();
 		kfree_skb(skb);
 		return 1;
 	}
 
 	afinfo = nf_get_afinfo(pf);
 	if (!afinfo) {
-		read_unlock(&queue_handler_lock);
+		rcu_read_unlock();
 		kfree_skb(skb);
 		return 1;
 	}
@@ -110,7 +122,7 @@
 		if (net_ratelimit())
 			printk(KERN_ERR "OOM queueing packet %p\n",
 			       skb);
-		read_unlock(&queue_handler_lock);
+		rcu_read_unlock();
 		kfree_skb(skb);
 		return 1;
 	}
@@ -120,7 +132,7 @@
 
 	/* If it's going away, ignore hook. */
 	if (!try_module_get(info->elem->owner)) {
-		read_unlock(&queue_handler_lock);
+		rcu_read_unlock();
 		kfree(info);
 		return 0;
 	}
@@ -138,10 +150,9 @@
 	}
 #endif
 	afinfo->saveroute(skb, info);
-	status = queue_handler[pf]->outfn(skb, info, queuenum,
-					  queue_handler[pf]->data);
+	status = qh->outfn(skb, info, queuenum, qh->data);
 
-	read_unlock(&queue_handler_lock);
+	rcu_read_unlock();
 
 	if (status < 0) {
 		/* James M doesn't say fuck enough. */
@@ -308,18 +319,18 @@
 	loff_t *pos = v;
 	struct nf_queue_handler *qh;
 
-	read_lock_bh(&queue_handler_lock);
-	qh = queue_handler[*pos];
+	rcu_read_lock();
+	qh = rcu_dereference(queue_handler[*pos]);
 	if (!qh)
 		ret = seq_printf(s, "%2lld NONE\n", *pos);
 	else
 		ret = seq_printf(s, "%2lld %s\n", *pos, qh->name);
-	read_unlock_bh(&queue_handler_lock);
+	rcu_read_unlock();
 
 	return ret;
 }
 
-static struct seq_operations nfqueue_seq_ops = {
+static const struct seq_operations nfqueue_seq_ops = {
 	.start	= seq_start,
 	.next	= seq_next,
 	.stop	= seq_stop,
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index e32e30e..e185a5b 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -962,7 +962,7 @@
 			  inst->flushtimeout, atomic_read(&inst->use));
 }
 
-static struct seq_operations nful_seq_ops = {
+static const struct seq_operations nful_seq_ops = {
 	.start	= seq_start,
 	.next	= seq_next,
 	.stop	= seq_stop,
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 7a97bec..bb65a38 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -913,9 +913,7 @@
 		case NFQNL_CFG_CMD_PF_UNBIND:
 			QDEBUG("unregistering queue handler for pf=%u\n",
 				ntohs(cmd->pf));
-			/* This is a bug and a feature.  We can unregister
-			 * other handlers(!) */
-			ret = nf_unregister_queue_handler(ntohs(cmd->pf));
+			ret = nf_unregister_queue_handler(ntohs(cmd->pf), &nfqh);
 			break;
 		default:
 			ret = -EINVAL;
@@ -1050,7 +1048,7 @@
 			  atomic_read(&inst->use));
 }
 
-static struct seq_operations nfqnl_seq_ops = {
+static const struct seq_operations nfqnl_seq_ops = {
 	.start	= seq_start,
 	.next	= seq_next,
 	.stop	= seq_stop,
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 0eb2504..cc2baa6 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -320,8 +320,8 @@
 		return -EINVAL;
 	}
 	if (match->hooks && (hook_mask & ~match->hooks) != 0) {
-		printk("%s_tables: %s match: bad hook_mask %u\n",
-		       xt_prefix[family], match->name, hook_mask);
+		printk("%s_tables: %s match: bad hook_mask %u/%u\n",
+		       xt_prefix[family], match->name, hook_mask, match->hooks);
 		return -EINVAL;
 	}
 	if (match->proto && (match->proto != proto || inv_proto)) {
@@ -410,8 +410,9 @@
 		return -EINVAL;
 	}
 	if (target->hooks && (hook_mask & ~target->hooks) != 0) {
-		printk("%s_tables: %s target: bad hook_mask %u\n",
-		       xt_prefix[family], target->name, hook_mask);
+		printk("%s_tables: %s target: bad hook_mask %u/%u\n",
+		       xt_prefix[family], target->name, hook_mask,
+		       target->hooks);
 		return -EINVAL;
 	}
 	if (target->proto && (target->proto != proto || inv_proto)) {
@@ -744,7 +745,7 @@
 		return 0;
 }
 
-static struct seq_operations xt_tgt_seq_ops = {
+static const struct seq_operations xt_tgt_seq_ops = {
 	.start	= xt_tgt_seq_start,
 	.next	= xt_tgt_seq_next,
 	.stop	= xt_tgt_seq_stop,
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 3088483..5194285 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -39,7 +39,7 @@
 	return XT_CONTINUE;
 }
 
-static struct xt_target xt_classify_target[] = {
+static struct xt_target xt_classify_target[] __read_mostly = {
 	{
 		.family		= AF_INET,
 		.name 		= "CLASSIFY",
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index b03ce00..5a00c54 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -76,33 +76,33 @@
 	return XT_CONTINUE;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *entry,
 	   const struct xt_target *target,
 	   void *targinfo,
 	   unsigned int hook_mask)
 {
-	struct xt_connmark_target_info *matchinfo = targinfo;
+	const struct xt_connmark_target_info *matchinfo = targinfo;
 
 	if (nf_ct_l3proto_try_module_get(target->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", target->family);
-		return 0;
+		return false;
 	}
 	if (matchinfo->mode == XT_CONNMARK_RESTORE) {
 		if (strcmp(tablename, "mangle") != 0) {
 			printk(KERN_WARNING "CONNMARK: restore can only be "
 			       "called from \"mangle\" table, not \"%s\"\n",
 			       tablename);
-			return 0;
+			return false;
 		}
 	}
 	if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) {
 		printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static void
@@ -121,7 +121,7 @@
 
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_xt_connmark_target_info *cm = src;
+	const struct compat_xt_connmark_target_info *cm = src;
 	struct xt_connmark_target_info m = {
 		.mark	= cm->mark,
 		.mask	= cm->mask,
@@ -132,7 +132,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct xt_connmark_target_info *m = src;
+	const struct xt_connmark_target_info *m = src;
 	struct compat_xt_connmark_target_info cm = {
 		.mark	= m->mark,
 		.mask	= m->mask,
@@ -142,7 +142,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_target xt_connmark_target[] = {
+static struct xt_target xt_connmark_target[] __read_mostly = {
 	{
 		.name		= "CONNMARK",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 81c0c58..63d7313 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -33,7 +33,7 @@
  * If the packet has a security mark and the connection does not, copy
  * the security mark from the packet to the connection.
  */
-static void secmark_save(struct sk_buff *skb)
+static void secmark_save(const struct sk_buff *skb)
 {
 	if (skb->secmark) {
 		struct nf_conn *ct;
@@ -85,16 +85,16 @@
 	return XT_CONTINUE;
 }
 
-static int checkentry(const char *tablename, const void *entry,
-		      const struct xt_target *target, void *targinfo,
-		      unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *entry,
+		       const struct xt_target *target, void *targinfo,
+		       unsigned int hook_mask)
 {
-	struct xt_connsecmark_target_info *info = targinfo;
+	const struct xt_connsecmark_target_info *info = targinfo;
 
 	if (nf_ct_l3proto_try_module_get(target->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", target->family);
-		return 0;
+		return false;
 	}
 	switch (info->mode) {
 	case CONNSECMARK_SAVE:
@@ -103,10 +103,10 @@
 
 	default:
 		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
 static void
@@ -115,7 +115,7 @@
 	nf_ct_l3proto_module_put(target->family);
 }
 
-static struct xt_target xt_connsecmark_target[] = {
+static struct xt_target xt_connsecmark_target[] __read_mostly = {
 	{
 		.name		= "CONNSECMARK",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
index 9f2f220..798ab73 100644
--- a/net/netfilter/xt_DSCP.c
+++ b/net/netfilter/xt_DSCP.c
@@ -66,22 +66,22 @@
 	return XT_CONTINUE;
 }
 
-static int checkentry(const char *tablename,
-		      const void *e_void,
-		      const struct xt_target *target,
-		      void *targinfo,
-		      unsigned int hook_mask)
+static bool checkentry(const char *tablename,
+		       const void *e_void,
+		       const struct xt_target *target,
+		       void *targinfo,
+		       unsigned int hook_mask)
 {
 	const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp;
 
-	if ((dscp > XT_DSCP_MAX)) {
+	if (dscp > XT_DSCP_MAX) {
 		printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_target xt_dscp_target[] = {
+static struct xt_target xt_dscp_target[] __read_mostly = {
 	{
 		.name		= "DSCP",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index 4381780..f30fe0b 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -65,43 +65,43 @@
 }
 
 
-static int
+static bool
 checkentry_v0(const char *tablename,
 	      const void *entry,
 	      const struct xt_target *target,
 	      void *targinfo,
 	      unsigned int hook_mask)
 {
-	struct xt_mark_target_info *markinfo = targinfo;
+	const struct xt_mark_target_info *markinfo = targinfo;
 
 	if (markinfo->mark > 0xffffffff) {
 		printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static int
+static bool
 checkentry_v1(const char *tablename,
 	      const void *entry,
 	      const struct xt_target *target,
 	      void *targinfo,
 	      unsigned int hook_mask)
 {
-	struct xt_mark_target_info_v1 *markinfo = targinfo;
+	const struct xt_mark_target_info_v1 *markinfo = targinfo;
 
 	if (markinfo->mode != XT_MARK_SET
 	    && markinfo->mode != XT_MARK_AND
 	    && markinfo->mode != XT_MARK_OR) {
 		printk(KERN_WARNING "MARK: unknown mode %u\n",
 		       markinfo->mode);
-		return 0;
+		return false;
 	}
 	if (markinfo->mark > 0xffffffff) {
 		printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 #ifdef CONFIG_COMPAT
@@ -114,7 +114,7 @@
 
 static void compat_from_user_v1(void *dst, void *src)
 {
-	struct compat_xt_mark_target_info_v1 *cm = src;
+	const struct compat_xt_mark_target_info_v1 *cm = src;
 	struct xt_mark_target_info_v1 m = {
 		.mark	= cm->mark,
 		.mode	= cm->mode,
@@ -124,7 +124,7 @@
 
 static int compat_to_user_v1(void __user *dst, void *src)
 {
-	struct xt_mark_target_info_v1 *m = src;
+	const struct xt_mark_target_info_v1 *m = src;
 	struct compat_xt_mark_target_info_v1 cm = {
 		.mark	= m->mark,
 		.mode	= m->mode,
@@ -133,7 +133,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_target xt_mark_target[] = {
+static struct xt_target xt_mark_target[] __read_mostly = {
 	{
 		.name		= "MARK",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
index 901ed7a..d3594c7 100644
--- a/net/netfilter/xt_NFLOG.c
+++ b/net/netfilter/xt_NFLOG.c
@@ -38,21 +38,21 @@
 	return XT_CONTINUE;
 }
 
-static int
+static bool
 nflog_checkentry(const char *tablename, const void *entry,
 		 const struct xt_target *target, void *targetinfo,
 		 unsigned int hookmask)
 {
-	struct xt_nflog_info *info = targetinfo;
+	const struct xt_nflog_info *info = targetinfo;
 
 	if (info->flags & ~XT_NFLOG_MASK)
-		return 0;
+		return false;
 	if (info->prefix[sizeof(info->prefix) - 1] != '\0')
-		return 0;
-	return 1;
+		return false;
+	return true;
 }
 
-static struct xt_target xt_nflog_target[] = {
+static struct xt_target xt_nflog_target[] __read_mostly = {
 	{
 		.name		= "NFLOG",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 201155b..13f59f3 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -36,7 +36,7 @@
 	return NF_QUEUE_NR(tinfo->queuenum);
 }
 
-static struct xt_target xt_nfqueue_target[] = {
+static struct xt_target xt_nfqueue_target[] __read_mostly = {
 	{
 		.name		= "NFQUEUE",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index 5085fb3..b7d6312 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -33,7 +33,7 @@
 	return XT_CONTINUE;
 }
 
-static struct xt_target xt_notrack_target[] = {
+static struct xt_target xt_notrack_target[] __read_mostly = {
 	{
 		.name		= "NOTRACK",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index 705f0e8..c83779a 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -51,7 +51,7 @@
 	return XT_CONTINUE;
 }
 
-static int checkentry_selinux(struct xt_secmark_target_info *info)
+static bool checkentry_selinux(struct xt_secmark_target_info *info)
 {
 	int err;
 	struct xt_secmark_target_selinux_info *sel = &info->u.sel;
@@ -63,53 +63,53 @@
 		if (err == -EINVAL)
 			printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n",
 			       sel->selctx);
-		return 0;
+		return false;
 	}
 
 	if (!sel->selsid) {
 		printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n",
 		       sel->selctx);
-		return 0;
+		return false;
 	}
 
 	err = selinux_relabel_packet_permission(sel->selsid);
 	if (err) {
 		printk(KERN_INFO PFX "unable to obtain relabeling permission\n");
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static int checkentry(const char *tablename, const void *entry,
-		      const struct xt_target *target, void *targinfo,
-		      unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *entry,
+		       const struct xt_target *target, void *targinfo,
+		       unsigned int hook_mask)
 {
 	struct xt_secmark_target_info *info = targinfo;
 
 	if (mode && mode != info->mode) {
 		printk(KERN_INFO PFX "mode already set to %hu cannot mix with "
 		       "rules for mode %hu\n", mode, info->mode);
-		return 0;
+		return false;
 	}
 
 	switch (info->mode) {
 	case SECMARK_MODE_SEL:
 		if (!checkentry_selinux(info))
-			return 0;
+			return false;
 		break;
 
 	default:
 		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
-		return 0;
+		return false;
 	}
 
 	if (!mode)
 		mode = info->mode;
-	return 1;
+	return true;
 }
 
-static struct xt_target xt_secmark_target[] = {
+static struct xt_target xt_secmark_target[] __read_mostly = {
 	{
 		.name		= "SECMARK",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 15fe8f6..d40f7e4 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -93,7 +93,7 @@
 				return 0;
 
 			opt[i+2] = (newmss & 0xff00) >> 8;
-			opt[i+3] = (newmss & 0x00ff);
+			opt[i+3] = newmss & 0x00ff;
 
 			nf_proto_csum_replace2(&tcph->check, *pskb,
 					       htons(oldmss), htons(newmss), 0);
@@ -126,7 +126,7 @@
 	opt[0] = TCPOPT_MSS;
 	opt[1] = TCPOLEN_MSS;
 	opt[2] = (newmss & 0xff00) >> 8;
-	opt[3] = (newmss & 0x00ff);
+	opt[3] = newmss & 0x00ff;
 
 	nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0);
 
@@ -197,19 +197,19 @@
 #define TH_SYN 0x02
 
 /* Must specify -p tcp --syn */
-static inline int find_syn_match(const struct xt_entry_match *m)
+static inline bool find_syn_match(const struct xt_entry_match *m)
 {
 	const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data;
 
 	if (strcmp(m->u.kernel.match->name, "tcp") == 0 &&
 	    tcpinfo->flg_cmp & TH_SYN &&
 	    !(tcpinfo->invflags & XT_TCP_INV_FLAGS))
-		return 1;
+		return true;
 
-	return 0;
+	return false;
 }
 
-static int
+static bool
 xt_tcpmss_checkentry4(const char *tablename,
 		      const void *entry,
 		      const struct xt_target *target,
@@ -225,16 +225,16 @@
 			   (1 << NF_IP_POST_ROUTING))) != 0) {
 		printk("xt_TCPMSS: path-MTU clamping only supported in "
 		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
-		return 0;
+		return false;
 	}
 	if (IPT_MATCH_ITERATE(e, find_syn_match))
-		return 1;
+		return true;
 	printk("xt_TCPMSS: Only works on TCP SYN packets\n");
-	return 0;
+	return false;
 }
 
 #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
-static int
+static bool
 xt_tcpmss_checkentry6(const char *tablename,
 		      const void *entry,
 		      const struct xt_target *target,
@@ -250,16 +250,16 @@
 			   (1 << NF_IP6_POST_ROUTING))) != 0) {
 		printk("xt_TCPMSS: path-MTU clamping only supported in "
 		       "FORWARD, OUTPUT and POSTROUTING hooks\n");
-		return 0;
+		return false;
 	}
 	if (IP6T_MATCH_ITERATE(e, find_syn_match))
-		return 1;
+		return true;
 	printk("xt_TCPMSS: Only works on TCP SYN packets\n");
-	return 0;
+	return false;
 }
 #endif
 
-static struct xt_target xt_tcpmss_reg[] = {
+static struct xt_target xt_tcpmss_reg[] __read_mostly = {
 	{
 		.family		= AF_INET,
 		.name		= "TCPMSS",
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c
new file mode 100644
index 0000000..4df2ded
--- /dev/null
+++ b/net/netfilter/xt_TRACE.c
@@ -0,0 +1,53 @@
+/* This is a module which is used to mark packets for tracing.
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_TRACE");
+MODULE_ALIAS("ip6t_TRACE");
+
+static unsigned int
+target(struct sk_buff **pskb,
+       const struct net_device *in,
+       const struct net_device *out,
+       unsigned int hooknum,
+       const struct xt_target *target,
+       const void *targinfo)
+{
+	(*pskb)->nf_trace = 1;
+	return XT_CONTINUE;
+}
+
+static struct xt_target xt_trace_target[] __read_mostly = {
+	{
+		.name		= "TRACE",
+		.family		= AF_INET,
+		.target		= target,
+		.table		= "raw",
+		.me		= THIS_MODULE,
+	},
+	{
+		.name		= "TRACE",
+		.family		= AF_INET6,
+		.target		= target,
+		.table		= "raw",
+		.me		= THIS_MODULE,
+	},
+};
+
+static int __init xt_trace_init(void)
+{
+	return xt_register_targets(xt_trace_target,
+				   ARRAY_SIZE(xt_trace_target));
+}
+
+static void __exit xt_trace_fini(void)
+{
+	xt_unregister_targets(xt_trace_target, ARRAY_SIZE(xt_trace_target));
+}
+
+module_init(xt_trace_init);
+module_exit(xt_trace_fini);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 7db492d..64bcdb0 100644
--- a/net/netfilter/xt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -15,7 +15,7 @@
 MODULE_ALIAS("ipt_comment");
 MODULE_ALIAS("ip6t_comment");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -23,13 +23,13 @@
       const void *matchinfo,
       int offset,
       unsigned int protooff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	/* We always match */
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_comment_match[] = {
+static struct xt_match xt_comment_match[] __read_mostly = {
 	{
 		.name		= "comment",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 804afe5..dd4d79b 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -15,7 +15,7 @@
 MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
 MODULE_ALIAS("ipt_connbytes");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -23,10 +23,10 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_connbytes_info *sinfo = matchinfo;
-	struct nf_conn *ct;
+	const struct nf_conn *ct;
 	enum ip_conntrack_info ctinfo;
 	u_int64_t what = 0;	/* initialize to make gcc happy */
 	u_int64_t bytes = 0;
@@ -35,7 +35,7 @@
 
 	ct = nf_ct_get(skb, &ctinfo);
 	if (!ct)
-		return 0;
+		return false;
 	counters = ct->counters;
 
 	switch (sinfo->what) {
@@ -90,36 +90,36 @@
 	}
 
 	if (sinfo->count.to)
-		return (what <= sinfo->count.to && what >= sinfo->count.from);
+		return what <= sinfo->count.to && what >= sinfo->count.from;
 	else
-		return (what >= sinfo->count.from);
+		return what >= sinfo->count.from;
 }
 
-static int check(const char *tablename,
-		 const void *ip,
-		 const struct xt_match *match,
-		 void *matchinfo,
-		 unsigned int hook_mask)
+static bool check(const char *tablename,
+		  const void *ip,
+		  const struct xt_match *match,
+		  void *matchinfo,
+		  unsigned int hook_mask)
 {
 	const struct xt_connbytes_info *sinfo = matchinfo;
 
 	if (sinfo->what != XT_CONNBYTES_PKTS &&
 	    sinfo->what != XT_CONNBYTES_BYTES &&
 	    sinfo->what != XT_CONNBYTES_AVGPKT)
-		return 0;
+		return false;
 
 	if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
 	    sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
 	    sinfo->direction != XT_CONNBYTES_DIR_BOTH)
-		return 0;
+		return false;
 
 	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", match->family);
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
 static void
@@ -128,7 +128,7 @@
 	nf_ct_l3proto_module_put(match->family);
 }
 
-static struct xt_match xt_connbytes_match[] = {
+static struct xt_match xt_connbytes_match[] __read_mostly = {
 	{
 		.name		= "connbytes",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index e180325..e73fa9b 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -30,7 +30,7 @@
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("ipt_connmark");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -38,38 +38,38 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_connmark_info *info = matchinfo;
-	struct nf_conn *ct;
+	const struct nf_conn *ct;
 	enum ip_conntrack_info ctinfo;
 
 	ct = nf_ct_get(skb, &ctinfo);
 	if (!ct)
-		return 0;
+		return false;
 
-	return (((ct->mark) & info->mask) == info->mark) ^ info->invert;
+	return ((ct->mark & info->mask) == info->mark) ^ info->invert;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip,
 	   const struct xt_match *match,
 	   void *matchinfo,
 	   unsigned int hook_mask)
 {
-	struct xt_connmark_info *cm = matchinfo;
+	const struct xt_connmark_info *cm = matchinfo;
 
 	if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
 		printk(KERN_WARNING "connmark: only support 32bit mark\n");
-		return 0;
+		return false;
 	}
 	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", match->family);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static void
@@ -88,7 +88,7 @@
 
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_xt_connmark_info *cm = src;
+	const struct compat_xt_connmark_info *cm = src;
 	struct xt_connmark_info m = {
 		.mark	= cm->mark,
 		.mask	= cm->mask,
@@ -99,7 +99,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct xt_connmark_info *m = src;
+	const struct xt_connmark_info *m = src;
 	struct compat_xt_connmark_info cm = {
 		.mark	= m->mark,
 		.mask	= m->mask,
@@ -109,7 +109,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_match xt_connmark_match[] = {
+static struct xt_match xt_connmark_match[] __read_mostly = {
 	{
 		.name		= "connmark",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 189ded5..ca4b69f 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -19,7 +19,7 @@
 MODULE_DESCRIPTION("iptables connection tracking match module");
 MODULE_ALIAS("ipt_conntrack");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -27,14 +27,14 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_conntrack_info *sinfo = matchinfo;
-	struct nf_conn *ct;
+	const struct nf_conn *ct;
 	enum ip_conntrack_info ctinfo;
 	unsigned int statebit;
 
-	ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
+	ct = nf_ct_get(skb, &ctinfo);
 
 #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
 
@@ -54,53 +54,53 @@
 		}
 		if (FWINV((statebit & sinfo->statemask) == 0,
 			  XT_CONNTRACK_STATE))
-			return 0;
+			return false;
 	}
 
 	if (ct == NULL) {
 		if (sinfo->flags & ~XT_CONNTRACK_STATE)
-			return 0;
-		return 1;
+			return false;
+		return true;
 	}
 
 	if (sinfo->flags & XT_CONNTRACK_PROTO &&
 	    FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum !=
 		  sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
 		  XT_CONNTRACK_PROTO))
-		return 0;
+		return false;
 
 	if (sinfo->flags & XT_CONNTRACK_ORIGSRC &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip &
 		   sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
 		  XT_CONNTRACK_ORIGSRC))
-		return 0;
+		return false;
 
 	if (sinfo->flags & XT_CONNTRACK_ORIGDST &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip &
 		   sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
 		  XT_CONNTRACK_ORIGDST))
-		return 0;
+		return false;
 
 	if (sinfo->flags & XT_CONNTRACK_REPLSRC &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip &
 		   sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
 		  XT_CONNTRACK_REPLSRC))
-		return 0;
+		return false;
 
 	if (sinfo->flags & XT_CONNTRACK_REPLDST &&
 	    FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip &
 		   sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) !=
 		  sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
 		  XT_CONNTRACK_REPLDST))
-		return 0;
+		return false;
 
 	if (sinfo->flags & XT_CONNTRACK_STATUS &&
 	    FWINV((ct->status & sinfo->statusmask) == 0,
 		  XT_CONNTRACK_STATUS))
-		return 0;
+		return false;
 
 	if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
 		unsigned long expires = timer_pending(&ct->timeout) ?
@@ -109,12 +109,12 @@
 		if (FWINV(!(expires >= sinfo->expires_min &&
 			    expires <= sinfo->expires_max),
 			  XT_CONNTRACK_EXPIRES))
-			return 0;
+			return false;
 	}
-	return 1;
+	return true;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip,
 	   const struct xt_match *match,
@@ -124,9 +124,9 @@
 	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", match->family);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static void destroy(const struct xt_match *match, void *matchinfo)
@@ -150,7 +150,7 @@
 
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_xt_conntrack_info *cm = src;
+	const struct compat_xt_conntrack_info *cm = src;
 	struct xt_conntrack_info m = {
 		.statemask	= cm->statemask,
 		.statusmask	= cm->statusmask,
@@ -167,7 +167,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct xt_conntrack_info *m = src;
+	const struct xt_conntrack_info *m = src;
 	struct compat_xt_conntrack_info cm = {
 		.statemask	= m->statemask,
 		.statusmask	= m->statusmask,
@@ -183,7 +183,7 @@
 }
 #endif
 
-static struct xt_match conntrack_match = {
+static struct xt_match conntrack_match __read_mostly = {
 	.name		= "conntrack",
 	.match		= match,
 	.checkentry	= checkentry,
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 2c9c0de..83224ec 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -31,40 +31,40 @@
 static unsigned char *dccp_optbuf;
 static DEFINE_SPINLOCK(dccp_buflock);
 
-static inline int
+static inline bool
 dccp_find_option(u_int8_t option,
 		 const struct sk_buff *skb,
 		 unsigned int protoff,
 		 const struct dccp_hdr *dh,
-		 int *hotdrop)
+		 bool *hotdrop)
 {
 	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
-	unsigned char *op;
+	const unsigned char *op;
 	unsigned int optoff = __dccp_hdr_len(dh);
 	unsigned int optlen = dh->dccph_doff*4 - __dccp_hdr_len(dh);
 	unsigned int i;
 
 	if (dh->dccph_doff * 4 < __dccp_hdr_len(dh)) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	if (!optlen)
-		return 0;
+		return false;
 
 	spin_lock_bh(&dccp_buflock);
 	op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf);
 	if (op == NULL) {
 		/* If we don't have the whole header, drop packet. */
 		spin_unlock_bh(&dccp_buflock);
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	for (i = 0; i < optlen; ) {
 		if (op[i] == option) {
 			spin_unlock_bh(&dccp_buflock);
-			return 1;
+			return true;
 		}
 
 		if (op[i] < 2)
@@ -74,24 +74,24 @@
 	}
 
 	spin_unlock_bh(&dccp_buflock);
-	return 0;
+	return false;
 }
 
 
-static inline int
+static inline bool
 match_types(const struct dccp_hdr *dh, u_int16_t typemask)
 {
-	return (typemask & (1 << dh->dccph_type));
+	return typemask & (1 << dh->dccph_type);
 }
 
-static inline int
+static inline bool
 match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff,
-	     const struct dccp_hdr *dh, int *hotdrop)
+	     const struct dccp_hdr *dh, bool *hotdrop)
 {
 	return dccp_find_option(option, skb, protoff, dh, hotdrop);
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -99,25 +99,25 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_dccp_info *info = matchinfo;
 	struct dccp_hdr _dh, *dh;
 
 	if (offset)
-		return 0;
+		return false;
 
 	dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh);
 	if (dh == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
-	return  DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0])
-			&& (ntohs(dh->dccph_sport) <= info->spts[1])),
+	return  DCCHECK(ntohs(dh->dccph_sport) >= info->spts[0]
+			&& ntohs(dh->dccph_sport) <= info->spts[1],
 			XT_DCCP_SRC_PORTS, info->flags, info->invflags)
-		&& DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0])
-			&& (ntohs(dh->dccph_dport) <= info->dpts[1])),
+		&& DCCHECK(ntohs(dh->dccph_dport) >= info->dpts[0]
+			&& ntohs(dh->dccph_dport) <= info->dpts[1],
 			XT_DCCP_DEST_PORTS, info->flags, info->invflags)
 		&& DCCHECK(match_types(dh, info->typemask),
 			   XT_DCCP_TYPE, info->flags, info->invflags)
@@ -126,7 +126,7 @@
 			   XT_DCCP_OPTION, info->flags, info->invflags);
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *inf,
 	   const struct xt_match *match,
@@ -140,7 +140,7 @@
 		&& !(info->invflags & ~info->flags);
 }
 
-static struct xt_match xt_dccp_match[] = {
+static struct xt_match xt_dccp_match[] __read_mostly = {
 	{
 		.name 		= "dccp",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
index 56b247e..dde6d66 100644
--- a/net/netfilter/xt_dscp.c
+++ b/net/netfilter/xt_dscp.c
@@ -22,14 +22,14 @@
 MODULE_ALIAS("ipt_dscp");
 MODULE_ALIAS("ip6t_dscp");
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in,
-		 const struct net_device *out,
-		 const struct xt_match *match,
-		 const void *matchinfo,
-		 int offset,
-		 unsigned int protoff,
-		 int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  const struct xt_match *match,
+		  const void *matchinfo,
+		  int offset,
+		  unsigned int protoff,
+		  bool *hotdrop)
 {
 	const struct xt_dscp_info *info = matchinfo;
 	u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
@@ -37,14 +37,14 @@
 	return (dscp == info->dscp) ^ !!info->invert;
 }
 
-static int match6(const struct sk_buff *skb,
-		  const struct net_device *in,
-		  const struct net_device *out,
-		  const struct xt_match *match,
-		  const void *matchinfo,
-		  int offset,
-		  unsigned int protoff,
-		  int *hotdrop)
+static bool match6(const struct sk_buff *skb,
+		   const struct net_device *in,
+		   const struct net_device *out,
+		   const struct xt_match *match,
+		   const void *matchinfo,
+		   int offset,
+		   unsigned int protoff,
+		   bool *hotdrop)
 {
 	const struct xt_dscp_info *info = matchinfo;
 	u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
@@ -52,23 +52,23 @@
 	return (dscp == info->dscp) ^ !!info->invert;
 }
 
-static int checkentry(const char *tablename,
-		      const void *info,
-		      const struct xt_match *match,
-		      void *matchinfo,
-		      unsigned int hook_mask)
+static bool checkentry(const char *tablename,
+		       const void *info,
+		       const struct xt_match *match,
+		       void *matchinfo,
+		       unsigned int hook_mask)
 {
 	const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp;
 
 	if (dscp > XT_DSCP_MAX) {
 		printk(KERN_ERR "xt_dscp: dscp %x out of range\n", dscp);
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_dscp_match[] = {
+static struct xt_match xt_dscp_match[] __read_mostly = {
 	{
 		.name		= "dscp",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
index 7c95f14..b11378e 100644
--- a/net/netfilter/xt_esp.c
+++ b/net/netfilter/xt_esp.c
@@ -31,10 +31,10 @@
 #endif
 
 /* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
+static inline bool
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
 {
-	int r = 0;
+	bool r;
 	duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
 		 min, spi, max);
 	r = (spi >= min && spi <= max) ^ invert;
@@ -42,7 +42,7 @@
 	return r;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -50,14 +50,14 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	struct ip_esp_hdr _esp, *eh;
 	const struct xt_esp *espinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp);
 	if (eh == NULL) {
@@ -65,8 +65,8 @@
 		 * can't.  Hence, no choice but to drop.
 		 */
 		duprintf("Dropping evil ESP tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi),
@@ -74,7 +74,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *ip_void,
 	   const struct xt_match *match,
@@ -85,13 +85,13 @@
 
 	if (espinfo->invflags & ~XT_ESP_INV_MASK) {
 		duprintf("xt_esp: unknown flags %X\n", espinfo->invflags);
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_esp_match[] = {
+static struct xt_match xt_esp_match[] __read_mostly = {
 	{
 		.name		= "esp",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index d3043fa..d6b3d01 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -94,7 +94,8 @@
 static HLIST_HEAD(hashlimit_htables);
 static struct kmem_cache *hashlimit_cachep __read_mostly;
 
-static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
+static inline bool dst_cmp(const struct dsthash_ent *ent,
+			   const struct dsthash_dst *b)
 {
 	return !memcmp(&ent->dst, b, sizeof(ent->dst));
 }
@@ -106,7 +107,8 @@
 }
 
 static struct dsthash_ent *
-dsthash_find(const struct xt_hashlimit_htable *ht, struct dsthash_dst *dst)
+dsthash_find(const struct xt_hashlimit_htable *ht,
+	     const struct dsthash_dst *dst)
 {
 	struct dsthash_ent *ent;
 	struct hlist_node *pos;
@@ -122,7 +124,8 @@
 
 /* allocate dsthash_ent, initialize dst, put in htable and lock it */
 static struct dsthash_ent *
-dsthash_alloc_init(struct xt_hashlimit_htable *ht, struct dsthash_dst *dst)
+dsthash_alloc_init(struct xt_hashlimit_htable *ht,
+		   const struct dsthash_dst *dst)
 {
 	struct dsthash_ent *ent;
 
@@ -227,19 +230,21 @@
 	return 0;
 }
 
-static int select_all(struct xt_hashlimit_htable *ht, struct dsthash_ent *he)
+static bool select_all(const struct xt_hashlimit_htable *ht,
+		       const struct dsthash_ent *he)
 {
 	return 1;
 }
 
-static int select_gc(struct xt_hashlimit_htable *ht, struct dsthash_ent *he)
+static bool select_gc(const struct xt_hashlimit_htable *ht,
+		      const struct dsthash_ent *he)
 {
-	return (jiffies >= he->expires);
+	return jiffies >= he->expires;
 }
 
 static void htable_selective_cleanup(struct xt_hashlimit_htable *ht,
-				int (*select)(struct xt_hashlimit_htable *ht,
-					      struct dsthash_ent *he))
+			bool (*select)(const struct xt_hashlimit_htable *ht,
+				      const struct dsthash_ent *he))
 {
 	unsigned int i;
 
@@ -282,7 +287,8 @@
 	vfree(hinfo);
 }
 
-static struct xt_hashlimit_htable *htable_find_get(char *name, int family)
+static struct xt_hashlimit_htable *htable_find_get(const char *name,
+						   int family)
 {
 	struct xt_hashlimit_htable *hinfo;
 	struct hlist_node *pos;
@@ -367,7 +373,8 @@
 }
 
 static int
-hashlimit_init_dst(struct xt_hashlimit_htable *hinfo, struct dsthash_dst *dst,
+hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
+		   struct dsthash_dst *dst,
 		   const struct sk_buff *skb, unsigned int protoff)
 {
 	__be16 _ports[2], *ports;
@@ -432,7 +439,7 @@
 	return 0;
 }
 
-static int
+static bool
 hashlimit_match(const struct sk_buff *skb,
 		const struct net_device *in,
 		const struct net_device *out,
@@ -440,10 +447,10 @@
 		const void *matchinfo,
 		int offset,
 		unsigned int protoff,
-		int *hotdrop)
+		bool *hotdrop)
 {
-	struct xt_hashlimit_info *r =
-		((struct xt_hashlimit_info *)matchinfo)->u.master;
+	const struct xt_hashlimit_info *r =
+		((const struct xt_hashlimit_info *)matchinfo)->u.master;
 	struct xt_hashlimit_htable *hinfo = r->hinfo;
 	unsigned long now = jiffies;
 	struct dsthash_ent *dh;
@@ -478,20 +485,20 @@
 		/* We're underlimit. */
 		dh->rateinfo.credit -= dh->rateinfo.cost;
 		spin_unlock_bh(&hinfo->lock);
-		return 1;
+		return true;
 	}
 
 	spin_unlock_bh(&hinfo->lock);
 
 	/* default case: we're overlimit, thus don't match */
-	return 0;
+	return false;
 
 hotdrop:
-	*hotdrop = 1;
-	return 0;
+	*hotdrop = true;
+	return false;
 }
 
-static int
+static bool
 hashlimit_checkentry(const char *tablename,
 		     const void *inf,
 		     const struct xt_match *match,
@@ -505,20 +512,20 @@
 	    user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) {
 		printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n",
 		       r->cfg.avg, r->cfg.burst);
-		return 0;
+		return false;
 	}
 	if (r->cfg.mode == 0 ||
 	    r->cfg.mode > (XT_HASHLIMIT_HASH_DPT |
 			   XT_HASHLIMIT_HASH_DIP |
 			   XT_HASHLIMIT_HASH_SIP |
 			   XT_HASHLIMIT_HASH_SPT))
-		return 0;
+		return false;
 	if (!r->cfg.gc_interval)
-		return 0;
+		return false;
 	if (!r->cfg.expire)
-		return 0;
+		return false;
 	if (r->name[sizeof(r->name) - 1] != '\0')
-		return 0;
+		return false;
 
 	/* This is the best we've got: We cannot release and re-grab lock,
 	 * since checkentry() is called before x_tables.c grabs xt_mutex.
@@ -530,19 +537,19 @@
 	r->hinfo = htable_find_get(r->name, match->family);
 	if (!r->hinfo && htable_create(r, match->family) != 0) {
 		mutex_unlock(&hlimit_mutex);
-		return 0;
+		return false;
 	}
 	mutex_unlock(&hlimit_mutex);
 
 	/* Ugly hack: For SMP, we only want to use one set */
 	r->u.master = r;
-	return 1;
+	return true;
 }
 
 static void
 hashlimit_destroy(const struct xt_match *match, void *matchinfo)
 {
-	struct xt_hashlimit_info *r = matchinfo;
+	const struct xt_hashlimit_info *r = matchinfo;
 
 	htable_put(r->hinfo);
 }
@@ -571,7 +578,7 @@
 }
 #endif
 
-static struct xt_match xt_hashlimit[] = {
+static struct xt_match xt_hashlimit[] __read_mostly = {
 	{
 		.name		= "hashlimit",
 		.family		= AF_INET,
@@ -694,7 +701,7 @@
 	return 0;
 }
 
-static struct seq_operations dl_seq_ops = {
+static const struct seq_operations dl_seq_ops = {
 	.start = dl_seq_start,
 	.next  = dl_seq_next,
 	.stop  = dl_seq_stop,
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index c139b2f..0a1f4c6 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -22,13 +22,8 @@
 MODULE_ALIAS("ipt_helper");
 MODULE_ALIAS("ip6t_helper");
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -36,61 +31,51 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_helper_info *info = matchinfo;
-	struct nf_conn *ct;
-	struct nf_conn_help *master_help;
+	const struct nf_conn *ct;
+	const struct nf_conn_help *master_help;
+	const struct nf_conntrack_helper *helper;
 	enum ip_conntrack_info ctinfo;
-	int ret = info->invert;
+	bool ret = info->invert;
 
-	ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
-	if (!ct) {
-		DEBUGP("xt_helper: Eek! invalid conntrack?\n");
+	ct = nf_ct_get(skb, &ctinfo);
+	if (!ct || !ct->master)
 		return ret;
-	}
 
-	if (!ct->master) {
-		DEBUGP("xt_helper: conntrack %p has no master\n", ct);
-		return ret;
-	}
-
-	read_lock_bh(&nf_conntrack_lock);
 	master_help = nfct_help(ct->master);
-	if (!master_help || !master_help->helper) {
-		DEBUGP("xt_helper: master ct %p has no helper\n",
-			exp->expectant);
-		goto out_unlock;
-	}
+	if (!master_help)
+		return ret;
 
-	DEBUGP("master's name = %s , info->name = %s\n",
-		ct->master->helper->name, info->name);
+	/* rcu_read_lock()ed by nf_hook_slow */
+	helper = rcu_dereference(master_help->helper);
+	if (!helper)
+		return ret;
 
 	if (info->name[0] == '\0')
-		ret ^= 1;
+		ret = !ret;
 	else
 		ret ^= !strncmp(master_help->helper->name, info->name,
 				strlen(master_help->helper->name));
-out_unlock:
-	read_unlock_bh(&nf_conntrack_lock);
 	return ret;
 }
 
-static int check(const char *tablename,
-		 const void *inf,
-		 const struct xt_match *match,
-		 void *matchinfo,
-		 unsigned int hook_mask)
+static bool check(const char *tablename,
+		  const void *inf,
+		  const struct xt_match *match,
+		  void *matchinfo,
+		  unsigned int hook_mask)
 {
 	struct xt_helper_info *info = matchinfo;
 
 	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", match->family);
-		return 0;
+		return false;
 	}
 	info->name[29] = '\0';
-	return 1;
+	return true;
 }
 
 static void
@@ -99,7 +84,7 @@
 	nf_ct_l3proto_module_put(match->family);
 }
 
-static struct xt_match xt_helper_match[] = {
+static struct xt_match xt_helper_match[] __read_mostly = {
 	{
 		.name		= "helper",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index 77288c5..3dad173 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -20,7 +20,7 @@
 MODULE_ALIAS("ipt_length");
 MODULE_ALIAS("ip6t_length");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -28,7 +28,7 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_length_info *info = matchinfo;
 	u_int16_t pktlen = ntohs(ip_hdr(skb)->tot_len);
@@ -36,7 +36,7 @@
 	return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
 }
 
-static int
+static bool
 match6(const struct sk_buff *skb,
        const struct net_device *in,
        const struct net_device *out,
@@ -44,16 +44,16 @@
        const void *matchinfo,
        int offset,
        unsigned int protoff,
-       int *hotdrop)
+       bool *hotdrop)
 {
 	const struct xt_length_info *info = matchinfo;
-	const u_int16_t pktlen = (ntohs(ipv6_hdr(skb)->payload_len) +
-				  sizeof(struct ipv6hdr));
+	const u_int16_t pktlen = ntohs(ipv6_hdr(skb)->payload_len) +
+				 sizeof(struct ipv6hdr);
 
 	return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
 }
 
-static struct xt_match xt_length_match[] = {
+static struct xt_match xt_length_match[] __read_mostly = {
 	{
 		.name		= "length",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 571a72a..4fcca79 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -57,7 +57,7 @@
 
 #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
 
-static int
+static bool
 ipt_limit_match(const struct sk_buff *skb,
 		const struct net_device *in,
 		const struct net_device *out,
@@ -65,9 +65,10 @@
 		const void *matchinfo,
 		int offset,
 		unsigned int protoff,
-		int *hotdrop)
+		bool *hotdrop)
 {
-	struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master;
+	struct xt_rateinfo *r =
+		((const struct xt_rateinfo *)matchinfo)->master;
 	unsigned long now = jiffies;
 
 	spin_lock_bh(&limit_lock);
@@ -79,11 +80,11 @@
 		/* We're not limited. */
 		r->credit -= r->cost;
 		spin_unlock_bh(&limit_lock);
-		return 1;
+		return true;
 	}
 
 	spin_unlock_bh(&limit_lock);
-	return 0;
+	return false;
 }
 
 /* Precision saver. */
@@ -98,7 +99,7 @@
 	return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE;
 }
 
-static int
+static bool
 ipt_limit_checkentry(const char *tablename,
 		     const void *inf,
 		     const struct xt_match *match,
@@ -112,7 +113,7 @@
 	    || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
 		printk("Overflow in xt_limit, try lower: %u/%u\n",
 		       r->avg, r->burst);
-		return 0;
+		return false;
 	}
 
 	/* For SMP, we only want to use one set of counters. */
@@ -125,7 +126,7 @@
 		r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
 		r->cost = user2credits(r->avg);
 	}
-	return 1;
+	return true;
 }
 
 #ifdef CONFIG_COMPAT
@@ -144,7 +145,7 @@
  * master pointer, which does not need to be preserved. */
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_xt_rateinfo *cm = src;
+	const struct compat_xt_rateinfo *cm = src;
 	struct xt_rateinfo m = {
 		.avg		= cm->avg,
 		.burst		= cm->burst,
@@ -158,7 +159,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct xt_rateinfo *m = src;
+	const struct xt_rateinfo *m = src;
 	struct compat_xt_rateinfo cm = {
 		.avg		= m->avg,
 		.burst		= m->burst,
@@ -172,7 +173,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_match xt_limit_match[] = {
+static struct xt_match xt_limit_match[] __read_mostly = {
 	{
 		.name		= "limit",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index 1d3a1d9..00490d7 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -24,7 +24,7 @@
 MODULE_ALIAS("ipt_mac");
 MODULE_ALIAS("ip6t_mac");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -32,19 +32,19 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
     const struct xt_mac_info *info = matchinfo;
 
     /* Is mac pointer valid? */
-    return (skb_mac_header(skb) >= skb->head &&
-	    (skb_mac_header(skb) + ETH_HLEN) <= skb->data
-	    /* If so, compare... */
-	    && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr))
-		^ info->invert));
+    return skb_mac_header(skb) >= skb->head &&
+	   skb_mac_header(skb) + ETH_HLEN <= skb->data
+	   /* If so, compare... */
+	   && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr))
+		^ info->invert);
 }
 
-static struct xt_match xt_mac_match[] = {
+static struct xt_match xt_mac_match[] __read_mostly = {
 	{
 		.name		= "mac",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index 39911dd..c02a7f8 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -19,7 +19,7 @@
 MODULE_ALIAS("ipt_mark");
 MODULE_ALIAS("ip6t_mark");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -27,14 +27,14 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_mark_info *info = matchinfo;
 
 	return ((skb->mark & info->mask) == info->mark) ^ info->invert;
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *entry,
 	   const struct xt_match *match,
@@ -45,9 +45,9 @@
 
 	if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
 		printk(KERN_WARNING "mark: only supports 32bit mark\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 #ifdef CONFIG_COMPAT
@@ -60,7 +60,7 @@
 
 static void compat_from_user(void *dst, void *src)
 {
-	struct compat_xt_mark_info *cm = src;
+	const struct compat_xt_mark_info *cm = src;
 	struct xt_mark_info m = {
 		.mark	= cm->mark,
 		.mask	= cm->mask,
@@ -71,7 +71,7 @@
 
 static int compat_to_user(void __user *dst, void *src)
 {
-	struct xt_mark_info *m = src;
+	const struct xt_mark_info *m = src;
 	struct compat_xt_mark_info cm = {
 		.mark	= m->mark,
 		.mask	= m->mask,
@@ -81,7 +81,7 @@
 }
 #endif /* CONFIG_COMPAT */
 
-static struct xt_match xt_mark_match[] = {
+static struct xt_match xt_mark_match[] __read_mostly = {
 	{
 		.name		= "mark",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index 4dce2a8..e8ae102 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -33,24 +33,24 @@
 #endif
 
 /* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
+static inline bool
 ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags,
 	    u_int8_t count, u_int16_t src, u_int16_t dst)
 {
 	unsigned int i;
 	for (i = 0; i < count; i++) {
 		if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src)
-			return 1;
+			return true;
 
 		if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst)
-			return 1;
+			return true;
 	}
 
-	return 0;
+	return false;
 }
 
 /* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
+static inline bool
 ports_match_v1(const struct xt_multiport_v1 *minfo,
 	       u_int16_t src, u_int16_t dst)
 {
@@ -67,34 +67,34 @@
 
 			if (minfo->flags == XT_MULTIPORT_SOURCE
 			    && src >= s && src <= e)
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 			if (minfo->flags == XT_MULTIPORT_DESTINATION
 			    && dst >= s && dst <= e)
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 			if (minfo->flags == XT_MULTIPORT_EITHER
 			    && ((dst >= s && dst <= e)
 				|| (src >= s && src <= e)))
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 		} else {
 			/* exact port matching */
 			duprintf("src or dst matches with %d?\n", s);
 
 			if (minfo->flags == XT_MULTIPORT_SOURCE
 			    && src == s)
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 			if (minfo->flags == XT_MULTIPORT_DESTINATION
 			    && dst == s)
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 			if (minfo->flags == XT_MULTIPORT_EITHER
 			    && (src == s || dst == s))
-				return 1 ^ minfo->invert;
+				return true ^ minfo->invert;
 		}
 	}
 
 	return minfo->invert;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -102,13 +102,13 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	__be16 _ports[2], *pptr;
 	const struct xt_multiport *multiinfo = matchinfo;
 
 	if (offset)
-		return 0;
+		return false;
 
 	pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
 	if (pptr == NULL) {
@@ -116,8 +116,8 @@
 		 * can't.  Hence, no choice but to drop.
 		 */
 		duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return ports_match(multiinfo->ports,
@@ -125,7 +125,7 @@
 			   ntohs(pptr[0]), ntohs(pptr[1]));
 }
 
-static int
+static bool
 match_v1(const struct sk_buff *skb,
 	 const struct net_device *in,
 	 const struct net_device *out,
@@ -133,13 +133,13 @@
 	 const void *matchinfo,
 	 int offset,
 	 unsigned int protoff,
-	 int *hotdrop)
+	 bool *hotdrop)
 {
 	__be16 _ports[2], *pptr;
 	const struct xt_multiport_v1 *multiinfo = matchinfo;
 
 	if (offset)
-		return 0;
+		return false;
 
 	pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
 	if (pptr == NULL) {
@@ -147,14 +147,14 @@
 		 * can't.  Hence, no choice but to drop.
 		 */
 		duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
 }
 
-static inline int
+static inline bool
 check(u_int16_t proto,
       u_int8_t ip_invflags,
       u_int8_t match_flags,
@@ -172,7 +172,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *info,
 	   const struct xt_match *match,
@@ -186,7 +186,7 @@
 		     multiinfo->count);
 }
 
-static int
+static bool
 checkentry_v1(const char *tablename,
 	      const void *info,
 	      const struct xt_match *match,
@@ -200,7 +200,7 @@
 		     multiinfo->count);
 }
 
-static int
+static bool
 checkentry6(const char *tablename,
 	    const void *info,
 	    const struct xt_match *match,
@@ -214,7 +214,7 @@
 		     multiinfo->count);
 }
 
-static int
+static bool
 checkentry6_v1(const char *tablename,
 	       const void *info,
 	       const struct xt_match *match,
@@ -228,7 +228,7 @@
 		     multiinfo->count);
 }
 
-static struct xt_match xt_multiport_match[] = {
+static struct xt_match xt_multiport_match[] __read_mostly = {
 	{
 		.name		= "multiport",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 35a0fe2..f47cab7a6 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -14,8 +14,6 @@
 #include <linux/netfilter/xt_physdev.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_bridge.h>
-#define MATCH   1
-#define NOMATCH 0
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
@@ -23,7 +21,7 @@
 MODULE_ALIAS("ipt_physdev");
 MODULE_ALIAS("ip6t_physdev");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -31,14 +29,14 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	int i;
 	static const char nulldevname[IFNAMSIZ];
 	const struct xt_physdev_info *info = matchinfo;
-	unsigned int ret;
+	bool ret;
 	const char *indev, *outdev;
-	struct nf_bridge_info *nf_bridge;
+	const struct nf_bridge_info *nf_bridge;
 
 	/* Not a bridged IP packet or no info available yet:
 	 * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
@@ -47,61 +45,61 @@
 		/* Return MATCH if the invert flags of the used options are on */
 		if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
 		    !(info->invert & XT_PHYSDEV_OP_BRIDGED))
-			return NOMATCH;
+			return false;
 		if ((info->bitmask & XT_PHYSDEV_OP_ISIN) &&
 		    !(info->invert & XT_PHYSDEV_OP_ISIN))
-			return NOMATCH;
+			return false;
 		if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) &&
 		    !(info->invert & XT_PHYSDEV_OP_ISOUT))
-			return NOMATCH;
+			return false;
 		if ((info->bitmask & XT_PHYSDEV_OP_IN) &&
 		    !(info->invert & XT_PHYSDEV_OP_IN))
-			return NOMATCH;
+			return false;
 		if ((info->bitmask & XT_PHYSDEV_OP_OUT) &&
 		    !(info->invert & XT_PHYSDEV_OP_OUT))
-			return NOMATCH;
-		return MATCH;
+			return false;
+		return true;
 	}
 
 	/* This only makes sense in the FORWARD and POSTROUTING chains */
 	if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
 	    (!!(nf_bridge->mask & BRNF_BRIDGED) ^
 	    !(info->invert & XT_PHYSDEV_OP_BRIDGED)))
-		return NOMATCH;
+		return false;
 
 	if ((info->bitmask & XT_PHYSDEV_OP_ISIN &&
 	    (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) ||
 	    (info->bitmask & XT_PHYSDEV_OP_ISOUT &&
 	    (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT))))
-		return NOMATCH;
+		return false;
 
 	if (!(info->bitmask & XT_PHYSDEV_OP_IN))
 		goto match_outdev;
 	indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
-	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+	for (i = 0, ret = false; i < IFNAMSIZ/sizeof(unsigned int); i++) {
 		ret |= (((const unsigned int *)indev)[i]
 			^ ((const unsigned int *)info->physindev)[i])
 			& ((const unsigned int *)info->in_mask)[i];
 	}
 
-	if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN))
-		return NOMATCH;
+	if (!ret ^ !(info->invert & XT_PHYSDEV_OP_IN))
+		return false;
 
 match_outdev:
 	if (!(info->bitmask & XT_PHYSDEV_OP_OUT))
-		return MATCH;
+		return true;
 	outdev = nf_bridge->physoutdev ?
 		 nf_bridge->physoutdev->name : nulldevname;
-	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+	for (i = 0, ret = false; i < IFNAMSIZ/sizeof(unsigned int); i++) {
 		ret |= (((const unsigned int *)outdev)[i]
 			^ ((const unsigned int *)info->physoutdev)[i])
 			& ((const unsigned int *)info->out_mask)[i];
 	}
 
-	return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT);
+	return ret ^ !(info->invert & XT_PHYSDEV_OP_OUT);
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 		       const void *ip,
 		       const struct xt_match *match,
@@ -112,7 +110,7 @@
 
 	if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
 	    info->bitmask & ~XT_PHYSDEV_OP_MASK)
-		return 0;
+		return false;
 	if (info->bitmask & XT_PHYSDEV_OP_OUT &&
 	    (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
 	     info->invert & XT_PHYSDEV_OP_BRIDGED) &&
@@ -122,12 +120,12 @@
 		       "OUTPUT, FORWARD and POSTROUTING chains for non-bridged "
 		       "traffic is not supported anymore.\n");
 		if (hook_mask & (1 << NF_IP_LOCAL_OUT))
-			return 0;
+			return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_physdev_match[] = {
+static struct xt_match xt_physdev_match[] __read_mostly = {
 	{
 		.name		= "physdev",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index e1409fc..a52925f 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -21,29 +21,29 @@
 MODULE_ALIAS("ipt_pkttype");
 MODULE_ALIAS("ip6t_pkttype");
 
-static int match(const struct sk_buff *skb,
+static bool match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
       const struct xt_match *match,
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	u_int8_t type;
 	const struct xt_pkttype_info *info = matchinfo;
 
 	if (skb->pkt_type == PACKET_LOOPBACK)
-		type = (MULTICAST(ip_hdr(skb)->daddr)
+		type = MULTICAST(ip_hdr(skb)->daddr)
 			? PACKET_MULTICAST
-			: PACKET_BROADCAST);
+			: PACKET_BROADCAST;
 	else
 		type = skb->pkt_type;
 
 	return (type == info->pkttype) ^ info->invert;
 }
 
-static struct xt_match xt_pkttype_match[] = {
+static struct xt_match xt_pkttype_match[] __read_mostly = {
 	{
 		.name		= "pkttype",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 15b45a9..6d6d3b7 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -20,7 +20,7 @@
 MODULE_DESCRIPTION("Xtables IPsec policy matching module");
 MODULE_LICENSE("GPL");
 
-static inline int
+static inline bool
 xt_addr_cmp(const union xt_policy_addr *a1, const union xt_policy_addr *m,
 	    const union xt_policy_addr *a2, unsigned short family)
 {
@@ -30,11 +30,11 @@
 	case AF_INET6:
 		return !ipv6_masked_addr_cmp(&a1->a6, &m->a6, &a2->a6);
 	}
-	return 0;
+	return false;
 }
 
-static inline int
-match_xfrm_state(struct xfrm_state *x, const struct xt_policy_elem *e,
+static inline bool
+match_xfrm_state(const struct xfrm_state *x, const struct xt_policy_elem *e,
 		 unsigned short family)
 {
 #define MATCH_ADDR(x,y,z)	(!e->match.x ||			       \
@@ -55,7 +55,7 @@
 		unsigned short family)
 {
 	const struct xt_policy_elem *e;
-	struct sec_path *sp = skb->sp;
+	const struct sec_path *sp = skb->sp;
 	int strict = info->flags & XT_POLICY_MATCH_STRICT;
 	int i, pos;
 
@@ -85,7 +85,7 @@
 		 unsigned short family)
 {
 	const struct xt_policy_elem *e;
-	struct dst_entry *dst = skb->dst;
+	const struct dst_entry *dst = skb->dst;
 	int strict = info->flags & XT_POLICY_MATCH_STRICT;
 	int i, pos;
 
@@ -108,14 +108,14 @@
 	return strict ? i == info->len : 0;
 }
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in,
-		 const struct net_device *out,
-		 const struct xt_match *match,
-		 const void *matchinfo,
-		 int offset,
-		 unsigned int protoff,
-		 int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  const struct xt_match *match,
+		  const void *matchinfo,
+		  int offset,
+		  unsigned int protoff,
+		  bool *hotdrop)
 {
 	const struct xt_policy_info *info = matchinfo;
 	int ret;
@@ -126,45 +126,45 @@
 		ret = match_policy_out(skb, info, match->family);
 
 	if (ret < 0)
-		ret = info->flags & XT_POLICY_MATCH_NONE ? 1 : 0;
+		ret = info->flags & XT_POLICY_MATCH_NONE ? true : false;
 	else if (info->flags & XT_POLICY_MATCH_NONE)
-		ret = 0;
+		ret = false;
 
 	return ret;
 }
 
-static int checkentry(const char *tablename, const void *ip_void,
-		      const struct xt_match *match,
-		      void *matchinfo, unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *ip_void,
+		       const struct xt_match *match,
+		       void *matchinfo, unsigned int hook_mask)
 {
 	struct xt_policy_info *info = matchinfo;
 
 	if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
 		printk(KERN_ERR "xt_policy: neither incoming nor "
 				"outgoing policy selected\n");
-		return 0;
+		return false;
 	}
 	/* hook values are equal for IPv4 and IPv6 */
 	if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
 	    && info->flags & XT_POLICY_MATCH_OUT) {
 		printk(KERN_ERR "xt_policy: output policy not valid in "
 				"PRE_ROUTING and INPUT\n");
-		return 0;
+		return false;
 	}
 	if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
 	    && info->flags & XT_POLICY_MATCH_IN) {
 		printk(KERN_ERR "xt_policy: input policy not valid in "
 				"POST_ROUTING and OUTPUT\n");
-		return 0;
+		return false;
 	}
 	if (info->len > XT_POLICY_MAX_ELEM) {
 		printk(KERN_ERR "xt_policy: too many policy elements\n");
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_policy_match[] = {
+static struct xt_match xt_policy_match[] __read_mostly = {
 	{
 		.name		= "policy",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
index bfdde06..dae9744 100644
--- a/net/netfilter/xt_quota.c
+++ b/net/netfilter/xt_quota.c
@@ -16,19 +16,20 @@
 
 static DEFINE_SPINLOCK(quota_lock);
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in, const struct net_device *out,
       const struct xt_match *match, const void *matchinfo,
-      int offset, unsigned int protoff, int *hotdrop)
+      int offset, unsigned int protoff, bool *hotdrop)
 {
-	struct xt_quota_info *q = ((struct xt_quota_info *)matchinfo)->master;
-	int ret = q->flags & XT_QUOTA_INVERT ? 1 : 0;
+	struct xt_quota_info *q =
+		((const struct xt_quota_info *)matchinfo)->master;
+	bool ret = q->flags & XT_QUOTA_INVERT;
 
 	spin_lock_bh(&quota_lock);
 	if (q->quota >= skb->len) {
 		q->quota -= skb->len;
-		ret ^= 1;
+		ret = !ret;
 	} else {
 		/* we do not allow even small packets from now on */
 		q->quota = 0;
@@ -38,21 +39,21 @@
 	return ret;
 }
 
-static int
+static bool
 checkentry(const char *tablename, const void *entry,
 	   const struct xt_match *match, void *matchinfo,
 	   unsigned int hook_mask)
 {
-	struct xt_quota_info *q = (struct xt_quota_info *)matchinfo;
+	struct xt_quota_info *q = matchinfo;
 
 	if (q->flags & ~XT_QUOTA_MASK)
-		return 0;
+		return false;
 	/* For SMP, we only want to use one set of counters. */
 	q->master = q;
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_quota_match[] = {
+static struct xt_match xt_quota_match[] __read_mostly = {
 	{
 		.name		= "quota",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index c2017f8..cc3e76d 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -21,7 +21,7 @@
 MODULE_DESCRIPTION("X_tables realm match");
 MODULE_ALIAS("ipt_realm");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -29,15 +29,15 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_realm_info *info = matchinfo;
-	struct dst_entry *dst = skb->dst;
+	const struct dst_entry *dst = skb->dst;
 
 	return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
 }
 
-static struct xt_match realm_match = {
+static struct xt_match realm_match __read_mostly = {
 	.name		= "realm",
 	.match		= match,
 	.matchsize	= sizeof(struct xt_realm_info),
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index f86d8d7..c002153 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -23,7 +23,7 @@
 #define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
 					      || (!!((invflag) & (option)) ^ (cond)))
 
-static int
+static bool
 match_flags(const struct xt_sctp_flag_info *flag_info,
 	    const int flag_count,
 	    u_int8_t chunktype,
@@ -31,23 +31,21 @@
 {
 	int i;
 
-	for (i = 0; i < flag_count; i++) {
-		if (flag_info[i].chunktype == chunktype) {
+	for (i = 0; i < flag_count; i++)
+		if (flag_info[i].chunktype == chunktype)
 			return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
-		}
-	}
 
-	return 1;
+	return true;
 }
 
-static inline int
+static inline bool
 match_packet(const struct sk_buff *skb,
 	     unsigned int offset,
 	     const u_int32_t *chunkmap,
 	     int chunk_match_type,
 	     const struct xt_sctp_flag_info *flag_info,
 	     const int flag_count,
-	     int *hotdrop)
+	     bool *hotdrop)
 {
 	u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
 	sctp_chunkhdr_t _sch, *sch;
@@ -56,16 +54,15 @@
 	int i = 0;
 #endif
 
-	if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
+	if (chunk_match_type == SCTP_CHUNK_MATCH_ALL)
 		SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
-	}
 
 	do {
 		sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
 		if (sch == NULL || sch->length == 0) {
 			duprintf("Dropping invalid SCTP packet.\n");
-			*hotdrop = 1;
-			return 0;
+			*hotdrop = true;
+			return false;
 		}
 
 		duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
@@ -80,28 +77,26 @@
 			case SCTP_CHUNK_MATCH_ANY:
 				if (match_flags(flag_info, flag_count,
 					sch->type, sch->flags)) {
-					return 1;
+					return true;
 				}
 				break;
 
 			case SCTP_CHUNK_MATCH_ALL:
 				if (match_flags(flag_info, flag_count,
-					sch->type, sch->flags)) {
+				    sch->type, sch->flags))
 					SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type);
-				}
 				break;
 
 			case SCTP_CHUNK_MATCH_ONLY:
 				if (!match_flags(flag_info, flag_count,
-					sch->type, sch->flags)) {
-					return 0;
-				}
+				    sch->type, sch->flags))
+					return false;
 				break;
 			}
 		} else {
 			switch (chunk_match_type) {
 			case SCTP_CHUNK_MATCH_ONLY:
-				return 0;
+				return false;
 			}
 		}
 	} while (offset < skb->len);
@@ -110,16 +105,16 @@
 	case SCTP_CHUNK_MATCH_ALL:
 		return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
 	case SCTP_CHUNK_MATCH_ANY:
-		return 0;
+		return false;
 	case SCTP_CHUNK_MATCH_ONLY:
-		return 1;
+		return true;
 	}
 
 	/* This will never be reached, but required to stop compiler whine */
-	return 0;
+	return false;
 }
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -127,29 +122,29 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_sctp_info *info = matchinfo;
 	sctp_sctphdr_t _sh, *sh;
 
 	if (offset) {
 		duprintf("Dropping non-first fragment.. FIXME\n");
-		return 0;
+		return false;
 	}
 
 	sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh);
 	if (sh == NULL) {
 		duprintf("Dropping evil TCP offset=0 tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 	duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest));
 
-	return  SCCHECK(((ntohs(sh->source) >= info->spts[0])
-			&& (ntohs(sh->source) <= info->spts[1])),
+	return  SCCHECK(ntohs(sh->source) >= info->spts[0]
+			&& ntohs(sh->source) <= info->spts[1],
 			XT_SCTP_SRC_PORTS, info->flags, info->invflags)
-		&& SCCHECK(((ntohs(sh->dest) >= info->dpts[0])
-			&& (ntohs(sh->dest) <= info->dpts[1])),
+		&& SCCHECK(ntohs(sh->dest) >= info->dpts[0]
+			&& ntohs(sh->dest) <= info->dpts[1],
 			XT_SCTP_DEST_PORTS, info->flags, info->invflags)
 		&& SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t),
 					info->chunkmap, info->chunk_match_type,
@@ -158,7 +153,7 @@
 			   XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
 }
 
-static int
+static bool
 checkentry(const char *tablename,
 	   const void *inf,
 	   const struct xt_match *match,
@@ -177,7 +172,7 @@
 				| SCTP_CHUNK_MATCH_ONLY)));
 }
 
-static struct xt_match xt_sctp_match[] = {
+static struct xt_match xt_sctp_match[] __read_mostly = {
 	{
 		.name		= "sctp",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index 149294f..e0a528d 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -20,7 +20,7 @@
 MODULE_ALIAS("ipt_state");
 MODULE_ALIAS("ip6t_state");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -28,7 +28,7 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_state_info *sinfo = matchinfo;
 	enum ip_conntrack_info ctinfo;
@@ -44,18 +44,18 @@
 	return (sinfo->statemask & statebit);
 }
 
-static int check(const char *tablename,
-		 const void *inf,
-		 const struct xt_match *match,
-		 void *matchinfo,
-		 unsigned int hook_mask)
+static bool check(const char *tablename,
+		  const void *inf,
+		  const struct xt_match *match,
+		  void *matchinfo,
+		  unsigned int hook_mask)
 {
 	if (nf_ct_l3proto_try_module_get(match->family) < 0) {
 		printk(KERN_WARNING "can't load conntrack support for "
 				    "proto=%d\n", match->family);
-		return 0;
+		return false;
 	}
-	return 1;
+	return true;
 }
 
 static void
@@ -64,7 +64,7 @@
 	nf_ct_l3proto_module_put(match->family);
 }
 
-static struct xt_match xt_state_match[] = {
+static struct xt_match xt_state_match[] __read_mostly = {
 	{
 		.name		= "state",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c
index 091a9f8..4089dae 100644
--- a/net/netfilter/xt_statistic.c
+++ b/net/netfilter/xt_statistic.c
@@ -24,26 +24,26 @@
 
 static DEFINE_SPINLOCK(nth_lock);
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in, const struct net_device *out,
       const struct xt_match *match, const void *matchinfo,
-      int offset, unsigned int protoff, int *hotdrop)
+      int offset, unsigned int protoff, bool *hotdrop)
 {
 	struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
-	int ret = info->flags & XT_STATISTIC_INVERT ? 1 : 0;
+	bool ret = info->flags & XT_STATISTIC_INVERT;
 
 	switch (info->mode) {
 	case XT_STATISTIC_MODE_RANDOM:
 		if ((net_random() & 0x7FFFFFFF) < info->u.random.probability)
-			ret ^= 1;
+			ret = !ret;
 		break;
 	case XT_STATISTIC_MODE_NTH:
 		info = info->master;
 		spin_lock_bh(&nth_lock);
 		if (info->u.nth.count++ == info->u.nth.every) {
 			info->u.nth.count = 0;
-			ret ^= 1;
+			ret = !ret;
 		}
 		spin_unlock_bh(&nth_lock);
 		break;
@@ -52,21 +52,21 @@
 	return ret;
 }
 
-static int
+static bool
 checkentry(const char *tablename, const void *entry,
 	   const struct xt_match *match, void *matchinfo,
 	   unsigned int hook_mask)
 {
-	struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
+	struct xt_statistic_info *info = matchinfo;
 
 	if (info->mode > XT_STATISTIC_MODE_MAX ||
 	    info->flags & ~XT_STATISTIC_MASK)
-		return 0;
+		return false;
 	info->master = info;
-	return 1;
+	return true;
 }
 
-static struct xt_match xt_statistic_match[] = {
+static struct xt_match xt_statistic_match[] __read_mostly = {
 	{
 		.name		= "statistic",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 999a005..8641334 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -21,14 +21,14 @@
 MODULE_ALIAS("ipt_string");
 MODULE_ALIAS("ip6t_string");
 
-static int match(const struct sk_buff *skb,
-		 const struct net_device *in,
-		 const struct net_device *out,
-		 const struct xt_match *match,
-		 const void *matchinfo,
-		 int offset,
-		 unsigned int protoff,
-		 int *hotdrop)
+static bool match(const struct sk_buff *skb,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  const struct xt_match *match,
+		  const void *matchinfo,
+		  int offset,
+		  unsigned int protoff,
+		  bool *hotdrop)
 {
 	const struct xt_string_info *conf = matchinfo;
 	struct ts_state state;
@@ -42,30 +42,30 @@
 
 #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m)
 
-static int checkentry(const char *tablename,
-		      const void *ip,
-		      const struct xt_match *match,
-		      void *matchinfo,
-		      unsigned int hook_mask)
+static bool checkentry(const char *tablename,
+		       const void *ip,
+		       const struct xt_match *match,
+		       void *matchinfo,
+		       unsigned int hook_mask)
 {
 	struct xt_string_info *conf = matchinfo;
 	struct ts_config *ts_conf;
 
 	/* Damn, can't handle this case properly with iptables... */
 	if (conf->from_offset > conf->to_offset)
-		return 0;
+		return false;
 	if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0')
-		return 0;
+		return false;
 	if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE)
-		return 0;
+		return false;
 	ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
 				     GFP_KERNEL, TS_AUTOLOAD);
 	if (IS_ERR(ts_conf))
-		return 0;
+		return false;
 
 	conf->config = ts_conf;
 
-	return 1;
+	return true;
 }
 
 static void destroy(const struct xt_match *match, void *matchinfo)
@@ -73,7 +73,7 @@
 	textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
 }
 
-static struct xt_match xt_string_match[] = {
+static struct xt_match xt_string_match[] __read_mostly = {
 	{
 		.name 		= "string",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 80571d0..cd5f6d7 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -23,7 +23,7 @@
 MODULE_DESCRIPTION("iptables TCP MSS match module");
 MODULE_ALIAS("ipt_tcpmss");
 
-static int
+static bool
 match(const struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
@@ -31,7 +31,7 @@
       const void *matchinfo,
       int offset,
       unsigned int protoff,
-      int *hotdrop)
+      bool *hotdrop)
 {
 	const struct xt_tcpmss_match_info *info = matchinfo;
 	struct tcphdr _tcph, *th;
@@ -77,11 +77,11 @@
 	return info->invert;
 
 dropit:
-	*hotdrop = 1;
-	return 0;
+	*hotdrop = true;
+	return false;
 }
 
-static struct xt_match xt_tcpmss_match[] = {
+static struct xt_match xt_tcpmss_match[] __read_mostly = {
 	{
 		.name		= "tcpmss",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 46414b5..ab7d845 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -27,22 +27,19 @@
 
 
 /* Returns 1 if the port is matched by the range, 0 otherwise */
-static inline int
-port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
+static inline bool
+port_match(u_int16_t min, u_int16_t max, u_int16_t port, bool invert)
 {
-	int ret;
-
-	ret = (port >= min && port <= max) ^ invert;
-	return ret;
+	return (port >= min && port <= max) ^ invert;
 }
 
-static int
+static bool
 tcp_find_option(u_int8_t option,
 		const struct sk_buff *skb,
 		unsigned int protoff,
 		unsigned int optlen,
-		int invert,
-		int *hotdrop)
+		bool invert,
+		bool *hotdrop)
 {
 	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
 	u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
@@ -57,8 +54,8 @@
 	op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr),
 				optlen, _opt);
 	if (op == NULL) {
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	for (i = 0; i < optlen; ) {
@@ -70,7 +67,7 @@
 	return invert;
 }
 
-static int
+static bool
 tcp_match(const struct sk_buff *skb,
 	  const struct net_device *in,
 	  const struct net_device *out,
@@ -78,7 +75,7 @@
 	  const void *matchinfo,
 	  int offset,
 	  unsigned int protoff,
-	  int *hotdrop)
+	  bool *hotdrop)
 {
 	struct tcphdr _tcph, *th;
 	const struct xt_tcp *tcpinfo = matchinfo;
@@ -92,51 +89,51 @@
 		*/
 		if (offset == 1) {
 			duprintf("Dropping evil TCP offset=1 frag.\n");
-			*hotdrop = 1;
+			*hotdrop = true;
 		}
 		/* Must not be a fragment. */
-		return 0;
+		return false;
 	}
 
-#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
+#define FWINVTCP(bool, invflg) ((bool) ^ !!(tcpinfo->invflags & (invflg)))
 
 	th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
 	if (th == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil TCP offset=0 tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
 			ntohs(th->source),
 			!!(tcpinfo->invflags & XT_TCP_INV_SRCPT)))
-		return 0;
+		return false;
 	if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
 			ntohs(th->dest),
 			!!(tcpinfo->invflags & XT_TCP_INV_DSTPT)))
-		return 0;
+		return false;
 	if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
 		      == tcpinfo->flg_cmp,
 		      XT_TCP_INV_FLAGS))
-		return 0;
+		return false;
 	if (tcpinfo->option) {
 		if (th->doff * 4 < sizeof(_tcph)) {
-			*hotdrop = 1;
-			return 0;
+			*hotdrop = true;
+			return false;
 		}
 		if (!tcp_find_option(tcpinfo->option, skb, protoff,
 				     th->doff*4 - sizeof(_tcph),
 				     tcpinfo->invflags & XT_TCP_INV_OPTION,
 				     hotdrop))
-			return 0;
+			return false;
 	}
-	return 1;
+	return true;
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 tcp_checkentry(const char *tablename,
 	       const void *info,
 	       const struct xt_match *match,
@@ -149,7 +146,7 @@
 	return !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
 }
 
-static int
+static bool
 udp_match(const struct sk_buff *skb,
 	  const struct net_device *in,
 	  const struct net_device *out,
@@ -157,22 +154,22 @@
 	  const void *matchinfo,
 	  int offset,
 	  unsigned int protoff,
-	  int *hotdrop)
+	  bool *hotdrop)
 {
 	struct udphdr _udph, *uh;
 	const struct xt_udp *udpinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
-		return 0;
+		return false;
 
 	uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
 	if (uh == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil UDP tinygram.\n");
-		*hotdrop = 1;
-		return 0;
+		*hotdrop = true;
+		return false;
 	}
 
 	return port_match(udpinfo->spts[0], udpinfo->spts[1],
@@ -184,7 +181,7 @@
 }
 
 /* Called when user tries to insert an entry of this type. */
-static int
+static bool
 udp_checkentry(const char *tablename,
 	       const void *info,
 	       const struct xt_match *match,
@@ -197,7 +194,7 @@
 	return !(udpinfo->invflags & ~XT_UDP_INV_MASK);
 }
 
-static struct xt_match xt_tcpudp_match[] = {
+static struct xt_match xt_tcpudp_match[] __read_mostly = {
 	{
 		.name		= "tcp",
 		.family		= AF_INET,
diff --git a/net/netfilter/xt_u32.c b/net/netfilter/xt_u32.c
new file mode 100644
index 0000000..04b677a
--- /dev/null
+++ b/net/netfilter/xt_u32.c
@@ -0,0 +1,135 @@
+/*
+ *	xt_u32 - kernel module to match u32 packet content
+ *
+ *	Original author: Don Cohen <don@isis.cs3-inc.com>
+ *	© Jan Engelhardt <jengelh@gmx.de>, 2007
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_u32.h>
+
+static bool u32_match_it(const struct xt_u32 *data,
+			 const struct sk_buff *skb)
+{
+	const struct xt_u32_test *ct;
+	unsigned int testind;
+	unsigned int nnums;
+	unsigned int nvals;
+	unsigned int i;
+	u_int32_t pos;
+	u_int32_t val;
+	u_int32_t at;
+	int ret;
+
+	/*
+	 * Small example: "0 >> 28 == 4 && 8 & 0xFF0000 >> 16 = 6, 17"
+	 * (=IPv4 and (TCP or UDP)). Outer loop runs over the "&&" operands.
+	 */
+	for (testind = 0; testind < data->ntests; ++testind) {
+		ct  = &data->tests[testind];
+		at  = 0;
+		pos = ct->location[0].number;
+
+		if (skb->len < 4 || pos > skb->len - 4);
+			return false;
+
+		ret   = skb_copy_bits(skb, pos, &val, sizeof(val));
+		BUG_ON(ret < 0);
+		val   = ntohl(val);
+		nnums = ct->nnums;
+
+		/* Inner loop runs over "&", "<<", ">>" and "@" operands */
+		for (i = 1; i < nnums; ++i) {
+			u_int32_t number = ct->location[i].number;
+			switch (ct->location[i].nextop) {
+			case XT_U32_AND:
+				val &= number;
+				break;
+			case XT_U32_LEFTSH:
+				val <<= number;
+				break;
+			case XT_U32_RIGHTSH:
+				val >>= number;
+				break;
+			case XT_U32_AT:
+				if (at + val < at)
+					return false;
+				at += val;
+				pos = number;
+				if (at + 4 < at || skb->len < at + 4 ||
+				    pos > skb->len - at - 4)
+					return false;
+
+				ret = skb_copy_bits(skb, at + pos, &val,
+						    sizeof(val));
+				BUG_ON(ret < 0);
+				val = ntohl(val);
+				break;
+			}
+		}
+
+		/* Run over the "," and ":" operands */
+		nvals = ct->nvalues;
+		for (i = 0; i < nvals; ++i)
+			if (ct->value[i].min <= val && val <= ct->value[i].max)
+				break;
+
+		if (i >= ct->nvalues)
+			return false;
+	}
+
+	return true;
+}
+
+static bool u32_match(const struct sk_buff *skb,
+		      const struct net_device *in,
+		      const struct net_device *out,
+		      const struct xt_match *match, const void *matchinfo,
+		      int offset, unsigned int protoff, bool *hotdrop)
+{
+	const struct xt_u32 *data = matchinfo;
+	bool ret;
+
+	ret = u32_match_it(data, skb);
+	return ret ^ data->invert;
+}
+
+static struct xt_match u32_reg[] __read_mostly = {
+	{
+		.name       = "u32",
+		.family     = AF_INET,
+		.match      = u32_match,
+		.matchsize  = sizeof(struct xt_u32),
+		.me         = THIS_MODULE,
+	},
+	{
+		.name       = "u32",
+		.family     = AF_INET6,
+		.match      = u32_match,
+		.matchsize  = sizeof(struct xt_u32),
+		.me         = THIS_MODULE,
+	},
+};
+
+static int __init xt_u32_init(void)
+{
+	return xt_register_matches(u32_reg, ARRAY_SIZE(u32_reg));
+}
+
+static void __exit xt_u32_exit(void)
+{
+	xt_unregister_matches(u32_reg, ARRAY_SIZE(u32_reg));
+}
+
+module_init(xt_u32_init);
+module_exit(xt_u32_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
+MODULE_DESCRIPTION("netfilter u32 match module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_u32");
+MODULE_ALIAS("ip6t_u32");
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 1f15821..a3c8e69 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1713,7 +1713,7 @@
 	return 0;
 }
 
-static struct seq_operations netlink_seq_ops = {
+static const struct seq_operations netlink_seq_ops = {
 	.start  = netlink_seq_start,
 	.next   = netlink_seq_next,
 	.stop   = netlink_seq_stop,
diff --git a/net/netlink/attr.c b/net/netlink/attr.c
index c591212..e4d7bed 100644
--- a/net/netlink/attr.c
+++ b/net/netlink/attr.c
@@ -72,6 +72,17 @@
 			return -ERANGE;
 		break;
 
+	case NLA_NESTED_COMPAT:
+		if (attrlen < pt->len)
+			return -ERANGE;
+		if (attrlen < NLA_ALIGN(pt->len))
+			break;
+		if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN)
+			return -ERANGE;
+		nla = nla_data(nla) + NLA_ALIGN(pt->len);
+		if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla))
+			return -ERANGE;
+		break;
 	default:
 		if (pt->len)
 			minlen = pt->len;
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 5d4a26c..5d66490 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1328,7 +1328,7 @@
 	return 0;
 }
 
-static struct seq_operations nr_info_seqops = {
+static const struct seq_operations nr_info_seqops = {
 	.start = nr_info_start,
 	.next = nr_info_next,
 	.stop = nr_info_stop,
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 2f76e062..24fe4a6 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -922,7 +922,7 @@
 	return 0;
 }
 
-static struct seq_operations nr_node_seqops = {
+static const struct seq_operations nr_node_seqops = {
 	.start = nr_node_start,
 	.next = nr_node_next,
 	.stop = nr_node_stop,
@@ -1006,7 +1006,7 @@
 	return 0;
 }
 
-static struct seq_operations nr_neigh_seqops = {
+static const struct seq_operations nr_neigh_seqops = {
 	.start = nr_neigh_start,
 	.next = nr_neigh_next,
 	.stop = nr_neigh_stop,
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index f8b8301..7c27bd3 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1928,7 +1928,7 @@
 	return 0;
 }
 
-static struct seq_operations packet_seq_ops = {
+static const struct seq_operations packet_seq_ops = {
 	.start	= packet_seq_start,
 	.next	= packet_seq_next,
 	.stop	= packet_seq_stop,
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index d476c43..f4d3aba 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1454,7 +1454,7 @@
 	return 0;
 }
 
-static struct seq_operations rose_info_seqops = {
+static const struct seq_operations rose_info_seqops = {
 	.start = rose_info_start,
 	.next = rose_info_next,
 	.stop = rose_info_stop,
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 929a784..bbcbad1 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -1118,7 +1118,7 @@
 	return 0;
 }
 
-static struct seq_operations rose_node_seqops = {
+static const struct seq_operations rose_node_seqops = {
 	.start = rose_node_start,
 	.next = rose_node_next,
 	.stop = rose_node_stop,
@@ -1200,7 +1200,7 @@
 }
 
 
-static struct seq_operations rose_neigh_seqops = {
+static const struct seq_operations rose_neigh_seqops = {
 	.start = rose_neigh_start,
 	.next = rose_neigh_next,
 	.stop = rose_neigh_stop,
@@ -1284,7 +1284,7 @@
 	return 0;
 }
 
-static struct seq_operations rose_route_seqops = {
+static const struct seq_operations rose_route_seqops = {
 	.start = rose_route_start,
 	.next = rose_route_next,
 	.stop = rose_route_stop,
diff --git a/net/rxrpc/ar-proc.c b/net/rxrpc/ar-proc.c
index 1c0be0e..2e83ce3 100644
--- a/net/rxrpc/ar-proc.c
+++ b/net/rxrpc/ar-proc.c
@@ -30,31 +30,13 @@
  */
 static void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos)
 {
-	struct list_head *_p;
-	loff_t pos = *_pos;
-
 	read_lock(&rxrpc_call_lock);
-	if (!pos)
-		return SEQ_START_TOKEN;
-	pos--;
-
-	list_for_each(_p, &rxrpc_calls)
-		if (!pos--)
-			break;
-
-	return _p != &rxrpc_calls ? _p : NULL;
+	return seq_list_start_head(&rxrpc_calls, *_pos);
 }
 
 static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct list_head *_p;
-
-	(*pos)++;
-
-	_p = v;
-	_p = (v == SEQ_START_TOKEN) ? rxrpc_calls.next : _p->next;
-
-	return _p != &rxrpc_calls ? _p : NULL;
+	return seq_list_next(v, &rxrpc_calls, pos);
 }
 
 static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
@@ -68,7 +50,7 @@
 	struct rxrpc_call *call;
 	char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1];
 
-	if (v == SEQ_START_TOKEN) {
+	if (v == &rxrpc_calls) {
 		seq_puts(seq,
 			 "Proto Local                  Remote                "
 			 " SvID ConnID   CallID   End Use State    Abort   "
@@ -104,7 +86,7 @@
 	return 0;
 }
 
-static struct seq_operations rxrpc_call_seq_ops = {
+static const struct seq_operations rxrpc_call_seq_ops = {
 	.start  = rxrpc_call_seq_start,
 	.next   = rxrpc_call_seq_next,
 	.stop   = rxrpc_call_seq_stop,
@@ -129,32 +111,14 @@
  */
 static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos)
 {
-	struct list_head *_p;
-	loff_t pos = *_pos;
-
 	read_lock(&rxrpc_connection_lock);
-	if (!pos)
-		return SEQ_START_TOKEN;
-	pos--;
-
-	list_for_each(_p, &rxrpc_connections)
-		if (!pos--)
-			break;
-
-	return _p != &rxrpc_connections ? _p : NULL;
+	return seq_list_start_head(&rxrpc_connections, *_pos);
 }
 
 static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v,
 				       loff_t *pos)
 {
-	struct list_head *_p;
-
-	(*pos)++;
-
-	_p = v;
-	_p = (v == SEQ_START_TOKEN) ? rxrpc_connections.next : _p->next;
-
-	return _p != &rxrpc_connections ? _p : NULL;
+	return seq_list_next(v, &rxrpc_connections, pos);
 }
 
 static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v)
@@ -168,7 +132,7 @@
 	struct rxrpc_transport *trans;
 	char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1];
 
-	if (v == SEQ_START_TOKEN) {
+	if (v == &rxrpc_connections) {
 		seq_puts(seq,
 			 "Proto Local                  Remote                "
 			 " SvID ConnID   Calls    End Use State    Key     "
@@ -206,7 +170,7 @@
 	return 0;
 }
 
-static struct seq_operations rxrpc_connection_seq_ops = {
+static const struct seq_operations rxrpc_connection_seq_ops = {
 	.start  = rxrpc_connection_seq_start,
 	.next   = rxrpc_connection_seq_next,
 	.stop   = rxrpc_connection_seq_stop,
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 475df84..b466288 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -111,6 +111,17 @@
 	  To compile this code as a module, choose M here: the
 	  module will be called sch_prio.
 
+config NET_SCH_RR
+	tristate "Multi Band Round Robin Queuing (RR)"
+	select NET_SCH_PRIO
+	---help---
+	  Say Y here if you want to use an n-band round robin packet
+	  scheduler.
+
+	  The module uses sch_prio for its framework and is aliased as
+	  sch_rr, so it will load sch_prio, although it is referred
+	  to using sch_rr.
+
 config NET_SCH_RED
 	tristate "Random Early Detection (RED)"
 	---help---
@@ -275,7 +286,6 @@
 config NET_CLS_RSVP
 	tristate "IPv4 Resource Reservation Protocol (RSVP)"
 	select NET_CLS
-	select NET_ESTIMATOR
 	---help---
 	  The Resource Reservation Protocol (RSVP) permits end systems to
 	  request a minimum and maximum data flow rate for a connection; this
@@ -290,7 +300,6 @@
 config NET_CLS_RSVP6
 	tristate "IPv6 Resource Reservation Protocol (RSVP6)"
 	select NET_CLS
-	select NET_ESTIMATOR
 	---help---
 	  The Resource Reservation Protocol (RSVP) permits end systems to
 	  request a minimum and maximum data flow rate for a connection; this
@@ -382,7 +391,6 @@
 
 config NET_CLS_ACT
 	bool "Actions"
-	select NET_ESTIMATOR
 	---help---
 	  Say Y here if you want to use traffic control actions. Actions
 	  get attached to classifiers and are invoked after a successful
@@ -465,7 +473,6 @@
 config NET_CLS_POLICE
 	bool "Traffic Policing (obsolete)"
 	depends on NET_CLS_ACT!=y
-	select NET_ESTIMATOR
 	---help---
 	  Say Y here if you want to do traffic policing, i.e. strict
 	  bandwidth limiting. This option is obsoleted by the traffic
@@ -480,14 +487,6 @@
 	  classification based on the incoming device. This option is
 	  likely to disappear in favour of the metadata ematch.
 
-config NET_ESTIMATOR
-	bool "Rate estimator"
-	---help---
-	  Say Y here to allow using rate estimators to estimate the current
-	  rate-of-flow for network devices, queues, etc. This module is
-	  automatically selected if needed but can be selected manually for
-	  statistical purposes.
-
 endif # NET_SCHED
 
 endmenu
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 711dd26..feef366 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -11,23 +11,13 @@
  *
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/kmod.h>
-#include <net/sock.h>
 #include <net/sch_generic.h>
 #include <net/act_api.h>
 #include <net/netlink.h>
@@ -42,10 +32,8 @@
 			write_lock_bh(hinfo->lock);
 			*p1p = p->tcfc_next;
 			write_unlock_bh(hinfo->lock);
-#ifdef CONFIG_NET_ESTIMATOR
 			gen_kill_estimator(&p->tcfc_bstats,
 					   &p->tcfc_rate_est);
-#endif
 			kfree(p);
 			return;
 		}
@@ -232,15 +220,12 @@
 		p->tcfc_bindcnt = 1;
 
 	spin_lock_init(&p->tcfc_lock);
-	p->tcfc_stats_lock = &p->tcfc_lock;
 	p->tcfc_index = index ? index : tcf_hash_new_index(idx_gen, hinfo);
 	p->tcfc_tm.install = jiffies;
 	p->tcfc_tm.lastuse = jiffies;
-#ifdef CONFIG_NET_ESTIMATOR
 	if (est)
 		gen_new_estimator(&p->tcfc_bstats, &p->tcfc_rate_est,
-				  p->tcfc_stats_lock, est);
-#endif
+				  &p->tcfc_lock, est);
 	a->priv = (void *) p;
 	return p;
 }
@@ -599,12 +584,12 @@
 	if (compat_mode) {
 		if (a->type == TCA_OLD_COMPAT)
 			err = gnet_stats_start_copy_compat(skb, 0,
-				TCA_STATS, TCA_XSTATS, h->tcf_stats_lock, &d);
+				TCA_STATS, TCA_XSTATS, &h->tcf_lock, &d);
 		else
 			return 0;
 	} else
 		err = gnet_stats_start_copy(skb, TCA_ACT_STATS,
-			h->tcf_stats_lock, &d);
+					    &h->tcf_lock, &d);
 
 	if (err < 0)
 		goto errout;
@@ -614,9 +599,7 @@
 			goto errout;
 
 	if (gnet_stats_copy_basic(&d, &h->tcf_bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
 	    gnet_stats_copy_rate_est(&d, &h->tcf_rate_est) < 0 ||
-#endif
 	    gnet_stats_copy_queue(&d, &h->tcf_qstats) < 0)
 		goto errout;
 
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 7517f37..a9631e4 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -10,26 +10,15 @@
  *
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/proc_fs.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <linux/tc_act/tc_gact.h>
 #include <net/tc_act/tc_gact.h>
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 00b05f4..6b407ec 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -11,27 +11,15 @@
  * Copyright:	Jamal Hadi Salim (2002-4)
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/kmod.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <linux/tc_act/tc_ipt.h>
 #include <net/tc_act/tc_ipt.h>
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index de21c92..5795789 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -12,31 +12,19 @@
  *
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/proc_fs.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <linux/tc_act/tc_mirred.h>
 #include <net/tc_act/tc_mirred.h>
 
-#include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 
 #define MIRRED_TAB_MASK     7
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 6f8684b..b46fab5 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -9,26 +9,15 @@
  * Authors:	Jamal Hadi Salim (2002-4)
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/proc_fs.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <linux/tc_act/tc_pedit.h>
 #include <net/tc_act/tc_pedit.h>
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 616f465..d204038 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -10,25 +10,15 @@
  * 		J Hadi Salim (action changes)
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/module.h>
 #include <linux/rtnetlink.h>
 #include <linux/init.h>
-#include <net/sock.h>
 #include <net/act_api.h>
 #include <net/netlink.h>
 
@@ -118,10 +108,8 @@
 			write_lock_bh(&police_lock);
 			*p1p = p->tcf_next;
 			write_unlock_bh(&police_lock);
-#ifdef CONFIG_NET_ESTIMATOR
 			gen_kill_estimator(&p->tcf_bstats,
 					   &p->tcf_rate_est);
-#endif
 			if (p->tcfp_R_tab)
 				qdisc_put_rtab(p->tcfp_R_tab);
 			if (p->tcfp_P_tab)
@@ -185,7 +173,6 @@
 	ret = ACT_P_CREATED;
 	police->tcf_refcnt = 1;
 	spin_lock_init(&police->tcf_lock);
-	police->tcf_stats_lock = &police->tcf_lock;
 	if (bind)
 		police->tcf_bindcnt = 1;
 override:
@@ -227,15 +214,13 @@
 		police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
 	police->tcf_action = parm->action;
 
-#ifdef CONFIG_NET_ESTIMATOR
 	if (tb[TCA_POLICE_AVRATE-1])
 		police->tcfp_ewma_rate =
 			*(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
 	if (est)
 		gen_replace_estimator(&police->tcf_bstats,
 				      &police->tcf_rate_est,
-				      police->tcf_stats_lock, est);
-#endif
+				      &police->tcf_lock, est);
 
 	spin_unlock_bh(&police->tcf_lock);
 	if (ret != ACT_P_CREATED)
@@ -281,14 +266,12 @@
 	police->tcf_bstats.bytes += skb->len;
 	police->tcf_bstats.packets++;
 
-#ifdef CONFIG_NET_ESTIMATOR
 	if (police->tcfp_ewma_rate &&
 	    police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
 		police->tcf_qstats.overlimits++;
 		spin_unlock(&police->tcf_lock);
 		return police->tcf_action;
 	}
-#endif
 
 	if (skb->len <= police->tcfp_mtu) {
 		if (police->tcfp_R_tab == NULL) {
@@ -348,10 +331,8 @@
 	if (police->tcfp_result)
 		RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
 			&police->tcfp_result);
-#ifdef CONFIG_NET_ESTIMATOR
 	if (police->tcfp_ewma_rate)
 		RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
-#endif
 	return skb->len;
 
 rtattr_failure:
@@ -458,7 +439,6 @@
 
 	police->tcf_refcnt = 1;
 	spin_lock_init(&police->tcf_lock);
-	police->tcf_stats_lock = &police->tcf_lock;
 	if (parm->rate.rate) {
 		police->tcfp_R_tab =
 			qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
@@ -477,14 +457,12 @@
 			goto failure;
 		police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
 	}
-#ifdef CONFIG_NET_ESTIMATOR
 	if (tb[TCA_POLICE_AVRATE-1]) {
 		if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32))
 			goto failure;
 		police->tcfp_ewma_rate =
 			*(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
 	}
-#endif
 	police->tcfp_toks = police->tcfp_burst = parm->burst;
 	police->tcfp_mtu = parm->mtu;
 	if (police->tcfp_mtu == 0) {
@@ -498,11 +476,9 @@
 	police->tcf_index = parm->index ? parm->index :
 		tcf_police_new_index();
 	police->tcf_action = parm->action;
-#ifdef CONFIG_NET_ESTIMATOR
 	if (est)
 		gen_new_estimator(&police->tcf_bstats, &police->tcf_rate_est,
-				  police->tcf_stats_lock, est);
-#endif
+				  &police->tcf_lock, est);
 	h = tcf_hash(police->tcf_index, POL_TAB_MASK);
 	write_lock_bh(&police_lock);
 	police->tcf_next = tcf_police_ht[h];
@@ -528,14 +504,12 @@
 	police->tcf_bstats.bytes += skb->len;
 	police->tcf_bstats.packets++;
 
-#ifdef CONFIG_NET_ESTIMATOR
 	if (police->tcfp_ewma_rate &&
 	    police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
 		police->tcf_qstats.overlimits++;
 		spin_unlock(&police->tcf_lock);
 		return police->tcf_action;
 	}
-#endif
 	if (skb->len <= police->tcfp_mtu) {
 		if (police->tcfp_R_tab == NULL) {
 			spin_unlock(&police->tcf_lock);
@@ -591,10 +565,8 @@
 	if (police->tcfp_result)
 		RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
 			&police->tcfp_result);
-#ifdef CONFIG_NET_ESTIMATOR
 	if (police->tcfp_ewma_rate)
 		RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
-#endif
 	return skb->len;
 
 rtattr_failure:
@@ -607,14 +579,12 @@
 	struct gnet_dump d;
 
 	if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
-					 TCA_XSTATS, police->tcf_stats_lock,
+					 TCA_XSTATS, &police->tcf_lock,
 					 &d) < 0)
 		goto errout;
 
 	if (gnet_stats_copy_basic(&d, &police->tcf_bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
 	    gnet_stats_copy_rate_est(&d, &police->tcf_rate_est) < 0 ||
-#endif
 	    gnet_stats_copy_queue(&d, &police->tcf_qstats) < 0)
 		goto errout;
 
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 36e1eda..fb84ef3 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <net/netlink.h>
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index ebf94ed..36b72aa 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -14,26 +14,16 @@
  *
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/kmod.h>
 #include <linux/netlink.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <net/pkt_cls.h>
 
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index c885412..8dbcf27 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -13,7 +13,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/rtnetlink.h>
 #include <linux/skbuff.h>
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index bbec4a0..8adbd6a 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -19,29 +19,12 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <linux/netfilter.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index cc941d0..0a8409c 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -10,28 +10,14 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/dst.h>
+#include <net/route.h>
+#include <net/netlink.h>
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 
diff --git a/net/sched/cls_rsvp.c b/net/sched/cls_rsvp.c
index 0a683c0..cbb5e0d 100644
--- a/net/sched/cls_rsvp.c
+++ b/net/sched/cls_rsvp.c
@@ -10,27 +10,12 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/ip.h>
 #include <net/netlink.h>
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
diff --git a/net/sched/cls_rsvp6.c b/net/sched/cls_rsvp6.c
index 93b6abe..dd08aea 100644
--- a/net/sched/cls_rsvp6.c
+++ b/net/sched/cls_rsvp6.c
@@ -10,28 +10,12 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
 #include <linux/ipv6.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 #include <net/netlink.h>
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 47ac0c5..2314820 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -9,12 +9,9 @@
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <net/ip.h>
 #include <net/act_api.h>
 #include <net/netlink.h>
 #include <net/pkt_cls.h>
-#include <net/route.h>
 
 
 /*
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index c7a347b..77961e2 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -30,30 +30,14 @@
  *	nfmark match added by Catalin(ux aka Dino) BOIE <catab at umbrella.ro>
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
 #include <linux/rtnetlink.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 63146d3..2483739 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -84,9 +84,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/mm.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
 #include <linux/rtnetlink.h>
 #include <linux/skbuff.h>
 #include <net/pkt_cls.h>
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index bec600a..d92ea26 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -19,30 +19,18 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/kmod.h>
 #include <linux/list.h>
-#include <linux/bitops.h>
 #include <linux/hrtimer.h>
 
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
 static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid,
 			struct Qdisc *old, struct Qdisc *new);
 static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n,
@@ -515,7 +503,6 @@
 	sch->handle = handle;
 
 	if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
-#ifdef CONFIG_NET_ESTIMATOR
 		if (tca[TCA_RATE-1]) {
 			err = gen_new_estimator(&sch->bstats, &sch->rate_est,
 						sch->stats_lock,
@@ -531,7 +518,6 @@
 				goto err_out3;
 			}
 		}
-#endif
 		qdisc_lock_tree(dev);
 		list_add_tail(&sch->list, &dev->qdisc_list);
 		qdisc_unlock_tree(dev);
@@ -559,11 +545,9 @@
 		if (err)
 			return err;
 	}
-#ifdef CONFIG_NET_ESTIMATOR
 	if (tca[TCA_RATE-1])
 		gen_replace_estimator(&sch->bstats, &sch->rate_est,
 			sch->stats_lock, tca[TCA_RATE-1]);
-#endif
 	return 0;
 }
 
@@ -839,9 +823,7 @@
 		goto rtattr_failure;
 
 	if (gnet_stats_copy_basic(&d, &q->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
 	    gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 ||
-#endif
 	    gnet_stats_copy_queue(&d, &q->qstats) < 0)
 		goto rtattr_failure;
 
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index d1c383f..54b92d2 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -8,15 +8,12 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/skbuff.h>
-#include <linux/interrupt.h>
 #include <linux/atmdev.h>
 #include <linux/atmclip.h>
-#include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/file.h> /* for fput */
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
-#include <net/sock.h>
 
 
 extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */
@@ -71,7 +68,6 @@
 	int			ref;		/* reference count */
 	struct gnet_stats_basic	bstats;
 	struct gnet_stats_queue	qstats;
-	spinlock_t		*stats_lock;
 	struct atm_flow_data	*next;
 	struct atm_flow_data	*excess;	/* flow for excess traffic;
 						   NULL to set CLP instead */
diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c
index cb0c456..f914fc4 100644
--- a/net/sched/sch_blackhole.c
+++ b/net/sched/sch_blackhole.c
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/pkt_sched.h>
 
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index ee2d596..b184c35 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -11,28 +11,12 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
 #include <net/pkt_sched.h>
 
 
@@ -148,7 +132,6 @@
 	struct gnet_stats_basic bstats;
 	struct gnet_stats_queue qstats;
 	struct gnet_stats_rate_est rate_est;
-	spinlock_t		*stats_lock;
 	struct tc_cbq_xstats	xstats;
 
 	struct tcf_proto	*filter_list;
@@ -1442,7 +1425,6 @@
 	q->link.ewma_log = TC_CBQ_DEF_EWMA;
 	q->link.avpkt = q->link.allot/2;
 	q->link.minidle = -0x7FFFFFFF;
-	q->link.stats_lock = &sch->dev->queue_lock;
 
 	qdisc_watchdog_init(&q->watchdog, sch);
 	hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
@@ -1653,9 +1635,7 @@
 		cl->xstats.undertime = cl->undertime - q->now;
 
 	if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
 	    gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
-#endif
 	    gnet_stats_copy_queue(d, &cl->qstats) < 0)
 		return -1;
 
@@ -1726,9 +1706,7 @@
 	tcf_destroy_chain(cl->filter_list);
 	qdisc_destroy(cl->q);
 	qdisc_put_rtab(cl->R_tab);
-#ifdef CONFIG_NET_ESTIMATOR
 	gen_kill_estimator(&cl->bstats, &cl->rate_est);
-#endif
 	if (cl != &q->link)
 		kfree(cl);
 }
@@ -1873,11 +1851,10 @@
 
 		sch_tree_unlock(sch);
 
-#ifdef CONFIG_NET_ESTIMATOR
 		if (tca[TCA_RATE-1])
 			gen_replace_estimator(&cl->bstats, &cl->rate_est,
-				cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+					      &sch->dev->queue_lock,
+					      tca[TCA_RATE-1]);
 		return 0;
 	}
 
@@ -1935,7 +1912,6 @@
 	cl->allot = parent->allot;
 	cl->quantum = cl->allot;
 	cl->weight = cl->R_tab->rate.rate;
-	cl->stats_lock = &sch->dev->queue_lock;
 
 	sch_tree_lock(sch);
 	cbq_link_class(cl);
@@ -1963,11 +1939,9 @@
 		cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1]));
 	sch_tree_unlock(sch);
 
-#ifdef CONFIG_NET_ESTIMATOR
 	if (tca[TCA_RATE-1])
 		gen_new_estimator(&cl->bstats, &cl->rate_est,
-			cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+				  &sch->dev->queue_lock, tca[TCA_RATE-1]);
 
 	*arg = (unsigned long)cl;
 	return 0;
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 3c6fd18..4d2c233 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -9,7 +9,6 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/skbuff.h>
-#include <linux/netdevice.h> /* for pkt_sched */
 #include <linux/rtnetlink.h>
 #include <net/pkt_sched.h>
 #include <net/dsfield.h>
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index c2689f4..c264308 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -13,7 +13,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/pkt_sched.h>
 
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index f4d3448..c81649c 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -11,27 +11,19 @@
  *              - Ingress support
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
 #include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/init.h>
 #include <linux/rcupdate.h>
 #include <linux/list.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 
 /* Main transmission queue. */
@@ -59,122 +51,143 @@
 	spin_unlock_bh(&dev->queue_lock);
 }
 
+static inline int qdisc_qlen(struct Qdisc *q)
+{
+	return q->q.qlen;
+}
+
+static inline int dev_requeue_skb(struct sk_buff *skb, struct net_device *dev,
+				  struct Qdisc *q)
+{
+	if (unlikely(skb->next))
+		dev->gso_skb = skb;
+	else
+		q->ops->requeue(skb, q);
+
+	netif_schedule(dev);
+	return 0;
+}
+
+static inline struct sk_buff *dev_dequeue_skb(struct net_device *dev,
+					      struct Qdisc *q)
+{
+	struct sk_buff *skb;
+
+	if ((skb = dev->gso_skb))
+		dev->gso_skb = NULL;
+	else
+		skb = q->dequeue(q);
+
+	return skb;
+}
+
+static inline int handle_dev_cpu_collision(struct sk_buff *skb,
+					   struct net_device *dev,
+					   struct Qdisc *q)
+{
+	int ret;
+
+	if (unlikely(dev->xmit_lock_owner == smp_processor_id())) {
+		/*
+		 * Same CPU holding the lock. It may be a transient
+		 * configuration error, when hard_start_xmit() recurses. We
+		 * detect it by checking xmit owner and drop the packet when
+		 * deadloop is detected. Return OK to try the next skb.
+		 */
+		kfree_skb(skb);
+		if (net_ratelimit())
+			printk(KERN_WARNING "Dead loop on netdevice %s, "
+			       "fix it urgently!\n", dev->name);
+		ret = qdisc_qlen(q);
+	} else {
+		/*
+		 * Another cpu is holding lock, requeue & delay xmits for
+		 * some time.
+		 */
+		__get_cpu_var(netdev_rx_stat).cpu_collision++;
+		ret = dev_requeue_skb(skb, dev, q);
+	}
+
+	return ret;
+}
+
 /*
-   dev->queue_lock serializes queue accesses for this device
-   AND dev->qdisc pointer itself.
-
-   netif_tx_lock serializes accesses to device driver.
-
-   dev->queue_lock and netif_tx_lock are mutually exclusive,
-   if one is grabbed, another must be free.
+ * NOTE: Called under dev->queue_lock with locally disabled BH.
+ *
+ * __LINK_STATE_QDISC_RUNNING guarantees only one CPU can process this
+ * device at a time. dev->queue_lock serializes queue accesses for
+ * this device AND dev->qdisc pointer itself.
+ *
+ *  netif_tx_lock serializes accesses to device driver.
+ *
+ *  dev->queue_lock and netif_tx_lock are mutually exclusive,
+ *  if one is grabbed, another must be free.
+ *
+ * Note, that this procedure can be called by a watchdog timer
+ *
+ * Returns to the caller:
+ *				0  - queue is empty or throttled.
+ *				>0 - queue is not empty.
+ *
  */
-
-
-/* Kick device.
-
-   Returns:  0  - queue is empty or throttled.
-	    >0  - queue is not empty.
-
-   NOTE: Called under dev->queue_lock with locally disabled BH.
-*/
-
 static inline int qdisc_restart(struct net_device *dev)
 {
 	struct Qdisc *q = dev->qdisc;
 	struct sk_buff *skb;
+	unsigned lockless;
+	int ret;
 
 	/* Dequeue packet */
-	if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
-		unsigned nolock = (dev->features & NETIF_F_LLTX);
+	if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL))
+		return 0;
 
-		dev->gso_skb = NULL;
+	/*
+	 * When the driver has LLTX set, it does its own locking in
+	 * start_xmit. These checks are worth it because even uncongested
+	 * locks can be quite expensive. The driver can do a trylock, as
+	 * is being done here; in case of lock contention it should return
+	 * NETDEV_TX_LOCKED and the packet will be requeued.
+	 */
+	lockless = (dev->features & NETIF_F_LLTX);
 
-		/*
-		 * When the driver has LLTX set it does its own locking
-		 * in start_xmit. No need to add additional overhead by
-		 * locking again. These checks are worth it because
-		 * even uncongested locks can be quite expensive.
-		 * The driver can do trylock like here too, in case
-		 * of lock congestion it should return -1 and the packet
-		 * will be requeued.
-		 */
-		if (!nolock) {
-			if (!netif_tx_trylock(dev)) {
-			collision:
-				/* So, someone grabbed the driver. */
-
-				/* It may be transient configuration error,
-				   when hard_start_xmit() recurses. We detect
-				   it by checking xmit owner and drop the
-				   packet when deadloop is detected.
-				*/
-				if (dev->xmit_lock_owner == smp_processor_id()) {
-					kfree_skb(skb);
-					if (net_ratelimit())
-						printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
-					goto out;
-				}
-				__get_cpu_var(netdev_rx_stat).cpu_collision++;
-				goto requeue;
-			}
-		}
-
-		{
-			/* And release queue */
-			spin_unlock(&dev->queue_lock);
-
-			if (!netif_queue_stopped(dev)) {
-				int ret;
-
-				ret = dev_hard_start_xmit(skb, dev);
-				if (ret == NETDEV_TX_OK) {
-					if (!nolock) {
-						netif_tx_unlock(dev);
-					}
-					spin_lock(&dev->queue_lock);
-					q = dev->qdisc;
-					goto out;
-				}
-				if (ret == NETDEV_TX_LOCKED && nolock) {
-					spin_lock(&dev->queue_lock);
-					q = dev->qdisc;
-					goto collision;
-				}
-			}
-
-			/* NETDEV_TX_BUSY - we need to requeue */
-			/* Release the driver */
-			if (!nolock) {
-				netif_tx_unlock(dev);
-			}
-			spin_lock(&dev->queue_lock);
-			q = dev->qdisc;
-		}
-
-		/* Device kicked us out :(
-		   This is possible in three cases:
-
-		   0. driver is locked
-		   1. fastroute is enabled
-		   2. device cannot determine busy state
-		      before start of transmission (f.e. dialout)
-		   3. device is buggy (ppp)
-		 */
-
-requeue:
-		if (unlikely(q == &noop_qdisc))
-			kfree_skb(skb);
-		else if (skb->next)
-			dev->gso_skb = skb;
-		else
-			q->ops->requeue(skb, q);
-		netif_schedule(dev);
+	if (!lockless && !netif_tx_trylock(dev)) {
+		/* Another CPU grabbed the driver tx lock */
+		return handle_dev_cpu_collision(skb, dev, q);
 	}
-	return 0;
 
-out:
-	BUG_ON((int) q->q.qlen < 0);
-	return q->q.qlen;
+	/* And release queue */
+	spin_unlock(&dev->queue_lock);
+
+	ret = dev_hard_start_xmit(skb, dev);
+
+	if (!lockless)
+		netif_tx_unlock(dev);
+
+	spin_lock(&dev->queue_lock);
+	q = dev->qdisc;
+
+	switch (ret) {
+	case NETDEV_TX_OK:
+		/* Driver sent out skb successfully */
+		ret = qdisc_qlen(q);
+		break;
+
+	case NETDEV_TX_LOCKED:
+		/* Driver try lock failed */
+		ret = handle_dev_cpu_collision(skb, dev, q);
+		break;
+
+	default:
+		/* Driver returned NETDEV_TX_BUSY - requeue skb */
+		if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit()))
+			printk(KERN_WARNING "BUG %s code %d qlen %d\n",
+			       dev->name, ret, q->q.qlen);
+
+		ret = dev_requeue_skb(skb, dev, q);
+		break;
+	}
+
+	return ret;
 }
 
 void __qdisc_run(struct net_device *dev)
@@ -493,9 +506,7 @@
 		return;
 
 	list_del(&qdisc->list);
-#ifdef CONFIG_NET_ESTIMATOR
 	gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
-#endif
 	if (ops->reset)
 		ops->reset(qdisc);
 	if (ops->destroy)
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index fa1b4fe..3cc6dda 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -21,7 +21,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/pkt_sched.h>
 #include <net/red.h>
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 9d124c4..874452c 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -53,7 +53,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/jiffies.h>
 #include <linux/compiler.h>
 #include <linux/spinlock.h>
 #include <linux/skbuff.h>
@@ -62,13 +61,11 @@
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <linux/init.h>
-#include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/pkt_sched.h>
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
 #include <net/pkt_cls.h>
-#include <asm/system.h>
 #include <asm/div64.h>
 
 /*
@@ -122,7 +119,6 @@
 	struct gnet_stats_basic bstats;
 	struct gnet_stats_queue qstats;
 	struct gnet_stats_rate_est rate_est;
-	spinlock_t	*stats_lock;
 	unsigned int	level;		/* class level in hierarchy */
 	struct tcf_proto *filter_list;	/* filter list */
 	unsigned int	filter_cnt;	/* filter count */
@@ -1054,11 +1050,10 @@
 		}
 		sch_tree_unlock(sch);
 
-#ifdef CONFIG_NET_ESTIMATOR
 		if (tca[TCA_RATE-1])
 			gen_replace_estimator(&cl->bstats, &cl->rate_est,
-				cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+					      &sch->dev->queue_lock,
+					      tca[TCA_RATE-1]);
 		return 0;
 	}
 
@@ -1098,7 +1093,6 @@
 	cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
 	if (cl->qdisc == NULL)
 		cl->qdisc = &noop_qdisc;
-	cl->stats_lock = &sch->dev->queue_lock;
 	INIT_LIST_HEAD(&cl->children);
 	cl->vt_tree = RB_ROOT;
 	cl->cf_tree = RB_ROOT;
@@ -1112,11 +1106,9 @@
 	cl->cl_pcvtoff = parent->cl_cvtoff;
 	sch_tree_unlock(sch);
 
-#ifdef CONFIG_NET_ESTIMATOR
 	if (tca[TCA_RATE-1])
 		gen_new_estimator(&cl->bstats, &cl->rate_est,
-			cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+				  &sch->dev->queue_lock, tca[TCA_RATE-1]);
 	*arg = (unsigned long)cl;
 	return 0;
 }
@@ -1128,9 +1120,7 @@
 
 	tcf_destroy_chain(cl->filter_list);
 	qdisc_destroy(cl->qdisc);
-#ifdef CONFIG_NET_ESTIMATOR
 	gen_kill_estimator(&cl->bstats, &cl->rate_est);
-#endif
 	if (cl != &q->root)
 		kfree(cl);
 }
@@ -1384,9 +1374,7 @@
 	xstats.rtwork  = cl->cl_cumul;
 
 	if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
 	    gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
-#endif
 	    gnet_stats_copy_queue(d, &cl->qstats) < 0)
 		return -1;
 
@@ -1448,8 +1436,6 @@
 		return -EINVAL;
 	qopt = RTA_DATA(opt);
 
-	sch->stats_lock = &sch->dev->queue_lock;
-
 	q->defcls = qopt->defcls;
 	for (i = 0; i < HFSC_HSIZE; i++)
 		INIT_LIST_HEAD(&q->clhash[i]);
@@ -1464,7 +1450,6 @@
 					  sch->handle);
 	if (q->root.qdisc == NULL)
 		q->root.qdisc = &noop_qdisc;
-	q->root.stats_lock = &sch->dev->queue_lock;
 	INIT_LIST_HEAD(&q->root.children);
 	q->root.vt_tree = RB_ROOT;
 	q->root.cf_tree = RB_ROOT;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 035788c..b417a95 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -28,32 +28,16 @@
  * $Id: sch_htb.c,v 1.25 2003/12/07 11:08:25 devik Exp devik $
  */
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
 #include <linux/list.h>
 #include <linux/compiler.h>
-#include <net/netlink.h>
-#include <net/sock.h>
-#include <net/pkt_sched.h>
 #include <linux/rbtree.h>
+#include <net/netlink.h>
+#include <net/pkt_sched.h>
 
 /* HTB algorithm.
     Author: devik@cdi.cz
@@ -69,8 +53,6 @@
 */
 
 #define HTB_HSIZE 16		/* classid hash size */
-#define HTB_EWMAC 2		/* rate average over HTB_EWMAC*HTB_HSIZE sec */
-#define HTB_RATECM 1		/* whether to use rate computer */
 #define HTB_HYSTERESIS 1	/* whether to use mode hysteresis for speedup */
 #define HTB_VER 0x30011		/* major must be matched with number suplied by TC as version */
 
@@ -95,12 +77,6 @@
 	struct tc_htb_xstats xstats;	/* our special stats */
 	int refcnt;		/* usage count of this class */
 
-#ifdef HTB_RATECM
-	/* rate measurement counters */
-	unsigned long rate_bytes, sum_bytes;
-	unsigned long rate_packets, sum_packets;
-#endif
-
 	/* topology */
 	int level;		/* our level (see above) */
 	struct htb_class *parent;	/* parent class */
@@ -153,15 +129,12 @@
 				/* of un.leaf originals should be done. */
 };
 
-/* TODO: maybe compute rate when size is too large .. or drop ? */
 static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate,
 			   int size)
 {
 	int slot = size >> rate->rate.cell_log;
-	if (slot > 255) {
-		cl->xstats.giants++;
-		slot = 255;
-	}
+	if (slot > 255)
+		return (rate->data[255]*(slot >> 8) + rate->data[slot & 0xFF]);
 	return rate->data[slot];
 }
 
@@ -194,10 +167,6 @@
 	int rate2quantum;	/* quant = rate / rate2quantum */
 	psched_time_t now;	/* cached dequeue time */
 	struct qdisc_watchdog watchdog;
-#ifdef HTB_RATECM
-	struct timer_list rttim;	/* rate computer timer */
-	int recmp_bucket;	/* which hash bucket to recompute next */
-#endif
 
 	/* non shaped skbs; let them go directly thru */
 	struct sk_buff_head direct_queue;
@@ -634,13 +603,14 @@
 		cl->qstats.drops++;
 		return NET_XMIT_DROP;
 	} else {
-		cl->bstats.packets++;
+		cl->bstats.packets +=
+			skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
 		cl->bstats.bytes += skb->len;
 		htb_activate(q, cl);
 	}
 
 	sch->q.qlen++;
-	sch->bstats.packets++;
+	sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
 	sch->bstats.bytes += skb->len;
 	return NET_XMIT_SUCCESS;
 }
@@ -677,34 +647,6 @@
 	return NET_XMIT_SUCCESS;
 }
 
-#ifdef HTB_RATECM
-#define RT_GEN(D,R) R+=D-(R/HTB_EWMAC);D=0
-static void htb_rate_timer(unsigned long arg)
-{
-	struct Qdisc *sch = (struct Qdisc *)arg;
-	struct htb_sched *q = qdisc_priv(sch);
-	struct hlist_node *p;
-	struct htb_class *cl;
-
-
-	/* lock queue so that we can muck with it */
-	spin_lock_bh(&sch->dev->queue_lock);
-
-	q->rttim.expires = jiffies + HZ;
-	add_timer(&q->rttim);
-
-	/* scan and recompute one bucket at time */
-	if (++q->recmp_bucket >= HTB_HSIZE)
-		q->recmp_bucket = 0;
-
-	hlist_for_each_entry(cl,p, q->hash + q->recmp_bucket, hlist) {
-		RT_GEN(cl->sum_bytes, cl->rate_bytes);
-		RT_GEN(cl->sum_packets, cl->rate_packets);
-	}
-	spin_unlock_bh(&sch->dev->queue_lock);
-}
-#endif
-
 /**
  * htb_charge_class - charges amount "bytes" to leaf and ancestors
  *
@@ -717,8 +659,9 @@
  * In such case we remove class from event queue first.
  */
 static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
-			     int level, int bytes)
+			     int level, struct sk_buff *skb)
 {
+	int bytes = skb->len;
 	long toks, diff;
 	enum htb_cmode old_mode;
 
@@ -750,16 +693,12 @@
 			if (cl->cmode != HTB_CAN_SEND)
 				htb_add_to_wait_tree(q, cl, diff);
 		}
-#ifdef HTB_RATECM
-		/* update rate counters */
-		cl->sum_bytes += bytes;
-		cl->sum_packets++;
-#endif
 
 		/* update byte stats except for leaves which are already updated */
 		if (cl->level) {
 			cl->bstats.bytes += bytes;
-			cl->bstats.packets++;
+			cl->bstats.packets += skb_is_gso(skb)?
+					skb_shinfo(skb)->gso_segs:1;
 		}
 		cl = cl->parent;
 	}
@@ -943,7 +882,7 @@
 		   gives us slightly better performance */
 		if (!cl->un.leaf.q->q.qlen)
 			htb_deactivate(q, cl);
-		htb_charge_class(q, cl, level, skb->len);
+		htb_charge_class(q, cl, level, skb);
 	}
 	return skb;
 }
@@ -1095,13 +1034,6 @@
 	if (q->direct_qlen < 2)	/* some devices have zero tx_queue_len */
 		q->direct_qlen = 2;
 
-#ifdef HTB_RATECM
-	init_timer(&q->rttim);
-	q->rttim.function = htb_rate_timer;
-	q->rttim.data = (unsigned long)sch;
-	q->rttim.expires = jiffies + HZ;
-	add_timer(&q->rttim);
-#endif
 	if ((q->rate2quantum = gopt->rate2quantum) < 1)
 		q->rate2quantum = 1;
 	q->defcls = gopt->defcls;
@@ -1175,11 +1107,6 @@
 {
 	struct htb_class *cl = (struct htb_class *)arg;
 
-#ifdef HTB_RATECM
-	cl->rate_est.bps = cl->rate_bytes / (HTB_EWMAC * HTB_HSIZE);
-	cl->rate_est.pps = cl->rate_packets / (HTB_EWMAC * HTB_HSIZE);
-#endif
-
 	if (!cl->level && cl->un.leaf.q)
 		cl->qstats.qlen = cl->un.leaf.q->q.qlen;
 	cl->xstats.tokens = cl->tokens;
@@ -1277,6 +1204,7 @@
 		BUG_TRAP(cl->un.leaf.q);
 		qdisc_destroy(cl->un.leaf.q);
 	}
+	gen_kill_estimator(&cl->bstats, &cl->rate_est);
 	qdisc_put_rtab(cl->rate);
 	qdisc_put_rtab(cl->ceil);
 
@@ -1305,9 +1233,6 @@
 	struct htb_sched *q = qdisc_priv(sch);
 
 	qdisc_watchdog_cancel(&q->watchdog);
-#ifdef HTB_RATECM
-	del_timer_sync(&q->rttim);
-#endif
 	/* This line used to be after htb_destroy_class call below
 	   and surprisingly it worked in 2.4. But it must precede it
 	   because filter need its target class alive to be able to call
@@ -1403,6 +1328,20 @@
 	if (!cl) {		/* new class */
 		struct Qdisc *new_q;
 		int prio;
+		struct {
+			struct rtattr		rta;
+			struct gnet_estimator	opt;
+		} est = {
+			.rta = {
+				.rta_len	= RTA_LENGTH(sizeof(est.opt)),
+				.rta_type	= TCA_RATE,
+			},
+			.opt = {
+				/* 4s interval, 16s averaging constant */
+				.interval	= 2,
+				.ewma_log	= 2,
+			},
+		};
 
 		/* check for valid classid */
 		if (!classid || TC_H_MAJ(classid ^ sch->handle)
@@ -1418,6 +1357,9 @@
 		if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
 			goto failure;
 
+		gen_new_estimator(&cl->bstats, &cl->rate_est,
+				  &sch->dev->queue_lock,
+				  tca[TCA_RATE-1] ? : &est.rta);
 		cl->refcnt = 1;
 		INIT_LIST_HEAD(&cl->sibling);
 		INIT_HLIST_NODE(&cl->hlist);
@@ -1469,8 +1411,13 @@
 		hlist_add_head(&cl->hlist, q->hash + htb_hash(classid));
 		list_add_tail(&cl->sibling,
 			      parent ? &parent->children : &q->root);
-	} else
+	} else {
+		if (tca[TCA_RATE-1])
+			gen_replace_estimator(&cl->bstats, &cl->rate_est,
+					      &sch->dev->queue_lock,
+					      tca[TCA_RATE-1]);
 		sch_tree_lock(sch);
+	}
 
 	/* it used to be a nasty bug here, we have to check that node
 	   is really leaf before changing cl->un.leaf ! */
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index f8b9f1c..cd0aab6 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -9,21 +9,14 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/list.h>
 #include <linux/skbuff.h>
-#include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
 #include <linux/netfilter.h>
-#include <linux/smp.h>
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-#include <linux/kmod.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
 
 
 #undef DEBUG_INGRESS
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 5d9d8bc..9e5e87e 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -14,11 +14,9 @@
  */
 
 #include <linux/module.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 6d7542c..2d8c084 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -12,37 +12,23 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
 #include <net/netlink.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 
 
 struct prio_sched_data
 {
 	int bands;
+	int curband; /* for round-robin */
 	struct tcf_proto *filter_list;
 	u8  prio2band[TC_PRIO_MAX+1];
 	struct Qdisc *queues[TCQ_PRIO_BANDS];
+	int mq;
 };
 
 
@@ -70,14 +56,17 @@
 #endif
 			if (TC_H_MAJ(band))
 				band = 0;
-			return q->queues[q->prio2band[band&TC_PRIO_MAX]];
+			band = q->prio2band[band&TC_PRIO_MAX];
+			goto out;
 		}
 		band = res.classid;
 	}
 	band = TC_H_MIN(band) - 1;
 	if (band >= q->bands)
-		return q->queues[q->prio2band[0]];
-
+		band = q->prio2band[0];
+out:
+	if (q->mq)
+		skb_set_queue_mapping(skb, band);
 	return q->queues[band];
 }
 
@@ -144,17 +133,58 @@
 	struct Qdisc *qdisc;
 
 	for (prio = 0; prio < q->bands; prio++) {
-		qdisc = q->queues[prio];
-		skb = qdisc->dequeue(qdisc);
-		if (skb) {
-			sch->q.qlen--;
-			return skb;
+		/* Check if the target subqueue is available before
+		 * pulling an skb.  This way we avoid excessive requeues
+		 * for slower queues.
+		 */
+		if (!netif_subqueue_stopped(sch->dev, (q->mq ? prio : 0))) {
+			qdisc = q->queues[prio];
+			skb = qdisc->dequeue(qdisc);
+			if (skb) {
+				sch->q.qlen--;
+				return skb;
+			}
 		}
 	}
 	return NULL;
 
 }
 
+static struct sk_buff *rr_dequeue(struct Qdisc* sch)
+{
+	struct sk_buff *skb;
+	struct prio_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *qdisc;
+	int bandcount;
+
+	/* Only take one pass through the queues.  If nothing is available,
+	 * return nothing.
+	 */
+	for (bandcount = 0; bandcount < q->bands; bandcount++) {
+		/* Check if the target subqueue is available before
+		 * pulling an skb.  This way we avoid excessive requeues
+		 * for slower queues.  If the queue is stopped, try the
+		 * next queue.
+		 */
+		if (!netif_subqueue_stopped(sch->dev,
+					    (q->mq ? q->curband : 0))) {
+			qdisc = q->queues[q->curband];
+			skb = qdisc->dequeue(qdisc);
+			if (skb) {
+				sch->q.qlen--;
+				q->curband++;
+				if (q->curband >= q->bands)
+					q->curband = 0;
+				return skb;
+			}
+		}
+		q->curband++;
+		if (q->curband >= q->bands)
+			q->curband = 0;
+	}
+	return NULL;
+}
+
 static unsigned int prio_drop(struct Qdisc* sch)
 {
 	struct prio_sched_data *q = qdisc_priv(sch);
@@ -198,21 +228,41 @@
 static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
 {
 	struct prio_sched_data *q = qdisc_priv(sch);
-	struct tc_prio_qopt *qopt = RTA_DATA(opt);
+	struct tc_prio_qopt *qopt;
+	struct rtattr *tb[TCA_PRIO_MAX];
 	int i;
 
-	if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
+	if (rtattr_parse_nested_compat(tb, TCA_PRIO_MAX, opt, qopt,
+				       sizeof(*qopt)))
 		return -EINVAL;
-	if (qopt->bands > TCQ_PRIO_BANDS || qopt->bands < 2)
+	q->bands = qopt->bands;
+	/* If we're multiqueue, make sure the number of incoming bands
+	 * matches the number of queues on the device we're associating with.
+	 * If the number of bands requested is zero, then set q->bands to
+	 * dev->egress_subqueue_count.
+	 */
+	q->mq = RTA_GET_FLAG(tb[TCA_PRIO_MQ - 1]);
+	if (q->mq) {
+		if (sch->handle != TC_H_ROOT)
+			return -EINVAL;
+		if (netif_is_multiqueue(sch->dev)) {
+			if (q->bands == 0)
+				q->bands = sch->dev->egress_subqueue_count;
+			else if (q->bands != sch->dev->egress_subqueue_count)
+				return -EINVAL;
+		} else
+			return -EOPNOTSUPP;
+	}
+
+	if (q->bands > TCQ_PRIO_BANDS || q->bands < 2)
 		return -EINVAL;
 
 	for (i=0; i<=TC_PRIO_MAX; i++) {
-		if (qopt->priomap[i] >= qopt->bands)
+		if (qopt->priomap[i] >= q->bands)
 			return -EINVAL;
 	}
 
 	sch_tree_lock(sch);
-	q->bands = qopt->bands;
 	memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
 
 	for (i=q->bands; i<TCQ_PRIO_BANDS; i++) {
@@ -268,11 +318,17 @@
 {
 	struct prio_sched_data *q = qdisc_priv(sch);
 	unsigned char *b = skb_tail_pointer(skb);
+	struct rtattr *nest;
 	struct tc_prio_qopt opt;
 
 	opt.bands = q->bands;
 	memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX+1);
-	RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+
+	nest = RTA_NEST_COMPAT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+	if (q->mq)
+		RTA_PUT_FLAG(skb, TCA_PRIO_MQ);
+	RTA_NEST_COMPAT_END(skb, nest);
+
 	return skb->len;
 
 rtattr_failure:
@@ -443,17 +499,44 @@
 	.owner		=	THIS_MODULE,
 };
 
+static struct Qdisc_ops rr_qdisc_ops = {
+	.next		=	NULL,
+	.cl_ops		=	&prio_class_ops,
+	.id		=	"rr",
+	.priv_size	=	sizeof(struct prio_sched_data),
+	.enqueue	=	prio_enqueue,
+	.dequeue	=	rr_dequeue,
+	.requeue	=	prio_requeue,
+	.drop		=	prio_drop,
+	.init		=	prio_init,
+	.reset		=	prio_reset,
+	.destroy	=	prio_destroy,
+	.change		=	prio_tune,
+	.dump		=	prio_dump,
+	.owner		=	THIS_MODULE,
+};
+
 static int __init prio_module_init(void)
 {
-	return register_qdisc(&prio_qdisc_ops);
+	int err;
+
+	err = register_qdisc(&prio_qdisc_ops);
+	if (err < 0)
+		return err;
+	err = register_qdisc(&rr_qdisc_ops);
+	if (err < 0)
+		unregister_qdisc(&prio_qdisc_ops);
+	return err;
 }
 
 static void __exit prio_module_exit(void)
 {
 	unregister_qdisc(&prio_qdisc_ops);
+	unregister_qdisc(&rr_qdisc_ops);
 }
 
 module_init(prio_module_init)
 module_exit(prio_module_exit)
 
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("sch_rr");
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 00db53e..9b95fef 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/pkt_sched.h>
 #include <net/inet_ecn.h>
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 96dfdf7..9579573 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -10,31 +10,17 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
 #include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
 #include <linux/init.h>
+#include <linux/ipv6.h>
+#include <linux/skbuff.h>
 #include <net/ip.h>
 #include <net/netlink.h>
-#include <linux/ipv6.h>
-#include <net/route.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 
 
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 5386295..22e431d 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -13,29 +13,12 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/jiffies.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
 #include <net/pkt_sched.h>
 
 
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index f05ad9a..0968184 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -9,30 +9,17 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
 #include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
 #include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
 #include <linux/init.h>
-#include <net/ip.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
 #include <linux/moduleparam.h>
-#include <net/sock.h>
+#include <net/dst.h>
+#include <net/neighbour.h>
 #include <net/pkt_sched.h>
 
 /*
@@ -225,7 +212,6 @@
 	return 0;
 }
 
-/* "teql*" netdevice routines */
 
 static int
 __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev)
@@ -277,6 +263,7 @@
 	int busy;
 	int nores;
 	int len = skb->len;
+	int subq = skb->queue_mapping;
 	struct sk_buff *skb_res = NULL;
 
 	start = master->slaves;
@@ -293,7 +280,9 @@
 
 		if (slave->qdisc_sleeping != q)
 			continue;
-		if (netif_queue_stopped(slave) || ! netif_running(slave)) {
+		if (netif_queue_stopped(slave) ||
+		    netif_subqueue_stopped(slave, subq) ||
+		    !netif_running(slave)) {
 			busy = 1;
 			continue;
 		}
@@ -302,6 +291,7 @@
 		case 0:
 			if (netif_tx_trylock(slave)) {
 				if (!netif_queue_stopped(slave) &&
+				    !netif_subqueue_stopped(slave, subq) &&
 				    slave->hard_start_xmit(skb, slave) == 0) {
 					netif_tx_unlock(slave);
 					master->slaves = NEXT_SLAVE(q);
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 2f12bf2..e4cd841 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -250,7 +250,7 @@
 	return 0;
 }
 
-static struct seq_operations sctp_eps_ops = {
+static const struct seq_operations sctp_eps_ops = {
 	.start = sctp_eps_seq_start,
 	.next  = sctp_eps_seq_next,
 	.stop  = sctp_eps_seq_stop,
@@ -361,7 +361,7 @@
 	return 0;
 }
 
-static struct seq_operations sctp_assoc_ops = {
+static const struct seq_operations sctp_assoc_ops = {
 	.start = sctp_assocs_seq_start,
 	.next  = sctp_assocs_seq_next,
 	.stop  = sctp_assocs_seq_stop,
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 099a983..c094583 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -853,7 +853,7 @@
 	u32 priv_len, maj_stat;
 	int pad, saved_len, remaining_len, offset;
 
-	rqstp->rq_sendfile_ok = 0;
+	rqstp->rq_splice_ok = 0;
 
 	priv_len = svc_getnl(&buf->head[0]);
 	if (rqstp->rq_deferred) {
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 543b085..01c3c41 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -1210,7 +1210,7 @@
 	return cd->cache_show(m, cd, cp);
 }
 
-static struct seq_operations cache_content_op = {
+static const struct seq_operations cache_content_op = {
 	.start	= c_start,
 	.next	= c_next,
 	.stop	= c_stop,
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index e673ef9..55ea6df 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -814,7 +814,7 @@
 	rqstp->rq_res.tail[0].iov_base = NULL;
 	rqstp->rq_res.tail[0].iov_len = 0;
 	/* Will be turned off only in gss privacy case: */
-	rqstp->rq_sendfile_ok = 1;
+	rqstp->rq_splice_ok = 1;
 	/* tcp needs a space for the record length... */
 	if (rqstp->rq_prot == IPPROTO_TCP)
 		svc_putnl(resv, 0);
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 77d2d9c..711ca4b 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -1,8 +1,8 @@
 /*
  * net/tipc/eth_media.c: Ethernet bearer support for TIPC
  *
- * Copyright (c) 2001-2006, Ericsson AB
- * Copyright (c) 2005-2006, Wind River Systems
+ * Copyright (c) 2001-2007, Ericsson AB
+ * Copyright (c) 2005-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -87,6 +87,9 @@
 /**
  * recv_msg - handle incoming TIPC message from an Ethernet interface
  *
+ * Accept only packets explicitly sent to this node, or broadcast packets;
+ * ignores packets sent using Ethernet multicast, and traffic sent to other
+ * nodes (which can happen if interface is running in promiscuous mode).
  * Routine truncates any Ethernet padding/CRC appended to the message,
  * and ensures message size matches actual length
  */
@@ -98,9 +101,7 @@
 	u32 size;
 
 	if (likely(eb_ptr->bearer)) {
-	       if (likely(!dev->promiscuity) ||
-		   !memcmp(skb_mac_header(buf), dev->dev_addr, ETH_ALEN) ||
-		   !memcmp(skb_mac_header(buf), dev->broadcast, ETH_ALEN)) {
+		if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
 			size = msg_size((struct tipc_msg *)buf->data);
 			skb_trim(buf, size);
 			if (likely(buf->len == size)) {
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 2124f32..5adfdfd 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1,8 +1,8 @@
 /*
  * net/tipc/link.c: TIPC link code
  *
- * Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2004-2006, Wind River Systems
+ * Copyright (c) 1996-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -1260,7 +1260,7 @@
 	 * (Must not hold any locks while building message.)
 	 */
 
-	res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt,
+	res = msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt,
 			!sender->user_port, &buf);
 
 	read_lock_bh(&tipc_net_lock);
@@ -1271,7 +1271,7 @@
 		if (likely(l_ptr)) {
 			if (likely(buf)) {
 				res = link_send_buf_fast(l_ptr, buf,
-							 &sender->max_pkt);
+							 &sender->publ.max_pkt);
 				if (unlikely(res < 0))
 					buf_discard(buf);
 exit:
@@ -1299,12 +1299,12 @@
 			 * then re-try fast path or fragment the message
 			 */
 
-			sender->max_pkt = link_max_pkt(l_ptr);
+			sender->publ.max_pkt = link_max_pkt(l_ptr);
 			tipc_node_unlock(node);
 			read_unlock_bh(&tipc_net_lock);
 
 
-			if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt)
+			if ((msg_hdr_sz(hdr) + res) <= sender->publ.max_pkt)
 				goto again;
 
 			return link_send_sections_long(sender, msg_sect,
@@ -1357,7 +1357,7 @@
 
 again:
 	fragm_no = 1;
-	max_pkt = sender->max_pkt - INT_H_SIZE;
+	max_pkt = sender->publ.max_pkt - INT_H_SIZE;
 		/* leave room for tunnel header in case of link changeover */
 	fragm_sz = max_pkt - INT_H_SIZE;
 		/* leave room for fragmentation header in each fragment */
@@ -1463,7 +1463,7 @@
 			goto reject;
 		}
 		if (link_max_pkt(l_ptr) < max_pkt) {
-			sender->max_pkt = link_max_pkt(l_ptr);
+			sender->publ.max_pkt = link_max_pkt(l_ptr);
 			tipc_node_unlock(node);
 			for (; buf_chain; buf_chain = buf) {
 				buf = buf_chain->next;
diff --git a/net/tipc/port.c b/net/tipc/port.c
index bcd5da0..5d2b9ce 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -1,8 +1,8 @@
 /*
  * net/tipc/port.c: TIPC port code
  *
- * Copyright (c) 1992-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 1992-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -239,6 +239,8 @@
 	}
 
 	tipc_port_lock(ref);
+	p_ptr->publ.usr_handle = usr_handle;
+	p_ptr->publ.max_pkt = MAX_PKT_DEFAULT;
 	p_ptr->publ.ref = ref;
 	msg = &p_ptr->publ.phdr;
 	msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0);
@@ -248,11 +250,9 @@
 	msg_set_importance(msg,importance);
 	p_ptr->last_in_seqno = 41;
 	p_ptr->sent = 1;
-	p_ptr->publ.usr_handle = usr_handle;
 	INIT_LIST_HEAD(&p_ptr->wait_list);
 	INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
 	p_ptr->congested_link = NULL;
-	p_ptr->max_pkt = MAX_PKT_DEFAULT;
 	p_ptr->dispatcher = dispatcher;
 	p_ptr->wakeup = wakeup;
 	p_ptr->user_port = NULL;
@@ -1243,7 +1243,7 @@
 	res = TIPC_OK;
 exit:
 	tipc_port_unlock(p_ptr);
-	p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref);
+	p_ptr->publ.max_pkt = tipc_link_get_max_pkt(peer->node, ref);
 	return res;
 }
 
diff --git a/net/tipc/port.h b/net/tipc/port.h
index 7ef4d64..e5f8c16 100644
--- a/net/tipc/port.h
+++ b/net/tipc/port.h
@@ -1,8 +1,8 @@
 /*
  * net/tipc/port.h: Include file for TIPC port code
  *
- * Copyright (c) 1994-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 1994-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -81,7 +81,6 @@
  * @acked:
  * @publications: list of publications for port
  * @pub_count: total # of publications port has made during its lifetime
- * @max_pkt: maximum packet size "hint" used when building messages sent by port
  * @probing_state:
  * @probing_interval:
  * @last_in_seqno:
@@ -102,7 +101,6 @@
 	u32 acked;
 	struct list_head publications;
 	u32 pub_count;
-	u32 max_pkt;
 	u32 probing_state;
 	u32 probing_interval;
 	u32 last_in_seqno;
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 45832fb..4a8f37f 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1,8 +1,8 @@
 /*
  * net/tipc/socket.c: TIPC socket API
  *
- * Copyright (c) 2001-2006, Ericsson AB
- * Copyright (c) 2004-2006, Wind River Systems
+ * Copyright (c) 2001-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -607,23 +607,24 @@
 static int send_stream(struct kiocb *iocb, struct socket *sock,
 		       struct msghdr *m, size_t total_len)
 {
+	struct tipc_port *tport;
 	struct msghdr my_msg;
 	struct iovec my_iov;
 	struct iovec *curr_iov;
 	int curr_iovlen;
 	char __user *curr_start;
+	u32 hdr_size;
 	int curr_left;
 	int bytes_to_send;
 	int bytes_sent;
 	int res;
 
-	if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE))
-		return send_packet(iocb, sock, m, total_len);
-
-	/* Can only send large data streams if already connected */
+	/* Handle special cases where there is no connection */
 
 	if (unlikely(sock->state != SS_CONNECTED)) {
-		if (sock->state == SS_DISCONNECTING)
+		if (sock->state == SS_UNCONNECTED)
+			return send_packet(iocb, sock, m, total_len);
+		else if (sock->state == SS_DISCONNECTING)
 			return -EPIPE;
 		else
 			return -ENOTCONN;
@@ -648,17 +649,25 @@
 	my_msg.msg_name = NULL;
 	bytes_sent = 0;
 
+	tport = tipc_sk(sock->sk)->p;
+	hdr_size = msg_hdr_sz(&tport->phdr);
+
 	while (curr_iovlen--) {
 		curr_start = curr_iov->iov_base;
 		curr_left = curr_iov->iov_len;
 
 		while (curr_left) {
-			bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE)
-				? curr_left : TIPC_MAX_USER_MSG_SIZE;
+			bytes_to_send = tport->max_pkt - hdr_size;
+			if (bytes_to_send > TIPC_MAX_USER_MSG_SIZE)
+				bytes_to_send = TIPC_MAX_USER_MSG_SIZE;
+			if (curr_left < bytes_to_send)
+				bytes_to_send = curr_left;
 			my_iov.iov_base = curr_start;
 			my_iov.iov_len = bytes_to_send;
 			if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) {
-				return bytes_sent ? bytes_sent : res;
+				if (bytes_sent != 0)
+					res = bytes_sent;
+				return res;
 			}
 			curr_left -= bytes_to_send;
 			curr_start += bytes_to_send;
@@ -1600,33 +1609,6 @@
 }
 
 /**
- * Placeholders for non-implemented functionality
- *
- * Returns error code (POSIX-compliant where defined)
- */
-
-static int ioctl(struct socket *s, u32 cmd, unsigned long arg)
-{
-	return -EINVAL;
-}
-
-static int no_mmap(struct file *file, struct socket *sock,
-		   struct vm_area_struct *vma)
-{
-	return -EINVAL;
-}
-static ssize_t no_sendpage(struct socket *sock, struct page *page,
-			   int offset, size_t size, int flags)
-{
-	return -EINVAL;
-}
-
-static int no_skpair(struct socket *s1, struct socket *s2)
-{
-	return -EOPNOTSUPP;
-}
-
-/**
  * Protocol switches for the various types of TIPC sockets
  */
 
@@ -1636,19 +1618,19 @@
 	.release	= release,
 	.bind		= bind,
 	.connect	= connect,
-	.socketpair	= no_skpair,
+	.socketpair	= sock_no_socketpair,
 	.accept		= accept,
 	.getname	= get_name,
 	.poll		= poll,
-	.ioctl		= ioctl,
+	.ioctl		= sock_no_ioctl,
 	.listen		= listen,
 	.shutdown	= shutdown,
 	.setsockopt	= setsockopt,
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_msg,
 	.recvmsg	= recv_msg,
-	.mmap		= no_mmap,
-	.sendpage	= no_sendpage
+        .mmap		= sock_no_mmap,
+        .sendpage	= sock_no_sendpage
 };
 
 static struct proto_ops packet_ops = {
@@ -1657,19 +1639,19 @@
 	.release	= release,
 	.bind		= bind,
 	.connect	= connect,
-	.socketpair	= no_skpair,
+	.socketpair	= sock_no_socketpair,
 	.accept		= accept,
 	.getname	= get_name,
 	.poll		= poll,
-	.ioctl		= ioctl,
+	.ioctl		= sock_no_ioctl,
 	.listen		= listen,
 	.shutdown	= shutdown,
 	.setsockopt	= setsockopt,
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_packet,
 	.recvmsg	= recv_msg,
-	.mmap		= no_mmap,
-	.sendpage	= no_sendpage
+        .mmap		= sock_no_mmap,
+        .sendpage	= sock_no_sendpage
 };
 
 static struct proto_ops stream_ops = {
@@ -1678,19 +1660,19 @@
 	.release	= release,
 	.bind		= bind,
 	.connect	= connect,
-	.socketpair	= no_skpair,
+	.socketpair	= sock_no_socketpair,
 	.accept		= accept,
 	.getname	= get_name,
 	.poll		= poll,
-	.ioctl		= ioctl,
+	.ioctl		= sock_no_ioctl,
 	.listen		= listen,
 	.shutdown	= shutdown,
 	.setsockopt	= setsockopt,
 	.getsockopt	= getsockopt,
 	.sendmsg	= send_stream,
 	.recvmsg	= recv_stream,
-	.mmap		= no_mmap,
-	.sendpage	= no_sendpage
+        .mmap		= sock_no_mmap,
+        .sendpage	= sock_no_sendpage
 };
 
 static struct net_proto_family tipc_family_ops = {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d70fa30..65ebccc 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -592,7 +592,8 @@
 	u->dentry = NULL;
 	u->mnt	  = NULL;
 	spin_lock_init(&u->lock);
-	atomic_set(&u->inflight, sock ? 0 : -1);
+	atomic_set(&u->inflight, 0);
+	INIT_LIST_HEAD(&u->link);
 	mutex_init(&u->readlock); /* single task reading lock */
 	init_waitqueue_head(&u->peer_wait);
 	unix_insert_socket(unix_sockets_unbound, sk);
@@ -1134,9 +1135,6 @@
 	/* take ten and and send info to listening sock */
 	spin_lock(&other->sk_receive_queue.lock);
 	__skb_queue_tail(&other->sk_receive_queue, skb);
-	/* Undo artificially decreased inflight after embrion
-	 * is installed to listening socket. */
-	atomic_inc(&newu->inflight);
 	spin_unlock(&other->sk_receive_queue.lock);
 	unix_state_unlock(other);
 	other->sk_data_ready(other, 0);
@@ -2048,7 +2046,7 @@
 	return 0;
 }
 
-static struct seq_operations unix_seq_ops = {
+static const struct seq_operations unix_seq_ops = {
 	.start  = unix_seq_start,
 	.next   = unix_seq_next,
 	.stop   = unix_seq_stop,
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index f20b7ea..406b643 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -62,6 +62,10 @@
  *	AV		1 Mar 1999
  *		Damn. Added missing check for ->dead in listen queues scanning.
  *
+ *	Miklos Szeredi 25 Jun 2007
+ *		Reimplement with a cycle collecting algorithm. This should
+ *		solve several problems with the previous code, like being racy
+ *		wrt receive and holding up unrelated socket operations.
  */
 
 #include <linux/kernel.h>
@@ -84,10 +88,9 @@
 
 /* Internal data structures and random procedures: */
 
-#define GC_HEAD		((struct sock *)(-1))
-#define GC_ORPHAN	((struct sock *)(-3))
-
-static struct sock *gc_current = GC_HEAD; /* stack of objects to mark */
+static LIST_HEAD(gc_inflight_list);
+static LIST_HEAD(gc_candidates);
+static DEFINE_SPINLOCK(unix_gc_lock);
 
 atomic_t unix_tot_inflight = ATOMIC_INIT(0);
 
@@ -122,8 +125,16 @@
 {
 	struct sock *s = unix_get_socket(fp);
 	if(s) {
-		atomic_inc(&unix_sk(s)->inflight);
+		struct unix_sock *u = unix_sk(s);
+		spin_lock(&unix_gc_lock);
+		if (atomic_inc_return(&u->inflight) == 1) {
+			BUG_ON(!list_empty(&u->link));
+			list_add_tail(&u->link, &gc_inflight_list);
+		} else {
+			BUG_ON(list_empty(&u->link));
+		}
 		atomic_inc(&unix_tot_inflight);
+		spin_unlock(&unix_gc_lock);
 	}
 }
 
@@ -131,182 +142,218 @@
 {
 	struct sock *s = unix_get_socket(fp);
 	if(s) {
-		atomic_dec(&unix_sk(s)->inflight);
+		struct unix_sock *u = unix_sk(s);
+		spin_lock(&unix_gc_lock);
+		BUG_ON(list_empty(&u->link));
+		if (atomic_dec_and_test(&u->inflight))
+			list_del_init(&u->link);
 		atomic_dec(&unix_tot_inflight);
+		spin_unlock(&unix_gc_lock);
 	}
 }
 
-
-/*
- *	Garbage Collector Support Functions
- */
-
-static inline struct sock *pop_stack(void)
+static inline struct sk_buff *sock_queue_head(struct sock *sk)
 {
-	struct sock *p = gc_current;
-	gc_current = unix_sk(p)->gc_tree;
-	return p;
+	return (struct sk_buff *) &sk->sk_receive_queue;
 }
 
-static inline int empty_stack(void)
+#define receive_queue_for_each_skb(sk, next, skb) \
+	for (skb = sock_queue_head(sk)->next, next = skb->next; \
+	     skb != sock_queue_head(sk); skb = next, next = skb->next)
+
+static void scan_inflight(struct sock *x, void (*func)(struct sock *),
+			  struct sk_buff_head *hitlist)
 {
-	return gc_current == GC_HEAD;
+	struct sk_buff *skb;
+	struct sk_buff *next;
+
+	spin_lock(&x->sk_receive_queue.lock);
+	receive_queue_for_each_skb(x, next, skb) {
+		/*
+		 *	Do we have file descriptors ?
+		 */
+		if (UNIXCB(skb).fp) {
+			bool hit = false;
+			/*
+			 *	Process the descriptors of this socket
+			 */
+			int nfd = UNIXCB(skb).fp->count;
+			struct file **fp = UNIXCB(skb).fp->fp;
+			while (nfd--) {
+				/*
+				 *	Get the socket the fd matches
+				 *	if it indeed does so
+				 */
+				struct sock *sk = unix_get_socket(*fp++);
+				if(sk) {
+					hit = true;
+					func(sk);
+				}
+			}
+			if (hit && hitlist != NULL) {
+				__skb_unlink(skb, &x->sk_receive_queue);
+				__skb_queue_tail(hitlist, skb);
+			}
+		}
+	}
+	spin_unlock(&x->sk_receive_queue.lock);
 }
 
-static void maybe_unmark_and_push(struct sock *x)
+static void scan_children(struct sock *x, void (*func)(struct sock *),
+			  struct sk_buff_head *hitlist)
 {
-	struct unix_sock *u = unix_sk(x);
+	if (x->sk_state != TCP_LISTEN)
+		scan_inflight(x, func, hitlist);
+	else {
+		struct sk_buff *skb;
+		struct sk_buff *next;
+		struct unix_sock *u;
+		LIST_HEAD(embryos);
 
-	if (u->gc_tree != GC_ORPHAN)
-		return;
-	sock_hold(x);
-	u->gc_tree = gc_current;
-	gc_current = x;
+		/*
+		 * For a listening socket collect the queued embryos
+		 * and perform a scan on them as well.
+		 */
+		spin_lock(&x->sk_receive_queue.lock);
+		receive_queue_for_each_skb(x, next, skb) {
+			u = unix_sk(skb->sk);
+
+			/*
+			 * An embryo cannot be in-flight, so it's safe
+			 * to use the list link.
+			 */
+			BUG_ON(!list_empty(&u->link));
+			list_add_tail(&u->link, &embryos);
+		}
+		spin_unlock(&x->sk_receive_queue.lock);
+
+		while (!list_empty(&embryos)) {
+			u = list_entry(embryos.next, struct unix_sock, link);
+			scan_inflight(&u->sk, func, hitlist);
+			list_del_init(&u->link);
+		}
+	}
 }
 
+static void dec_inflight(struct sock *sk)
+{
+	atomic_dec(&unix_sk(sk)->inflight);
+}
+
+static void inc_inflight(struct sock *sk)
+{
+	atomic_inc(&unix_sk(sk)->inflight);
+}
+
+static void inc_inflight_move_tail(struct sock *sk)
+{
+	struct unix_sock *u = unix_sk(sk);
+
+	atomic_inc(&u->inflight);
+	/*
+	 * If this is still a candidate, move it to the end of the
+	 * list, so that it's checked even if it was already passed
+	 * over
+	 */
+	if (u->gc_candidate)
+		list_move_tail(&u->link, &gc_candidates);
+}
 
 /* The external entry point: unix_gc() */
 
 void unix_gc(void)
 {
-	static DEFINE_MUTEX(unix_gc_sem);
-	int i;
-	struct sock *s;
+	static bool gc_in_progress = false;
+
+	struct unix_sock *u;
+	struct unix_sock *next;
 	struct sk_buff_head hitlist;
-	struct sk_buff *skb;
+	struct list_head cursor;
 
+	spin_lock(&unix_gc_lock);
+
+	/* Avoid a recursive GC. */
+	if (gc_in_progress)
+		goto out;
+
+	gc_in_progress = true;
 	/*
-	 *	Avoid a recursive GC.
+	 * First, select candidates for garbage collection.  Only
+	 * in-flight sockets are considered, and from those only ones
+	 * which don't have any external reference.
+	 *
+	 * Holding unix_gc_lock will protect these candidates from
+	 * being detached, and hence from gaining an external
+	 * reference.  This also means, that since there are no
+	 * possible receivers, the receive queues of these sockets are
+	 * static during the GC, even though the dequeue is done
+	 * before the detach without atomicity guarantees.
 	 */
+	list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
+		int total_refs;
+		int inflight_refs;
 
-	if (!mutex_trylock(&unix_gc_sem))
-		return;
+		total_refs = file_count(u->sk.sk_socket->file);
+		inflight_refs = atomic_read(&u->inflight);
 
-	spin_lock(&unix_table_lock);
-
-	forall_unix_sockets(i, s)
-	{
-		unix_sk(s)->gc_tree = GC_ORPHAN;
-	}
-	/*
-	 *	Everything is now marked
-	 */
-
-	/* Invariant to be maintained:
-		- everything unmarked is either:
-		-- (a) on the stack, or
-		-- (b) has all of its children unmarked
-		- everything on the stack is always unmarked
-		- nothing is ever pushed onto the stack twice, because:
-		-- nothing previously unmarked is ever pushed on the stack
-	 */
-
-	/*
-	 *	Push root set
-	 */
-
-	forall_unix_sockets(i, s)
-	{
-		int open_count = 0;
-
-		/*
-		 *	If all instances of the descriptor are not
-		 *	in flight we are in use.
-		 *
-		 *	Special case: when socket s is embrion, it may be
-		 *	hashed but still not in queue of listening socket.
-		 *	In this case (see unix_create1()) we set artificial
-		 *	negative inflight counter to close race window.
-		 *	It is trick of course and dirty one.
-		 */
-		if (s->sk_socket && s->sk_socket->file)
-			open_count = file_count(s->sk_socket->file);
-		if (open_count > atomic_read(&unix_sk(s)->inflight))
-			maybe_unmark_and_push(s);
-	}
-
-	/*
-	 *	Mark phase
-	 */
-
-	while (!empty_stack())
-	{
-		struct sock *x = pop_stack();
-		struct sock *sk;
-
-		spin_lock(&x->sk_receive_queue.lock);
-		skb = skb_peek(&x->sk_receive_queue);
-
-		/*
-		 *	Loop through all but first born
-		 */
-
-		while (skb && skb != (struct sk_buff *)&x->sk_receive_queue) {
-			/*
-			 *	Do we have file descriptors ?
-			 */
-			if(UNIXCB(skb).fp)
-			{
-				/*
-				 *	Process the descriptors of this socket
-				 */
-				int nfd=UNIXCB(skb).fp->count;
-				struct file **fp = UNIXCB(skb).fp->fp;
-				while(nfd--)
-				{
-					/*
-					 *	Get the socket the fd matches if
-					 *	it indeed does so
-					 */
-					if((sk=unix_get_socket(*fp++))!=NULL)
-					{
-						maybe_unmark_and_push(sk);
-					}
-				}
-			}
-			/* We have to scan not-yet-accepted ones too */
-			if (x->sk_state == TCP_LISTEN)
-				maybe_unmark_and_push(skb->sk);
-			skb=skb->next;
+		BUG_ON(inflight_refs < 1);
+		BUG_ON(total_refs < inflight_refs);
+		if (total_refs == inflight_refs) {
+			list_move_tail(&u->link, &gc_candidates);
+			u->gc_candidate = 1;
 		}
-		spin_unlock(&x->sk_receive_queue.lock);
-		sock_put(x);
 	}
 
+	/*
+	 * Now remove all internal in-flight reference to children of
+	 * the candidates.
+	 */
+	list_for_each_entry(u, &gc_candidates, link)
+		scan_children(&u->sk, dec_inflight, NULL);
+
+	/*
+	 * Restore the references for children of all candidates,
+	 * which have remaining references.  Do this recursively, so
+	 * only those remain, which form cyclic references.
+	 *
+	 * Use a "cursor" link, to make the list traversal safe, even
+	 * though elements might be moved about.
+	 */
+	list_add(&cursor, &gc_candidates);
+	while (cursor.next != &gc_candidates) {
+		u = list_entry(cursor.next, struct unix_sock, link);
+
+		/* Move cursor to after the current position. */
+		list_move(&cursor, &u->link);
+
+		if (atomic_read(&u->inflight) > 0) {
+			list_move_tail(&u->link, &gc_inflight_list);
+			u->gc_candidate = 0;
+			scan_children(&u->sk, inc_inflight_move_tail, NULL);
+		}
+	}
+	list_del(&cursor);
+
+	/*
+	 * Now gc_candidates contains only garbage.  Restore original
+	 * inflight counters for these as well, and remove the skbuffs
+	 * which are creating the cycle(s).
+	 */
 	skb_queue_head_init(&hitlist);
+	list_for_each_entry(u, &gc_candidates, link)
+		scan_children(&u->sk, inc_inflight, &hitlist);
 
-	forall_unix_sockets(i, s)
-	{
-		struct unix_sock *u = unix_sk(s);
+	spin_unlock(&unix_gc_lock);
 
-		if (u->gc_tree == GC_ORPHAN) {
-			struct sk_buff *nextsk;
-
-			spin_lock(&s->sk_receive_queue.lock);
-			skb = skb_peek(&s->sk_receive_queue);
-			while (skb &&
-			       skb != (struct sk_buff *)&s->sk_receive_queue) {
-				nextsk = skb->next;
-				/*
-				 *	Do we have file descriptors ?
-				 */
-				if (UNIXCB(skb).fp) {
-					__skb_unlink(skb,
-						     &s->sk_receive_queue);
-					__skb_queue_tail(&hitlist, skb);
-				}
-				skb = nextsk;
-			}
-			spin_unlock(&s->sk_receive_queue.lock);
-		}
-		u->gc_tree = GC_ORPHAN;
-	}
-	spin_unlock(&unix_table_lock);
-
-	/*
-	 *	Here we are. Hitlist is filled. Die.
-	 */
-
+	/* Here we are. Hitlist is filled. Die. */
 	__skb_queue_purge(&hitlist);
-	mutex_unlock(&unix_gc_sem);
+
+	spin_lock(&unix_gc_lock);
+
+	/* All candidates should have been detached by now. */
+	BUG_ON(!list_empty(&gc_candidates));
+	gc_in_progress = false;
+
+ out:
+	spin_unlock(&unix_gc_lock);
 }
diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c
index 2051065..236e7ea 100644
--- a/net/wanrouter/wanproc.c
+++ b/net/wanrouter/wanproc.c
@@ -164,14 +164,14 @@
 	return 0;
 }
 
-static struct seq_operations config_op = {
+static const struct seq_operations config_op = {
 	.start	= r_start,
 	.next	= r_next,
 	.stop	= r_stop,
 	.show	= config_show,
 };
 
-static struct seq_operations status_op = {
+static const struct seq_operations status_op = {
 	.start	= r_start,
 	.next	= r_next,
 	.stop	= r_stop,
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c
index 96001f0..7405b9c 100644
--- a/net/x25/x25_proc.c
+++ b/net/x25/x25_proc.c
@@ -234,21 +234,21 @@
 	return 0;
 }
 
-static struct seq_operations x25_seq_route_ops = {
+static const struct seq_operations x25_seq_route_ops = {
 	.start  = x25_seq_route_start,
 	.next   = x25_seq_route_next,
 	.stop   = x25_seq_route_stop,
 	.show   = x25_seq_route_show,
 };
 
-static struct seq_operations x25_seq_socket_ops = {
+static const struct seq_operations x25_seq_socket_ops = {
 	.start  = x25_seq_socket_start,
 	.next   = x25_seq_socket_next,
 	.stop   = x25_seq_socket_stop,
 	.show   = x25_seq_socket_show,
 };
 
-static struct seq_operations x25_seq_forward_ops = {
+static const struct seq_operations x25_seq_forward_ops = {
 	.start  = x25_seq_forward_start,
 	.next   = x25_seq_forward_next,
 	.stop   = x25_seq_forward_stop,
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index dfacb9c..e070c3f 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -686,6 +686,37 @@
 	return x;
 }
 
+struct xfrm_state *
+xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
+		    unsigned short family, u8 mode, u8 proto, u32 reqid)
+{
+	unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family);
+	struct xfrm_state *rx = NULL, *x = NULL;
+	struct hlist_node *entry;
+
+	spin_lock(&xfrm_state_lock);
+	hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
+		if (x->props.family == family &&
+		    x->props.reqid == reqid &&
+		    !(x->props.flags & XFRM_STATE_WILDRECV) &&
+		    xfrm_state_addr_check(x, daddr, saddr, family) &&
+		    mode == x->props.mode &&
+		    proto == x->id.proto &&
+		    x->km.state == XFRM_STATE_VALID) {
+			rx = x;
+			break;
+		}
+	}
+
+	if (rx)
+		xfrm_state_hold(rx);
+	spin_unlock(&xfrm_state_lock);
+
+
+	return rx;
+}
+EXPORT_SYMBOL(xfrm_stateonly_find);
+
 static void __xfrm_state_insert(struct xfrm_state *x)
 {
 	unsigned int h;
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index 5f38f67..a1aa89f 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -118,7 +118,7 @@
 	default: return -1;
 	}
 
-	chip = dev->private;
+	chip = input_get_drvdata(dev);
 	if (! chip || (beep = chip->beep) == NULL)
 		return -1;
 
@@ -239,8 +239,8 @@
 	input_dev->evbit[0] = BIT(EV_SND);
 	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
 	input_dev->event = snd_pmac_beep_event;
-	input_dev->private = chip;
-	input_dev->cdev.dev = &chip->pdev->dev;
+	input_dev->dev.parent = &chip->pdev->dev;
+	input_set_drvdata(input_dev, chip);
 
 	beep->dev = input_dev;
 	beep->buf = dmabuf;
@@ -251,8 +251,8 @@
 	err = snd_ctl_add(chip->card, beep_ctl);
 	if (err < 0)
 		goto fail1;
- 
- 	chip->beep = beep;
+
+	chip->beep = beep;
 
 	err = input_register_device(beep->dev);
 	if (err)