## Automatically generated incremental diff
## From:   linux-2.4.26-rc1
## To:     linux-2.4.26-rc2
## Robot:  $Id: make-incremental-diff,v 1.12 2004/01/06 07:19:36 hpa Exp $

diff -urN linux-2.4.26-rc1/CREDITS linux-2.4.26-rc2/CREDITS
--- linux-2.4.26-rc1/CREDITS	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-rc2/CREDITS	2004-04-05 17:40:56.000000000 -0700
@@ -3386,9 +3386,9 @@
 W: http://www.yoshifuji.org/~hideaki/
 P: 1024D/E0620EEA 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA
 D: IPv6 and other networking related stuff
-D: USAGI/WIDE Project, The University of Tokyo
-S: Green House #102, 1-15-5, Nishikata, 
-S: Bunkyo, Tokyo 113-0024
+D: USAGI/WIDE Project, Keio University
+S: Jeunet Palace Kawasaki #1-201, 10-2, Furukawa-cho, Saiwai-ku
+S: Kawasaki, Kanagawa 212-0025
 S: Japan
 
 N: Eric Youngdale
diff -urN linux-2.4.26-rc1/Documentation/Configure.help linux-2.4.26-rc2/Documentation/Configure.help
--- linux-2.4.26-rc1/Documentation/Configure.help	2004-04-05 17:40:53.000000000 -0700
+++ linux-2.4.26-rc2/Documentation/Configure.help	2004-04-05 17:40:56.000000000 -0700
@@ -1159,6 +1159,14 @@
   This effect can be also invoked by calling "idex=ata66"
   If unsure, say N.
 
+ATI IXP chipset IDE support
+CONFIG_BLK_DEV_ATIIXP
+  This driver adds explicit support for ATI IXP chipset.
+  This allows the kernel to change PIO, DMA and UDMA speeds
+  and to configure the chip to optimum performance.
+
+  Say Y here if you have an ATI IXP chipset IDE controller.
+
 CMD64X/CMD680 chipset support
 CONFIG_BLK_DEV_CMD64X
   Say Y here if you have an IDE controller which uses any of these
@@ -7047,8 +7055,11 @@
 
 Packet socket: mmapped IO
 CONFIG_PACKET_MMAP
-  If you say Y here, the Packet protocol driver will use an IO
-  mechanism that results in faster communication.
+  If you say Y here, the Packet protocol driver can use a faster and 
+  more efficient capture method. This feature also allows bigger 
+  receive buffers. To take advantage of this method who have to use 
+  a libpcap library that supports it. For more info see
+  <file:Documentation/networking/packet_mmap.txt>.
 
   If unsure, say N.
 
diff -urN linux-2.4.26-rc1/Documentation/networking/packet_mmap.txt linux-2.4.26-rc2/Documentation/networking/packet_mmap.txt
--- linux-2.4.26-rc1/Documentation/networking/packet_mmap.txt	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-rc2/Documentation/networking/packet_mmap.txt	2004-04-05 17:40:56.000000000 -0700
@@ -0,0 +1,412 @@
+
+DaveM:
+
+If you agree with it I will send two small patches to modify
+kernel's configure help. 
+
+	Ulisses
+
+--------------------------------------------------------------------------------
++ ABSTRACT
+--------------------------------------------------------------------------------
+
+This file documents the CONFIG_PACKET_MMAP option available with the PACKET
+socket interface on 2.4 and 2.6 kernels. This type of sockets is used for 
+capture network traffic with utilities like tcpdump or any other that uses 
+the libpcap library. 
+
+You can find the latest version of this document at
+
+    http://pusa.uv.es/~ulisses/packet_mmap/
+
+Please send me your comments to
+
+    Ulisses Alonso Camaró <uaca@i.hate.spam.alumni.uv.es>
+
+-------------------------------------------------------------------------------
++ Why use PACKET_MMAP
+--------------------------------------------------------------------------------
+
+In Linux 2.4/2.6 if PACKET_MMAP is not enabled, the capture process is very
+inefficient. It uses very limited buffers and requires one system call
+to capture each packet, it requires two if you want to get packet's 
+timestamp (like libpcap always does).
+
+In the other hand PACKET_MMAP is very efficient. PACKET_MMAP provides a size 
+configurable circular buffer mapped in user space. This way reading packets just 
+needs to wait for them, most of the time there is no need to issue a single 
+system call. By using a shared buffer between the kernel and the user 
+also has the benefit of minimizing packet copies.
+
+It's fine to use PACKET_MMAP to improve the performance of the capture process, 
+but it isn't everything. At least, if you are capturing at high speeds (this 
+is relative to the cpu speed), you should check if the device driver of your 
+network interface card supports some sort of interrupt load mitigation or 
+(even better) if it supports NAPI, also make sure it is enabled.
+
+--------------------------------------------------------------------------------
++ How to use CONFIG_PACKET_MMAP
+--------------------------------------------------------------------------------
+
+From the user standpoint, you should use the higher level libpcap library, wich
+is a de facto standard, portable across nearly all operating systems
+including Win32. 
+
+Said that, at time of this writing, official libpcap 0.8.1 is out and doesn't include
+support for PACKET_MMAP, and also probably the libpcap included in your distribution. 
+
+I'm aware of two implementations of PACKET_MMAP in libpcap:
+
+    http://pusa.uv.es/~ulisses/packet_mmap/  (by Simon Patarin, based on libpcap 0.6.2)
+    http://public.lanl.gov/cpw/              (by Phil Wood, based on lastest libpcap)
+
+The rest of this document is intended for people who want to understand
+the low level details or want to improve libpcap by including PACKET_MMAP
+support.
+
+--------------------------------------------------------------------------------
++ How to use CONFIG_PACKET_MMAP directly
+--------------------------------------------------------------------------------
+
+From the system calls stand point, the use of PACKET_MMAP involves
+the following process:
+
+
+[setup]     socket() -------> creation of the capture socket
+            setsockopt() ---> allocation of the circular buffer (ring)
+            mmap() ---------> maping of the allocated buffer to the
+                              user process
+
+[capture]   poll() ---------> to wait for incoming packets
+
+[shutdown]  close() --------> destruction of the capture socket and
+                              deallocation of all associated 
+                              resources.
+
+
+socket creation and destruction is straight forward, and is done 
+the same way with or without PACKET_MMAP:
+
+int fd;
+
+fd= socket(PF_PACKET, mode, htons(ETH_P_ALL))
+
+where mode is SOCK_RAW for the raw interface were link level
+information can be captured or SOCK_DGRAM for the cooked
+interface where link level information capture is not 
+supported and a link level pseudo-header is provided 
+by the kernel.
+
+The destruction of the socket and all associated resources
+is done by a simple call to close(fd).
+
+Next I will describe PACKET_MMAP settings and it's constraints,
+also the maping of the circular buffer in the user process and 
+the use of this buffer.
+
+--------------------------------------------------------------------------------
++ PACKET_MMAP settings
+--------------------------------------------------------------------------------
+
+
+To setup PACKET_MMAP from user level code is done with a call like
+
+     setsockopt(fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req))
+
+The most significant argument in the previous call is the req parameter, 
+this parameter must to have the following structure:
+
+    struct tpacket_req
+    {
+        unsigned int    tp_block_size;  /* Minimal size of contiguous block */
+        unsigned int    tp_block_nr;    /* Number of blocks */
+        unsigned int    tp_frame_size;  /* Size of frame */
+        unsigned int    tp_frame_nr;    /* Total number of frames */
+    };
+
+This structure is defined in /usr/include/linux/if_packet.h and establishes a 
+circular buffer (ring) of unswappable memory mapped in the capture process. 
+Being mapped in the capture process allows reading the captured frames and 
+related meta-information like timestamps without requiring a system call.
+
+Captured frames are grouped in blocks. Each block is a physically contiguous 
+region of memory and holds tp_block_size/tp_frame_size frames. The total number 
+of blocks is tp_block_nr. Note that tp_frame_nr is a redundant parameter because
+
+    frames_per_block = tp_block_size/tp_frame_size
+
+indeed, packet_set_ring checks that the following condition is true
+
+    frames_per_block * tp_block_nr == tp_frame_nr
+
+
+Lets see an example, with the following values:
+
+     tp_block_size= 4096
+     tp_frame_size= 2048
+     tp_block_nr  = 4
+     tp_frame_nr  = 8
+
+we will get the following buffer structure:
+
+        block #1                 block #2         
++---------+---------+    +---------+---------+    
+| frame 1 | frame 2 |    | frame 3 | frame 4 |    
++---------+---------+    +---------+---------+    
+
+        block #3                 block #4
++---------+---------+    +---------+---------+
+| frame 5 | frame 6 |    | frame 7 | frame 8 |
++---------+---------+    +---------+---------+
+
+A frame can be of any size with the only condition it can fit in a block. A block
+can only hold an integer number of frames, or in other words, a frame cannot 
+be spawn accross two blocks so there are some datails you have to take into 
+account when choosing the frame_size. See "Maping and use of the circular 
+buffer (ring)".
+
+
+--------------------------------------------------------------------------------
++ PACKET_MMAP setting constraints
+--------------------------------------------------------------------------------
+
+In kernel versions prior to 2.4.26 (for the 2.4 branch) and 2.6.5 (2.6 branch),
+the PACKET_MMAP buffer could hold only 32768 frames in a 32 bit architecture or
+16384 in a 64 bit architecture. For information on these kernel versions
+see http://pusa.uv.es/~ulisses/packet_mmap/packet_mmap.pre-2.4.26_2.6.5.txt
+
+ Block size limit
+------------------
+
+As stated earlier, each block is a contiguous physical region of memory. These 
+memory regions are allocated with calls to the __get_free_pages() function. As 
+the name indicates, this function allocates pages of memory, and the second
+argument is "order" or a power of two number of pages, that is 
+(for PAGE_SIZE == 4096) order=0 ==> 4096 bytes, order=1 ==> 8192 bytes, 
+order=2 ==> 16384 bytes, etc. The maximum size of a 
+region allocated by __get_free_pages is determined by the MAX_ORDER macro. More 
+precisely the limit can be calculated as:
+
+   PAGE_SIZE << MAX_ORDER
+
+   In a i386 architecture PAGE_SIZE is 4096 bytes 
+   In a 2.4/i386 kernel MAX_ORDER is 10
+   In a 2.6/i386 kernel MAX_ORDER is 11
+
+So get_free_pages can allocate as much as 4MB or 8MB in a 2.4/2.6 kernel 
+respectively, with an i386 architecture.
+
+User space programs can include /usr/include/sys/user.h and 
+/usr/include/linux/mmzone.h to get PAGE_SIZE MAX_ORDER declarations.
+
+The pagesize can also be determined dynamically with the getpagesize (2) 
+system call. 
+
+
+ Block number limit
+--------------------
+
+To understand the constraints of PACKET_MMAP, we have to see the structure 
+used to hold the pointers to each block.
+
+Currently, this structure is a dynamically allocated vector with kmalloc 
+called pg_vec, its size limits the number of blocks that can be allocated.
+
+    +---+---+---+---+
+    | x | x | x | x |
+    +---+---+---+---+
+      |   |   |   |
+      |   |   |   v
+      |   |   v  block #4
+      |   v  block #3
+      v  block #2
+     block #1
+
+
+kmalloc allocates any number of bytes of phisically contiguous memory from 
+a pool of pre-determined sizes. This pool of memory is mantained by the slab 
+allocator wich is at the end the responsible for doing the allocation and 
+hence wich imposes the maximum memory that kmalloc can allocate. 
+
+In a 2.4/2.6 kernel and the i386 architecture, the limit is 131072 bytes. The 
+predetermined sizes that kmalloc uses can be checked in the "size-<bytes>" 
+entries of /proc/slabinfo
+
+In a 32 bit architecture, pointers are 4 bytes long, so the total number of 
+pointers to blocks is
+
+     131072/4 = 32768 blocks
+
+
+ PACKET_MMAP buffer size calculator
+------------------------------------
+
+Definitions:
+
+<size-max>    : is the maximum size of allocable with kmalloc (see /proc/slabinfo)
+<pointer size>: depends on the architecture -- sizeof(void *)
+<page size>   : depends on the architecture -- PAGE_SIZE or getpagesize (2)
+<max-order>   : is the value defined with MAX_ORDER
+<frame size>  : it's an upper bound of frame's capture size (more on this later)
+
+from these definitions we will derive 
+
+	<block number> = <size-max>/<pointer size>
+	<block size> = <pagesize> << <max-order>
+
+so, the max buffer size is
+
+	<block number> * <block size>
+
+and, the number of frames be
+
+	<block number> * <block size> / <frame size>
+
+Suposse the following parameters, wich apply for 2.6 kernel and an
+i386 architecture:
+
+	<size-max> = 131072 bytes
+	<pointer size> = 4 bytes
+	<pagesize> = 4096 bytes
+	<max-order> = 11
+
+and a value for <frame size> of 2048 byteas. These parameters will yield
+
+	<block number> = 131072/4 = 32768 blocks
+	<block size> = 4096 << 11 = 8 MiB.
+
+and hence the buffer will have a 262144 MiB size. So it can hold 
+262144 MiB / 2048 bytes = 134217728 frames
+
+
+Actually, this buffer size is not possible with an i386 architecture. 
+Remember that the memory is allocated in kernel space, in the case of 
+an i386 kernel's memory size is limited to 1GiB.
+
+All memory allocations are not freed until the socket is closed. The memory 
+allocations are done with GFP_KERNEL priority, this basically means that 
+the allocation can wait and swap other process' memory in order to allocate 
+the nececessary memory, so normally limits can be reached.
+
+ Other constraints
+-------------------
+
+If you check the source code you will see that what I draw here as a frame
+is not only the link level frame. At the begining of each frame there is a 
+header called struct tpacket_hdr used in PACKET_MMAP to hold link level's frame
+meta information like timestamp. So what we draw here a frame it's really 
+the following (from include/linux/if_packet.h):
+
+/*
+   Frame structure:
+
+   - Start. Frame must be aligned to TPACKET_ALIGNMENT=16
+   - struct tpacket_hdr
+   - pad to TPACKET_ALIGNMENT=16
+   - struct sockaddr_ll
+   - Gap, chosen so that packet data (Start+tp_net) alignes to 
+     TPACKET_ALIGNMENT=16
+   - Start+tp_mac: [ Optional MAC header ]
+   - Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
+   - Pad to align to TPACKET_ALIGNMENT=16
+ */
+           
+ 
+ The following are conditions that are checked in packet_set_ring
+
+   tp_block_size must be a multiple of PAGE_SIZE (1)
+   tp_frame_size must be greater than TPACKET_HDRLEN (obvious)
+   tp_frame_size must be a multiple of TPACKET_ALIGNMENT
+   tp_frame_nr   must be exactly frames_per_block*tp_block_nr
+
+Note that tp_block_size should be choosed to be a power of two or there will
+be a waste of memory.
+
+--------------------------------------------------------------------------------
++ Maping and use of the circular buffer (ring)
+--------------------------------------------------------------------------------
+
+The maping of the buffer in the user process is done with the conventional 
+mmap function. Even the circular buffer is compound of several physically
+discontiguous blocks of memory, they are contiguous to the user space, hence
+just one call to mmap is needed:
+
+    mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+If tp_frame_size is a divisor of tp_block_size frames will be 
+contiguosly spaced by tp_frame_size bytes. If not, each 
+tp_block_size/tp_frame_size frames there will be a gap between 
+the frames. This is because a frame cannot be spawn across two
+blocks. 
+
+At the beginning of each frame there is an status field (see 
+struct tpacket_hdr). If this field is 0 means that the frame is ready
+to be used for the kernel, If not, there is a frame the user can read 
+and the following flags apply:
+
+     from include/linux/if_packet.h
+
+     #define TP_STATUS_COPY          2 
+     #define TP_STATUS_LOSING        4 
+     #define TP_STATUS_CSUMNOTREADY  8 
+
+
+TP_STATUS_COPY        : This flag indicates that the frame (and associated
+                        meta information) has been truncated because it's 
+                        larger than tp_frame_size. This packet can be 
+                        read entirely with recvfrom().
+                        
+                        In order to make this work it must to be
+                        enabled previously with setsockopt() and 
+                        the PACKET_COPY_THRESH option. 
+
+                        The number of frames than can be buffered to 
+                        be read with recvfrom is limited like a normal socket.
+                        See the SO_RCVBUF option in the socket (7) man page.
+
+TP_STATUS_LOSING      : indicates there were packet drops from last time 
+                        statistics where checked with getsockopt() and
+                        the PACKET_STATISTICS option.
+
+TP_STATUS_CSUMNOTREADY: currently it's used for outgoing IP packets wich 
+                        it's checksum will be done in hardware. So while 
+                        reading the packet we should not try to check the 
+                        checksum. 
+
+for convenience there are also the following defines:
+
+     #define TP_STATUS_KERNEL        0
+     #define TP_STATUS_USER          1
+
+The kernel initializes all frames to TP_STATUS_KERNEL, when the kernel
+receives a packet it puts in the buffer and updates the status with
+at least the TP_STATUS_USER flag. Then the user can read the packet,
+once the packet is read the user must zero the status field, so the kernel 
+can use again that frame buffer.
+
+The user can use poll (any other variant should apply too) to check if new
+packets are in the ring:
+
+    struct pollfd pfd;
+
+    pfd.fd = fd;
+    pfd.revents = 0;
+    pfd.events = POLLIN|POLLRDNORM|POLLERR;
+
+    if (status == TP_STATUS_KERNEL)
+        retval = poll(&pfd, 1, timeout);
+
+It doesn't incur in a race condition to first check the status value and 
+then poll for frames.
+
+--------------------------------------------------------------------------------
++ THANKS
+--------------------------------------------------------------------------------
+   
+   Jesse Brandeburg, for fixing my grammathical/spelling errors
+
+>>> EOF
+-
+To unsubscribe from this list: send the line "unsubscribe linux-net" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at  http://vger.kernel.org/majordomo-info.html
\ No newline at end of file
diff -urN linux-2.4.26-rc1/Makefile linux-2.4.26-rc2/Makefile
--- linux-2.4.26-rc1/Makefile	2004-04-05 17:40:53.000000000 -0700
+++ linux-2.4.26-rc2/Makefile	2004-04-05 17:40:56.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 26
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.26-rc1/arch/i386/kernel/acpi.c linux-2.4.26-rc2/arch/i386/kernel/acpi.c
--- linux-2.4.26-rc1/arch/i386/kernel/acpi.c	2004-04-05 17:40:53.000000000 -0700
+++ linux-2.4.26-rc2/arch/i386/kernel/acpi.c	2004-04-05 17:40:57.000000000 -0700
@@ -590,6 +590,10 @@
 
 
 
