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:
Finn Thain 2016-01-03 16:06:03 +11:00 committed by Martin K. Petersen
parent 707d62b37f
commit 62717f537e
2 changed files with 72 additions and 17 deletions

View File

@ -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;

View File

@ -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);