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