Re: 2.4.21-pre3 kernel crash

Edward Tandi
2003-01-27T20:18:28Z

FYI It works!

Thanks, I actually reported high-memory and DMA problems on the
13th-15th of Jan (under the title of Linux 2.4.21-pre3-ac3 and KT400)
but I thought it was VIA specific. I knew it was only time before a
fix...

The VIA audio issue is still there though ;-)

Ed-T.

On Mon, 2003-01-27 at 19:23, Jens Axboe wrote:
> On Mon, Jan 27 2003, Martin MOKREJ? wrote:
> > On Mon, 27 Jan 2003, Ross Biro wrote:
> >
> > > This looks like the same problem I ran into with IDE and highmem not
> > > getting along. Try compiling your kernel with out highmem enabled and
> > > see what happenes.
> >
> > Yes, that "fixes" it. Any "better solution"? ;-)
> >
> > > >Trace; c024dfc1 <ide_build_sglist+181/1a0>
> > > >Trace; c024e1b4 <ide_build_dmatable+54/1a0>
> > > >Trace; c024e6df <__ide_dma_read+3f/150>
>
> Someone completely lost the highmem capable scatterlist setup, *boggle*.
> This should fix it.
>
> ===== drivers/ide/ide-dma.c 1.7 vs edited =====
> --- 1.7/drivers/ide/ide-dma.c Wed Nov 20 18:46:24 2002
> +++ edited/drivers/ide/ide-dma.c Mon Jan 27 20:22:06 2003
> @@ -249,6 +249,7 @@
> {
> struct buffer_head *bh;
> struct scatterlist *sg = hwif->sg_table;
> + unsigned long lastdataend = ~0UL;
> int nents = 0;
>
> if (hwif->sg_dma_active)
> @@ -256,22 +257,28 @@
>
> bh = rq->bh;
> do {
> - unsigned char *virt_addr = bh->b_data;
> - unsigned int size = bh->b_size;
> + if (bh_phys(bh) == lastdataend) {
> + sg[nents - 1].length += bh->b_size;
> + lastdataend += bh->b_size;
> + continue;
> + }
>
> if (nents >= PRD_ENTRIES)
> return 0;
>
> - while ((bh = bh->b_reqnext) != NULL) {
> - if ((virt_addr + size) != (unsigned char *) bh->b_data)
> - break;
> - size += bh->b_size;
> - }
> memset(&sg[nents], 0, sizeof(*sg));
> - sg[nents].address = virt_addr;
> - sg[nents].length = size;
> - if(size == 0)
> - BUG();
> + if (bh->b_page) {
> + sg[nents].page = bh->b_page;
> + sg[nents].offset = bh_offset(bh);
> + } else {
> + if (((unsigned long) bh->b_data) < PAGE_SIZE)
> + BUG();
> +
> + sg[nents].address = bh->b_data;
> + }
> +
> + sg[nents].length = bh->b_size;
> + lastdataend = bh_phys(bh) + bh->b_size;
> nents++;
> } while (bh != NULL);
>