All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Renninger <trenn@suse.de>
To: linux-acpi <linux-acpi@vger.kernel.org>
Cc: Christian Birchinger <joker@netswarm.net>,
	"Li, Shaohua" <shaohua.li@intel.com>, Len Brown <lenb@kernel.org>,
	ibm-acpi-devel <ibm-acpi-devel@lists.sourceforge.net>
Subject: [PATCH 1/2] Export a func to find the corresponding PCI bus:seg.func of an ACPI device
Date: Mon, 15 Oct 2007 18:33:05 +0200	[thread overview]
Message-ID: <1192465985.9847.585.camel@queen.suse.de> (raw)

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 <trenn@suse.de>

---
 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);
 



             reply	other threads:[~2007-10-15 16:33 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-15 16:33 Thomas Renninger [this message]
2007-10-15 16:48 ` [PATCH 1/2] Export a func to find the corresponding PCI bus:seg.func of an ACPI device Matthew Garrett
2007-10-16  1:12   ` Shaohua Li
2007-10-16 14:39   ` [PATCH 1/1] Recent Lenovo ThinkPads define a dummy grahpics device, find it and ignore it Thomas Renninger
2007-10-16 14:43     ` Thomas Renninger
2007-10-16 14:49     ` Matthew Garrett
     [not found]       ` <20071016144901.GB21749-1xO5oi07KQx4cg9Nei1l7Q@public.gmane.org>
2007-10-16 15:11         ` Thomas Renninger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1192465985.9847.585.camel@queen.suse.de \
    --to=trenn@suse.de \
    --cc=ibm-acpi-devel@lists.sourceforge.net \
    --cc=joker@netswarm.net \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=shaohua.li@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.