aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2006-01-06 03:28:07 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:36:09 -0500
commit9b847548663ef1039dd49f0eb4463d001e596bc3 (patch)
tree105a0eece522b1347bea57f609f6c04ed673fdb3 /drivers/scsi/libata-core.c
parent88202a0c84e1951d6630d1d557d4801a8cc5b5ef (diff)
[PATCH] Suspend support for libata
This patch adds suspend patch to libata, and ata_piix in particular. For most low level drivers, they should just need to add the 4 hooks to work. As I can only test ata_piix, I didn't enable it for more though. Suspend support is the single most important feature on a notebook, and most new notebooks have sata drives. It's quite embarrassing that we _still_ do not support this. Right now, it's perfectly possible to suspend the drive in mid-transfer. Signed-off-by: Jens Axboe <axboe@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r--drivers/scsi/libata-core.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 9ea102587914..9c66d4059399 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -4154,6 +4154,96 @@ err_out:
4154 * Inherited from caller. 4154 * Inherited from caller.
4155 */ 4155 */
4156 4156
4157/*
4158 * Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
4159 * without filling any other registers
4160 */
4161static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev,
4162 u8 cmd)
4163{
4164 struct ata_taskfile tf;
4165 int err;
4166
4167 ata_tf_init(ap, &tf, dev->devno);
4168
4169 tf.command = cmd;
4170 tf.flags |= ATA_TFLAG_DEVICE;
4171 tf.protocol = ATA_PROT_NODATA;
4172
4173 err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
4174 if (err)
4175 printk(KERN_ERR "%s: ata command failed: %d\n",
4176 __FUNCTION__, err);
4177
4178 return err;
4179}
4180
4181static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev)
4182{
4183 u8 cmd;
4184
4185 if (!ata_try_flush_cache(dev))
4186 return 0;
4187
4188 if (ata_id_has_flush_ext(dev->id))
4189 cmd = ATA_CMD_FLUSH_EXT;
4190 else
4191 cmd = ATA_CMD_FLUSH;
4192
4193 return ata_do_simple_cmd(ap, dev, cmd);
4194}
4195
4196static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev)
4197{
4198 return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1);
4199}
4200
4201static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
4202{
4203 return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE);
4204}
4205
4206/**
4207 * ata_device_resume - wakeup a previously suspended devices
4208 *
4209 * Kick the drive back into action, by sending it an idle immediate
4210 * command and making sure its transfer mode matches between drive
4211 * and host.
4212 *
4213 */
4214int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
4215{
4216 if (ap->flags & ATA_FLAG_SUSPENDED) {
4217 ap->flags &= ~ATA_FLAG_SUSPENDED;
4218 ata_set_mode(ap);
4219 }
4220 if (!ata_dev_present(dev))
4221 return 0;
4222 if (dev->class == ATA_DEV_ATA)
4223 ata_start_drive(ap, dev);
4224
4225 return 0;
4226}
4227
4228/**
4229 * ata_device_suspend - prepare a device for suspend
4230 *
4231 * Flush the cache on the drive, if appropriate, then issue a
4232 * standbynow command.
4233 *
4234 */
4235int ata_device_suspend(struct ata_port *ap, struct ata_device *dev)
4236{
4237 if (!ata_dev_present(dev))
4238 return 0;
4239 if (dev->class == ATA_DEV_ATA)
4240 ata_flush_cache(ap, dev);
4241
4242 ata_standby_drive(ap, dev);
4243 ap->flags |= ATA_FLAG_SUSPENDED;
4244 return 0;
4245}
4246
4157int ata_port_start (struct ata_port *ap) 4247int ata_port_start (struct ata_port *ap)
4158{ 4248{
4159 struct device *dev = ap->host_set->dev; 4249 struct device *dev = ap->host_set->dev;
@@ -4902,6 +4992,23 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
4902 4992
4903 return (tmp == bits->val) ? 1 : 0; 4993 return (tmp == bits->val) ? 1 : 0;
4904} 4994}
4995
4996int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
4997{
4998 pci_save_state(pdev);
4999 pci_disable_device(pdev);
5000 pci_set_power_state(pdev, PCI_D3hot);
5001 return 0;
5002}
5003
5004int ata_pci_device_resume(struct pci_dev *pdev)
5005{
5006 pci_set_power_state(pdev, PCI_D0);
5007 pci_restore_state(pdev);
5008 pci_enable_device(pdev);
5009 pci_set_master(pdev);
5010 return 0;
5011}
4905#endif /* CONFIG_PCI */ 5012#endif /* CONFIG_PCI */
4906 5013
4907 5014
@@ -5005,4 +5112,11 @@ EXPORT_SYMBOL_GPL(ata_pci_host_stop);
5005EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); 5112EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
5006EXPORT_SYMBOL_GPL(ata_pci_init_one); 5113EXPORT_SYMBOL_GPL(ata_pci_init_one);
5007EXPORT_SYMBOL_GPL(ata_pci_remove_one); 5114EXPORT_SYMBOL_GPL(ata_pci_remove_one);
5115EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
5116EXPORT_SYMBOL_GPL(ata_pci_device_resume);
5008#endif /* CONFIG_PCI */ 5117#endif /* CONFIG_PCI */
5118
5119EXPORT_SYMBOL_GPL(ata_device_suspend);
5120EXPORT_SYMBOL_GPL(ata_device_resume);
5121EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
5122EXPORT_SYMBOL_GPL(ata_scsi_device_resume);