+#ifndef __HAVE_ARCH_CMPXCHG
+#warning ACPI uses CMPXCHG, i486 and later hardware
+#endif
+
 /* --------------------------------------------------------------------------
                               Low-Level Sleep Support
    -------------------------------------------------------------------------- */
diff -urN linux-2.4.26-rc1/arch/i386/kernel/io_apic.c linux-2.4.26-rc2/arch/i386/kernel/io_apic.c
--- linux-2.4.26-rc1/arch/i386/kernel/io_apic.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-rc2/arch/i386/kernel/io_apic.c	2004-04-05 17:40:57.000000000 -0700
@@ -1864,7 +1864,11 @@
 	entry.trigger = edge_level;
 	entry.polarity = active_high_low;
 
-	add_pin_to_irq(irq, ioapic, pin);
+	/*
+	 * IRQs < 16 are already in the irq_2_pin[] map
+	 */
+	if (irq >= 16)
+		add_pin_to_irq(irq, ioapic, pin);
 
 	entry.vector = assign_irq_vector(irq);
 
diff -urN linux-2.4.26-rc1/arch/ppc/boot/common/misc-simple.c linux-2.4.26-rc2/arch/ppc/boot/common/misc-simple.c
--- linux-2.4.26-rc1/arch/ppc/boot/common/misc-simple.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/boot/common/misc-simple.c	2004-04-05 17:40:57.000000000 -0700
@@ -75,7 +75,7 @@
 extern void gunzip(void *, int, unsigned char *, int *);
 extern void serial_fixups(void);
 
-static struct bi_record *
+struct bi_record *
 decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
 		void *ignored)
 {
diff -urN linux-2.4.26-rc1/arch/ppc/kernel/Makefile linux-2.4.26-rc2/arch/ppc/kernel/Makefile
--- linux-2.4.26-rc1/arch/ppc/kernel/Makefile	2004-04-05 17:40:53.000000000 -0700
+++ linux-2.4.26-rc2/arch/ppc/kernel/Makefile	2004-04-05 17:40:57.000000000 -0700
@@ -55,15 +55,16 @@
 obj-$(CONFIG_SERIAL_TEXT_DEBUG)	+= gen550_dbg.o
 endif
 obj-$(CONFIG_PPC_OCP)		+= ocp.o
-obj-$(CONFIG_40x)		+= ppc4xx_setup.o
-obj-$(CONFIG_4xx)		+= ppc4xx_pic.o todc_time.o
+obj-$(CONFIG_40x)		+= ppc4xx_setup.o ppc4xx_pic.o
+obj-$(CONFIG_4xx)		+= todc_time.o
 obj-$(CONFIG_STBXXX_DMA)	+= ppc4xx_stbdma.o
 ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_40x)		+= ppc405_pci.o
 obj-$(CONFIG_4xx)		+= indirect_pci.o pci_auto.o
 endif
-obj-$(CONFIG_44x)		+= ibm44x_common.o
+obj-$(CONFIG_44x)		+= ppc4xx_pic.o ibm44x_common.o
 obj-$(CONFIG_440GP)		+= ibm440gp_common.o
+obj-$(CONFIG_440GX)		+= ibm440gx_common.o
 obj-$(CONFIG_PPC4xx_DMA)	+= ppc4xx_dma.o
 obj-$(CONFIG_PPC4xx_EDMA)	+= ppc4xx_sgdma.o
 obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o
diff -urN linux-2.4.26-rc1/arch/ppc/kernel/cputable.c linux-2.4.26-rc2/arch/ppc/kernel/cputable.c
--- linux-2.4.26-rc1/arch/ppc/kernel/cputable.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/kernel/cputable.c	2004-04-05 17:40:57.000000000 -0700
@@ -417,6 +417,20 @@
         32, 32,
         0, /*__setup_cpu_440 */
     },
