--- /dev/null
+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,
+ },
+ };
--- /dev/null
+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);
+
--- /dev/null
+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;
+ }
--- /dev/null
+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;
--- /dev/null
+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:
--- /dev/null
+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);
+
--- /dev/null
+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);
++ }
+ }
+
+ /*
--- /dev/null
+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);
+ }
--- /dev/null
+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;
+ }
--- /dev/null
+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;
+ }
--- /dev/null
+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;
+ }
+
--- /dev/null
+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;
--- /dev/null
+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
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
--- /dev/null
+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);
+
--- /dev/null
+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);
+ }