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.
This commit is contained in:
parent
708c9dab9f
commit
562235ab97
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user