tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

panic on zero length SCSI read



Hi,

I was reading a music CD with cdparanoia on sparc64.  The drive failed to
read a sector from the disk and the machine paniced with:

  iommu_dvmamap_sync: segment too short 0

and the backtrace was:

  _iommu_dvmamap_sync()
  iommu_dvmamap_sync()
  esiop_scsipi_request()
  scsipi_run_queue()

A fix for the panic is simple (see attached), but I wonder if instead, esiop
should be modified to not call bus_dmamap_sync() if the length is 0?  In this
case, it is esiop_cmd->cmd_c.dmamap_cmd->dm_mapsize at line 1608 of esiop.c
in current sources:

                bus_dmamap_sync(sc->sc_c.sc_dmat, esiop_cmd->cmd_c.dmamap_cmd,
                    0, esiop_cmd->cmd_c.dmamap_cmd->dm_mapsize,
                    BUS_DMASYNC_PREWRITE);

but perhaps the same applies in other cases too.

Thanks,

J

PS.  dmesg excerpts:

  NetBSD 5.0_STABLE (ULTRA-PCI.MP) #0: Tue Oct 13 16:44:14 BST 2009
    ...
  mainbus0 (root): SUNW,Ultra-80 (Sun Enterprise 420R): hostid 80e8d665
    ...
  esiop0 at pci0 dev 3 function 0: Symbios Logic 53c875 (ultra-wide scsi)
  esiop0: using on-board RAM
  esiop0: interrupting at ivec 1820
  scsibus0 at esiop0: 16 targets, 8 luns per target
    ...
  cd0 at scsibus0 target 6 lun 0: <TOSHIBA, DVD-ROM SD-M1401, 1009> cdrom 
removable
  cd0: sync (50.00ns offset 16), 8-bit (20.000MB/s) transfers

PPS.  Version not really relevant - this bug appears to have been there for
some time.

-- 
  My other computer also runs NetBSD    /        Sailing at Newbiggin
        http://www.netbsd.org/        /   http://www.newbigginsailingclub.org/
Index: dev/iommu.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/dev/iommu.c,v
retrieving revision 1.85
diff -u -p -r1.85 iommu.c
--- dev/iommu.c 18 Oct 2008 03:31:10 -0000      1.85
+++ dev/iommu.c 30 Nov 2009 13:58:18 -0000
@@ -999,6 +999,10 @@ iommu_dvmamap_sync(bus_dma_tag_t t, bus_
        bus_size_t len, int ops)
 {
 
+       /* If len is 0, then there is nothing to do */
+       if (len == 0)
+               return;
+
        if (ops & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)) {
                /* Flush the CPU then the IOMMU */
                bus_dmamap_sync(t->_parent, map, offset, len, ops);


Home | Main Index | Thread Index | Old Index