⬢ DragonFlyBSD Kernel Audit
DF-4261 / fix.diff
← back to finding ↓ download raw
--- 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;