+    { /* 440GX Rev. B */
+        0xf0000fff, 0x50000851, "440GX Rev. B",
+        CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
+        PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+        32, 32,
+        0, /*__setup_cpu_440 */
+    },
+    { /* 440GX Rev. B1 (2.1) */
+        0xf0000fff, 0x50000852, "440GX Rev. B1 (2.1)",
+        CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
+        PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+        32, 32,
+        0, /*__setup_cpu_440 */
+    },
 #endif /* CONFIG_44x */
 #if !CLASSIC_PPC
     {	/* default match */
diff -urN linux-2.4.26-rc1/arch/ppc/kernel/head_44x.S linux-2.4.26-rc2/arch/ppc/kernel/head_44x.S
--- linux-2.4.26-rc1/arch/ppc/kernel/head_44x.S	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/kernel/head_44x.S	2004-04-05 17:40:57.000000000 -0700
@@ -30,6 +30,16 @@
 #define STND_EXC        0
 #define CRIT_EXC        1
 
+#ifdef CONFIG_440A
+#define MCHK_EXC	2
+#define __SPRN_MCSRR0	SPRN_MCSRR0
+#define __SPRN_MCSRR1	SPRN_MCSRR1
+#else
+#define MCHK_EXC	CRIT_EXC
+#define __SPRN_MCSRR0	SPRN_CSRR0
+#define __SPRN_MCSRR1	SPRN_CSRR1
+#endif
+
 /*
  * Macros
  */
@@ -396,7 +406,25 @@
 
 	/* Machine Check Interrupt */
 	/* TODO: provide bus error register status */
-	CRIT_EXCEPTION(0x200, MachineCheck,MachineCheckException);
+	START_EXCEPTION(MachineCheck)
+	COMMON_PROLOG;
+	mfspr   r22,__SPRN_MCSRR0       /* Faulting instruction address    */
+	lis     r20,MSR_WE@h
+	mfspr   r23,__SPRN_MCSRR1       /* MSR at the time of fault        */
+	andc    r23,r23,r20             /* disable processor wait state    */
+	COMMON_EPILOG;
+#ifdef CONFIG_440A
+	lis	r20,MCSR_MCS@h
+	mfspr	r4,SPRN_MCSR		/* We may want to access original
+					   MCSR as arg2 in the future. --ebs */
+	mtspr	SPRN_MCSR,r20		/* Clear Machine Check Summary field */
+#endif	
+	mfspr	r5,SPRN_ESR		/* Grab the ESR, save it */
+	stw	r5,_ESR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	li	r7,MCHK_EXC
+	li	r20,MSR_KERNEL
+	FINISH_EXCEPTION(0x200, MachineCheckException)
 
 	/* Data Storage Interrupt */
 	START_EXCEPTION(DataStorage)
@@ -415,7 +443,7 @@
 	 * offending address and handle it.
 	 */
 	mfspr	r20, SPRN_ESR
-	andis.	r20, r20, ESR_ST@h
+	andis.	r20, r20, ESR_DST@h
 	beq	2f
 
 	mfspr	r20, SPRN_DEAR		/* Get faulting address */
@@ -994,7 +1022,7 @@
 	lwz	r24,0(r23)		/* Virtual address of the handler */
 	lwz	r23,4(r23)		/* Handler return pointer */
 	cmpwi	cr0,r7,STND_EXC		/* What type of exception is this? */
-	bne	3f			/* It is a critical exception... */
+	bne	3f			/* It is a critical/machine check exception... */
 
 	/* Standard exception jump path
 	*/
@@ -1010,19 +1038,23 @@
 	mtspr	SPRN_SRR1,r20		/* Set up the machine state register */
 	mtlr	r23			/* Set up the return pointer */
 	SYNC
-	/* We shouldn't need a 405 erratum #77 workaround here, because we're not
-	 * actually returning to the interrupted instruction yet. */
 	rfi
 
-	/* Critical exception jump path
+	/* Critical/Machine check exception jump path
 	*/
-
-3:	mtspr	SPRN_CSRR0,r24		/* Set up the instruction pointer */
-	mtspr	SPRN_CSRR1,r20		/* Set up the machine state register */
+3:	cmpwi	r7,CRIT_EXC		/* Critical or machine check ? */
 	mtlr	r23			/* Set up the return pointer */
+	bne	4f
+	mtspr	SPRN_CSRR0,r24		/* Set up the instruction pointer */
+	mtspr	SPRN_CSRR1,r20		/* Set up the machine state register */
 	SYNC
 	rfci
 
+4:	mtspr	SPRN_MCSRR0,r24		/* Set up the instruction pointer */
+	mtspr	SPRN_MCSRR1,r20		/* Set up the machine state register */
+	SYNC	
+	RFMCI
+
 /* On kernel stack overlow, load up an initial stack pointer and call
  * StackOverflow(regs), which should NOT return.
  */ 
diff -urN linux-2.4.26-rc1/arch/ppc/kernel/ibm440gp_common.c linux-2.4.26-rc2/arch/ppc/kernel/ibm440gp_common.c
--- linux-2.4.26-rc1/arch/ppc/kernel/ibm440gp_common.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/kernel/ibm440gp_common.c	2004-04-05 17:40:57.000000000 -0700
@@ -25,7 +25,7 @@
 /*
  * Calculate 440GP clocks
  */
-void __init ibm440gp_get_clocks(struct ibm440gp_clocks* p, unsigned int sys_clk, 
+void __init ibm440gp_get_clocks(struct ibm44x_clocks* p, unsigned int sys_clk, 
 	unsigned int ser_clk)
 {
 	u32 cpc0_sys0 = mfdcr(DCRN_CPC0_SYS0);
@@ -68,11 +68,11 @@
     
 	if (cpc0_cr0 & 0x00400000){
 		/* External UART clock */
-		p->uart = ser_clk;
+		p->uart0 = p->uart1 = ser_clk;
 	}
 	else {
 		/* Internal UART clock */    
     		u32 uart_div = ((cpc0_cr0 >> 16) & 0x1f) + 1;
-		p->uart = p->plb / uart_div;
+		p->uart0 = p->uart1 = p->plb / uart_div;
 	}
 }
diff -urN linux-2.4.26-rc1/arch/ppc/kernel/ibm440gp_common.h linux-2.4.26-rc2/arch/ppc/kernel/ibm440gp_common.h
--- linux-2.4.26-rc1/arch/ppc/kernel/ibm440gp_common.h	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/kernel/ibm440gp_common.h	2004-04-05 17:40:57.000000000 -0700
@@ -20,24 +20,14 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
-
-/*
- * All clocks are in Hz
- */
-struct ibm440gp_clocks {
-	unsigned int cpu;	/* CPUCoreClk */
-	unsigned int plb;	/* PLBClk */
-	unsigned int opb;	/* OPBClk */
-	unsigned int ebc;	/* PerClk */
-	unsigned int uart;	
-};
+#include <kernel/ibm44x_common.h>
 
 /*
  * Please, refer to the Figure 13.1 in 440GP user manual
  * 
  * if internal UART clock is used, ser_clk is ignored
  */
-void ibm440gp_get_clocks(struct ibm440gp_clocks*, unsigned int sys_clk, 
+void ibm440gp_get_clocks(struct ibm44x_clocks*, unsigned int sys_clk, 
 	unsigned int ser_clk) __init;
  
 #endif /* __ASSEMBLY__ */
diff -urN linux-2.4.26-rc1/arch/ppc/kernel/ibm440gx_common.c linux-2.4.26-rc2/arch/ppc/kernel/ibm440gx_common.c
--- linux-2.4.26-rc1/arch/ppc/kernel/ibm440gx_common.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/kernel/ibm440gx_common.c	2004-04-05 17:40:57.000000000 -0700
@@ -0,0 +1,191 @@
+/*
+ * arch/ppc/kernel/ibm440gx_common.c
+ *
+ * PPC440GX system library
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003 Zultys Technologies
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/ibm44x.h>
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <kernel/ibm440gx_common.h>
+
+/*
+ * Calculate 440GX clocks
+ */
+static inline u32 __fix_zero(u32 v, u32 def){
+	return v ? v : def;
+}
+ 
+void __init ibm440gx_get_clocks(struct ibm44x_clocks* p, unsigned int sys_clk, 
+	unsigned int ser_clk)
+{
+	u32 pllc  = CPR_READ(DCRN_CPR_PLLC);
+	u32 plld  = CPR_READ(DCRN_CPR_PLLD);
+	u32 uart0 = SDR_READ(DCRN_SDR_UART0);
+	u32 uart1 = SDR_READ(DCRN_SDR_UART1);
+	
+	/* Dividers */
+	u32 fbdv   = __fix_zero((plld >> 24) & 0x1f, 32);
+	u32 fwdva  = __fix_zero((plld >> 16) & 0xf, 16);
+	u32 fwdvb  = __fix_zero((plld >> 8) & 7, 8);
+	u32 lfbdv  = __fix_zero(plld & 0x3f, 64);
+	u32 pradv0 = __fix_zero((CPR_READ(DCRN_CPR_PRIMAD) >> 24) & 7, 8);
+	u32 prbdv0 = __fix_zero((CPR_READ(DCRN_CPR_PRIMBD) >> 24) & 7, 8);
+	u32 opbdv0 = __fix_zero((CPR_READ(DCRN_CPR_OPBD) >> 24) & 3, 4);
+	u32 perdv0 = __fix_zero((CPR_READ(DCRN_CPR_PERD) >> 24) & 3, 4);
+
+	/* Input clocks for primary dividers */	
+	u32 clk_a, clk_b;
+
+	if (pllc & 0x40000000){
+		u32 m;
+	    
+		/* Feedback path */
+		switch ((pllc >> 24) & 7){
+		case 0:
+			/* PLLOUTx */
+			m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
+			break;
+		case 1:
+			/* CPU */
+			m = fwdva * pradv0;
+			break;
+		case 5:
+			/* PERClk */
+			m = fwdvb * prbdv0 * opbdv0 * perdv0;
+			break;
+		default:
+			printk(KERN_EMERG "invalid PLL feedback source\n");
+			goto bypass;
+		}
+		m *= fbdv;
+		p->vco = sys_clk * m;
+		clk_a = p->vco / fwdva;
+		clk_b = p->vco / fwdvb;
+	}
+	else {
+bypass:	
+		/* Bypass system PLL */
+		p->vco = 0;
+		clk_a = clk_b = sys_clk;
+	}
+	
+	p->cpu = clk_a / pradv0;
+	p->plb = clk_b / prbdv0;
+	p->opb = p->plb / opbdv0;
+	p->ebc = p->opb / perdv0;
+	
+	/* UARTs clock */
+	if (uart0 & 0x00800000)
+		p->uart0 = ser_clk;
+	else
+		p->uart0 = p->plb / __fix_zero(uart0 & 0xff, 256);
+
+	if (uart1 & 0x00800000)
+		p->uart1 = ser_clk;
+	else
+		p->uart1 = p->plb / __fix_zero(uart1 & 0xff, 256);
+}
+
+/* Enable L2 cache (call with IRQs disabled) */
+void __init ibm440gx_l2c_enable(void){
+	u32 r;
+	
+	asm volatile ("sync" ::: "memory");
+
+	/* Disable SRAM */
+	mtdcr(DCRN_SRAM0_DPC,   mfdcr(DCRN_SRAM0_DPC)   & ~SRAM_DPC_ENABLE);
+	mtdcr(DCRN_SRAM0_SB0CR, mfdcr(DCRN_SRAM0_SB0CR) & ~SRAM_SBCR_BU_MASK);
+	mtdcr(DCRN_SRAM0_SB1CR, mfdcr(DCRN_SRAM0_SB1CR) & ~SRAM_SBCR_BU_MASK);
+	mtdcr(DCRN_SRAM0_SB2CR, mfdcr(DCRN_SRAM0_SB2CR) & ~SRAM_SBCR_BU_MASK);
+	mtdcr(DCRN_SRAM0_SB3CR, mfdcr(DCRN_SRAM0_SB3CR) & ~SRAM_SBCR_BU_MASK);
+	
+	/* Enable L2_MODE without ICU/DCU */
+	r = mfdcr(DCRN_L2C0_CFG) & ~(L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_SS_MASK);
+	r |= L2C_CFG_L2M | L2C_CFG_SS_256;
+	mtdcr(DCRN_L2C0_CFG, r);
+	
+	mtdcr(DCRN_L2C0_ADDR, 0);
+	
+	/* Hardware Clear Command */
+	mtdcr(DCRN_L2C0_CMD, L2C_CMD_HCC);
+	while (!(mfdcr(DCRN_L2C0_SR) & L2C_SR_CC)) ;
+	
+	/* Clear Cache Parity and Tag Errors */
+	mtdcr(DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
+	
+	/* Enable 64G snoop region starting at 0 */
+	r = mfdcr(DCRN_L2C0_SNP0) & ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
+	r |= L2C_SNP_SSR_32G | L2C_SNP_ESR;
+	mtdcr(DCRN_L2C0_SNP0, r);
+
+	r = mfdcr(DCRN_L2C0_SNP1) & ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
+	r |= 0x80000000 | L2C_SNP_SSR_32G | L2C_SNP_ESR;
+	mtdcr(DCRN_L2C0_SNP1, r);
+	
+	asm volatile ("sync" ::: "memory");
+	
+	/* Enable ICU/DCU ports */
+	r = mfdcr(DCRN_L2C0_CFG);
+	r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM 
+		| L2C_CFG_PMUX_MASK | L2C_CFG_PMIM | L2C_CFG_TPEI | L2C_CFG_CPEI
+		| L2C_CFG_NAM | L2C_CFG_NBRM);
+	r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN 
+		| L2C_CFG_SMCM;
+	mtdcr(DCRN_L2C0_CFG, r);
+	
+	asm volatile ("sync; isync" ::: "memory");
+}
+
+/* Disable L2 cache (call with IRQs disabled) */
+void __init ibm440gx_l2c_disable(void){
+	u32 r;
+	
+	asm volatile ("sync" ::: "memory");
+
+	/* Disable L2C mode */
+	r = mfdcr(DCRN_L2C0_CFG) & ~(L2C_CFG_L2M | L2C_CFG_ICU | L2C_CFG_DCU);
+	mtdcr(DCRN_L2C0_CFG, r);
+
+	/* Enable SRAM */
+	mtdcr(DCRN_SRAM0_DPC, mfdcr(DCRN_SRAM0_DPC) | SRAM_DPC_ENABLE);
+	mtdcr(DCRN_SRAM0_SB0CR,
+	      SRAM_SBCR_BAS0 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+	mtdcr(DCRN_SRAM0_SB1CR,
+	      SRAM_SBCR_BAS1 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+	mtdcr(DCRN_SRAM0_SB2CR,
+	      SRAM_SBCR_BAS2 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+	mtdcr(DCRN_SRAM0_SB3CR,
+	      SRAM_SBCR_BAS3 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
+	
+	asm volatile ("sync; isync" ::: "memory");
+}
+
+int ibm440gx_show_cpuinfo(struct seq_file *m){
+
+	u32 l2c_cfg = mfdcr(DCRN_L2C0_CFG);
+	const char* s;
+	if (l2c_cfg & L2C_CFG_L2M){
+	    switch (l2c_cfg & (L2C_CFG_ICU | L2C_CFG_DCU)){
+		case L2C_CFG_ICU: s = "I-Cache only";    break;
+		case L2C_CFG_DCU: s = "D-Cache only";    break;
+		default:	  s = "I-Cache/D-Cache"; break;	
+	    }
+	}
+	else
+	    s = "disabled";
+
+	seq_printf(m, "L2-Cache\t: %s (0x%08x 0x%08x)\n", s, 
+	    l2c_cfg, mfdcr(DCRN_L2C0_SR));
+}
+
diff -urN linux-2.4.26-rc1/arch/ppc/kernel/ibm440gx_common.h linux-2.4.26-rc2/arch/ppc/kernel/ibm440gx_common.h
--- linux-2.4.26-rc1/arch/ppc/kernel/ibm440gx_common.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/kernel/ibm440gx_common.h	2004-04-05 17:40:57.000000000 -0700
@@ -0,0 +1,42 @@
+/*
+ * arch/ppc/kernel/ibm440gx_common.h
+ *
+ * PPC440GX system library
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003 Zultys Technologies
+ *
+ * This program is free software; 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.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_SYSLIB_IBM440GX_COMMON_H
+#define __PPC_SYSLIB_IBM440GX_COMMON_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <kernel/ibm44x_common.h>
+
+/*
+ * Please, refer to the Figure 14.1 in 440GX user manual
+ * 
+ * if internal UART clock is used, ser_clk is ignored
+ */
+void ibm440gx_get_clocks(struct ibm44x_clocks*, unsigned int sys_clk, 
+	unsigned int ser_clk) __init;
+
+/* Enable L2 cache */
+void ibm440gx_l2c_enable(void) __init;
+
+/* Add L2C info to /proc/cpuinfo */
+int ibm440gx_show_cpuinfo(struct seq_file*);
+
+#endif /* __ASSEMBLY__ */
+#endif /* __PPC_SYSLIB_IBM440GX_COMMON_H */
+#endif /* __KERNEL__ */
diff -urN linux-2.4.26-rc1/arch/ppc/kernel/ibm44x_common.h linux-2.4.26-rc2/arch/ppc/kernel/ibm44x_common.h
--- linux-2.4.26-rc1/arch/ppc/kernel/ibm44x_common.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/kernel/ibm44x_common.h	2004-04-05 17:40:57.000000000 -0700
@@ -0,0 +1,36 @@
+/*
+ * arch/ppc/kernel/ibm44x_common.h
+ *
+ * PPC44x system library
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003 Zultys Technologies
+ *
+ * This program is free software; 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.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_SYSLIB_IBM44x_COMMON_H
+#define __PPC_SYSLIB_IBM44x_COMMON_H
+
+#ifndef __ASSEMBLY__
+
+/*
+ * All clocks are in Hz
+ */
+struct ibm44x_clocks {
+	unsigned int vco;	/* VCO, 0 if system PLL is bypassed */
+	unsigned int cpu;	/* CPUCoreClk */
+	unsigned int plb;	/* PLBClk */
+	unsigned int opb;	/* OPBClk */
+	unsigned int ebc;	/* PerClk */
+	unsigned int uart0;
+	unsigned int uart1;
+};
+
+#endif /* __ASSEMBLY__ */
+#endif /* __PPC_SYSLIB_IBM44x_COMMON_H */
+#endif /* __KERNEL__ */
diff -urN linux-2.4.26-rc1/arch/ppc/kernel/traps.c linux-2.4.26-rc2/arch/ppc/kernel/traps.c
--- linux-2.4.26-rc1/arch/ppc/kernel/traps.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/kernel/traps.c	2004-04-05 17:40:57.000000000 -0700
@@ -212,15 +212,44 @@
 	if (check_io_access(regs))
 		return;
 
-#ifdef CONFIG_4xx
+#if defined(CONFIG_4xx) && !defined(CONFIG_440A)
 	if (reason & ESR_IMCP) {
 		printk("Instruction");
 		mtspr(SPRN_ESR, reason & ~ESR_IMCP);
 	} else
 		printk("Data");
 	printk(" machine check in kernel mode.\n");
-
-#else /* !CONFIG_4xx */
+#elif defined(CONFIG_440A)
+	printk("Machine check in kernel mode.\n");
+	if (reason & ESR_IMCP){
+		printk("Instruction Synchronous Machine Check exception\n");
+		mtspr(SPRN_ESR, reason & ~ESR_IMCP);
+	}
+	else {
+		u32 mcsr = mfspr(SPRN_MCSR);
+		if (mcsr & MCSR_IB)
+			printk("Instruction Read PLB Error\n");
+		if (mcsr & MCSR_DRB)
+			printk("Data Read PLB Error\n");
+		if (mcsr & MCSR_DWB)
+			printk("Data Write PLB Error\n");
+		if (mcsr & MCSR_TLBP)
+			printk("TLB Parity Error\n");
+		if (mcsr & MCSR_ICP){
+			flush_instruction_cache();
+			printk("I-Cache Parity Error\n");
+		}	
+		if (mcsr & MCSR_DCSP)
+			printk("D-Cache Search Parity Error\n");
+		if (mcsr & MCSR_DCFP)
+			printk("D-Cache Flush Parity Error\n");
+		if (mcsr & MCSR_IMPE)
+			printk("Machine Check exception is imprecise\n");
+		
+		/* Clear MCSR */
+		mtspr(SPRN_MCSR, mcsr);
+	}
+#else /* !CONFIG_4xx && !CONFIG_E500 */
 	printk("Machine check in kernel mode.\n");
 	printk("Caused by (from SRR1=%lx): ", reason);
 	switch (reason & 0x601F0000) {
diff -urN linux-2.4.26-rc1/arch/ppc/platforms/ebony.c linux-2.4.26-rc2/arch/ppc/platforms/ebony.c
--- linux-2.4.26-rc1/arch/ppc/platforms/ebony.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/platforms/ebony.c	2004-04-05 17:40:57.000000000 -0700
@@ -234,7 +234,7 @@
 	/* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
 	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
 	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
-	PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA);
+	PCIX_WRITEL(0x80000007, PCIX0_PIM0SA);
 
 	eieio();
 }
@@ -335,7 +335,7 @@
 ebony_setup_arch(void)
 {
 	unsigned char * vpd_base;
-	struct ibm440gp_clocks clocks;
+	struct ibm44x_clocks clocks;
 	bd_t *bip = (bd_t *) __res;
 
 #if !defined(CONFIG_BDI_SWITCH)
diff -urN linux-2.4.26-rc1/arch/ppc/platforms/ocotea.c linux-2.4.26-rc2/arch/ppc/platforms/ocotea.c
--- linux-2.4.26-rc1/arch/ppc/platforms/ocotea.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/platforms/ocotea.c	2004-04-05 17:40:57.000000000 -0700
@@ -44,6 +44,8 @@
 #include <asm/bootinfo.h>
 #include <asm/ppc4xx_pic.h>
 
+#include <kernel/ibm440gx_common.h>
+
 extern void abort(void);
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int pckbd_getkeycode(unsigned int scancode);
@@ -79,11 +81,13 @@
 static int
 ocotea_show_cpuinfo(struct seq_file *m)
 {
+	ibm440gx_show_cpuinfo(m);
 	seq_printf(m, "vendor\t\t: IBM\n");
 	seq_printf(m, "machine\t\t: PPC440GX EVB (Ocotea)\n");
 
 	return 0;
 }
+
 static inline int
 ocotea_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 {
@@ -147,7 +151,7 @@
 	/* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */
 	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH);
 	PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL);
-	PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA);
+	PCIX_WRITEL(0x80000007, PCIX0_PIM0SA);
 
 	eieio();
 }
@@ -205,14 +209,14 @@
 TODC_ALLOC();
 
 static void __init
-ocotea_early_serial_map(void)
+ocotea_early_serial_map(const struct ibm44x_clocks* clks)
 {
 	struct serial_struct serial_req;
 
 	/* Setup ioremapped serial port access */
 	memset(&serial_req, 0, sizeof(serial_req));
 	serial_req.line = 0;
-	serial_req.baud_base = BASE_BAUD;
+	serial_req.baud_base = clks->uart0 / 16;
 	serial_req.port = 0;
 	serial_req.irq = 0;
 	serial_req.flags = ASYNC_BOOT_AUTOCONF;
@@ -231,6 +235,7 @@
 
 	/* Assume early_serial_setup() doesn't modify serial_req */
 	serial_req.line = 1;
+	serial_req.baud_base = clks->uart1 / 16;
 	serial_req.port = 1;
 	serial_req.irq = 1; 
 	serial_req.iomem_base = ioremap64(PPC440GX_UART1_ADDR, 8);
@@ -251,6 +256,7 @@
 	unsigned char *addr;
 	unsigned long long mac64;
 	bd_t *bip = (bd_t *) __res;
+	struct ibm44x_clocks clocks;
 
 	/* Retrieve MAC addresses from flash */
 	addr = ioremap64(OCOTEA_MAC_BASE, OCOTEA_MAC_SIZE);
@@ -271,7 +277,18 @@
 	 */
         mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM));
 #endif
-
+	/*
+	 * Determine various clocks.
+	 * To be completely correct we should get SysClk
+	 * from FPGA, because it can be changed by on-board switches
+	 * --ebs
+	 */
+	ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+	bip->bi_opb_busfreq = clocks.opb;
+	
+	/* Use IIC in standard (100 kHz) mode */
+	bip->bi_iic_fast[0] = bip->bi_iic_fast[1] = 0;
+	
 	/* Setup TODC access */
 	TODC_INIT(TODC_TYPE_DS1743,
 			0,
@@ -300,7 +317,7 @@
 	conswitchp = &dummy_con;
 #endif
 
-	ocotea_early_serial_map();
+	ocotea_early_serial_map(&clocks);
 
 	/* Identify the system */
 	printk("IBM Ocotea port (MontaVista Software, Inc. <source@mvista.com>)\n");
@@ -405,6 +422,9 @@
 {
 	parse_bootinfo(find_bootinfo());
 
+	/* Disable L2-Cache due to hardware issues */
+	ibm440gx_l2c_disable();
+
 	ppc_md.setup_arch = ocotea_setup_arch;
 	ppc_md.show_cpuinfo = ocotea_show_cpuinfo;
 	ppc_md.init_IRQ = ocotea_init_irq;
diff -urN linux-2.4.26-rc1/arch/ppc/platforms/ocotea.h linux-2.4.26-rc2/arch/ppc/platforms/ocotea.h
--- linux-2.4.26-rc1/arch/ppc/platforms/ocotea.h	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc/platforms/ocotea.h	2004-04-05 17:40:57.000000000 -0700
@@ -25,7 +25,7 @@
 #define PPC44x_EMAC0_MR0	0xE0000800
 
 /* Location of MAC addresses in firmware */
-#define OCOTEA_MAC_BASE		(OCOTEA_SMALL_FLASH_HIGH+0xc0500)
+#define OCOTEA_MAC_BASE		(OCOTEA_SMALL_FLASH_HIGH+0xb0500)
 #define OCOTEA_MAC_SIZE		0x200
 #define OCOTEA_MAC1_OFFSET	0x100
 
@@ -55,6 +55,9 @@
 #define UART0_IO_BASE	(u8 *) 0xE0000200
 #define UART1_IO_BASE	(u8 *) 0xE0000300
 
+/* This value is used only to fill something in STD_UART_OP definition,
+   actual value is determined in ocotea_early_serial_map.   --ebs
+*/
 #define BASE_BAUD	11059200/16
 #define STD_UART_OP(num)					\
 	{ 0, BASE_BAUD, 0, UART##num##_INT,			\
diff -urN linux-2.4.26-rc1/arch/ppc64/kernel/lparcfg.c linux-2.4.26-rc2/arch/ppc64/kernel/lparcfg.c
--- linux-2.4.26-rc1/arch/ppc64/kernel/lparcfg.c	2004-02-18 05:36:30.000000000 -0800
+++ linux-2.4.26-rc2/arch/ppc64/kernel/lparcfg.c	2004-04-05 17:40:58.000000000 -0700
@@ -326,7 +326,7 @@
 		system_potential_processors =  get_splpar_potential_characteristics();
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "system_active_processors=%d\n",
-			      (h_resource >> 2*8) && 0xffff);
+			      (h_resource >> 2*8) & 0xffff);
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "system_potential_processors=%d\n",
 			      system_potential_processors);
@@ -366,16 +366,16 @@
 
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
-			      "pool=%d\n", (h_aggregation >> 0*8)&&0xffff);
+			      "pool=%d\n", (h_aggregation >> 0*8)&0xffff);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
-			      "pool_capacity=%d\n", (h_resource >> 3*8) &&0xffff);
+			      "pool_capacity=%d\n", (h_resource >> 3*8) &0xffff);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
-			      "group=%d\n", (h_aggregation >> 2*8)&&0xffff);
+			      "group=%d\n", (h_aggregation >> 2*8)&0xffff);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
-			      "capped=%d\n", (h_resource >> 6*8)&&0x40);
+			      "capped=%d\n", (h_resource >> 6*8)&0x40);
 
 		n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n,
 			      "capacity_weight=%d\n", (int)(h_resource>>5*8)&0xFF);
diff -urN linux-2.4.26-rc1/arch/x86_64/Makefile linux-2.4.26-rc2/arch/x86_64/Makefile
--- linux-2.4.26-rc1/arch/x86_64/Makefile	2004-04-05 17:40:53.000000000 -0700
+++ linux-2.4.26-rc2/arch/x86_64/Makefile	2004-04-05 17:40:58.000000000 -0700
@@ -60,7 +60,7 @@
 CFLAGS += $(call check_gcc,-march=k8,)
 endif
 ifdef CONFIG_MPSC
-CFLAGS += $(call check_gcc,-march=prescott,)
+CFLAGS += $(call check_gcc,-march=nocona,)
 endif
 
 HEAD := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
diff -urN linux-2.4.26-rc1/arch/x86_64/kernel/io_apic.c linux-2.4.26-rc2/arch/x86_64/kernel/io_apic.c
--- linux-2.4.26-rc1/arch/x86_64/kernel/io_apic.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-rc2/arch/x86_64/kernel/io_apic.c	2004-04-05 17:40:58.000000000 -0700
@@ -1850,7 +1850,11 @@
 	entry.trigger = edge_level;
 	entry.polarity = active_high_low;
 
-	add_pin_to_irq(irq, ioapic, pin);
+	/*
+	 * IRQs < 16 are already in the irq_2_pin[] map
+	 */
+	if (irq >= 16)
+		add_pin_to_irq(irq, ioapic, pin);
 
 	entry.vector = assign_irq_vector(irq);
 
