296 lines
9.5 KiB
Diff
296 lines
9.5 KiB
Diff
--- l/drivers/scsi/atari_scsi.c.org 2007-05-18 18:24:37.000000000 +0200
|
|
+++ l/drivers/scsi/atari_scsi.c 2007-05-20 21:31:46.000000000 +0200
|
|
@@ -186,17 +186,18 @@
|
|
/***************************** Prototypes *****************************/
|
|
|
|
#ifdef REAL_DMA
|
|
-static int scsi_dma_is_ignored_buserr(unsigned char dma_stat);
|
|
-static void atari_scsi_fetch_restbytes(void);
|
|
-static long atari_scsi_dma_residual(struct Scsi_Host *instance);
|
|
-static int falcon_classify_cmd(Scsi_Cmnd *cmd);
|
|
-static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
|
|
- Scsi_Cmnd *cmd, int write_flag);
|
|
-#endif
|
|
-static irqreturn_t scsi_tt_intr(int irq, void *dummy);
|
|
-static irqreturn_t scsi_falcon_intr(int irq, void *dummy);
|
|
-static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata);
|
|
-static void falcon_get_lock(void);
|
|
+static int scsi_dma_is_ignored_buserr( unsigned char dma_stat );
|
|
+static void atari_scsi_fetch_restbytes( void );
|
|
+static long atari_scsi_dma_residual( struct Scsi_Host *instance );
|
|
+static int falcon_classify_cmd( Scsi_Cmnd *cmd );
|
|
+static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
|
|
+ Scsi_Cmnd *cmd, int write_flag );
|
|
+#endif
|
|
+static irqreturn_t scsi_tt_intr( int irq, void *dummy);
|
|
+static irqreturn_t scsi_falcon_intr( int irq, void *dummy);
|
|
+static void falcon_release_lock_if_possible( struct NCR5380_hostdata *
|
|
+ hostdata );
|
|
+static int falcon_get_lock( void );
|
|
#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
|
|
static void atari_scsi_reset_boot(void);
|
|
#endif
|
|
@@ -523,7 +524,9 @@
|
|
}
|
|
falcon_got_lock = 0;
|
|
stdma_release();
|
|
- wake_up(&falcon_fairness_wait);
|
|
+#if defined(FALCON_FAIRNESS_WAIT)
|
|
+ wake_up( &falcon_fairness_wait );
|
|
+#endif
|
|
}
|
|
|
|
local_irq_restore(flags);
|
|
@@ -544,21 +547,38 @@
|
|
* Complicated, complicated.... Sigh...
|
|
*/
|
|
|
|
-static void falcon_get_lock(void)
|
|
+/* MSch 20061229: atari_queue_command gets called from softirq context quite
|
|
+ * heavily in the 2.6 kernel series. Since atari_queue_command might need to
|
|
+ * sleep in order to grab the ST-DMA lock, I have modified falcon_get_lock to
|
|
+ * immediately return with error status if called in softirq context with the
|
|
+ * lock not currently held by the SCSI driver, and the ST-DMA locked by some
|
|
+ * other driver. atari_queue_command then returns SCSI_MLQUEUE_HOST_BUSY and
|
|
+ * prevents further commands from issueing.
|
|
+ */
|
|
+
|
|
+static int falcon_get_lock(void)
|
|
{
|
|
unsigned long flags;
|
|
|
|
if (IS_A_TT())
|
|
- return;
|
|
+ return 0;
|
|
|
|
local_irq_save(flags);
|
|
|
|
- while (!in_irq() && falcon_got_lock && stdma_others_waiting())
|
|
- sleep_on(&falcon_fairness_wait);
|
|
+#if defined (FALCON_FAIRNESS_WAIT)
|
|
+ while( !in_irq() && falcon_got_lock && stdma_others_waiting() )
|
|
+ sleep_on( &falcon_fairness_wait );
|
|
+#endif
|
|
|
|
while (!falcon_got_lock) {
|
|
if (in_irq())
|
|
panic("Falcon SCSI hasn't ST-DMA lock in interrupt");
|
|
+ /* we may not sleep in soft interrupts neither, so bail out */
|
|
+ if (in_softirq() && stdma_islocked()) {
|
|
+ printk(KERN_INFO "Falcon SCSI does not hold ST-DMA lock in softirq!\n" );
|
|
+ local_irq_restore(flags);
|
|
+ return 1;
|
|
+ }
|
|
if (!falcon_trying_lock) {
|
|
falcon_trying_lock = 1;
|
|
stdma_lock(scsi_falcon_intr, NULL);
|
|
@@ -573,6 +593,8 @@
|
|
local_irq_restore(flags);
|
|
if (!falcon_got_lock)
|
|
panic("Falcon SCSI: someone stole the lock :-(\n");
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
|
|
@@ -845,7 +867,7 @@
|
|
} else {
|
|
atari_turnon_irq(IRQ_MFP_FSCSI);
|
|
}
|
|
- if ((rv & SCSI_RESET_ACTION) == SCSI_RESET_SUCCESS)
|
|
+ if (rv == SUCCESS)
|
|
falcon_release_lock_if_possible(hostdata);
|
|
|
|
return rv;
|
|
--- l/drivers/scsi/atari_NCR5380.c.org 2007-05-18 18:24:38.000000000 +0200
|
|
+++ l/drivers/scsi/atari_NCR5380.c 2007-05-20 21:29:39.000000000 +0200
|
|
@@ -475,12 +475,13 @@
|
|
int cnt = 1;
|
|
#endif
|
|
|
|
- for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
|
|
- cmd->SCp.buffers_residual &&
|
|
- virt_to_phys(page_address(cmd->SCp.buffer[1].page) +
|
|
- cmd->SCp.buffer[1].offset) == endaddr;) {
|
|
- MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
|
|
- page_address(cmd->SCp.buffer[1].page), endaddr);
|
|
+ for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
|
|
+ cmd->SCp.buffers_residual &&
|
|
+ virt_to_phys(page_address(cmd->SCp.buffer[1].page)+
|
|
+ cmd->SCp.buffer[1].offset) == endaddr; ) {
|
|
+ MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
|
|
+ page_address(cmd->SCp.buffer[1].page)+cmd->SCp.buffer[1].offset,
|
|
+ endaddr);
|
|
#if (NDEBUG & NDEBUG_MERGING)
|
|
++cnt;
|
|
#endif
|
|
@@ -998,6 +999,35 @@
|
|
}
|
|
#endif
|
|
|
|
+ local_irq_save(flags);
|
|
+ /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
|
|
+ * Otherwise a running NCR5380_main may steal the lock.
|
|
+ * Lock before actually inserting due to fairness reasons explained in
|
|
+ * atari_scsi.c. If we insert first, then it's impossible for this driver
|
|
+ * to release the lock.
|
|
+ * Stop timer for this command while waiting for the lock, or timeouts
|
|
+ * may happen (and they really do), and it's no good if the command doesn't
|
|
+ * appear in any of the queues.
|
|
+ * ++roman: Just disabling the NCR interrupt isn't sufficient here,
|
|
+ * because also a timer int can trigger an abort or reset, which would
|
|
+ * alter queues and touch the lock.
|
|
+ */
|
|
+ if (!IS_A_TT()) {
|
|
+ int rv;
|
|
+ /* MSch: since we get called from softirq context here, and cannot
|
|
+ * sleep safely, the return status of falcon_get_lock is now used to
|
|
+ * figure out if we could successfully lock, or need to bail out.
|
|
+ * Signal the midlevel we're unable to queue the command in this case.
|
|
+ */
|
|
+ oldto = atari_scsi_update_timeout(cmd, 0);
|
|
+ rv = falcon_get_lock();
|
|
+ atari_scsi_update_timeout(cmd, oldto);
|
|
+ if (rv) {
|
|
+ local_irq_restore(flags);
|
|
+ return SCSI_MLQUEUE_HOST_BUSY;
|
|
+ }
|
|
+ }
|
|
+
|
|
/*
|
|
* We use the host_scribble field as a pointer to the next command
|
|
* in a queue
|
|
@@ -1015,24 +1045,6 @@
|
|
* sense data is only guaranteed to be valid while the condition exists.
|
|
*/
|
|
|
|
- local_irq_save(flags);
|
|
- /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
|
|
- * Otherwise a running NCR5380_main may steal the lock.
|
|
- * Lock before actually inserting due to fairness reasons explained in
|
|
- * atari_scsi.c. If we insert first, then it's impossible for this driver
|
|
- * to release the lock.
|
|
- * Stop timer for this command while waiting for the lock, or timeouts
|
|
- * may happen (and they really do), and it's no good if the command doesn't
|
|
- * appear in any of the queues.
|
|
- * ++roman: Just disabling the NCR interrupt isn't sufficient here,
|
|
- * because also a timer int can trigger an abort or reset, which would
|
|
- * alter queues and touch the lock.
|
|
- */
|
|
- if (!IS_A_TT()) {
|
|
- oldto = atari_scsi_update_timeout(cmd, 0);
|
|
- falcon_get_lock();
|
|
- atari_scsi_update_timeout(cmd, oldto);
|
|
- }
|
|
if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
|
|
LIST(cmd, hostdata->issue_queue);
|
|
SET_NEXT(cmd, hostdata->issue_queue);
|
|
@@ -1056,10 +1068,9 @@
|
|
* If we're not in an interrupt, we can call NCR5380_main()
|
|
* unconditionally, because it cannot be already running.
|
|
*/
|
|
- if (in_interrupt() || ((flags >> 8) & 7) >= 6)
|
|
- queue_main();
|
|
- else
|
|
- NCR5380_main(NULL);
|
|
+
|
|
+ queue_main();
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -2681,7 +2692,7 @@
|
|
* host byte of the result field to, if zero DID_ABORTED is
|
|
* used.
|
|
*
|
|
- * Returns : 0 - success, -1 on failure.
|
|
+ * Returns : SUCCESS - success, FAILED on failure.
|
|
*
|
|
* XXX - there is no way to abort the command that is currently
|
|
* connected, you have to wait for it to complete. If this is
|
|
@@ -2751,11 +2762,11 @@
|
|
local_irq_restore(flags);
|
|
cmd->scsi_done(cmd);
|
|
falcon_release_lock_if_possible(hostdata);
|
|
- return SCSI_ABORT_SUCCESS;
|
|
+ return SUCCESS;
|
|
} else {
|
|
/* local_irq_restore(flags); */
|
|
printk("scsi%d: abort of connected command failed!\n", HOSTNO);
|
|
- return SCSI_ABORT_ERROR;
|
|
+ return FAILED;
|
|
}
|
|
}
|
|
#endif
|
|
@@ -2779,7 +2790,7 @@
|
|
* yet... */
|
|
tmp->scsi_done(tmp);
|
|
falcon_release_lock_if_possible(hostdata);
|
|
- return SCSI_ABORT_SUCCESS;
|
|
+ return SUCCESS;
|
|
}
|
|
}
|
|
|
|
@@ -2797,7 +2808,7 @@
|
|
if (hostdata->connected) {
|
|
local_irq_restore(flags);
|
|
ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
|
|
- return SCSI_ABORT_SNOOZE;
|
|
+ return FAILED;
|
|
}
|
|
|
|
/*
|
|
@@ -2832,7 +2843,7 @@
|
|
ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
|
|
|
|
if (NCR5380_select(instance, cmd, (int)cmd->tag))
|
|
- return SCSI_ABORT_BUSY;
|
|
+ return FAILED;
|
|
|
|
ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO);
|
|
|
|
@@ -2859,7 +2870,7 @@
|
|
local_irq_restore(flags);
|
|
tmp->scsi_done(tmp);
|
|
falcon_release_lock_if_possible(hostdata);
|
|
- return SCSI_ABORT_SUCCESS;
|
|
+ return SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
@@ -2885,7 +2896,7 @@
|
|
*/
|
|
falcon_release_lock_if_possible(hostdata);
|
|
|
|
- return SCSI_ABORT_NOT_RUNNING;
|
|
+ return SUCCESS;
|
|
}
|
|
|
|
|
|
@@ -2894,7 +2905,7 @@
|
|
*
|
|
* Purpose : reset the SCSI bus.
|
|
*
|
|
- * Returns : SCSI_RESET_WAKEUP
|
|
+ * Returns : SUCCESS
|
|
*
|
|
*/
|
|
|
|
@@ -2984,7 +2995,7 @@
|
|
* the midlevel code that the reset was SUCCESSFUL, and there is no
|
|
* need to 'wake up' the commands by a request_sense
|
|
*/
|
|
- return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
|
|
+ return SUCCESS;
|
|
#else /* 1 */
|
|
|
|
/* MSch: new-style reset handling: let the mid-level do what it can */
|
|
@@ -3032,6 +3043,6 @@
|
|
local_irq_restore(flags);
|
|
|
|
/* we did no complete reset of all commands, so a wakeup is required */
|
|
- return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
|
|
+ return SUCCESS;
|
|
#endif /* 1 */
|
|
}
|