acpi panics - potential fix
Nate Lawson
nate at root.org
Sun May 11 10:38:15 PDT 2003
If you are having acpi panics, please try the attached patch.
-Nate
---------- Forwarded message ----------
Date: Wed, 07 May 2003 11:23:31 +0900
From: Takayoshi Kochi <kochi at netbsd.org>
Reply-To: acpi-jp at jp.FreeBSD.org
To: acpi-jp at jp.FreeBSD.org
Subject: [acpi-jp 2182] Re: Outstanding ACPI issues for 5.1-RELEASE
(please ignore my last posting, sorry)
Hello Nate and all,
While tracking NetBSD PR/17872, Takashi Yamamoto found
a bug in nsalloc.c. In AcpiNsDeleteNode(), it was possible
to make parent-child loop. Robert Moore admitted this is
a bug and will be fixed in the next release.
And I found another problem about reference counting of
ACPI_NAMESPACE_NODE objects. Under a certain condition
(for my laptop, repeated evaluation of _BST method of
battery) reference count goes up to wrap UINT16 and may
cause unexpected object free. I reported this
to Robert also, but I haven't got official fix.
It seems to me that reference counting of ACPI_NAMESPACE_NODE
is unnecessary but I'm not sure. I attached my
fix (which also includes Yamamoto-san's fix), but
please take this as an experimetntal patch.
The acpi_thermal panic problem might be related to this one.
For more info about the NetBSD PR/17872, plase refer to the url:
http://www.netbsd.org/cgi-bin/query-pr-single.pl?number=17872
From: Nate Lawson <nate at root.org>
Subject: [acpi-jp 2177] Outstanding ACPI issues for 5.1-RELEASE
Date: Tue, 6 May 2003 14:28:21 -0700
> Here is a list of the current problems. We would like to fix as many as
> possible before the release. If anyone has time to tackle these issues,
> please let me know. The reporters listed below should open a PR and send
> me the number as I do not want to replicate GNATS in email.
>
> --------------------------------------------------------------
> Problem: acpi_thermal causes a panic
> Reporter: ru at freebsd.org
> Information:
> This looks like referencing a freed or uninitialized data member.
>
> The below was produces with the latest 0228 ACPI diff in-tree, and acpi
> device compiled directly into a kernel. Loading it as a module gave me
> some lines offset in the source file, and the faulting address was
> 0xdeadc0de.
---
Takayoshi Kochi
-------------- next part --------------
--- nsalloc.c.orig 2003-03-05 02:33:38.000000000 +0900
+++ nsalloc.c 2003-04-25 20:11:13.000000000 +0900
@@ -210,7 +210,14 @@
}
else
{
- ParentNode->Child = NextNode->Peer;
+ if (NextNode->Flags & ANOBJ_END_OF_PEER_LIST)
+ {
+ ParentNode->Child = NULL;
+ }
+ else
+ {
+ ParentNode->Child = NextNode->Peer;
+ }
}
@@ -517,6 +524,62 @@
/*******************************************************************************
*
+ * FUNCTION: AcpiNsRemoveReference
+ *
+ * PARAMETERS: Node - Named node whose reference count is to be
+ * decremented
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Remove a Node reference. Decrements the reference count
+ * of all parent Nodes up to the root. Any node along
+ * the way that reaches zero references is freed.
+ *
+ ******************************************************************************/
+
+static void
+AcpiNsRemoveReference (
+ ACPI_NAMESPACE_NODE *Node)
+{
+ ACPI_NAMESPACE_NODE *ParentNode;
+ ACPI_NAMESPACE_NODE *ThisNode;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ /*
+ * Decrement the reference count(s) of this node and all
+ * nodes up to the root, Delete anything with zero remaining references.
+ */
+ ThisNode = Node;
+ while (ThisNode)
+ {
+ /* Prepare to move up to parent */
+
+ ParentNode = AcpiNsGetParentNode (ThisNode);
+
+ /* Decrement the reference count on this node */
+
+ ThisNode->ReferenceCount--;
+
+ /* Delete the node if no more references */
+
+ if (!ThisNode->ReferenceCount)
+ {
+ /* Delete all children and delete the node */
+
+ AcpiNsDeleteChildren (ThisNode);
+ AcpiNsDeleteNode (ThisNode);
+ }
+
+ ThisNode = ParentNode;
+ }
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: AcpiNsDeleteNamespaceSubtree
*
* PARAMETERS: ParentNode - Root of the subtree to be deleted
@@ -532,8 +595,9 @@
AcpiNsDeleteNamespaceSubtree (
ACPI_NAMESPACE_NODE *ParentNode)
{
- ACPI_NAMESPACE_NODE *ChildNode = NULL;
- UINT32 Level = 1;
+ ACPI_NAMESPACE_NODE *ChildNode;
+ ACPI_NAMESPACE_NODE *DeletionNode;
+ UINT32 Level;
ACPI_FUNCTION_TRACE ("NsDeleteNamespaceSubtree");
@@ -544,6 +608,10 @@
return_VOID;
}
+ ChildNode = NULL;
+ DeletionNode = NULL;
+ Level = 1;
+
/*
* Traverse the tree of objects until we bubble back up
* to where we started.
@@ -554,6 +622,12 @@
ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode,
ChildNode);
+ if (DeletionNode)
+ {
+ AcpiNsRemoveReference (DeletionNode);
+ DeletionNode = NULL;
+ }
+
if (ChildNode)
{
/* Found a child node - detach any attached object */
@@ -572,6 +646,10 @@
ParentNode = ChildNode;
ChildNode = 0;
}
+ else
+ {
+ DeletionNode = ChildNode;
+ }
}
else
{
@@ -585,7 +663,10 @@
* Now delete all of the children of this parent
* all at the same time.
*/
- AcpiNsDeleteChildren (ParentNode);
+ if (Level != 0)
+ {
+ DeletionNode = ParentNode;
+ }
/* New "last child" is this parent node */
@@ -603,62 +684,6 @@
/*******************************************************************************
*
- * FUNCTION: AcpiNsRemoveReference
- *
- * PARAMETERS: Node - Named node whose reference count is to be
- * decremented
- *
- * RETURN: None.
- *
- * DESCRIPTION: Remove a Node reference. Decrements the reference count
- * of all parent Nodes up to the root. Any node along
- * the way that reaches zero references is freed.
- *
- ******************************************************************************/
-
-static void
-AcpiNsRemoveReference (
- ACPI_NAMESPACE_NODE *Node)
-{
- ACPI_NAMESPACE_NODE *ParentNode;
- ACPI_NAMESPACE_NODE *ThisNode;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- /*
- * Decrement the reference count(s) of this node and all
- * nodes up to the root, Delete anything with zero remaining references.
- */
- ThisNode = Node;
- while (ThisNode)
- {
- /* Prepare to move up to parent */
-
- ParentNode = AcpiNsGetParentNode (ThisNode);
-
- /* Decrement the reference count on this node */
-
- ThisNode->ReferenceCount--;
-
- /* Delete the node if no more references */
-
- if (!ThisNode->ReferenceCount)
- {
- /* Delete all children and delete the node */
-
- AcpiNsDeleteChildren (ThisNode);
- AcpiNsDeleteNode (ThisNode);
- }
-
- ThisNode = ParentNode;
- }
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiNsDeleteNamespaceByOwner
*
* PARAMETERS: OwnerId - All nodes with this owner will be deleted
More information about the freebsd-current
mailing list