diff -urN linux-2.4.26-rc1/drivers/acpi/bus.c linux-2.4.26-rc2/drivers/acpi/bus.c
--- linux-2.4.26-rc1/drivers/acpi/bus.c	2004-04-05 17:40:53.000000000 -0700
+++ linux-2.4.26-rc2/drivers/acpi/bus.c	2004-04-05 17:40:58.000000000 -0700
@@ -1877,6 +1877,11 @@
 #ifdef CONFIG_X86
 	if (!acpi_ioapic) {
 		extern acpi_interrupt_flags acpi_sci_flags;
+
+		/* compatible (0) means level (3) */
+		if (acpi_sci_flags.trigger == 0)
+			acpi_sci_flags.trigger = 3;
+
 		/* Set PIC-mode SCI trigger type */
 		acpi_pic_sci_set_trigger(acpi_fadt.sci_int, acpi_sci_flags.trigger);
 	} else {
diff -urN linux-2.4.26-rc1/drivers/acpi/pci_irq.c linux-2.4.26-rc2/drivers/acpi/pci_irq.c
--- linux-2.4.26-rc1/drivers/acpi/pci_irq.c	2004-04-05 17:40:53.000000000 -0700
+++ linux-2.4.26-rc2/drivers/acpi/pci_irq.c	2004-04-05 17:40:58.000000000 -0700
@@ -277,11 +277,6 @@
 	return_VALUE(entry->irq);
 }
 
-/*
- * current thinking is that acpi_pci_irq_derive() adds no value
- * and should be deleted, so warn if it actually does something.
- */
-
 static int
 acpi_pci_irq_derive (
 	struct pci_dev		*dev,
@@ -289,6 +284,7 @@
 {
 	struct pci_dev		*bridge = dev;
 	int			irq = 0;
+	u8			bridge_pin = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_pci_irq_derive");
 
@@ -297,12 +293,28 @@
 
 	/* 
 	 * Attempt to derive an IRQ for this device from a parent bridge's
-	 * PCI interrupt routing entry (a.k.a. the "bridge swizzle").
+	 * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge)
 	 */
 	while (!irq && bridge->bus->self) {
 		pin = (pin + PCI_SLOT(bridge->devfn)) % 4;
 		bridge = bridge->bus->self;
-		irq = acpi_pci_irq_lookup(0, bridge->bus->number, PCI_SLOT(bridge->devfn), pin);
+
+		if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
+			/* PC card has the same IRQ as its cardbridge */
+			pci_read_config_byte(bridge, PCI_INTERRUPT_PIN, &bridge_pin);
+			if (!bridge_pin) {
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					"No interrupt pin configured for device %s\n",
+					pci_name(bridge)));
+				return_VALUE(0);
+			}
+			/* Pin is from 0 to 3 */
+			bridge_pin --;
+			pin = bridge_pin;
+		}
+
+		irq = acpi_pci_irq_lookup(0, bridge->bus->number,
+				PCI_SLOT(bridge->devfn), pin);
 	}
 
 	if (!irq) {
@@ -310,7 +322,7 @@
 		return_VALUE(0);
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Derive IRQ %d for device %s from %s\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n",
 		irq, pci_name(dev), pci_name(bridge)));
 
 	return_VALUE(irq);
@@ -348,13 +360,6 @@
  	irq = acpi_pci_irq_lookup(0, dev->bus->number, PCI_SLOT(dev->devfn), pin);
  
 	/*
-	 * Check if the device has an IRQ,
-	 * Hotplug devices may get IRQs by scanning
-	 */
-	if (!irq && dev->irq)
-		irq = dev->irq;
-
-	/*
 	 * If no PRT entry was found, we'll try to derive an IRQ from the
 	 * device's parent bridge.
 	 */
diff -urN linux-2.4.26-rc1/drivers/block/cciss.c linux-2.4.26-rc2/drivers/block/cciss.c
--- linux-2.4.26-rc1/drivers/block/cciss.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-rc2/drivers/block/cciss.c	2004-04-05 17:40:59.000000000 -0700
@@ -508,12 +508,8 @@
 			driver_geo.heads = hba[ctlr]->drv[dsk].heads;
 			driver_geo.sectors = hba[ctlr]->drv[dsk].sectors;
 			driver_geo.cylinders = hba[ctlr]->drv[dsk].cylinders;
-		} else {
-			driver_geo.heads = 0xff;
-			driver_geo.sectors = 0x3f;
-			driver_geo.cylinders = 
-				hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f);
-		}
+		} else 
+			return -ENXIO;
 		driver_geo.start=
 			hba[ctlr]->hd[MINOR(inode->i_rdev)].start_sect;
 		if (copy_to_user((void *) arg, &driver_geo,
@@ -528,12 +524,8 @@
 			driver_geo.heads = hba[ctlr]->drv[dsk].heads;
 			driver_geo.sectors = hba[ctlr]->drv[dsk].sectors;
 			driver_geo.cylinders = hba[ctlr]->drv[dsk].cylinders;
-		} else {
-			driver_geo.heads = 0xff;
-			driver_geo.sectors = 0x3f;
-			driver_geo.cylinders = 
-				hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f);
-		}
+		} else 
+			return -ENXIO;
 		driver_geo.start= 
 		hba[ctlr]->hd[MINOR(inode->i_rdev)].start_sect;
 		if (copy_to_user((void *) arg, &driver_geo,  
diff -urN linux-2.4.26-rc1/drivers/block/cciss_scsi.c linux-2.4.26-rc2/drivers/block/cciss_scsi.c
--- linux-2.4.26-rc1/drivers/block/cciss_scsi.c	2003-11-28 10:26:19.000000000 -0800
+++ linux-2.4.26-rc2/drivers/block/cciss_scsi.c	2004-04-05 17:40:59.000000000 -0700
@@ -589,6 +589,8 @@
 
 	for(i=0; i<num_luns; i++) {
 		/* Execute an inquiry to figure the device type */
+		/* Skip over masked devices */
+		if (ld_buff->LUN[i][3] & 0xC0) continue;
 		memset(inq_buff, 0, sizeof(InquiryData_struct));
 		memcpy(scsi3addr, ld_buff->LUN[i], 8); /* ugly... */
 		return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
@@ -1148,6 +1150,7 @@
 		int devtype;
 
 		/* for each physical lun, do an inquiry */
+		if (ld_buff->LUN[i][3] & 0xC0) continue;
 		memset(inq_buff, 0, sizeof(InquiryData_struct));
 		memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
 
diff -urN linux-2.4.26-rc1/drivers/ide/Config.in linux-2.4.26-rc2/drivers/ide/Config.in
--- linux-2.4.26-rc1/drivers/ide/Config.in	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/drivers/ide/Config.in	2004-04-05 17:40:59.000000000 -0700
@@ -49,6 +49,7 @@
 	    dep_mbool    '      ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3
 	    dep_tristate '    AMD and nVidia IDE support' CONFIG_BLK_DEV_AMD74XX $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_mbool    '      AMD Viper ATA-66 Override' CONFIG_AMD74XX_OVERRIDE $CONFIG_BLK_DEV_AMD74XX
+	    dep_tristate '    ATI IXP chipset IDE support' CONFIG_BLK_DEV_ATIIXP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
 	    dep_tristate '    CMD64{3|6|8|9} chipset support' CONFIG_BLK_DEV_CMD64X $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_tristate '    Compaq Triflex IDE support' CONFIG_BLK_DEV_TRIFLEX $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_tristate '    CY82C693 chipset support' CONFIG_BLK_DEV_CY82C693 $CONFIG_BLK_DEV_IDEDMA_PCI
diff -urN linux-2.4.26-rc1/drivers/ide/ide-probe.c linux-2.4.26-rc2/drivers/ide/ide-probe.c
--- linux-2.4.26-rc1/drivers/ide/ide-probe.c	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.26-rc2/drivers/ide/ide-probe.c	2004-04-05 17:40:59.000000000 -0700
@@ -102,7 +102,8 @@
 		if (id->config == 0x848a) return 1;	/* CompactFlash */
 		if (!strncmp(id->model, "KODAK ATA_FLASH", 15)	/* Kodak */
 		 || !strncmp(id->model, "Hitachi CV", 10)	/* Hitachi */
-		 || !strncmp(id->model, "SunDisk SDCFB", 13)	/* SunDisk */
+		 || !strncmp(id->model, "SunDisk SDCFB", 13)	/* old SanDisk */
+		 || !strncmp(id->model, "SanDisk SDCFB", 13)	/* SanDisk */
 		 || !strncmp(id->model, "HAGIWARA HPC", 12)	/* Hagiwara */
 		 || !strncmp(id->model, "LEXAR ATA_FLASH", 15)	/* Lexar */
 		 || !strncmp(id->model, "ATA_FLASH", 9))	/* Simple Tech */
diff -urN linux-2.4.26-rc1/drivers/ide/pci/Makefile linux-2.4.26-rc2/drivers/ide/pci/Makefile
--- linux-2.4.26-rc1/drivers/ide/pci/Makefile	2003-11-28 10:26:20.000000000 -0800
+++ linux-2.4.26-rc2/drivers/ide/pci/Makefile	2004-04-05 17:40:59.000000000 -0700
@@ -8,6 +8,7 @@
 obj-$(CONFIG_BLK_DEV_AEC62XX)		+= aec62xx.o
 obj-$(CONFIG_BLK_DEV_ALI15X3)		+= alim15x3.o
 obj-$(CONFIG_BLK_DEV_AMD74XX)		+= amd74xx.o
+obj-$(CONFIG_BLK_DEV_ATIIXP)		+= atiixp.o
 obj-$(CONFIG_BLK_DEV_CMD640)		+= cmd640.o
 obj-$(CONFIG_BLK_DEV_CMD64X)		+= cmd64x.o
 obj-$(CONFIG_BLK_DEV_CS5530)		+= cs5530.o
diff -urN linux-2.4.26-rc1/drivers/ide/pci/atiixp.c linux-2.4.26-rc2/drivers/ide/pci/atiixp.c
--- linux-2.4.26-rc1/drivers/ide/pci/atiixp.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.26-rc2/drivers/ide/pci/atiixp.c	2004-04-05 17:40:59.000000000 -0700
@@ -0,0 +1,522 @@
+/*
+ *  linux/drivers/ide/pci/atiixp.c	Version 0.01-bart2	Feb. 26, 2004
+ *
+ *  Copyright (C) 2003 ATI Inc. <hyu@ati.com>
+ *  Copyright (C) 2004 Bartlomiej Zolnierkiewicz
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#include "ide_modes.h"
+
+#define ATIIXP_IDE_PIO_TIMING		0x40
+#define ATIIXP_IDE_MDMA_TIMING		0x44
+#define ATIIXP_IDE_PIO_CONTROL		0x48
+#define ATIIXP_IDE_PIO_MODE		0x4a
+#define ATIIXP_IDE_UDMA_CONTROL		0x54
+#define ATIIXP_IDE_UDMA_MODE		0x56
+
+typedef struct {
+	u8 command_width;
+	u8 recover_width;
+} atiixp_ide_timing;
+
+static atiixp_ide_timing pio_timing[] = {
+	{ 0x05, 0x0d },
+	{ 0x04, 0x07 },
+	{ 0x03, 0x04 },
+	{ 0x02, 0x02 },
+	{ 0x02, 0x00 },
+};
+
+static atiixp_ide_timing mdma_timing[] = {
+	{ 0x07, 0x07 },
+	{ 0x02, 0x01 },
+	{ 0x02, 0x00 },
+};
+
+static int save_mdma_mode[4];
+
+#define DISPLAY_ATIIXP_TIMINGS
+
+#if defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS)
+
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static u8 atiixp_proc;
+static struct pci_dev *bmide_dev;
+
+/**
+ *	atiixp_get_info		-	fill in /proc for ATIIXP IDE
+ *	@buffer: buffer to fill
+ *	@addr: address of user start in buffer
+ *	@offset: offset into 'file'
+ *	@count: buffer count
+ *
+ *	Output summary data on the tuning.
+ */
+
+static int atiixp_get_info(char *buffer, char **addr, off_t offset, int count)
+{
+	char *p = buffer;
+	struct pci_dev *dev = bmide_dev;
+	unsigned long bibma = pci_resource_start(dev, 4);
+	u32 mdma_timing = 0;
+	u16 udma_mode = 0, pio_mode = 0;
+	u8 c0, c1, udma_control = 0;
+
+	p += sprintf(p, "\n                          ATI ");
+	p += sprintf(p, "ATIIXP Ultra100 IDE Chipset.\n");
+
+	pci_read_config_byte(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_control);
+	pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &udma_mode);
+	pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode);
+	pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &mdma_timing);
+
+	/*
+	 * at that point bibma+0x2 et bibma+0xa are byte registers
+	 * to investigate:
+	 */
+	c0 = inb(bibma + 0x02);
+	c1 = inb(bibma + 0x0a);
+
+	p += sprintf(p, "--------------- Primary Channel "
+			"---------------- Secondary Channel "
+			"-------------\n");
+	p += sprintf(p, "                %sabled "
+			"                        %sabled\n",
+			(c0 & 0x80) ? "dis" : " en",
+			(c1 & 0x80) ? "dis" : " en");
+	p += sprintf(p, "--------------- drive0 --------- drive1 "
+			"-------- drive0 ---------- drive1 ------\n");
+	p += sprintf(p, "DMA enabled:    %s              %s "
+			"            %s               %s\n",
+			(c0 & 0x20) ? "yes" : "no ",
+			(c0 & 0x40) ? "yes" : "no ",
+			(c1 & 0x20) ? "yes" : "no ",
+			(c1 & 0x40) ? "yes" : "no " );
+	p += sprintf(p, "UDMA enabled:   %s              %s "
+			"            %s               %s\n",
+			(udma_control & 0x01) ? "yes" : "no ",
+			(udma_control & 0x02) ? "yes" : "no ",
+			(udma_control & 0x04) ? "yes" : "no ",
+			(udma_control & 0x08) ? "yes" : "no " );
+	p += sprintf(p, "UDMA mode:      %c                %c "
+			"              %c                 %c\n",
+			(udma_control & 0x01) ?
+			((udma_mode & 0x07) + 48) : 'X',
+			(udma_control & 0x02) ?
+			(((udma_mode >> 4) & 0x07) + 48) : 'X',
+			(udma_control & 0x04) ?
+			(((udma_mode >> 8) & 0x07) + 48) : 'X',
+			(udma_control & 0x08) ?
+			(((udma_mode >> 12) & 0x07) + 48) : 'X');
+	p += sprintf(p, "MDMA mode:      %c                %c "
+			"              %c                 %c\n",
+			(save_mdma_mode[0] && (c0 & 0x20)) ?
+			((save_mdma_mode[0] & 0xf) + 48) : 'X',
+			(save_mdma_mode[1] && (c0 & 0x40)) ?
+			((save_mdma_mode[1] & 0xf) + 48) : 'X',
+			(save_mdma_mode[2] && (c1 & 0x20)) ?
+			((save_mdma_mode[2] & 0xf) + 48) : 'X',
+			(save_mdma_mode[3] && (c1 & 0x40)) ?
+			((save_mdma_mode[3] & 0xf) + 48) : 'X');
+	p += sprintf(p, "PIO mode:       %c                %c "
+			"              %c                 %c\n",
+			(c0 & 0x20) ? 'X' : ((pio_mode & 0x07) + 48),
+			(c0 & 0x40) ? 'X' : (((pio_mode >> 4) & 0x07) + 48),
+			(c1 & 0x20) ? 'X' : (((pio_mode >> 8) & 0x07) + 48),
+			(c1 & 0x40) ? 'X' : (((pio_mode >> 12) & 0x07) + 48));
+
+	return p - buffer;	/* => must be less than 4k! */
+}
+
+static ide_pci_host_proc_t atiixp_procs = {
+	.name		= "atiixp",
+	.set		= 1,
+	.get_info	= atiixp_get_info,
+};
+#endif  /* defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+/**
+ *	atiixp_ratemask		-	compute rate mask for ATIIXP IDE
+ *	@drive: IDE drive to compute for
+ *
+ *	Returns the available modes for the ATIIXP IDE controller.
+ */
+
+static u8 atiixp_ratemask(ide_drive_t *drive)
+{
+	u8 mode = 3;
+
+	if (!eighty_ninty_three(drive))
+		mode = min(mode, (u8)1);
+	return mode;
+}
+
+/**
+ *	atiixp_dma_2_pio		-	return the PIO mode matching DMA
+ *	@xfer_rate: transfer speed
+ *
+ *	Returns the nearest equivalent PIO timing for the PIO or DMA
+ *	mode requested by the controller.
+ */
+
+static u8 atiixp_dma_2_pio(u8 xfer_rate) {
+	switch(xfer_rate) {
+		case XFER_UDMA_6:
+		case XFER_UDMA_5:
+		case XFER_UDMA_4:
+		case XFER_UDMA_3:
+		case XFER_UDMA_2:
+		case XFER_UDMA_1:
+		case XFER_UDMA_0:
+		case XFER_MW_DMA_2:
+		case XFER_PIO_4:
+			return 4;
+		case XFER_MW_DMA_1:
+		case XFER_PIO_3:
+			return 3;
+		case XFER_SW_DMA_2:
+		case XFER_PIO_2:
+			return 2;
+		case XFER_MW_DMA_0:
+		case XFER_SW_DMA_1:
+		case XFER_SW_DMA_0:
+		case XFER_PIO_1:
+		case XFER_PIO_0:
+		case XFER_PIO_SLOW:
+		default:
+			return 0;
+	}
+}
+
+static int atiixp_ide_dma_host_on(ide_drive_t *drive)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	u16 tmp16;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
+	if (save_mdma_mode[drive->dn])
+		tmp16 &= ~(1 << drive->dn);
+	else
+		tmp16 |= (1 << drive->dn);
+	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	return __ide_dma_host_on(drive);
+}
+
+static int atiixp_ide_dma_host_off(ide_drive_t *drive)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	u16 tmp16;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
+	tmp16 &= ~(1 << drive->dn);
+	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	return __ide_dma_host_off(drive);
+}
+
+/**
+ *	atiixp_tune_drive		-	tune a drive attached to a ATIIXP
+ *	@drive: drive to tune
+ *	@pio: desired PIO mode
+ *
+ *	Set the interface PIO mode.
+ */
+
+static void atiixp_tuneproc(ide_drive_t *drive, u8 pio)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+	u32 pio_timing_data;
+	u16 pio_mode_data;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
+	pio_mode_data &= ~(0x07 << (drive->dn * 4));
+	pio_mode_data |= (pio << (drive->dn * 4));
+	pci_write_config_word(dev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
+
+	pci_read_config_dword(dev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
+	pio_timing_data &= ~(0xff << timing_shift);
+	pio_timing_data |= (pio_timing[pio].recover_width << timing_shift) |
+		 (pio_timing[pio].command_width << (timing_shift + 4));
+	pci_write_config_dword(dev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+}
+
+/**
+ *	atiixp_tune_chipset	-	tune a ATIIXP interface
+ *	@drive: IDE drive to tune
+ *	@xferspeed: speed to configure
+ *
+ *	Set a ATIIXP interface channel to the desired speeds. This involves
+ *	requires the right timing data into the ATIIXP configuration space
+ *	then setting the drive parameters appropriately
+ */
+
+static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+	u32 tmp32;
+	u16 tmp16;
+	u8 speed, pio;
+
+	speed = ide_rate_filter(atiixp_ratemask(drive), xferspeed);
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	save_mdma_mode[drive->dn] = 0;
+	if (speed >= XFER_UDMA_0) {
+		pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &tmp16);
+		tmp16 &= ~(0x07 << (drive->dn * 4));
+		tmp16 |= ((speed & 0x07) << (drive->dn * 4));
+		pci_write_config_word(dev, ATIIXP_IDE_UDMA_MODE, tmp16);
+	} else {
+		if ((speed >= XFER_MW_DMA_0) && (speed <= XFER_MW_DMA_2)) {
+			save_mdma_mode[drive->dn] = speed;
+			pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
+			tmp32 &= ~(0xff << timing_shift);
+			tmp32 |= (mdma_timing[speed & 0x03].recover_width << timing_shift) |
+				(mdma_timing[speed & 0x03].command_width << (timing_shift + 4));
+			pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
+		}
+	}
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	if (speed >= XFER_SW_DMA_0)
+		pio = atiixp_dma_2_pio(speed);
+	else
+		pio = speed - XFER_PIO_0;
+
+	atiixp_tuneproc(drive, pio);
+
+	return ide_config_drive_speed(drive, speed);
+}
+
+/**
+ *	atiixp_config_drive_for_dma	-	configure drive for DMA
+ *	@drive: IDE drive to configure
+ *
+ *	Set up a ATIIXP interface channel for the best available speed.
+ *	We prefer UDMA if it is available and then MWDMA. If DMA is
+ *	not available we switch to PIO and return 0.
+ */
+
+static int atiixp_config_drive_for_dma(ide_drive_t *drive)
+{
+	u8 speed = ide_dma_speed(drive, atiixp_ratemask(drive));
+
+	/* If no DMA speed was available then disable DMA and use PIO. */
+	if (!speed) {
+		u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
+		speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
+	}
+
+	(void) atiixp_speedproc(drive, speed);
+	return ide_dma_enable(drive);
+}
+
+/**
+ *	atiixp_dma_check	-	set up an IDE device
+ *	@drive: IDE drive to configure
+ *
+ *	Set up the ATIIXP interface for the best available speed on this
+ *	interface, preferring DMA to PIO.
+ */
+
+static int atiixp_dma_check(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct hd_driveid *id	= drive->id;
+	u8 tspeed, speed;
+
+	drive->init_speed = 0;
+
+	if ((id->capability & 1) && drive->autodma) {
+		/* Consult the list of known "bad" drives */
+		if (__ide_dma_bad_drive(drive))
+			goto fast_ata_pio;
+		if (id->field_valid & 4) {
+			if (id->dma_ultra & hwif->ultra_mask) {
+				/* Force if Capable UltraDMA */
+				if ((id->field_valid & 2) &&
+				    (!atiixp_config_drive_for_dma(drive)))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & hwif->mwdma_mask) ||
+			    (id->dma_1word & hwif->swdma_mask)) {
+				/* Force if Capable regular DMA modes */
+				if (!atiixp_config_drive_for_dma(drive))
+					goto no_dma_set;
+			}
+		} else if (__ide_dma_good_drive(drive) &&
+			   (id->eide_dma_time < 150)) {
+			/* Consult the list of known "good" drives */
+			if (!atiixp_config_drive_for_dma(drive))
+				goto no_dma_set;
+		} else {
+			goto fast_ata_pio;
+		}
+		return hwif->ide_dma_on(drive);
+	} else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+no_dma_set:
+		tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
+		speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
+		hwif->speedproc(drive, speed);
+		return hwif->ide_dma_off_quietly(drive);
+	}
+	/* IORDY not supported */
+	return 0;
+}
+
+/**
+ *	init_chipset_atiixp	-	set up the ATIIXP chipset
+ *	@dev: PCI device to set up
+ *	@name: Name of the device
+ *
+ *	Initialize the PCI device as required. For the ATIIXP this turns
+ *	out to be nice and simple
+ */
+
+static unsigned int __devinit init_chipset_atiixp(struct pci_dev *dev, const char *name)
+{
+#if defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS)
+	if (!atiixp_proc) {
+		atiixp_proc = 1;
+		bmide_dev = dev;
+		ide_pci_register_host_proc(&atiixp_procs);
+	}
+#endif /* DISPLAY_ATIIXP_TIMINGS && CONFIG_PROC_FS */
+	return 0;
+}
+
+/**
+ *	init_hwif_atiixp		-	fill in the hwif for the ATIIXP
+ *	@hwif: IDE interface
+ *
+ *	Set up the ide_hwif_t for the ATIIXP interface according to the
+ *	capabilities of the hardware.
+ */
+
+static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
+{
+	if (!hwif->irq)
+		hwif->irq = hwif->channel ? 15 : 14;
+
+	hwif->autodma = 0;
+	hwif->tuneproc = &atiixp_tuneproc;
+	hwif->speedproc = &atiixp_speedproc;
+	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
+
+	if (!hwif->dma_base)
+		return;
+
+	hwif->atapi_dma = 1;
+	hwif->ultra_mask = 0x3f;
+	hwif->mwdma_mask = 0x06;
+	hwif->swdma_mask = 0x04;
+
+	/* FIXME: proper cable detection needed */
+	hwif->udma_four = 1;
+	hwif->ide_dma_host_on = &atiixp_ide_dma_host_on;
+	hwif->ide_dma_host_off = &atiixp_ide_dma_host_off;
+	hwif->ide_dma_check = &atiixp_dma_check;
+	if (!noautodma)
+		hwif->autodma = 1;
+
+	hwif->drives[1].autodma = hwif->autodma;
+	hwif->drives[0].autodma = hwif->autodma;
+}
+
+static ide_pci_device_t atiixp_pci_info[] __devinitdata = {
+	{	/* 0 */
+		.vendor		= PCI_VENDOR_ID_ATI,
+		.device		= PCI_DEVICE_ID_ATI_IXP_IDE,
+		.name		= "ATIIXP",
+		.init_chipset	= init_chipset_atiixp,
+		.init_hwif	= init_hwif_atiixp,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
+		.bootable	= ON_BOARD,
+	}
+};
+
+/**
+ *	atiixp_init_one	-	called when a ATIIXP is found
+ *	@dev: the atiixp device
+ *	@id: the matching pci id
+ *
+ *	Called when the PCI registration layer (or the IDE initialization)
+ *	finds a device matching our IDE device tables.
+ */
+
+static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	ide_pci_device_t *d = &atiixp_pci_info[id->driver_data];
+
+	if (dev->device != d->device)
+		BUG();
+	ide_setup_pci_device(dev, d);
+	return 0;
+}
+
+static struct pci_device_id atiixp_pci_tbl[] = {
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ 0, },
+};
+
+static struct pci_driver driver = {
+	.name		= "ATIIXP IDE",
+	.id_table	= atiixp_pci_tbl,
+	.probe		= atiixp_init_one,
+};
+
+static int atiixp_ide_init(void)
+{
+	return ide_pci_register_driver(&driver);
+}
+
+module_init(atiixp_ide_init);
+
+MODULE_AUTHOR("HUI YU");
+MODULE_DESCRIPTION("PCI driver module for ATI IXP IDE");
+MODULE_LICENSE("GPL");
+
+EXPORT_NO_SYMBOLS;
diff -urN linux-2.4.26-rc1/drivers/ide/pci/hpt366.c linux-2.4.26-rc2/drivers/ide/pci/hpt366.c
--- linux-2.4.26-rc1/drivers/ide/pci/hpt366.c	2003-08-25 04:44:41.000000000 -0700
+++ linux-2.4.26-rc2/drivers/ide/pci/hpt366.c	2004-04-05 17:40:59.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/ide/pci/hpt366.c		Version 0.36	April 25, 2003
  *
