]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 22 Aug 2013 21:55:55 +0000 (14:55 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 22 Aug 2013 21:55:55 +0000 (14:55 -0700)
added patches:
acpi-add-_sta-evaluation-at-do_acpi_find_child.patch
acpi-try-harder-to-resolve-_adr-collisions-for-bridges.patch
mac80211-don-t-wait-for-tx-status-forever.patch

queue-3.10/acpi-add-_sta-evaluation-at-do_acpi_find_child.patch [new file with mode: 0644]
queue-3.10/acpi-try-harder-to-resolve-_adr-collisions-for-bridges.patch [new file with mode: 0644]
queue-3.10/mac80211-don-t-wait-for-tx-status-forever.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/acpi-add-_sta-evaluation-at-do_acpi_find_child.patch b/queue-3.10/acpi-add-_sta-evaluation-at-do_acpi_find_child.patch
new file mode 100644 (file)
index 0000000..a2230ad
--- /dev/null
@@ -0,0 +1,60 @@
+From c7d9ca90aa9497f0b6e301ec67c52dd4b57a7852 Mon Sep 17 00:00:00 2001
+From: Jeff Wu <zlinuxkernel@gmail.com>
+Date: Wed, 29 May 2013 06:31:30 +0000
+Subject: ACPI: add _STA evaluation at do_acpi_find_child()
+
+From: Jeff Wu <zlinuxkernel@gmail.com>
+
+commit c7d9ca90aa9497f0b6e301ec67c52dd4b57a7852 upstream.
+
+Once do_acpi_find_child() has found the first matching handle, it
+makes the acpi_get_child() loop stop and return that handle.  On some
+platforms, though, there are multiple devices with the same value of
+"_ADR" in the same namespace scope, and if one of them is enabled,
+the others will be disabled.  For example:
+
+ Address : 0x1FFFF ; path : SB_PCI0.SATA.DEV0
+ Address : 0x1FFFF ; path : SB_PCI0.SATA.DEV1
+ Address : 0x1FFFF ; path : SB_PCI0.SATA.DEV2
+
+If DEV0 and DEV1 are disabled and DEV2 is enabled, the handle of DEV2
+should be returned, but actually the function always returns the
+handle of DEV0.
+
+To address that issue, make do_acpi_find_child() evaluate _STA to
+check the device status.  If a matching device object exists, but is
+disabled, acpi_get_child() will continue to walk the namespace in the
+hope of finding an enabled one.  If one is found, its handle will be
+returned, but otherwise the function will return the handle of the
+disabled object found before (in case it is enabled going forward).
+
+[rjw: Changelog]
+Signed-off-by: Jeff Wu <zlinuxkernel@gmail.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Cc: Peter Wu <lekensteyn@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/glue.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/acpi/glue.c
++++ b/drivers/acpi/glue.c
+@@ -81,13 +81,15 @@ static struct acpi_bus_type *acpi_get_bu
+ static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used,
+                                     void *addr_p, void **ret_p)
+ {
+-      unsigned long long addr;
++      unsigned long long addr, sta;
+       acpi_status status;
+       status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr);
+       if (ACPI_SUCCESS(status) && addr == *((u64 *)addr_p)) {
+               *ret_p = handle;
+-              return AE_CTRL_TERMINATE;
++              status = acpi_bus_get_status_handle(handle, &sta);
++              if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_ENABLED))
++                      return AE_CTRL_TERMINATE;
+       }
+       return AE_OK;
+ }
diff --git a/queue-3.10/acpi-try-harder-to-resolve-_adr-collisions-for-bridges.patch b/queue-3.10/acpi-try-harder-to-resolve-_adr-collisions-for-bridges.patch
new file mode 100644 (file)
index 0000000..97ec7f9
--- /dev/null
@@ -0,0 +1,243 @@
+From 60f75b8e97daf4a39790a20d962cb861b9220af5 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Wed, 7 Aug 2013 22:55:00 +0200
+Subject: ACPI: Try harder to resolve _ADR collisions for bridges
+
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+
+commit 60f75b8e97daf4a39790a20d962cb861b9220af5 upstream.
+
+In theory, under a given ACPI namespace node there should be only
+one child device object with _ADR whose value matches a given bus
+address exactly.  In practice, however, there are systems in which
+multiple child device objects under a given parent have _ADR matching
+exactly the same address.  In those cases we use _STA to determine
+which of the multiple matching devices is enabled, since some systems
+are known to indicate which ACPI device object to associate with the
+given physical (usually PCI) device this way.
+
+Unfortunately, as it turns out, there are systems in which many
+device objects under the same parent have _ADR matching exactly the
+same bus address and none of them has _STA, in which case they all
+should be regarded as enabled according to the spec.  Still, if
+those device objects are supposed to represent bridges (e.g. this
+is the case for device objects corresponding to PCIe ports), we can
+try harder and skip the ones that have no child device objects in the
+ACPI namespace.  With luck, we can avoid using device objects that we
+are not expected to use this way.
+
+Although this only works for bridges whose children also have ACPI
+namespace representation, it is sufficient to address graphics
+adapter detection issues on some systems, so rework the code finding
+a matching device ACPI handle for a given bus address to implement
+this idea.
+
+Introduce a new function, acpi_find_child(), taking three arguments:
+the ACPI handle of the device's parent, a bus address suitable for
+the device's bus type and a bool indicating if the device is a
+bridge and make it work as outlined above.  Reimplement the function
+currently used for this purpose, acpi_get_child(), as a call to
+acpi_find_child() with the last argument set to 'false' and make
+the PCI subsystem use acpi_find_child() with the bridge information
+passed as the last argument to it.  [Lan Tianyu notices that it is
+not sufficient to use pci_is_bridge() for that, because the device's
+subordinate pointer hasn't been set yet at this point, so use
+hdr_type instead.]
+
+This change fixes a regression introduced inadvertently by commit
+33f767d (ACPI: Rework acpi_get_child() to be more efficient) which
+overlooked the fact that for acpi_walk_namespace() "post-order" means
+"after all children have been visited" rather than "on the way back",
+so for device objects without children and for namespace walks of
+depth 1, as in the acpi_get_child() case, the "post-order" callbacks
+ordering is actually the same as the ordering of "pre-order" ones.
+Since that commit changed the namespace walk in acpi_get_child() to
+terminate after finding the first matching object instead of going
+through all of them and returning the last one, it effectively
+changed the result returned by that function in some rare cases and
+that led to problems (the switch from a "pre-order" to a "post-order"
+callback was supposed to prevent that from happening, but it was
+ineffective).
+
+As it turns out, the systems where the change made by commit
+33f767d actually matters are those where there are multiple ACPI
+device objects representing the same PCIe port (which effectively
+is a bridge).  Moreover, only one of them, and the one we are
+expected to use, has child device objects in the ACPI namespace,
+so the regression can be addressed as described above.
+
+References: https://bugzilla.kernel.org/show_bug.cgi?id=60561
+Reported-by: Peter Wu <lekensteyn@gmail.com>
+Tested-by: Vladimir Lalov <mail@vlalov.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Peter Wu <lekensteyn@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/glue.c     |   99 +++++++++++++++++++++++++++++++++++++++---------
+ drivers/pci/pci-acpi.c  |   15 +++++--
+ include/acpi/acpi_bus.h |    6 ++
+ 3 files changed, 98 insertions(+), 22 deletions(-)
+
+--- a/drivers/acpi/glue.c
++++ b/drivers/acpi/glue.c
+@@ -78,34 +78,99 @@ static struct acpi_bus_type *acpi_get_bu
+       return ret;
+ }
+-static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used,
+-                                    void *addr_p, void **ret_p)
++static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used,
++                                void *not_used, void **ret_p)
+ {
+-      unsigned long long addr, sta;
+-      acpi_status status;
++      struct acpi_device *adev = NULL;
+-      status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr);
+-      if (ACPI_SUCCESS(status) && addr == *((u64 *)addr_p)) {
++      acpi_bus_get_device(handle, &adev);
++      if (adev) {
+               *ret_p = handle;
+-              status = acpi_bus_get_status_handle(handle, &sta);
+-              if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_ENABLED))
+-                      return AE_CTRL_TERMINATE;
++              return AE_CTRL_TERMINATE;
+       }
+       return AE_OK;
+ }
+-acpi_handle acpi_get_child(acpi_handle parent, u64 address)
++static bool acpi_extra_checks_passed(acpi_handle handle, bool is_bridge)
+ {
+-      void *ret = NULL;
++      unsigned long long sta;
++      acpi_status status;
+-      if (!parent)
+-              return NULL;
++      status = acpi_bus_get_status_handle(handle, &sta);
++      if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED))
++              return false;
++
++      if (is_bridge) {
++              void *test = NULL;
++
++              /* Check if this object has at least one child device. */
++              acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
++                                  acpi_dev_present, NULL, NULL, &test);
++              return !!test;
++      }
++      return true;
++}
+-      acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, NULL,
+-                          do_acpi_find_child, &address, &ret);
+-      return (acpi_handle)ret;
++struct find_child_context {
++      u64 addr;
++      bool is_bridge;
++      acpi_handle ret;
++      bool ret_checked;
++};
++
++static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used,
++                               void *data, void **not_used)
++{
++      struct find_child_context *context = data;
++      unsigned long long addr;
++      acpi_status status;
++
++      status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr);
++      if (ACPI_FAILURE(status) || addr != context->addr)
++              return AE_OK;
++
++      if (!context->ret) {
++              /* This is the first matching object.  Save its handle. */
++              context->ret = handle;
++              return AE_OK;
++      }
++      /*
++       * There is more than one matching object with the same _ADR value.
++       * That really is unexpected, so we are kind of beyond the scope of the
++       * spec here.  We have to choose which one to return, though.
++       *
++       * First, check if the previously found object is good enough and return
++       * its handle if so.  Second, check the same for the object that we've
++       * just found.
++       */
++      if (!context->ret_checked) {
++              if (acpi_extra_checks_passed(context->ret, context->is_bridge))
++                      return AE_CTRL_TERMINATE;
++              else
++                      context->ret_checked = true;
++      }
++      if (acpi_extra_checks_passed(handle, context->is_bridge)) {
++              context->ret = handle;
++              return AE_CTRL_TERMINATE;
++      }
++      return AE_OK;
++}
++
++acpi_handle acpi_find_child(acpi_handle parent, u64 addr, bool is_bridge)
++{
++      if (parent) {
++              struct find_child_context context = {
++                      .addr = addr,
++                      .is_bridge = is_bridge,
++              };
++
++              acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, do_find_child,
++                                  NULL, &context, NULL);
++              return context.ret;
++      }
++      return NULL;
+ }
+-EXPORT_SYMBOL(acpi_get_child);
++EXPORT_SYMBOL_GPL(acpi_find_child);
+ static int acpi_bind_one(struct device *dev, acpi_handle handle)
+ {
+--- a/drivers/pci/pci-acpi.c
++++ b/drivers/pci/pci-acpi.c
+@@ -317,13 +317,20 @@ void acpi_pci_remove_bus(struct pci_bus
+ /* ACPI bus type */
+ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
+ {
+-      struct pci_dev * pci_dev;
+-      u64     addr;
++      struct pci_dev *pci_dev = to_pci_dev(dev);
++      bool is_bridge;
++      u64 addr;
+-      pci_dev = to_pci_dev(dev);
++      /*
++       * pci_is_bridge() is not suitable here, because pci_dev->subordinate
++       * is set only after acpi_pci_find_device() has been called for the
++       * given device.
++       */
++      is_bridge = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE
++                      || pci_dev->hdr_type == PCI_HEADER_TYPE_CARDBUS;
+       /* Please ref to ACPI spec for the syntax of _ADR */
+       addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
+-      *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
++      *handle = acpi_find_child(ACPI_HANDLE(dev->parent), addr, is_bridge);
+       if (!*handle)
+               return -ENODEV;
+       return 0;
+--- a/include/acpi/acpi_bus.h
++++ b/include/acpi/acpi_bus.h
+@@ -455,7 +455,11 @@ struct acpi_pci_root {
+ };
+ /* helper */
+-acpi_handle acpi_get_child(acpi_handle, u64);
++acpi_handle acpi_find_child(acpi_handle, u64, bool);
++static inline acpi_handle acpi_get_child(acpi_handle handle, u64 addr)
++{
++      return acpi_find_child(handle, addr, false);
++}
+ int acpi_is_root_bridge(acpi_handle);
+ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
+ #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev))
diff --git a/queue-3.10/mac80211-don-t-wait-for-tx-status-forever.patch b/queue-3.10/mac80211-don-t-wait-for-tx-status-forever.patch
new file mode 100644 (file)
index 0000000..ce68dda
--- /dev/null
@@ -0,0 +1,67 @@
+From cb236d2d713cff83d024a82b836757d9e2b50715 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Mon, 29 Jul 2013 23:07:43 +0200
+Subject: mac80211: don't wait for TX status forever
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit cb236d2d713cff83d024a82b836757d9e2b50715 upstream.
+
+TX status notification can get lost, or the frames could
+get stuck on the queue, so don't wait for the callback
+from the driver forever and instead time out after half
+a second.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ net/mac80211/mlme.c |   15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -31,10 +31,12 @@
+ #include "led.h"
+ #define IEEE80211_AUTH_TIMEOUT                (HZ / 5)
++#define IEEE80211_AUTH_TIMEOUT_LONG   (HZ / 2)
+ #define IEEE80211_AUTH_TIMEOUT_SHORT  (HZ / 10)
+ #define IEEE80211_AUTH_MAX_TRIES      3
+ #define IEEE80211_AUTH_WAIT_ASSOC     (HZ * 5)
+ #define IEEE80211_ASSOC_TIMEOUT               (HZ / 5)
++#define IEEE80211_ASSOC_TIMEOUT_LONG  (HZ / 2)
+ #define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10)
+ #define IEEE80211_ASSOC_MAX_TRIES     3
+@@ -3470,10 +3472,13 @@ static int ieee80211_probe_auth(struct i
+       if (tx_flags == 0) {
+               auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
+-              ifmgd->auth_data->timeout_started = true;
++              auth_data->timeout_started = true;
+               run_again(ifmgd, auth_data->timeout);
+       } else {
+-              auth_data->timeout_started = false;
++              auth_data->timeout =
++                      round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG);
++              auth_data->timeout_started = true;
++              run_again(ifmgd, auth_data->timeout);
+       }
+       return 0;
+@@ -3510,7 +3515,11 @@ static int ieee80211_do_assoc(struct iee
+               assoc_data->timeout_started = true;
+               run_again(&sdata->u.mgd, assoc_data->timeout);
+       } else {
+-              assoc_data->timeout_started = false;
++              assoc_data->timeout =
++                      round_jiffies_up(jiffies +
++                                       IEEE80211_ASSOC_TIMEOUT_LONG);
++              assoc_data->timeout_started = true;
++              run_again(&sdata->u.mgd, assoc_data->timeout);
+       }
+       return 0;
index 630b59faf9c0db62d6499bd8cded637e22011481..71542fe5dafbc15707fe0156a8e74773f6dc2123 100644 (file)
@@ -1 +1,4 @@
 kvm-s390-move-kvm_guest_enter-exit-closer-to-sie.patch
+mac80211-don-t-wait-for-tx-status-forever.patch
+acpi-add-_sta-evaluation-at-do_acpi_find_child.patch
+acpi-try-harder-to-resolve-_adr-collisions-for-bridges.patch