Hi,

Li: Could you double check and comment on that one please. It works fine
here on a Lenovo ThinkPad...

These two should avoid the registration of a dummy ACPI device for
graphics card on recent Lenovo ThinkPads.

Christian: This is why you saw two devices in /proc/acpi/video
It would be great if you could check if it's working for you.


    Thomas

------------------

Export a func to find the corresponding PCI bus:seg.func of an ACPI device

Signed-off-by: Thomas Renninger <[EMAIL PROTECTED]>

---
 drivers/acpi/pci_root.c |  155 ++++++++++++++++++++++++++++++++++++++----------
 include/linux/acpi.h    |    2 
 2 files changed, 127 insertions(+), 30 deletions(-)

Index: lenb/drivers/acpi/pci_root.c
===================================================================
--- lenb.orig/drivers/acpi/pci_root.c
+++ lenb/drivers/acpi/pci_root.c
@@ -32,6 +32,7 @@
 #include <linux/pm.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
+#include <linux/mod_devicetable.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -184,31 +185,11 @@ static void acpi_pci_bridge_scan(struct 
                }
 }
 
-static int acpi_pci_root_add(struct acpi_device *device)
+static int acpi_pci_root_get_seg_bus(struct acpi_device *device, u16 *seg, u16 
*bus)
 {
-       int result = 0;
-       struct acpi_pci_root *root = NULL;
-       struct acpi_pci_root *tmp;
+
        acpi_status status = AE_OK;
        unsigned long value = 0;
-       acpi_handle handle = NULL;
-       struct acpi_device *child;
-
-
-       if (!device)
-               return -EINVAL;
-
-       root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
-       if (!root)
-               return -ENOMEM;
-       INIT_LIST_HEAD(&root->node);
-
-       root->device = device;
-       strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
-       strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
-       acpi_driver_data(device) = root;
-
-       device->ops.bind = acpi_pci_bind;
 
        /* 
         * Segment
@@ -219,17 +200,16 @@ static int acpi_pci_root_add(struct acpi
                                       &value);
        switch (status) {
        case AE_OK:
-               root->id.segment = (u16) value;
+               *seg = (u16) value;
                break;
        case AE_NOT_FOUND:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Assuming segment 0 (no _SEG)\n"));
-               root->id.segment = 0;
+               *seg = 0;
                break;
        default:
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SEG"));
-               result = -ENODEV;
-               goto end;
+               return -ENODEV;
        }
 
        /* 
@@ -241,17 +221,48 @@ static int acpi_pci_root_add(struct acpi
                                       &value);
        switch (status) {
        case AE_OK:
-               root->id.bus = (u16) value;
+               *bus = (u16) value;
                break;
        case AE_NOT_FOUND:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming bus 0 (no _BBN)\n"));
-               root->id.bus = 0;
+               *bus = 0;
                break;
        default:
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BBN"));
-               result = -ENODEV;
-               goto end;
+               return -ENODEV;
        }
+       return 0;
+}
+
+static int acpi_pci_root_add(struct acpi_device *device)
+{
+       int result = 0;
+       struct acpi_pci_root *root = NULL;
+       struct acpi_pci_root *tmp;
+       acpi_status status = AE_OK;
+       acpi_handle handle = NULL;
+       struct acpi_device *child;
+
+
+       if (!device)
+               return -EINVAL;
+
+       root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
+       if (!root)
+               return -ENOMEM;
+       INIT_LIST_HEAD(&root->node);
+
+       root->device = device;
+       strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
+       strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
+       acpi_driver_data(device) = root;
+
+       device->ops.bind = acpi_pci_bind;
+
+       result = acpi_pci_root_get_seg_bus(device, &root->id.bus,
+                                          &root->id.segment);
+       if (result < 0)
+               goto end;
 
        /* Some systems have wrong _BBN */
        list_for_each_entry(tmp, &acpi_pci_roots, node) {
@@ -392,3 +403,87 @@ static int __init acpi_pci_root_init(voi
 }
 
 subsys_initcall(acpi_pci_root_init);
+
+/*
+ * Find the struct pci_dev* structure associated to the given ACPI device
+ *
+ * The device might be deeper in the device tree, the function goes until the
+ * PCI root bridge and returns the registered PCI device in the PCI sublayer,
+ * e.g.:
+ *
+ * \_SB
+ *     PCI0
+ *         SATA          S-ATA controller
+ *             _ADR      PCI Address of the SATA controller
+ *             PRT0      Port 0 device
+ *                 _ADR  Physical port and multiplier topology
+ *             PRTn      Port n device
+ *
+ * Whether PRT0 or SATA is passed it will always return the pci_dev
+ * structure of the SATA device.
+ * Be aware that the PCI device could be a PCI root bridge (e.g. in AGP
+ * case). If you want to have the real PCI struct of it, you need PCI sublayer
+ * functions to map the PCI root bridge device to the PCI bus the device has
+ * been set up to.
+ *
+ * Returns:
+ *   - zero on success
+ *   - -EINVAL on a real error -> buggy BIOS...
+ *   - -ENODEV is there is no physicaly PCI device associated/registered
+ */
+
+int acpi_find_pci_device(struct acpi_device *device, struct pci_dev *pci)
+{
+       struct acpi_device *parent, *child;
+       unsigned int devfn;
+       u16 bus, seg;
+       int result;
+       const struct acpi_device_id root_bridge_ids[] = {
+               {PCI_ROOT_HID_STRING, 0},
+               {PCI_EXPRESS_ROOT_HID_STRING, 0},
+               {"", 0},
+       };
+       pci = NULL;
+
+       if (!device || !device->parent) {
+               return -EINVAL;
+       }
+       child = device;
+       parent = device->parent;
+
+       while (acpi_match_device_ids(parent, root_bridge_ids)) {
+               /* Passed device was not under a PCI root bus */
+               if (!parent)
+                       return -EINVAL;
+
+               child = parent;
+               parent = parent->parent;
+
+       }
+
+       if (!child->flags.bus_address) {
+               printk (KERN_DEBUG PREFIX "Child device of PCI root bus has no"
+                       " _ADR func\n");
+               return -EINVAL;
+       }
+
+       /* _ADR  is lowest 16 bit -> func, highest 16 bit -> slot
+        * devfn is lowest  3 bit -> func, rest is        -> slot
+        */
+       devfn = (acpi_device_adr(child) >> 13) |
+               (acpi_device_adr(child) & 0xFFFF);
+
+       result = acpi_pci_root_get_seg_bus(parent, &bus, &seg);
+       if (result < 0)
+               return -EINVAL;
+
+       pci = pci_get_bus_and_slot(bus, devfn);
+
+       /* There is no physical PCI device registered for the ACPI device */
+       if (!pci)
+               return -ENODEV;
+       pci_dev_put(pci);
+
+       return 0;
+}
+EXPORT_SYMBOL(acpi_find_pci_device);
Index: lenb/include/linux/acpi.h
===================================================================
--- lenb.orig/include/linux/acpi.h
+++ lenb/include/linux/acpi.h
@@ -170,6 +170,8 @@ struct acpi_prt_list {
 
 struct pci_dev;
 
+int acpi_find_pci_device(struct acpi_device *device, struct pci_dev *pci);
+
 int acpi_pci_irq_enable (struct pci_dev *dev);
 void acpi_penalize_isa_irq(int irq, int active);
 



-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
ibm-acpi-devel mailing list
ibm-acpi-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ibm-acpi-devel

Reply via email to