Hi again
A patch to tmscsim.c, removing bus_to_virt() and, while at it, cleaning up
cpu / le32 conversions, could look something like this. Notice, it uses
the same <...>_k(un)map_atomic_sg() as proposed for dc395x, so, certainly
this is not a final patch - in the end those function would migrate to
something like scsi_lib.c(?). No, I still don't know how to test those PIO
paths.
Kurt, there are your comments in dc395x.c around the PIO code. Have you
found out when and how it gets invoked? Do you still remember? Any hints
for testing possibilities?
Thanks
Guennadi
---
Guennadi Liakhovetski
diff -u a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
--- a/drivers/scsi/tmscsim.c 13 Jan 2005 21:10:01
+++ b/drivers/scsi/tmscsim.c 21 Apr 2005 21:36:51
@@ -856,8 +856,8 @@
pSRB->pSegmentList++;
psgl = pSRB->pSegmentList;
- pSRB->SGBusAddr =
cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
- pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
+ pSRB->SGBusAddr = sg_dma_address(psgl);
+ pSRB->SGToBeXferLen = sg_dma_len(psgl);
}
else
pSRB->SGToBeXferLen = 0;
@@ -882,10 +882,42 @@
}
}
+
+/**
+ * dc390_kmap_atomic_sg - find and atomically map an sg-elemnt
+ * @sg: scatter-gather list
+ * @sg_count: number of segments in sg
+ * @offset: offset in bytes into sg
+ * @len: on return number of bytes mapped
+ *
+ * Return virtual address
+ */
+static void *dc390_kmap_atomic_sg(struct scatterlist *sg, int sg_count, size_t
offset, size_t *len)
+{
+ int i;
+ size_t sg_len = 0;
+
+ for (i = 0; i < sg_count; i++) {
+ sg_len += sg[i].length;
+ if (sg_len > offset)
+ break;
+ }
+
+ BUG_ON(i == sg_count);
+
+ *len = sg_len - offset;
+
+ return kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset +
sg[i].length - *len;
+}
+
+static void dc390_kunmap_atomic_sg(void *virt)
+{
+ kunmap_atomic(virt_to_page(virt), KM_BIO_SRC_IRQ);
+}
static void
dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
{
- u8 sstatus, residual, bval;
+ u8 sstatus;
struct scatterlist *psgl;
u32 ResidCnt, i;
unsigned long xferCnt;
@@ -931,16 +963,17 @@
pSRB->pSegmentList++;
psgl = pSRB->pSegmentList;
- pSRB->SGBusAddr =
cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
- pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
+ pSRB->SGBusAddr = sg_dma_address(psgl);
+ pSRB->SGToBeXferLen = sg_dma_len(psgl);
}
else
pSRB->SGToBeXferLen = 0;
}
else /* phase changed */
{
- residual = 0;
- bval = DC390_read8 (Current_Fifo);
+ u8 residual = 0;
+ u8 bval = DC390_read8 (Current_Fifo);
+
while( bval & 0x1f )
{
DEBUG1(printk (KERN_DEBUG "Check for residuals,"));
@@ -988,10 +1021,20 @@
if( residual )
{
+ size_t count = 1;
+ unsigned long flags;
+
bval = DC390_read8 (ScsiFifo); /* get one residual byte */
- ptr = (u8 *) bus_to_virt( pSRB->SGBusAddr );
+
+ local_irq_save(flags);
+ ptr = (u8*)dc390_kmap_atomic_sg(pSRB->pSegmentList,
pSRB->SGcount, pSRB->TotalXferredLen, &count);
+
*ptr = bval;
- pSRB->SGBusAddr++; xferCnt++;
+ dc390_kunmap_atomic_sg(ptr);
+ local_irq_restore(flags);
+
+ pSRB->SGBusAddr++;
+ xferCnt++;
pSRB->TotalXferredLen++;
pSRB->SGToBeXferLen--;
}
@@ -1212,32 +1255,31 @@
{
struct scsi_cmnd *pcmd = pSRB->pcmd;
struct scatterlist *psgl;
+
pSRB->TotalXferredLen = 0;
pSRB->SGIndex = 0;
if (pcmd->use_sg) {
+ unsigned long last_xfer;
+
pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
- psgl = pSRB->pSegmentList;
- //dc390_pci_sync(pSRB);
- while (pSRB->TotalXferredLen + (unsigned long) sg_dma_len(psgl) <
pSRB->Saved_Ptr)
- {
- pSRB->TotalXferredLen += (unsigned long) sg_dma_len(psgl);
- pSRB->SGIndex++;
- if( pSRB->SGIndex < pSRB->SGcount )
- {
- pSRB->pSegmentList++;
- psgl = pSRB->pSegmentList;
- pSRB->SGBusAddr =
cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
- pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
- }
- else
- pSRB->SGToBeXferLen = 0;
+ for (psgl = pSRB->pSegmentList; pSRB->TotalXferredLen +
sg_dma_len(psgl) < pSRB->Saved_Ptr; psgl++) {
+ pSRB->TotalXferredLen += sg_dma_len(psgl);
+ pSRB->SGIndex++;
}
- pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
- pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
- printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus
%08lx\n",
- pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
+ BUG_ON(pSRB->SGIndex >= pSRB->SGcount);
+
+ last_xfer = pSRB->Saved_Ptr - pSRB->TotalXferredLen;
+
+ pSRB->pSegmentList += pSRB->SGIndex;
+ pSRB->SGBusAddr = sg_dma_address(psgl) + last_xfer;
+ pSRB->SGToBeXferLen = sg_dma_len(psgl) - last_xfer;
+
+ //dc390_pci_sync(pSRB);
+
+ DEBUG0(printk(KERN_INFO "DC390: Pointer restored. Segment %i, Total
%li, Bus %08lx\n",
+ pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr));
} else if(pcmd->request_buffer) {
//dc390_pci_sync(pSRB);
@@ -1245,11 +1287,11 @@
pSRB->SGcount = 1;
pSRB->pSegmentList = (struct scatterlist *) &pSRB->Segmentx;
} else {
- pSRB->SGcount = 0;
- printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without
Scatter-Gather ??\n");
+ pSRB->SGcount = 0;
+ printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without
Scatter-Gather ??\n");
}
- pSRB->TotalXferredLen = pSRB->Saved_Ptr;
+ pSRB->TotalXferredLen = pSRB->Saved_Ptr;
}
@@ -1385,8 +1427,8 @@
if( !pSRB->SGToBeXferLen )
{
psgl = pSRB->pSegmentList;
- pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
- pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
+ pSRB->SGBusAddr = sg_dma_address(psgl);
+ pSRB->SGToBeXferLen = sg_dma_len(psgl);
DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
}
lval = pSRB->SGToBeXferLen;
@@ -1397,8 +1439,8 @@
lval >>= 8;
DC390_write8 (CtcReg_High, (u8) lval);
- DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
- DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
+ DC390_write32 (DMA_XferCnt, cpu_to_le32(pSRB->SGToBeXferLen));
+ DC390_write32 (DMA_XferAddr, cpu_to_le32((u32)pSRB->SGBusAddr));
//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */
pSRB->SRBState = SRB_DATA_XFER;
@@ -2036,7 +2078,7 @@
if (pSRB)
{
- printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08x, Phase
%02x\n",
+ printk ("DC390: SRB: Xferred %08lx, Remain %08x, State %08x, Phase
%02x\n",
pSRB->TotalXferredLen, pSRB->SGToBeXferLen, pSRB->SRBState,
pSRB->ScsiPhase);
printk ("DC390: AdpaterStatus: %02x, SRB Status %02x\n",
pSRB->AdaptStatus, pSRB->SRBStatus);
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html