diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2016-01-03 16:06:02 +1100 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-01-06 21:43:08 -0500 |
commit | 707d62b37fbb1de74da6e5cf263bcd8223ae3cf7 (patch) | |
tree | 21db484b3859630593a189a59838f312ebd81498 /drivers/scsi/NCR5380.h | |
parent | 8b00c3d5d40da0477fceffadcfbc2c09f24104d0 (diff) |
ncr5380: Fix EH during arbitration and selection
During arbitration and selection, the relevant command is invisible to
exception handlers and can be found only in a pointer on the stack of a
different thread.
When eh_abort_handler can't find a given command, it can't decide whether
that command was completed already or is still in arbitration or selection
phase. But it must return either SUCCESS (e.g. command completed earlier)
or FAILED (could not abort the nexus, try bus reset).
The solution is to make sure all commands belonging to the LLD are always
visible to exception handlers. Add another scsi_cmnd pointer to the
hostdata struct to track the command in arbitration or selection phase.
Replace 'retain_dma_irq' with the new 'selecting' pointer, to bring
atari_NCR5380.c into line with NCR5380.c.
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>
Diffstat (limited to 'drivers/scsi/NCR5380.h')
-rw-r--r-- | drivers/scsi/NCR5380.h | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 81e077afa8db..ee83ab5f32e8 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -255,6 +255,7 @@ struct NCR5380_hostdata { #endif unsigned char last_message; /* last message OUT */ struct scsi_cmnd *connected; /* currently connected cmnd */ + struct scsi_cmnd *selecting; /* cmnd to be connected */ struct list_head unissued; /* waiting to be issued */ struct list_head autosense; /* priority issue queue */ struct list_head disconnected; /* waiting for reconnect */ @@ -265,7 +266,6 @@ struct NCR5380_hostdata { char info[256]; int read_overruns; /* number of bytes to cut from a * transfer to handle chip overruns */ - int retain_dma_intr; struct work_struct main_task; #ifdef SUPPORT_TAGS struct tag_alloc TagAlloc[8][8]; /* 8 targets and 8 LUNs */ @@ -329,7 +329,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id); static void NCR5380_main(struct work_struct *work); static const char *NCR5380_info(struct Scsi_Host *instance); static void NCR5380_reselect(struct Scsi_Host *instance); -static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd); +static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); #if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL) static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); #endif |