]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
update 2.6.19 queue
authorChris Wright <chrisw@sous-sol.org>
Tue, 2 Jan 2007 20:40:43 +0000 (12:40 -0800)
committerChris Wright <chrisw@sous-sol.org>
Tue, 2 Jan 2007 20:40:43 +0000 (12:40 -0800)
22 files changed:
queue-2.6.19/bluetooth-add-packet-size-checks-for-capi-messages.patch [new file with mode: 0644]
queue-2.6.19/buglet-in-vmscan.c.patch [new file with mode: 0644]
queue-2.6.19/cciss-fix-xfer_read-xfer_write-in-do_cciss_request.patch [new file with mode: 0644]
queue-2.6.19/corrupted-cramfs-filesystems-cause-kernel-oops.patch [new file with mode: 0644]
queue-2.6.19/ext2-skip-pages-past-number-of-blocks-in-ext2_find_entry.patch [new file with mode: 0644]
queue-2.6.19/fix-aoe-without-scatter-gather.patch [new file with mode: 0644]
queue-2.6.19/fix-for-shmem_truncate_range-bug_on.patch [new file with mode: 0644]
queue-2.6.19/fix-reversed-logic-in-udp_get_port.patch [new file with mode: 0644]
queue-2.6.19/handle-ext3-directory-corruption-better.patch [new file with mode: 0644]
queue-2.6.19/i2c-fix-broken-ds1337-initialization.patch [new file with mode: 0644]
queue-2.6.19/i386-cpu-hotplug-broken-with-2gb-vmsplit.patch [new file with mode: 0644]
queue-2.6.19/net-don-t-export-linux-random.h-outside-__kernel__.patch [new file with mode: 0644]
queue-2.6.19/pktgen-fix-module-load-unload-races.patch [new file with mode: 0644]
queue-2.6.19/ramfs-breaks-without-config_block.patch [new file with mode: 0644]
queue-2.6.19/sched-fix-bad-missed-wakeups-in-the-i386-x86_64-ia64-acpi-and-apm-idle-code.patch [new file with mode: 0644]
queue-2.6.19/series
queue-2.6.19/smc911x-fix-netpoll-compilation-faliure.patch [new file with mode: 0644]
queue-2.6.19/softmac-fixed-handling-of-deassociation-from-ap.patch [new file with mode: 0644]
queue-2.6.19/sparc32-add-offset-in-pci_map_sg.patch [new file with mode: 0644]
queue-2.6.19/sparc64-fix-mem-xxx-handling.patch [new file with mode: 0644]
queue-2.6.19/sparc64-handle-isa-devices-with-no-regs-property.patch [new file with mode: 0644]
queue-2.6.19/zd1211rw-call-ieee80211_rx-in-tasklet.patch [new file with mode: 0644]

