Bugzilla – Attachment 48189 Details for
Bug 104647
Suspend to Disk broken for SATA hard drives
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
IDP Log In
|
Forgot Password
[patch]
My libata suspend patch
libata-suspend.diff (text/plain), 9.31 KB, created by
Jens Axboe
on 2005-08-30 15:16:50 UTC
(
hide
)
Description:
My libata suspend patch
Filename:
MIME Type:
Creator:
Jens Axboe
Created:
2005-08-30 15:16:50 UTC
Size:
9.31 KB
patch
obsolete
>From: Jens Axboe <axboe@suse.de> >Subject: Fix libata suspend >Patch-mainline: >References: 104647 > >Acked-by: >Signed-off-by: > >diff -u --recursive --new-file --exclude='.*' linux-2.6.12/drivers/scsi/ata_piix.c linux/drivers/scsi/ata_piix.c >--- linux-2.6.12/drivers/scsi/ata_piix.c 2005-06-17 15:48:29.000000000 -0400 >+++ linux/drivers/scsi/ata_piix.c 2005-07-02 12:34:11.000000000 -0400 >@@ -104,6 +104,8 @@ > .id_table = piix_pci_tbl, > .probe = piix_init_one, > .remove = ata_pci_remove_one, >+ .suspend = ata_pci_device_suspend, >+ .resume = ata_pci_device_resume, > }; > > static Scsi_Host_Template piix_sht = { >@@ -124,6 +126,8 @@ > .slave_configure = ata_scsi_slave_config, > .bios_param = ata_std_bios_param, > .ordered_flush = 1, >+ .resume = ata_scsi_device_resume, >+ .suspend = ata_scsi_device_suspend, > }; > > static struct ata_port_operations piix_pata_ops = { >diff -u --recursive --new-file --exclude='.*' linux-2.6.12/drivers/scsi/libata-core.c linux/drivers/scsi/libata-core.c >--- linux-2.6.12/drivers/scsi/libata-core.c 2005-06-17 15:48:29.000000000 -0400 >+++ linux/drivers/scsi/libata-core.c 2005-07-02 12:34:11.000000000 -0400 >@@ -3632,6 +3632,104 @@ > * LOCKING: > */ > >+/* >+ * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, >+ * without filling any other registers >+ */ >+static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev, >+ u8 cmd) >+{ >+ DECLARE_COMPLETION(wait); >+ struct ata_queued_cmd *qc; >+ unsigned long flags; >+ int rc; >+ >+ qc = ata_qc_new_init(ap, dev); >+ BUG_ON(qc == NULL); >+ >+ qc->tf.command = cmd; >+ qc->tf.flags |= ATA_TFLAG_DEVICE; >+ qc->tf.protocol = ATA_PROT_NODATA; >+ >+ qc->waiting = &wait; >+ qc->complete_fn = ata_qc_complete_noop; >+ >+ spin_lock_irqsave(&ap->host_set->lock, flags); >+ rc = ata_qc_issue(qc); >+ spin_unlock_irqrestore(&ap->host_set->lock, flags); >+ >+ if (!rc) >+ wait_for_completion(&wait); >+ >+ return rc; >+} >+ >+static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev) >+{ >+ u8 cmd; >+ >+ if (!ata_try_flush_cache(dev)) >+ return 0; >+ >+ if (ata_id_has_flush_ext(dev->id)) >+ cmd = ATA_CMD_FLUSH_EXT; >+ else >+ cmd = ATA_CMD_FLUSH; >+ >+ return ata_do_simple_cmd(ap, dev, cmd); >+} >+ >+static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev) >+{ >+ return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1); >+} >+ >+static int ata_start_drive(struct ata_port *ap, struct ata_device *dev) >+{ >+ return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE); >+} >+ >+/** >+ * ata_device_resume - wakeup a previously suspended devices >+ * >+ * Kick the drive back into action, by sending it an idle immediate >+ * command and making sure its transfer mode matches between drive >+ * and host. >+ * >+ */ >+int ata_device_resume(struct ata_port *ap, struct ata_device *dev) >+{ >+ if (ap->flags & ATA_FLAG_SUSPENDED) { >+ ap->flags &= ~ATA_FLAG_SUSPENDED; >+ ata_set_mode(ap); >+ } >+ if (!ata_dev_present(dev)) >+ return 0; >+ if (dev->class == ATA_DEV_ATA) >+ ata_start_drive(ap, dev); >+ >+ return 0; >+} >+ >+/** >+ * ata_device_suspend - prepare a device for suspend >+ * >+ * Flush the cache on the drive, if appropriate, then issue a >+ * standbynow command. >+ * >+ */ >+int ata_device_suspend(struct ata_port *ap, struct ata_device *dev) >+{ >+ if (!ata_dev_present(dev)) >+ return 0; >+ if (dev->class == ATA_DEV_ATA) >+ ata_flush_cache(ap, dev); >+ >+ ata_standby_drive(ap, dev); >+ ap->flags |= ATA_FLAG_SUSPENDED; >+ return 0; >+} >+ > int ata_port_start (struct ata_port *ap) > { > struct device *dev = ap->host_set->dev; >@@ -4337,6 +4435,23 @@ > > return (tmp == bits->val) ? 1 : 0; > } >+ >+int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state) >+{ >+ pci_save_state(pdev); >+ pci_disable_device(pdev); >+ pci_set_power_state(pdev, PCI_D3hot); >+ return 0; >+} >+ >+int ata_pci_device_resume(struct pci_dev *pdev) >+{ >+ pci_set_power_state(pdev, PCI_D0); >+ pci_restore_state(pdev); >+ pci_enable_device(pdev); >+ pci_set_master(pdev); >+ return 0; >+} > #endif /* CONFIG_PCI */ > > >@@ -4413,4 +4528,11 @@ > EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); > EXPORT_SYMBOL_GPL(ata_pci_init_one); > EXPORT_SYMBOL_GPL(ata_pci_remove_one); >+EXPORT_SYMBOL_GPL(ata_pci_device_suspend); >+EXPORT_SYMBOL_GPL(ata_pci_device_resume); > #endif /* CONFIG_PCI */ >+ >+EXPORT_SYMBOL_GPL(ata_device_suspend); >+EXPORT_SYMBOL_GPL(ata_device_resume); >+EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); >+EXPORT_SYMBOL_GPL(ata_scsi_device_resume); >diff -u --recursive --new-file --exclude='.*' linux-2.6.12/drivers/scsi/libata-scsi.c linux/drivers/scsi/libata-scsi.c >--- linux-2.6.12/drivers/scsi/libata-scsi.c 2005-06-17 15:48:29.000000000 -0400 >+++ linux/drivers/scsi/libata-scsi.c 2005-07-02 12:34:11.000000000 -0400 >@@ -390,6 +390,22 @@ > return 0; > } > >+int ata_scsi_device_resume(struct scsi_device *sdev) >+{ >+ struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; >+ struct ata_device *dev = &ap->device[sdev->id]; >+ >+ return ata_device_resume(ap, dev); >+} >+ >+int ata_scsi_device_suspend(struct scsi_device *sdev) >+{ >+ struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; >+ struct ata_device *dev = &ap->device[sdev->id]; >+ >+ return ata_device_suspend(ap, dev); >+} >+ > /** > * ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command > * @qc: Storage for translated ATA taskfile >diff -u --recursive --new-file --exclude='.*' linux-2.6.12/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c >--- linux-2.6.12/drivers/scsi/scsi_lib.c 2005-06-17 15:48:29.000000000 -0400 >+++ linux/drivers/scsi/scsi_lib.c 2005-07-02 12:34:11.000000000 -0400 >@@ -1855,8 +1855,9 @@ > void > scsi_device_resume(struct scsi_device *sdev) > { >- if(scsi_device_set_state(sdev, SDEV_RUNNING)) >+ if (scsi_device_set_state(sdev, SDEV_RUNNING)) > return; >+ > scsi_run_queue(sdev->request_queue); > } > EXPORT_SYMBOL(scsi_device_resume); >diff -u --recursive --new-file --exclude='.*' linux-2.6.12/drivers/scsi/scsi_sysfs.c linux/drivers/scsi/scsi_sysfs.c >--- linux-2.6.12/drivers/scsi/scsi_sysfs.c 2005-06-17 15:48:29.000000000 -0400 >+++ linux/drivers/scsi/scsi_sysfs.c 2005-07-02 12:34:11.000000000 -0400 >@@ -199,9 +199,40 @@ > return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; > } > >+static int scsi_bus_suspend(struct device * dev, pm_message_t state) >+{ >+ 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) >+ return err; >+ >+ if (sht->suspend) >+ err = sht->suspend(sdev); >+ >+ return err; >+} >+ >+static int scsi_bus_resume(struct device * dev) >+{ >+ struct scsi_device *sdev = to_scsi_device(dev); >+ struct scsi_host_template *sht = sdev->host->hostt; >+ int err = 0; >+ >+ if (sht->resume) >+ err = sht->resume(sdev); >+ >+ scsi_device_resume(sdev); >+ return err; >+} >+ > struct bus_type scsi_bus_type = { > .name = "scsi", > .match = scsi_bus_match, >+ .suspend = scsi_bus_suspend, >+ .resume = scsi_bus_resume, > }; > > int scsi_sysfs_register(void) >diff -u --recursive --new-file --exclude='.*' linux-2.6.12/include/linux/ata.h linux/include/linux/ata.h >--- linux-2.6.12/include/linux/ata.h 2005-06-17 15:48:29.000000000 -0400 >+++ linux/include/linux/ata.h 2005-07-02 12:34:11.000000000 -0400 >@@ -125,6 +125,8 @@ > ATA_CMD_PACKET = 0xA0, > ATA_CMD_VERIFY = 0x40, > ATA_CMD_VERIFY_EXT = 0x42, >+ ATA_CMD_STANDBYNOW1 = 0xE0, >+ ATA_CMD_IDLEIMMEDIATE = 0xE1, > > /* SETFEATURES stuff */ > SETFEATURES_XFER = 0x03, >diff -u --recursive --new-file --exclude='.*' linux-2.6.12/include/linux/libata.h linux/include/linux/libata.h >--- linux-2.6.12/include/linux/libata.h 2005-06-17 15:48:29.000000000 -0400 >+++ linux/include/linux/libata.h 2005-07-02 12:34:11.000000000 -0400 >@@ -113,6 +113,7 @@ > ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ > ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ > ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ >+ ATA_FLAG_SUSPENDED = (1 << 9), /* port is suspended */ > > ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ > ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ >@@ -387,6 +388,8 @@ > extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, > unsigned int n_ports); > extern void ata_pci_remove_one (struct pci_dev *pdev); >+extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state); >+extern int ata_pci_device_resume(struct pci_dev *pdev); > #endif /* CONFIG_PCI */ > extern int ata_device_add(struct ata_probe_ent *ent); > extern int ata_scsi_detect(Scsi_Host_Template *sht); >@@ -395,6 +398,10 @@ > extern int ata_scsi_error(struct Scsi_Host *host); > extern int ata_scsi_release(struct Scsi_Host *host); > extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); >+extern int ata_scsi_device_resume(struct scsi_device *); >+extern int ata_scsi_device_suspend(struct scsi_device *); >+extern int ata_device_resume(struct ata_port *, struct ata_device *); >+extern int ata_device_suspend(struct ata_port *, struct ata_device *); > /* > * Default driver ops implementations > */ >diff -u --recursive --new-file --exclude='.*' linux-2.6.12/include/scsi/scsi_host.h linux/include/scsi/scsi_host.h >--- linux-2.6.12/include/scsi/scsi_host.h 2005-06-17 15:48:29.000000000 -0400 >+++ linux/include/scsi/scsi_host.h 2005-07-02 12:34:11.000000000 -0400 >@@ -270,6 +270,12 @@ > int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int); > > /* >+ * suspend support >+ */ >+ int (*resume)(struct scsi_device *); >+ int (*suspend)(struct scsi_device *); >+ >+ /* > * Name of proc directory > */ > char *proc_name;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
Actions:
View
|
Diff
Attachments on
bug 104647
:
48149
|
48150
|
48151
|
48153
|
48154
|
48155
| 48189 |
49281