Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Jul 2001 05:25:53 -0700
From:      "neckpain@nettaxi.com" <neckpain@nettaxi.com>
To:        msmith@freebsd.org
Cc:        current@freebsd.org
Subject:   Re: acpica malfunctions
Message-ID:  <200107271225.FAA09468@mail25.bigmailbox.com>

index | next in thread | raw e-mail

[-- Attachment #1 --]
In-Reply-To: <200107232037.f6NKbx201647@mass.dis.org>; from msmith@FreeBSD.ORG on Mon, Jul 23, 2001 at 01:37:59PM -0700

On Mon, Jul 23, 2001 at 01:37:59PM -0700, Mike Smith wrote:
> > > > 1. Acpica modules hangs in
> > > >     AcpiRsCalculateByteStreamLength() called from
> > > >     AcpiRsCreateByteStream() called from
> > > >     AcpiRsSetSrsMethodData() called from
> > > >     AcpiSetCurrentResources() from somewhere in acpi_pcib.c .
> > > >
> > > >     The hang itself occurs at LinkedList->Id == 9 and LinkedList->Length 
> > == 0
> > > > .
> > >
> > > Can you replace &crsbuf with crsbuf in acpi_pcib.c at line 484?
> > > I think I should be passing a pointer to the buffer, not a pointer to a
> > > pointer.
> > 
> > There's no &crsbuf in line 484 (not in rev 1.10, nor 1.11).
> > 
> > Assuming you're talking about the one in line 478, it doesn't compile if you
> > change it to crsbuf from &crsbuf, since crsbuf is an ACPI_BUFFER, not
> > an (ACPI_BUFFER *).
> 
> Um.  Sorry about the line numbers, and yes, sorry about the confusion 
> there; I just looked at it and it seemed wrong.
> 
> I'd still like to know the allocation length for that buffer though; my 
> last suspicion is that it doesn't contain any resources at all, and so 
> we're overrunning it when we go to try to stuff an interrupt resource 
> into it.  If that's the case, it's easy to fix.  If not, then we will 
> have to go hunting snarks.

Mike,
Seems like I managed to solve my problem. Attached is to be applied against
sys/dev/acpica/acpi_pcib.c, rev 1.10 .

First of all, the list returned in crsbuf was terminated with an element
with its Length field equal to zero (and Id field was ACPI_RSTYPE_IRQ).
Since AcpiRsCalculateByteStreamLength() expects ACPI_RSTYPE_END_TAG as
terminator and doesn't check the validity of Length field (or, in other words,
this function doesn't treat it as terminator), the function never returned.

And as you suggested, AcpiGetCurrentResources() returned an IRQ resource
with no interrupts(NumberOfInterrupts = 0, and no room for
Data.Irq.Interrupts[0]). Thus the line 476 in acpi_pcib.c was overwriting
the Id field in the next element.

The patch tries to allocate another buffer to resize the list, and to modify the
last element's Id to ACPI_RSTYPE_END_TAG.
I think AcpiRsCalculateByteStreamLength() should just exit the while loop
when it found an element with Length = 0, rather than wait for the end tag
forever.

Thanks.


------------------------------------------------------------
Shop Smart Compare Prices on Name-Brand Products from Name-Brand Stores!!
http://www.smartshop.com/cgi-bin/main.cgi?ssa=4099

[-- Attachment #2 --]
Index: sys/dev/acpica/acpi_pcib.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpica/acpi_pcib.c,v
retrieving revision 1.10
diff -u -u -r1.10 acpi_pcib.c
--- sys/dev/acpica/acpi_pcib.c	2001/07/07 10:12:06	1.10
+++ sys/dev/acpica/acpi_pcib.c	2001/07/27 02:44:32
@@ -269,6 +269,41 @@
     pci_cfgregwrite(bus, slot, func, reg, data, bytes);
 }
 
+static ACPI_STATUS
+acpi_EnlargeResource(ACPI_BUFFER *bufp, ACPI_RESOURCE *curp, size_t want)
+{
+	ACPI_RESOURCE	*top;
+	ACPI_RESOURCE	*alloc;
+	size_t		p;
+	size_t		BufferSize;
+
+	if (curp < (top = bufp->Pointer) ||
+	    POINTER_ADD(ACPI_RESOURCE, top, bufp->Length - curp->Length) < curp)
+		return AE_BAD_PARAMETER;
+
+	BufferSize = bufp->Length - curp->Length + want;
+	if ((alloc = AcpiOsAllocate(BufferSize)) == NULL)
+		return AE_NO_MEMORY;
+
+	p = (char *)curp - (char *)top;
+	memcpy(alloc, top, p);
+
+	memcpy((char *)alloc + p, curp, want);
+	(POINTER_ADD(ACPI_RESOURCE, alloc, p))->Length = want;
+
+	memcpy((char *)alloc + p + want, (char *)curp + curp->Length,
+	    bufp->Length - p - curp->Length);
+
+	alloc->Length += want - curp->Length;
+	bufp->Length = BufferSize;
+	AcpiOsFree(bufp->Pointer);
+	bufp->Pointer = alloc;
+
+	return AE_OK;
+}
+
+
+
 /*
  * Route an interrupt for a child of the bridge.
  *
@@ -473,6 +508,43 @@
     for (i = 0; i < prsres->Data.Irq.NumberOfInterrupts; i++)
 	printf("  %d", prsres->Data.Irq.Interrupts[i]);
     printf("\n");
+
+    {
+	ACPI_RESOURCE	*r, *s;
+	size_t		newsize;
+	int		i, j, n;
+
+	/*
+	 * first grow the size of IRQ resource so we have room for an IRQ
+	 */
+	n = crsres->Data.Irq.NumberOfInterrupts +
+	    prsres->Data.Irq.NumberOfInterrupts;
+	newsize = (char *)&(crsres->Data.Irq.Interrupts[0]) - (char *)crsres +
+	    n * sizeof (crsres->Data.Irq.Interrupts[0]);
+	if (acpi_EnlargeResource(&crsbuf, crsres, newsize) != AE_OK)
+	    goto out;
+
+	/* fix crsres point to the resource in the newly allocated buffer */
+	acpi_FindIndexedResource((ACPI_RESOURCE *)crsbuf.Pointer,
+	    prt->SourceIndex, &crsres);
+
+	for (i = crsres->Data.Irq.NumberOfInterrupts, j = 0; i < n; ++i, ++j)
+	    crsres->Data.Irq.Interrupts[i] = prsres->Data.Irq.Interrupts[j];
+	crsres->Data.Irq.NumberOfInterrupts = n;
+
+	/*
+	 * find the last element(Length = 0)
+	 * and set Id to ACPI_RSTYPE_END_TAG
+	 */
+	r = crsbuf.Pointer,
+	s = POINTER_ADD(ACPI_RESOURCE, crsbuf.Pointer, crsbuf.Length);
+	for (; r < s; r = POINTER_ADD(ACPI_RESOURCE, r, r->Length))
+	    if (r->Length == 0) {
+		r->Id = ACPI_RSTYPE_END_TAG;
+		break;
+	    }
+    }
+
     crsres->Data.Irq.Interrupts[0] = prsres->Data.Irq.Interrupts[0];
     crsres->Data.Irq.NumberOfInterrupts = 1;
     if (ACPI_FAILURE(status = AcpiSetCurrentResources(lnkdev, &crsbuf))) {
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200107271225.FAA09468>