From 3349e36e2896c71806ddaed726d65171a3045358 Mon Sep 17 00:00:00 2001 From: Paul Winder Date: Mon, 4 Nov 2019 10:04:03 +0000 Subject: 11790 ACPI method _CRS should be used to identify bus numbers during initial probe Reviewed by: Andrew Stormont Reviewed by: Toomas Soome Reviewed by: Igor Kozhukhov Reviewed by: Randy Fishel Approved by: Dan McDonald --- usr/src/uts/intel/io/acpica/osl.c | 70 ++++++++++++++++++++++++++++++++++++- usr/src/uts/intel/io/pci/pci_boot.c | 19 ++++------ usr/src/uts/intel/sys/acpica.h | 4 ++- 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 @@ -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); -- cgit v1.2.3