forked from Minki/linux
ncr5380: Implement new eh_bus_reset_handler
NCR5380.c lacks a sane eh_bus_reset_handler. The atari_NCR5380.c code is much better but it should not throw out the issue queue (that would be a host reset) and it neglects to set the result code for commands that it throws out. Fix these bugs and keep the two core drivers in sync. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Reviewed-by: Hannes Reinecke <hare@suse.com> Tested-by: Ondrej Zary <linux@rainbow-software.org> Tested-by: Michael Schmitz <schmitzmic@gmail.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
707d62b37f
commit
62717f537e
@ -2482,18 +2482,66 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct Scsi_Host *instance = cmd->device->host;
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
int i;
|
||||
unsigned long flags;
|
||||
struct NCR5380_cmd *ncmd;
|
||||
|
||||
spin_lock_irqsave(&hostdata->lock, flags);
|
||||
|
||||
#if (NDEBUG & NDEBUG_ANY)
|
||||
scmd_printk(KERN_INFO, cmd, "performing bus reset\n");
|
||||
scmd_printk(KERN_INFO, cmd, __func__);
|
||||
#endif
|
||||
NCR5380_dprint(NDEBUG_ANY, instance);
|
||||
NCR5380_dprint_phase(NDEBUG_ANY, instance);
|
||||
|
||||
do_reset(instance);
|
||||
|
||||
/* reset NCR registers */
|
||||
NCR5380_write(MODE_REG, MR_BASE);
|
||||
NCR5380_write(TARGET_COMMAND_REG, 0);
|
||||
NCR5380_write(SELECT_ENABLE_REG, 0);
|
||||
|
||||
/* After the reset, there are no more connected or disconnected commands
|
||||
* and no busy units; so clear the low-level status here to avoid
|
||||
* conflicts when the mid-level code tries to wake up the affected
|
||||
* commands!
|
||||
*/
|
||||
|
||||
hostdata->selecting = NULL;
|
||||
|
||||
list_for_each_entry(ncmd, &hostdata->disconnected, list) {
|
||||
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
|
||||
|
||||
set_host_byte(cmd, DID_RESET);
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
list_for_each_entry(ncmd, &hostdata->autosense, list) {
|
||||
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
|
||||
|
||||
set_host_byte(cmd, DID_RESET);
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
if (hostdata->connected) {
|
||||
set_host_byte(hostdata->connected, DID_RESET);
|
||||
complete_cmd(instance, hostdata->connected);
|
||||
hostdata->connected = NULL;
|
||||
}
|
||||
|
||||
if (hostdata->sensing) {
|
||||
set_host_byte(hostdata->connected, DID_RESET);
|
||||
complete_cmd(instance, hostdata->sensing);
|
||||
hostdata->sensing = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
hostdata->busy[i] = 0;
|
||||
#ifdef REAL_DMA
|
||||
hostdata->dma_len = 0;
|
||||
#endif
|
||||
|
||||
queue_work(hostdata->work_q, &hostdata->main_task);
|
||||
spin_unlock_irqrestore(&hostdata->lock, flags);
|
||||
|
||||
return SUCCESS;
|
||||
|
@ -2694,11 +2694,12 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
int i;
|
||||
unsigned long flags;
|
||||
struct NCR5380_cmd *ncmd;
|
||||
|
||||
spin_lock_irqsave(&hostdata->lock, flags);
|
||||
|
||||
#if (NDEBUG & NDEBUG_ANY)
|
||||
scmd_printk(KERN_INFO, cmd, "performing bus reset\n");
|
||||
scmd_printk(KERN_INFO, cmd, __func__);
|
||||
#endif
|
||||
NCR5380_dprint(NDEBUG_ANY, instance);
|
||||
NCR5380_dprint_phase(NDEBUG_ANY, instance);
|
||||
@ -2718,27 +2719,32 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
|
||||
|
||||
hostdata->selecting = NULL;
|
||||
|
||||
if (hostdata->connected)
|
||||
dsprintk(NDEBUG_ABORT, instance, "reset aborted a connected command\n");
|
||||
hostdata->connected = NULL;
|
||||
list_for_each_entry(ncmd, &hostdata->disconnected, list) {
|
||||
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
|
||||
|
||||
set_host_byte(cmd, DID_RESET);
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
list_for_each_entry(ncmd, &hostdata->autosense, list) {
|
||||
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
|
||||
|
||||
set_host_byte(cmd, DID_RESET);
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
if (hostdata->connected) {
|
||||
set_host_byte(hostdata->connected, DID_RESET);
|
||||
complete_cmd(instance, hostdata->connected);
|
||||
hostdata->connected = NULL;
|
||||
}
|
||||
|
||||
if (hostdata->sensing) {
|
||||
set_host_byte(hostdata->connected, DID_RESET);
|
||||
complete_cmd(instance, hostdata->sensing);
|
||||
hostdata->sensing = NULL;
|
||||
}
|
||||
|
||||
if (!list_empty(&hostdata->autosense))
|
||||
dsprintk(NDEBUG_ABORT, instance, "reset aborted autosense list\n");
|
||||
INIT_LIST_HEAD(&hostdata->autosense);
|
||||
|
||||
if (!list_empty(&hostdata->unissued))
|
||||
dsprintk(NDEBUG_ABORT, instance, "reset aborted unissued list\n");
|
||||
INIT_LIST_HEAD(&hostdata->unissued);
|
||||
|
||||
if (!list_empty(&hostdata->disconnected))
|
||||
dsprintk(NDEBUG_ABORT, instance, "reset aborted disconnected list\n");
|
||||
INIT_LIST_HEAD(&hostdata->disconnected);
|
||||
|
||||
#ifdef SUPPORT_TAGS
|
||||
free_all_tags(hostdata);
|
||||
#endif
|
||||
@ -2748,6 +2754,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
|
||||
hostdata->dma_len = 0;
|
||||
#endif
|
||||
|
||||
queue_work(hostdata->work_q, &hostdata->main_task);
|
||||
maybe_release_dma_irq(instance);
|
||||
spin_unlock_irqrestore(&hostdata->lock, flags);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user