--- /dev/null
+From heiko.carstens@de.ibm.com Fri May 4 12:29:29 2007
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Fri, 04 May 2007 21:22:10 +0200
+Subject: s390: page_mkclean data corruption.
+To: stable@kernel.org, greg@kroah.com
+Cc: heiko.carstens@de.ibm.com, schwidefsky@de.ibm.com
+Message-ID: <20070504192825.956914833@de.ibm.com>
+Content-Disposition: inline; filename=01-data-corruption.diff
+
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+The git commit c2fda5fed81eea077363b285b66eafce20dfd45a which
+added the page_test_and_clear_dirty call to page_mkclean and the
+git commit 7658cc289288b8ae7dd2c2224549a048431222b3 which fixes
+the "nasty and subtle race in shared mmap'ed page writeback"
+problem in clear_page_dirty_for_io cause data corruption on s390.
+
+The effect of the two changes is that for every call to
+clear_page_dirty_for_io a page_test_and_clear_dirty is done. If
+the per page dirty bit is set set_page_dirty is called. Strangly
+clear_page_dirty_for_io is called for not-uptodate pages, e.g.
+over this call-chain:
+
+[<000000000007c0f2>] clear_page_dirty_for_io+0x12a/0x130
+[<000000000007c494>] generic_writepages+0x258/0x3e0
+[<000000000007c692>] do_writepages+0x76/0x7c
+[<00000000000c7a26>] __writeback_single_inode+0xba/0x3e4
+[<00000000000c831a>] sync_sb_inodes+0x23e/0x398
+[<00000000000c8802>] writeback_inodes+0x12e/0x140
+[<000000000007b9ee>] wb_kupdate+0xd2/0x178
+[<000000000007cca2>] pdflush+0x162/0x23c
+
+The bad news now is that page_test_and_clear_dirty might claim
+that a not-uptodate page is dirty since SetPageUptodate which
+resets the per page dirty bit has not yet been called. The page
+writeback that follows clobbers the data on disk.
+
+The simplest solution to this problem is to move the call to
+page_test_and_clear_dirty under the "if (page_mapped(page))".
+If a file backed page is mapped it is uptodate.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ mm/rmap.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/mm/rmap.c
++++ b/mm/rmap.c
+@@ -490,9 +490,9 @@ int page_mkclean(struct page *page)
+ struct address_space *mapping = page_mapping(page);
+ if (mapping)
+ ret = page_mkclean_file(mapping, page);
++ if (page_test_and_clear_dirty(page))
++ ret = 1;
+ }
+- if (page_test_and_clear_dirty(page))
+- ret = 1;
+
+ return ret;
+ }
--- /dev/null
+From heiko.carstens@de.ibm.com Fri May 4 12:30:05 2007
+From: Heiko Carstens <heiko.carstens@de.ibm.com>
+Date: Fri, 04 May 2007 21:22:11 +0200
+Subject: s390: Fix TCP/UDP pseudo header checksum computation.
+To: stable@kernel.org, greg@kroah.com
+Cc: heiko.carstens@de.ibm.com, schwidefsky@de.ibm.com
+Message-ID: <20070504192839.425473994@de.ibm.com>
+Content-Disposition: inline; filename=02-network.diff
+
+
+From: Heiko Carstens <heiko.carstens@de.ibm.com>
+
+git commit f994aae1bd8e4813d59a2ed64d17585fe42d03fc changed the
+function declaration of csum_tcpudp_nofold. Argument types were
+changed from unsigned long to __be32 (unsigned int). Therefore we
+lost the implicit type conversion that zeroed the upper half of the
+registers that are used to pass parameters. Since the inline assembly
+relied on this we ended up adding random values and wrong checksums
+were created.
+Showed only up on machines with more than 4GB since gcc produced code
+where the registers that are used to pass 'saddr' and 'daddr' previously
+contained addresses before calling this function.
+Fix this by using 32 bit arithmetics and convert code to C, since gcc
+produces better code than these hand-optimized versions.
+
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/asm-s390/checksum.h | 59 +++++++++++---------------------------------
+ 1 file changed, 15 insertions(+), 44 deletions(-)
+
+--- a/include/asm-s390/checksum.h
++++ b/include/asm-s390/checksum.h
+@@ -121,50 +121,21 @@ csum_tcpudp_nofold(__be32 saddr, __be32
+ unsigned short len, unsigned short proto,
+ __wsum sum)
+ {
+-#ifndef __s390x__
+- asm volatile(
+- " alr %0,%1\n" /* sum += saddr */
+- " brc 12,0f\n"
+- " ahi %0,1\n" /* add carry */
+- "0:"
+- : "+&d" (sum) : "d" (saddr) : "cc");
+- asm volatile(
+- " alr %0,%1\n" /* sum += daddr */
+- " brc 12,1f\n"
+- " ahi %0,1\n" /* add carry */
+- "1:"
+- : "+&d" (sum) : "d" (daddr) : "cc");
+- asm volatile(
+- " alr %0,%1\n" /* sum += len + proto */
+- " brc 12,2f\n"
+- " ahi %0,1\n" /* add carry */
+- "2:"
+- : "+&d" (sum)
+- : "d" (len + proto)
+- : "cc");
+-#else /* __s390x__ */
+- asm volatile(
+- " lgfr %0,%0\n"
+- " algr %0,%1\n" /* sum += saddr */
+- " brc 12,0f\n"
+- " aghi %0,1\n" /* add carry */
+- "0: algr %0,%2\n" /* sum += daddr */
+- " brc 12,1f\n"
+- " aghi %0,1\n" /* add carry */
+- "1: algfr %0,%3\n" /* sum += len + proto */
+- " brc 12,2f\n"
+- " aghi %0,1\n" /* add carry */
+- "2: srlg 0,%0,32\n"
+- " alr %0,0\n" /* fold to 32 bits */
+- " brc 12,3f\n"
+- " ahi %0,1\n" /* add carry */
+- "3: llgfr %0,%0"
+- : "+&d" (sum)
+- : "d" (saddr), "d" (daddr),
+- "d" (len + proto)
+- : "cc", "0");
+-#endif /* __s390x__ */
+- return sum;
++ __u32 csum = (__force __u32)sum;
++
++ csum += (__force __u32)saddr;
++ if (csum < (__force __u32)saddr)
++ csum++;
++
++ csum += (__force __u32)daddr;
++ if (csum < (__force __u32)daddr)
++ csum++;
++
++ csum += len + proto;
++ if (csum < len + proto)
++ csum++;
++
++ return (__force __wsum)csum;
+ }
+
+ /*