Hi,
the attached patch fixes part of the DMA problems we see with multiple
disks and the sgiwd93.c with DISCONNECTs. Klaus patch formerly just
disabled all DMA replacing it with PIO which is a major performance hit.
This patch simply deletes all the HPC Scatter/Gather stuff thus we will
see a couple more interrupts due to all segments beeing transferred
individually. The transfer itself still happens with the HPC DMA thus
the performance impact will not be that large. I am running a test right
now but it seems the error is gone.
This also touches the wd33c93.c generic part which brings us closer to
mainstream as these to lines are a difference between the sgi/mips tree
and the mainline kernel as we would need this kind of modification if
we would do the scatter-gather DMA.
Index: sgiwd93.c
===================================================================
RCS file: /cvs/linux/drivers/scsi/sgiwd93.c,v
retrieving revision 1.28
diff -u -r1.28 sgiwd93.c
--- sgiwd93.c 2001/11/06 07:56:05 1.28
+++ sgiwd93.c 2001/12/10 20:06:01
@@ -115,42 +115,16 @@
hdata->dma_dir = datainp;
- if(cmd->SCp.buffers_residual) {
- struct scatterlist *slp = cmd->SCp.buffer;
- int i, totlen = 0;
-
-#ifdef DEBUG_DMA
- printk("SCLIST<");
-#endif
- for(i = 0; i <= cmd->SCp.buffers_residual; i++) {
-#ifdef DEBUG_DMA
- printk("[%p,%d]", slp[i].address, slp[i].length);
-#endif
- fill_hpc_entries (&hcp, slp[i].address, slp[i].length);
- totlen += slp[i].length;
- }
-#ifdef DEBUG_DMA
- printk(">tlen<%d>", totlen);
-#endif
- hdata->dma_bounce_len = totlen; /* a trick... */
- write_wd33c93_count(regs, totlen);
- } else {
- /* Non-scattered dma. */
-#ifdef DEBUG_DMA
- printk("ONEBUF<%p,%d>", cmd->SCp.ptr, cmd->SCp.this_residual);
-#endif
- /*
- * wd33c93 shouldn't pass us bogus dma_setups, but
- * it does:-( The other wd33c93 drivers deal with
- * it the same way (which isn't that obvious).
- * IMHO a better fix would be, not to do these
- * dma setups in the first place
- */
- if (cmd->SCp.ptr == NULL)
- return 1;
- fill_hpc_entries (&hcp, cmd->SCp.ptr,cmd->SCp.this_residual);
- write_wd33c93_count(regs, cmd->SCp.this_residual);
- }
+ /*
+ * wd33c93 shouldn't pass us bogus dma_setups, but
+ * it does:-( The other wd33c93 drivers deal with
+ * it the same way (which isn't that obvious).
+ * IMHO a better fix would be, not to do these
+ * dma setups in the first place
+ */
+ if (cmd->SCp.ptr == NULL)
+ return 1;
+ fill_hpc_entries (&hcp, cmd->SCp.ptr,cmd->SCp.this_residual);
/* To make sure, if we trip an HPC bug, that we transfer
* every single byte, we tag on an extra zero length dma
@@ -196,44 +170,6 @@
}
hregs->ctrl = 0;
- /* See how far we got and update scatterlist state if necessary. */
- if(SCpnt->SCp.buffers_residual) {
- struct scatterlist *slp = SCpnt->SCp.buffer;
- int totlen, wd93_residual, transferred, i;
-
- /* Yep, we were doing the scatterlist thang. */
- totlen = hdata->dma_bounce_len;
- wd93_residual = read_wd33c93_count(regp);
- transferred = totlen - wd93_residual;
-
-#ifdef DEBUG_DMA
- printk("tlen<%d>resid<%d>transf<%d> ",
- totlen, wd93_residual, transferred);
-#endif
-
- /* Avoid long winded partial-transfer search for common case. */
- if(transferred != totlen) {
- /* This is the nut case. */
-#ifdef DEBUG_DMA
- printk("Jed was here...");
-#endif
- for(i = 0; i <= SCpnt->SCp.buffers_residual; i++) {
- if(slp[i].length >= transferred)
- break;
- transferred -= slp[i].length;
- }
- } else {
- /* This is the common case. */
-#ifdef DEBUG_DMA
- printk("did it all...");
-#endif
- i = SCpnt->SCp.buffers_residual;
- }
- SCpnt->SCp.buffer = &slp[i];
- SCpnt->SCp.buffers_residual = SCpnt->SCp.buffers_residual - i;
- SCpnt->SCp.ptr = (char *) slp[i].address;
- SCpnt->SCp.this_residual = slp[i].length;
- }
#ifdef DEBUG_DMA
printk("\n");
#endif
Index: wd33c93.c
===================================================================
RCS file: /cvs/linux/drivers/scsi/wd33c93.c,v
retrieving revision 1.19
diff -u -r1.19 wd33c93.c
--- wd33c93.c 2001/11/06 07:56:05 1.19
+++ wd33c93.c 2001/12/10 20:06:01
@@ -612,6 +612,7 @@
(is_dir_out(cmd))?DATA_OUT_DIR:DATA_IN_DIR))
write_wd33c93_count(regs, 0); /* guarantee a DATA_PHASE interrupt */
else {
+ write_wd33c93_count(regs, cmd->SCp.this_residual);
write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA);
hostdata->dma = D_DMA_RUNNING;
}
@@ -733,6 +734,7 @@
hostdata->dma_cnt++;
#endif
write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA);
+ write_wd33c93_count(regs, cmd->SCp.this_residual);
if ((hostdata->level2 >= L2_DATA) ||
(hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) {
Flo
--
Florian Lohoff flo@rfc822.org +49-5201-669912
Nine nineth on september the 9th Welcome to the new billenium
PGP signature