- * Copyright (C) 1999-2002		Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
  * Portions Copyright (C) 2003		Red Hat Inc
  *
@@ -668,6 +668,31 @@
 	return __ide_dma_lostirq(drive);
 }
 
+/* returns 1 if DMA IRQ issued, 0 otherwise */
+static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	u16 bfifo		= 0;
+	u8 reginfo		= hwif->channel ? 0x56 : 0x52;
+	u8 dma_stat;
+
+	pci_read_config_word(hwif->pci_dev, reginfo, &bfifo);
+	if (bfifo & 0x1FF) {
+//		printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
+		return 0;
+	}
+
+	dma_stat = hwif->INB(hwif->dma_status);
+	/* return 1 if INTR asserted */
+	if ((dma_stat & 4) == 4)
+		return 1;
+
+	if (!drive->waiting_for_dma)
+		printk(KERN_WARNING "%s: (%s) called while not waiting\n",
+				drive->name, __FUNCTION__);
+	return 0;
+}
+
 static int hpt374_ide_dma_end (ide_drive_t *drive)
 {
 	struct pci_dev *dev	= HWIF(drive)->pci_dev;
@@ -1245,11 +1270,13 @@
 		hwif->udma_four = ((ata66 & regmask) ? 0 : 1);
 	hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
 
-	if (hpt_minimum_revision(dev,8))
+	if (hpt_minimum_revision(dev,8)) {
+		hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
 		hwif->ide_dma_end = &hpt374_ide_dma_end;
-	else if (hpt_minimum_revision(dev,5))
+	} else if (hpt_minimum_revision(dev,5)) {
+		hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
 		hwif->ide_dma_end = &hpt374_ide_dma_end;
-	else if (hpt_minimum_revision(dev,3)) {
+	} else if (hpt_minimum_revision(dev,3)) {
 		hwif->ide_dma_begin = &hpt370_ide_dma_begin;
 		hwif->ide_dma_end = &hpt370_ide_dma_end;
 		hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
diff -urN linux-2.4.26-rc1/drivers/md/raid1.c linux-2.4.26-rc2/drivers/md/raid1.c
--- linux-2.4.26-rc1/drivers/md/raid1.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-rc2/drivers/md/raid1.c	2004-04-05 17:41:00.000000000 -0700
@@ -487,6 +487,12 @@
 		goto rb_out;
 	
 
+#if defined(CONFIG_ALPHA) && ((__GNUC__ < 3) || \
+			      ((__GNUC__ == 3) && (__GNUC_MINOR__ < 3)))
+	/* Work around a compiler bug in older gcc */
+	new_disk = *(volatile int *)&new_disk;
+#endif
+
 	/* make sure that disk is operational */
 	while( !conf->mirrors[new_disk].operational) {
 		if (new_disk <= 0) new_disk = conf->raid_disks;
@@ -544,6 +550,11 @@
 	
 	/* Find the disk which is closest */
 	
+#if defined(CONFIG_ALPHA) && ((__GNUC__ < 3) || \
+			      ((__GNUC__ == 3) && (__GNUC_MINOR__ < 3)))
+	/* Work around a compiler bug in older gcc */
+	disk = *(volatile int *)&disk;
+#endif
 	do {
 		if (disk <= 0)
 			disk = conf->raid_disks;
diff -urN linux-2.4.26-rc1/fs/smbfs/proc.c linux-2.4.26-rc2/fs/smbfs/proc.c
--- linux-2.4.26-rc1/fs/smbfs/proc.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-rc2/fs/smbfs/proc.c	2004-04-05 17:41:10.000000000 -0700
@@ -915,7 +915,9 @@
 		SB_of(server)->s_maxbytes = ~0ULL >> 1;
 		VERBOSE("LFS enabled\n");
 	}
-#ifdef CONFIG_SMB_UNIX
+#ifndef CONFIG_SMB_UNIX
+	server->opt.capabilities &= ~SMB_CAP_UNIX;
+#endif
 	if (server->opt.capabilities & SMB_CAP_UNIX) {
 		struct inode *inode;
 		VERBOSE("Using UNIX CIFS extensions\n");
@@ -924,9 +926,6 @@
 		if (inode)
 			inode->i_op = &smb_dir_inode_operations_unix;
 	}
-#else
-	server->opt.capabilities &= ~SMB_CAP_UNIX;
-#endif
 
 	VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
 		server->opt.protocol, server->opt.max_xmit, server->conn_pid,
@@ -2615,9 +2614,18 @@
 	struct inode *inode = dir->d_inode;
 	int result;
 
+retry:
 	result = smb_proc_getattr_trans2_std(server, dir, attr);
-	if (result < 0)
+	if (result < 0) {
+		if (server->rcls == ERRSRV && server->err == ERRerror) {
+			/* a damn Win95 bug - sometimes it clags if you 
+			   ask it too fast */
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(HZ/5);
+			goto retry;
+		}
 		goto out;
+	}
 
 	/*
 	 * None of the other getattr versions here can make win9x
diff -urN linux-2.4.26-rc1/fs/xfs/linux/xfs_aops.c linux-2.4.26-rc2/fs/xfs/linux/xfs_aops.c
--- linux-2.4.26-rc1/fs/xfs/linux/xfs_aops.c	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/fs/xfs/linux/xfs_aops.c	2004-04-05 17:41:10.000000000 -0700
@@ -542,8 +542,10 @@
 			clear_buffer_dirty(bh);
 		}
 
-		for (i = 0; i < cnt; i++)
+		for (i = 0; i < cnt; i++) {
+			refile_buffer(bh_arr[i]);
 			submit_bh(WRITE, bh_arr[i]);
+		}
 	} else
 		unlock_page(page);
 }
@@ -678,7 +680,8 @@
 	struct buffer_head	*bh_arr[MAX_BUF_PER_PAGE], *bh, *head;
 	xfs_iomap_t		*iomp, iomap;
 	unsigned long		p_offset = 0, end_index;
-	loff_t			offset, end_offset;
+	loff_t			offset;
+	unsigned long long	end_offset;
 	int			len, err, i, cnt = 0, uptodate = 1;
 	int			flags = startio ? 0 : BMAPI_TRYLOCK;
 	int			page_dirty = 1;
@@ -695,9 +698,8 @@
 	}
 
 	offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
-	end_offset = offset + PAGE_CACHE_SIZE;
-	if (end_offset > i_size_read(inode))
-		end_offset = i_size_read(inode);
+	end_offset = min_t(unsigned long long,
+			offset + PAGE_CACHE_SIZE, i_size_read(inode));
 
 	bh = head = page_buffers(page);
 	iomp = NULL;
diff -urN linux-2.4.26-rc1/fs/xfs/linux/xfs_file.c linux-2.4.26-rc2/fs/xfs/linux/xfs_file.c
--- linux-2.4.26-rc1/fs/xfs/linux/xfs_file.c	2004-02-18 05:36:31.000000000 -0800
+++ linux-2.4.26-rc2/fs/xfs/linux/xfs_file.c	2004-04-05 17:41:10.000000000 -0700
@@ -68,17 +68,18 @@
 {
 	struct inode	*inode = file->f_dentry->d_inode;
 	vnode_t		*vp = LINVFS_GET_VP(inode);
-	int		error;
+	size_t		rval;
 
 	if (unlikely(file->f_flags & O_DIRECT)) {
 		ioflags |= IO_ISDIRECT;
 		down_read(&inode->i_alloc_sem);
-		VOP_READ(vp, file, buf, size, offset, ioflags, NULL, error);
+		VOP_READ(vp, file, buf, size, offset, ioflags, NULL, rval);
 		up_read(&inode->i_alloc_sem);
 	} else {
-		VOP_READ(vp, file, buf, size, offset, ioflags, NULL, error);
+		VOP_READ(vp, file, buf, size, offset, ioflags, NULL, rval);
 	}
-	return error;
+
+	return rval;
 }
 
 STATIC ssize_t
@@ -113,7 +114,7 @@
 	struct inode	*inode = file->f_dentry->d_inode;
 	vnode_t		*vp = LINVFS_GET_VP(inode);
 	loff_t		pos;
-	int		error;	/* Use negative errors in this f'n */
+	ssize_t		rval;	/* Use negative errors in this f'n */
 
 	if ((ssize_t) count < 0)
 		return -EINVAL;
@@ -125,10 +126,10 @@
 	if (pos < 0)
 		return -EINVAL;
 
-	error = file->f_error;
-	if (error) {
+	rval = file->f_error;
+	if (rval) {
 		file->f_error = 0;
-		return error;
+		return rval;
 	}
 
 	/* We allow multiple direct writers in, there is no
@@ -137,16 +138,17 @@
 	if (unlikely(file->f_flags & O_DIRECT)) {
 		ioflags |= IO_ISDIRECT;
 		down_read(&inode->i_alloc_sem);
-		VOP_WRITE(vp, file, buf, count, &pos, ioflags, NULL, error);
+		VOP_WRITE(vp, file, buf, count, &pos, ioflags, NULL, rval);
 		*ppos = pos;
 		up_read(&inode->i_alloc_sem);
 	} else {
 		down(&inode->i_sem);
-		VOP_WRITE(vp, file, buf, count, &pos, ioflags, NULL, error);
+		VOP_WRITE(vp, file, buf, count, &pos, ioflags, NULL, rval);
 		*ppos = pos;
 		up(&inode->i_sem);
 	}
-	return error;
+
+	return rval;
 }
 
 STATIC inline ssize_t
diff -urN linux-2.4.26-rc1/fs/xfs/linux/xfs_ioctl.c linux-2.4.26-rc2/fs/xfs/linux/xfs_ioctl.c
--- linux-2.4.26-rc1/fs/xfs/linux/xfs_ioctl.c	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/fs/xfs/linux/xfs_ioctl.c	2004-04-05 17:41:10.000000000 -0700
@@ -852,6 +852,9 @@
 	case XFS_IOC_ERROR_INJECTION: {
 		xfs_error_injection_t in;
 
+		if (!capable(CAP_SYS_ADMIN))
+			return EPERM;
+
 		if (copy_from_user(&in, (char *)arg, sizeof(in)))
 			return -XFS_ERROR(EFAULT);
 
@@ -860,6 +863,9 @@
 	}
 
 	case XFS_IOC_ERROR_CLEARALL:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
 		error = xfs_errortag_clearall(mp);
 		return -error;
 
@@ -884,7 +890,7 @@
 	if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
 		return -XFS_ERROR(EPERM);
 
-	if (filp->f_flags & O_RDONLY)
+	if (!(filp->f_flags & FMODE_WRITE))
 		return -XFS_ERROR(EBADF);
 
 	if (vp->v_type != VREG)
diff -urN linux-2.4.26-rc1/fs/xfs/xfs_attr_leaf.c linux-2.4.26-rc2/fs/xfs/xfs_attr_leaf.c
--- linux-2.4.26-rc1/fs/xfs/xfs_attr_leaf.c	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/fs/xfs/xfs_attr_leaf.c	2004-04-05 17:41:10.000000000 -0700
@@ -575,8 +575,8 @@
 	for ( ; i < nsbuf; i++, sbp++) {
 		attrnames_t	*namesp;
 
-		namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure :
-			((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
+		namesp = (sbp->flags & XFS_ATTR_SECURE) ? &attr_secure :
+			((sbp->flags & XFS_ATTR_ROOT) ? &attr_trusted :
 			  &attr_user);
 
 		if (cursor->hashval != INT_GET(sbp->hash, ARCH_CONVERT)) {
@@ -587,8 +587,7 @@
 			ASSERT(context->flags & ATTR_KERNAMELS);
 			context->count += namesp->attr_namelen +
 						sbp->namelen + 1;
-		}
-		else {
+		} else {
 			if (xfs_attr_put_listent(context, namesp,
 					sbp->name, sbp->namelen,
 					INT_GET(sbp->valuelen, ARCH_CONVERT)))
diff -urN linux-2.4.26-rc1/fs/xfs/xfs_dfrag.c linux-2.4.26-rc2/fs/xfs/xfs_dfrag.c
--- linux-2.4.26-rc1/fs/xfs/xfs_dfrag.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-rc2/fs/xfs/xfs_dfrag.c	2004-04-05 17:41:10.000000000 -0700
@@ -119,6 +119,11 @@
 		tip = XFS_BHVTOI(tbdp);
 	}
 
+	if (ip->i_mount != tip->i_mount) {
+		error =  XFS_ERROR(EINVAL);
+		goto error0;
+	}
+
 	if (ip->i_ino == tip->i_ino) {
 		error =  XFS_ERROR(EINVAL);
 		goto error0;
@@ -147,20 +152,17 @@
 	xfs_lock_inodes(ips, 2, 0, lock_flags);
 
 	/* Check permissions */
-	if ((error = _MAC_XFS_IACCESS(ip, MACWRITE, NULL))) {
-		goto error0;
-	}
-	if ((error = _MAC_XFS_IACCESS(tip, MACWRITE, NULL))) {
+	error = xfs_iaccess(ip, S_IWUSR, NULL);
+	if (error)
 		goto error0;
-	}
-	if ((current_fsuid(cred) != ip->i_d.di_uid) &&
-	    (error = xfs_iaccess(ip, S_IWUSR, NULL)) &&
-	    !capable_cred(NULL, CAP_FOWNER)) {
+
+	error = xfs_iaccess(tip, S_IWUSR, NULL);
+	if (error)
 		goto error0;
-	}
-	if ((current_fsuid(cred) != tip->i_d.di_uid) &&
-	    (error = xfs_iaccess(tip, S_IWUSR, NULL)) &&
-	    !capable_cred(NULL, CAP_FOWNER)) {
+
+	/* Verify that both files have the same format */
+	if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) {
+		error = XFS_ERROR(EINVAL);
 		goto error0;
 	}
 
diff -urN linux-2.4.26-rc1/fs/xfs/xfs_inode.c linux-2.4.26-rc2/fs/xfs/xfs_inode.c
--- linux-2.4.26-rc1/fs/xfs/xfs_inode.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-rc2/fs/xfs/xfs_inode.c	2004-04-05 17:41:10.000000000 -0700
@@ -3707,13 +3707,13 @@
 	 * Read/write DACs are always overridable.
 	 * Executable DACs are overridable if at least one exec bit is set.
 	 */
-	if ((orgmode & (S_IRUSR|S_IWUSR)) || (inode->i_mode & S_IXUGO))
+	if (!(orgmode & S_IXUSR) ||
+	    (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
 		if (capable_cred(cr, CAP_DAC_OVERRIDE))
 			return 0;
 
 	if ((orgmode == S_IRUSR) ||
-	    (((ip->i_d.di_mode & S_IFMT) == S_IFDIR) &&
-	     (!(orgmode & ~(S_IWUSR|S_IXUSR))))) {
+	    (S_ISDIR(inode->i_mode) && (!(orgmode & S_IWUSR)))) {
 		if (capable_cred(cr, CAP_DAC_READ_SEARCH))
 			return 0;
 #ifdef	NOISE
diff -urN linux-2.4.26-rc1/fs/xfs/xfs_log.c linux-2.4.26-rc2/fs/xfs/xfs_log.c
--- linux-2.4.26-rc1/fs/xfs/xfs_log.c	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/fs/xfs/xfs_log.c	2004-04-05 17:41:10.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -940,7 +940,8 @@
 void
 xlog_iodone(xfs_buf_t *bp)
 {
-	xlog_in_core_t *iclog;
+	xlog_in_core_t	*iclog;
+	xlog_t		*l;
 	int		aborted;
 
 	iclog = XFS_BUF_FSPRIVATE(bp, xlog_in_core_t *);
@@ -949,18 +950,19 @@
 	aborted = 0;
 
 	/*
+	 * Some versions of cpp barf on the recursive definition of
+	 * ic_log -> hic_fields.ic_log and expand ic_log twice when
+	 * it is passed through two macros.  Workaround broken cpp.
+	 */
+	l = iclog->ic_log;
+
+	/*
 	 * Race to shutdown the filesystem if we see an error.
 	 */
-	if (XFS_BUF_GETERROR(bp)) {
-		/* Some versions of cpp barf on the recursive definition of
-		 * ic_log -> hic_fields.ic_log and expand ic_log twice when
-		 * it is passed through two macros.  Workaround for broken cpp
-		 */
-		struct log *l;
-		xfs_ioerror_alert("xlog_iodone",
-				  iclog->ic_log->l_mp, bp, XFS_BUF_ADDR(bp));
+	if (XFS_TEST_ERROR((XFS_BUF_GETERROR(bp)), l->l_mp,
+			XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) {
+		xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp));
 		XFS_BUF_STALE(bp);
-		l = iclog->ic_log;
 		xfs_force_shutdown(l->l_mp, XFS_LOG_IO_ERROR);
 		/*
 		 * This flag will be propagated to the trans-committed
@@ -3158,6 +3160,7 @@
 		uint		xflags)
 {
 	xlog_ticket_t	*tic;
+	uint		num_headers;
 	SPLDECL(s);
 
  alloc:
@@ -3181,21 +3184,30 @@
 	 * in the log.  A unit in this case is the amount of space for one
 	 * of these log operations.  Normal reservations have a cnt of 1
 	 * and their unit amount is the total amount of space required.
-	 * The following line of code adds one log record header length
-	 * for each part of an operation which may fall on a different
-	 * log record.
 	 *
-	 * One more XLOG_HEADER_SIZE is added to account for possible
-	 * round off errors when syncing a LR to disk.  The bytes are
-	 * subtracted if the thread using this ticket is the first writer
-	 * to a new LR.
-	 *
-	 * We add an extra log header for the possibility that the commit
-	 * record is the first data written to a new log record.  In this
-	 * case it is separate from the rest of the transaction data and
-	 * will be charged for the log record header.
+	 * The following lines of code account for non-transaction data
+	 * which occupy space in the on-disk log. 
 	 */
-	unit_bytes += log->l_iclog_hsize * (XLOG_BTOLRBB(unit_bytes) + 2);
+
+	/* for start-rec */
+	unit_bytes += sizeof(xlog_op_header_t); 
+
+	/* for padding */
+	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) &&
+		log->l_mp->m_sb.sb_logsunit > 1) {
+		/* log su roundoff */
+		unit_bytes += log->l_mp->m_sb.sb_logsunit;  
+	} else {
+		/* BB roundoff */
+		unit_bytes += BBSIZE;
+        }
+
+	/* for commit-rec */
+	unit_bytes += sizeof(xlog_op_header_t);
+ 
+	/* for LR headers */
+	num_headers = ((unit_bytes + log->l_iclog_size-1) >> log->l_iclog_size_log);
+	unit_bytes += log->l_iclog_hsize * num_headers;
 
 	tic->t_unit_res		= unit_bytes;
 	tic->t_curr_res		= unit_bytes;
diff -urN linux-2.4.26-rc1/fs/xfs/xfs_log_priv.h linux-2.4.26-rc2/fs/xfs/xfs_log_priv.h
--- linux-2.4.26-rc1/fs/xfs/xfs_log_priv.h	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/fs/xfs/xfs_log_priv.h	2004-04-05 17:41:10.000000000 -0700
@@ -57,12 +57,6 @@
 #define XLOG_RECORD_BSHIFT	14		/* 16384 == 1 << 14 */
 #define XLOG_BIG_RECORD_BSHIFT	15		/* 32k == 1 << 15 */
 #define XLOG_MAX_RECORD_BSHIFT	18		/* 256k == 1 << 18 */
-#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XLOG_BTOLRBB)
-int xlog_btolrbb(int b);
-#define XLOG_BTOLRBB(b)		xlog_btolrbb(b)
-#else
-#define XLOG_BTOLRBB(b)		(((b)+XLOG_RECORD_BSIZE-1) >> XLOG_RECORD_BSHIFT)
-#endif
 #define XLOG_BTOLSUNIT(log, b)  (((b)+(log)->l_mp->m_sb.sb_logsunit-1) / \
                                  (log)->l_mp->m_sb.sb_logsunit)
 #define XLOG_LSUNITTOB(log, su) ((su) * (log)->l_mp->m_sb.sb_logsunit)
@@ -560,6 +554,7 @@
 extern int	 xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
 extern xfs_caddr_t xlog_align(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
 
+/* iclog tracing */
 #define XLOG_TRACE_GRAB_FLUSH  1
 #define XLOG_TRACE_REL_FLUSH   2
 #define XLOG_TRACE_SLEEP_FLUSH 3
diff -urN linux-2.4.26-rc1/fs/xfs/xfs_macros.c linux-2.4.26-rc2/fs/xfs/xfs_macros.c
--- linux-2.4.26-rc1/fs/xfs/xfs_macros.c	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/fs/xfs/xfs_macros.c	2004-04-05 17:41:10.000000000 -0700
@@ -2219,14 +2219,6 @@
 }
 #endif
 
-#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XLOG_BTOLRBB)
-int
-xlog_btolrbb(int b)
-{
-	return XLOG_BTOLRBB(b);
-}
-#endif
-
 #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XLOG_GRANT_ADD_SPACE)
 void
 xlog_grant_add_space(xlog_t *log, int bytes, int type)
diff -urN linux-2.4.26-rc1/fs/xfs/xfs_trans.h linux-2.4.26-rc2/fs/xfs/xfs_trans.h
--- linux-2.4.26-rc1/fs/xfs/xfs_trans.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-rc2/fs/xfs/xfs_trans.h	2004-04-05 17:41:10.000000000 -0700
@@ -535,6 +535,8 @@
  *    the super block to reflect the freed blocks: sector size
  *    worst case split in allocation btrees per extent assuming 4 extents:
  *		4 exts * 2 trees * (2 * max depth - 1) * block size
+ *    the inode btree: max depth * blocksize
+ *    the allocation btrees: 2 trees * (max depth - 1) * block size
  */
 #define	XFS_CALC_ITRUNCATE_LOG_RES(mp) \
 	(MAX( \
@@ -545,7 +547,11 @@
 	  (4 * (mp)->m_sb.sb_sectsize) + \
 	  (mp)->m_sb.sb_sectsize + \
 	  XFS_ALLOCFREE_LOG_RES(mp, 4) + \
-	  (128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))))))
+	  (128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))) + \
+	  (128 * 5) + \
+	  XFS_ALLOCFREE_LOG_RES(mp, 1) + \
+	   (128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \
+	    XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
 
 #define	XFS_ITRUNCATE_LOG_RES(mp)   ((mp)->m_reservations.tr_itruncate)
 
@@ -713,6 +719,7 @@
 	 XFS_FSB_TO_B((mp), 1) + \
 	 MAX((__uint16_t)XFS_FSB_TO_B((mp), 1), XFS_INODE_CLUSTER_SIZE(mp)) + \
 	 (128 * 5) + \
+	  XFS_ALLOCFREE_LOG_RES(mp, 1) + \
 	  (128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \
 	   XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
 
diff -urN linux-2.4.26-rc1/fs/xfs/xfs_vfsops.c linux-2.4.26-rc2/fs/xfs/xfs_vfsops.c
--- linux-2.4.26-rc1/fs/xfs/xfs_vfsops.c	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/fs/xfs/xfs_vfsops.c	2004-04-05 17:41:10.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * XFS filesystem operations.
  *
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -229,7 +229,10 @@
 		mp->m_swidth = ap->swidth;
 	}
 
-	if (ap->logbufs != 0 && ap->logbufs != -1 &&
+	if (ap->logbufs != -1 &&
+#if defined(DEBUG) || defined(XLOG_NOLOG)
+	    ap->logbufs != 0 &&
+#endif
 	    (ap->logbufs < XLOG_MIN_ICLOGS ||
 	     ap->logbufs > XLOG_MAX_ICLOGS)) {
 		cmn_err(CE_WARN,
@@ -1482,8 +1485,10 @@
 			 */
 			if (XFS_BUF_ISPINNED(bp))
 				xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
-			if (!(flags & SYNC_WAIT))
-				XFS_BUF_BFLAGS(bp) |= XFS_B_ASYNC;
+			if (flags & SYNC_WAIT)
+				XFS_BUF_UNASYNC(bp);
+			else
+				XFS_BUF_ASYNC(bp);
 			error = xfs_bwrite(mp, bp);
 		}
 		if (error) {
diff -urN linux-2.4.26-rc1/fs/xfs/xfs_vnodeops.c linux-2.4.26-rc2/fs/xfs/xfs_vnodeops.c
--- linux-2.4.26-rc1/fs/xfs/xfs_vnodeops.c	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/fs/xfs/xfs_vnodeops.c	2004-04-05 17:41:10.000000000 -0700
@@ -1106,14 +1106,11 @@
 	xfs_off_t	stop)
 {
 	xfs_inode_t	*ip;
-	int		error;
-	int		error2;
-	int		syncall;
-	vnode_t		*vp;
 	xfs_trans_t	*tp;
+	int		error;
 
-	vp = BHV_TO_VNODE(bdp);
-	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
+	vn_trace_entry(BHV_TO_VNODE(bdp),
+			__FUNCTION__, (inst_t *)__return_address);
 
 	ip = XFS_BHVTOI(bdp);
 
@@ -1122,44 +1119,6 @@
 	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
 		return XFS_ERROR(EIO);
 
-	xfs_ilock(ip, XFS_IOLOCK_EXCL);
-
-	syncall = error = error2 = 0;
-
-	if (stop == -1)  {
-		ASSERT(start >= 0);
-		if (start == 0)
-			syncall = 1;
-		stop = xfs_file_last_byte(ip);
-	}
-
-	/*
-	 * If we're invalidating, always flush since we want to
-	 * tear things down.  Otherwise, don't flush anything if
-	 * we're not dirty.
-	 */
-	if (flag & FSYNC_INVAL) {
-		if (ip->i_df.if_flags & XFS_IFEXTENTS &&
-		    ip->i_df.if_bytes > 0) {
-			VOP_FLUSHINVAL_PAGES(vp, start, -1, FI_REMAPF_LOCKED);
-		}
-		ASSERT(syncall == 0 || (VN_CACHED(vp) == 0));
-	} else {
-		/*
-		 * In the non-invalidating case, calls to fsync() do not
-		 * flush all the dirty mmap'd pages.  That requires a
-		 * call to msync().
-		 */
-		VOP_FLUSH_PAGES(vp, start, -1,
-				(flag & FSYNC_WAIT) ? 0 : XFS_B_ASYNC,
-				FI_NONE, error2);
-	}
-
-	if (error2) {
-		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
-		return XFS_ERROR(error2);
-	}
-
 	/*
 	 * We always need to make sure that the required inode state
 	 * is safe on disk.  The vnode might be clean but because
@@ -1199,7 +1158,7 @@
 		 * be pinned.  If it is, force the log.
 		 */
 
-		xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_SHARED);
+		xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
 		if (xfs_ipincount(ip)) {
 			xfs_log_force(ip->i_mount, (xfs_lsn_t)0,
@@ -1222,7 +1181,6 @@
 				XFS_FSYNC_TS_LOG_RES(ip->i_mount),
 				0, 0, 0)))  {
 			xfs_trans_cancel(tp, 0);
-			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 			return error;
 		}
 		xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1237,68 +1195,18 @@
 		 * inode in another recent transaction.	 So we
 		 * play it safe and fire off the transaction anyway.
 		 */
-		xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL);
+		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 		xfs_trans_ihold(tp, ip);
 		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 		if (flag & FSYNC_WAIT)
 			xfs_trans_set_sync(tp);
 		error = xfs_trans_commit(tp, 0, NULL);
 
-		xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL);
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	}
 	return error;
 }
 
