]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 24 Jan 2013 00:15:31 +0000 (16:15 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 24 Jan 2013 00:15:31 +0000 (16:15 -0800)
added patches:
pci-aer-pci_get_domain_bus_and_slot-call-missing-required-pci_dev_put.patch
pci-allow-pcie_aspm-force-even-when-fadt-indicates-it-is-unsupported.patch
pci-pciehp-use-per-slot-workqueues-to-avoid-deadlock.patch
pci-shpchp-handle-push-button-event-asynchronously.patch

queue-3.4/pci-aer-pci_get_domain_bus_and_slot-call-missing-required-pci_dev_put.patch [new file with mode: 0644]
queue-3.4/pci-allow-pcie_aspm-force-even-when-fadt-indicates-it-is-unsupported.patch [new file with mode: 0644]
queue-3.4/pci-pciehp-use-per-slot-workqueues-to-avoid-deadlock.patch [new file with mode: 0644]
queue-3.4/pci-shpchp-handle-push-button-event-asynchronously.patch [new file with mode: 0644]
queue-3.4/series

diff --git a/queue-3.4/pci-aer-pci_get_domain_bus_and_slot-call-missing-required-pci_dev_put.patch b/queue-3.4/pci-aer-pci_get_domain_bus_and_slot-call-missing-required-pci_dev_put.patch
new file mode 100644 (file)
index 0000000..c15c273
--- /dev/null
@@ -0,0 +1,32 @@
+From a82b6af37d20bfe6e99a4d890f1cf1d89059929f Mon Sep 17 00:00:00 2001
+From: Betty Dall <betty.dall@hp.com>
+Date: Sun, 13 Jan 2013 15:46:18 -0700
+Subject: PCI/AER: pci_get_domain_bus_and_slot() call missing required pci_dev_put()
+
+From: Betty Dall <betty.dall@hp.com>
+
+commit a82b6af37d20bfe6e99a4d890f1cf1d89059929f upstream.
+
+The function aer_recover_queue() calls pci_get_domain_bus_and_slot(), which
+requires that the caller decrement the reference count with pci_dev_put().
+This patch adds the missing call to pci_dev_put().
+
+Signed-off-by: Betty Dall <betty.dall@hp.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Shuah Khan <shuah.khan@hp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pcie/aer/aerdrv_core.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/pci/pcie/aer/aerdrv_core.c
++++ b/drivers/pci/pcie/aer/aerdrv_core.c
+@@ -637,6 +637,7 @@ static void aer_recover_work_func(struct
+                       continue;
+               }
+               do_recovery(pdev, entry.severity);
++              pci_dev_put(pdev);
+       }
+ }
+ #endif
diff --git a/queue-3.4/pci-allow-pcie_aspm-force-even-when-fadt-indicates-it-is-unsupported.patch b/queue-3.4/pci-allow-pcie_aspm-force-even-when-fadt-indicates-it-is-unsupported.patch
new file mode 100644 (file)
index 0000000..35c5b54
--- /dev/null
@@ -0,0 +1,38 @@
+From 9e16721498b0c3d3ebfa0b503c63d35c0a4c0642 Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Tue, 27 Nov 2012 14:09:40 +0000
+Subject: PCI: Allow pcie_aspm=force even when FADT indicates it is unsupported
+
+From: Colin Ian King <colin.king@canonical.com>
+
+commit 9e16721498b0c3d3ebfa0b503c63d35c0a4c0642 upstream.
+
+Right now using pcie_aspm=force will not enable ASPM if the FADT indicates
+ASPM is unsupported.  However, the semantics of force should probably allow
+for this, especially as they did before 3c076351c4 ("PCI: Rework ASPM
+disable code")
+
+This patch just skips the clearing of any ASPM setup that the firmware has
+carried out on this bus if pcie_aspm=force is being used.
+
+Reference: http://bugs.launchpad.net/bugs/962038
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pcie/aspm.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/pci/pcie/aspm.c
++++ b/drivers/pci/pcie/aspm.c
+@@ -798,6 +798,9 @@ void pcie_clear_aspm(struct pci_bus *bus
+ {
+       struct pci_dev *child;
++      if (aspm_force)
++              return;
++
+       /*
+        * Clear any ASPM setup that the firmware has carried out on this bus
+        */
diff --git a/queue-3.4/pci-pciehp-use-per-slot-workqueues-to-avoid-deadlock.patch b/queue-3.4/pci-pciehp-use-per-slot-workqueues-to-avoid-deadlock.patch
new file mode 100644 (file)
index 0000000..f45fff3
--- /dev/null
@@ -0,0 +1,189 @@
+From c2be6f93b383c873a4f9d521afa49b1b67d06085 Mon Sep 17 00:00:00 2001
+From: Yijing Wang <wangyijing@huawei.com>
+Date: Fri, 11 Jan 2013 10:15:54 +0800
+Subject: PCI: pciehp: Use per-slot workqueues to avoid deadlock
+
+From: Yijing Wang <wangyijing@huawei.com>
+
+commit c2be6f93b383c873a4f9d521afa49b1b67d06085 upstream.
+
+When we have a hotplug-capable PCIe port with a second hotplug-capable
+PCIe port below it, removing the device below the upstream port causes
+a deadlock.
+
+The deadlock happens because we use the pciehp_wq workqueue to run
+pciehp_power_thread(), which uses pciehp_disable_slot() to remove devices
+below the upstream port.  When we remove the downstream PCIe port, we call
+pciehp_remove(), the pciehp driver's .remove() method.  That calls
+flush_workqueue(pciehp_wq), which deadlocks because the
+pciehp_power_thread() work item is still running.
+
+This patch avoids the deadlock by creating a workqueue for every PCIe port
+and removing the single shared workqueue.
+
+Here's the call path that leads to the deadlock:
+
+  pciehp_queue_pushbutton_work
+    queue_work(pciehp_wq)                   # queue pciehp_power_thread
+    ...
+
+  pciehp_power_thread
+    pciehp_disable_slot
+      remove_board
+       pciehp_unconfigure_device
+         pci_stop_and_remove_bus_device
+           ...
+             pciehp_remove                 # pciehp driver .remove method
+               pciehp_release_ctrl
+                 pcie_cleanup_slot
+                   flush_workqueue(pciehp_wq)
+
+This is fairly urgent because it can be caused by simply unplugging a
+Thunderbolt adapter, as reported by Daniel below.
+
+[bhelgaas: changelog]
+Reference: http://lkml.kernel.org/r/CAMVG2ssiRgcTD1bej2tkUUfsWmpL5eNtPcNif9va2-Gzb2u8nQ@mail.gmail.com
+Reported-and-tested-by: Daniel J Blueman <daniel@quora.org>
+Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
+Signed-off-by: Yijing Wang <wangyijing@huawei.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/hotplug/pciehp.h      |    2 +-
+ drivers/pci/hotplug/pciehp_core.c |   11 ++---------
+ drivers/pci/hotplug/pciehp_ctrl.c |    8 ++++----
+ drivers/pci/hotplug/pciehp_hpc.c  |   11 ++++++++++-
+ 4 files changed, 17 insertions(+), 15 deletions(-)
+
+--- a/drivers/pci/hotplug/pciehp.h
++++ b/drivers/pci/hotplug/pciehp.h
+@@ -44,7 +44,6 @@ extern bool pciehp_poll_mode;
+ extern int pciehp_poll_time;
+ extern bool pciehp_debug;
+ extern bool pciehp_force;
+-extern struct workqueue_struct *pciehp_wq;
+ #define dbg(format, arg...)                                           \
+ do {                                                                  \
+@@ -78,6 +77,7 @@ struct slot {
+       struct hotplug_slot *hotplug_slot;
+       struct delayed_work work;       /* work for button event */
+       struct mutex lock;
++      struct workqueue_struct *wq;
+ };
+ struct event_info {
+--- a/drivers/pci/hotplug/pciehp_core.c
++++ b/drivers/pci/hotplug/pciehp_core.c
+@@ -42,7 +42,6 @@ bool pciehp_debug;
+ bool pciehp_poll_mode;
+ int pciehp_poll_time;
+ bool pciehp_force;
+-struct workqueue_struct *pciehp_wq;
+ #define DRIVER_VERSION        "0.4"
+ #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
+@@ -340,18 +339,13 @@ static int __init pcied_init(void)
+ {
+       int retval = 0;
+-      pciehp_wq = alloc_workqueue("pciehp", 0, 0);
+-      if (!pciehp_wq)
+-              return -ENOMEM;
+-
+       pciehp_firmware_init();
+       retval = pcie_port_service_register(&hpdriver_portdrv);
+       dbg("pcie_port_service_register = %d\n", retval);
+       info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+-      if (retval) {
+-              destroy_workqueue(pciehp_wq);
++      if (retval)
+               dbg("Failure to register service\n");
+-      }
++
+       return retval;
+ }
+@@ -359,7 +353,6 @@ static void __exit pcied_cleanup(void)
+ {
+       dbg("unload_pciehpd()\n");
+       pcie_port_service_unregister(&hpdriver_portdrv);
+-      destroy_workqueue(pciehp_wq);
+       info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
+ }
+--- a/drivers/pci/hotplug/pciehp_ctrl.c
++++ b/drivers/pci/hotplug/pciehp_ctrl.c
+@@ -49,7 +49,7 @@ static int queue_interrupt_event(struct
+       info->p_slot = p_slot;
+       INIT_WORK(&info->work, interrupt_event_handler);
+-      queue_work(pciehp_wq, &info->work);
++      queue_work(p_slot->wq, &info->work);
+       return 0;
+ }
+@@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct
+               kfree(info);
+               goto out;
+       }
+-      queue_work(pciehp_wq, &info->work);
++      queue_work(p_slot->wq, &info->work);
+  out:
+       mutex_unlock(&p_slot->lock);
+ }
+@@ -377,7 +377,7 @@ static void handle_button_press_event(st
+               if (ATTN_LED(ctrl))
+                       pciehp_set_attention_status(p_slot, 0);
+-              queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ);
++              queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
+               break;
+       case BLINKINGOFF_STATE:
+       case BLINKINGON_STATE:
+@@ -439,7 +439,7 @@ static void handle_surprise_event(struct
+       else
+               p_slot->state = POWERON_STATE;
+-      queue_work(pciehp_wq, &info->work);
++      queue_work(p_slot->wq, &info->work);
+ }
+ static void interrupt_event_handler(struct work_struct *work)
+--- a/drivers/pci/hotplug/pciehp_hpc.c
++++ b/drivers/pci/hotplug/pciehp_hpc.c
+@@ -874,23 +874,32 @@ static void pcie_shutdown_notification(s
+ static int pcie_init_slot(struct controller *ctrl)
+ {
+       struct slot *slot;
++      char name[32];
+       slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+       if (!slot)
+               return -ENOMEM;
++      snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl));
++      slot->wq = alloc_workqueue(name, 0, 0);
++      if (!slot->wq)
++              goto abort;
++
+       slot->ctrl = ctrl;
+       mutex_init(&slot->lock);
+       INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
+       ctrl->slot = slot;
+       return 0;
++abort:
++      kfree(slot);
++      return -ENOMEM;
+ }
+ static void pcie_cleanup_slot(struct controller *ctrl)
+ {
+       struct slot *slot = ctrl->slot;
+       cancel_delayed_work(&slot->work);
+-      flush_workqueue(pciehp_wq);
++      destroy_workqueue(slot->wq);
+       kfree(slot);
+ }
diff --git a/queue-3.4/pci-shpchp-handle-push-button-event-asynchronously.patch b/queue-3.4/pci-shpchp-handle-push-button-event-asynchronously.patch
new file mode 100644 (file)
index 0000000..8cb9ec6
--- /dev/null
@@ -0,0 +1,95 @@
+From d347e75847c1fb299c97736638f45e6ea39702d4 Mon Sep 17 00:00:00 2001
+From: Bjorn Helgaas <bhelgaas@google.com>
+Date: Fri, 11 Jan 2013 12:07:22 -0700
+Subject: PCI: shpchp: Handle push button event asynchronously
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+commit d347e75847c1fb299c97736638f45e6ea39702d4 upstream.
+
+Use non-ordered workqueue for attention button events.
+
+Attention button events on each slot can be handled asynchronously. So
+we should use non-ordered workqueue. This patch also removes ordered
+workqueue in shpchp as a result.
+
+486b10b9f4 ("PCI: pciehp: Handle push button event asynchronously") made
+the same change to pciehp.  I split this out from a patch by Yijing Wang
+<wangyijing@huawei.com> so we fix one thing at a time and to make the
+shpchp history correspond more closely with the pciehp history.
+
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+CC: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/hotplug/shpchp.h      |    1 -
+ drivers/pci/hotplug/shpchp_core.c |   10 ----------
+ drivers/pci/hotplug/shpchp_ctrl.c |    2 +-
+ 3 files changed, 1 insertion(+), 12 deletions(-)
+
+--- a/drivers/pci/hotplug/shpchp.h
++++ b/drivers/pci/hotplug/shpchp.h
+@@ -47,7 +47,6 @@ extern bool shpchp_poll_mode;
+ extern int shpchp_poll_time;
+ extern bool shpchp_debug;
+ extern struct workqueue_struct *shpchp_wq;
+-extern struct workqueue_struct *shpchp_ordered_wq;
+ #define dbg(format, arg...)                                           \
+ do {                                                                  \
+--- a/drivers/pci/hotplug/shpchp_core.c
++++ b/drivers/pci/hotplug/shpchp_core.c
+@@ -40,7 +40,6 @@ bool shpchp_debug;
+ bool shpchp_poll_mode;
+ int shpchp_poll_time;
+ struct workqueue_struct *shpchp_wq;
+-struct workqueue_struct *shpchp_ordered_wq;
+ #define DRIVER_VERSION        "0.4"
+ #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
+@@ -175,7 +174,6 @@ void cleanup_slots(struct controller *ct
+               list_del(&slot->slot_list);
+               cancel_delayed_work(&slot->work);
+               flush_workqueue(shpchp_wq);
+-              flush_workqueue(shpchp_ordered_wq);
+               pci_hp_deregister(slot->hotplug_slot);
+       }
+ }
+@@ -364,17 +362,10 @@ static int __init shpcd_init(void)
+       if (!shpchp_wq)
+               return -ENOMEM;
+-      shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0);
+-      if (!shpchp_ordered_wq) {
+-              destroy_workqueue(shpchp_wq);
+-              return -ENOMEM;
+-      }
+-
+       retval = pci_register_driver(&shpc_driver);
+       dbg("%s: pci_register_driver = %d\n", __func__, retval);
+       info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+       if (retval) {
+-              destroy_workqueue(shpchp_ordered_wq);
+               destroy_workqueue(shpchp_wq);
+       }
+       return retval;
+@@ -384,7 +375,6 @@ static void __exit shpcd_cleanup(void)
+ {
+       dbg("unload_shpchpd()\n");
+       pci_unregister_driver(&shpc_driver);
+-      destroy_workqueue(shpchp_ordered_wq);
+       destroy_workqueue(shpchp_wq);
+       info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
+ }
+--- a/drivers/pci/hotplug/shpchp_ctrl.c
++++ b/drivers/pci/hotplug/shpchp_ctrl.c
+@@ -456,7 +456,7 @@ void shpchp_queue_pushbutton_work(struct
+               kfree(info);
+               goto out;
+       }
+-      queue_work(shpchp_ordered_wq, &info->work);
++      queue_work(shpchp_wq, &info->work);
+  out:
+       mutex_unlock(&p_slot->lock);
+ }
index 1d09bd65740bd376b3b3a56a3cc9e5dccac2cada..cd51d36b3a0d4a21b636285f26dc5e70a8a91305 100644 (file)
@@ -5,3 +5,7 @@ evm-checking-if-removexattr-is-not-a-null.patch
 ptrace-introduce-signal_wake_up_state-and-ptrace_signal_wake_up.patch
 ptrace-ensure-arch_ptrace-ptrace_request-can-never-race-with-sigkill.patch
 wake_up_process-should-be-never-used-to-wakeup-a-task_stopped-traced-task.patch
+pci-aer-pci_get_domain_bus_and_slot-call-missing-required-pci_dev_put.patch
+pci-allow-pcie_aspm-force-even-when-fadt-indicates-it-is-unsupported.patch
+pci-pciehp-use-per-slot-workqueues-to-avoid-deadlock.patch
+pci-shpchp-handle-push-button-event-asynchronously.patch