[parisc-linux] Re: kernel>=2.6.4-rc3 hung or panic on C1[18]0 [was: 2.6.5-rc2-pa2 boot panic on c110 :(]

Joel Soete soete.joel at tiscali.be
Sun Apr 18 08:39:45 MDT 2004


Hello,

Sorry but I absolutly blind this week-end (no access to 192.25.206 ie debian.org, p-l.org and cvs.p-l.org :_( ), more over I had 
to confirm 'membership in the mailing list parisc-linux' which has been disabled, so I didn't received anymore followup :(

Any way I progress: I revert the following patch against the last pa kernel I had here ie 2.6.5-pa5:
===================================================================
RCS file: /var/lib/cvs/linux-2.6/drivers/parisc/ccio-dma.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- linux-2.6/drivers/parisc/ccio-dma.c 2004/03/09 21:49:04     1.12
+++ linux-2.6/drivers/parisc/ccio-dma.c 2004/03/10 19:24:48     1.13
@@ -38,9 +38,7 @@
  #include <linux/spinlock.h>
  #include <linux/slab.h>
  #include <linux/string.h>
-#define PCI_DEBUG
  #include <linux/pci.h>
-#undef PCI_DEBUG
  #include <linux/reboot.h>

  #include <asm/byteorder.h>
@@ -344,15 +342,16 @@
   * of available pages for the requested size.
   */
  static int
-ccio_alloc_range(struct ioc *ioc, unsigned long pages_needed)
+ccio_alloc_range(struct ioc *ioc, size_t size)
  {
+       unsigned int pages_needed = size >> IOVP_SHIFT;
         unsigned int res_idx;
  #ifdef CCIO_SEARCH_TIME
         unsigned long cr_start = mfctl(16);
  #endif

-       ASSERT(pages_needed);
-       ASSERT((pages_needed * IOVP_SIZE) <= DMA_CHUNK_SIZE);
+       BUG_ON(pages_needed == 0);
+       BUG_ON((pages_needed * IOVP_SIZE) > DMA_CHUNK_SIZE);

         DBG_RES("%s() size: %d pages_needed %d\n",
                 __FUNCTION__, size, pages_needed);
@@ -387,7 +386,7 @@
                 CCIO_FIND_FREE_MAPPING(ioc, res_idx, ~0UL, 64);
  #endif
         } else {
-               panic("%s: %s() Too many pages to map. pages_needed: %ld\n",
+               panic("%s: %s() Too many pages to map. pages_needed: %u\n",
                        __FILE__,  __FUNCTION__, pages_needed);
         }

@@ -420,7 +419,7 @@

  #define CCIO_FREE_MAPPINGS(ioc, res_idx, mask, size) \
          u##size *res_ptr = (u##size *)&((ioc)->res_map[res_idx]); \
-        ASSERT((*res_ptr & mask) == mask); \
+        BUG_ON((*res_ptr & mask) != mask); \
          *res_ptr &= ~(mask);

  /**
@@ -438,9 +437,9 @@
         unsigned long iovp = CCIO_IOVP(iova);
         unsigned int res_idx = PDIR_INDEX(iovp) >> 3;

-       ASSERT(pages_mapped);
-       ASSERT((pages_mapped * IOVP_SIZE) <= DMA_CHUNK_SIZE);
-       ASSERT(pages_mapped <= BITS_PER_LONG);
+       BUG_ON(pages_mapped == 0);
+       BUG_ON((pages_mapped * IOVP_SIZE) > DMA_CHUNK_SIZE);
+       BUG_ON(pages_mapped > BITS_PER_LONG);

         DBG_RES("%s():  res_idx: %d pages_mapped %d\n",
                 __FUNCTION__, res_idx, pages_mapped);
@@ -558,13 +557,14 @@
   * index are bits 12:19 of the value returned by LCI.
   */
  void CCIO_INLINE
-ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, void * vba, unsigned long hints)+ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, 
unsigned long vba,
+                  unsigned long hints)
  {
         register unsigned long pa = (volatile unsigned long) vba;
         register unsigned long ci; /* coherent index */

         /* We currently only support kernel addresses */
-       ASSERT(sid == KERNEL_SPACE);
+       BUG_ON(sid != KERNEL_SPACE);

         mtsp(sid,1);

@@ -677,7 +677,7 @@
                 unsigned int idx = PDIR_INDEX(iovp);
                 char *pdir_ptr = (char *) &(ioc->pdir_base[idx]);

-               ASSERT(idx < (ioc->pdir_size / sizeof(u64)));
+               BUG_ON(idx >= (ioc->pdir_size / sizeof(u64)));
                 pdir_ptr[7] = 0;        /* clear only VALID bit */
                 /*
                 ** FIXME: PCX_W platforms don't need FDC/SYNC. (eg C360)
@@ -747,7 +747,7 @@
         BUG_ON(!dev);
         ioc = GET_IOC(dev);

-       ASSERT(size > 0);
+       BUG_ON(size <= 0);

         /* save offset bits */
         offset = ((unsigned long) addr) & ~IOVP_MASK;
@@ -761,7 +761,7 @@
         ioc->msingle_pages += size >> IOVP_SHIFT;
  #endif

-       idx = ccio_alloc_range(ioc, (size >> IOVP_SHIFT));
+       idx = ccio_alloc_range(ioc, size);
         iovp = (dma_addr_t)MKIOVP(idx);

         pdir_start = &(ioc->pdir_base[idx]);
@@ -774,7 +774,7 @@
                 hint |= HINT_SAFE_DMA;

         while(size > 0) {
-               ccio_io_pdir_entry(pdir_start, KERNEL_SPACE, addr, hint);
+               ccio_io_pdir_entry(pdir_start, KERNEL_SPACE, (unsigned long)addr, hint);

                 DBG_RUN(" pdir %p %08x%08x\n",
                         pdir_start,
@@ -886,162 +886,10 @@
  */
  #define PIDE_FLAG 0x80000000UL

-/**
- * ccio_fill_pdir - Insert coalesced scatter/gather chunks into the I/O Pdir.
- * @ioc: The I/O Controller.
- * @startsg: The scatter/gather list of coalesced chunks.
- * @nents: The number of entries in the scatter/gather list.
- * @hint: The DMA Hint.
- *
- * This function inserts the coalesced scatter/gather list chunks into the
- * I/O Controller's I/O Pdir.
- */
-static CCIO_INLINE int
-ccio_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents,
-              unsigned long hint)
-{
-       struct scatterlist *dma_sg = startsg;   /* pointer to current DMA */
-       int n_mappings = 0;
-       unsigned long dma_offset = 0, dma_len = 0;
-       u64 *pdirp = NULL;
-
-       while (nents-- > 0) {
-               unsigned long vaddr;
-               long size;
-
-               DBG_RUN_SG(" %d : %08lx/%05x %08lx/%05x\n", nents,
-                          (unsigned long)sg_dma_address(startsg), cnt,
-                          sg_virt_addr(startsg), startsg->length
-               );
-
-
-               /*
-               ** Look for the start of a new DMA stream
-               */
-
-               if (sg_dma_address(startsg) & PIDE_FLAG) {
-                       u32 pide = sg_dma_address(startsg) & ~PIDE_FLAG;
-
-                       if (pdirp) {
-                               BUG_ON(dma_len != sg_dma_len(dma_sg));
-                               dma_sg++;
-                       }
-                       dma_len = sg_dma_len(startsg);
-                       dma_offset = (unsigned long) pide & ~IOVP_MASK;
-                       n_mappings++;
-                       sg_dma_address(dma_sg) = pide;
-                       pdirp = &(ioc->pdir_base[pide >> IOVP_SHIFT]);
-               }
-
-               BUG_ON(pdirp == NULL);
-
-               sg_dma_len(startsg) = 0;
-               vaddr = sg_virt_addr(startsg);
-               sg_dma_len(dma_sg) += startsg->length;
-               size = startsg->length + dma_offset;
-               dma_offset = 0;
-               if (unlikely(size > IOVP_SIZE)) {
-                       printk("VIRTUAL CHUNK has size 0x%lx\n",
-                              size);
-               }
  #ifdef CCIO_MAP_STATS
-               ioc->msg_pages += startsg->length >> IOVP_SHIFT;
+#define IOMMU_MAP_STATS
  #endif
-               do {
-                       ccio_io_pdir_entry(pdirp, KERNEL_SPACE,
-                                          (void *)vaddr, hint);
-                       vaddr += IOVP_SIZE;
-                       size -= IOVP_SIZE;
-                       pdirp++;
-               } while(unlikely(size > 0));
-               startsg++;
-       }
-       return(n_mappings);
-}
-
-/*
-** First pass is to walk the SG list and determine where the breaks are
-** in the DMA stream. Allocates PDIR entries but does not fill them.
-** Returns the number of DMA chunks.
-**
-** Doing the fill separate from the coalescing/allocation keeps the
-** code simpler. Future enhancement could make one pass through
-** the sglist do both.
-*/
-
-static CCIO_INLINE int
-ccio_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, int nents)
-{
-       struct scatterlist *contig_sg;     /* contig chunk head */
-       unsigned long dma_offset, dma_len; /* start/len of DMA stream */
-       int n_mappings = 0;
-
-       while (nents > 0) {
-
-               /*
-               ** Prepare for first/next DMA stream
-               */
-               contig_sg = startsg;
-               dma_len = startsg->length;
-               dma_offset = sg_virt_addr(startsg) & ~IOVP_MASK;
-
-               /* PARANOID: clear entries */
-               sg_dma_address(startsg) = 0;
-               sg_dma_len(startsg) = 0;
-
-               /*
-               ** This loop terminates one iteration "early" since
-               ** it's always looking one "ahead".
-               */
-               while(--nents > 0) {
-                       unsigned long prevstartsg_end, startsg_end;
-
-                       prevstartsg_end = sg_virt_addr(startsg) +
-                               startsg->length;
-
-                       startsg++;
-                       startsg_end = sg_virt_addr(startsg) +
-                               startsg->length;
-
-                       /* PARANOID: clear entries */
-                       sg_dma_address(startsg) = 0;
-                       sg_dma_len(startsg) = 0;
-
-                       /*
-                       ** First make sure current dma stream won't
-                       ** exceed DMA_CHUNK_SIZE if we coalesce the
-                       ** next entry.
-                       */
-                       if(unlikely(ROUNDUP(dma_len + dma_offset + startsg->length,
-                                           IOVP_SIZE) > DMA_CHUNK_SIZE))
-                               break;
-
-                       /*
-                       ** Next see if we can append the next chunk (i.e.
-                       ** it must end on one page and begin on another
-                       */
-                       if (unlikely(((prevstartsg_end | sg_virt_addr(startsg))
& ~PAGE_MASK) != 0))
-                               break;
-
-                       dma_len += startsg->length;
-               }
-
-               /*
-               ** End of DMA Stream
-               ** Terminate last VCONTIG block.
-               ** Allocate space for DMA stream.
-               */
-               sg_dma_len(contig_sg) = dma_len;
-               dma_len = ROUNDUP(dma_len + dma_offset, IOVP_SIZE);
-               sg_dma_address(contig_sg) =
-                       PIDE_FLAG
-                       | (ccio_alloc_range(ioc, (dma_len >> IOVP_SHIFT)) << IOVP_SHIFT)
-                       | dma_offset;
-               n_mappings++;
-       }
-
-       return n_mappings;
-}
+#include "iommu-helpers.h"

  /**
   * ccio_map_sg - Map the scatter/gather list into the IOMMU.
@@ -1094,7 +942,7 @@
         ** w/o this association, we wouldn't have coherent DMA!
         ** Access to the virtual address is what forces a two pass algorithm.
         */
-       coalesced = ccio_coalesce_chunks(ioc, sglist, nents);
+       coalesced = iommu_coalesce_chunks(ioc, sglist, nents, ccio_alloc_range);
         /*
         ** Program the I/O Pdir
@@ -1104,7 +952,7 @@
         ** o dma_len will contain the number of bytes to map
         ** o page/offset contain the virtual address.
         */
-       filled = ccio_fill_pdir(ioc, sglist, nents, hint);
+       filled = iommu_fill_pdir(ioc, sglist, nents, hint, ccio_io_pdir_entry);

         spin_unlock_irqrestore(&ioc->res_lock, flags);

@@ -1446,16 +1294,16 @@
         */

         iov_order = get_order(iova_space_size) >> (IOVP_SHIFT - PAGE_SHIFT);
-       ASSERT(iov_order <= (30 - IOVP_SHIFT));   /* iova_space_size <= 1GB */
-       ASSERT(iov_order >= (20 - IOVP_SHIFT));   /* iova_space_size >= 1MB */
+       BUG_ON(iov_order > (30 - IOVP_SHIFT));   /* iova_space_size <= 1GB */
+       BUG_ON(iov_order < (20 - IOVP_SHIFT));   /* iova_space_size >= 1MB */
         iova_space_size = 1 << (iov_order + IOVP_SHIFT);

         ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64);

-       ASSERT(ioc->pdir_size < 4 * 1024 * 1024);   /* max pdir size < 4MB */
+       BUG_ON(ioc->pdir_size >= 4 * 1024 * 1024);   /* max pdir size < 4MB */

         /* Verify it's a power of two */
-       ASSERT((1 << get_order(ioc->pdir_size)) == (ioc->pdir_size >> PAGE_SHIFT));
+       BUG_ON((1 << get_order(ioc->pdir_size)) != (ioc->pdir_size >> PAGE_SHIFT));

         DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits) PDIR size 0x%0x",
                 __FUNCTION__, ioc->ioc_hpa, physmem>>20, iova_space_size>>20,