-
-#if 0
-/*
- * This is a utility routine for xfs_inactive.  It is called when a
- * transaction attempting to free up the disk space for a file encounters
- * an error.  It cancels the old transaction and starts up a new one
- * to be used to free up the inode.  It also sets the inode size and extent
- * counts to 0 and frees up any memory being used to store inline data,
- * extents, or btree roots.
- */
-STATIC void
-xfs_itruncate_cleanup(
-	xfs_trans_t	**tpp,
-	xfs_inode_t	*ip,
-	int		commit_flags,
-	int		fork)
-{
-	xfs_mount_t	*mp;
-	/* REFERENCED */
-	int		error;
-
-	mp = ip->i_mount;
-	if (*tpp) {
-		xfs_trans_cancel(*tpp, commit_flags | XFS_TRANS_ABORT);
-	}
-	xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
-	*tpp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
-	error = xfs_trans_reserve(*tpp, 0, XFS_IFREE_LOG_RES(mp), 0, 0,
-				  XFS_DEFAULT_LOG_COUNT);
-	if (error) {
-		return;
-	}
-
-	xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
-	xfs_trans_ijoin(*tpp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
-	xfs_trans_ihold(*tpp, ip);
-
-	xfs_idestroy_fork(ip, fork);
-
-	if (fork == XFS_DATA_FORK) {
-		ip->i_d.di_nblocks = 0;
-		ip->i_d.di_nextents = 0;
-		ip->i_d.di_size = 0;
-	} else {
-		ip->i_d.di_anextents = 0;
-	}
-	xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
-}
-#endif
-
 /*
  * This is called by xfs_inactive to free any blocks beyond eof,
  * when the link count isn't zero.
diff -urN linux-2.4.26-rc1/include/asm-i386/acpi.h linux-2.4.26-rc2/include/asm-i386/acpi.h
--- linux-2.4.26-rc1/include/asm-i386/acpi.h	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/include/asm-i386/acpi.h	2004-04-05 17:41:10.000000000 -0700
@@ -52,15 +52,6 @@
 #define ACPI_ENABLE_IRQS()  __sti()
 #define ACPI_FLUSH_CPU_CACHE()	wbinvd()
 
-/*
- * A brief explanation as GNU inline assembly is a bit hairy
- *  %0 is the output parameter in EAX ("=a")
- *  %1 and %2 are the input parameters in ECX ("c")
- *  and an immediate value ("i") respectively
- *  All actual register references are preceded with "%%" as in "%%edx"
- *  Immediate values in the assembly are preceded by "$" as in "$0x1"
- *  The final asm parameter are the operation altered non-output registers.
- */
 
 static inline int
 __acpi_acquire_global_lock (unsigned int *lock)
diff -urN linux-2.4.26-rc1/include/asm-i386/system.h linux-2.4.26-rc2/include/asm-i386/system.h
--- linux-2.4.26-rc1/include/asm-i386/system.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.26-rc2/include/asm-i386/system.h	2004-04-05 17:41:10.000000000 -0700
@@ -238,6 +238,7 @@
 
 #ifdef CONFIG_X86_CMPXCHG
 #define __HAVE_ARCH_CMPXCHG 1
+#endif
 
 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 				      unsigned long new, int size)
