diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2014-11-12 08:12:15 +0300 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-11-20 11:11:17 +0300 |
commit | e3c3da67340ac7d1d2f630f319eb718474b0d9c3 (patch) | |
tree | 3786bf1885076bc2ef606aab34d0f9cd357c7980 /drivers/scsi/atari_scsi.c | |
parent | ef1081cbf05b22d3d0e05b267a5559a8cd8e8d4a (diff) | |
download | linux-e3c3da67340ac7d1d2f630f319eb718474b0d9c3.tar.xz |
atari_NCR5380: Refactor Falcon locking
Simplify falcon_release_lock_if_possible() by making callers responsible for
disabling local IRQ's, which they must do anyway to correctly synchronize
the ST DMA "lock" with core driver data structures. Move this
synchronization logic to the core driver with which it is tightly coupled.
Other LLD's like sun3_scsi and mac_scsi that can make use of this core
driver can just stub out the NCR5380_acquire_dma_irq() and
NCR5380_release_dma_irq() calls so the compiler will eliminate the
ST DMA code.
Remove a redundant local_irq_save/restore pair (irq's are disabled for
interrupt handlers these days). Revise the locking for
atari_scsi_bus_reset(): use local_irq_save/restore() instead of
atari_turnoff/turnon_irq(). There is no guarantee that atari_scsi still
holds the ST DMA lock during EH, so atari_turnoff/turnon_irq() could
end up dropping an IDE or floppy interrupt.
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/atari_scsi.c')
-rw-r--r-- | drivers/scsi/atari_scsi.c | 47 |
1 files changed, 17 insertions, 30 deletions
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 70c662f9fee4..045112186f84 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -109,6 +109,9 @@ #define NCR5380_dma_xfer_len(instance, cmd, phase) \ atari_dma_xfer_len(cmd->SCp.this_residual, cmd, !((phase) & SR_IO)) +#define NCR5380_acquire_dma_irq(instance) falcon_get_lock() +#define NCR5380_release_dma_irq(instance) falcon_release_lock() + #include "NCR5380.h" @@ -448,23 +451,13 @@ static void atari_scsi_fetch_restbytes(void) * connected command and the disconnected queue is empty. */ -static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata) +static void falcon_release_lock(void) { - unsigned long flags; - if (IS_A_TT()) return; - local_irq_save(flags); - - if (!hostdata->disconnected_queue && - !hostdata->issue_queue && - !hostdata->connected && - !hostdata->retain_dma_intr && - stdma_is_locked_by(scsi_falcon_intr)) + if (stdma_is_locked_by(scsi_falcon_intr)) stdma_release(); - - local_irq_restore(flags); } /* This function manages the locking of the ST-DMA. @@ -787,36 +780,30 @@ static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value) static int atari_scsi_bus_reset(struct scsi_cmnd *cmd) { int rv; - struct NCR5380_hostdata *hostdata = shost_priv(cmd->device->host); + unsigned long flags; + + local_irq_save(flags); - /* For doing the reset, SCSI interrupts must be disabled first, - * since the 5380 raises its IRQ line while _RST is active and we - * can't disable interrupts completely, since we need the timer. - */ - /* And abort a maybe active DMA transfer */ - if (IS_A_TT()) { - atari_turnoff_irq(IRQ_TT_MFP_SCSI); #ifdef REAL_DMA + /* Abort a maybe active DMA transfer */ + if (IS_A_TT()) { tt_scsi_dma.dma_ctrl = 0; -#endif } else { - atari_turnoff_irq(IRQ_MFP_FSCSI); -#ifdef REAL_DMA st_dma.dma_mode_status = 0x90; atari_dma_active = 0; atari_dma_orig_addr = NULL; -#endif } +#endif rv = NCR5380_bus_reset(cmd); - if (IS_A_TT()) - atari_turnon_irq(IRQ_TT_MFP_SCSI); - else - atari_turnon_irq(IRQ_MFP_FSCSI); + /* The 5380 raises its IRQ line while _RST is active but the ST DMA + * "lock" has been released so this interrupt may end up handled by + * floppy or IDE driver (if one of them holds the lock). The NCR5380 + * interrupt flag has been cleared already. + */ - if (rv == SUCCESS) - falcon_release_lock_if_possible(hostdata); + local_irq_restore(flags); return rv; } |