diff options
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r-- | drivers/scsi/libata-core.c | 145 |
1 files changed, 139 insertions, 6 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9ea102587914..f55b9b3f7b37 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -562,16 +562,28 @@ static const u8 ata_rw_cmds[] = { | |||
562 | ATA_CMD_WRITE_MULTI, | 562 | ATA_CMD_WRITE_MULTI, |
563 | ATA_CMD_READ_MULTI_EXT, | 563 | ATA_CMD_READ_MULTI_EXT, |
564 | ATA_CMD_WRITE_MULTI_EXT, | 564 | ATA_CMD_WRITE_MULTI_EXT, |
565 | 0, | ||
566 | 0, | ||
567 | 0, | ||
568 | ATA_CMD_WRITE_MULTI_FUA_EXT, | ||
565 | /* pio */ | 569 | /* pio */ |
566 | ATA_CMD_PIO_READ, | 570 | ATA_CMD_PIO_READ, |
567 | ATA_CMD_PIO_WRITE, | 571 | ATA_CMD_PIO_WRITE, |
568 | ATA_CMD_PIO_READ_EXT, | 572 | ATA_CMD_PIO_READ_EXT, |
569 | ATA_CMD_PIO_WRITE_EXT, | 573 | ATA_CMD_PIO_WRITE_EXT, |
574 | 0, | ||
575 | 0, | ||
576 | 0, | ||
577 | 0, | ||
570 | /* dma */ | 578 | /* dma */ |
571 | ATA_CMD_READ, | 579 | ATA_CMD_READ, |
572 | ATA_CMD_WRITE, | 580 | ATA_CMD_WRITE, |
573 | ATA_CMD_READ_EXT, | 581 | ATA_CMD_READ_EXT, |
574 | ATA_CMD_WRITE_EXT | 582 | ATA_CMD_WRITE_EXT, |
583 | 0, | ||
584 | 0, | ||
585 | 0, | ||
586 | ATA_CMD_WRITE_FUA_EXT | ||
575 | }; | 587 | }; |
576 | 588 | ||
577 | /** | 589 | /** |
@@ -584,25 +596,32 @@ static const u8 ata_rw_cmds[] = { | |||
584 | * LOCKING: | 596 | * LOCKING: |
585 | * caller. | 597 | * caller. |
586 | */ | 598 | */ |
587 | void ata_rwcmd_protocol(struct ata_queued_cmd *qc) | 599 | int ata_rwcmd_protocol(struct ata_queued_cmd *qc) |
588 | { | 600 | { |
589 | struct ata_taskfile *tf = &qc->tf; | 601 | struct ata_taskfile *tf = &qc->tf; |
590 | struct ata_device *dev = qc->dev; | 602 | struct ata_device *dev = qc->dev; |
603 | u8 cmd; | ||
591 | 604 | ||
592 | int index, lba48, write; | 605 | int index, fua, lba48, write; |
593 | 606 | ||
607 | fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0; | ||
594 | lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0; | 608 | lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0; |
595 | write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0; | 609 | write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0; |
596 | 610 | ||
597 | if (dev->flags & ATA_DFLAG_PIO) { | 611 | if (dev->flags & ATA_DFLAG_PIO) { |
598 | tf->protocol = ATA_PROT_PIO; | 612 | tf->protocol = ATA_PROT_PIO; |
599 | index = dev->multi_count ? 0 : 4; | 613 | index = dev->multi_count ? 0 : 8; |
600 | } else { | 614 | } else { |
601 | tf->protocol = ATA_PROT_DMA; | 615 | tf->protocol = ATA_PROT_DMA; |
602 | index = 8; | 616 | index = 16; |
603 | } | 617 | } |
604 | 618 | ||
605 | tf->command = ata_rw_cmds[index + lba48 + write]; | 619 | cmd = ata_rw_cmds[index + fua + lba48 + write]; |
620 | if (cmd) { | ||
621 | tf->command = cmd; | ||
622 | return 0; | ||
623 | } | ||
624 | return -1; | ||
606 | } | 625 | } |
607 | 626 | ||
608 | static const char * const xfer_mode_str[] = { | 627 | static const char * const xfer_mode_str[] = { |
@@ -4154,6 +4173,96 @@ err_out: | |||
4154 | * Inherited from caller. | 4173 | * Inherited from caller. |
4155 | */ | 4174 | */ |
4156 | 4175 | ||
4176 | /* | ||
4177 | * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, | ||
4178 | * without filling any other registers | ||
4179 | */ | ||
4180 | static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev, | ||
4181 | u8 cmd) | ||
4182 | { | ||
4183 | struct ata_taskfile tf; | ||
4184 | int err; | ||
4185 | |||
4186 | ata_tf_init(ap, &tf, dev->devno); | ||
4187 | |||
4188 | tf.command = cmd; | ||
4189 | tf.flags |= ATA_TFLAG_DEVICE; | ||
4190 | tf.protocol = ATA_PROT_NODATA; | ||
4191 | |||
4192 | err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); | ||
4193 | if (err) | ||
4194 | printk(KERN_ERR "%s: ata command failed: %d\n", | ||
4195 | __FUNCTION__, err); | ||
4196 | |||
4197 | return err; | ||
4198 | } | ||
4199 | |||
4200 | static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev) | ||
4201 | { | ||
4202 | u8 cmd; | ||
4203 | |||
4204 | if (!ata_try_flush_cache(dev)) | ||
4205 | return 0; | ||
4206 | |||
4207 | if (ata_id_has_flush_ext(dev->id)) | ||
4208 | cmd = ATA_CMD_FLUSH_EXT; | ||
4209 | else | ||
4210 | cmd = ATA_CMD_FLUSH; | ||
4211 | |||
4212 | return ata_do_simple_cmd(ap, dev, cmd); | ||
4213 | } | ||
4214 | |||
4215 | static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev) | ||
4216 | { | ||
4217 | return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1); | ||
4218 | } | ||
4219 | |||
4220 | static int ata_start_drive(struct ata_port *ap, struct ata_device *dev) | ||
4221 | { | ||
4222 | return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE); | ||
4223 | } | ||
4224 | |||
4225 | /** | ||
4226 | * ata_device_resume - wakeup a previously suspended devices | ||
4227 | * | ||
4228 | * Kick the drive back into action, by sending it an idle immediate | ||
4229 | * command and making sure its transfer mode matches between drive | ||
4230 | * and host. | ||
4231 | * | ||
4232 | */ | ||
4233 | int ata_device_resume(struct ata_port *ap, struct ata_device *dev) | ||
4234 | { | ||
4235 | if (ap->flags & ATA_FLAG_SUSPENDED) { | ||
4236 | ap->flags &= ~ATA_FLAG_SUSPENDED; | ||
4237 | ata_set_mode(ap); | ||
4238 | } | ||
4239 | if (!ata_dev_present(dev)) | ||
4240 | return 0; | ||
4241 | if (dev->class == ATA_DEV_ATA) | ||
4242 | ata_start_drive(ap, dev); | ||
4243 | |||
4244 | return 0; | ||
4245 | } | ||
4246 | |||
4247 | /** | ||
4248 | * ata_device_suspend - prepare a device for suspend | ||
4249 | * | ||
4250 | * Flush the cache on the drive, if appropriate, then issue a | ||
4251 | * standbynow command. | ||
4252 | * | ||
4253 | */ | ||
4254 | int ata_device_suspend(struct ata_port *ap, struct ata_device *dev) | ||
4255 | { | ||
4256 | if (!ata_dev_present(dev)) | ||
4257 | return 0; | ||
4258 | if (dev->class == ATA_DEV_ATA) | ||
4259 | ata_flush_cache(ap, dev); | ||
4260 | |||
4261 | ata_standby_drive(ap, dev); | ||
4262 | ap->flags |= ATA_FLAG_SUSPENDED; | ||
4263 | return 0; | ||
4264 | } | ||
4265 | |||
4157 | int ata_port_start (struct ata_port *ap) | 4266 | int ata_port_start (struct ata_port *ap) |
4158 | { | 4267 | { |
4159 | struct device *dev = ap->host_set->dev; | 4268 | struct device *dev = ap->host_set->dev; |
@@ -4902,6 +5011,23 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits) | |||
4902 | 5011 | ||
4903 | return (tmp == bits->val) ? 1 : 0; | 5012 | return (tmp == bits->val) ? 1 : 0; |
4904 | } | 5013 | } |
5014 | |||
5015 | int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state) | ||
5016 | { | ||
5017 | pci_save_state(pdev); | ||
5018 | pci_disable_device(pdev); | ||
5019 | pci_set_power_state(pdev, PCI_D3hot); | ||
5020 | return 0; | ||
5021 | } | ||
5022 | |||
5023 | int ata_pci_device_resume(struct pci_dev *pdev) | ||
5024 | { | ||
5025 | pci_set_power_state(pdev, PCI_D0); | ||
5026 | pci_restore_state(pdev); | ||
5027 | pci_enable_device(pdev); | ||
5028 | pci_set_master(pdev); | ||
5029 | return 0; | ||
5030 | } | ||
4905 | #endif /* CONFIG_PCI */ | 5031 | #endif /* CONFIG_PCI */ |
4906 | 5032 | ||
4907 | 5033 | ||
@@ -5005,4 +5131,11 @@ EXPORT_SYMBOL_GPL(ata_pci_host_stop); | |||
5005 | EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); | 5131 | EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); |
5006 | EXPORT_SYMBOL_GPL(ata_pci_init_one); | 5132 | EXPORT_SYMBOL_GPL(ata_pci_init_one); |
5007 | EXPORT_SYMBOL_GPL(ata_pci_remove_one); | 5133 | EXPORT_SYMBOL_GPL(ata_pci_remove_one); |
5134 | EXPORT_SYMBOL_GPL(ata_pci_device_suspend); | ||
5135 | EXPORT_SYMBOL_GPL(ata_pci_device_resume); | ||
5008 | #endif /* CONFIG_PCI */ | 5136 | #endif /* CONFIG_PCI */ |
5137 | |||
5138 | EXPORT_SYMBOL_GPL(ata_device_suspend); | ||
5139 | EXPORT_SYMBOL_GPL(ata_device_resume); | ||
5140 | EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); | ||
5141 | EXPORT_SYMBOL_GPL(ata_scsi_device_resume); | ||