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 --- nsalloc.c.orig 2003-03-05 02:33:38.000000000 +0900 +++ nsalloc.c 2003-04-25 20:11:13.000000000 +0900 _at__at_ -210,7 +210,14 _at__at_ } else { - ParentNode->Child = NextNode->Peer; + if (NextNode->Flags & ANOBJ_END_OF_PEER_LIST) + { + ParentNode->Child = NULL; + } + else + { + ParentNode->Child = NextNode->Peer; + } } _at__at_ -517,6 +524,62 _at__at_ /******************************************************************************* * + * 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 _at__at_ -532,8 +595,9 _at__at_ 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"); _at__at_ -544,6 +608,10 _at__at_ return_VOID; } + ChildNode = NULL; + DeletionNode = NULL; + Level = 1; + /* * Traverse the tree of objects until we bubble back up * to where we started. _at__at_ -554,6 +622,12 _at__at_ ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode, ChildNode); + if (DeletionNode) + { + AcpiNsRemoveReference (DeletionNode); + DeletionNode = NULL; + } + if (ChildNode) { /* Found a child node - detach any attached object */ _at__at_ -572,6 +646,10 _at__at_ ParentNode = ChildNode; ChildNode = 0; } + else + { + DeletionNode = ChildNode; + } } else { _at__at_ -585,7 +663,10 _at__at_ * 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 */ _at__at_ -603,62 +684,6 _at__at_ /******************************************************************************* * - * 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 deletedReceived on Sun May 11 2003 - 08:38:15 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:07 UTC