]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.3-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 May 2012 02:24:39 +0000 (19:24 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 May 2012 02:24:39 +0000 (19:24 -0700)
added patches:
alsa-hda-idt-fix-power-map-for-speaker-pins-with-some-hp-laptops.patch
namespaces-pid_ns-fix-leakage-on-fork-failure.patch
usbnet-fix-skb-traversing-races-during-unlink-v2.patch

queue-3.3/alsa-hda-idt-fix-power-map-for-speaker-pins-with-some-hp-laptops.patch [new file with mode: 0644]
queue-3.3/namespaces-pid_ns-fix-leakage-on-fork-failure.patch [new file with mode: 0644]
queue-3.3/series
queue-3.3/usbnet-fix-skb-traversing-races-during-unlink-v2.patch [new file with mode: 0644]

diff --git a/queue-3.3/alsa-hda-idt-fix-power-map-for-speaker-pins-with-some-hp-laptops.patch b/queue-3.3/alsa-hda-idt-fix-power-map-for-speaker-pins-with-some-hp-laptops.patch
new file mode 100644 (file)
index 0000000..3a5b937
--- /dev/null
@@ -0,0 +1,43 @@
+From b0791dda813c179e539b0fc1ecd3f5f30f2571e2 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 15 May 2012 08:07:31 +0200
+Subject: ALSA: hda/idt - Fix power-map for speaker-pins with some HP laptops
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit b0791dda813c179e539b0fc1ecd3f5f30f2571e2 upstream.
+
+BIOS on some HP laptops don't set the speaker-pins as fixed but expose
+as jacks, and this confuses the driver as if these pins are
+jack-detectable.  As a result, the machine doesn't get sounds from
+speakers because the driver prepares the power-map update via jack
+unsol events which never come up in reality.  The bug was introduced
+in some time in 3.2 for enabling the power-mapping feature.
+
+This patch fixes the problem by replacing the check of the persistent
+power-map bits with a proper is_jack_detectable() call.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43240
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_sigmatel.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -4394,9 +4394,9 @@ static int stac92xx_init(struct hda_code
+               def_conf = get_defcfg_connect(def_conf);
+               /* skip any ports that don't have jacks since presence
+                * detection is useless */
+-              if (def_conf != AC_JACK_PORT_COMPLEX) {
+-                      if (def_conf != AC_JACK_PORT_NONE)
+-                              stac_toggle_power_map(codec, nid, 1);
++              if (def_conf != AC_JACK_PORT_NONE &&
++                  !is_jack_detectable(codec, nid)) {
++                      stac_toggle_power_map(codec, nid, 1);
+                       continue;
+               }
+               if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) {
diff --git a/queue-3.3/namespaces-pid_ns-fix-leakage-on-fork-failure.patch b/queue-3.3/namespaces-pid_ns-fix-leakage-on-fork-failure.patch
new file mode 100644 (file)
index 0000000..c2b2d9f
--- /dev/null
@@ -0,0 +1,47 @@
+From 5e2bf0142231194d36fdc9596b36a261ed2b9fe7 Mon Sep 17 00:00:00 2001
+From: Mike Galbraith <efault@gmx.de>
+Date: Thu, 10 May 2012 13:01:45 -0700
+Subject: namespaces, pid_ns: fix leakage on fork() failure
+
+From: Mike Galbraith <efault@gmx.de>
+
+commit 5e2bf0142231194d36fdc9596b36a261ed2b9fe7 upstream.
+
+Fork() failure post namespace creation for a child cloned with
+CLONE_NEWPID leaks pid_namespace/mnt_cache due to proc being mounted
+during creation, but not unmounted during cleanup.  Call
+pid_ns_release_proc() during cleanup.
+
+Signed-off-by: Mike Galbraith <efault@gmx.de>
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Pavel Emelyanov <xemul@parallels.com>
+Cc: Cyrill Gorcunov <gorcunov@openvz.org>
+Cc: Louis Rilling <louis.rilling@kerlabs.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>
+
+---
+ kernel/fork.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -47,6 +47,7 @@
+ #include <linux/audit.h>
+ #include <linux/memcontrol.h>
+ #include <linux/ftrace.h>
++#include <linux/proc_fs.h>
+ #include <linux/profile.h>
+ #include <linux/rmap.h>
+ #include <linux/ksm.h>
+@@ -1438,6 +1439,8 @@ bad_fork_cleanup_io:
+       if (p->io_context)
+               exit_io_context(p);
+ bad_fork_cleanup_namespaces:
++      if (unlikely(clone_flags & CLONE_NEWPID))
++              pid_ns_release_proc(p->nsproxy->pid_ns);
+       exit_task_namespaces(p);
+ bad_fork_cleanup_mm:
+       if (p->mm)
index dfeb6a9f8feb0cc24874ac21d706642777ea4f75..bcf3b63fa543d58810ab7c6e418146f740d92651 100644 (file)
@@ -1,3 +1,6 @@
 alsa-echoaudio-remove-incorrect-part-of-assertion.patch
 alsa-hda-lessen-cpu-usage-when-waiting-for-chip-to-respond.patch
 alsa-hda-realtek-add-missing-cd-input-pin-for-msi-7350-mobo.patch
+alsa-hda-idt-fix-power-map-for-speaker-pins-with-some-hp-laptops.patch
+usbnet-fix-skb-traversing-races-during-unlink-v2.patch
+namespaces-pid_ns-fix-leakage-on-fork-failure.patch
diff --git a/queue-3.3/usbnet-fix-skb-traversing-races-during-unlink-v2.patch b/queue-3.3/usbnet-fix-skb-traversing-races-during-unlink-v2.patch
new file mode 100644 (file)
index 0000000..72a176a
--- /dev/null
@@ -0,0 +1,218 @@
+From 5b6e9bcdeb65634b4ad604eb4536404bbfc62cfa Mon Sep 17 00:00:00 2001
+From: Ming Lei <tom.leiming@gmail.com>
+Date: Thu, 26 Apr 2012 11:33:46 +0800
+Subject: usbnet: fix skb traversing races during unlink(v2)
+
+From: Ming Lei <tom.leiming@gmail.com>
+
+commit 5b6e9bcdeb65634b4ad604eb4536404bbfc62cfa upstream.
+
+Commit 4231d47e6fe69f061f96c98c30eaf9fb4c14b96d(net/usbnet: avoid
+recursive locking in usbnet_stop()) fixes the recursive locking
+problem by releasing the skb queue lock before unlink, but may
+cause skb traversing races:
+       - after URB is unlinked and the queue lock is released,
+       the refered skb and skb->next may be moved to done queue,
+       even be released
+       - in skb_queue_walk_safe, the next skb is still obtained
+       by next pointer of the last skb
+       - so maybe trigger oops or other problems
+
+This patch extends the usage of entry->state to describe 'start_unlink'
+state, so always holding the queue(rx/tx) lock to change the state if
+the referd skb is in rx or tx queue because we need to know if the
+refered urb has been started unlinking in unlink_urbs.
+
+The other part of this patch is based on Huajun's patch:
+always traverse from head of the tx/rx queue to get skb which is
+to be unlinked but not been started unlinking.
+
+Signed-off-by: Huajun Li <huajun.li.lee@gmail.com>
+Signed-off-by: Ming Lei <tom.leiming@gmail.com>
+Cc: Oliver Neukum <oneukum@suse.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/usb/usbnet.c   |   54 +++++++++++++++++++++++++++++++--------------
+ include/linux/usb/usbnet.h |    3 +-
+ 2 files changed, 40 insertions(+), 17 deletions(-)
+
+--- a/drivers/net/usb/usbnet.c
++++ b/drivers/net/usb/usbnet.c
+@@ -281,17 +281,32 @@ int usbnet_change_mtu (struct net_device
+ }
+ EXPORT_SYMBOL_GPL(usbnet_change_mtu);
++/* The caller must hold list->lock */
++static void __usbnet_queue_skb(struct sk_buff_head *list,
++                      struct sk_buff *newsk, enum skb_state state)
++{
++      struct skb_data *entry = (struct skb_data *) newsk->cb;
++
++      __skb_queue_tail(list, newsk);
++      entry->state = state;
++}
++
+ /*-------------------------------------------------------------------------*/
+ /* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from
+  * completion callbacks.  2.5 should have fixed those bugs...
+  */
+-static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list)
++static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
++              struct sk_buff_head *list, enum skb_state state)
+ {
+       unsigned long           flags;
++      enum skb_state          old_state;
++      struct skb_data *entry = (struct skb_data *) skb->cb;
+       spin_lock_irqsave(&list->lock, flags);
++      old_state = entry->state;
++      entry->state = state;
+       __skb_unlink(skb, list);
+       spin_unlock(&list->lock);
+       spin_lock(&dev->done.lock);
+@@ -299,6 +314,7 @@ static void defer_bh(struct usbnet *dev,
+       if (dev->done.qlen == 1)
+               tasklet_schedule(&dev->bh);
+       spin_unlock_irqrestore(&dev->done.lock, flags);
++      return old_state;
+ }
+ /* some work can't be done in tasklets, so we use keventd
+@@ -339,7 +355,6 @@ static int rx_submit (struct usbnet *dev
+       entry = (struct skb_data *) skb->cb;
+       entry->urb = urb;
+       entry->dev = dev;
+-      entry->state = rx_start;
+       entry->length = 0;
+       usb_fill_bulk_urb (urb, dev->udev, dev->in,
+@@ -371,7 +386,7 @@ static int rx_submit (struct usbnet *dev
+                       tasklet_schedule (&dev->bh);
+                       break;
+               case 0:
+-                      __skb_queue_tail (&dev->rxq, skb);
++                      __usbnet_queue_skb(&dev->rxq, skb, rx_start);
+               }
+       } else {
+               netif_dbg(dev, ifdown, dev->net, "rx: stopped\n");
+@@ -422,16 +437,17 @@ static void rx_complete (struct urb *urb
+       struct skb_data         *entry = (struct skb_data *) skb->cb;
+       struct usbnet           *dev = entry->dev;
+       int                     urb_status = urb->status;
++      enum skb_state          state;
+       skb_put (skb, urb->actual_length);
+-      entry->state = rx_done;
++      state = rx_done;
+       entry->urb = NULL;
+       switch (urb_status) {
+       /* success */
+       case 0:
+               if (skb->len < dev->net->hard_header_len) {
+-                      entry->state = rx_cleanup;
++                      state = rx_cleanup;
+                       dev->net->stats.rx_errors++;
+                       dev->net->stats.rx_length_errors++;
+                       netif_dbg(dev, rx_err, dev->net,
+@@ -470,7 +486,7 @@ static void rx_complete (struct urb *urb
+                                 "rx throttle %d\n", urb_status);
+               }
+ block:
+-              entry->state = rx_cleanup;
++              state = rx_cleanup;
+               entry->urb = urb;
+               urb = NULL;
+               break;
+@@ -481,17 +497,18 @@ block:
+               // FALLTHROUGH
+       default:
+-              entry->state = rx_cleanup;
++              state = rx_cleanup;
+               dev->net->stats.rx_errors++;
+               netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status);
+               break;
+       }
+-      defer_bh(dev, skb, &dev->rxq);
++      state = defer_bh(dev, skb, &dev->rxq, state);
+       if (urb) {
+               if (netif_running (dev->net) &&
+-                  !test_bit (EVENT_RX_HALT, &dev->flags)) {
++                  !test_bit (EVENT_RX_HALT, &dev->flags) &&
++                  state != unlink_start) {
+                       rx_submit (dev, urb, GFP_ATOMIC);
+                       return;
+               }
+@@ -577,16 +594,23 @@ EXPORT_SYMBOL_GPL(usbnet_purge_paused_rx
+ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
+ {
+       unsigned long           flags;
+-      struct sk_buff          *skb, *skbnext;
++      struct sk_buff          *skb;
+       int                     count = 0;
+       spin_lock_irqsave (&q->lock, flags);
+-      skb_queue_walk_safe(q, skb, skbnext) {
++      while (!skb_queue_empty(q)) {
+               struct skb_data         *entry;
+               struct urb              *urb;
+               int                     retval;
+-              entry = (struct skb_data *) skb->cb;
++              skb_queue_walk(q, skb) {
++                      entry = (struct skb_data *) skb->cb;
++                      if (entry->state != unlink_start)
++                              goto found;
++              }
++              break;
++found:
++              entry->state = unlink_start;
+               urb = entry->urb;
+               /*
+@@ -1037,8 +1061,7 @@ static void tx_complete (struct urb *urb
+       }
+       usb_autopm_put_interface_async(dev->intf);
+-      entry->state = tx_done;
+-      defer_bh(dev, skb, &dev->txq);
++      (void) defer_bh(dev, skb, &dev->txq, tx_done);
+ }
+ /*-------------------------------------------------------------------------*/
+@@ -1094,7 +1117,6 @@ netdev_tx_t usbnet_start_xmit (struct sk
+       entry = (struct skb_data *) skb->cb;
+       entry->urb = urb;
+       entry->dev = dev;
+-      entry->state = tx_start;
+       entry->length = length;
+       usb_fill_bulk_urb (urb, dev->udev, dev->out,
+@@ -1153,7 +1175,7 @@ netdev_tx_t usbnet_start_xmit (struct sk
+               break;
+       case 0:
+               net->trans_start = jiffies;
+-              __skb_queue_tail (&dev->txq, skb);
++              __usbnet_queue_skb(&dev->txq, skb, tx_start);
+               if (dev->txq.qlen >= TX_QLEN (dev))
+                       netif_stop_queue (net);
+       }
+--- a/include/linux/usb/usbnet.h
++++ b/include/linux/usb/usbnet.h
+@@ -191,7 +191,8 @@ extern void usbnet_cdc_status(struct usb
+ enum skb_state {
+       illegal = 0,
+       tx_start, tx_done,
+-      rx_start, rx_done, rx_cleanup
++      rx_start, rx_done, rx_cleanup,
++      unlink_start
+ };
+ struct skb_data {     /* skb->cb is one of these */