Hi
I wonder if somebody could advice me. I am a SCSI LLDD developer.
I have a question about an implementation of eh_abort_handler()
for SCSI hosts when SCSI command timer is fired. I may check out
the queue and look for a command given as an argument to abort.
But, what I should do when the command is being processed. I can
not abort it halfway.
As I saw a statement to check if scmd->serial_number has been
cleared in scsi_try_to_abort_cmd, I got to think it makes sense
that let LLDD to keep processing the command and be going to call
scsi_done().
static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
{
unsigned long flags;
int rtn = FAILED;
if (!scmd->device->host->hostt->eh_abort_handler)
return rtn;
/*
* scsi_done was called just after the command timed out and
* before
* we had a chance to process it. (db)
*/
>> if (scmd->serial_number == 0)
return SUCCESS;
scmd->owner = SCSI_OWNER_LOWLEVEL;
spin_lock_irqsave(scmd->device->host->host_lock, flags);
rtn = scmd->device->host->hostt->eh_abort_handler(scmd);
spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
return rtn;
}
I soon realized this idea is wrong. Any calling scsi_done() isn't
significant after the timer is fired.
void scsi_done(struct scsi_cmnd *cmd)
{
/*
* We don't have to worry about this one timing out any more.
* If we are unable to remove the timer, then the command
* has already timed out. In which case, we have no choice but
* to
* let the timeout function run, as we have no idea where in
* fact
* that function could really be. It might be on another
* processor,
* etc, etc.
*/
if (!scsi_delete_timer(cmd))
return;
__scsi_done(cmd);
}
int scsi_delete_timer(struct scsi_cmnd *scmd)
{
int rtn;
rtn = del_timer(&scmd->eh_timeout);
SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p,"
" rtn: %d\n", __FUNCTION__,
scmd, rtn));
scmd->eh_timeout.data = (unsigned long)NULL;
scmd->eh_timeout.function = NULL;
return rtn;
}
LLDD calls scsi_done() and forget about the command. Therefore, I think
it could make sense to set cmd->serial_number = 0 in scsi_done() even
after the timer is fired.
void scsi_done(struct scsi_cmnd *cmd)
{
---- snip ----
if (!scsi_delete_timer(cmd)) {
cmd->serial_number = 0;
return;
}
__scsi_done(cmd);
}
Or I should properly implement an error recovery function using
scsi_transport interface? I mean I return EH_HANDLED in
scmd->device->host->transportt->eh_timed_out(scmd)
Thanks and regrds,
Hiroki Takada
--
----------------------------------------------------------
Hiroki Takada <[EMAIL PROTECTED]>
Engineering Development Group, Super Storage Div.
Core Micro Systems Inc.
2-22-2, Koishikawa, Bunkyo-Ku, Tokyo 112-0002
TEL : +81-50-5558-5410 (IP Phone)
TEL : +81-3-5802-6872 / FAX : +81-3-5802-5113
-
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