summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica/acpi_pci_link.c
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-08-05 06:54:16 +0000
committernjl <njl@FreeBSD.org>2004-08-05 06:54:16 +0000
commit562235ab9797faabe4696ea9b435010730825dc3 (patch)
treec033ad987dd8203ade1a69d4f64b14edf502ef45 /sys/dev/acpica/acpi_pci_link.c
parent708c9dab9fb4dbff2b9b609703d7160fcfc38d25 (diff)
downloadFreeBSD-src-562235ab9797faabe4696ea9b435010730825dc3.zip
FreeBSD-src-562235ab9797faabe4696ea9b435010730825dc3.tar.gz
Work around non-compliant BIOS PCI link devices. Some systems have the
following behavior: * Link devices return invalid status (_STA) values. The results are very unreliable -- sometimes never present. Just ignore the status and pick the best configuration from _PRS. * Link devices return invalid current settings (_CRS). Even after setting the link value, many systems still return a different setting for _CRS. When setting an IRQ, don't bother to check _CRS to see if we succeeded. Note that we still check _CRS before routing and this should be addressed as well. Since this is a sensitive area, leave the old behavior accessible via uncommenting the define for ACPI_OLD_PCI_LINK at the top of the file. Once this has been thoroughly tested, this option and the code it covers will be removed. Thanks to Len Brown at Intel for informing us of these issues as he worked around them in Linux.
Diffstat (limited to 'sys/dev/acpica/acpi_pci_link.c')
-rw-r--r--sys/dev/acpica/acpi_pci_link.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/sys/dev/acpica/acpi_pci_link.c b/sys/dev/acpica/acpi_pci_link.c
index 400aa14..669aba4 100644
--- a/sys/dev/acpica/acpi_pci_link.c
+++ b/sys/dev/acpica/acpi_pci_link.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+/* XXX Uncomment this if you have new PCI IRQ problems starting 2004/8/5. */
+/* #define ACPI_OLD_PCI_LINK 1 */
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -73,10 +76,12 @@ static struct acpi_prt_entries acpi_prt_entries;
static int irq_penalty[MAX_ACPI_INTERRUPTS];
+#ifdef ACPI_OLD_PCI_LINK
#define ACPI_STA_PRESENT 0x00000001
#define ACPI_STA_ENABLE 0x00000002
#define ACPI_STA_SHOWINUI 0x00000004
#define ACPI_STA_FUNCTIONAL 0x00000008
+#endif /* ACPI_OLD_PCI_LINK */
/*
* PCI link object management
@@ -171,6 +176,7 @@ acpi_pci_link_entry_dump(struct acpi_prt_entry *entry)
(int)entry->prt.Pin);
}
+#ifdef ACPI_OLD_PCI_LINK
static ACPI_STATUS
acpi_pci_link_get_object_status(ACPI_HANDLE handle, UINT32 *sta)
{
@@ -215,6 +221,7 @@ acpi_pci_link_get_object_status(ACPI_HANDLE handle, UINT32 *sta)
AcpiOsFree(buf.Pointer);
return_ACPI_STATUS (AE_OK);
}
+#endif /* ACPI_OLD_PCI_LINK */
static ACPI_STATUS
acpi_pci_link_get_irq_resources(ACPI_RESOURCE *resources,
@@ -439,7 +446,9 @@ acpi_pci_link_add_prt(device_t pcidev, ACPI_PCI_ROUTING_TABLE *prt, int busno)
{
ACPI_HANDLE handle;
ACPI_STATUS error;
+#ifdef ACPI_OLD_PCI_LINK
UINT32 sta;
+#endif
struct acpi_prt_entry *entry;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -457,6 +466,11 @@ acpi_pci_link_add_prt(device_t pcidev, ACPI_PCI_ROUTING_TABLE *prt, int busno)
return_ACPI_STATUS (error);
}
+ /*
+ * PCI link status (_STA) is unreliable. Many systems return
+ * erroneous values so we ignore it.
+ */
+#ifdef ACPI_OLD_PCI_LINK
error = acpi_pci_link_get_object_status(handle, &sta);
if (ACPI_FAILURE(error)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
@@ -471,6 +485,7 @@ acpi_pci_link_add_prt(device_t pcidev, ACPI_PCI_ROUTING_TABLE *prt, int busno)
acpi_name(handle)));
return_ACPI_STATUS (AE_ERROR);
}
+#endif /* ACPI_OLD_PCI_LINK */
TAILQ_FOREACH(entry, &acpi_prt_entries, links) {
if (entry->busno == busno &&
@@ -539,7 +554,9 @@ acpi_pci_link_set_irq(struct acpi_pci_link_entry *link, UINT8 irq)
ACPI_STATUS error;
ACPI_RESOURCE resbuf;
ACPI_BUFFER crsbuf;
+#ifdef ACPI_OLD_PCI_LINK
UINT32 sta;
+#endif
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -614,7 +631,13 @@ acpi_pci_link_set_irq(struct acpi_pci_link_entry *link, UINT8 irq)
AcpiOsFree(crsbuf.Pointer);
link->current_irq = 0;
+ error = AE_OK;
+ /*
+ * PCI link status (_STA) is unreliable. Many systems return
+ * erroneous values so we ignore it.
+ */
+#ifdef ACPI_OLD_PCI_LINK
error = acpi_pci_link_get_object_status(link->handle, &sta);
if (ACPI_FAILURE(error)) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
@@ -629,7 +652,14 @@ acpi_pci_link_set_irq(struct acpi_pci_link_entry *link, UINT8 irq)
acpi_name(link->handle)));
return_ACPI_STATUS (AE_ERROR);
}
+#endif /* ACPI_OLD_PCI_LINK */
+ /*
+ * Many systems always return invalid values for current settings
+ * (_CRS). Since we can't trust the value returned, we have to
+ * assume we were successful.
+ */
+#ifdef ACPI_OLD_PCI_LINK
error = acpi_pci_link_get_current_irq(link, &link->current_irq);
if (ACPI_FAILURE(error)) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
@@ -647,6 +677,7 @@ acpi_pci_link_set_irq(struct acpi_pci_link_entry *link, UINT8 irq)
link->current_irq = 0;
error = AE_ERROR;
}
+#endif /* ACPI_OLD_PCI_LINK */
return_ACPI_STATUS (error);
}
OpenPOWER on IntegriCloud