Commit 85923211 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by James Bottomley

[SCSI] tmscsim: Remove the last bus_to_virt()

Dynamically map the buffer for PIO for the residue byte.
Signed-off-by: default avatarG. Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 46e5ba2b
...@@ -351,6 +351,27 @@ static u8 dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20}; ...@@ -351,6 +351,27 @@ static u8 dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
* (DCBs, SRBs, Queueing) * (DCBs, SRBs, Queueing)
* *
**********************************************************************/ **********************************************************************/
static void inline dc390_start_segment(struct dc390_srb* pSRB)
{
struct scatterlist *psgl = pSRB->pSegmentList;
/* start new sg segment */
pSRB->SGBusAddr = sg_dma_address(psgl);
pSRB->SGToBeXferLen = sg_dma_len(psgl);
}
static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue)
{
unsigned long xfer = pSRB->SGToBeXferLen - residue;
/* xfer more bytes transferred */
pSRB->SGBusAddr += xfer;
pSRB->TotalXferredLen += xfer;
pSRB->SGToBeXferLen = residue;
return xfer;
}
static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun) static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
{ {
struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL; struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL;
...@@ -741,11 +762,10 @@ static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id) ...@@ -741,11 +762,10 @@ static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id)
} }
static void static void
dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
{ {
u8 sstatus; u8 sstatus;
struct scatterlist *psgl; u32 ResidCnt;
u32 ResidCnt, xferCnt;
u8 dstate = 0; u8 dstate = 0;
sstatus = *psstatus; sstatus = *psstatus;
...@@ -776,25 +796,20 @@ dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) ...@@ -776,25 +796,20 @@ dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
if( pSRB->SGIndex < pSRB->SGcount ) if( pSRB->SGIndex < pSRB->SGcount )
{ {
pSRB->pSegmentList++; pSRB->pSegmentList++;
psgl = pSRB->pSegmentList;
pSRB->SGBusAddr = sg_dma_address(psgl); dc390_start_segment(pSRB);
pSRB->SGToBeXferLen = sg_dma_len(psgl);
} }
else else
pSRB->SGToBeXferLen = 0; pSRB->SGToBeXferLen = 0;
} }
else else
{ {
ResidCnt = (u32) DC390_read8 (Current_Fifo) & 0x1f; ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
ResidCnt |= (u32) DC390_read8 (CtcReg_High) << 16; (((u32) DC390_read8 (CtcReg_High) << 16) |
ResidCnt |= (u32) DC390_read8 (CtcReg_Mid) << 8; ((u32) DC390_read8 (CtcReg_Mid) << 8) |
ResidCnt += (u32) DC390_read8 (CtcReg_Low); (u32) DC390_read8 (CtcReg_Low));
xferCnt = pSRB->SGToBeXferLen - ResidCnt; dc390_advance_segment(pSRB, ResidCnt);
pSRB->SGBusAddr += xferCnt;
pSRB->TotalXferredLen += xferCnt;
pSRB->SGToBeXferLen = ResidCnt;
} }
} }
if ((*psstatus & 7) != SCSI_DATA_OUT) if ((*psstatus & 7) != SCSI_DATA_OUT)
...@@ -805,13 +820,11 @@ dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) ...@@ -805,13 +820,11 @@ dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
} }
static void static void
dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
{ {
u8 sstatus, residual, bval; u8 sstatus, residual, bval;
struct scatterlist *psgl; u32 ResidCnt, i;
u32 ResidCnt, i;
unsigned long xferCnt; unsigned long xferCnt;
u8 *ptr;
sstatus = *psstatus; sstatus = *psstatus;
...@@ -851,10 +864,8 @@ dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) ...@@ -851,10 +864,8 @@ dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
if( pSRB->SGIndex < pSRB->SGcount ) if( pSRB->SGIndex < pSRB->SGcount )
{ {
pSRB->pSegmentList++; pSRB->pSegmentList++;
psgl = pSRB->pSegmentList;
pSRB->SGBusAddr = sg_dma_address(psgl); dc390_start_segment(pSRB);
pSRB->SGToBeXferLen = sg_dma_len(psgl);
} }
else else
pSRB->SGToBeXferLen = 0; pSRB->SGToBeXferLen = 0;
...@@ -894,41 +905,38 @@ dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) ...@@ -894,41 +905,38 @@ dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
/* It seems a DMA Blast abort isn't that bad ... */ /* It seems a DMA Blast abort isn't that bad ... */
if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n"); if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
//DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24; dc390_laststatus &= ~0xff000000;
dc390_laststatus |= bval << 24;
DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval)); DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
ResidCnt = (u32) DC390_read8 (CtcReg_High); ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
ResidCnt <<= 8; ((u32) DC390_read8 (CtcReg_Mid) << 8)) |
ResidCnt |= (u32) DC390_read8 (CtcReg_Mid); (u32) DC390_read8 (CtcReg_Low);
ResidCnt <<= 8;
ResidCnt |= (u32) DC390_read8 (CtcReg_Low); xferCnt = dc390_advance_segment(pSRB, ResidCnt);
xferCnt = pSRB->SGToBeXferLen - ResidCnt; if (residual) {
pSRB->SGBusAddr += xferCnt; size_t count = 1;
pSRB->TotalXferredLen += xferCnt; size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList);
pSRB->SGToBeXferLen = ResidCnt; unsigned long flags;
u8 *ptr;
if( residual )
{
static int feedback_requested;
bval = DC390_read8 (ScsiFifo); /* get one residual byte */ bval = DC390_read8 (ScsiFifo); /* get one residual byte */
if (!feedback_requested) { local_irq_save(flags);
feedback_requested = 1; ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count);
printk(KERN_WARNING "%s: Please, contact <linux-scsi@vger.kernel.org> " if (likely(ptr)) {
"to help improve support for your system.\n", __FILE__); *(ptr + offset) = bval;
scsi_kunmap_atomic_sg(ptr);
} }
local_irq_restore(flags);
WARN_ON(!ptr);
ptr = (u8 *) bus_to_virt( pSRB->SGBusAddr ); /* 1 more byte read */
*ptr = bval; xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1);
pSRB->SGBusAddr++;
xferCnt++;
pSRB->TotalXferredLen++;
pSRB->SGToBeXferLen--;
} }
DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\ DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
pSRB->TotalXferredLen, pSRB->SGToBeXferLen)); pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
} }
} }
if ((*psstatus & 7) != SCSI_DATA_IN) if ((*psstatus & 7) != SCSI_DATA_IN)
...@@ -1137,7 +1145,7 @@ dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB) ...@@ -1137,7 +1145,7 @@ dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB)
/* handle RESTORE_PTR */ /* handle RESTORE_PTR */
/* I presume, this command is already mapped, so, have to remap. */ /* This doesn't look very healthy... to-be-fixed */
static void static void
dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
{ {
...@@ -1146,6 +1154,7 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) ...@@ -1146,6 +1154,7 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
pSRB->TotalXferredLen = 0; pSRB->TotalXferredLen = 0;
pSRB->SGIndex = 0; pSRB->SGIndex = 0;
if (pcmd->use_sg) { if (pcmd->use_sg) {
size_t saved;
pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer; pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
psgl = pSRB->pSegmentList; psgl = pSRB->pSegmentList;
//dc390_pci_sync(pSRB); //dc390_pci_sync(pSRB);
...@@ -1157,15 +1166,16 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) ...@@ -1157,15 +1166,16 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
if( pSRB->SGIndex < pSRB->SGcount ) if( pSRB->SGIndex < pSRB->SGcount )
{ {
pSRB->pSegmentList++; pSRB->pSegmentList++;
psgl = pSRB->pSegmentList;
pSRB->SGBusAddr = sg_dma_address(psgl); dc390_start_segment(pSRB);
pSRB->SGToBeXferLen = sg_dma_len(psgl);
} }
else else
pSRB->SGToBeXferLen = 0; pSRB->SGToBeXferLen = 0;
} }
pSRB->SGToBeXferLen -= pSRB->Saved_Ptr - pSRB->TotalXferredLen;
pSRB->SGBusAddr += pSRB->Saved_Ptr - pSRB->TotalXferredLen; saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen;
pSRB->SGToBeXferLen -= saved;
pSRB->SGBusAddr += saved;
printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n", printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr); pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
...@@ -1286,7 +1296,6 @@ dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) ...@@ -1286,7 +1296,6 @@ dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
static void static void
dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
{ {
struct scatterlist *psgl;
unsigned long lval; unsigned long lval;
struct dc390_dcb* pDCB = pACB->pActiveDCB; struct dc390_dcb* pDCB = pACB->pActiveDCB;
...@@ -1315,9 +1324,8 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) ...@@ -1315,9 +1324,8 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
if( !pSRB->SGToBeXferLen ) if( !pSRB->SGToBeXferLen )
{ {
psgl = pSRB->pSegmentList; dc390_start_segment(pSRB);
pSRB->SGBusAddr = sg_dma_address(psgl);
pSRB->SGToBeXferLen = sg_dma_len(psgl);
DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.")); DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
} }
lval = pSRB->SGToBeXferLen; lval = pSRB->SGToBeXferLen;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment