Module Name:    src
Committed By:   jruoho
Date:           Thu Apr 14 06:25:25 UTC 2011

Modified Files:
        src/sys/dev/acpi: acpi_power.c

Log Message:
Simplify by using a static array for the reference counting.


To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 src/sys/dev/acpi/acpi_power.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/acpi/acpi_power.c
diff -u src/sys/dev/acpi/acpi_power.c:1.29 src/sys/dev/acpi/acpi_power.c:1.30
--- src/sys/dev/acpi/acpi_power.c:1.29	Sun Jan  9 16:22:07 2011
+++ src/sys/dev/acpi/acpi_power.c	Thu Apr 14 06:25:25 2011
@@ -1,7 +1,7 @@
-/* $NetBSD: acpi_power.c,v 1.29 2011/01/09 16:22:07 jruoho Exp $ */
+/* $NetBSD: acpi_power.c,v 1.30 2011/04/14 06:25:25 jruoho Exp $ */
 
 /*-
- * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009, 2010, 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -56,7 +56,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_power.c,v 1.29 2011/01/09 16:22:07 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_power.c,v 1.30 2011/04/14 06:25:25 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/kmem.h>
@@ -74,27 +74,15 @@
 #define	ACPI_STA_POW_OFF		0x00
 #define	ACPI_STA_POW_ON			0x01
 
-/*
- * References.
- */
-struct acpi_power_ref {
-	ACPI_HANDLE			ref_handle;
-
-	SIMPLEQ_ENTRY(acpi_power_ref)	ref_list;
-};
-
-/*
- * Resources.
- */
 struct acpi_power_res {
 	ACPI_HANDLE			res_handle;
 	ACPI_INTEGER			res_level;
 	ACPI_INTEGER			res_order;
+	ACPI_HANDLE			res_ref[5];
 	char				res_name[5];
 	kmutex_t			res_mutex;
 
 	TAILQ_ENTRY(acpi_power_res)	res_list;
-	SIMPLEQ_HEAD(, acpi_power_ref)	ref_head;
 };
 
 static TAILQ_HEAD(, acpi_power_res) res_head =
@@ -128,6 +116,7 @@
 	ACPI_OBJECT *obj;
 	ACPI_BUFFER buf;
 	ACPI_STATUS rv;
+	size_t i;
 
 	rv = acpi_eval_struct(hdl, NULL, &buf);
 
@@ -155,7 +144,9 @@
 	(void)strlcpy(res->res_name,
 	    acpi_xname(hdl), sizeof(res->res_name));
 
-	SIMPLEQ_INIT(&res->ref_head);
+	for (i = 0; i < __arraycount(res->res_ref); i++)
+		res->res_ref[i] = NULL;
+
 	mutex_init(&res->res_mutex, MUTEX_DEFAULT, IPL_NONE);
 
 	/*
@@ -481,8 +472,13 @@
 	if (res == NULL)
 		return AE_NOT_FOUND;
 
+	if (ref == NULL)
+		return AE_BAD_PARAMETER;
+
 	/*
-	 * (De)reference the resource.
+	 * Adjust the reference counting. This is
+	 * necessary since a single power resource
+	 * can be shared by multiple devices.
 	 */
 	switch (on) {
 
@@ -510,82 +506,70 @@
 }
 
 static ACPI_STATUS
-acpi_power_res_ref(struct acpi_power_res *res, ACPI_HANDLE hdl)
+acpi_power_res_ref(struct acpi_power_res *res, ACPI_HANDLE ref)
 {
-	struct acpi_power_ref *ref, *tmp;
+	size_t i, j = SIZE_MAX;
 
-	ref = kmem_zalloc(sizeof(*ref), KM_SLEEP);
+	mutex_enter(&res->res_mutex);
 
-	if (ref == NULL)
-		return AE_NO_MEMORY;
+	for (i = 0; i < __arraycount(res->res_ref); i++) {
 
-	mutex_enter(&res->res_mutex);
+		/*
+		 * Do not error out if the handle
+		 * has already been referenced.
+		 */
+		if (res->res_ref[i] == ref) {
+			mutex_exit(&res->res_mutex);
+			return AE_OK;
+		}
 
-	SIMPLEQ_FOREACH(tmp, &res->ref_head, ref_list) {
+		if (j == SIZE_MAX && res->res_ref[i] == NULL)
+			j = i;
+	}
 
-		if (tmp->ref_handle == hdl)
-			goto out;
+	if (j == SIZE_MAX) {
+		mutex_exit(&res->res_mutex);
+		return AE_LIMIT;
 	}
 
-	ref->ref_handle = hdl;
-	SIMPLEQ_INSERT_TAIL(&res->ref_head, ref, ref_list);
+	res->res_ref[j] = ref;
 	mutex_exit(&res->res_mutex);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s referenced "
-		"by %s\n", res->res_name, acpi_xname(hdl)));
-
-	return AE_OK;
-
-out:
-	mutex_exit(&res->res_mutex);
-	kmem_free(ref, sizeof(*ref));
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s already referenced "
-		"by %s?\n", res->res_name, acpi_xname(hdl)));
+		"by %s\n", res->res_name, acpi_xname(ref)));
 
 	return AE_OK;
 }
 
 static ACPI_STATUS
-acpi_power_res_deref(struct acpi_power_res *res, ACPI_HANDLE hdl)
+acpi_power_res_deref(struct acpi_power_res *res, ACPI_HANDLE ref)
 {
-	struct acpi_power_ref *ref;
+	size_t i;
 
 	mutex_enter(&res->res_mutex);
 
-	if (SIMPLEQ_EMPTY(&res->ref_head) != 0) {
+	for (i = 0; i < __arraycount(res->res_ref); i++) {
+
+		if (res->res_ref[i] != ref)
+			continue;
+
+		res->res_ref[i] = NULL;
 		mutex_exit(&res->res_mutex);
-		return AE_OK;
-	}
 
-	SIMPLEQ_FOREACH(ref, &res->ref_head, ref_list) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s dereferenced "
+			"by %s\n", res->res_name, acpi_xname(ref)));
 
-		if (ref->ref_handle == hdl) {
-			SIMPLEQ_REMOVE(&res->ref_head,
-			    ref, acpi_power_ref, ref_list);
-			mutex_exit(&res->res_mutex);
-			kmem_free(ref, sizeof(*ref));
-			mutex_enter(&res->res_mutex);
-			break;
-		}
+		return AE_OK;
 	}
 
 	/*
-	 * If the queue remains non-empty,
+	 * If the array remains to be non-empty,
 	 * something else is using the resource
 	 * and hence it can not be turned off.
 	 */
-	if (SIMPLEQ_EMPTY(&res->ref_head) == 0) {
-		mutex_exit(&res->res_mutex);
-		return AE_ABORT_METHOD;
-	}
-
 	mutex_exit(&res->res_mutex);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s dereferenced "
-		"by %s\n", res->res_name, acpi_xname(hdl)));
-
-	return AE_OK;
+	return AE_ABORT_METHOD;
 }
 
 static ACPI_STATUS

Reply via email to