* because also a timer int can trigger an abort or reset, which would
         * alter queues and touch the lock.
         */
-       if (!falcon_get_lock())
+       if (!NCR5380_acquire_dma_irq(instance))
                return SCSI_MLQUEUE_HOST_BUSY;
 
        local_irq_save(flags);
        return 0;
 }
 
+static inline void maybe_release_dma_irq(struct Scsi_Host *instance)
+{
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+       /* Caller does the locking needed to set & test these data atomically */
+       if (!hostdata->disconnected_queue &&
+           !hostdata->issue_queue &&
+           !hostdata->connected &&
+           !hostdata->retain_dma_intr)
+               NCR5380_release_dma_irq(instance);
+}
+
 /*
  * Function : NCR5380_main (void)
  *
                                        cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE);
 #endif
                                        if (!NCR5380_select(instance, tmp)) {
+                                               local_irq_disable();
                                                hostdata->retain_dma_intr--;
                                                /* release if target did not response! */
-                                               falcon_release_lock_if_possible(hostdata);
+                                               maybe_release_dma_irq(instance);
+                                               local_irq_restore(flags);
                                                break;
                                        } else {
                                                local_irq_disable();
                                case COMMAND_COMPLETE:
                                        /* Accept message by clearing ACK */
                                        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                                       /* ++guenther: possible race with Falcon locking */
-                                       hostdata->retain_dma_intr++;
-                                       hostdata->connected = NULL;
                                        dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu "
                                                  "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
+
+                                       local_irq_save(flags);
+                                       hostdata->retain_dma_intr++;
+                                       hostdata->connected = NULL;
 #ifdef SUPPORT_TAGS
                                        cmd_free_tag(cmd);
                                        if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
 
                                                dprintk(NDEBUG_AUTOSENSE, "scsi%d: performing request sense\n", HOSTNO);
 
-                                               local_irq_save(flags);
                                                LIST(cmd,hostdata->issue_queue);
                                                SET_NEXT(cmd, hostdata->issue_queue);
                                                hostdata->issue_queue = (struct scsi_cmnd *) cmd;
-                                               local_irq_restore(flags);
                                                dprintk(NDEBUG_QUEUES, "scsi%d: REQUEST SENSE added to head of "
                                                          "issue queue\n", H_NO(cmd));
                                        } else {
                                                cmd->scsi_done(cmd);
                                        }
 
+                                       local_irq_restore(flags);
+
                                        NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
                                        /*
                                         * Restore phase bits to 0 so an interrupted selection,
                                        while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
                                                barrier();
 
+                                       local_irq_save(flags);
                                        hostdata->retain_dma_intr--;
                                        /* ++roman: For Falcon SCSI, release the lock on the
                                         * ST-DMA here if no other commands are waiting on the
                                         * disconnected queue.
                                         */
-                                       falcon_release_lock_if_possible(hostdata);
+                                       maybe_release_dma_irq(instance);
+                                       local_irq_restore(flags);
                                        return;
                                case MESSAGE_REJECT:
                                        /* Accept message by clearing ACK */
                                hostdata->last_message = msgout;
                                NCR5380_transfer_pio(instance, &phase, &len, &data);
                                if (msgout == ABORT) {
+                                       local_irq_save(flags);
 #ifdef SUPPORT_TAGS
                                        cmd_free_tag(cmd);
 #else
 #endif
                                        hostdata->connected = NULL;
                                        cmd->result = DID_ERROR << 16;
-                                       cmd->scsi_done(cmd);
                                        NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                                       falcon_release_lock_if_possible(hostdata);
+                                       maybe_release_dma_irq(instance);
+                                       local_irq_restore(flags);
+                                       cmd->scsi_done(cmd);
                                        return;
                                }
                                msgout = NOP;
        unsigned char msg[3];
        unsigned char *data;
        struct scsi_cmnd *tmp = NULL, *prev;
-/*     unsigned long flags; */
 
        /*
         * Disable arbitration, etc. since the host adapter obviously
                    && (tag == tmp->tag)
 #endif
                    ) {
-                       /* ++guenther: prevent race with falcon_release_lock */
-                       hostdata->retain_dma_intr++;
                        if (prev) {
                                REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
                                SET_NEXT(prev, NEXT(tmp));
        hostdata->connected = tmp;
        dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n",
                   HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
-       hostdata->retain_dma_intr--;
 }
 
 
 #else
                        hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 #endif
+                       maybe_release_dma_irq(instance);
                        local_irq_restore(flags);
                        cmd->scsi_done(cmd);
-                       falcon_release_lock_if_possible(hostdata);
                        return SUCCESS;
                } else {
-/*                     local_irq_restore(flags); */
+                       local_irq_restore(flags);
                        printk("scsi%d: abort of connected command failed!\n", HOSTNO);
                        return FAILED;
                }
                        (*prev) = NEXT(tmp);
                        SET_NEXT(tmp, NULL);
                        tmp->result = DID_ABORT << 16;
+                       maybe_release_dma_irq(instance);
                        local_irq_restore(flags);
                        dprintk(NDEBUG_ABORT, "scsi%d: abort removed command from issue queue.\n",
                                    HOSTNO);
                        /* Tagged queuing note: no tag to free here, hasn't been assigned
                         * yet... */
                        tmp->scsi_done(tmp);
-                       falcon_release_lock_if_possible(hostdata);
                        return SUCCESS;
                }
        }
 #else
                                        hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 #endif
+                                       maybe_release_dma_irq(instance);
                                        local_irq_restore(flags);
                                        tmp->scsi_done(tmp);
-                                       falcon_release_lock_if_possible(hostdata);
                                        return SUCCESS;
                                }
                        }
                }
        }
 
+       /* Maybe it is sufficient just to release the ST-DMA lock... (if
+        * possible at all) At least, we should check if the lock could be
+        * released after the abort, in case it is kept due to some bug.
+        */
+       maybe_release_dma_irq(instance);
+       local_irq_restore(flags);
+
        /*
         * Case 5 : If we reached this point, the command was not found in any of
         *          the queues.
         * broke.
         */
 
-       local_irq_restore(flags);
        printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO);
 
-       /* Maybe it is sufficient just to release the ST-DMA lock... (if
-        * possible at all) At least, we should check if the lock could be
-        * released after the abort, in case it is kept due to some bug.
-        */
-       falcon_release_lock_if_possible(hostdata);
-
        return FAILED;
 }
 
 
 static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
 {
-       SETUP_HOSTDATA(cmd->device->host);
+       struct Scsi_Host *instance = cmd->device->host;
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
        int i;
        unsigned long flags;
 #if defined(RESET_RUN_DONE)
        struct scsi_cmnd *connected, *disconnected_queue;
 #endif
 
-       NCR5380_print_status(cmd->device->host);
+       NCR5380_print_status(instance);
 
        /* get in phase */
        NCR5380_write(TARGET_COMMAND_REG,
 #ifdef REAL_DMA
        hostdata->dma_len = 0;
 #endif
+
+       maybe_release_dma_irq(instance);
        local_irq_restore(flags);
 
        /* we did no complete reset of all commands, so a wakeup is required */
 
 #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"
 
 
  * 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.
 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;
 }