@@ -270,10 +271,6 @@
 	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
 					(unsigned long)(n),sizeof(*(ptr))))
     
-#else
-/* Compiling for a 386 proper.	Is it worth implementing via cli/sti?  */
-#endif
-
 /*
  * Force strict CPU ordering.
  * And yes, this is required on UP too when we're talking
diff -urN linux-2.4.26-rc1/include/asm-ppc/ibm44x.h linux-2.4.26-rc2/include/asm-ppc/ibm44x.h
--- linux-2.4.26-rc1/include/asm-ppc/ibm44x.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-rc2/include/asm-ppc/ibm44x.h	2004-04-05 17:41:10.000000000 -0700
@@ -4,9 +4,10 @@
  * PPC44x definitions
  *
  * Matt Porter <mporter@mvista.com>
- *
  * Copyright 2002-2003 MontaVista Software Inc.
  *
+ * Eugene Surovegin <ebs@ebshome.net>
+ *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
@@ -80,13 +81,34 @@
 /*
  * SPRN definitions
  */
-#define SPRN_CPC0_GPIO		0xe5/BEARLRL
+#define SPRN_CPC0_GPIO		0xe5
 
 /*
  * DCRN definitions
  */ 
 
 #ifdef CONFIG_440GX
+/* CPRs */
+#define DCRN_CPR_CONFIG_ADDR	0xc
+#define DCRN_CPR_CONFIG_DATA	0xd
+
+#define DCRN_CPR_CLKUPD		0x0020
+#define DCRN_CPR_PLLC		0x0040
+#define DCRN_CPR_PLLD		0x0060
+#define DCRN_CPR_PRIMAD		0x0080
+#define DCRN_CPR_PRIMBD		0x00a0
+#define DCRN_CPR_OPBD		0x00c0
+#define DCRN_CPR_PERD		0x00e0
+#define DCRN_CPR_MALD		0x0100
+
+/* CPRs read/write helper macros */
+#define CPR_READ(offset) ({\
+	mtdcr(DCRN_CPR_CONFIG_ADDR, offset); \
+	mfdcr(DCRN_CPR_CONFIG_DATA);})
+#define CPR_WRITE(offset, data) ({\
+	mtdcr(DCRN_CPR_CONFIG_ADDR, offset); \
+	mtdcr(DCRN_CPR_CONFIG_DATA, data);})
+
 /* SDRs */
 #define DCRN_SDR_CONFIG_ADDR 	0xe 
 #define DCRN_SDR_CONFIG_DATA	0xf
@@ -117,6 +139,8 @@
 #define DCRN_SDR_MFR_E3TXFH	0x00000004
 #define DCRN_SDR_MFR_E3RXFL	0x00000002
 #define DCRN_SDR_MFR_E3RXFH	0x00000001
+#define DCRN_SDR_UART0		0x0120
+#define DCRN_SDR_UART1		0x0121
 
 /* SDR read/write helper macros */
 #define SDR_READ(offset) ({\
@@ -327,6 +351,81 @@
 #define PPC44x_MEM_SIZE_256M		0x10000000
 #define PPC44x_MEM_SIZE_512M		0x20000000
 
+#ifdef CONFIG_440GX
+/* Internal SRAM Controller */
+#define DCRN_SRAM0_SB0CR	0x020
+#define DCRN_SRAM0_SB1CR	0x021
+#define DCRN_SRAM0_SB2CR	0x022
+#define DCRN_SRAM0_SB3CR	0x023
+#define  SRAM_SBCR_BAS0		0x80000000
+#define  SRAM_SBCR_BAS1		0x80010000
+#define  SRAM_SBCR_BAS2		0x80020000
+#define  SRAM_SBCR_BAS3		0x80030000
+#define  SRAM_SBCR_BU_MASK	0x00000180
+#define  SRAM_SBCR_BS_64KB	0x00000800
+#define  SRAM_SBCR_BU_RO	0x00000080
+#define  SRAM_SBCR_BU_RW	0x00000180
+#define DCRN_SRAM0_BEAR		0x024
+#define DCRN_SRAM0_BESR0	0x025
+#define DCRN_SRAM0_BESR1	0x026
+#define DCRN_SRAM0_PMEG		0x027
+#define DCRN_SRAM0_CID		0x028
+#define DCRN_SRAM0_REVID	0x029
+#define DCRN_SRAM0_DPC		0x02a
+#define  SRAM_DPC_ENABLE	0x80000000
+
+/* L2 Cache Controller */
+#define DCRN_L2C0_CFG		0x030
+#define  L2C_CFG_L2M		0x80000000
+#define  L2C_CFG_ICU		0x40000000
+#define  L2C_CFG_DCU		0x20000000
+#define  L2C_CFG_DCW_MASK	0x1e000000
+#define  L2C_CFG_TPC		0x01000000
+#define  L2C_CFG_CPC		0x00800000
+#define  L2C_CFG_FRAN		0x00200000
+#define  L2C_CFG_SS_MASK	0x00180000
+#define  L2C_CFG_SS_256		0x00000000
+#define  L2C_CFG_CPIM		0x00040000
+#define  L2C_CFG_TPIM		0x00020000
+#define  L2C_CFG_LIM		0x00010000
+#define  L2C_CFG_PMUX_MASK	0x00007000
+#define  L2C_CFG_PMUX_SNP	0x00000000
+#define  L2C_CFG_PMUX_IF	0x00001000
+#define  L2C_CFG_PMUX_DF	0x00002000
+#define  L2C_CFG_PMUX_DS	0x00003000
+#define  L2C_CFG_PMIM		0x00000800
+#define  L2C_CFG_TPEI		0x00000400
+#define  L2C_CFG_CPEI		0x00000200
+#define  L2C_CFG_NAM		0x00000100
+#define  L2C_CFG_SMCM		0x00000080
+#define  L2C_CFG_NBRM		0x00000040
+#define DCRN_L2C0_CMD		0x031
+#define  L2C_CMD_CLR		0x80000000
+#define  L2C_CMD_DIAG		0x40000000
+#define  L2C_CMD_INV		0x20000000
+#define  L2C_CMD_CCP		0x10000000
+#define  L2C_CMD_CTE		0x08000000
+#define  L2C_CMD_STRC		0x04000000
+#define  L2C_CMD_STPC		0x02000000
+#define  L2C_CMD_RPMC		0x01000000
+#define  L2C_CMD_HCC		0x00800000
+#define DCRN_L2C0_ADDR		0x032
+#define DCRN_L2C0_DATA		0x033
+#define DCRN_L2C0_SR		0x034
+#define  L2C_SR_CC		0x80000000
+#define  L2C_SR_CPE		0x40000000
+#define  L2C_SR_TPE		0x20000000
+#define  L2C_SR_LRU		0x10000000
+#define  L2C_SR_PCS		0x08000000
+#define DCRN_L2C0_REVID		0x035
+#define DCRN_L2C0_SNP0		0x036
+#define DCRN_L2C0_SNP1		0x037
+#define  L2C_SNP_BA_MASK	0xffff0000
+#define  L2C_SNP_SSR_MASK	0x0000f000
+#define  L2C_SNP_SSR_32G	0x0000f000
+#define  L2C_SNP_ESR		0x00000800
+#endif /* CONFIG_440GX */
+
 /*
  * PCI-X definitions
  */
diff -urN linux-2.4.26-rc1/include/asm-ppc/ppc_asm.h linux-2.4.26-rc2/include/asm-ppc/ppc_asm.h
--- linux-2.4.26-rc1/include/asm-ppc/ppc_asm.h	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-rc2/include/asm-ppc/ppc_asm.h	2004-04-05 17:41:10.000000000 -0700
@@ -163,6 +163,8 @@
 #define CLR_TOP32(r)
 #endif /* CONFIG_PPC64BRIDGE */
 
+#define RFMCI		.long 0x4c00004c	/* rfmci instruction */
+
 #ifdef CONFIG_IBM405_ERR77
 #define PPC405_ERR77(ra,rb)	dcbt	ra, rb;
 #define	PPC405_ERR77_SYNC	sync;
diff -urN linux-2.4.26-rc1/include/asm-ppc/processor.h linux-2.4.26-rc2/include/asm-ppc/processor.h
--- linux-2.4.26-rc1/include/asm-ppc/processor.h	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/include/asm-ppc/processor.h	2004-04-05 17:41:10.000000000 -0700
@@ -544,10 +544,22 @@
 #define SPRN_IVOR13	0x19d	/* Interrupt Vector Offset Register 13 */
 #define SPRN_IVOR14	0x19e	/* Interrupt Vector Offset Register 14 */
 #define SPRN_IVOR15	0x19f	/* Interrupt Vector Offset Register 15 */
+#define SPRN_MCSRR0	0x23a	/* Machine Check Save and Restore Register 0 */
+#define SPRN_MCSRR1	0x23b	/* Machine Check Save and Restore Register 1 */
+#define SPRN_MCSR	0x23c	/* Machine Check Syndrom Register */
+#if defined(CONFIG_440A)
+#define  MCSR_MCS	0x80000000 /* Machine Check Summary */
+#define  MCSR_IB	0x40000000 /* Instruction PLB Error */
+#define  MCSR_DRB	0x20000000 /* Data Read PLB Error */
+#define  MCSR_DWB	0x10000000 /* Data Write PLB Error */
+#define  MCSR_TLBP	0x08000000 /* TLB Parity Error */
+#define  MCSR_ICP	0x04000000 /* I-Cache Parity Error */
+#define  MCSR_DCSP	0x02000000 /* D-Cache Search Parity Error */
+#define  MCSR_DCFP	0x01000000 /* D-Cache Flush Parity Error */
+#define  MCSR_IMPE	0x00800000 /* Imprecise Machine Check Exception */
+#endif
 #define SPRN_MMUCR	0x3b2	/* MMU Control Register */
 
-#define ESR_ST		0x00800000	/* Store Operation */
-
 /* Short-hand versions for a number of the above SPRNs */
 
 #define	CTR	SPRN_CTR	/* Counter Register */
@@ -664,7 +676,9 @@
 #define PVR_440GP_RB	0x40120440
 #define PVR_440GP_RC1	0x40120481
 #define PVR_440GP_RC2	0x40200481
-#define PVR_440GX_RC1	0x51b21850
+#define PVR_440GX_RA	0x51b21850
+#define PVR_440GX_RB	0x51b21851
+#define PVR_440GX_RB1	0x51b21852
 #define	PVR_601		0x00010000
 #define	PVR_602		0x00050000
 #define	PVR_603		0x00030000
diff -urN linux-2.4.26-rc1/include/linux/inetdevice.h linux-2.4.26-rc2/include/linux/inetdevice.h
--- linux-2.4.26-rc1/include/linux/inetdevice.h	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/include/linux/inetdevice.h	2004-04-05 17:41:10.000000000 -0700
@@ -34,8 +34,6 @@
 	rwlock_t		lock;
 	int			dead;
 	struct in_ifaddr	*ifa_list;	/* IP ifaddr chain		*/
-	int			mc_initted;
-
 	struct ip_mc_list	*mc_list;	/* IP multicast filter chain    */
 	rwlock_t		mc_lock;	/* for mc_tomb */
 	struct ip_mc_list	*mc_tomb;
diff -urN linux-2.4.26-rc1/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.26-rc2/include/linux/netfilter_ipv4/ip_conntrack.h
--- linux-2.4.26-rc1/include/linux/netfilter_ipv4/ip_conntrack.h	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-rc2/include/linux/netfilter_ipv4/ip_conntrack.h	2004-04-05 17:41:10.000000000 -0700
@@ -156,7 +156,8 @@
 	union ip_conntrack_expect_help help;
 };
 
