All of lore.kernel.org
 help / color / mirror / Atom feed
* RE: PATCH for disabling write cache on SATA drives
@ 2004-06-29 19:19 Edwards, Scott (MED, Kelly IT Resouces)
  2004-06-30  3:03 ` Jeff Garzik
  0 siblings, 1 reply; 6+ messages in thread
From: Edwards, Scott (MED, Kelly IT Resouces) @ 2004-06-29 19:19 UTC (permalink / raw)
  To: 'Jeff Garzik'
  Cc: 'linux-scsi@vger.kernel.org', linux-ide,
	'sedwards@xmission.com'


On Monday, June 28, 2004 at 6:12 PM, Jeff Garzik wrote:

> On Fri, Jun 25, 2004 at 06:21:24PM -0500, Edwards, Scott (MED, Kelly
IT Resouces) wrote:
>> 
>> I don't know if this is useful for anyone or if anyone even cares,
but just
>> in case someone does, this is the patch I made to disable the write
cache on
>> the Serial ATA drives.  It doesn't make the write cache controllable
from
>> the user level, it just ALWAYS disables it.  (I tried to make one
that could
>> be sent via an ioctl, but there were far too many things that I
didn't
>> understand and it didn't work.)  Since I have never done this before
I don't
>> know if there is some protocol that I missed, if so I'm sorry.  If
there are
>> glaring stupid mistakes (very likely) please let me know.
>
> In principle your patch is fine, but I would really like to find a
> better way of allowing the user to do this.
>
> My immediate guess would be to use the standard SCSI method of
disabling
> write cache, and have that initiate wbcache disable on the SATA side.
>
> Long term, this would be augmented by an "ATA passthru" opcode or
ioctl.
>
>	Jeff

I first tried to make a real scsi ioctl command in libata-scsi.c, so I
could just use the scsiinfo program to disable the write cache.  I  made
a xlat_mode_select command but it didn't work and management didn't want
me
spending more time trying to figure it out.  And really for it to work
correctly there would have to be a xlat_mode_sense because now it is
just 
simulated (in ata_scsi_simulate).

I'm willing to work on it on my own time as soon as I get a SATA drive, 
if someone would be willing to advise me on how to send the ATA commands
to the drive (I think this is where it failed before).

Thanks
  -Scott


^ permalink raw reply	[flat|nested] 6+ messages in thread
* PATCH for disabling write cache on SATA drives
@ 2004-06-25 23:21 Edwards, Scott (MED, Kelly IT Resouces)
  2004-06-29  0:12 ` Jeff Garzik
  0 siblings, 1 reply; 6+ messages in thread
From: Edwards, Scott (MED, Kelly IT Resouces) @ 2004-06-25 23:21 UTC (permalink / raw)
  To: 'linux-scsi@vger.kernel.org'


I don't know if this is useful for anyone or if anyone even cares, but just
in case someone does, this is the patch I made to disable the write cache on
the Serial ATA drives.  It doesn't make the write cache controllable from
the user level, it just ALWAYS disables it.  (I tried to make one that could
be sent via an ioctl, but there were far too many things that I didn't
understand and it didn't work.)  Since I have never done this before I don't
know if there is some protocol that I missed, if so I'm sorry.  If there are
glaring stupid mistakes (very likely) please let me know.

Thanks
  -Scott


diff -ru linux-2.6.7/drivers/scsi/libata-core.c
linux-2.6.7-dwc/drivers/scsi/libata-core.c
--- linux-2.6.7/drivers/scsi/libata-core.c	2004-06-15
23:18:38.000000000 -0600
+++ linux-2.6.7-dwc/drivers/scsi/libata-core.c	2004-06-25
16:39:16.000000000 -0600
@@ -55,6 +55,7 @@
 static void ata_host_set_udma(struct ata_port *ap);
 static void ata_dev_set_pio(struct ata_port *ap, unsigned int device);
 static void ata_dev_set_udma(struct ata_port *ap, unsigned int device);
+static void ata_dev_disable_wcache(struct ata_port *ap, unsigned int
device);
 static void ata_set_mode(struct ata_port *ap);
 static int ata_qc_issue_prot(struct ata_queued_cmd *qc);
 
@@ -1111,14 +1112,20 @@
 			dev->n_sectors = ata_id_u32(dev, 60);
 		}
 
