Commit 584a5da2 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by James Bottomley

[PATCH] tmscsim: (CH) Fix error handling

I might be wrong, but it looks like the attached patch has still not been
applied, although it is pretty important - it fixes error handling in
tmscsim. E.g., it was reported, that this patch fixes a problem with
tmscsim in 2.6.7 with a SCSI-3 scanner, that doesn't support REPORT LUNS
command.
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 118dcd8d
/***********************************************************************
* FILE NAME : DC390.H *
* BY : C.L. Huang *
* Description: Device Driver for Tekram DC-390(T) PCI SCSI *
* Bus Master Host Adapter *
***********************************************************************/
/* $Id: dc390.h,v 2.43.2.22 2000/12/20 00:39:36 garloff Exp $ */
/*
* DC390/AMD 53C974 driver, header file
*/
#ifndef DC390_H
#define DC390_H
#include <linux/version.h>
#define DC390_BANNER "Tekram DC390/AM53C974"
#define DC390_VERSION "2.1d 2004-05-27"
/* We don't have eh_abort_handler, eh_device_reset_handler,
* eh_bus_reset_handler, eh_host_reset_handler yet!
* So long: Use old exception handling :-( */
#define OLD_EH
#if LINUX_VERSION_CODE < KERNEL_VERSION (2,1,70) || defined (OLD_EH)
# define NEW_EH
#else
# define NEW_EH use_new_eh_code: 1,
# define USE_NEW_EH
#endif
#endif /* DC390_H */
......@@ -1632,18 +1632,6 @@ dc390_DoingSRB_Done(struct dc390_acb* pACB, struct scsi_cmnd *cmd)
psrb2 = psrb->pNextSRB;
pcmd = psrb->pcmd;
dc390_Free_insert (pACB, psrb);
#ifndef USE_NEW_EH
/* New EH will crash on being given timed out cmnds */
if (pcmd == cmd)
pcmd->result = MK_RES(0,DID_ABORT,0,0);
else
pcmd->result = MK_RES(0,DID_RESET,0,0);
/* ReleaseSRB( pDCB, pSRB ); */
DEBUG0(printk (KERN_DEBUG "DC390: DoingSRB_Done: done pid %li\n", pcmd->pid));
pcmd->scsi_done( pcmd );
#endif
psrb = psrb2;
}
pdcb->GoingSRBCnt = 0;
......
......@@ -240,17 +240,15 @@
#include <linux/spinlock.h>
#include <asm/io.h>
#if 0
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#else
#include "scsi.h"
#endif
#include <scsi/scsi_host.h>
#include <scsi/scsicam.h>
#include "dc390.h"
#define DC390_BANNER "Tekram DC390/AM53C974"
#define DC390_VERSION "2.1d 2004-05-27"
#define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI
......@@ -302,7 +300,6 @@ static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start,
static struct dc390_acb* dc390_pACB_start= NULL;
static struct dc390_acb* dc390_pACB_current = NULL;
static unsigned long dc390_lastabortedpid = 0;
static u32 dc390_laststatus = 0;
static u8 dc390_adapterCnt = 0;
......@@ -1215,146 +1212,54 @@ static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, stru
}
/***********************************************************************
* Function : int DC390_abort (struct scsi_cmnd *cmd)
*
* Purpose : Abort an errant SCSI command
*
* Inputs : cmd - command to abort
*
* Returns : 0 on success, -1 on failure.
*
* Status: Buggy !
***********************************************************************/
static int DC390_abort (struct scsi_cmnd *cmd)
static int DC390_abort(struct scsi_cmnd *cmd)
{
struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
struct dc390_srb *pSRB, *psrb;
u32 count, i;
int status;
//unsigned long sbac;
struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n",
cmd->pid, cmd->device->id, cmd->device->lun);
if( !pDCB ) goto NOT_RUN;
/* Added 98/07/02 KG */
/*
pSRB = pDCB->pActiveSRB;
if (pSRB && pSRB->pcmd == cmd )
goto ON_GOING;
*/
pSRB = pDCB->pWaitingSRB;
if( !pSRB )
goto ON_GOING;
struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
struct dc390_srb *pSRB, *psrb;
/* Now scan Waiting queue */
if( pSRB->pcmd == cmd )
{
pDCB->pWaitingSRB = pSRB->pNextSRB;
goto IN_WAIT;
}
else
{
psrb = pSRB;
if( !(psrb->pNextSRB) )
goto ON_GOING;
while( psrb->pNextSRB->pcmd != cmd )
{
psrb = psrb->pNextSRB;
if( !(psrb->pNextSRB) || psrb == pSRB)
goto ON_GOING;
}
pSRB = psrb->pNextSRB;
psrb->pNextSRB = pSRB->pNextSRB;
if( pSRB == pDCB->pWaitLast )
pDCB->pWaitLast = psrb;
IN_WAIT:
dc390_Free_insert (pACB, pSRB);
printk("DC390: Abort command (pid %li, Device %02i-%02i)\n",
cmd->pid, cmd->device->id, cmd->device->lun);
pSRB = pDCB->pWaitingSRB;
if (!pSRB)
goto on_going;
/* Now scan Waiting queue */
if (pSRB->pcmd != cmd) {
psrb = pSRB;
if (!(psrb->pNextSRB))
goto on_going;
while (psrb->pNextSRB->pcmd != cmd) {
psrb = psrb->pNextSRB;
if (!(psrb->pNextSRB) || psrb == pSRB)
goto on_going;
}
pSRB = psrb->pNextSRB;
psrb->pNextSRB = pSRB->pNextSRB;
if (pSRB == pDCB->pWaitLast)
pDCB->pWaitLast = psrb;
} else
pDCB->pWaitingSRB = pSRB->pNextSRB;
dc390_Free_insert(pACB, pSRB);
pDCB->WaitSRBCnt--;
INIT_LIST_HEAD((struct list_head*)&cmd->SCp);
status = SCSI_ABORT_SUCCESS;
goto ABO_X;
}
/* SRB has already been sent ! */
ON_GOING:
/* abort() is too stupid for already sent commands at the moment.
* If it's called we are in trouble anyway, so let's dump some info
* into the syslog at least. (KG, 98/08/20,99/06/20) */
dc390_dumpinfo (pACB, pDCB, pSRB);
pSRB = pDCB->pGoingSRB;
pDCB->DCBFlag |= ABORT_DEV_;
/* Now for the hard part: The command is currently processed */
for( count = pDCB->GoingSRBCnt, i=0; i<count; i++)
{
if( pSRB->pcmd != cmd )
pSRB = pSRB->pNextSRB;
else
{
if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) )
{
status = SCSI_ABORT_BUSY;
printk ("DC390: Abort current command (pid %li, SRB %p)\n",
cmd->pid, pSRB);
goto ABO_X;
}
else
{
status = SCSI_ABORT_SNOOZE;
goto ABO_X;
}
}
}
return SUCCESS;
NOT_RUN:
status = SCSI_ABORT_NOT_RUNNING;
on_going:
/* abort() is too stupid for already sent commands at the moment.
* If it's called we are in trouble anyway, so let's dump some info
* into the syslog at least. (KG, 98/08/20,99/06/20) */
dc390_dumpinfo(pACB, pDCB, pSRB);
ABO_X:
cmd->result = DID_ABORT << 16;
printk(KERN_INFO "DC390: Aborted pid %li with status %i\n", cmd->pid, status);
#if 0
if (cmd->pid == dc390_lastabortedpid) /* repeated failure ? */
{
/* Let's do something to help the bus getting clean again */
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
DC390_write8 (ScsiCmd, DMA_COMMAND);
//DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
//DC390_write8 (ScsiCmd, RESET_ATN_CMD);
DC390_write8 (ScsiCmd, NOP_CMD);
//udelay (10000);
//DC390_read8 (INT_Status);
//DC390_write8 (ScsiCmd, EN_SEL_RESEL);
}
sbac = DC390_read32 (DMA_ScsiBusCtrl);
if (sbac & SCSI_BUSY)
{ /* clear BSY, SEL and ATN */
printk (KERN_WARNING "DC390: Reset SCSI device: ");
//DC390_write32 (DMA_ScsiBusCtrl, (sbac | SCAM) & ~SCSI_LINES);
//udelay (250);
//sbac = DC390_read32 (DMA_ScsiBusCtrl);
//printk ("%08lx ", sbac);
//DC390_write32 (DMA_ScsiBusCtrl, sbac & ~(SCSI_LINES | SCAM));
//udelay (100);
//sbac = DC390_read32 (DMA_ScsiBusCtrl);
//printk ("%08lx ", sbac);
DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
udelay (250);
DC390_write8 (ScsiCmd, NOP_CMD);
sbac = DC390_read32 (DMA_ScsiBusCtrl);
printk ("%08lx\n", sbac);
}
#endif
dc390_lastabortedpid = cmd->pid;
//do_DC390_Interrupt (pACB->IRQLevel, 0, 0);
#ifndef USE_NEW_EH
if (status == SCSI_ABORT_SUCCESS) cmd->scsi_done(cmd);
#endif
return( status );
pDCB->DCBFlag |= ABORT_DEV_;
printk(KERN_INFO "DC390: Aborted pid %li\n", cmd->pid);
return FAILED;
}
......@@ -1381,93 +1286,38 @@ static void dc390_ResetDevParam( struct dc390_acb* pACB )
}
#if 0
/* Moves all SRBs from Going to Waiting for all DCBs */
static void dc390_RecoverSRB( struct dc390_acb* pACB )
{
struct dc390_dcb *pDCB, *pdcb;
struct dc390_srb *psrb, *psrb2;
u32 cnt, i;
pDCB = pACB->pLinkDCB;
if( !pDCB ) return;
pdcb = pDCB;
do
{
cnt = pdcb->GoingSRBCnt;
psrb = pdcb->pGoingSRB;
for (i=0; i<cnt; i++)
{
psrb2 = psrb;
psrb = psrb->pNextSRB;
/* dc390_RewaitSRB( pDCB, psrb ); */
if( pdcb->pWaitingSRB )
{
psrb2->pNextSRB = pdcb->pWaitingSRB;
pdcb->pWaitingSRB = psrb2;
}
else
{
pdcb->pWaitingSRB = psrb2;
pdcb->pWaitLast = psrb2;
psrb2->pNextSRB = NULL;
}
}
pdcb->GoingSRBCnt = 0;
pdcb->pGoingSRB = NULL;
pdcb->TagMask = 0;
pdcb = pdcb->pNextDCB;
} while( pdcb != pDCB );
}
#endif
/***********************************************************************
* Function : int DC390_reset (struct scsi_cmnd *cmd, ...)
*
* Purpose : perform a hard reset on the SCSI bus
*
* Inputs : cmd - command which caused the SCSI RESET
* resetFlags - how hard to try
*
* Returns : 0 on success.
***********************************************************************/
static int DC390_reset (struct scsi_cmnd *cmd)
static int DC390_bus_reset (struct scsi_cmnd *cmd)
{
u8 bval;
struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata;
struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata;
u8 bval;
printk(KERN_INFO "DC390: RESET ... ");
del_timer (&pACB->Waiting_Timer);
if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
bval = DC390_read8 (CtrlReg1);
bval |= DIS_INT_ON_SCSI_RST;
DC390_write8 (CtrlReg1, bval); /* disable IRQ on bus reset */
bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
DC390_write8(CtrlReg1, bval); /* disable IRQ on bus reset */
pACB->ACBFlag |= RESET_DEV;
dc390_ResetSCSIBus( pACB );
pACB->ACBFlag |= RESET_DEV;
dc390_ResetSCSIBus(pACB);
dc390_ResetDevParam( pACB );
udelay (1000);
pACB->pScsiHost->last_reset = jiffies + 3*HZ/2
dc390_ResetDevParam(pACB);
udelay(1000);
pACB->pScsiHost->last_reset = jiffies + 3*HZ/2
+ HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
DC390_read8 (INT_Status); /* Reset Pending INT */
DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
DC390_read8(INT_Status); /* Reset Pending INT */
dc390_DoingSRB_Done( pACB, cmd );
/* dc390_RecoverSRB (pACB); */
pACB->pActiveDCB = NULL;
dc390_DoingSRB_Done(pACB, cmd);
pACB->ACBFlag = 0;
bval = DC390_read8 (CtrlReg1);
bval &= ~DIS_INT_ON_SCSI_RST;
DC390_write8 (CtrlReg1, bval); /* re-enable interrupt */
pACB->pActiveDCB = NULL;
pACB->ACBFlag = 0;
bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST;
DC390_write8(CtrlReg1, bval); /* re-enable interrupt */
dc390_Waiting_process( pACB );
dc390_Waiting_process(pACB);
printk("done\n");
return( SCSI_RESET_SUCCESS );
return SUCCESS;
}
#include "scsiiom.c"
......@@ -1821,7 +1671,7 @@ static struct scsi_host_template driver_template = {
.slave_destroy = dc390_slave_destroy,
.queuecommand = DC390_queue_command,
.eh_abort_handler = DC390_abort,
.eh_bus_reset_handler = DC390_reset,
.eh_bus_reset_handler = DC390_bus_reset,
.bios_param = DC390_bios_param,
.can_queue = 42,
.this_id = 7,
......
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