diff --git a/queue-2.6.19/bluetooth-add-packet-size-checks-for-capi-messages.patch b/queue-2.6.19/bluetooth-add-packet-size-checks-for-capi-messages.patch
new file mode 100644 (file)
index 0000000..bef4f67
--- /dev/null
@@ -0,0 +1,121 @@
+From vendor-sec-admin@lst.de  Mon Dec 11 06:28:38 2006
+Message-ID: <457D68B0.6060503@redhat.com>
+From: Marcel Holtmann <marcel@holtmann.org>
+CC: Al Viro <viro@zeniv.linux.org.uk>
+Subject: Bluetooth: Add packet size checks for CAPI messages (CVE-2006-6106)
+Date: Mon, 11 Dec 2006 15:18:24 +0100
+
+With malformed packets it might be possible to overwrite internal
+CMTP and CAPI data structures. This patch adds additional length
+checks to prevent these kinds of remote attacks.
+
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ net/bluetooth/cmtp/capi.c |   39 +++++++++++++++++++++++++++++++++------
+ 1 file changed, 33 insertions(+), 6 deletions(-)
+
+--- linux-2.6.19.1.orig/net/bluetooth/cmtp/capi.c
++++ linux-2.6.19.1/net/bluetooth/cmtp/capi.c
+@@ -196,6 +196,9 @@ static void cmtp_recv_interopmsg(struct 
+       switch (CAPIMSG_SUBCOMMAND(skb->data)) {
+       case CAPI_CONF:
++              if (skb->len < CAPI_MSG_BASELEN + 10)
++                      break;
++
+               func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
+               info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
+@@ -226,6 +229,9 @@ static void cmtp_recv_interopmsg(struct 
+                       break;
+               case CAPI_FUNCTION_GET_PROFILE:
++                      if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
++                              break;
++
+                       controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
+                       msgnum = CAPIMSG_MSGID(skb->data);
+@@ -246,17 +252,26 @@ static void cmtp_recv_interopmsg(struct 
+                       break;
+               case CAPI_FUNCTION_GET_MANUFACTURER:
++                      if (skb->len < CAPI_MSG_BASELEN + 15)
++                              break;
++
+                       controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
+                       if (!info && ctrl) {
++                              int len = min_t(uint, CAPI_MANUFACTURER_LEN,
++                                              skb->data[CAPI_MSG_BASELEN + 14]);
++
++                              memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
+                               strncpy(ctrl->manu,
+-                                      skb->data + CAPI_MSG_BASELEN + 15,
+-                                      skb->data[CAPI_MSG_BASELEN + 14]);
++                                      skb->data + CAPI_MSG_BASELEN + 15, len);
+                       }
+                       break;
+               case CAPI_FUNCTION_GET_VERSION:
++                      if (skb->len < CAPI_MSG_BASELEN + 32)
++                              break;
++
+                       controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
+                       if (!info && ctrl) {
+@@ -269,13 +284,18 @@ static void cmtp_recv_interopmsg(struct 
+                       break;
+               case CAPI_FUNCTION_GET_SERIAL_NUMBER:
++                      if (skb->len < CAPI_MSG_BASELEN + 17)
++                              break;
++
+                       controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
+                       if (!info && ctrl) {
++                              int len = min_t(uint, CAPI_SERIAL_LEN,
++                                              skb->data[CAPI_MSG_BASELEN + 16]);
++
+                               memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
+                               strncpy(ctrl->serial,
+-                                      skb->data + CAPI_MSG_BASELEN + 17,
+-                                      skb->data[CAPI_MSG_BASELEN + 16]);
++                                      skb->data + CAPI_MSG_BASELEN + 17, len);
+                       }
+                       break;
+@@ -284,14 +304,18 @@ static void cmtp_recv_interopmsg(struct 
+               break;
+       case CAPI_IND:
++              if (skb->len < CAPI_MSG_BASELEN + 6)
++                      break;
++
+               func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
+               if (func == CAPI_FUNCTION_LOOPBACK) {
++                      int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
++                                              skb->data[CAPI_MSG_BASELEN + 5]);
+                       appl = CAPIMSG_APPID(skb->data);
+                       msgnum = CAPIMSG_MSGID(skb->data);
+                       cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
+-                                              skb->data + CAPI_MSG_BASELEN + 6,
+-                                              skb->data[CAPI_MSG_BASELEN + 5]);
++                                              skb->data + CAPI_MSG_BASELEN + 6, len);
+               }
+               break;
+@@ -309,6 +333,9 @@ void cmtp_recv_capimsg(struct cmtp_sessi
+       BT_DBG("session %p skb %p len %d", session, skb, skb->len);
++      if (skb->len < CAPI_MSG_BASELEN)
++              return;
++
+       if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
+               cmtp_recv_interopmsg(session, skb);
+               return;
diff --git a/queue-2.6.19/buglet-in-vmscan.c.patch b/queue-2.6.19/buglet-in-vmscan.c.patch
new file mode 100644 (file)
index 0000000..6655540
--- /dev/null
@@ -0,0 +1,32 @@
+From stable-bounces@linux.kernel.org  Fri Dec 29 16:57:04 2006
+Message-Id: <200612300049.kBU0nJHN008167@shell0.pdx.osdl.net>
+To: torvalds@osdl.org
+From: akpm@osdl.org
+Date: Fri, 29 Dec 2006 16:48:59 -0800
+Cc: akpm@osdl.org, clameter@engr.sgi.com, stable@kernel.org, sgoel01@yahoo.com
+Subject: Buglet in vmscan.c
+
+From: Shantanu Goel <sgoel01@yahoo.com>
+
+Fix a rather obvious buglet.  Noticed while instrumenting the VM using
+/proc/vmstat.
+
+Cc: Christoph Lameter <clameter@engr.sgi.com>
+Cc: <stable@kernel.org>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ mm/vmscan.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-2.6.19.1.orig/mm/vmscan.c
++++ linux-2.6.19.1/mm/vmscan.c
+@@ -691,7 +691,7 @@ static unsigned long shrink_inactive_lis
+                       __count_vm_events(KSWAPD_STEAL, nr_freed);
+               } else
+                       __count_zone_vm_events(PGSCAN_DIRECT, zone, nr_scan);
+-              __count_vm_events(PGACTIVATE, nr_freed);
++              __count_zone_vm_events(PGSTEAL, zone, nr_freed);
+               if (nr_taken == 0)
+                       goto done;
diff --git a/queue-2.6.19/cciss-fix-xfer_read-xfer_write-in-do_cciss_request.patch b/queue-2.6.19/cciss-fix-xfer_read-xfer_write-in-do_cciss_request.patch
new file mode 100644 (file)
index 0000000..f4d44b0
--- /dev/null
@@ -0,0 +1,35 @@
+From stable-bounces@linux.kernel.org  Sat Dec 23 12:21:40 2006
+Date: Sat, 23 Dec 2006 15:11:58 -0500
+From: Chuck Ebbert <76306.1226@compuserve.com>
+To: linux-stable <stable@kernel.org>
+Message-ID: <200612231514_MC3-1-D628-9FB6@compuserve.com>
+Content-Disposition: inline
+Cc: Mike Miller <mike.miller@hp.com>
+Subject: cciss: fix XFER_READ/XFER_WRITE in do_cciss_request
+
+From: Mike Miller <mike.miller@hp.com>
+
+This patch fixes a stupid bug. Sometime during the 2tb enhancement I ended up
+replacing the macros XFER_READ and XFER_WRITE with h->cciss_read and
+h->cciss_write respectively. It seemed to work somehow at least on x86_64 and
+ia64. I don't know how. But people started complaining about command timeouts
+on older controllers like the 64xx series and only on ia32. This resolves the
+issue reproduced in our lab. Please consider this for inclusion. 
+
+Signed-off-by: Mike Miller <mike.miller@hp.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ drivers/block/cciss.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-2.6.19.1.orig/drivers/block/cciss.c
++++ linux-2.6.19.1/drivers/block/cciss.c
+@@ -2530,7 +2530,7 @@ static void do_cciss_request(request_que
+       c->Request.Type.Type = TYPE_CMD;        // It is a command.
+       c->Request.Type.Attribute = ATTR_SIMPLE;
+       c->Request.Type.Direction =
+-          (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
++          (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE;
+       c->Request.Timeout = 0; // Don't time out
+       c->Request.CDB[0] =
+           (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
diff --git a/queue-2.6.19/corrupted-cramfs-filesystems-cause-kernel-oops.patch b/queue-2.6.19/corrupted-cramfs-filesystems-cause-kernel-oops.patch
new file mode 100644 (file)
index 0000000..5fa5308
--- /dev/null
@@ -0,0 +1,47 @@
+From stable-bounces@linux.kernel.org  Sat Dec 30 15:33:45 2006
+Message-ID: <4596F606.2090504@gentoo.org>
+Date: Sat, 30 Dec 2006 18:28:06 -0500
+From: Daniel Drake <dsd@gentoo.org>
+To: stable@kernel.org
+Cc: phillip@lougher.org.uk
+Subject: corrupted cramfs filesystems cause kernel oops (CVE-2006-5823)
+
+From: Phillip Lougher <phillip@lougher.org.uk>
+
+Steve Grubb's fzfuzzer tool (http://people.redhat.com/sgrubb/files/
+fsfuzzer-0.6.tar.gz) generates corrupt Cramfs filesystems which cause
+Cramfs to kernel oops in cramfs_uncompress_block().  The cause of the oops
+is an unchecked corrupted block length field read by cramfs_readpage().
+
+This patch adds a sanity check to cramfs_readpage() which checks that the
+block length field is sensible.  The (PAGE_CACHE_SIZE << 1) size check is
+intentional, even though the uncompressed data is not going to be larger
+than PAGE_CACHE_SIZE, gzip sometimes generates compressed data larger than
+the original source data.  Mkcramfs checks that the compressed size is
+always less than or equal to PAGE_CACHE_SIZE << 1.  Of course Cramfs could
+use the original uncompressed data in this case, but it doesn't.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.org.uk>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+Date: Thu, 7 Dec 2006 04:37:20 +0000 (-0800)
+Subject: [PATCH] corrupted cramfs filesystems cause kernel oops
+X-Git-Tag: v2.6.20-rc1
+X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=8bb0269160df2a60764013994d0bc5165406cf4a
+
+ fs/cramfs/inode.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- linux-2.6.19.1.orig/fs/cramfs/inode.c
++++ linux-2.6.19.1/fs/cramfs/inode.c
+@@ -481,6 +481,8 @@ static int cramfs_readpage(struct file *
+               pgdata = kmap(page);
+               if (compr_len == 0)
+                       ; /* hole */
++              else if (compr_len > (PAGE_CACHE_SIZE << 1))
++                      printk(KERN_ERR "cramfs: bad compressed blocksize %u\n", compr_len);
+               else {
+                       mutex_lock(&read_mutex);
+                       bytes_filled = cramfs_uncompress_block(pgdata,
diff --git a/queue-2.6.19/ext2-skip-pages-past-number-of-blocks-in-ext2_find_entry.patch b/queue-2.6.19/ext2-skip-pages-past-number-of-blocks-in-ext2_find_entry.patch
new file mode 100644 (file)
index 0000000..8a1256a
--- /dev/null
@@ -0,0 +1,47 @@
+From stable-bounces@linux.kernel.org  Sat Dec 30 15:36:19 2006
+Message-ID: <4596F698.5070505@gentoo.org>
+Date: Sat, 30 Dec 2006 18:30:32 -0500
+From: Daniel Drake <dsd@gentoo.org>
+To: stable@kernel.org
+Cc: sandeen@redhat.com
+Subject: ext2: skip pages past number of blocks in ext2_find_entry (CVE-2006-6054)
+
+From: Eric Sandeen <sandeen@redhat.com>
+
+This one was pointed out on the MOKB site:
+http://kernelfun.blogspot.com/2006/11/mokb-09-11-2006-linux-26x-ext2checkpage.html
+
+If a directory's i_size is corrupted, ext2_find_entry() will keep processing
+pages until the i_size is reached, even if there are no more blocks associated
+with the directory inode.  This patch puts in some minimal sanity-checking
+so that we don't keep checking pages (and issuing errors) if we know there
+can be no more data to read, based on the block count of the directory inode.
+
+This is somewhat similar in approach to the ext3 patch I sent earlier this
+year.
+
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+Not upstream yet
+
+ fs/ext2/dir.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- linux-2.6.19.1.orig/fs/ext2/dir.c
++++ linux-2.6.19.1/fs/ext2/dir.c
+@@ -368,6 +368,14 @@ struct ext2_dir_entry_2 * ext2_find_entr
+               }
+               if (++n >= npages)
+                       n = 0;
++              /* next page is past the blocks we've got */
++              if (unlikely(n > (dir->i_blocks >> (PAGE_CACHE_SHIFT - 9)))) {
++                      ext2_error(dir->i_sb, __FUNCTION__,
++                              "dir %lu size %lld exceeds block count %llu",
++                              dir->i_ino, dir->i_size,
++                              (unsigned long long)dir->i_blocks);
++                              goto out;
++              }
+       } while (n != start);
+ out:
+       return NULL;
diff --git a/queue-2.6.19/fix-aoe-without-scatter-gather.patch b/queue-2.6.19/fix-aoe-without-scatter-gather.patch
new file mode 100644 (file)
index 0000000..dac2f66
--- /dev/null
@@ -0,0 +1,89 @@
+From stable-bounces@linux.kernel.org  Fri Dec 22 01:16:04 2006
+Message-Id: <200612220909.kBM99N3M018750@shell0.pdx.osdl.net>
+To: torvalds@osdl.org
+From: akpm@osdl.org
+Date: Fri, 22 Dec 2006 01:09:21 -0800
+Cc: akpm@osdl.org, greg@kroah.com, boddingt@optusnet.com.au, ecashin@coraid.com, stable@kernel.org
+Subject: fix aoe without scatter-gather [Bug 7662]
+
+From: "Ed L. Cashin" <ecashin@coraid.com>
+
+Fix a bug that only appears when AoE goes over a network card that does not
+support scatter-gather.  The headers in the linear part of the skb appeared
+to be larger than they really were, resulting in data that was offset by 24
+bytes.
+
+This patch eliminates the offset data on cards that don't support
+scatter-gather or have had scatter-gather turned off.  There remains an
+unrelated issue that I'll address in a separate email.
+
+Fixes bugzilla #7662
+
+Signed-off-by: "Ed L. Cashin" <ecashin@coraid.com>
+Cc: <stable@kernel.org>
+Cc: Greg KH <greg@kroah.com>
+Cc: <boddingt@optusnet.com.au>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ drivers/block/aoe/aoecmd.c |   13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+--- linux-2.6.19.1.orig/drivers/block/aoe/aoecmd.c
++++ linux-2.6.19.1/drivers/block/aoe/aoecmd.c
+@@ -30,8 +30,6 @@ new_skb(ulong len)
+               skb->nh.raw = skb->mac.raw = skb->data;
+               skb->protocol = __constant_htons(ETH_P_AOE);
+               skb->priority = 0;
+-              skb_put(skb, len);
+-              memset(skb->head, 0, len);
+               skb->next = skb->prev = NULL;
+               /* tell the network layer not to perform IP checksums
+@@ -122,8 +120,8 @@ aoecmd_ata_rw(struct aoedev *d, struct f
+       skb = f->skb;
+       h = (struct aoe_hdr *) skb->mac.raw;
+       ah = (struct aoe_atahdr *) (h+1);
+-      skb->len = sizeof *h + sizeof *ah;
+-      memset(h, 0, ETH_ZLEN);
++      skb_put(skb, sizeof *h + sizeof *ah);
++      memset(h, 0, skb->len);
+       f->tag = aoehdr_atainit(d, h);
+       f->waited = 0;
+       f->buf = buf;
+@@ -149,7 +147,6 @@ aoecmd_ata_rw(struct aoedev *d, struct f
+               skb->len += bcnt;
+               skb->data_len = bcnt;
+       } else {
+-              skb->len = ETH_ZLEN;
+               writebit = 0;
+       }
+@@ -206,6 +203,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigne
+                       printk(KERN_INFO "aoe: skb alloc failure\n");
+                       continue;
+               }
++              skb_put(skb, sizeof *h + sizeof *ch);
+               skb->dev = ifp;
+               if (sl_tail == NULL)
+                       sl_tail = skb;
+@@ -243,6 +241,7 @@ freeframe(struct aoedev *d)
+                       continue;
+               if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) {
+                       skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0;
++                      skb_trim(f->skb, 0);
+                       return f;
+               }
+               n++;
+@@ -698,8 +697,8 @@ aoecmd_ata_id(struct aoedev *d)
+       skb = f->skb;
+       h = (struct aoe_hdr *) skb->mac.raw;
+       ah = (struct aoe_atahdr *) (h+1);
+-      skb->len = ETH_ZLEN;
+-      memset(h, 0, ETH_ZLEN);
++      skb_put(skb, sizeof *h + sizeof *ah);
++      memset(h, 0, skb->len);
+       f->tag = aoehdr_atainit(d, h);
+       f->waited = 0;
diff --git a/queue-2.6.19/fix-for-shmem_truncate_range-bug_on.patch b/queue-2.6.19/fix-for-shmem_truncate_range-bug_on.patch
new file mode 100644 (file)
index 0000000..7523050
--- /dev/null
@@ -0,0 +1,42 @@
+From stable-bounces@linux.kernel.org  Fri Dec 22 01:13:06 2006
+Message-Id: <200612220906.kBM96PM4018647@shell0.pdx.osdl.net>
+To: torvalds@osdl.org
+From: akpm@osdl.org
+Date: Fri, 22 Dec 2006 01:06:23 -0800
+Cc: akpm@osdl.org, hugh@veritas.com, pbadari@us.ibm.com, stable@kernel.org
+Subject: Fix for shmem_truncate_range() BUG_ON()
+
+From: Badari Pulavarty <pbadari@us.ibm.com>
+
+Ran into BUG() while doing madvise(REMOVE) testing.  If we are punching a
+hole into shared memory segment using madvise(REMOVE) and the entire hole
+is below the indirect blocks, we hit following assert.
+
+               BUG_ON(limit <= SHMEM_NR_DIRECT);
+
+Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
+Cc: Hugh Dickins <hugh@veritas.com>
+Cc: <stable@kernel.org>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ mm/shmem.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- linux-2.6.19.1.orig/mm/shmem.c
++++ linux-2.6.19.1/mm/shmem.c
+@@ -515,7 +515,12 @@ static void shmem_truncate_range(struct 
+                       size = SHMEM_NR_DIRECT;
+               nr_swaps_freed = shmem_free_swp(ptr+idx, ptr+size);
+       }
+-      if (!topdir)
++
++      /*
++       * If there are no indirect blocks or we are punching a hole
++       * below indirect blocks, nothing to be done.
++       */
++      if (!topdir || (punch_hole && (limit <= SHMEM_NR_DIRECT)))
+               goto done2;
+       BUG_ON(limit <= SHMEM_NR_DIRECT);
diff --git a/queue-2.6.19/fix-reversed-logic-in-udp_get_port.patch b/queue-2.6.19/fix-reversed-logic-in-udp_get_port.patch
new file mode 100644 (file)
index 0000000..413cdd3
--- /dev/null
@@ -0,0 +1,60 @@
+From stable-bounces@linux.kernel.org  Fri Dec 22 12:02:42 2006
+Date: Fri, 22 Dec 2006 11:56:21 -0800 (PST)
+Message-Id: <20061222.115621.104034701.davem@davemloft.net>
+To: stable@kernel.org
+From: David Miller <davem@davemloft.net>
+Subject: [UDP]: Fix reversed logic in udp_get_port()
+
+When this code was converted to use sk_for_each() the
+logic for the "best hash chain length" code was reversed,
+breaking everything.
+
+The original code was of the form:
+
+                       size = 0;
+                       do {
+                               if (++size >= best_size_so_far)
+                                       goto next;
+                       } while ((sk = sk->next) != NULL);
+                       best_size_so_far = size;
+                       best = result;
+               next:;
+
+and this got converted into:
+
+                       sk_for_each(sk2, node, head)
+                               if (++size < best_size_so_far) {
+                                       best_size_so_far = size;
+                                       best = result;
+                               }
+
+Which does something very very different from the original.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ net/ipv4/udp.c |   13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- linux-2.6.19.1.orig/net/ipv4/udp.c
++++ linux-2.6.19.1/net/ipv4/udp.c
+@@ -167,11 +167,14 @@ int udp_get_port(struct sock *sk, unsign
+                               goto gotit;
+                       }
+                       size = 0;
+-                      sk_for_each(sk2, node, head)
+-                              if (++size < best_size_so_far) {
+-                                      best_size_so_far = size;
+-                                      best = result;
+-                              }
++                      sk_for_each(sk2, node, head) {
++                              if (++size >= best_size_so_far)
++                                      goto next;
++                      }
++                      best_size_so_far = size;
++                      best = result;
++              next:
++                      ;
+               }
+               result = best;
+               for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) {
diff --git a/queue-2.6.19/handle-ext3-directory-corruption-better.patch b/queue-2.6.19/handle-ext3-directory-corruption-better.patch
new file mode 100644 (file)
index 0000000..aaacd74
--- /dev/null
@@ -0,0 +1,89 @@
+From stable-bounces@linux.kernel.org  Sat Dec 30 15:27:45 2006
+Message-ID: <4596F49F.4080406@gentoo.org>
+Date: Sat, 30 Dec 2006 18:22:07 -0500
+From: Daniel Drake <dsd@gentoo.org>
+To: stable@kernel.org
+Cc: sandeen@redhat.com
+Subject: handle ext3 directory corruption better (CVE-2006-6053)
+
+From: Eric Sandeen <sandeen@redhat.com>
+
+I've been using Steve Grubb's purely evil "fsfuzzer" tool, at
+http://people.redhat.com/sgrubb/files/fsfuzzer-0.4.tar.gz
+
+Basically it makes a filesystem, splats some random bits over it, then
+tries to mount it and do some simple filesystem actions.
+
+At best, the filesystem catches the corruption gracefully.  At worst,
+things spin out of control.
+
+As you might guess, we found a couple places in ext3 where things spin out
+of control :)
+
+First, we had a corrupted directory that was never checked for
+consistency...  it was corrupt, and pointed to another bad "entry" of
+length 0.  The for() loop looped forever, since the length of
+ext3_next_entry(de) was 0, and we kept looking at the same pointer over and
+over and over and over...  I modeled this check and subsequent action on
+what is done for other directory types in ext3_readdir...
+
+(adding this check adds some computational expense; I am testing a followup
+patch to reduce the number of times we check and re-check these directory
+entries, in all cases.  Thanks for the idea, Andreas).
+
+Next we had a root directory inode which had a corrupted size, claimed to
+be > 200M on a 4M filesystem.  There was only really 1 block in the
+directory, but because the size was so large, readdir kept coming back for
+more, spewing thousands of printk's along the way.
+
+Per Andreas' suggestion, if we're in this read error condition and we're
+trying to read an offset which is greater than i_blocks worth of bytes,
+stop trying, and break out of the loop.
+
+With these two changes fsfuzz test survives quite well on ext3.
+
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Cc: <linux-ext4@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+Date: Thu, 7 Dec 2006 04:36:26 +0000 (-0800)
+Subject: [PATCH] handle ext3 directory corruption better
+X-Git-Tag: v2.6.20-rc1
+X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=40b851348fe9bf49c26025b34261d25142269b60
+
+ fs/ext3/dir.c   |    3 +++
+ fs/ext3/namei.c |    9 +++++++++
+ 2 files changed, 12 insertions(+)
+
+--- linux-2.6.19.1.orig/fs/ext3/dir.c
++++ linux-2.6.19.1/fs/ext3/dir.c
+@@ -154,6 +154,9 @@ static int ext3_readdir(struct file * fi
+                       ext3_error (sb, "ext3_readdir",
+                               "directory #%lu contains a hole at offset %lu",
+                               inode->i_ino, (unsigned long)filp->f_pos);
++                      /* corrupt size?  Maybe no more blocks to read */
++                      if (filp->f_pos > inode->i_blocks << 9)
++                              break;
+                       filp->f_pos += sb->s_blocksize - offset;
+                       continue;
+               }
+--- linux-2.6.19.1.orig/fs/ext3/namei.c
++++ linux-2.6.19.1/fs/ext3/namei.c
+@@ -552,6 +552,15 @@ static int htree_dirblock_to_tree(struct
+                                          dir->i_sb->s_blocksize -
+                                          EXT3_DIR_REC_LEN(0));
+       for (; de < top; de = ext3_next_entry(de)) {
++              if (!ext3_check_dir_entry("htree_dirblock_to_tree", dir, de, bh,
++                                      (block<<EXT3_BLOCK_SIZE_BITS(dir->i_sb))
++                                              +((char *)de - bh->b_data))) {
++                      /* On error, skip the f_pos to the next block. */
++                      dir_file->f_pos = (dir_file->f_pos |
++                                      (dir->i_sb->s_blocksize - 1)) + 1;
++                      brelse (bh);
++                      return count;
++              }
+               ext3fs_dirhash(de->name, de->name_len, hinfo);
+               if ((hinfo->hash < start_hash) ||
+                   ((hinfo->hash == start_hash) &&
diff --git a/queue-2.6.19/i2c-fix-broken-ds1337-initialization.patch b/queue-2.6.19/i2c-fix-broken-ds1337-initialization.patch
new file mode 100644 (file)
index 0000000..60f6a22
--- /dev/null
@@ -0,0 +1,60 @@
+From stable-bounces@linux.kernel.org  Tue Dec 19 23:40:57 2006
+Date: Wed, 20 Dec 2006 08:34:43 +0100
+From: Jean Delvare <khali@linux-fr.org>
+To: stable@kernel.org
+Message-Id: <20061220083443.45e488cb.khali@linux-fr.org>
+Cc: Dirk Eibach <eibach@gdsys.de>, Adrian Bunk <bunk@stusta.de>
+Subject: i2c: fix broken ds1337 initialization
+
+From: Dirk Eibach <eibach@gdsys.de>
+
+On a custom board with ds1337 RTC I found that upgrade from 2.6.15 to
+2.6.18 broke RTC support.
+
+The main problem are changes to ds1337_init_client().
+When a ds1337 recognizes a problem (e.g. power or clock failure) bit 7
+in status register is set. This has to be reset by writing 0 to status
+register. But since there are only 16 byte written to the chip and the
+first byte is interpreted as an address, the status register (which is
+the 16th) is never written.
+The other problem is, that initializing all registers to zero is not
+valid for day, date and month register. Funny enough this is checked by
+ds1337_detect(), which depends on this values not being zero. So then
+treated by ds1337_init_client() the ds1337 is not detected anymore,
+whereas the failure bit in the status register is still set.
+
+Broken by commit f9e8957937ebf60d22732a5ca9130f48a7603f60 (2.6.16-rc1,
+2006-01-06). This fix is in Linus' tree since 2.6.20-rc1 (commit
+763d9c046a2e511ec090a8986d3f85edf7448e7e).
+
+Signed-off-by: Dirk Stieler <stieler@gdsys.de>
+Signed-off-by: Dirk Eibach <eibach@gdsys.de>
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ drivers/i2c/chips/ds1337.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- linux-2.6.19.1.orig/drivers/i2c/chips/ds1337.c
++++ linux-2.6.19.1/drivers/i2c/chips/ds1337.c
+@@ -347,13 +347,19 @@ static void ds1337_init_client(struct i2
+       if ((status & 0x80) || (control & 0x80)) {
+               /* RTC not running */
+-              u8 buf[16];
++              u8 buf[1+16];   /* First byte is interpreted as address */
+               struct i2c_msg msg[1];
+               dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
+               /* Initialize all, including STATUS and CONTROL to zero */
+               memset(buf, 0, sizeof(buf));
++
++              /* Write valid values in the date/time registers */
++              buf[1+DS1337_REG_DAY] = 1;
++              buf[1+DS1337_REG_DATE] = 1;
++              buf[1+DS1337_REG_MONTH] = 1;
++
+               msg[0].addr = client->addr;
+               msg[0].flags = 0;
+               msg[0].len = sizeof(buf);
diff --git a/queue-2.6.19/i386-cpu-hotplug-broken-with-2gb-vmsplit.patch b/queue-2.6.19/i386-cpu-hotplug-broken-with-2gb-vmsplit.patch
new file mode 100644 (file)
index 0000000..6f247fb
--- /dev/null
@@ -0,0 +1,30 @@
+From stable-bounces@linux.kernel.org  Sat Dec 23 18:48:39 2006
+Date: Sat, 23 Dec 2006 21:39:08 -0500
+From: Chuck Ebbert <76306.1226@compuserve.com>
+To: linux-stable <stable@kernel.org>
+Message-ID: <200612232141_MC3-1-D628-F7DD@compuserve.com>
+Content-Disposition: inline
+Cc: Shaohua Li <shaohua.li@intel.com>
+Subject: [stable] [stable patch] i386: CPU hotplug broken with 2GB VMSPLIT
+
+From: Shaohua Li <shaohua.li@intel.com>
+
+In VMSPLIT mode, kernel PGD might have more entries than user space
+
+Signed-off-by: Shaohua Li <shaohua.li@intel.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ arch/i386/kernel/smpboot.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-2.6.19.1.orig/arch/i386/kernel/smpboot.c
++++ linux-2.6.19.1/arch/i386/kernel/smpboot.c
+@@ -1095,7 +1095,7 @@ static int __cpuinit __smp_prepare_cpu(i
+       /* init low mem mapping */
+       clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+-                      KERNEL_PGD_PTRS);
++                      min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS));
+       flush_tlb_all();
+       schedule_work(&task);
+       wait_for_completion(&done);
diff --git a/queue-2.6.19/net-don-t-export-linux-random.h-outside-__kernel__.patch b/queue-2.6.19/net-don-t-export-linux-random.h-outside-__kernel__.patch
new file mode 100644 (file)
index 0000000..4265b86
--- /dev/null
@@ -0,0 +1,39 @@
+From stable-bounces@linux.kernel.org  Tue Jan  2 00:14:53 2007
+Date: Tue, 02 Jan 2007 00:07:50 -0800 (PST)
+Message-Id: <20070102.000750.115910105.davem@davemloft.net>
+To: stable@kernel.org
+From: David Miller <davem@davemloft.net>
+Subject: NET: Don't export linux/random.h outside __KERNEL__
+
+From: David Woodhouse <dwmw2@infradead.org>
+
+Don't add it there please; add it lower down inside the existing #ifdef
+__KERNEL__. You just made the _userspace_ net.h include random.h, which
+then fails to compile unless <asm/types.h> was already included.
+
+Signed-off-by: David Woodhouse <dwmw2@infradead.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+
+---
+ include/linux/net.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-2.6.19.1.orig/include/linux/net.h
++++ linux-2.6.19.1/include/linux/net.h
+@@ -19,7 +19,6 @@
+ #define _LINUX_NET_H
+ #include <linux/wait.h>
+-#include <linux/random.h>
+ #include <asm/socket.h>
+ struct poll_table_struct;
+@@ -57,6 +56,7 @@ typedef enum {
+ #ifdef __KERNEL__
+ #include <linux/stringify.h>
++#include <linux/random.h>
+ #define SOCK_ASYNC_NOSPACE    0
+ #define SOCK_ASYNC_WAITDATA   1
diff --git a/queue-2.6.19/pktgen-fix-module-load-unload-races.patch b/queue-2.6.19/pktgen-fix-module-load-unload-races.patch
new file mode 100644 (file)
index 0000000..87003c8
--- /dev/null
@@ -0,0 +1,91 @@
+From stable-bounces@linux.kernel.org  Mon Jan  1 21:11:24 2007
+Date: Mon, 01 Jan 2007 21:04:19 -0800 (PST)
+Message-Id: <20070101.210419.104643422.davem@davemloft.net>
+To: stable@kernel.org
+From: David Miller <davem@davemloft.net>
+Cc: bunk@stusta.de
+Subject: PKTGEN: Fix module load/unload races.
+
+From: Robert Olsson <Robert.Olsson@data.slu.se>
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+
+---
+ net/core/pktgen.c |   20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+--- linux-2.6.19.1.orig/net/core/pktgen.c
++++ linux-2.6.19.1/net/core/pktgen.c
+@@ -147,6 +147,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
+ #include <linux/wait.h>
++#include <linux/completion.h>
+ #include <linux/etherdevice.h>
+ #include <net/checksum.h>
+ #include <net/ipv6.h>
+@@ -206,6 +207,11 @@ static struct proc_dir_entry *pg_proc_di
+ #define VLAN_TAG_SIZE(x) ((x)->vlan_id == 0xffff ? 0 : 4)
+ #define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4)
++struct pktgen_thread_info {
++       struct pktgen_thread *t;
++       struct completion *c;
++};
++
+ struct flow_state {
+       __u32 cur_daddr;
+       int count;
+@@ -3264,10 +3270,11 @@ out:;
+  * Main loop of the thread goes here
+  */
+-static void pktgen_thread_worker(struct pktgen_thread *t)
++static void pktgen_thread_worker(struct pktgen_thread_info *info)
+ {
+       DEFINE_WAIT(wait);
+       struct pktgen_dev *pkt_dev = NULL;
++      struct pktgen_thread *t = info->t;
+       int cpu = t->cpu;
+       sigset_t tmpsig;
+       u32 max_before_softirq;
+@@ -3307,6 +3314,8 @@ static void pktgen_thread_worker(struct 
+       __set_current_state(TASK_INTERRUPTIBLE);
+       mb();
++        complete(info->c);
++
+       while (1) {
+               __set_current_state(TASK_RUNNING);
+@@ -3518,6 +3527,8 @@ static struct pktgen_thread *__init pktg
+ static int __init pktgen_create_thread(const char *name, int cpu)
+ {
+       int err;
++      struct pktgen_thread_info info;
++        struct completion started;
+       struct pktgen_thread *t = NULL;
+       struct proc_dir_entry *pe;
+@@ -3558,7 +3569,11 @@ static int __init pktgen_create_thread(c
+       t->removed = 0;
+-      err = kernel_thread((void *)pktgen_thread_worker, (void *)t,
++      init_completion(&started);
++        info.t = t;
++        info.c = &started;
++
++      err = kernel_thread((void *)pktgen_thread_worker, (void *)&info,
+                         CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+       if (err < 0) {
+               printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
+@@ -3568,6 +3583,7 @@ static int __init pktgen_create_thread(c
+               return err;
+       }
++      wait_for_completion(&started);
+       return 0;
+ }
diff --git a/queue-2.6.19/ramfs-breaks-without-config_block.patch b/queue-2.6.19/ramfs-breaks-without-config_block.patch
new file mode 100644 (file)
index 0000000..712f98c
--- /dev/null
@@ -0,0 +1,60 @@
+From stable-bounces@linux.kernel.org  Fri Dec 29 16:55:45 2006
+Message-Id: <200612300048.kBU0mhs0008126@shell0.pdx.osdl.net>
+To: torvalds@osdl.org
+From: akpm@osdl.org
+Date: Fri, 29 Dec 2006 16:48:24 -0800
+Cc: akpm@osdl.org, dimitri.gorokhovik@free.fr, stable@kernel.org
+Subject: ramfs breaks without CONFIG_BLOCK
+
+From: Dimitri Gorokhovik <dimitri.gorokhovik@free.fr>
+
+ramfs doesn't provide the .set_dirty_page a_op, and when the BLOCK layer is
+not configured in, 'set_page_dirty' makes a call via a NULL pointer.
+
+Signed-off-by: Dimitri Gorokhovik <dimitri.gorokhovik@free.fr>
+Cc: <stable@kernel.org>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ fs/ramfs/file-mmu.c   |    4 +++-
+ fs/ramfs/file-nommu.c |    4 +++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- linux-2.6.19.1.orig/fs/ramfs/file-mmu.c
++++ linux-2.6.19.1/fs/ramfs/file-mmu.c
+@@ -25,11 +25,13 @@
+  */
+ #include <linux/fs.h>
++#include <linux/mm.h>
+ const struct address_space_operations ramfs_aops = {
+       .readpage       = simple_readpage,
+       .prepare_write  = simple_prepare_write,
+-      .commit_write   = simple_commit_write
++      .commit_write   = simple_commit_write,
++      .set_page_dirty = __set_page_dirty_nobuffers,
+ };
+ const struct file_operations ramfs_file_operations = {
+--- linux-2.6.19.1.orig/fs/ramfs/file-nommu.c
++++ linux-2.6.19.1/fs/ramfs/file-nommu.c
+@@ -11,6 +11,7 @@
+ #include <linux/module.h>
+ #include <linux/fs.h>
++#include <linux/mm.h>
+ #include <linux/pagemap.h>
+ #include <linux/highmem.h>
+ #include <linux/init.h>
+@@ -30,7 +31,8 @@ static int ramfs_nommu_setattr(struct de
+ const struct address_space_operations ramfs_aops = {
+       .readpage               = simple_readpage,
+       .prepare_write          = simple_prepare_write,
+-      .commit_write           = simple_commit_write
++      .commit_write           = simple_commit_write,
++      .set_page_dirty = __set_page_dirty_nobuffers,
+ };
+ const struct file_operations ramfs_file_operations = {
diff --git a/queue-2.6.19/sched-fix-bad-missed-wakeups-in-the-i386-x86_64-ia64-acpi-and-apm-idle-code.patch b/queue-2.6.19/sched-fix-bad-missed-wakeups-in-the-i386-x86_64-ia64-acpi-and-apm-idle-code.patch
new file mode 100644 (file)
index 0000000..8198511
--- /dev/null
@@ -0,0 +1,224 @@
+From mingo@elte.hu  Thu Dec 21 04:29:43 2006
+Date: Thu, 21 Dec 2006 13:20:30 +0100
+From: Ingo Molnar <mingo@elte.hu>
+To: Greg KH <gregkh@suse.de>, Chris Wright <chrisw@kernel.org>, Adrian Bunk <bunk@stusta.de>, stable@kernel.org
+Subject: sched: fix bad missed wakeups in the i386, x86_64, ia64, ACPI and APM idle code
+Message-ID: <20061221122030.GA10727@elte.hu>
+
+From: Ingo Molnar <mingo@elte.hu>
+
+Fernando Lopez-Lezcano reported frequent scheduling latencies and audio 
+xruns starting at the 2.6.18-rt kernel, and those problems persisted all 
+until current -rt kernels. The latencies were serious and unjustified by 
+system load, often in the milliseconds range.
+
+After a patient and heroic multi-month effort of Fernando, where he 
+tested dozens of kernels, tried various configs, boot options, 
+test-patches of mine and provided latency traces of those incidents, the 
+following 'smoking gun' trace was captured by him:
+
+                 _------=> CPU#
+                / _-----=> irqs-off
+               | / _----=> need-resched
+               || / _---=> hardirq/softirq
+               ||| / _--=> preempt-depth
+               |||| /
+               |||||     delay
+   cmd     pid ||||| time  |   caller
+      \   /    |||||   \   |   /
+  IRQ_19-1479  1D..1    0us : __trace_start_sched_wakeup (try_to_wake_up)
+  IRQ_19-1479  1D..1    0us : __trace_start_sched_wakeup <<...>-5856> (37 0)
+  IRQ_19-1479  1D..1    0us : __trace_start_sched_wakeup (c01262ba 0 0)
+  IRQ_19-1479  1D..1    0us : resched_task (try_to_wake_up)
+  IRQ_19-1479  1D..1    0us : __spin_unlock_irqrestore (try_to_wake_up)
+  ...
+  <idle>-0     1...1   11us!: default_idle (cpu_idle)
+  ...
+  <idle>-0     0Dn.1  602us : smp_apic_timer_interrupt (c0103baf 1 0)
+  ...
+   <...>-5856  0D..2  618us : __switch_to (__schedule)
+   <...>-5856  0D..2  618us : __schedule <<idle>-0> (20 162)
+   <...>-5856  0D..2  619us : __spin_unlock_irq (__schedule)
+   <...>-5856  0...1  619us : trace_stop_sched_switched (__schedule)
+   <...>-5856  0D..1  619us : trace_stop_sched_switched <<...>-5856> (37 0)
+
+what is visible in this trace is that CPU#1 ran try_to_wake_up() for 
+PID:5856, it placed PID:5856 on CPU#0's runqueue and ran resched_task() 
+for CPU#0. But it decided to not send an IPI that no CPU - due to 
+TS_POLLING. But CPU#0 never woke up after its NEED_RESCHED bit was set, 
+and only rescheduled to PID:5856 upon the next lapic timer IRQ. The 
+result was a 600+ usecs latency and a missed wakeup!
+
+the bug turned out to be an idle-wakeup bug introduced into the mainline 
+kernel this summer via an optimization in the x86_64 tree:
+
+    commit 495ab9c045e1b0e5c82951b762257fe1c9d81564
+    Author: Andi Kleen <ak@suse.de>
+    Date:   Mon Jun 26 13:59:11 2006 +0200
+
+    [PATCH] i386/x86-64/ia64: Move polling flag into thread_info_status
+
+    During some profiling I noticed that default_idle causes a lot of
+    memory traffic. I think that is caused by the atomic operations
+    to clear/set the polling flag in thread_info. There is actually
+    no reason to make this atomic - only the idle thread does it
+    to itself, other CPUs only read it. So I moved it into ti->status.
+
+the problem is this type of change:
+
+        if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
+-               clear_thread_flag(TIF_POLLING_NRFLAG);
++               current_thread_info()->status &= ~TS_POLLING;
+                smp_mb__after_clear_bit();
+                while (!need_resched()) {
+                        local_irq_disable();
+
+this changes clear_thread_flag() to an explicit clearing of TS_POLLING. 
+clear_thread_flag() is defined as:
+
+        clear_bit(flag, &ti->flags);
+
+and clear_bit() is a LOCK-ed atomic instruction on all x86 platforms:
+
+  static inline void clear_bit(int nr, volatile unsigned long * addr)
+  {
+          __asm__ __volatile__( LOCK_PREFIX
+                  "btrl %1,%0"
+
+hence smp_mb__after_clear_bit() is defined as a simple compile barrier:
+
+  #define smp_mb__after_clear_bit()       barrier()
+
+but the explicit TS_POLLING clearing introduced by the patch:
+
++               current_thread_info()->status &= ~TS_POLLING;
+
+is not an atomic op! So the clearing of the TS_POLLING bit is freely 
+reorderable with the reading of the NEED_RESCHED bit - and both now 
+reside in different memory addresses.
+
+CPU idle wakeup very much depends on ordered memory ops, the clearing of 
+the TS_POLLING flag must always be done before we test need_resched() 
+and hit the idle instruction(s). [Symmetrically, the wakeup code needs 
+to set NEED_RESCHED before it tests the TS_POLLING flag, so memory 
+ordering is paramount.]
+
+Fernando's dual-core Athlon64 system has a sufficiently advanced memory 
+ordering model so that it triggered this scenario very often.
+
+( And it also turned out that the reason why these latencies never
+  triggered on my testsystems is that i routinely use idle=poll, which
+  was the only idle variant not affected by this bug. )
+
+The fix is to change the smp_mb__after_clear_bit() to an smp_mb(), to 
+act as an absolute barrier between the TS_POLLING write and the 
+NEED_RESCHED read. This affects almost all idling methods (default, 
+ACPI, APM), on all 3 x86 architectures: i386, x86_64, ia64.
+
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Tested-by: Fernando Lopez-Lezcano <nando@ccrma.Stanford.EDU>
+[chrisw: backport to 2.6.19.1]
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ arch/i386/kernel/apm.c        |    6 +++++-
+ arch/i386/kernel/process.c    |    7 ++++++-
+ arch/ia64/kernel/process.c    |   10 ++++++++--
+ arch/x86_64/kernel/process.c  |    6 +++++-
+ drivers/acpi/processor_idle.c |   12 ++++++++++--
+ 5 files changed, 34 insertions(+), 7 deletions(-)
+
+--- linux-2.6.19.1.orig/arch/i386/kernel/apm.c
++++ linux-2.6.19.1/arch/i386/kernel/apm.c
+@@ -784,7 +784,11 @@ static int apm_do_idle(void)
+       polling = !!(current_thread_info()->status & TS_POLLING);
+       if (polling) {
+               current_thread_info()->status &= ~TS_POLLING;
+-              smp_mb__after_clear_bit();
++              /*
++               * TS_POLLING-cleared state must be visible before we
++               * test NEED_RESCHED:
++               */
++              smp_mb();
+       }
+       if (!need_resched()) {
+               idled = 1;
+--- linux-2.6.19.1.orig/arch/i386/kernel/process.c
++++ linux-2.6.19.1/arch/i386/kernel/process.c
+@@ -103,7 +103,12 @@ void default_idle(void)
+       if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
+               current_thread_info()->status &= ~TS_POLLING;
+-              smp_mb__after_clear_bit();
++              /*
++               * TS_POLLING-cleared state must be visible before we
++               * test NEED_RESCHED:
++               */
++              smp_mb();
++
+               while (!need_resched()) {
+                       local_irq_disable();
+                       if (!need_resched())
+--- linux-2.6.19.1.orig/arch/ia64/kernel/process.c
++++ linux-2.6.19.1/arch/ia64/kernel/process.c
+@@ -268,10 +268,16 @@ cpu_idle (void)
+       /* endless idle loop with no priority at all */
+       while (1) {
+-              if (can_do_pal_halt)
++              if (can_do_pal_halt) {
+                       current_thread_info()->status &= ~TS_POLLING;
+-              else
++                      /*
++                       * TS_POLLING-cleared state must be visible before we
++                       * test NEED_RESCHED:
++                       */
++                      smp_mb();
++              } else {
+                       current_thread_info()->status |= TS_POLLING;
++              }
+               if (!need_resched()) {
+                       void (*idle)(void);
+--- linux-2.6.19.1.orig/arch/x86_64/kernel/process.c
++++ linux-2.6.19.1/arch/x86_64/kernel/process.c
+@@ -111,7 +111,11 @@ static void default_idle(void)
+       local_irq_enable();
+       current_thread_info()->status &= ~TS_POLLING;
+-      smp_mb__after_clear_bit();
++      /*
++       * TS_POLLING-cleared state must be visible before we
++       * test NEED_RESCHED:
++       */
++      smp_mb();
+       while (!need_resched()) {
+               local_irq_disable();
+               if (!need_resched())
+--- linux-2.6.19.1.orig/drivers/acpi/processor_idle.c
++++ linux-2.6.19.1/drivers/acpi/processor_idle.c
+@@ -211,7 +211,11 @@ acpi_processor_power_activate(struct acp
+ static void acpi_safe_halt(void)
+ {
+       current_thread_info()->status &= ~TS_POLLING;
+-      smp_mb__after_clear_bit();
++      /*
++       * TS_POLLING-cleared state must be visible before we
++       * test NEED_RESCHED:
++       */
++      smp_mb();
+       if (!need_resched())
+               safe_halt();
+       current_thread_info()->status |= TS_POLLING;
+@@ -345,7 +349,11 @@ static void acpi_processor_idle(void)
+        */
+       if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) {
+               current_thread_info()->status &= ~TS_POLLING;
+-              smp_mb__after_clear_bit();
++              /*
++               * TS_POLLING-cleared state must be visible before we
++               * test NEED_RESCHED:
++               */
++              smp_mb();
+               if (need_resched()) {
+                       current_thread_info()->status |= TS_POLLING;
+                       local_irq_enable();
index cf6a8b16ca384861cf12d092ccf8beccc0ad6cbe..10f968589793642e46d2049bcc35c9608ed42ac5 100644 (file)
@@ -14,3 +14,24 @@ arm-add-sys_-at-syscalls.patch
 sched-remove-__cpuinitdata-anotation-to-cpu_isolated_map.patch
 ib-srp-fix-fmr-mapping-for-32-bit-kernels-and-addresses-above-4g.patch
 scsi-add-missing-cdb-clearing-in-scsi_execute.patch
+bluetooth-add-packet-size-checks-for-capi-messages.patch
+i2c-fix-broken-ds1337-initialization.patch
+sched-fix-bad-missed-wakeups-in-the-i386-x86_64-ia64-acpi-and-apm-idle-code.patch
+fix-for-shmem_truncate_range-bug_on.patch
+smc911x-fix-netpoll-compilation-faliure.patch
+fix-aoe-without-scatter-gather.patch
+fix-reversed-logic-in-udp_get_port.patch
+cciss-fix-xfer_read-xfer_write-in-do_cciss_request.patch
+i386-cpu-hotplug-broken-with-2gb-vmsplit.patch
+ramfs-breaks-without-config_block.patch
+buglet-in-vmscan.c.patch
+softmac-fixed-handling-of-deassociation-from-ap.patch
+zd1211rw-call-ieee80211_rx-in-tasklet.patch
+handle-ext3-directory-corruption-better.patch
+corrupted-cramfs-filesystems-cause-kernel-oops.patch
+ext2-skip-pages-past-number-of-blocks-in-ext2_find_entry.patch
+pktgen-fix-module-load-unload-races.patch
+sparc64-fix-mem-xxx-handling.patch
+sparc64-handle-isa-devices-with-no-regs-property.patch
+net-don-t-export-linux-random.h-outside-__kernel__.patch
+sparc32-add-offset-in-pci_map_sg.patch
diff --git a/queue-2.6.19/smc911x-fix-netpoll-compilation-faliure.patch b/queue-2.6.19/smc911x-fix-netpoll-compilation-faliure.patch
new file mode 100644 (file)
index 0000000..38beab8
--- /dev/null
@@ -0,0 +1,33 @@
+From stable-bounces@linux.kernel.org  Fri Dec 22 01:15:30 2006
+Message-Id: <200612220908.kBM98PCx018719@shell0.pdx.osdl.net>
+To: torvalds@osdl.org
+From: akpm@osdl.org
+Date: Fri, 22 Dec 2006 01:08:24 -0800
+Cc: akpm@osdl.org, stable@kernel.org, jeff@garzik.org, vitalywool@gmail.com
+Subject: smc911x: fix netpoll compilation faliure
+
+From: Vitaly Wool <vitalywool@gmail.com>
+
+Fix the compilation failure for smc911x.c when NET_POLL_CONTROLLER is set.
+
+Signed-off-by: Vitaly Wool <vitalywool@gmail.com>
+Cc: Jeff Garzik <jeff@garzik.org>
+Cc: <stable@kernel.org>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ drivers/net/smc911x.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-2.6.19.1.orig/drivers/net/smc911x.c
++++ linux-2.6.19.1/drivers/net/smc911x.c
+@@ -1331,7 +1331,7 @@ smc911x_rx_dma_irq(int dma, void *data)
+ static void smc911x_poll_controller(struct net_device *dev)
+ {
+       disable_irq(dev->irq);
+-      smc911x_interrupt(dev->irq, dev, NULL);
++      smc911x_interrupt(dev->irq, dev);
+       enable_irq(dev->irq);
+ }
+ #endif
diff --git a/queue-2.6.19/softmac-fixed-handling-of-deassociation-from-ap.patch b/queue-2.6.19/softmac-fixed-handling-of-deassociation-from-ap.patch
new file mode 100644 (file)
index 0000000..410f4da
--- /dev/null
@@ -0,0 +1,80 @@
+From stable-bounces@linux.kernel.org  Sat Dec 30 13:24:14 2006
+Message-ID: <4596D796.6030202@gentoo.org>
+Date: Sat, 30 Dec 2006 16:18:14 -0500
+From: Daniel Drake <dsd@gentoo.org>
+To: stable@kernel.org
+Cc: Ulrich Kunitz <kune@deine-taler.de>
+Subject: softmac: Fixed handling of deassociation from AP
+
+From: Ulrich Kunitz <kune@deine-taler.de>
+
+In 2.6.19 a deauthentication from the AP doesn't start a
+reassociation by the softmac code. It appears that
+mac->associnfo.associating must be set and the
+ieee80211softmac_assoc_work function must be scheduled. This patch
+fixes that.
+
+Signed-off-by: Ulrich Kunitz <kune@deine-taler.de>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+Date: Sun, 3 Dec 2006 15:32:00 +0000 (+0100)
+Subject: [PATCH] softmac: Fixed handling of deassociation from AP
+X-Git-Tag: v2.6.20-rc1
+X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=2b50c24554d31c2db2f93b1151b5991e62f96594
+
+ net/ieee80211/softmac/ieee80211softmac_assoc.c |   14 ++++++++++++--
+ net/ieee80211/softmac/ieee80211softmac_auth.c  |    2 ++
+ net/ieee80211/softmac/ieee80211softmac_priv.h  |    2 ++
+ 3 files changed, 16 insertions(+), 2 deletions(-)
+
+--- linux-2.6.19.1.orig/net/ieee80211/softmac/ieee80211softmac_assoc.c
++++ linux-2.6.19.1/net/ieee80211/softmac/ieee80211softmac_assoc.c
+@@ -427,6 +427,17 @@ ieee80211softmac_handle_assoc_response(s
+       return 0;
+ }
++void
++ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac)
++{
++      unsigned long flags;
++
++      spin_lock_irqsave(&mac->lock, flags);
++      mac->associnfo.associating = 1;
++      schedule_work(&mac->associnfo.work);
++      spin_unlock_irqrestore(&mac->lock, flags);
++}
++
+ int
+ ieee80211softmac_handle_disassoc(struct net_device * dev,
+                                struct ieee80211_disassoc *disassoc)
+@@ -445,8 +456,7 @@ ieee80211softmac_handle_disassoc(struct 
+       dprintk(KERN_INFO PFX "got disassoc frame\n");
+       ieee80211softmac_disassoc(mac);
+-      /* try to reassociate */
+-      schedule_work(&mac->associnfo.work);
++      ieee80211softmac_try_reassoc(mac);
+       return 0;
+ }
+--- linux-2.6.19.1.orig/net/ieee80211/softmac/ieee80211softmac_auth.c
++++ linux-2.6.19.1/net/ieee80211/softmac/ieee80211softmac_auth.c
+@@ -328,6 +328,8 @@ ieee80211softmac_deauth_from_net(struct 
+       /* can't transmit data right now... */
+       netif_carrier_off(mac->dev);
+       spin_unlock_irqrestore(&mac->lock, flags);
++
++      ieee80211softmac_try_reassoc(mac);
+ }
+ /* 
+--- linux-2.6.19.1.orig/net/ieee80211/softmac/ieee80211softmac_priv.h
++++ linux-2.6.19.1/net/ieee80211/softmac/ieee80211softmac_priv.h
+@@ -238,4 +238,6 @@ void ieee80211softmac_call_events_locked
+ int ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
+       int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask);
++void ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac);
++
+ #endif /* IEEE80211SOFTMAC_PRIV_H_ */
diff --git a/queue-2.6.19/sparc32-add-offset-in-pci_map_sg.patch b/queue-2.6.19/sparc32-add-offset-in-pci_map_sg.patch
new file mode 100644 (file)
index 0000000..cd0b771
--- /dev/null
@@ -0,0 +1,36 @@
+From stable-bounces@linux.kernel.org  Tue Jan  2 00:16:30 2007
+Date: Tue, 02 Jan 2007 00:09:25 -0800 (PST)
+Message-Id: <20070102.000925.85688510.davem@davemloft.net>
+To: stable@kernel.org
+From: David Miller <davem@davemloft.net>
+Subject: sparc32: add offset in pci_map_sg()
+
+From: Jan Andersson <jan.andersson@ieee.org>
+
+Add sg->offset to sg->dvma_address in pci_map_sg() on sparc32.  Without the
+offset, transfers to buffers that do not begin on a page boundary will not
+work as expected.
+
+Signed-off-by: Jan Andersson <jan.andersson@ieee.org>
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: William Lee Irwin III <wli@holomorphy.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+
+---
+ arch/sparc/kernel/ioport.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- linux-2.6.19.1.orig/arch/sparc/kernel/ioport.c
++++ linux-2.6.19.1/arch/sparc/kernel/ioport.c
+@@ -728,7 +728,8 @@ int pci_map_sg(struct pci_dev *hwdev, st
+       /* IIep is write-through, not flushing. */
+       for (n = 0; n < nents; n++) {
+               BUG_ON(page_address(sg->page) == NULL);
+-              sg->dvma_address = virt_to_phys(page_address(sg->page));
++              sg->dvma_address =
++                      virt_to_phys(page_address(sg->page)) + sg->offset;
+               sg->dvma_length = sg->length;
+               sg++;
+       }
diff --git a/queue-2.6.19/sparc64-fix-mem-xxx-handling.patch b/queue-2.6.19/sparc64-fix-mem-xxx-handling.patch
new file mode 100644 (file)
index 0000000..6b6104f
--- /dev/null
@@ -0,0 +1,190 @@
+From stable-bounces@linux.kernel.org  Tue Jan  2 00:10:39 2007
+Date: Tue, 02 Jan 2007 00:03:37 -0800 (PST)
+Message-Id: <20070102.000337.95059128.davem@davemloft.net>
+To: stable@kernel.org
+From: David Miller <davem@davemloft.net>
+Subject: SPARC64: Fix "mem=xxx" handling.
+
+We were not being careful enough.  When we trim the physical
+memory areas, we have to make sure we don't remove the kernel
+image or initial ramdisk image ranges.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+
+---
+ arch/sparc64/mm/init.c |  147 +++++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 124 insertions(+), 23 deletions(-)
+
+--- linux-2.6.19.1.orig/arch/sparc64/mm/init.c
++++ linux-2.6.19.1/arch/sparc64/mm/init.c
+@@ -872,6 +872,115 @@ static unsigned long __init choose_bootm
+       prom_halt();
+ }
++static void __init trim_pavail(unsigned long *cur_size_p,
++                             unsigned long *end_of_phys_p)
++{
++      unsigned long to_trim = *cur_size_p - cmdline_memory_size;
++      unsigned long avoid_start, avoid_end;
++      int i;
++
++      to_trim = PAGE_ALIGN(to_trim);
++
++      avoid_start = avoid_end = 0;
++#ifdef CONFIG_BLK_DEV_INITRD
++      avoid_start = initrd_start;
++      avoid_end = PAGE_ALIGN(initrd_end);
++#endif
++
++      /* Trim some pavail[] entries in order to satisfy the
++       * requested "mem=xxx" kernel command line specification.
++       *
++       * We must not trim off the kernel image area nor the
++       * initial ramdisk range (if any).  Also, we must not trim
++       * any pavail[] entry down to zero in order to preserve
++       * the invariant that all pavail[] entries have a non-zero
++       * size which is assumed by all of the code in here.
++       */
++      for (i = 0; i < pavail_ents; i++) {
++              unsigned long start, end, kern_end;
++              unsigned long trim_low, trim_high, n;
++
++              kern_end = PAGE_ALIGN(kern_base + kern_size);
++
++              trim_low = start = pavail[i].phys_addr;
++              trim_high = end = start + pavail[i].reg_size;
++
++              if (kern_base >= start &&
++                  kern_base < end) {
++                      trim_low = kern_base;
++                      if (kern_end >= end)
++                              continue;
++              }
++              if (kern_end >= start &&
++                  kern_end < end) {
++                      trim_high = kern_end;
++              }
++              if (avoid_start &&
++                  avoid_start >= start &&
++                  avoid_start < end) {
++                      if (trim_low > avoid_start)
++                              trim_low = avoid_start;
++                      if (avoid_end >= end)
++                              continue;
++              }
++              if (avoid_end &&
++                  avoid_end >= start &&
++                  avoid_end < end) {
++                      if (trim_high < avoid_end)
++                              trim_high = avoid_end;
++              }
++
++              if (trim_high <= trim_low)
++                      continue;
++
++              if (trim_low == start && trim_high == end) {
++                      /* Whole chunk is available for trimming.
++                       * Trim all except one page, in order to keep
++                       * entry non-empty.
++                       */
++                      n = (end - start) - PAGE_SIZE;
++                      if (n > to_trim)
++                              n = to_trim;
++
++                      if (n) {
++                              pavail[i].phys_addr += n;
++                              pavail[i].reg_size -= n;
++                              to_trim -= n;
++                      }
++              } else {
++                      n = (trim_low - start);
++                      if (n > to_trim)
++                              n = to_trim;
++
++                      if (n) {
++                              pavail[i].phys_addr += n;
++                              pavail[i].reg_size -= n;
++                              to_trim -= n;
++                      }
++                      if (to_trim) {
++                              n = end - trim_high;
++                              if (n > to_trim)
++                                      n = to_trim;
++                              if (n) {
++                                      pavail[i].reg_size -= n;
++                                      to_trim -= n;
++                              }
++                      }
++              }
++
++              if (!to_trim)
++                      break;
++      }
++
++      /* Recalculate.  */
++      *cur_size_p = 0UL;
++      for (i = 0; i < pavail_ents; i++) {
++              *end_of_phys_p = pavail[i].phys_addr +
++                      pavail[i].reg_size;
++              *cur_size_p += pavail[i].reg_size;
++      }
++}
++
+ static unsigned long __init bootmem_init(unsigned long *pages_avail,
+                                        unsigned long phys_base)
+ {
+@@ -889,31 +998,13 @@ static unsigned long __init bootmem_init
+               end_of_phys_memory = pavail[i].phys_addr +
+                       pavail[i].reg_size;
+               bytes_avail += pavail[i].reg_size;
+-              if (cmdline_memory_size) {
+-                      if (bytes_avail > cmdline_memory_size) {
+-                              unsigned long slack = bytes_avail - cmdline_memory_size;
+-
+-                              bytes_avail -= slack;
+-                              end_of_phys_memory -= slack;
+-
+-                              pavail[i].reg_size -= slack;
+-                              if ((long)pavail[i].reg_size <= 0L) {
+-                                      pavail[i].phys_addr = 0xdeadbeefUL;
+-                                      pavail[i].reg_size = 0UL;
+-                                      pavail_ents = i;
+-                              } else {
+-                                      pavail[i+1].reg_size = 0Ul;
+-                                      pavail[i+1].phys_addr = 0xdeadbeefUL;
+-                                      pavail_ents = i + 1;
+-                              }
+-                              break;
+-                      }
+-              }
+       }
+-      *pages_avail = bytes_avail >> PAGE_SHIFT;
+-
+-      end_pfn = end_of_phys_memory >> PAGE_SHIFT;
++      /* Determine the location of the initial ramdisk before trying
++       * to honor the "mem=xxx" command line argument.  We must know
++       * where the kernel image and the ramdisk image are so that we
++       * do not trim those two areas from the physical memory map.
++       */
+ #ifdef CONFIG_BLK_DEV_INITRD
+       /* Now have to check initial ramdisk, so that bootmap does not overwrite it */
+@@ -932,6 +1023,16 @@ static unsigned long __init bootmem_init
+               }
+       }
+ #endif        
++
++      if (cmdline_memory_size &&
++          bytes_avail > cmdline_memory_size)
++              trim_pavail(&bytes_avail,
++                          &end_of_phys_memory);
++
++      *pages_avail = bytes_avail >> PAGE_SHIFT;
++
++      end_pfn = end_of_phys_memory >> PAGE_SHIFT;
++
+       /* Initialize the boot-time allocator. */
+       max_pfn = max_low_pfn = end_pfn;
+       min_low_pfn = (phys_base >> PAGE_SHIFT);
diff --git a/queue-2.6.19/sparc64-handle-isa-devices-with-no-regs-property.patch b/queue-2.6.19/sparc64-handle-isa-devices-with-no-regs-property.patch
new file mode 100644 (file)
index 0000000..f13e546
--- /dev/null
@@ -0,0 +1,92 @@
+From stable-bounces@linux.kernel.org  Tue Jan  2 00:13:01 2007
+Date: Tue, 02 Jan 2007 00:06:00 -0800 (PST)
+Message-Id: <20070102.000600.59655621.davem@davemloft.net>
+To: stable@kernel.org
+From: David Miller <davem@davemloft.net>
+Subject: SPARC64: Handle ISA devices with no 'regs' property.
+
+And this points out that the return value from
+isa_dev_get_resource() and the 'pregs' arg to
+isa_dev_get_irq() are totally unused.
+
+Based upon a patch from Richard Mortimer <richm@oldelvet.org.uk>
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+
+---
+ arch/sparc64/kernel/isa.c |   20 ++++++++------------
+ 1 file changed, 8 insertions(+), 12 deletions(-)
+
+--- linux-2.6.19.1.orig/arch/sparc64/kernel/isa.c
++++ linux-2.6.19.1/arch/sparc64/kernel/isa.c
+@@ -22,14 +22,15 @@ static void __init report_dev(struct spa
+               printk(" [%s", isa_dev->prom_node->name);
+ }
+-static struct linux_prom_registers * __init
+-isa_dev_get_resource(struct sparc_isa_device *isa_dev)
++static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev)
+ {
+       struct linux_prom_registers *pregs;
+       unsigned long base, len;
+       int prop_len;
+       pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len);
++      if (!pregs)
++              return;
+       /* Only the first one is interesting. */
+       len = pregs[0].reg_size;
+@@ -44,12 +45,9 @@ isa_dev_get_resource(struct sparc_isa_de
+       request_resource(&isa_dev->bus->parent->io_space,
+                        &isa_dev->resource);
+-
+-      return pregs;
+ }
+-static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
+-                                 struct linux_prom_registers *pregs)
++static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev)
+ {
+       struct of_device *op = of_find_device_by_node(isa_dev->prom_node);
+@@ -69,7 +67,6 @@ static void __init isa_fill_children(str
+       printk(" ->");
+       while (dp) {
+-              struct linux_prom_registers *regs;
+               struct sparc_isa_device *isa_dev;
+               isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+@@ -87,8 +84,8 @@ static void __init isa_fill_children(str
+               isa_dev->bus = parent_isa_dev->bus;
+               isa_dev->prom_node = dp;
+-              regs = isa_dev_get_resource(isa_dev);
+-              isa_dev_get_irq(isa_dev, regs);
++              isa_dev_get_resource(isa_dev);
++              isa_dev_get_irq(isa_dev);
+               report_dev(isa_dev, 1);
+@@ -101,7 +98,6 @@ static void __init isa_fill_devices(stru
+       struct device_node *dp = isa_br->prom_node->child;
+       while (dp) {
+-              struct linux_prom_registers *regs;
+               struct sparc_isa_device *isa_dev;
+               isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+@@ -141,8 +137,8 @@ static void __init isa_fill_devices(stru
+               isa_dev->bus = isa_br;
+               isa_dev->prom_node = dp;
+-              regs = isa_dev_get_resource(isa_dev);
+-              isa_dev_get_irq(isa_dev, regs);
++              isa_dev_get_resource(isa_dev);
++              isa_dev_get_irq(isa_dev);
+               report_dev(isa_dev, 0);
diff --git a/queue-2.6.19/zd1211rw-call-ieee80211_rx-in-tasklet.patch b/queue-2.6.19/zd1211rw-call-ieee80211_rx-in-tasklet.patch
new file mode 100644 (file)
index 0000000..cca2ab6
--- /dev/null
@@ -0,0 +1,223 @@
+From stable-bounces@linux.kernel.org  Sat Dec 30 13:41:14 2006
+Message-ID: <4596DB95.8060004@gentoo.org>
+Date: Sat, 30 Dec 2006 16:35:17 -0500
+From: Daniel Drake <dsd@gentoo.org>
+To: stable@kernel.org
+Cc: Ulrich Kunitz <kune@deine-taler.de>
+Subject: zd1211rw: Call ieee80211_rx in tasklet
+
+From: Ulrich Kunitz <kune@deine-taler.de>
+
+[PATCH] zd1211rw: Call ieee80211_rx in tasklet
+
+The driver called ieee80211_rx in hardware interrupt context.  This has
+been against the intention of the ieee80211_rx function.  It caused a bug
+in the crypto routines used by WPA.  This patch calls ieee80211_rx in a
+tasklet.
+
+Signed-off-by: Ulrich Kunitz <kune@deine-taler.de>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+Date: Sun, 10 Dec 2006 19:13:12 +0000 (-0800)
+Subject: [PATCH] zd1211rw: Call ieee80211_rx in tasklet
+X-Git-Tag: v2.6.20-rc2
+X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=4d1feabcbf41f875447a392015acd0796f57baf6
+
+ drivers/net/wireless/zd1211rw/zd_mac.c |   91 ++++++++++++++++++++++++---------
+ drivers/net/wireless/zd1211rw/zd_mac.h |    6 +-
+ drivers/net/wireless/zd1211rw/zd_usb.c |    4 -
+ 3 files changed, 75 insertions(+), 26 deletions(-)
+
+--- linux-2.6.19.1.orig/drivers/net/wireless/zd1211rw/zd_mac.c
++++ linux-2.6.19.1/drivers/net/wireless/zd1211rw/zd_mac.c
+@@ -37,6 +37,8 @@ static void housekeeping_init(struct zd_
+ static void housekeeping_enable(struct zd_mac *mac);
+ static void housekeeping_disable(struct zd_mac *mac);
++static void do_rx(unsigned long mac_ptr);
++
+ int zd_mac_init(struct zd_mac *mac,
+               struct net_device *netdev,
+               struct usb_interface *intf)
+@@ -47,6 +49,10 @@ int zd_mac_init(struct zd_mac *mac,
+       spin_lock_init(&mac->lock);
+       mac->netdev = netdev;
++      skb_queue_head_init(&mac->rx_queue);
++      tasklet_init(&mac->rx_tasklet, do_rx, (unsigned long)mac);
++      tasklet_disable(&mac->rx_tasklet);
++
+       ieee_init(ieee);
+       softmac_init(ieee80211_priv(netdev));
+       zd_chip_init(&mac->chip, netdev, intf);
+@@ -132,6 +138,8 @@ out:
+ void zd_mac_clear(struct zd_mac *mac)
+ {
++      skb_queue_purge(&mac->rx_queue);
++      tasklet_kill(&mac->rx_tasklet);
+       zd_chip_clear(&mac->chip);
+       ZD_ASSERT(!spin_is_locked(&mac->lock));
+       ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
+@@ -160,6 +168,8 @@ int zd_mac_open(struct net_device *netde
+       struct zd_chip *chip = &mac->chip;
+       int r;
++      tasklet_enable(&mac->rx_tasklet);
++
+       r = zd_chip_enable_int(chip);
+       if (r < 0)
+               goto out;
+@@ -210,6 +220,8 @@ int zd_mac_stop(struct net_device *netde
+        */
+       zd_chip_disable_rx(chip);
++      skb_queue_purge(&mac->rx_queue);
++      tasklet_disable(&mac->rx_tasklet);
+       housekeeping_disable(mac);
+       ieee80211softmac_stop(netdev);
+@@ -873,45 +885,78 @@ static int fill_rx_stats(struct ieee8021
+       return 0;
+ }
+-int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length)
++static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
+ {
+       int r;
+       struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+       struct ieee80211_rx_stats stats;
+       const struct rx_status *status;
+-      struct sk_buff *skb;
+-      if (length < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
+-                   IEEE80211_FCS_LEN + sizeof(struct rx_status))
+-              return -EINVAL;
++      if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
++                     IEEE80211_FCS_LEN + sizeof(struct rx_status))
++      {
++              dev_dbg_f(zd_mac_dev(mac), "Packet with length %u to small.\n",
++                       skb->len);
++              goto free_skb;
++      }
+-      r = fill_rx_stats(&stats, &status, mac, buffer, length);
+-      if (r)
+-              return r;
++      r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
++      if (r) {
++              /* Only packets with rx errors are included here. */
++              goto free_skb;
++      }
+-      length -= ZD_PLCP_HEADER_SIZE+IEEE80211_FCS_LEN+
+-                sizeof(struct rx_status);
+-      buffer += ZD_PLCP_HEADER_SIZE;
++      __skb_pull(skb, ZD_PLCP_HEADER_SIZE);
++      __skb_trim(skb, skb->len -
++                      (IEEE80211_FCS_LEN + sizeof(struct rx_status)));
+-      update_qual_rssi(mac, buffer, length, stats.signal, stats.rssi);
++      update_qual_rssi(mac, skb->data, skb->len, stats.signal,
++                       status->signal_strength);
+-      r = filter_rx(ieee, buffer, length, &stats);
+-      if (r <= 0)
+-              return r;
+-      skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
+-      if (!skb)
+-              return -ENOMEM;
++      r = filter_rx(ieee, skb->data, skb->len, &stats);
++      if (r <= 0) {
++              if (r < 0)
++                      dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
++              goto free_skb;
++      }
++
+       if (ieee->iw_mode == IW_MODE_MONITOR)
+-              fill_rt_header(skb_put(skb, sizeof(struct zd_rt_hdr)), mac,
++              fill_rt_header(skb_push(skb, sizeof(struct zd_rt_hdr)), mac,
+                              &stats, status);
+-      memcpy(skb_put(skb, length), buffer, length);
+       r = ieee80211_rx(ieee, skb, &stats);
+-      if (!r) {
+-              ZD_ASSERT(in_irq());
+-              dev_kfree_skb_irq(skb);
++      if (r)
++              return;
++
++free_skb:
++      /* We are always in a soft irq. */
++      dev_kfree_skb(skb);
++}
++
++static void do_rx(unsigned long mac_ptr)
++{
++      struct zd_mac *mac = (struct zd_mac *)mac_ptr;
++      struct sk_buff *skb;
++
++      while ((skb = skb_dequeue(&mac->rx_queue)) != NULL)
++              zd_mac_rx(mac, skb);
++}
++
++int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
++{
++      struct sk_buff *skb;
++
++      skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
++      if (!skb) {
++              dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
++              return -ENOMEM;
+       }
++      skb_reserve(skb, sizeof(struct zd_rt_hdr));
++      memcpy(__skb_put(skb, length), buffer, length);
++      skb_queue_tail(&mac->rx_queue, skb);
++      tasklet_schedule(&mac->rx_tasklet);
++
+       return 0;
+ }
+--- linux-2.6.19.1.orig/drivers/net/wireless/zd1211rw/zd_mac.h
++++ linux-2.6.19.1/drivers/net/wireless/zd1211rw/zd_mac.h
+@@ -133,6 +133,10 @@ struct zd_mac {
+       /* Unlocked reading possible */
+       struct iw_statistics iw_stats;
+       struct housekeeping housekeeping;
++
++      struct tasklet_struct rx_tasklet;
++      struct sk_buff_head rx_queue;
++
+       unsigned int stats_count;
+       u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
+       u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE];
+@@ -174,7 +178,7 @@ int zd_mac_open(struct net_device *netde
+ int zd_mac_stop(struct net_device *netdev);
+ int zd_mac_set_mac_address(struct net_device *dev, void *p);
+-int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length);
++int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length);
+ int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain);
+ u8 zd_mac_get_regdomain(struct zd_mac *zd_mac);
+--- linux-2.6.19.1.orig/drivers/net/wireless/zd1211rw/zd_usb.c
++++ linux-2.6.19.1/drivers/net/wireless/zd1211rw/zd_usb.c
+@@ -599,13 +599,13 @@ static void handle_rx_packet(struct zd_u
+                       n = l+k;
+                       if (n > length)
+                               return;
+-                      zd_mac_rx(mac, buffer+l, k);
++                      zd_mac_rx_irq(mac, buffer+l, k);
+                       if (i >= 2)
+                               return;
+                       l = (n+3) & ~3;
+               }
+       } else {
+-              zd_mac_rx(mac, buffer, length);
++              zd_mac_rx_irq(mac, buffer, length);
+       }
+ }