diff options
Diffstat (limited to 'drivers/ata/libahci.c')
| -rw-r--r-- | drivers/ata/libahci.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index d61740e78d6d..402967902cbe 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c | |||
| @@ -496,8 +496,8 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv) | |||
| 496 | } | 496 | } |
| 497 | } | 497 | } |
| 498 | 498 | ||
| 499 | /* fabricate port_map from cap.nr_ports */ | 499 | /* fabricate port_map from cap.nr_ports for < AHCI 1.3 */ |
| 500 | if (!port_map) { | 500 | if (!port_map && vers < 0x10300) { |
| 501 | port_map = (1 << ahci_nr_ports(cap)) - 1; | 501 | port_map = (1 << ahci_nr_ports(cap)) - 1; |
| 502 | dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map); | 502 | dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map); |
| 503 | 503 | ||
| @@ -593,8 +593,22 @@ EXPORT_SYMBOL_GPL(ahci_start_engine); | |||
| 593 | int ahci_stop_engine(struct ata_port *ap) | 593 | int ahci_stop_engine(struct ata_port *ap) |
| 594 | { | 594 | { |
| 595 | void __iomem *port_mmio = ahci_port_base(ap); | 595 | void __iomem *port_mmio = ahci_port_base(ap); |
| 596 | struct ahci_host_priv *hpriv = ap->host->private_data; | ||
| 596 | u32 tmp; | 597 | u32 tmp; |
| 597 | 598 | ||
| 599 | /* | ||
| 600 | * On some controllers, stopping a port's DMA engine while the port | ||
| 601 | * is in ALPM state (partial or slumber) results in failures on | ||
| 602 | * subsequent DMA engine starts. For those controllers, put the | ||
| 603 | * port back in active state before stopping its DMA engine. | ||
| 604 | */ | ||
| 605 | if ((hpriv->flags & AHCI_HFLAG_WAKE_BEFORE_STOP) && | ||
| 606 | (ap->link.lpm_policy > ATA_LPM_MAX_POWER) && | ||
| 607 | ahci_set_lpm(&ap->link, ATA_LPM_MAX_POWER, ATA_LPM_WAKE_ONLY)) { | ||
| 608 | dev_err(ap->host->dev, "Failed to wake up port before engine stop\n"); | ||
| 609 | return -EIO; | ||
| 610 | } | ||
| 611 | |||
| 598 | tmp = readl(port_mmio + PORT_CMD); | 612 | tmp = readl(port_mmio + PORT_CMD); |
| 599 | 613 | ||
| 600 | /* check if the HBA is idle */ | 614 | /* check if the HBA is idle */ |
| @@ -689,6 +703,9 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, | |||
| 689 | void __iomem *port_mmio = ahci_port_base(ap); | 703 | void __iomem *port_mmio = ahci_port_base(ap); |
| 690 | 704 | ||
| 691 | if (policy != ATA_LPM_MAX_POWER) { | 705 | if (policy != ATA_LPM_MAX_POWER) { |
| 706 | /* wakeup flag only applies to the max power policy */ | ||
| 707 | hints &= ~ATA_LPM_WAKE_ONLY; | ||
| 708 | |||
| 692 | /* | 709 | /* |
| 693 | * Disable interrupts on Phy Ready. This keeps us from | 710 | * Disable interrupts on Phy Ready. This keeps us from |
| 694 | * getting woken up due to spurious phy ready | 711 | * getting woken up due to spurious phy ready |
| @@ -704,7 +721,8 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, | |||
| 704 | u32 cmd = readl(port_mmio + PORT_CMD); | 721 | u32 cmd = readl(port_mmio + PORT_CMD); |
| 705 | 722 | ||
| 706 | if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) { | 723 | if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) { |
| 707 | cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE); | 724 | if (!(hints & ATA_LPM_WAKE_ONLY)) |
| 725 | cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE); | ||
| 708 | cmd |= PORT_CMD_ICC_ACTIVE; | 726 | cmd |= PORT_CMD_ICC_ACTIVE; |
| 709 | 727 | ||
| 710 | writel(cmd, port_mmio + PORT_CMD); | 728 | writel(cmd, port_mmio + PORT_CMD); |
| @@ -712,6 +730,9 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, | |||
| 712 | 730 | ||
| 713 | /* wait 10ms to be sure we've come out of LPM state */ | 731 | /* wait 10ms to be sure we've come out of LPM state */ |
| 714 | ata_msleep(ap, 10); | 732 | ata_msleep(ap, 10); |
| 733 | |||
| 734 | if (hints & ATA_LPM_WAKE_ONLY) | ||
| 735 | return 0; | ||
| 715 | } else { | 736 | } else { |
| 716 | cmd |= PORT_CMD_ALPE; | 737 | cmd |= PORT_CMD_ALPE; |
| 717 | if (policy == ATA_LPM_MIN_POWER) | 738 | if (policy == ATA_LPM_MIN_POWER) |
