diff -urN oldtree/drivers/ata/ahci.c newtree/drivers/ata/ahci.c
--- oldtree/drivers/ata/ahci.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/ahci.c	2006-10-06 18:14:46.000000000 -0400
@@ -240,6 +240,7 @@
 	.bios_param		= ata_std_bios_param,
 	.suspend		= ata_scsi_device_suspend,
 	.resume			= ata_scsi_device_resume,
+        .shutdown               = ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations ahci_ops = {
diff -urN oldtree/drivers/ata/ata_piix.c newtree/drivers/ata/ata_piix.c
--- oldtree/drivers/ata/ata_piix.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/ata_piix.c	2006-10-06 18:14:46.000000000 -0400
@@ -267,6 +267,7 @@
 	.bios_param		= ata_std_bios_param,
 	.resume			= ata_scsi_device_resume,
 	.suspend		= ata_scsi_device_suspend,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations piix_pata_ops = {
diff -urN oldtree/drivers/ata/libata-core.c newtree/drivers/ata/libata-core.c
--- oldtree/drivers/ata/libata-core.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/libata-core.c	2006-10-06 18:14:46.000000000 -0400
@@ -6203,6 +6203,7 @@
 
 EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
 EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
+EXPORT_SYMBOL_GPL(ata_scsi_device_shutdown);
 
 EXPORT_SYMBOL_GPL(ata_eng_timeout);
 EXPORT_SYMBOL_GPL(ata_port_schedule_eh);
diff -urN oldtree/drivers/ata/libata-scsi.c newtree/drivers/ata/libata-scsi.c
--- oldtree/drivers/ata/libata-scsi.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/libata-scsi.c	2006-10-06 18:14:46.000000000 -0400
@@ -555,6 +555,52 @@
 }
 
 /**
+ *	ata_scsi_device_shutdown - prepares ATA device associated
+ *	with sdev for shutdown
+ *	@sdev: the SCSI device to resume
+ *
+ *	Request suspend EH action on the ATA device associated
+ *	with @sdev in order to flush its cache and unload heads,
+ *	and wait for the operation to complete.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0.
+ */
+int ata_scsi_device_shutdown(struct scsi_device *sdev)
+{
+	struct ata_port *ap = ata_shost_to_port(sdev->host);
+	struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
+	unsigned long flags;
+	unsigned int action;
+
+	if (!dev)
+		return 0;
+
+	/* if @sdev is already detached, nothing to do */
+	if (sdev->sdev_state == SDEV_OFFLINE ||
+	    sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
+		return 0;
+
+	spin_lock_irqsave(ap->lock, flags);
+
+	/* request suspend to flush cache and unload device heads */
+	action = ATA_EH_SUSPEND;
+	ap->eh_info.dev_action[dev->devno] |= action;
+	ap->eh_info.flags |= ATA_EHI_QUIET;
+	ata_port_schedule_eh(ap);
+
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	/* wait for EH to do the job */
+	ata_port_wait_eh(ap);
+
+	return 0;
+}
+
+/**
  *	ata_to_sense_error - convert ATA error to SCSI error
  *	@id: ATA device number
  *	@drv_stat: value contained in ATA status register
diff -urN oldtree/drivers/ata/pdc_adma.c newtree/drivers/ata/pdc_adma.c
--- oldtree/drivers/ata/pdc_adma.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/pdc_adma.c	2006-10-06 18:14:46.000000000 -0400
@@ -154,6 +154,7 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations adma_ata_ops = {
diff -urN oldtree/drivers/ata/sata_mv.c newtree/drivers/ata/sata_mv.c
--- oldtree/drivers/ata/sata_mv.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_mv.c	2006-10-06 18:14:46.000000000 -0400
@@ -392,6 +392,7 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations mv5_ops = {
diff -urN oldtree/drivers/ata/sata_nv.c newtree/drivers/ata/sata_nv.c
--- oldtree/drivers/ata/sata_nv.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_nv.c	2006-10-06 18:14:46.000000000 -0400
@@ -157,6 +157,7 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations nv_generic_ops = {
diff -urN oldtree/drivers/ata/sata_promise.c newtree/drivers/ata/sata_promise.c
--- oldtree/drivers/ata/sata_promise.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_promise.c	2006-10-06 18:14:46.000000000 -0400
@@ -123,6 +123,7 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations pdc_sata_ops = {
diff -urN oldtree/drivers/ata/sata_qstor.c newtree/drivers/ata/sata_qstor.c
--- oldtree/drivers/ata/sata_qstor.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_qstor.c	2006-10-06 18:14:46.000000000 -0400
@@ -144,6 +144,7 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations qs_ata_ops = {
diff -urN oldtree/drivers/ata/sata_sil.c newtree/drivers/ata/sata_sil.c
--- oldtree/drivers/ata/sata_sil.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_sil.c	2006-10-06 18:14:46.000000000 -0400
@@ -184,6 +184,7 @@
 	.bios_param		= ata_std_bios_param,
 	.suspend		= ata_scsi_device_suspend,
 	.resume			= ata_scsi_device_resume,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations sil_ops = {
diff -urN oldtree/drivers/ata/sata_sil24.c newtree/drivers/ata/sata_sil24.c
--- oldtree/drivers/ata/sata_sil24.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_sil24.c	2006-10-06 18:14:46.000000000 -0400
@@ -383,6 +383,7 @@
 	.bios_param		= ata_std_bios_param,
 	.suspend		= ata_scsi_device_suspend,
 	.resume			= ata_scsi_device_resume,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations sil24_ops = {
diff -urN oldtree/drivers/ata/sata_sis.c newtree/drivers/ata/sata_sis.c
--- oldtree/drivers/ata/sata_sis.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_sis.c	2006-10-06 18:14:46.000000000 -0400
@@ -97,6 +97,7 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations sis_ops = {
diff -urN oldtree/drivers/ata/sata_svw.c newtree/drivers/ata/sata_svw.c
--- oldtree/drivers/ata/sata_svw.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_svw.c	2006-10-06 18:14:46.000000000 -0400
@@ -303,6 +303,7 @@
 	.proc_info		= k2_sata_proc_info,
 #endif
 	.bios_param		= ata_std_bios_param,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 
diff -urN oldtree/drivers/ata/sata_sx4.c newtree/drivers/ata/sata_sx4.c
--- oldtree/drivers/ata/sata_sx4.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_sx4.c	2006-10-06 18:14:46.000000000 -0400
@@ -193,6 +193,7 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations pdc_20621_ops = {
diff -urN oldtree/drivers/ata/sata_uli.c newtree/drivers/ata/sata_uli.c
--- oldtree/drivers/ata/sata_uli.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_uli.c	2006-10-06 18:14:46.000000000 -0400
@@ -91,6 +91,7 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations uli_ops = {
diff -urN oldtree/drivers/ata/sata_via.c newtree/drivers/ata/sata_via.c
--- oldtree/drivers/ata/sata_via.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_via.c	2006-10-06 18:14:46.000000000 -0400
@@ -107,6 +107,7 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 static const struct ata_port_operations vt6420_sata_ops = {
diff -urN oldtree/drivers/ata/sata_vsc.c newtree/drivers/ata/sata_vsc.c
--- oldtree/drivers/ata/sata_vsc.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/ata/sata_vsc.c	2006-10-06 18:14:46.000000000 -0400
@@ -281,6 +281,7 @@
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.shutdown		= ata_scsi_device_shutdown,
 };
 
 
diff -urN oldtree/drivers/scsi/scsi_sysfs.c newtree/drivers/scsi/scsi_sysfs.c
--- oldtree/drivers/scsi/scsi_sysfs.c	2006-10-05 15:26:55.000000000 -0400
+++ newtree/drivers/scsi/scsi_sysfs.c	2006-10-06 18:14:46.000000000 -0400
@@ -304,11 +304,28 @@
 	return err;
 }
 
+static void scsi_bus_shutdown(struct device * dev)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct scsi_host_template *sht = sdev->host->hostt;
+	int err;
+
+	err = scsi_device_quiesce(sdev);
+	if (err)
+		printk(KERN_DEBUG "%s: error (0x%x) during shutdown\n",
+			__FUNCTION__, err);
+
+	if (sht->shutdown)
+		err = sht->shutdown(sdev);
+
+}
+
 struct bus_type scsi_bus_type = {
         .name		= "scsi",
         .match		= scsi_bus_match,
 	.suspend	= scsi_bus_suspend,
 	.resume		= scsi_bus_resume,
+	.shutdown	= scsi_bus_shutdown,
 };
 
 int scsi_sysfs_register(void)
diff -urN oldtree/include/linux/libata.h newtree/include/linux/libata.h
--- oldtree/include/linux/libata.h	2006-10-05 15:26:55.000000000 -0400
+++ newtree/include/linux/libata.h	2006-10-06 18:14:46.000000000 -0400
@@ -750,6 +750,7 @@
 extern int ata_port_offline(struct ata_port *ap);
 extern int ata_scsi_device_resume(struct scsi_device *);
 extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t mesg);
+extern int ata_scsi_device_shutdown(struct scsi_device *);
 extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg);
 extern void ata_host_resume(struct ata_host *host);
 extern int ata_ratelimit(void);
diff -urN oldtree/include/scsi/scsi_host.h newtree/include/scsi/scsi_host.h
--- oldtree/include/scsi/scsi_host.h	2006-10-05 15:26:55.000000000 -0400
+++ newtree/include/scsi/scsi_host.h	2006-10-06 18:14:46.000000000 -0400
@@ -321,6 +321,7 @@
 	 */
 	int (*resume)(struct scsi_device *);
 	int (*suspend)(struct scsi_device *, pm_message_t state);
+	int (*shutdown)(struct scsi_device *);
 
 	/*
 	 * Name of proc directory
