--- sys/dev/acpica/acpi_cpu_pstate.c.orig +++ sys/dev/acpica/acpi_cpu_pstate.c @@ -511,6 +511,7 @@ /* Save and try allocating status register */ error = acpi_pst_alloc_resource(dev, obj, 1, &sc->pst_sreg); if (error) { + acpi_pst_release_resource(dev, &sc->pst_creg); AcpiOsFree(obj); return error; } @@ -544,14 +545,16 @@ } device_printf(dev, "Can't get _PSS package - %s\n", AcpiFormatException(status)); - return ENXIO; + error = ENXIO; + goto failed; } obj = (ACPI_OBJECT *)buf.Pointer; if (!ACPI_PKG_VALID(obj, 1)) { device_printf(dev, "Invalid _PSS package\n"); AcpiOsFree(obj); - return ENXIO; + error = ENXIO; + goto failed; } /* Don't create too many P-States */ @@ -571,7 +574,8 @@ device_printf(dev, "Inconsistent # of P-States " "cross Processor objects\n"); AcpiOsFree(obj); - return ENXIO; + error = ENXIO; + goto failed; } /* @@ -591,7 +595,8 @@ device_printf(dev, "Invalud _PSS P%d\n", i); AcpiOsFree(obj); kfree(pstate, M_TEMP); - return ENXIO; + error = ENXIO; + goto failed; } for (j = 0; j < ACPI_PSS_PX_NENTRY; ++j) { if (acpi_PkgInt32(pkg, j, ptr[j]) != 0) { @@ -599,7 +604,8 @@ "_PSS P%d %dth entry\n", i, j); AcpiOsFree(obj); kfree(pstate, M_TEMP); - return ENXIO; + error = ENXIO; + goto failed; } } if (p->st_freq & 0x80000000) { @@ -607,7 +613,8 @@ i, p->st_freq); AcpiOsFree(obj); kfree(pstate, M_TEMP); - return ENXIO; + error = ENXIO; + goto failed; } } @@ -687,7 +694,7 @@ */ error = acpi_pst_eval_ppc(sc, &sstart); if (error && error != ENOENT) - return error; + goto failed; else if (!error) sc->pst_flags |= ACPI_PST_FLAG_PPC; proc_ppc: @@ -733,7 +740,7 @@ */ error = acpi_pst_eval_pdl(sc, &scount); if (error && error != ENOENT) - return error; + goto failed; else if (!error) sc->pst_flags |= ACPI_PST_FLAG_PDL; proc_pdl: @@ -810,6 +817,11 @@ sc->pst_parent->cpu_pst_notify = acpi_pst_notify; return 0; + +failed: + acpi_pst_release_resource(dev, &sc->pst_creg); + acpi_pst_release_resource(dev, &sc->pst_sreg); + return error; } static struct acpi_pst_domain * @@ -1518,6 +1530,29 @@ } static void +acpi_pst_release_resource(device_t dev, struct acpi_pst_res *res) +{ + int type; + + if (res->pr_res == NULL) + return; + + switch (res->pr_gas.SpaceId) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + type = SYS_RES_MEMORY; + break; + case ACPI_ADR_SPACE_SYSTEM_IO: + type = SYS_RES_IOPORT; + break; + default: + return; + } + bus_release_resource(dev, type, res->pr_rid, res->pr_res); + res->pr_res = NULL; + res->pr_rid = 0; +} + +static void acpi_pst_domain_check_nproc(device_t dev, struct acpi_pst_domain *dom) { struct acpi_pst_softc *pst;