Hi!

I'm currently working on a userland daemon to spin down idle disks. While
IDE support is fine, SCSI turns out as a problem. The reason is that
unlike IDE, the current SCSI implementation won't try a spinup if a spun
down disk is accessed.

Below you'll find a - completely untested - patch against stock 2.3.28,
that tries to add spinup support. Since I don't really understand what I
am doing here but merely ripped out some parts from the infamous
scsi-idle-patch, I'd be happy if someout could glance over it and tell me
what kind of Bad Things I introduced. 

I've seen the spinup code in sd_init_onedisk() using sd_wait_cmd() which
Alan came up with during his cleanups. I've also seen a lot of weird
locking stuff going on there. But I'd like to issue the spinup from
rw_intr, so the semaphores are out. Now is it safe to issue a cmd from
rw_intr without any further locks held or which looks would I have to
acquire? Or is it just a stupid thing to do anyway?

Regards,

Daniel.


--- drivers/scsi/sd.c.orig      Mon Nov 22 22:30:55 1999
+++ drivers/scsi/sd.c   Mon Nov 22 22:31:03 1999
@@ -346,6 +346,74 @@
 }
 
 /*
+ * handle spinup of idle disks
+ */
+
+#define DEBUG_IDLE 0
+
+static void sd_start_idle_done(Scsi_Cmnd * SCpnt)
+{
+       int result = SCpnt->result;
+       
+#ifdef DEBUG
+       printk("sd%c: sd_start_done(%d, %d)\n",
+               'a' + MINOR(SCpnt->request.rq_dev),
+               SCpnt->host->host_no, result);
+#endif
+       
+       if (result) {
+               Scsi_Device *sd = 
+                       rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].device;
+               printk("SCSI disk error: host %d channel %d id %d lun %d "
+                      "return code = %x\n",
+                       sd->host->host_no, sd->channel, sd->id, sd->lun, 
+                       result);
+               if (driver_byte(result) & DRIVER_SENSE)
+                       print_sense("sd", SCpnt);
+
+               SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.current_nr_sectors);
+               requeue_sd_request(SCpnt);
+
+               return;
+       }
+
+#if DEBUG_IDLE >= 1
+       printk("sd: drive has been started\n");
+#endif
+
+       requeue_sd_request(SCpnt);
+}
+
+static void sd_start_idle(Scsi_Cmnd * SCpnt)
+{
+       unsigned char cmd[10];
+       int dev, old_use_sg = SCpnt->use_sg, oldbufflen = SCpnt->bufflen;
+
+       dev = DEVICE_NR(SCpnt->request.rq_dev);
+
+#if DEBUG_IDLE >= 2
+       printk("sd%c: sd_start entered\n", 'a' + dev);
+#endif
+
+       cmd[0] = START_STOP;
+       cmd[1] = (rscsi_disks[dev].device->lun << 5) & 0xe0;
+       memset((void*) &cmd[2], 0, 8);
+       cmd[4] = 1;
+       SCpnt->use_sg  = 0;
+       SCpnt->bufflen = 0;
+       SCpnt->cmd_len = 0;
+       SCpnt->sense_buffer[0] = 0;
+       SCpnt->sense_buffer[2] = 0;
+
+       scsi_do_cmd(SCpnt, cmd, NULL, 0, sd_start_done, 
+                       SD_TIMEOUT, MAX_RETRIES);
+
+       SCpnt->use_sg  = old_use_sg;
+       SCpnt->bufflen = oldbufflen;
+}
+
+
+/*
  * rw_intr is the interrupt routine for the device driver.
  * It will be notified on the end of a SCSI read / write, and
  * will take one of several actions based on success or failure.
@@ -536,6 +604,15 @@
                                }
                        }
                }
+               if (sense_error(SCpnt->sense_buffer[2]) == NOT_READY) {
+#if DEBUG_IDLE >= 2
+                       printk("sd%c: drive is idle\n",
+                               'a' + DEVICE_NR(SCpnt->request.rq_dev));
+#endif
+                       sd_start_idle(SCpnt);
+                       return;
+               }
+                       
                /* If we had an ILLEGAL REQUEST returned, then we may have
                 * performed an unsupported command.  The only thing this should be
                 * would be a ten byte read where only a six byte read was supported.



-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]

Reply via email to