]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Nov 2012 23:31:34 +0000 (15:31 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Nov 2012 23:31:34 +0000 (15:31 -0800)
added patches:
arm-at91-at91sam9g45-fix-crypto-peripherals-irq-issue-due-to-sparse-irq-support.patch
cifs-do-not-lookup-hashed-negative-dentry-in-cifs_atomic_open.patch
cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch
crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch
fanotify-fix-missing-break.patch
libata-acpi-fix-null-ptr-derference-in-ata_acpi_dev_handle.patch
mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch
mac80211-don-t-send-null-data-packet-when-not-associated.patch
mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch
module-fix-out-by-one-error-in-kallsyms.patch
pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch
pci-pm-fix-proc-config-reg-access-for-d3cold-and-bridge-suspending.patch
pci-pm-resume-device-before-shutdown.patch
virtio-don-t-access-index-after-unregister.patch
xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch

16 files changed:
queue-3.6/arm-at91-at91sam9g45-fix-crypto-peripherals-irq-issue-due-to-sparse-irq-support.patch [new file with mode: 0644]
queue-3.6/cifs-do-not-lookup-hashed-negative-dentry-in-cifs_atomic_open.patch [new file with mode: 0644]
queue-3.6/cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch [new file with mode: 0644]
queue-3.6/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch [new file with mode: 0644]
queue-3.6/fanotify-fix-missing-break.patch [new file with mode: 0644]
queue-3.6/libata-acpi-fix-null-ptr-derference-in-ata_acpi_dev_handle.patch [new file with mode: 0644]
queue-3.6/mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch [new file with mode: 0644]
queue-3.6/mac80211-don-t-send-null-data-packet-when-not-associated.patch [new file with mode: 0644]
queue-3.6/mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch [new file with mode: 0644]
queue-3.6/module-fix-out-by-one-error-in-kallsyms.patch [new file with mode: 0644]
queue-3.6/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch [new file with mode: 0644]
queue-3.6/pci-pm-fix-proc-config-reg-access-for-d3cold-and-bridge-suspending.patch [new file with mode: 0644]
queue-3.6/pci-pm-resume-device-before-shutdown.patch [new file with mode: 0644]
queue-3.6/series
queue-3.6/virtio-don-t-access-index-after-unregister.patch [new file with mode: 0644]
queue-3.6/xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch [new file with mode: 0644]

diff --git a/queue-3.6/arm-at91-at91sam9g45-fix-crypto-peripherals-irq-issue-due-to-sparse-irq-support.patch b/queue-3.6/arm-at91-at91sam9g45-fix-crypto-peripherals-irq-issue-due-to-sparse-irq-support.patch
new file mode 100644 (file)
index 0000000..2c47538
--- /dev/null
@@ -0,0 +1,57 @@
+From 097965ee447e5ccec9776f9b075e64cf7607e5eb Mon Sep 17 00:00:00 2001
+From: Nicolas Royer <nicolas@eukrea.com>
+Date: Tue, 6 Nov 2012 17:31:03 +0100
+Subject: ARM: at91/AT91SAM9G45: fix crypto peripherals irq issue due to sparse irq support
+
+From: Nicolas Royer <nicolas@eukrea.com>
+
+commit 097965ee447e5ccec9776f9b075e64cf7607e5eb upstream.
+
+Spare irq support introduced by commit 8fe82a5 (ARM: at91: sparse irq support)
+involves to add the NR_IRQS_LEGACY offset to irq number.
+
+Signed-off-by: Nicolas Royer <nicolas@eukrea.com>
+Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
+Acked-by: Eric Bénard <eric@eukrea.com>
+Tested-by: Eric Bénard <eric@eukrea.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm/mach-at91/at91sam9g45_devices.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/mach-at91/at91sam9g45_devices.c
++++ b/arch/arm/mach-at91/at91sam9g45_devices.c
+@@ -1847,8 +1847,8 @@ static struct resource sha_resources[] =
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+-              .start  = AT91SAM9G45_ID_AESTDESSHA,
+-              .end    = AT91SAM9G45_ID_AESTDESSHA,
++              .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
++              .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .flags  = IORESOURCE_IRQ,
+       },
+ };
+@@ -1880,8 +1880,8 @@ static struct resource tdes_resources[]
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+-              .start  = AT91SAM9G45_ID_AESTDESSHA,
+-              .end    = AT91SAM9G45_ID_AESTDESSHA,
++              .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
++              .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .flags  = IORESOURCE_IRQ,
+       },
+ };
+@@ -1916,8 +1916,8 @@ static struct resource aes_resources[] =
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+-              .start  = AT91SAM9G45_ID_AESTDESSHA,
+-              .end    = AT91SAM9G45_ID_AESTDESSHA,
++              .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
++              .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .flags  = IORESOURCE_IRQ,
+       },
+ };
diff --git a/queue-3.6/cifs-do-not-lookup-hashed-negative-dentry-in-cifs_atomic_open.patch b/queue-3.6/cifs-do-not-lookup-hashed-negative-dentry-in-cifs_atomic_open.patch
new file mode 100644 (file)
index 0000000..45e55f7
--- /dev/null
@@ -0,0 +1,46 @@
+From 3798f47aa276b332c30da499cb4df4577e2f8872 Mon Sep 17 00:00:00 2001
+From: Sachin Prabhu <sprabhu@redhat.com>
+Date: Mon, 5 Nov 2012 11:39:32 +0000
+Subject: cifs: Do not lookup hashed negative dentry in cifs_atomic_open
+
+From: Sachin Prabhu <sprabhu@redhat.com>
+
+commit 3798f47aa276b332c30da499cb4df4577e2f8872 upstream.
+
+We do not need to lookup a hashed negative directory since we have
+already revalidated it before and have found it to be fine.
+
+This also prevents a crash in cifs_lookup() when it attempts to rehash
+the already hashed negative lookup dentry.
+
+The patch has been tested using the reproducer at
+https://bugzilla.redhat.com/show_bug.cgi?id=867344#c28
+
+Reported-by: Vit Zahradka <vit.zahradka@tiscali.cz>
+Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/dir.c |   11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+--- a/fs/cifs/dir.c
++++ b/fs/cifs/dir.c
+@@ -392,7 +392,16 @@ cifs_atomic_open(struct inode *inode, st
+        * in network traffic in the other paths.
+        */
+       if (!(oflags & O_CREAT)) {
+-              struct dentry *res = cifs_lookup(inode, direntry, 0);
++              struct dentry *res;
++
++              /*
++               * Check for hashed negative dentry. We have already revalidated
++               * the dentry and it is fine. No need to perform another lookup.
++               */
++              if (!d_unhashed(direntry))
++                      return -ENOENT;
++
++              res = cifs_lookup(inode, direntry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
diff --git a/queue-3.6/cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch b/queue-3.6/cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch
new file mode 100644 (file)
index 0000000..7315eec
--- /dev/null
@@ -0,0 +1,171 @@
+From 36960e440ccf94349c09fb944930d3bfe4bc473f Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+Date: Sat, 3 Nov 2012 09:37:28 -0400
+Subject: cifs: fix potential buffer overrun in cifs.idmap handling code
+
+From: Jeff Layton <jlayton@redhat.com>
+
+commit 36960e440ccf94349c09fb944930d3bfe4bc473f upstream.
+
+The userspace cifs.idmap program generally works with the wbclient libs
+to generate binary SIDs in userspace. That program defines the struct
+that holds these values as having a max of 15 subauthorities. The kernel
+idmapping code however limits that value to 5.
+
+When the kernel copies those values around though, it doesn't sanity
+check the num_subauths value handed back from userspace or from the
+server. It's possible therefore for userspace to hand us back a bogus
+num_subauths value (or one that's valid, but greater than 5) that could
+cause the kernel to walk off the end of the cifs_sid->sub_auths array.
+
+Fix this by defining a new routine for copying sids and using that in
+all of the places that copy it. If we end up with a sid that's longer
+than expected then this approach will just lop off the "extra" subauths,
+but that's basically what the code does today already. Better approaches
+might be to fix this code to reject SIDs with >5 subauths, or fix it
+to handle the subauths array dynamically.
+
+At the same time, change the kernel to check the length of the data
+returned by userspace. If it's shorter than struct cifs_sid, reject it
+and return -EIO. If that happens we'll end up with fields that are
+basically uninitialized.
+
+Long term, it might make sense to redefine cifs_sid using a flexarray at
+the end, to allow for variable-length subauth lists, and teach the code
+to handle the case where the subauths array being passed in from
+userspace is shorter than 5 elements.
+
+Note too, that I don't consider this a security issue since you'd need
+a compromised cifs.idmap program. If you have that, you can do all sorts
+of nefarious stuff. Still, this is probably reasonable for stable.
+
+Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsacl.c |   49 ++++++++++++++++++++-----------------------------
+ 1 file changed, 20 insertions(+), 29 deletions(-)
+
+--- a/fs/cifs/cifsacl.c
++++ b/fs/cifs/cifsacl.c
+@@ -225,6 +225,13 @@ sid_to_str(struct cifs_sid *sidptr, char
+ }
+ static void
++cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
++{
++      memcpy(dst, src, sizeof(*dst));
++      dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS);
++}
++
++static void
+ id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
+               struct cifs_sid_id **psidid, char *typestr)
+ {
+@@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struc
+               }
+       }
+-      memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
++      cifs_copy_sid(&(*psidid)->sid, sidptr);
+       (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
+       (*psidid)->refcount = 0;
+@@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtyp
+        * any fields of the node after a reference is put .
+        */
+       if (test_bit(SID_ID_MAPPED, &psidid->state)) {
+-              memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
++              cifs_copy_sid(ssid, &psidid->sid);
+               psidid->time = jiffies; /* update ts for accessing */
+               goto id_sid_out;
+       }
+@@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtyp
+               if (IS_ERR(sidkey)) {
+                       rc = -EINVAL;
+                       cFYI(1, "%s: Can't map and id to a SID", __func__);
++              } else if (sidkey->datalen < sizeof(struct cifs_sid)) {
++                      rc = -EIO;
++                      cFYI(1, "%s: Downcall contained malformed key "
++                              "(datalen=%hu)", __func__, sidkey->datalen);
+               } else {
+                       lsid = (struct cifs_sid *)sidkey->payload.data;
+-                      memcpy(&psidid->sid, lsid,
+-                              sidkey->datalen < sizeof(struct cifs_sid) ?
+-                              sidkey->datalen : sizeof(struct cifs_sid));
+-                      memcpy(ssid, &psidid->sid,
+-                              sidkey->datalen < sizeof(struct cifs_sid) ?
+-                              sidkey->datalen : sizeof(struct cifs_sid));
++                      cifs_copy_sid(&psidid->sid, lsid);
++                      cifs_copy_sid(ssid, &psidid->sid);
+                       set_bit(SID_ID_MAPPED, &psidid->state);
+                       key_put(sidkey);
+                       kfree(psidid->sidstr);
+@@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtyp
+                       return rc;
+               }
+               if (test_bit(SID_ID_MAPPED, &psidid->state))
+-                      memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
++                      cifs_copy_sid(ssid, &psidid->sid);
+               else
+                       rc = -EINVAL;
+       }
+@@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid *
+ static void copy_sec_desc(const struct cifs_ntsd *pntsd,
+                               struct cifs_ntsd *pnntsd, __u32 sidsoffset)
+ {
+-      int i;
+-
+       struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
+       struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
+@@ -692,26 +697,14 @@ static void copy_sec_desc(const struct c
+       owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+                               le32_to_cpu(pntsd->osidoffset));
+       nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
+-
+-      nowner_sid_ptr->revision = owner_sid_ptr->revision;
+-      nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
+-      for (i = 0; i < 6; i++)
+-              nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
+-      for (i = 0; i < 5; i++)
+-              nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
++      cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
+       /* copy group sid */
+       group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
+                               le32_to_cpu(pntsd->gsidoffset));
+       ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
+                                       sizeof(struct cifs_sid));
+-
+-      ngroup_sid_ptr->revision = group_sid_ptr->revision;
+-      ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
+-      for (i = 0; i < 6; i++)
+-              ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
+-      for (i = 0; i < 5; i++)
+-              ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
++      cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
+       return;
+ }
+@@ -1120,8 +1113,7 @@ static int build_sec_desc(struct cifs_nt
+                               kfree(nowner_sid_ptr);
+                               return rc;
+                       }
+-                      memcpy(owner_sid_ptr, nowner_sid_ptr,
+-                                      sizeof(struct cifs_sid));
++                      cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
+                       kfree(nowner_sid_ptr);
+                       *aclflag = CIFS_ACL_OWNER;
+               }
+@@ -1139,8 +1131,7 @@ static int build_sec_desc(struct cifs_nt
+                               kfree(ngroup_sid_ptr);
+                               return rc;
+                       }
+-                      memcpy(group_sid_ptr, ngroup_sid_ptr,
+-                                      sizeof(struct cifs_sid));
++                      cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
+                       kfree(ngroup_sid_ptr);
+                       *aclflag = CIFS_ACL_GROUP;
+               }
diff --git a/queue-3.6/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch b/queue-3.6/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch
new file mode 100644 (file)
index 0000000..8151a7a
--- /dev/null
@@ -0,0 +1,53 @@
+From 9efade1b3e981f5064f9db9ca971b4dc7557ae42 Mon Sep 17 00:00:00 2001
+From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+Date: Sun, 21 Oct 2012 20:42:28 +0300
+Subject: crypto: cryptd - disable softirqs in cryptd_queue_worker to prevent data corruption
+
+From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+
+commit 9efade1b3e981f5064f9db9ca971b4dc7557ae42 upstream.
+
+cryptd_queue_worker attempts to prevent simultaneous accesses to crypto
+workqueue by cryptd_enqueue_request using preempt_disable/preempt_enable.
+However cryptd_enqueue_request might be called from softirq context,
+so add local_bh_disable/local_bh_enable to prevent data corruption and
+panics.
+
+Bug report at http://marc.info/?l=linux-crypto-vger&m=134858649616319&w=2
+
+v2:
+ - Disable software interrupts instead of hardware interrupts
+
+Reported-by: Gurucharan Shetty <gurucharan.shetty@gmail.com>
+Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/cryptd.c |   11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/crypto/cryptd.c
++++ b/crypto/cryptd.c
+@@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct w
+       struct crypto_async_request *req, *backlog;
+       cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
+-      /* Only handle one request at a time to avoid hogging crypto
+-       * workqueue. preempt_disable/enable is used to prevent
+-       * being preempted by cryptd_enqueue_request() */
++      /*
++       * Only handle one request at a time to avoid hogging crypto workqueue.
++       * preempt_disable/enable is used to prevent being preempted by
++       * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent
++       * cryptd_enqueue_request() being accessed from software interrupts.
++       */
++      local_bh_disable();
+       preempt_disable();
+       backlog = crypto_get_backlog(&cpu_queue->queue);
+       req = crypto_dequeue_request(&cpu_queue->queue);
+       preempt_enable();
++      local_bh_enable();
+       if (!req)
+               return;
diff --git a/queue-3.6/fanotify-fix-missing-break.patch b/queue-3.6/fanotify-fix-missing-break.patch
new file mode 100644 (file)
index 0000000..ff57c42
--- /dev/null
@@ -0,0 +1,41 @@
+From 848561d368751a1c0f679b9f045a02944506a801 Mon Sep 17 00:00:00 2001
+From: Eric Paris <eparis@redhat.com>
+Date: Thu, 8 Nov 2012 15:53:37 -0800
+Subject: fanotify: fix missing break
+
+From: Eric Paris <eparis@redhat.com>
+
+commit 848561d368751a1c0f679b9f045a02944506a801 upstream.
+
+Anders Blomdell noted in 2010 that Fanotify lost events and provided a
+test case.  Eric Paris confirmed it was a bug and posted a fix to the
+list
+
+  https://groups.google.com/forum/?fromgroups=#!topic/linux.kernel/RrJfTfyW2BE
+
+but never applied it.  Repeated attempts over time to actually get him
+to apply it have never had a reply from anyone who has raised it
+
+So apply it anyway
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Reported-by: Anders Blomdell <anders.blomdell@control.lth.se>
+Cc: Eric Paris <eparis@redhat.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/notify/fanotify/fanotify.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/notify/fanotify/fanotify.c
++++ b/fs/notify/fanotify/fanotify.c
+@@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify
+                       if ((old->path.mnt == new->path.mnt) &&
+                           (old->path.dentry == new->path.dentry))
+                               return true;
++                      break;
+               case (FSNOTIFY_EVENT_NONE):
+                       return true;
+               default:
diff --git a/queue-3.6/libata-acpi-fix-null-ptr-derference-in-ata_acpi_dev_handle.patch b/queue-3.6/libata-acpi-fix-null-ptr-derference-in-ata_acpi_dev_handle.patch
new file mode 100644 (file)
index 0000000..55722fb
--- /dev/null
@@ -0,0 +1,49 @@
+From 60817a680b1bd3341b6909fab7d8a1fcc3a78369 Mon Sep 17 00:00:00 2001
+From: Aaron Lu <aaron.lu@intel.com>
+Date: Tue, 9 Oct 2012 15:37:48 +0800
+Subject: libata-acpi: Fix NULL ptr derference in ata_acpi_dev_handle
+
+From: Aaron Lu <aaron.lu@intel.com>
+
+commit 60817a680b1bd3341b6909fab7d8a1fcc3a78369 upstream.
+
+commit 6b66d95895c149cbc04d4fac5a2f5477c543a8ae didn't handle SATA PMP
+case in ata_acpi_bind_device and will cause a NULL ptr dereference when
+user attached a SATA drive to the PMP port. Fix this by checking PMP
+support.
+
+This bug is reported by Dan van der Ster in the following bugzilla page:
+https://bugzilla.kernel.org/show_bug.cgi?id=48211
+
+Reported-by: Dan van der Ster <dan@vanderster.com>
+Tested-by: Dan van der Ster <dan@vanderster.com>
+Signed-off-by: Aaron Lu <aaron.lu@intel.com>
+Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
+Tested-by: Simon <tangouniform@sbcglobal.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/ata/libata-acpi.c |   11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/ata/libata-acpi.c
++++ b/drivers/ata/libata-acpi.c
+@@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct a
+       struct acpi_device *acpi_dev;
+       struct acpi_device_power_state *states;
+-      if (ap->flags & ATA_FLAG_ACPI_SATA)
+-              ata_dev = &ap->link.device[sdev->channel];
+-      else
++      if (ap->flags & ATA_FLAG_ACPI_SATA) {
++              if (!sata_pmp_attached(ap))
++                      ata_dev = &ap->link.device[sdev->id];
++              else
++                      ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id];
++      }
++      else {
+               ata_dev = &ap->link.device[sdev->id];
++      }
+       *handle = ata_dev_acpi_handle(ata_dev);
diff --git a/queue-3.6/mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch b/queue-3.6/mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch
new file mode 100644 (file)
index 0000000..2079fec
--- /dev/null
@@ -0,0 +1,97 @@
+From 1f98ab7fef48a2968f37f422c256c9fbd978c3f0 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sat, 10 Nov 2012 03:44:14 +0100
+Subject: mac80211: call skb_dequeue/ieee80211_free_txskb instead of __skb_queue_purge
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit 1f98ab7fef48a2968f37f422c256c9fbd978c3f0 upstream.
+
+Fixes more wifi status skb leaks, leading to hostapd/wpa_supplicant hangs.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/ieee80211_i.h |    2 ++
+ net/mac80211/sta_info.c    |    6 +++---
+ net/mac80211/status.c      |    9 +++++++++
+ net/mac80211/tx.c          |    9 ++++++---
+ 4 files changed, 20 insertions(+), 6 deletions(-)
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1304,6 +1304,8 @@ netdev_tx_t ieee80211_monitor_start_xmit
+                                        struct net_device *dev);
+ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
+                                      struct net_device *dev);
++void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
++                            struct sk_buff_head *skbs);
+ /* HT */
+ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -730,8 +730,8 @@ int __must_check __sta_info_destroy(stru
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+               local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]);
+-              __skb_queue_purge(&sta->ps_tx_buf[ac]);
+-              __skb_queue_purge(&sta->tx_filtered[ac]);
++              ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]);
++              ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]);
+       }
+ #ifdef CONFIG_MAC80211_MESH
+@@ -765,7 +765,7 @@ int __must_check __sta_info_destroy(stru
+               tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]);
+               if (!tid_tx)
+                       continue;
+-              __skb_queue_purge(&tid_tx->pending);
++              ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
+               kfree(tid_tx);
+       }
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -648,3 +648,12 @@ void ieee80211_free_txskb(struct ieee802
+       dev_kfree_skb_any(skb);
+ }
+ EXPORT_SYMBOL(ieee80211_free_txskb);
++
++void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
++                            struct sk_buff_head *skbs)
++{
++      struct sk_buff *skb;
++
++      while ((skb = __skb_dequeue(skbs)))
++              ieee80211_free_txskb(hw, skb);
++}
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -1358,7 +1358,7 @@ static int invoke_tx_handlers(struct iee
+               if (tx->skb)
+                       ieee80211_free_txskb(&tx->local->hw, tx->skb);
+               else
+-                      __skb_queue_purge(&tx->skbs);
++                      ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
+               return -1;
+       } else if (unlikely(res == TX_QUEUED)) {
+               I802_DEBUG_INC(tx->local->tx_handlers_queued);
+@@ -2132,10 +2132,13 @@ netdev_tx_t ieee80211_subif_start_xmit(s
+  */
+ void ieee80211_clear_tx_pending(struct ieee80211_local *local)
+ {
++      struct sk_buff *skb;
+       int i;
+-      for (i = 0; i < local->hw.queues; i++)
+-              skb_queue_purge(&local->pending[i]);
++      for (i = 0; i < local->hw.queues; i++) {
++              while ((skb = skb_dequeue(&local->pending[i])) != NULL)
++                      ieee80211_free_txskb(&local->hw, skb);
++      }
+ }
+ /*
diff --git a/queue-3.6/mac80211-don-t-send-null-data-packet-when-not-associated.patch b/queue-3.6/mac80211-don-t-send-null-data-packet-when-not-associated.patch
new file mode 100644 (file)
index 0000000..2f0f49c
--- /dev/null
@@ -0,0 +1,35 @@
+From 20f544eea03db4b498942558b882d463ce575c3e Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Thu, 8 Nov 2012 14:06:28 +0100
+Subject: mac80211: don't send null data packet when not associated
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 20f544eea03db4b498942558b882d463ce575c3e upstream.
+
+On resume or firmware recovery, mac80211 sends a null
+data packet to see if the AP is still around and hasn't
+disconnected us. However, it always does this even if
+it wasn't even connected before, leading to a warning
+in the new channel context code. Fix this by checking
+that it's associated.
+
+Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/util.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -1434,6 +1434,8 @@ int ieee80211_reconfig(struct ieee80211_
+               list_for_each_entry(sdata, &local->interfaces, list) {
+                       if (sdata->vif.type != NL80211_IFTYPE_STATION)
+                               continue;
++                      if (!sdata->u.mgd.associated)
++                              continue;
+                       ieee80211_send_nullfunc(local, sdata, 0);
+               }
diff --git a/queue-3.6/mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch b/queue-3.6/mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch
new file mode 100644 (file)
index 0000000..b8e1ef7
--- /dev/null
@@ -0,0 +1,51 @@
+From 987c285c2ae2e4e32aca3a9b3252d28171c75711 Mon Sep 17 00:00:00 2001
+From: Arik Nemtsov <arik@wizery.com>
+Date: Mon, 5 Nov 2012 10:27:52 +0200
+Subject: mac80211: sync acccess to tx_filtered/ps_tx_buf queues
+
+From: Arik Nemtsov <arik@wizery.com>
+
+commit 987c285c2ae2e4e32aca3a9b3252d28171c75711 upstream.
+
+These are accessed without a lock when ending STA PSM. If the
+sta_cleanup timer accesses these lists at the same time, we might crash.
+
+This may fix some mysterious crashes we had during
+ieee80211_sta_ps_deliver_wakeup.
+
+Signed-off-by: Arik Nemtsov <arik@wizery.com>
+Signed-off-by: Ido Yariv <ido@wizery.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/sta_info.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -948,6 +948,7 @@ void ieee80211_sta_ps_deliver_wakeup(str
+       struct ieee80211_local *local = sdata->local;
+       struct sk_buff_head pending;
+       int filtered = 0, buffered = 0, ac;
++      unsigned long flags;
+       clear_sta_flag(sta, WLAN_STA_SP);
+@@ -963,12 +964,16 @@ void ieee80211_sta_ps_deliver_wakeup(str
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+               int count = skb_queue_len(&pending), tmp;
++              spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags);
+               skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending);
++              spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags);
+               tmp = skb_queue_len(&pending);
+               filtered += tmp - count;
+               count = tmp;
++              spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags);
+               skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending);
++              spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags);
+               tmp = skb_queue_len(&pending);
+               buffered += tmp - count;
+       }
diff --git a/queue-3.6/module-fix-out-by-one-error-in-kallsyms.patch b/queue-3.6/module-fix-out-by-one-error-in-kallsyms.patch
new file mode 100644 (file)
index 0000000..008739c
--- /dev/null
@@ -0,0 +1,78 @@
+From 59ef28b1f14899b10d6b2682c7057ca00a9a3f47 Mon Sep 17 00:00:00 2001
+From: Rusty Russell <rusty@rustcorp.com.au>
+Date: Thu, 25 Oct 2012 10:49:25 +1030
+Subject: module: fix out-by-one error in kallsyms
+
+From: Rusty Russell <rusty@rustcorp.com.au>
+
+commit 59ef28b1f14899b10d6b2682c7057ca00a9a3f47 upstream.
+
+Masaki found and patched a kallsyms issue: the last symbol in a
+module's symtab wasn't transferred.  This is because we manually copy
+the zero'th entry (which is always empty) then copy the rest in a loop
+starting at 1, though from src[0].  His fix was minimal, I prefer to
+rewrite the loops in more standard form.
+
+There are two loops: one to get the size, and one to copy.  Make these
+identical: always count entry 0 and any defined symbol in an allocated
+non-init section.
+
+This bug exists since the following commit was introduced.
+   module: reduce symbol table for loaded modules (v2)
+   commit: 4a4962263f07d14660849ec134ee42b63e95ea9a
+
+LKML: http://lkml.org/lkml/2012/10/24/27
+Reported-by: Masaki Kimura <masaki.kimura.kz@hitachi.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/module.c |   27 ++++++++++++++++-----------
+ 1 file changed, 16 insertions(+), 11 deletions(-)
+
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -2273,12 +2273,17 @@ static void layout_symtab(struct module
+       src = (void *)info->hdr + symsect->sh_offset;
+       nsrc = symsect->sh_size / sizeof(*src);
++      /* strtab always starts with a nul, so offset 0 is the empty string. */
++      strtab_size = 1;
++
+       /* Compute total space required for the core symbols' strtab. */
+-      for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src)
+-              if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) {
+-                      strtab_size += strlen(&info->strtab[src->st_name]) + 1;
++      for (ndst = i = 0; i < nsrc; i++) {
++              if (i == 0 ||
++                  is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
++                      strtab_size += strlen(&info->strtab[src[i].st_name])+1;
+                       ndst++;
+               }
++      }
+       /* Append room for core symbols at end of core part. */
+       info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);
+@@ -2312,15 +2317,15 @@ static void add_kallsyms(struct module *
+       mod->core_symtab = dst = mod->module_core + info->symoffs;
+       mod->core_strtab = s = mod->module_core + info->stroffs;
+       src = mod->symtab;
+-      *dst = *src;
+       *s++ = 0;
+-      for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
+-              if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum))
+-                      continue;
+-
+-              dst[ndst] = *src;
+-              dst[ndst++].st_name = s - mod->core_strtab;
+-              s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1;
++      for (ndst = i = 0; i < mod->num_symtab; i++) {
++              if (i == 0 ||
++                  is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
++                      dst[ndst] = src[i];
++                      dst[ndst++].st_name = s - mod->core_strtab;
++                      s += strlcpy(s, &mod->strtab[src[i].st_name],
++                                   KSYM_NAME_LEN) + 1;
++              }
+       }
+       mod->core_num_syms = ndst;
+ }
diff --git a/queue-3.6/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch b/queue-3.6/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch
new file mode 100644 (file)
index 0000000..9b2faf3
--- /dev/null
@@ -0,0 +1,156 @@
+From 90b5c1d7c45eeb622302680ff96ed30c1a2b6f0e Mon Sep 17 00:00:00 2001
+From: Huang Ying <ying.huang@intel.com>
+Date: Wed, 24 Oct 2012 14:54:13 +0800
+Subject: PCI/PM: Fix deadlock when unbinding device if parent in D3cold
+
+From: Huang Ying <ying.huang@intel.com>
+
+commit 90b5c1d7c45eeb622302680ff96ed30c1a2b6f0e upstream.
+
+If a PCI device and its parents are put into D3cold, unbinding the
+device will trigger deadlock as follow:
+
+- driver_unbind
+  - device_release_driver
+    - device_lock(dev)                         <--- previous lock here
+    - __device_release_driver
+      - pm_runtime_get_sync
+        ...
+          - rpm_resume(dev)
+            - rpm_resume(dev->parent)
+              ...
+                - pci_pm_runtime_resume
+                  ...
+                  - pci_set_power_state
+                    - __pci_start_power_transition
+                      - pci_wakeup_bus(dev->parent->subordinate)
+                        - pci_walk_bus
+                          - device_lock(dev)   <--- deadlock here
+
+
+If we do not do device_lock in pci_walk_bus, we can avoid deadlock.
+Device_lock in pci_walk_bus is introduced in commit:
+d71374dafbba7ec3f67371d3b7e9f6310a588808, corresponding email thread
+is: https://lkml.org/lkml/2006/5/26/38.  The patch author Zhang Yanmin
+said device_lock is added to pci_walk_bus because:
+
+  Some error handling functions call pci_walk_bus. For example, PCIe
+  aer. Here we lock the device, so the driver wouldn't detach from the
+  device, as the cb might call driver's callback function.
+
+So I fixed the deadlock as follows:
+
+- remove device_lock from pci_walk_bus
+- add device_lock into callback if callback will call driver's callback
+
+I checked pci_walk_bus users one by one, and found only PCIe aer needs
+device lock.
+
+Signed-off-by: Huang Ying <ying.huang@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+CC: Zhang Yanmin <yanmin.zhang@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/bus.c                  |    3 ---
+ drivers/pci/pcie/aer/aerdrv_core.c |   20 ++++++++++++++++----
+ 2 files changed, 16 insertions(+), 7 deletions(-)
+
+--- a/drivers/pci/bus.c
++++ b/drivers/pci/bus.c
+@@ -316,10 +316,7 @@ void pci_walk_bus(struct pci_bus *top, i
+               } else
+                       next = dev->bus_list.next;
+-              /* Run device routines with the device locked */
+-              device_lock(&dev->dev);
+               retval = cb(dev, userdata);
+-              device_unlock(&dev->dev);
+               if (retval)
+                       break;
+       }
+--- a/drivers/pci/pcie/aer/aerdrv_core.c
++++ b/drivers/pci/pcie/aer/aerdrv_core.c
+@@ -244,6 +244,7 @@ static int report_error_detected(struct
+       struct aer_broadcast_data *result_data;
+       result_data = (struct aer_broadcast_data *) data;
++      device_lock(&dev->dev);
+       dev->error_state = result_data->state;
+       if (!dev->driver ||
+@@ -262,12 +263,14 @@ static int report_error_detected(struct
+                                  dev->driver ?
+                                  "no AER-aware driver" : "no driver");
+               }
+-              return 0;
++              goto out;
+       }
+       err_handler = dev->driver->err_handler;
+       vote = err_handler->error_detected(dev, result_data->state);
+       result_data->result = merge_result(result_data->result, vote);
++out:
++      device_unlock(&dev->dev);
+       return 0;
+ }
+@@ -278,14 +281,17 @@ static int report_mmio_enabled(struct pc
+       struct aer_broadcast_data *result_data;
+       result_data = (struct aer_broadcast_data *) data;
++      device_lock(&dev->dev);
+       if (!dev->driver ||
+               !dev->driver->err_handler ||
+               !dev->driver->err_handler->mmio_enabled)
+-              return 0;
++              goto out;
+       err_handler = dev->driver->err_handler;
+       vote = err_handler->mmio_enabled(dev);
+       result_data->result = merge_result(result_data->result, vote);
++out:
++      device_unlock(&dev->dev);
+       return 0;
+ }
+@@ -296,14 +302,17 @@ static int report_slot_reset(struct pci_
+       struct aer_broadcast_data *result_data;
+       result_data = (struct aer_broadcast_data *) data;
++      device_lock(&dev->dev);
+       if (!dev->driver ||
+               !dev->driver->err_handler ||
+               !dev->driver->err_handler->slot_reset)
+-              return 0;
++              goto out;
+       err_handler = dev->driver->err_handler;
+       vote = err_handler->slot_reset(dev);
+       result_data->result = merge_result(result_data->result, vote);
++out:
++      device_unlock(&dev->dev);
+       return 0;
+ }
+@@ -311,15 +320,18 @@ static int report_resume(struct pci_dev
+ {
+       struct pci_error_handlers *err_handler;
++      device_lock(&dev->dev);
+       dev->error_state = pci_channel_io_normal;
+       if (!dev->driver ||
+               !dev->driver->err_handler ||
+               !dev->driver->err_handler->resume)
+-              return 0;
++              goto out;
+       err_handler = dev->driver->err_handler;
+       err_handler->resume(dev);
++out:
++      device_unlock(&dev->dev);
+       return 0;
+ }
diff --git a/queue-3.6/pci-pm-fix-proc-config-reg-access-for-d3cold-and-bridge-suspending.patch b/queue-3.6/pci-pm-fix-proc-config-reg-access-for-d3cold-and-bridge-suspending.patch
new file mode 100644 (file)
index 0000000..ec67650
--- /dev/null
@@ -0,0 +1,174 @@
+From b3c32c4f9565f93407921c0d8a4458042eb8998e Mon Sep 17 00:00:00 2001
+From: Huang Ying <ying.huang@intel.com>
+Date: Thu, 25 Oct 2012 09:36:03 +0800
+Subject: PCI/PM: Fix proc config reg access for D3cold and bridge suspending
+
+From: Huang Ying <ying.huang@intel.com>
+
+commit b3c32c4f9565f93407921c0d8a4458042eb8998e upstream.
+
+In https://bugzilla.kernel.org/show_bug.cgi?id=48981
+Peter reported that /proc/bus/pci/??/??.? does not work for 3.6.
+This is because the device configuration space registers are
+not accessible if the corresponding parent bridge is suspended or
+the device is put into D3cold state.
+
+This is the same as /sys/bus/pci/devices/0000:??:??.?/config access
+issue.  So the function used to solve sysfs issue is used to solve
+this issue.
+
+This patch moves pci_config_pm_runtime_get()/_put() from pci/pci-sysfs.c
+to pci/pci.c and makes them extern so they can be used by both the
+sysfs and proc paths.
+
+[bhelgaas: changelog, references, reporters]
+Reference: https://bugzilla.kernel.org/show_bug.cgi?id=48981
+Reference: https://bugzilla.kernel.org/show_bug.cgi?id=49031
+Reported-by: Forrest Loomis <cybercyst@gmail.com>
+Reported-by: Peter <lekensteyn@gmail.com>
+Reported-by: Micael Dias <kam1kaz3@gmail.com>
+Signed-off-by: Huang Ying <ying.huang@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pci-sysfs.c |   34 ----------------------------------
+ drivers/pci/pci.c       |   32 ++++++++++++++++++++++++++++++++
+ drivers/pci/pci.h       |    2 ++
+ drivers/pci/proc.c      |    8 ++++++++
+ 4 files changed, 42 insertions(+), 34 deletions(-)
+
+--- a/drivers/pci/pci-sysfs.c
++++ b/drivers/pci/pci-sysfs.c
+@@ -458,40 +458,6 @@ boot_vga_show(struct device *dev, struct
+ }
+ struct device_attribute vga_attr = __ATTR_RO(boot_vga);
+-static void
+-pci_config_pm_runtime_get(struct pci_dev *pdev)
+-{
+-      struct device *dev = &pdev->dev;
+-      struct device *parent = dev->parent;
+-
+-      if (parent)
+-              pm_runtime_get_sync(parent);
+-      pm_runtime_get_noresume(dev);
+-      /*
+-       * pdev->current_state is set to PCI_D3cold during suspending,
+-       * so wait until suspending completes
+-       */
+-      pm_runtime_barrier(dev);
+-      /*
+-       * Only need to resume devices in D3cold, because config
+-       * registers are still accessible for devices suspended but
+-       * not in D3cold.
+-       */
+-      if (pdev->current_state == PCI_D3cold)
+-              pm_runtime_resume(dev);
+-}
+-
+-static void
+-pci_config_pm_runtime_put(struct pci_dev *pdev)
+-{
+-      struct device *dev = &pdev->dev;
+-      struct device *parent = dev->parent;
+-
+-      pm_runtime_put(dev);
+-      if (parent)
+-              pm_runtime_put_sync(parent);
+-}
+-
+ static ssize_t
+ pci_read_config(struct file *filp, struct kobject *kobj,
+               struct bin_attribute *bin_attr,
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -1910,6 +1910,38 @@ bool pci_dev_run_wake(struct pci_dev *de
+ }
+ EXPORT_SYMBOL_GPL(pci_dev_run_wake);
++void pci_config_pm_runtime_get(struct pci_dev *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct device *parent = dev->parent;
++
++      if (parent)
++              pm_runtime_get_sync(parent);
++      pm_runtime_get_noresume(dev);
++      /*
++       * pdev->current_state is set to PCI_D3cold during suspending,
++       * so wait until suspending completes
++       */
++      pm_runtime_barrier(dev);
++      /*
++       * Only need to resume devices in D3cold, because config
++       * registers are still accessible for devices suspended but
++       * not in D3cold.
++       */
++      if (pdev->current_state == PCI_D3cold)
++              pm_runtime_resume(dev);
++}
++
++void pci_config_pm_runtime_put(struct pci_dev *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct device *parent = dev->parent;
++
++      pm_runtime_put(dev);
++      if (parent)
++              pm_runtime_put_sync(parent);
++}
++
+ /**
+  * pci_pm_init - Initialize PM functions of given PCI device
+  * @dev: PCI device to handle.
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(s
+ extern int pci_finish_runtime_suspend(struct pci_dev *dev);
+ extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
+ extern void pci_wakeup_bus(struct pci_bus *bus);
++extern void pci_config_pm_runtime_get(struct pci_dev *dev);
++extern void pci_config_pm_runtime_put(struct pci_dev *dev);
+ extern void pci_pm_init(struct pci_dev *dev);
+ extern void platform_pci_wakeup_init(struct pci_dev *dev);
+ extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
+--- a/drivers/pci/proc.c
++++ b/drivers/pci/proc.c
+@@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, cha
+       if (!access_ok(VERIFY_WRITE, buf, cnt))
+               return -EINVAL;
++      pci_config_pm_runtime_get(dev);
++
+       if ((pos & 1) && cnt) {
+               unsigned char val;
+               pci_user_read_config_byte(dev, pos, &val);
+@@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, cha
+               cnt--;
+       }
++      pci_config_pm_runtime_put(dev);
++
+       *ppos = pos;
+       return nbytes;
+ }
+@@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, co
+       if (!access_ok(VERIFY_READ, buf, cnt))
+               return -EINVAL;
++      pci_config_pm_runtime_get(dev);
++
+       if ((pos & 1) && cnt) {
+               unsigned char val;
+               __get_user(val, buf);
+@@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, co
+               cnt--;
+       }
++      pci_config_pm_runtime_put(dev);
++
+       *ppos = pos;
+       i_size_write(ino, dp->size);
+       return nbytes;
diff --git a/queue-3.6/pci-pm-resume-device-before-shutdown.patch b/queue-3.6/pci-pm-resume-device-before-shutdown.patch
new file mode 100644 (file)
index 0000000..a7ce170
--- /dev/null
@@ -0,0 +1,53 @@
+From 3ff2de9ba1a2e22e548979dbcd46e999b22c93d8 Mon Sep 17 00:00:00 2001
+From: Huang Ying <ying.huang@intel.com>
+Date: Wed, 24 Oct 2012 14:54:14 +0800
+Subject: PCI/PM: Resume device before shutdown
+
+From: Huang Ying <ying.huang@intel.com>
+
+commit 3ff2de9ba1a2e22e548979dbcd46e999b22c93d8 upstream.
+
+Some actions during shutdown need device to be in D0 state, such as
+MSI shutdown etc, so resume device before shutdown.
+
+Without this patch, a device may not be enumerated after a kexec
+because the corresponding bridge is not in D0, so that
+configuration space of the device is not accessible.
+
+Signed-off-by: Huang Ying <ying.huang@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pci-driver.c |   12 ++----------
+ 1 file changed, 2 insertions(+), 10 deletions(-)
+
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -421,6 +421,8 @@ static void pci_device_shutdown(struct d
+       struct pci_dev *pci_dev = to_pci_dev(dev);
+       struct pci_driver *drv = pci_dev->driver;
++      pm_runtime_resume(dev);
++
+       if (drv && drv->shutdown)
+               drv->shutdown(pci_dev);
+       pci_msi_shutdown(pci_dev);
+@@ -431,16 +433,6 @@ static void pci_device_shutdown(struct d
+        * continue to do DMA
+        */
+       pci_disable_device(pci_dev);
+-
+-      /*
+-       * Devices may be enabled to wake up by runtime PM, but they need not
+-       * be supposed to wake up the system from its "power off" state (e.g.
+-       * ACPI S5).  Therefore disable wakeup for all devices that aren't
+-       * supposed to wake up the system at this point.  The state argument
+-       * will be ignored by pci_enable_wake().
+-       */
+-      if (!device_may_wakeup(dev))
+-              pci_enable_wake(pci_dev, PCI_UNKNOWN, false);
+ }
+ #ifdef CONFIG_PM
index 32b3a24649be51e9752e5bf205b33be4408a239f..7d2e724ba8cc12bf1c984ede7369c98ee611a08b 100644 (file)
@@ -1 +1,16 @@
 mm-bugfix-set-current-reclaim_state-to-null-while-returning-from-kswapd.patch
+libata-acpi-fix-null-ptr-derference-in-ata_acpi_dev_handle.patch
+xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch
+mac80211-sync-acccess-to-tx_filtered-ps_tx_buf-queues.patch
+mac80211-don-t-send-null-data-packet-when-not-associated.patch
+mac80211-call-skb_dequeue-ieee80211_free_txskb-instead-of-__skb_queue_purge.patch
+pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch
+pci-pm-resume-device-before-shutdown.patch
+pci-pm-fix-proc-config-reg-access-for-d3cold-and-bridge-suspending.patch
+fanotify-fix-missing-break.patch
+module-fix-out-by-one-error-in-kallsyms.patch
+virtio-don-t-access-index-after-unregister.patch
+cifs-fix-potential-buffer-overrun-in-cifs.idmap-handling-code.patch
+cifs-do-not-lookup-hashed-negative-dentry-in-cifs_atomic_open.patch
+crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch
+arm-at91-at91sam9g45-fix-crypto-peripherals-irq-issue-due-to-sparse-irq-support.patch
diff --git a/queue-3.6/virtio-don-t-access-index-after-unregister.patch b/queue-3.6/virtio-don-t-access-index-after-unregister.patch
new file mode 100644 (file)
index 0000000..03ceac2
--- /dev/null
@@ -0,0 +1,54 @@
+From 237242bddc99041e15a4ca51b8439657cadaff17 Mon Sep 17 00:00:00 2001
+From: Cornelia Huck <cornelia.huck@de.ibm.com>
+Date: Fri, 9 Nov 2012 14:54:12 +1030
+Subject: virtio: Don't access index after unregister.
+
+From: Cornelia Huck <cornelia.huck@de.ibm.com>
+
+commit 237242bddc99041e15a4ca51b8439657cadaff17 upstream.
+
+Virtio wants to release used indices after the corresponding
+virtio device has been unregistered. However, virtio does not
+hold an extra reference, giving up its last reference with
+device_unregister(), making accessing dev->index afterwards
+invalid.
+
+I actually saw problems when testing my (not-yet-merged)
+virtio-ccw code:
+
+- device_add virtio-net,id=xxx
+-> creates device virtio<n> with n>0
+
+- device_del xxx
+-> deletes virtio<n>, but calls ida_simple_remove with an
+   index of 0
+
+- device_add virtio-net,id=xxx
+-> tries to add virtio0, which is still in use...
+
+So let's save the index we want to release before calling
+device_unregister().
+
+Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
+Acked-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
+Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/virtio/virtio.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/virtio/virtio.c
++++ b/drivers/virtio/virtio.c
+@@ -225,8 +225,10 @@ EXPORT_SYMBOL_GPL(register_virtio_device
+ void unregister_virtio_device(struct virtio_device *dev)
+ {
++      int index = dev->index; /* save for after device release */
++
+       device_unregister(&dev->dev);
+-      ida_simple_remove(&virtio_index_ida, dev->index);
++      ida_simple_remove(&virtio_index_ida, index);
+ }
+ EXPORT_SYMBOL_GPL(unregister_virtio_device);
diff --git a/queue-3.6/xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch b/queue-3.6/xfs-drop-buffer-io-reference-when-a-bad-bio-is-built.patch
new file mode 100644 (file)
index 0000000..d404366
--- /dev/null
@@ -0,0 +1,69 @@
+From d69043c42d8c6414fa28ad18d99973aa6c1c2e24 Mon Sep 17 00:00:00 2001
+From: Dave Chinner <dchinner@redhat.com>
+Date: Mon, 12 Nov 2012 22:09:46 +1100
+Subject: xfs: drop buffer io reference when a bad bio is built
+
+From: Dave Chinner <dchinner@redhat.com>
+
+commit d69043c42d8c6414fa28ad18d99973aa6c1c2e24 upstream.
+
+Error handling in xfs_buf_ioapply_map() does not handle IO reference
+counts correctly. We increment the b_io_remaining count before
+building the bio, but then fail to decrement it in the failure case.
+This leads to the buffer never running IO completion and releasing
+the reference that the IO holds, so at unmount we can leak the
+buffer. This leak is captured by this assert failure during unmount:
+
+XFS: Assertion failed: atomic_read(&pag->pag_ref) == 0, file: fs/xfs/xfs_mount.c, line: 273
+
+This is not a new bug - the b_io_remaining accounting has had this
+problem for a long, long time - it's just very hard to get a
+zero length bio being built by this code...
+
+Further, the buffer IO error can be overwritten on a multi-segment
+buffer by subsequent bio completions for partial sections of the
+buffer. Hence we should only set the buffer error status if the
+buffer is not already carrying an error status. This ensures that a
+partial IO error on a multi-segment buffer will not be lost. This
+part of the problem is a regression, however.
+
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Mark Tinguely <tinguely@sgi.com>
+Signed-off-by: Ben Myers <bpm@sgi.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/xfs/xfs_buf.c |   14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/fs/xfs/xfs_buf.c
++++ b/fs/xfs/xfs_buf.c
+@@ -1197,9 +1197,14 @@ xfs_buf_bio_end_io(
+ {
+       xfs_buf_t               *bp = (xfs_buf_t *)bio->bi_private;
+-      xfs_buf_ioerror(bp, -error);
++      /*
++       * don't overwrite existing errors - otherwise we can lose errors on
++       * buffers that require multiple bios to complete.
++       */
++      if (!bp->b_error)
++              xfs_buf_ioerror(bp, -error);
+-      if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
++      if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
+               invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp));
+       _xfs_buf_ioend(bp, 1);
+@@ -1279,6 +1284,11 @@ next_chunk:
+               if (size)
+                       goto next_chunk;
+       } else {
++              /*
++               * This is guaranteed not to be the last io reference count
++               * because the caller (xfs_buf_iorequest) holds a count itself.
++               */
++              atomic_dec(&bp->b_io_remaining);
+               xfs_buf_ioerror(bp, EIO);
+               bio_put(bio);
+       }