@@ -1469,7 +1317,7 @@
         }
         memset(ioc->pdir_base, 0, ioc->pdir_size);

-       ASSERT((((unsigned long)ioc->pdir_base) & PAGE_MASK) == (unsigned long)ioc->pdir_base);
+       BUG_ON((((unsigned long)ioc->pdir_base) & PAGE_MASK) != (unsigned long)ioc->pdir_base);
         DBG_INIT(" base %p", ioc->pdir_base);

         /* resource map size dictated by pdir_size */
@@ -1708,6 +1556,7 @@
                                        proc_runway_root, ccio_resource_map, NULL);
         }
         parisc_vmerge_boundary = IOVP_SIZE;
+       parisc_vmerge_max_size = BITS_PER_LONG * IOVP_SIZE;
         ioc_count++;
         return 0;
  }
==================================================================================================

And the test (find + tar) works again.

I presume that wrong stuff come from the ccio_fill_pdir() or ccio_coalesce_chunks() merge with lba one?
But I don't have yet more accurate idea on what went wrong here (difference between functions are important).

(would it help to rebuild this same kernel tree with gcc-3.0 32bit would help? right now is was build with latest gcc-3.3.3.)

Grant, James any idea?

Thanks again for your understanding,
	Joel

Joel Soete wrote:
> Hi all,
> 
> To summarise I do following test with different kernel to locate this pb:
> launch severall find into local big tree (different release of kernel 
> tree) in the same time of a tar of one of those tree.
> 
> with kernel 2.6.3-pa2 no pb
> with 2.6.4-rc1-pa3 no pb (apparently)
> with 2.6.4-rc3-pa6 system crash (as well as with 2.6.4-rc3-pa1)
> 
> with the last one (2.6.4-rc3-pa1) I also log:
> attempt to access beyond end of device
> sdb9: rw=0, want=2307486096, limit=3075696
> attempt to access beyond end of device
> sdb9: rw=0, want=2842788104, limit=3075696
> attempt to access beyond end of device
> sdb9: rw=0, want=1904280008, limit=3075696
> attempt to access beyond end of device
> sdb9: rw=0, want=2298589592, limit=3075696
> attempt to access beyond end of device
> sdb9: rw=0, want=26325376, limit=3075696
> attempt to access beyond end of device
> sdb9: rw=0, want=1371126224, limit=3075696
> attempt to access beyond end of device
> sdb9: rw=0, want=3277938880, limit=3075696
> attempt to access beyond end of device
> sdb9: rw=0, want=122917000, limit=3075696
> attempt to access beyond end of device
> sdb9: rw=0, want=1151862976, limit=3075696
> attempt to access beyond end of device
> sdb9: rw=0, want=3236466824, limit=3075696
> attempt to access beyond end of device
> sdb9: rw=0, want=3253102776, limit=3075696
> 
> during the first find alone?
> arq->state 2
> Badness in as_requeue_request at drivers/block/as-iosched.c:1479
> Kernel addresses on the stack:
>  [<10125de8>] printk+0x188/0x1c8
>  [<10105938>] dump_stack+0x18/0x24
>  [<102294fc>] as_requeue_request+0x64/0x10c
>  [<10220468>] elv_requeue_request+0x2c/0x38
>  [<1022313c>] blk_insert_request+0xfc/0x104
>  [<1024cbb0>] scsi_queue_insert+0x68/0x9c
>  [<1024915c>] scsi_finish_command+0x9c/0xc0
>  [<10249068>] scsi_softirq+0xfc/0x11c
>  [<10262fb4>] ncr53c8xx_intr+0x74/0xbc
>  [<101299cc>] do_softirq+0xf4/0xf8
>  [<10220468>] elv_requeue_request+0x2c/0x38
>  [<10107270>] do_cpu_irq_mask+0xfc/0x10c
>  [<10220468>] elv_requeue_request+0x2c/0x38
>  [<1010b068>] intr_return+0x0/0x14
>  [<1024cbb0>] scsi_queue_insert+0x68/0x9c
>  [<1010b070>] intr_return+0x8/0x14
>  [<1016ba8c>] may_open+0x58/0x1c8
>  [<1015a850>] dentry_open+0x138/0x1c4
>  [<1016e784>] locate_fd+0x158/0x194
>  [<1010b068>] intr_return+0x0/0x14
> 
> kernel BUG at include/linux/blkdev.h:543!
> Kernel addresses on the stack:
>  [<10125de8>] printk+0x188/0x1c8
>  [<10105938>] dump_stack+0x18/0x24
>  [<1024ddc8>] scsi_request_fn+0x2a0/0x2c4
>  [<10220468>] elv_requeue_request+0x2c/0x38
>  [<10223120>] blk_insert_request+0xe0/0x104
>  [<1024cbb0>] scsi_queue_insert+0x68/0x9c
>  [<1024915c>] scsi_finish_command+0x9c/0xc0
>  [<10249068>] scsi_softirq+0xfc/0x11c
>  [<10262fb4>] ncr53c8xx_intr+0x74/0xbc
>  [<101299cc>] do_softirq+0xf4/0xf8
>  [<10220468>] elv_requeue_request+0x2c/0x38
>  [<10107270>] do_cpu_irq_mask+0xfc/0x10c
>  [<10220468>] elv_requeue_request+0x2c/0x38
>  [<1010b068>] intr_return+0x0/0x14
>  [<1024cbb0>] scsi_queue_insert+0x68/0x9c
>  [<1010b070>] intr_return+0x8/0x14
>  [<1016ba8c>] may_open+0x58/0x1c8
>  [<1015a850>] dentry_open+0x138/0x1c4
>  [<1016e784>] locate_fd+0x158/0x194
>  [<1010b068>] intr_return+0x0/0x14
> [...]
> and so on severall time.
> 
> I also drive the same test over a nfs (as it seems that lan and scsi 
> ctrl on this c110 share the same U2 bridge?):
> no pb.
> 
> May I so reasonably thought that pb is loacted into ncr53c720 scsi driver?
> 
> Thanks in advance for additional help,
>     Joel
> 
> 
> 
> Joel Soete wrote:
> 
>>
>>
>> Andy Walker wrote:
>>
>>>> Hello Andy,
>>>>
>>>> Sorry for delay but I was a bit busy by a production server.
>>>
>>>
>>>
>>>
>>> No problem.
>>>
>>>
>>>>> 2.6.6-rc1-pa0 shows the same behaviour,
>>>>
>>>>
>>>>
>>>> Thanks.
>>>> but not a surprise regarding previous test.
>>>>
>>>>
>>>>> although it does seem to make it
>>>>> through the Gentoo boot process most times.
>>>>
>>>>
>>>>
>>>> I would not be surprise if it occures during some fsck. Do you also use
>>>> ext3 on your Gentoo?
>>>> btw Gentoo always install pkg by a local rebuild from src (that's a 
>>>> long
>>>> time that I visit the site)?
>>>
>>>
>>>
>>>
>>> That's the Gentoo way - so every package on my system is compiled
>>> -march=2.0 -mschedule=8000. The downside is that install and upgrade
>>> takes a long time on slow machines.
>>
>>
>>
>> Yes that why I do not investegate more: I don't have a lot of budget 
>> for my system which are generaly systems a bit outdated machine 
>> recover from trash still just enough for my investigation but a bit 
>> too slow to build all the tools I would like to maintained uptodate 
>> frequently. The very great stuff would have to have the choice: update 
>> from pre-compiled binaries or a local compile. The debian packaging 
>> system is very robust (some month ago, on a i386, I do an update from 
>> a old woody (r0 iirc) directly to unstable aka sid without any pb) but 
>> I do not yet find a clear doc explaining me how to personalize pkg 
>> from dpkg src (I would like for instance change the prefix in general 
>> /usr into /opt/app/app_rev a la hp)?
>>
>>> The upside is that you get total
>>> control over package selection and compilation options. I've played
>>> with Debian before but I find apt a pain compared to Gentoo's portage.
>>> Also all this sid/woody/stable/unstable etc.... stuff confuses me.
>>>
>> That is the simple aspect: in short
>>     the current stable release was named (the 2.x was potato, the 
>> current one woody)
>>     the very last packages otc are put in unstable (aka sid) for large 
>> testing and debuging
>>     when pkg become enough stable it is pushed in testing the futur 
>> debian release (recently named sarge)
>>
>> there are also security update for stable release only because there 
>> are in general in unstable and testing before!
>>
>> For my part I only have ineterest in very last available packages (so 
>> sid or unstable) to test new features but some times (rarely in fact) 
>> the system is a bit 'unstable' :) (that's my choice).
>>
>>>
>>>>> I've compiled 2.6.3-pa2 in the hope of getting the C180 up and stable.
>>>>
>>>>
>>>>
>>>> This seems to be the last one enough stable for me and my c110: I just
>>>> updated my distro (that used a lot tar iirc) and all works
>>>> fine with this kernel.
>>>
>>>
>>>
>>>
>>> 2.6.3-pa2 is rock solid. I've been running updates, kernel compilation -
>>> pretty heavy stuff, and no problems.
>>> I'm just about to 'emerge' X11 - that should keep it downloading,
>>> untarring and compiling for 24 hours.
>>>
>> Ok
>>
>>> Any suggestions for things I might test to narrow our problem down.
>>>
>> Not realy for the moment, as explain previously, the problem seems to 
>> apear between 2.6.4-rc1-pa3 and 2.6.4-rc3-pa6.
>> I will try to figure out now if it comes from upstream or from or 
>> tree: I am on going to rebuild 2.6.4-rc3-pa1 and see how will it behave.
>>
>> Thanks a lot,
>>     Joel
>>
> 


More information about the parisc-linux mailing list