Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0bbd6424c55f0ab9e7fcd6a851bc49e265259ff5
Commit:     0bbd6424c55f0ab9e7fcd6a851bc49e265259ff5
Parent:     9ef2241b18266d75319e7d66156243bd9010be44
Author:     Gary Hade <[EMAIL PROTECTED]>
AuthorDate: Thu Jul 5 11:10:48 2007 -0700
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Wed Jul 11 16:02:13 2007 -0700

    PCI: hotplug: acpiphp: avoid acpiphp "cannot get bridge info" PCI hotplug 
failure
    
    On some systems, the ACPI bus check event can reference a bridge that is
    higher in the ACPI hierarchy than the bridge immediately above the
    hotplug PCI slot into which an adapter was just inserted.  The current
    'acpiphp' code expects the bus check event to reference the bridge
    immediately above the slot that received the adapter so the hotplug
    operation can fail on these systems with the message "acpiphp_glue:
    cannot get bridge info".  This change fixes the problem by
    re-enumerating all slots that lie below the bridge referenced by the bus
    check event, including those slots that may be located under lower level
    PCI-to-PCI bridge(s).
    
    Signed-off-by: Gary Hade <[EMAIL PROTECTED]>
    Cc: <[EMAIL PROTECTED]>
    Signed-off-by: Kristen Carlson Accardi <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/pci/hotplug/acpiphp_glue.c |   48 ++++++++++++++++++++++++++++++++++-
 1 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/hotplug/acpiphp_glue.c 
b/drivers/pci/hotplug/acpiphp_glue.c
index 72ec4a2..1e125b5 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -1505,6 +1505,37 @@ static void handle_bridge_insertion(acpi_handle handle, 
u32 type)
  * ACPI event handlers
  */
 
+static acpi_status
+count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       int *count = (int *)context;
+       struct acpiphp_bridge *bridge;
+
+       bridge = acpiphp_handle_to_bridge(handle);
+       if (bridge)
+               (*count)++;
+       return AE_OK ;
+}
+
+static acpi_status
+check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       struct acpiphp_bridge *bridge;
+       char objname[64];
+       struct acpi_buffer buffer = { .length = sizeof(objname),
+                                     .pointer = objname };
+
+       bridge = acpiphp_handle_to_bridge(handle);
+       if (bridge) {
+               acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+               dbg("%s: re-enumerating slots under %s\n",
+                       __FUNCTION__, objname);
+               acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+               acpiphp_check_bridge(bridge);
+       }
+       return AE_OK ;
+}
+
 /**
  * handle_hotplug_event_bridge - handle ACPI event on bridges
  *
@@ -1522,6 +1553,7 @@ static void handle_hotplug_event_bridge(acpi_handle 
handle, u32 type, void *cont
        struct acpi_buffer buffer = { .length = sizeof(objname),
                                      .pointer = objname };
        struct acpi_device *device;
+       int num_sub_bridges = 0;
 
        if (acpi_bus_get_device(handle, &device)) {
                /* This bridge must have just been physically inserted */
@@ -1530,7 +1562,12 @@ static void handle_hotplug_event_bridge(acpi_handle 
handle, u32 type, void *cont
        }
 
        bridge = acpiphp_handle_to_bridge(handle);
-       if (!bridge) {
+       if (type == ACPI_NOTIFY_BUS_CHECK) {
+               acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
+                       count_sub_bridges, &num_sub_bridges, NULL);
+       }
+
+       if (!bridge && !num_sub_bridges) {
                err("cannot get bridge info\n");
                return;
        }
@@ -1541,7 +1578,14 @@ static void handle_hotplug_event_bridge(acpi_handle 
handle, u32 type, void *cont
        case ACPI_NOTIFY_BUS_CHECK:
                /* bus re-enumerate */
                dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
-               acpiphp_check_bridge(bridge);
+               if (bridge) {
+                       dbg("%s: re-enumerating slots under %s\n",
+                               __FUNCTION__, objname);
+                       acpiphp_check_bridge(bridge);
+               }
+               if (num_sub_bridges)
+                       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+                               ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL);
                break;
 
        case ACPI_NOTIFY_DEVICE_CHECK:
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to