@@ -29,6 +29,7 @@
#include <linux/msi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
#include <linux/libata.h>
#include <linux/ahci-remap.h>
#include <linux/io-64-nonatomic-lo-hi.h>
@@ -88,6 +89,8 @@ static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
static bool is_mcp89_apple(struct pci_dev *pdev);
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
+static int ahci_slave_configure(struct scsi_device *sdev);
+
#ifdef CONFIG_PM
static int ahci_pci_device_runtime_suspend(struct device *dev);
static int ahci_pci_device_runtime_resume(struct device *dev);
@@ -99,6 +102,7 @@ static int ahci_pci_device_resume(struct device *dev);
static struct scsi_host_template ahci_sht = {
AHCI_SHT("ahci"),
+ .slave_configure = ahci_slave_configure,
};
static struct ata_port_operations ahci_vt8251_ops = {
@@ -1398,6 +1402,27 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
{}
#endif
+static int ahci_slave_configure(struct scsi_device *sdev)
+{
+ /*
+ * Machines cutting power to the SSD during a warm reboot must send
+ * a STANDBY_IMMEDIATE before to prevent unclean shutdown of the disk.
+ */
+ static struct dmi_system_id sysids[] = {
+ {
+ /* x86-samus, the Chromebook Pixel 2. */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
+ },
+ },
+ { /* sentinel */ }
+ };
+ if (dmi_check_system(sysids))
+ sdev->send_stop_reboot = 1;
+ return ata_scsi_slave_config(sdev);
+}
+
/*
* On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected
* as DUMMY, or detected but eventually get a "link down" and never get up
@@ -3533,8 +3533,9 @@ static void sd_shutdown(struct device *dev)
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
sd_sync_cache(sdkp, NULL);
}
-
- if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
+ if ((sdkp->device->send_stop_reboot ||
+ system_state != SYSTEM_RESTART) &&
+ sdkp->device->manage_start_stop) {
sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
sd_start_stop_device(sdkp, 0);
}
@@ -199,6 +199,7 @@ struct scsi_device {
unsigned broken_fua:1; /* Don't set FUA bit */
unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */
unsigned unmap_limit_for_ws:1; /* Use the UNMAP limit for WRITE SAME */
+ unsigned send_stop_reboot:1; /* Send START_STOP_UNIT at reboot */
atomic_t disk_events_disable_depth; /* disable depth for disk events */