-#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+struct ip_conntrack_helper;
+
 struct ip_conntrack
 {
 	/* Usage count in here is 1 for hash table/destruct timer, 1 per skb,
diff -urN linux-2.4.26-rc1/include/linux/pci_ids.h linux-2.4.26-rc2/include/linux/pci_ids.h
--- linux-2.4.26-rc1/include/linux/pci_ids.h	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/include/linux/pci_ids.h	2004-04-05 17:41:10.000000000 -0700
@@ -317,6 +317,8 @@
 #define PCI_DEVICE_ID_ATI_RADEON_Lg	0x4c67
 /* RadeonIGP */
 #define PCI_DEVICE_ID_ATI_RADEON_IGP	0xCAB0
+/* ATI IXP Chipset */
+#define PCI_DEVICE_ID_ATI_IXP_IDE	0x4349
 
 #define PCI_VENDOR_ID_VLSI		0x1004
 #define PCI_DEVICE_ID_VLSI_82C592	0x0005
diff -urN linux-2.4.26-rc1/include/net/ipv6.h linux-2.4.26-rc2/include/net/ipv6.h
--- linux-2.4.26-rc1/include/net/ipv6.h	2004-04-05 17:40:54.000000000 -0700
+++ linux-2.4.26-rc2/include/net/ipv6.h	2004-04-05 17:41:10.000000000 -0700
@@ -321,7 +321,7 @@
 						    struct ipv6_txoptions *opt,
 						    u8 *proto);
 
-extern int			ipv6_skip_exthdr(struct sk_buff *, int start,
+extern int			ipv6_skip_exthdr(const struct sk_buff *, int start,
 					         u8 *nexthdrp, int len);
 
 extern int 			ipv6_ext_hdr(u8 nexthdr);
diff -urN linux-2.4.26-rc1/net/atm/mpoa_proc.c linux-2.4.26-rc2/net/atm/mpoa_proc.c
--- linux-2.4.26-rc1/net/atm/mpoa_proc.c	2001-07-04 11:50:38.000000000 -0700
+++ linux-2.4.26-rc2/net/atm/mpoa_proc.c	2004-04-05 17:41:11.000000000 -0700
@@ -102,7 +102,7 @@
 			     size_t count, loff_t *pos){
         unsigned long page = 0;
 	unsigned char *temp;
-        ssize_t length  = 0;
+        int length = 0;
 	int i = 0;
 	struct mpoa_client *mpc = mpcs;
 	in_cache_entry *in_entry;
diff -urN linux-2.4.26-rc1/net/ipv4/devinet.c linux-2.4.26-rc2/net/ipv4/devinet.c
--- linux-2.4.26-rc1/net/ipv4/devinet.c	2004-04-05 17:40:55.000000000 -0700
+++ linux-2.4.26-rc2/net/ipv4/devinet.c	2004-04-05 17:41:12.000000000 -0700
@@ -151,7 +151,8 @@
 #ifdef CONFIG_SYSCTL
 	devinet_sysctl_register(in_dev, &in_dev->cnf);
 #endif
-	if (dev->flags&IFF_UP)
+	ip_mc_init_dev(in_dev);
+	if (dev->flags & IFF_UP)
 		ip_mc_up(in_dev);
 	return in_dev;
 }
diff -urN linux-2.4.26-rc1/net/ipv4/igmp.c linux-2.4.26-rc2/net/ipv4/igmp.c
--- linux-2.4.26-rc1/net/ipv4/igmp.c	2004-04-05 17:40:55.000000000 -0700
+++ linux-2.4.26-rc2/net/ipv4/igmp.c	2004-04-05 17:41:12.000000000 -0700
@@ -1205,8 +1205,8 @@
 
 	ASSERT_RTNL();
 
-	if (!in_dev->mc_initted)
-		return;
+	for (i=in_dev->mc_list; i; i=i->next)
+		igmp_group_dropped(i);
 
 #ifdef CONFIG_IP_MULTICAST
 	in_dev->mr_ifc_count = 0;
@@ -1215,24 +1215,14 @@
 	in_dev->mr_gq_running = 0;
 	if (del_timer(&in_dev->mr_gq_timer))
 		__in_dev_put(in_dev);
-#endif
-
-	for (i=in_dev->mc_list; i; i=i->next)
-		igmp_group_dropped(i);
-
-#ifdef CONFIG_IP_MULTICAST
 	igmpv3_clear_delrec(in_dev);
 #endif
 
 	ip_mc_dec_group(in_dev, IGMP_ALL_HOSTS);
 }
 
-/* Device going up */
-
-void ip_mc_up(struct in_device *in_dev)
+void ip_mc_init_dev(struct in_device *in_dev)
 {
-	struct ip_mc_list *i;
-
 	ASSERT_RTNL();
 
 	in_dev->mc_tomb = 0;
@@ -1249,12 +1239,20 @@
 #endif
 
 	in_dev->mc_lock = RW_LOCK_UNLOCKED;
+}
+
+/* Device going up */
+
+void ip_mc_up(struct in_device *in_dev)
+{
+	struct ip_mc_list *i;
+
+	ASSERT_RTNL();
+
 	ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);
 
 	for (i=in_dev->mc_list; i; i=i->next)
 		igmp_group_added(i);
-
-	in_dev->mc_initted = 1;
 }
 
 /*
diff -urN linux-2.4.26-rc1/net/ipv4/netfilter/ip_nat_standalone.c linux-2.4.26-rc2/net/ipv4/netfilter/ip_nat_standalone.c
--- linux-2.4.26-rc1/net/ipv4/netfilter/ip_nat_standalone.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-rc2/net/ipv4/netfilter/ip_nat_standalone.c	2004-04-05 17:41:12.000000000 -0700
@@ -114,7 +114,16 @@
 		WRITE_LOCK(&ip_nat_lock);
 		/* Seen it before?  This can happen for loopback, retrans,
 		   or local packets.. */
-		if (!(info->initialized & (1 << maniptype))) {
+		if (!(info->initialized & (1 << maniptype))
+#ifndef CONFIG_IP_NF_NAT_LOCAL
+		    /* If this session has already been confirmed we must not
+		     * touch it again even if there is no mapping set up.
+		     * Can only happen on local->local traffic with
+		     * CONFIG_IP_NF_NAT_LOCAL disabled.
+		     */
+		    && !(ct->status & IPS_CONFIRMED)
+#endif
+		    ) {
 			unsigned int ret;
 
 			if (ct->master
diff -urN linux-2.4.26-rc1/net/ipv4/netfilter/ipt_MASQUERADE.c linux-2.4.26-rc2/net/ipv4/netfilter/ipt_MASQUERADE.c
--- linux-2.4.26-rc1/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-02-18 05:36:32.000000000 -0800
+++ linux-2.4.26-rc2/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-04-05 17:41:12.000000000 -0700
@@ -32,7 +32,7 @@
 	const struct ip_nat_multi_range *mr = targinfo;
 
 	if (strcmp(tablename, "nat") != 0) {
-		DEBUGP("masquerade_check: bad table `%s'.\n", table);
+		DEBUGP("masquerade_check: bad table `%s'.\n", tablename);
 		return 0;
 	}
 	if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
diff -urN linux-2.4.26-rc1/net/ipv4/tcp_ipv4.c linux-2.4.26-rc2/net/ipv4/tcp_ipv4.c
--- linux-2.4.26-rc1/net/ipv4/tcp_ipv4.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-rc2/net/ipv4/tcp_ipv4.c	2004-04-05 17:41:12.000000000 -0700
@@ -1804,7 +1804,8 @@
 do_time_wait:
 	if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
 		TCP_INC_STATS_BH(TcpInErrs);
-		goto discard_and_relse;
+		tcp_tw_put((struct tcp_tw_bucket *) sk);
+		goto discard_it;
 	}
 	switch(tcp_timewait_state_process((struct tcp_tw_bucket *)sk,
 					  skb, th, skb->len)) {
diff -urN linux-2.4.26-rc1/net/ipv6/exthdrs.c linux-2.4.26-rc2/net/ipv6/exthdrs.c
--- linux-2.4.26-rc1/net/ipv6/exthdrs.c	2004-04-05 17:40:55.000000000 -0700
+++ linux-2.4.26-rc2/net/ipv6/exthdrs.c	2004-04-05 17:41:13.000000000 -0700
@@ -783,7 +783,7 @@
  * --ANK (980726)
  */
 
-int ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len)
+int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len)
 {
 	u8 nexthdr = *nexthdrp;
 
diff -urN linux-2.4.26-rc1/net/ipv6/tcp_ipv6.c linux-2.4.26-rc2/net/ipv6/tcp_ipv6.c
--- linux-2.4.26-rc1/net/ipv6/tcp_ipv6.c	2003-11-28 10:26:21.000000000 -0800
+++ linux-2.4.26-rc2/net/ipv6/tcp_ipv6.c	2004-04-05 17:41:13.000000000 -0700
@@ -1647,7 +1647,7 @@
 do_time_wait:
 	if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
 		TCP_INC_STATS_BH(TcpInErrs);
-		sock_put(sk);
+		tcp_tw_put((struct tcp_tw_bucket *) sk);	
 		goto discard_it;
 	}
 
diff -urN linux-2.4.26-rc1/net/packet/af_packet.c linux-2.4.26-rc2/net/packet/af_packet.c
--- linux-2.4.26-rc1/net/packet/af_packet.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.26-rc2/net/packet/af_packet.c	2004-04-05 17:41:13.000000000 -0700
@@ -34,6 +34,8 @@
  *	Alexey Kuznetsov	:	Untied from IPv4 stack.
  *	Cyrus Durgin		:	Fixed kerneld for kmod.
  *	Michal Ostrowski        :       Module initialization cleanup.
+ *         Ulises Alonso        :       Frame number limit removal and 
+ *                                      packet_set_ring memory leak.
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -176,29 +178,46 @@
 
 struct packet_opt
 {
+	struct tpacket_stats	stats;
+#ifdef CONFIG_PACKET_MMAP
+	unsigned long		*pg_vec;
+	unsigned int		head;
+	unsigned int            frames_per_block;
+	unsigned int		frame_size;
+	unsigned int		frame_max;
+	int			copy_thresh;
+#endif
 	struct packet_type	prot_hook;
 	spinlock_t		bind_lock;
 	char			running;	/* prot_hook is attached*/
 	int			ifindex;	/* bound device		*/
-	struct tpacket_stats	stats;
 #ifdef CONFIG_PACKET_MULTICAST
 	struct packet_mclist	*mclist;
 #endif
 #ifdef CONFIG_PACKET_MMAP
 	atomic_t		mapped;
-	unsigned long		*pg_vec;
 	unsigned int		pg_vec_order;
 	unsigned int		pg_vec_pages;
 	unsigned int		pg_vec_len;
-
-	struct tpacket_hdr	**iovec;
-	unsigned int		frame_size;
-	unsigned int		iovmax;
-	unsigned int		head;
-	int			copy_thresh;
 #endif
 };
 
+#ifdef CONFIG_PACKET_MMAP
+
+static inline unsigned long packet_lookup_frame(struct packet_opt *po, unsigned int position)
+{
+	unsigned int pg_vec_pos, frame_offset;
+	unsigned long frame;
+
+	pg_vec_pos = position / po->frames_per_block;
+	frame_offset = position % po->frames_per_block;
+
+	frame = (unsigned long) (po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size));
+	
+	return frame;
+}
+#endif
+
 void packet_sock_destruct(struct sock *sk)
 {
 	BUG_TRAP(atomic_read(&sk->rmem_alloc)==0);
@@ -590,11 +609,11 @@
 		snaplen = skb->len-skb->data_len;
 
 	spin_lock(&sk->receive_queue.lock);
-	h = po->iovec[po->head];
+	h = (struct tpacket_hdr *)packet_lookup_frame(po, po->head);
 
 	if (h->tp_status)
 		goto ring_is_full;
-	po->head = po->head != po->iovmax ? po->head+1 : 0;
+	po->head = po->head != po->frame_max ? po->head+1 : 0;
 	po->stats.tp_packets++;
 	if (copy_skb) {
 		status |= TP_STATUS_COPY;
@@ -1555,10 +1574,13 @@
 	unsigned int mask = datagram_poll(file, sock, wait);
 
 	spin_lock_bh(&sk->receive_queue.lock);
-	if (po->iovec) {
-		unsigned last = po->head ? po->head-1 : po->iovmax;
+	if (po->pg_vec) {
+		unsigned last = po->head ? po->head-1 : po->frame_max;
+		struct tpacket_hdr *h;
+
+		h = (struct tpacket_hdr *)packet_lookup_frame(po, last);
 
-		if (po->iovec[last]->tp_status)
+		if (h->tp_status)
 			mask |= POLLIN | POLLRDNORM;
 	}
 	spin_unlock_bh(&sk->receive_queue.lock);
@@ -1618,16 +1640,18 @@
 static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing)
 {
 	unsigned long *pg_vec = NULL;
-	struct tpacket_hdr **io_vec = NULL;
 	struct packet_opt *po = sk->protinfo.af_packet;
 	int order = 0;
 	int err = 0;
 
 	if (req->tp_block_nr) {
 		int i, l;
-		int frames_per_block;
 
 		/* Sanity tests and some calculations */
+
+		if (po->pg_vec)
+			return -EBUSY;
+
 		if ((int)req->tp_block_size <= 0)
 			return -EINVAL;
 		if (req->tp_block_size&(PAGE_SIZE-1))
@@ -1636,10 +1660,11 @@
 			return -EINVAL;
 		if (req->tp_frame_size&(TPACKET_ALIGNMENT-1))
 			return -EINVAL;
-		frames_per_block = req->tp_block_size/req->tp_frame_size;
-		if (frames_per_block <= 0)
+
+		po->frames_per_block = req->tp_block_size/req->tp_frame_size;
+		if (po->frames_per_block <= 0)
 			return -EINVAL;
-		if (frames_per_block*req->tp_block_nr != req->tp_frame_nr)
+		if (po->frames_per_block*req->tp_block_nr != req->tp_frame_nr)
 			return -EINVAL;
 		/* OK! */
 
@@ -1666,20 +1691,16 @@
 		}
 		/* Page vector is allocated */
 
-		/* Draw frames */
-		io_vec = kmalloc(req->tp_frame_nr*sizeof(struct tpacket_hdr*), GFP_KERNEL);
-		if (io_vec == NULL)
-			goto out_free_pgvec;
-		memset(io_vec, 0, req->tp_frame_nr*sizeof(struct tpacket_hdr*));
-
 		l = 0;
 		for (i=0; i<req->tp_block_nr; i++) {
 			unsigned long ptr = pg_vec[i];
+			struct tpacket_hdr *header;
 			int k;
 
-			for (k=0; k<frames_per_block; k++, l++) {
-				io_vec[l] = (struct tpacket_hdr*)ptr;
-				io_vec[l]->tp_status = TP_STATUS_KERNEL;
+			for (k=0; k<po->frames_per_block; k++) {
+				
+				header = (struct tpacket_hdr*)ptr;
+				header->tp_status = TP_STATUS_KERNEL;
 				ptr += req->tp_frame_size;
 			}
 		}
@@ -1704,8 +1725,7 @@
 
 		spin_lock_bh(&sk->receive_queue.lock);
 		pg_vec = XC(po->pg_vec, pg_vec);
-		io_vec = XC(po->iovec, io_vec);
-		po->iovmax = req->tp_frame_nr-1;
+		po->frame_max = req->tp_frame_nr-1;
 		po->head = 0;
 		po->frame_size = req->tp_frame_size;
 		spin_unlock_bh(&sk->receive_queue.lock);
@@ -1714,7 +1734,7 @@
 		req->tp_block_nr = XC(po->pg_vec_len, req->tp_block_nr);
 
 		po->pg_vec_pages = req->tp_block_size/PAGE_SIZE;
-		po->prot_hook.func = po->iovec ? tpacket_rcv : packet_rcv;
+		po->prot_hook.func = po->pg_vec ? tpacket_rcv : packet_rcv;
 		skb_queue_purge(&sk->receive_queue);
 #undef XC
 		if (atomic_read(&po->mapped))
@@ -1728,9 +1748,6 @@
 
 	release_sock(sk);
 
-	if (io_vec)
-		kfree(io_vec);
-
 out_free_pgvec:
 	if (pg_vec)
 		free_pg_vec(pg_vec, order, req->tp_block_nr);
diff -urN linux-2.4.26-rc1/net/sctp/Config.in linux-2.4.26-rc2/net/sctp/Config.in
--- linux-2.4.26-rc1/net/sctp/Config.in	2004-04-05 17:40:55.000000000 -0700
+++ linux-2.4.26-rc2/net/sctp/Config.in	2004-04-05 17:41:14.000000000 -0700
@@ -4,10 +4,10 @@
 mainmenu_option next_comment
 comment '   SCTP Configuration (EXPERIMENTAL)'
 
-if [ "$CONFIG_IPV6" = "n" ]; then
-  tristate '  The SCTP Protocol (EXPERIMENTAL)' CONFIG_IP_SCTP
-else
-  dep_tristate '  The SCTP Protocol (EXPERIMENTAL)' CONFIG_IP_SCTP $CONFIG_IPV6
+tristate '  The SCTP Protocol (EXPERIMENTAL)' CONFIG_IP_SCTP
+
+if [ "$CONFIG_IP_SCTP" = "y" -a "$CONFIG_IPV6" = "m" ]; then
+	define_tristate CONFIG_IP_SCTP m
 fi
 
 if [ "$CONFIG_IP_SCTP" != "n" ]; then