+		if (dev->id[85] & (1 << 5)) {
+			dev->flags |= ATA_DFLAG_WCACHE;
+		}
+
 		ap->host->max_cmd_len = 16;
 
 		/* print device info to dmesg */
-		printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu
sectors:%s\n",
+		printk(KERN_INFO 
+		       "ata%u: dev %u ATA, max %s, %Lu sectors:%s,
wcache:%s\n",
 		       ap->id, device,
 		       ata_udma_string(udma_modes),
 		       (unsigned long long)dev->n_sectors,
-		       dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
+		       dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "",
+		       dev->flags & ATA_DFLAG_WCACHE ? "on" : "off");
 	}
 
 	/* ATAPI-specific feature tests */
@@ -1297,6 +1304,12 @@
 		ata_dev_set_udma(ap, 1);
 	}
 
+	if (ap->device[0]->flags & ATA_DFLAG_WCACHE)
+		ata_dev_disable_wcache(ap, 0);
+
+	if (ap->device[1]->flags & ATA_DFLAG_WCACHE)
+		ata_dev_disable_wcache(ap, 1);
+
 	if (ap->flags & ATA_FLAG_PORT_DISABLED)
 		return;
 
@@ -1680,6 +1693,43 @@
 	ap->ops->port_disable(ap);
 }
 
+static void ata_dev_disable_wcache(struct ata_port *ap, unsigned int
device)
+{
+	struct ata_taskfile tf;
+
+	struct ata_device *dev = &ap->device[device];
+
+	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+		return;
+
+	printk(KERN_INFO "disable write cache on dev: %u\n", device);
+
+	/* set up set-features taskfile */
+	DPRINTK("set features - disable write cache\n");
+	ata_tf_init(ap, &tf, dev->devno);
+	tf.ctl |= ATA_NIEN;
+	tf.command = ATA_CMD_SET_FEATURES;
+	tf.feature = SETFEATURES_XFER;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	tf.nsect = DISABLE_WRITE_CACHE;
+
+	/* do bus reset */
+	ata_tf_to_host(ap, &tf);
+
+	/* crazy ATAPI devices... */
+	if (dev->class == ATA_DEV_ATAPI)
+		msleep(150);
+
+	ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+	ata_irq_on(ap);	/* re-enable interrupts */
+
+	ata_wait_idle(ap);
+
+	DPRINTK("EXIT\n");
+}
+
 /**
  *	ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command
  *	@ap: Port associated with device @dev
diff -ru linux-2.6.7/include/linux/ata.h linux-2.6.7-dwc/include/linux/ata.h
--- linux-2.6.7/include/linux/ata.h	2004-06-15 23:19:36.000000000 -0600
+++ linux-2.6.7-dwc/include/linux/ata.h	2004-06-25 16:19:14.000000000 -0600
@@ -133,6 +133,8 @@
 	XFER_UDMA_0		= 0x40,
 	XFER_PIO_4		= 0x0C,
 	XFER_PIO_3		= 0x0B,
+	ENABLE_WRITE_CACHE      = 0x02,
+	DISABLE_WRITE_CACHE     = 0x82,
 
 	/* ATAPI stuff */
 	ATAPI_PKT_DMA		= (1 << 0),



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2004-06-30  3:55 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-06-29 19:19 PATCH for disabling write cache on SATA drives Edwards, Scott (MED, Kelly IT Resouces)
2004-06-30  3:03 ` Jeff Garzik
2004-06-30  3:47   ` J. Scott Edwards
2004-06-30  3:55     ` Jeff Garzik
  -- strict thread matches above, loose matches on Subject: below --
2004-06-25 23:21 Edwards, Scott (MED, Kelly IT Resouces)
2004-06-29  0:12 ` Jeff Garzik

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.