From owner-svn-src-all@freebsd.org Tue Dec 19 02:49:13 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 33B9CEA31A5; Tue, 19 Dec 2017 02:49:13 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 031DE7F614; Tue, 19 Dec 2017 02:49:12 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vBJ2nCvm052967; Tue, 19 Dec 2017 02:49:12 GMT (envelope-from cem@FreeBSD.org) Received: (from cem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vBJ2nCeO052965; Tue, 19 Dec 2017 02:49:12 GMT (envelope-from cem@FreeBSD.org) Message-Id: <201712190249.vBJ2nCeO052965@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: cem set sender to cem@FreeBSD.org using -f From: Conrad Meyer Date: Tue, 19 Dec 2017 02:49:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r326956 - head/sys/dev/acpica X-SVN-Group: head X-SVN-Commit-Author: cem X-SVN-Commit-Paths: head/sys/dev/acpica X-SVN-Commit-Revision: 326956 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Dec 2017 02:49:13 -0000 Author: cem Date: Tue Dec 19 02:49:11 2017 New Revision: 326956 URL: https://svnweb.freebsd.org/changeset/base/326956 Log: Implement ACPI CPU support when Processor object is not present By the ACPI standard (ACPI 5 chapter 8.4 Declaring Processors) Processors can be implemented in 2 distinct ways: * Through a Processor object type (which provides P_BLK) * Through a Device object type Prior to this change, the FreeBSD driver only supported the former. AMD Epyc / Poweredge systems we are testing both implement the latter only. Add the missing support. Because P_BLK is not defined in the device object case, C-states entering must be completely controlled via _CST methods rather than P_LVL2/3. John Baldwin points out that ACPI 6.0 formally deprecates the Processor keyword, so eventually processors will only be enumerated as Device objects. Submitted by: attilio Reviewed by: jhb, markj, Anton Rang Relnotes: maybe Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D13457 Modified: head/sys/dev/acpica/acpi_cpu.c Modified: head/sys/dev/acpica/acpi_cpu.c ============================================================================== --- head/sys/dev/acpica/acpi_cpu.c Tue Dec 19 01:02:58 2017 (r326955) +++ head/sys/dev/acpica/acpi_cpu.c Tue Dec 19 02:49:11 2017 (r326956) @@ -140,6 +140,8 @@ struct acpi_cpu_device { #define CST_FFH_MWAIT_HW_COORD 0x0001 #define CST_FFH_MWAIT_BM_AVOID 0x0002 +#define CPUDEV_DEVICE_ID "ACPI0007" + /* Allow users to ignore processor orders in MADT. */ static int cpu_unordered; SYSCTL_INT(_debug_acpi, OID_AUTO, cpu_unordered, CTLFLAG_RDTUN, @@ -236,44 +238,61 @@ MODULE_DEPEND(cpu, acpi, 1, 1, 1); static int acpi_cpu_probe(device_t dev) { + static char *cpudev_ids[] = { CPUDEV_DEVICE_ID, NULL }; int acpi_id, cpu_id; ACPI_BUFFER buf; ACPI_HANDLE handle; ACPI_OBJECT *obj; ACPI_STATUS status; + ACPI_OBJECT_TYPE type; - if (acpi_disabled("cpu") || acpi_get_type(dev) != ACPI_TYPE_PROCESSOR || - acpi_cpu_disabled) + if (acpi_disabled("cpu") || acpi_cpu_disabled) return (ENXIO); + type = acpi_get_type(dev); + if (type != ACPI_TYPE_PROCESSOR && type != ACPI_TYPE_DEVICE) + return (ENXIO); + if (type == ACPI_TYPE_DEVICE && + ACPI_ID_PROBE(device_get_parent(dev), dev, cpudev_ids) == NULL) + return (ENXIO); handle = acpi_get_handle(dev); if (cpu_softc == NULL) cpu_softc = malloc(sizeof(struct acpi_cpu_softc *) * (mp_maxid + 1), M_TEMP /* XXX */, M_WAITOK | M_ZERO); - /* Get our Processor object. */ - buf.Pointer = NULL; - buf.Length = ACPI_ALLOCATE_BUFFER; - status = AcpiEvaluateObject(handle, NULL, NULL, &buf); - if (ACPI_FAILURE(status)) { - device_printf(dev, "probe failed to get Processor obj - %s\n", - AcpiFormatException(status)); - return (ENXIO); - } - obj = (ACPI_OBJECT *)buf.Pointer; - if (obj->Type != ACPI_TYPE_PROCESSOR) { - device_printf(dev, "Processor object has bad type %d\n", obj->Type); + if (type == ACPI_TYPE_PROCESSOR) { + /* Get our Processor object. */ + buf.Pointer = NULL; + buf.Length = ACPI_ALLOCATE_BUFFER; + status = AcpiEvaluateObject(handle, NULL, NULL, &buf); + if (ACPI_FAILURE(status)) { + device_printf(dev, "probe failed to get Processor obj - %s\n", + AcpiFormatException(status)); + return (ENXIO); + } + obj = (ACPI_OBJECT *)buf.Pointer; + if (obj->Type != ACPI_TYPE_PROCESSOR) { + device_printf(dev, "Processor object has bad type %d\n", + obj->Type); + AcpiOsFree(obj); + return (ENXIO); + } + + /* + * Find the processor associated with our unit. We could use the + * ProcId as a key, however, some boxes do not have the same values + * in their Processor object as the ProcId values in the MADT. + */ + acpi_id = obj->Processor.ProcId; AcpiOsFree(obj); - return (ENXIO); + } else { + status = acpi_GetInteger(handle, "_UID", &acpi_id); + if (ACPI_FAILURE(status)) { + device_printf(dev, "Device object has bad value - %s\n", + AcpiFormatException(status)); + return (ENXIO); + } } - - /* - * Find the processor associated with our unit. We could use the - * ProcId as a key, however, some boxes do not have the same values - * in their Processor object as the ProcId values in the MADT. - */ - acpi_id = obj->Processor.ProcId; - AcpiOsFree(obj); if (acpi_pcpu_get_id(dev, &acpi_id, &cpu_id) != 0) return (ENXIO); @@ -325,19 +344,32 @@ acpi_cpu_attach(device_t dev) cpu_smi_cmd = AcpiGbl_FADT.SmiCommand; cpu_cst_cnt = AcpiGbl_FADT.CstControl; - buf.Pointer = NULL; - buf.Length = ACPI_ALLOCATE_BUFFER; - status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf); - if (ACPI_FAILURE(status)) { - device_printf(dev, "attach failed to get Processor obj - %s\n", - AcpiFormatException(status)); - return (ENXIO); + if (acpi_get_type(dev) == ACPI_TYPE_PROCESSOR) { + buf.Pointer = NULL; + buf.Length = ACPI_ALLOCATE_BUFFER; + status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf); + if (ACPI_FAILURE(status)) { + device_printf(dev, "attach failed to get Processor obj - %s\n", + AcpiFormatException(status)); + return (ENXIO); + } + obj = (ACPI_OBJECT *)buf.Pointer; + sc->cpu_p_blk = obj->Processor.PblkAddress; + sc->cpu_p_blk_len = obj->Processor.PblkLength; + sc->cpu_acpi_id = obj->Processor.ProcId; + AcpiOsFree(obj); + } else { + KASSERT(acpi_get_type(dev) == ACPI_TYPE_DEVICE, + ("Unexpected ACPI object")); + status = acpi_GetInteger(sc->cpu_handle, "_UID", &sc->cpu_acpi_id); + if (ACPI_FAILURE(status)) { + device_printf(dev, "Device object has bad value - %s\n", + AcpiFormatException(status)); + return (ENXIO); + } + sc->cpu_p_blk = 0; + sc->cpu_p_blk_len = 0; } - obj = (ACPI_OBJECT *)buf.Pointer; - sc->cpu_p_blk = obj->Processor.PblkAddress; - sc->cpu_p_blk_len = obj->Processor.PblkLength; - sc->cpu_acpi_id = obj->Processor.ProcId; - AcpiOsFree(obj); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: P_BLK at %#x/%d\n", device_get_unit(dev), sc->cpu_p_blk, sc->cpu_p_blk_len));