[7581] in linux-scsi channel archive

home help back first fref pref prev next nref lref last post

Auto-spinup.

daemon@ATHENA.MIT.EDU (Daniel Kobras)
Mon Nov 22 17:06:52 1999

Date:   Mon, 22 Nov 1999 22:59:55 +0100 (CET)
From: Daniel Kobras <daniel.kobras@student.uni-tuebingen.de>
To: Linux SCSI ML <linux-scsi@vger.rutgers.edu>
cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Message-ID: <Pine.LNX.3.96.991122213246.2394B-100000@abulafia>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII

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 majordomo@vger.rutgers.edu

home help back first fref pref prev next nref lref last post