linux/debian/patches/bugfix/m68k/debian-2.6.21-2-atari-scsi....

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 */
}