summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Winder <paul@winders.demon.co.uk>2019-11-04 10:04:03 +0000
committerDan McDonald <danmcd@joyent.com>2019-11-04 16:09:45 -0500
commit3349e36e2896c71806ddaed726d65171a3045358 (patch)
treeb4eab7a589430c09d26874a9cc1fddca8ec61d1c
parent4c2b14fdad703c6c165e45413b79543a54e88edb (diff)
downloadillumos-joyent-3349e36e2896c71806ddaed726d65171a3045358.tar.gz
11790 ACPI method _CRS should be used to identify bus numbers during initial probe
Reviewed by: Andrew Stormont <andyjstormont@gmail.com> Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: Igor Kozhukhov <igor@dilos.org> Reviewed by: Randy Fishel <randyf@sibernet.com> Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r--usr/src/uts/intel/io/acpica/osl.c70
-rw-r--r--usr/src/uts/intel/io/pci/pci_boot.c19
-rw-r--r--usr/src/uts/intel/sys/acpica.h4
3 files changed, 78 insertions, 15 deletions
diff --git a/usr/src/uts/intel/io/acpica/osl.c b/usr/src/uts/intel/io/acpica/osl.c
index a6e7f9788a..adb46eeae4 100644
--- a/usr/src/uts/intel/io/acpica/osl.c
+++ b/usr/src/uts/intel/io/acpica/osl.c
@@ -23,6 +23,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2018 Joyent, Inc.
+ * Copyright 2019 Western Digital Corporation
*/
/*
* Copyright (c) 2009-2010, Intel Corporation.
@@ -1259,6 +1260,73 @@ AcpiOsGetLine(char *Buffer, UINT32 len, UINT32 *BytesRead)
return (0);
}
+static ACPI_STATUS
+acpica_crs_cb(ACPI_RESOURCE *rp, void *context)
+{
+ int *busno = context;
+
+ if (rp->Data.Address.ProducerConsumer == 1)
+ return (AE_OK);
+
+ switch (rp->Type) {
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ if (rp->Data.Address16.Address.AddressLength == 0)
+ break;
+ if (rp->Data.Address16.ResourceType != ACPI_BUS_NUMBER_RANGE)
+ break;
+
+ *busno = rp->Data.Address16.Address.Minimum;
+ break;
+
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ if (rp->Data.Address32.Address.AddressLength == 0)
+ break;
+ if (rp->Data.Address32.ResourceType != ACPI_BUS_NUMBER_RANGE)
+ break;
+
+ *busno = rp->Data.Address32.Address.Minimum;
+ break;
+
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ if (rp->Data.Address64.Address.AddressLength == 0)
+ break;
+ if (rp->Data.Address64.ResourceType != ACPI_BUS_NUMBER_RANGE)
+ break;
+
+ *busno = (int)rp->Data.Address64.Address.Minimum;
+ break;
+
+ default:
+ break;
+ }
+
+ return (AE_OK);
+}
+
+/*
+ * Retrieve the bus number for a root bus.
+ *
+ * _CRS (Current Resource Setting) holds the bus number as set in
+ * PCI configuration, this may differ from _BBN and is a more reliable
+ * indicator of what the bus number is.
+ */
+ACPI_STATUS
+acpica_get_busno(ACPI_HANDLE hdl, int *busno)
+{
+ ACPI_STATUS rv;
+ int bus = -1;
+ int bbn;
+
+ if (ACPI_FAILURE(rv = acpica_eval_int(hdl, "_BBN", &bbn)))
+ return (rv);
+
+ (void) AcpiWalkResources(hdl, "_CRS", acpica_crs_cb, &bus);
+
+ *busno = bus == -1 ? bbn : bus;
+
+ return (AE_OK);
+}
+
/*
* Device tree binding
*/
@@ -1304,7 +1372,7 @@ acpica_find_pcibus_walker(ACPI_HANDLE hdl, UINT32 lvl, void *ctxp, void **rvpp)
*hdlp = hdl;
return (AE_CTRL_TERMINATE);
}
- } else if (ACPI_SUCCESS(acpica_eval_int(hdl, "_BBN", &bbn))) {
+ } else if (ACPI_SUCCESS(acpica_get_busno(hdl, &bbn))) {
if (bbn == busno) {
*hdlp = hdl;
return (AE_CTRL_TERMINATE);
diff --git a/usr/src/uts/intel/io/pci/pci_boot.c b/usr/src/uts/intel/io/pci/pci_boot.c
index 55fa91915d..20bc1bdda8 100644
--- a/usr/src/uts/intel/io/pci/pci_boot.c
+++ b/usr/src/uts/intel/io/pci/pci_boot.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2019 Joyent, Inc.
+ * Copyright 2019 Western Digital Corporation
*/
#include <sys/types.h>
@@ -189,8 +190,6 @@ int pua_cache_valid = 0;
static ACPI_STATUS
pci_process_acpi_device(ACPI_HANDLE hdl, UINT32 level, void *ctx, void **rv)
{
- ACPI_BUFFER rb;
- ACPI_OBJECT ro;
ACPI_DEVICE_INFO *adi;
int busnum;
@@ -218,18 +217,12 @@ pci_process_acpi_device(ACPI_HANDLE hdl, UINT32 level, void *ctx, void **rv)
AcpiOsFree(adi);
/*
- * XXX: ancient Big Bear broken _BBN will result in two
- * bus 0 _BBNs being found, so we need to handle duplicate
- * bus 0 gracefully. However, broken _BBN does not
- * hide a childless root-bridge so no need to work-around it
- * here
+ * acpica_get_busno() will check the presence of _BBN and
+ * fail if not present. It will then use the _CRS method to
+ * retrieve the actual bus number assigned, it will fall back
+ * to _BBN should the _CRS method fail.
*/
- rb.Pointer = &ro;
- rb.Length = sizeof (ro);
- if (ACPI_SUCCESS(AcpiEvaluateObjectTyped(hdl, "_BBN",
- NULL, &rb, ACPI_TYPE_INTEGER))) {
- busnum = ro.Integer.Value;
-
+ if (ACPI_SUCCESS(acpica_get_busno(hdl, &busnum))) {
/*
* Ignore invalid _BBN return values here (rather
* than panic) and emit a warning; something else
diff --git a/usr/src/uts/intel/sys/acpica.h b/usr/src/uts/intel/sys/acpica.h
index b60b4df114..e15ccc78a7 100644
--- a/usr/src/uts/intel/sys/acpica.h
+++ b/usr/src/uts/intel/sys/acpica.h
@@ -26,6 +26,7 @@
/*
* Copyright (c) 2009-2010, Intel Corporation.
* All rights reserved.
+ * Copyright 2019 Western Digital Corporation.
*/
#ifndef _SYS_ACPICA_H
@@ -141,7 +142,7 @@ typedef struct iflag {
*/
typedef struct device_id {
struct device_id *next;
- char *id;
+ char *id;
} device_id_t;
typedef struct property {
@@ -192,6 +193,7 @@ extern ACPI_STATUS acpica_get_cpu_object_by_apicid(UINT32, ACPI_HANDLE *);
extern ACPI_STATUS acpica_get_cpu_id_by_object(ACPI_HANDLE, processorid_t *);
extern ACPI_STATUS acpica_get_apicid_by_object(ACPI_HANDLE, UINT32 *);
extern ACPI_STATUS acpica_get_procid_by_object(ACPI_HANDLE, UINT32 *);
+extern ACPI_STATUS acpica_get_busno(ACPI_HANDLE, int *);
extern uint64_t acpica_get_core_feature(uint64_t);
extern void acpica_set_core_feature(uint64_t);