SCSI spinup.

Daniel Kobras (daniel.kobras@student.uni-tuebingen.de)
Thu, 2 Dec 1999 01:41:33 +0100 (CET)


Hi!

I sent this message to linux-scsi a couple of days ago but unfortunately
didn't arouse that much interest. However, since this one's pretty crucial
for my work on noflushd, I'm trying linux-kernel as well. The bottom line
is: Is the patch below save, and if no, under which conditions can it
break?

By the way: I see rw_intr - running in bottom half/interrupt context -
calling requeue_sd_request() calling scsi_do_cmd() calling SCSI_SLEEP
(under certain circumstances). Is this the sleep guaranteed to never
trigger when called from an interrupt context?

Regards,

Daniel.

---------- Forwarded message ----------

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-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/