diff options
Diffstat (limited to 'drivers/ata/libahci.c')
-rw-r--r-- | drivers/ata/libahci.c | 194 |
1 files changed, 64 insertions, 130 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 8eea309ea212..ebc08d65b3dd 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c | |||
@@ -56,9 +56,8 @@ MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip) | |||
56 | module_param_named(ignore_sss, ahci_ignore_sss, int, 0444); | 56 | module_param_named(ignore_sss, ahci_ignore_sss, int, 0444); |
57 | MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)"); | 57 | MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)"); |
58 | 58 | ||
59 | static int ahci_enable_alpm(struct ata_port *ap, | 59 | static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, |
60 | enum link_pm policy); | 60 | unsigned hints); |
61 | static void ahci_disable_alpm(struct ata_port *ap); | ||
62 | static ssize_t ahci_led_show(struct ata_port *ap, char *buf); | 61 | static ssize_t ahci_led_show(struct ata_port *ap, char *buf); |
63 | static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, | 62 | static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, |
64 | size_t size); | 63 | size_t size); |
@@ -164,8 +163,7 @@ struct ata_port_operations ahci_ops = { | |||
164 | .pmp_attach = ahci_pmp_attach, | 163 | .pmp_attach = ahci_pmp_attach, |
165 | .pmp_detach = ahci_pmp_detach, | 164 | .pmp_detach = ahci_pmp_detach, |
166 | 165 | ||
167 | .enable_pm = ahci_enable_alpm, | 166 | .set_lpm = ahci_set_lpm, |
168 | .disable_pm = ahci_disable_alpm, | ||
169 | .em_show = ahci_led_show, | 167 | .em_show = ahci_led_show, |
170 | .em_store = ahci_led_store, | 168 | .em_store = ahci_led_store, |
171 | .sw_activity_show = ahci_activity_show, | 169 | .sw_activity_show = ahci_activity_show, |
@@ -569,7 +567,7 @@ int ahci_stop_engine(struct ata_port *ap) | |||
569 | writel(tmp, port_mmio + PORT_CMD); | 567 | writel(tmp, port_mmio + PORT_CMD); |
570 | 568 | ||
571 | /* wait for engine to stop. This could be as long as 500 msec */ | 569 | /* wait for engine to stop. This could be as long as 500 msec */ |
572 | tmp = ata_wait_register(port_mmio + PORT_CMD, | 570 | tmp = ata_wait_register(ap, port_mmio + PORT_CMD, |
573 | PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500); | 571 | PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500); |
574 | if (tmp & PORT_CMD_LIST_ON) | 572 | if (tmp & PORT_CMD_LIST_ON) |
575 | return -EIO; | 573 | return -EIO; |
@@ -616,7 +614,7 @@ static int ahci_stop_fis_rx(struct ata_port *ap) | |||
616 | writel(tmp, port_mmio + PORT_CMD); | 614 | writel(tmp, port_mmio + PORT_CMD); |
617 | 615 | ||
618 | /* wait for completion, spec says 500ms, give it 1000 */ | 616 | /* wait for completion, spec says 500ms, give it 1000 */ |
619 | tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON, | 617 | tmp = ata_wait_register(ap, port_mmio + PORT_CMD, PORT_CMD_FIS_ON, |
620 | PORT_CMD_FIS_ON, 10, 1000); | 618 | PORT_CMD_FIS_ON, 10, 1000); |
621 | if (tmp & PORT_CMD_FIS_ON) | 619 | if (tmp & PORT_CMD_FIS_ON) |
622 | return -EBUSY; | 620 | return -EBUSY; |
@@ -642,127 +640,56 @@ static void ahci_power_up(struct ata_port *ap) | |||
642 | writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD); | 640 | writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD); |
643 | } | 641 | } |
644 | 642 | ||
645 | static void ahci_disable_alpm(struct ata_port *ap) | 643 | static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, |
644 | unsigned int hints) | ||
646 | { | 645 | { |
646 | struct ata_port *ap = link->ap; | ||
647 | struct ahci_host_priv *hpriv = ap->host->private_data; | 647 | struct ahci_host_priv *hpriv = ap->host->private_data; |
648 | void __iomem *port_mmio = ahci_port_base(ap); | ||
649 | u32 cmd; | ||
650 | struct ahci_port_priv *pp = ap->private_data; | 648 | struct ahci_port_priv *pp = ap->private_data; |
651 | |||
652 | /* IPM bits should be disabled by libata-core */ | ||
653 | /* get the existing command bits */ | ||
654 | cmd = readl(port_mmio + PORT_CMD); | ||
655 | |||
656 | /* disable ALPM and ASP */ | ||
657 | cmd &= ~PORT_CMD_ASP; | ||
658 | cmd &= ~PORT_CMD_ALPE; | ||
659 | |||
660 | /* force the interface back to active */ | ||
661 | cmd |= PORT_CMD_ICC_ACTIVE; | ||
662 | |||
663 | /* write out new cmd value */ | ||
664 | writel(cmd, port_mmio + PORT_CMD); | ||
665 | cmd = readl(port_mmio + PORT_CMD); | ||
666 | |||
667 | /* wait 10ms to be sure we've come out of any low power state */ | ||
668 | msleep(10); | ||
669 | |||
670 | /* clear out any PhyRdy stuff from interrupt status */ | ||
671 | writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT); | ||
672 | |||
673 | /* go ahead and clean out PhyRdy Change from Serror too */ | ||
674 | ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18))); | ||
675 | |||
676 | /* | ||
677 | * Clear flag to indicate that we should ignore all PhyRdy | ||
678 | * state changes | ||
679 | */ | ||
680 | hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG; | ||
681 | |||
682 | /* | ||
683 | * Enable interrupts on Phy Ready. | ||
684 | */ | ||
685 | pp->intr_mask |= PORT_IRQ_PHYRDY; | ||
686 | writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); | ||
687 | |||
688 | /* | ||
689 | * don't change the link pm policy - we can be called | ||
690 | * just to turn of link pm temporarily | ||
691 | */ | ||
692 | } | ||
693 | |||
694 | static int ahci_enable_alpm(struct ata_port *ap, | ||
695 | enum link_pm policy) | ||
696 | { | ||
697 | struct ahci_host_priv *hpriv = ap->host->private_data; | ||
698 | void __iomem *port_mmio = ahci_port_base(ap); | 649 | void __iomem *port_mmio = ahci_port_base(ap); |
699 | u32 cmd; | ||
700 | struct ahci_port_priv *pp = ap->private_data; | ||
701 | u32 asp; | ||
702 | 650 | ||
703 | /* Make sure the host is capable of link power management */ | 651 | if (policy != ATA_LPM_MAX_POWER) { |
704 | if (!(hpriv->cap & HOST_CAP_ALPM)) | ||
705 | return -EINVAL; | ||
706 | |||
707 | switch (policy) { | ||
708 | case MAX_PERFORMANCE: | ||
709 | case NOT_AVAILABLE: | ||
710 | /* | 652 | /* |
711 | * if we came here with NOT_AVAILABLE, | 653 | * Disable interrupts on Phy Ready. This keeps us from |
712 | * it just means this is the first time we | 654 | * getting woken up due to spurious phy ready |
713 | * have tried to enable - default to max performance, | 655 | * interrupts. |
714 | * and let the user go to lower power modes on request. | ||
715 | */ | 656 | */ |
716 | ahci_disable_alpm(ap); | 657 | pp->intr_mask &= ~PORT_IRQ_PHYRDY; |
717 | return 0; | 658 | writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); |
718 | case MIN_POWER: | 659 | |
719 | /* configure HBA to enter SLUMBER */ | 660 | sata_link_scr_lpm(link, policy, false); |
720 | asp = PORT_CMD_ASP; | ||
721 | break; | ||
722 | case MEDIUM_POWER: | ||
723 | /* configure HBA to enter PARTIAL */ | ||
724 | asp = 0; | ||
725 | break; | ||
726 | default: | ||
727 | return -EINVAL; | ||
728 | } | 661 | } |
729 | 662 | ||
730 | /* | 663 | if (hpriv->cap & HOST_CAP_ALPM) { |
731 | * Disable interrupts on Phy Ready. This keeps us from | 664 | u32 cmd = readl(port_mmio + PORT_CMD); |
732 | * getting woken up due to spurious phy ready interrupts | ||
733 | * TBD - Hot plug should be done via polling now, is | ||
734 | * that even supported? | ||
735 | */ | ||
736 | pp->intr_mask &= ~PORT_IRQ_PHYRDY; | ||
737 | writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); | ||
738 | 665 | ||
739 | /* | 666 | if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) { |
740 | * Set a flag to indicate that we should ignore all PhyRdy | 667 | cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE); |
741 | * state changes since these can happen now whenever we | 668 | cmd |= PORT_CMD_ICC_ACTIVE; |
742 | * change link state | ||
743 | */ | ||
744 | hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG; | ||
745 | 669 | ||
746 | /* get the existing command bits */ | 670 | writel(cmd, port_mmio + PORT_CMD); |
747 | cmd = readl(port_mmio + PORT_CMD); | 671 | readl(port_mmio + PORT_CMD); |
748 | 672 | ||
749 | /* | 673 | /* wait 10ms to be sure we've come out of LPM state */ |
750 | * Set ASP based on Policy | 674 | ata_msleep(ap, 10); |
751 | */ | 675 | } else { |
752 | cmd |= asp; | 676 | cmd |= PORT_CMD_ALPE; |
677 | if (policy == ATA_LPM_MIN_POWER) | ||
678 | cmd |= PORT_CMD_ASP; | ||
753 | 679 | ||
754 | /* | 680 | /* write out new cmd value */ |
755 | * Setting this bit will instruct the HBA to aggressively | 681 | writel(cmd, port_mmio + PORT_CMD); |
756 | * enter a lower power link state when it's appropriate and | 682 | } |
757 | * based on the value set above for ASP | 683 | } |
758 | */ | ||
759 | cmd |= PORT_CMD_ALPE; | ||
760 | 684 | ||
761 | /* write out new cmd value */ | 685 | if (policy == ATA_LPM_MAX_POWER) { |
762 | writel(cmd, port_mmio + PORT_CMD); | 686 | sata_link_scr_lpm(link, policy, false); |
763 | cmd = readl(port_mmio + PORT_CMD); | 687 | |
688 | /* turn PHYRDY IRQ back on */ | ||
689 | pp->intr_mask |= PORT_IRQ_PHYRDY; | ||
690 | writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); | ||
691 | } | ||
764 | 692 | ||
765 | /* IPM bits should be set by libata-core */ | ||
766 | return 0; | 693 | return 0; |
767 | } | 694 | } |
768 | 695 | ||
@@ -813,7 +740,7 @@ static void ahci_start_port(struct ata_port *ap) | |||
813 | emp->led_state, | 740 | emp->led_state, |
814 | 4); | 741 | 4); |
815 | if (rc == -EBUSY) | 742 | if (rc == -EBUSY) |
816 | msleep(1); | 743 | ata_msleep(ap, 1); |
817 | else | 744 | else |
818 | break; | 745 | break; |
819 | } | 746 | } |
@@ -872,7 +799,7 @@ int ahci_reset_controller(struct ata_host *host) | |||
872 | * reset must complete within 1 second, or | 799 | * reset must complete within 1 second, or |
873 | * the hardware should be considered fried. | 800 | * the hardware should be considered fried. |
874 | */ | 801 | */ |
875 | tmp = ata_wait_register(mmio + HOST_CTL, HOST_RESET, | 802 | tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET, |
876 | HOST_RESET, 10, 1000); | 803 | HOST_RESET, 10, 1000); |
877 | 804 | ||
878 | if (tmp & HOST_RESET) { | 805 | if (tmp & HOST_RESET) { |
@@ -1252,7 +1179,7 @@ int ahci_kick_engine(struct ata_port *ap) | |||
1252 | writel(tmp, port_mmio + PORT_CMD); | 1179 | writel(tmp, port_mmio + PORT_CMD); |
1253 | 1180 | ||
1254 | rc = 0; | 1181 | rc = 0; |
1255 | tmp = ata_wait_register(port_mmio + PORT_CMD, | 1182 | tmp = ata_wait_register(ap, port_mmio + PORT_CMD, |
1256 | PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); | 1183 | PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); |
1257 | if (tmp & PORT_CMD_CLO) | 1184 | if (tmp & PORT_CMD_CLO) |
1258 | rc = -EIO; | 1185 | rc = -EIO; |
@@ -1282,8 +1209,8 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp, | |||
1282 | writel(1, port_mmio + PORT_CMD_ISSUE); | 1209 | writel(1, port_mmio + PORT_CMD_ISSUE); |
1283 | 1210 | ||
1284 | if (timeout_msec) { | 1211 | if (timeout_msec) { |
1285 | tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, | 1212 | tmp = ata_wait_register(ap, port_mmio + PORT_CMD_ISSUE, |
1286 | 1, timeout_msec); | 1213 | 0x1, 0x1, 1, timeout_msec); |
1287 | if (tmp & 0x1) { | 1214 | if (tmp & 0x1) { |
1288 | ahci_kick_engine(ap); | 1215 | ahci_kick_engine(ap); |
1289 | return -EBUSY; | 1216 | return -EBUSY; |
@@ -1330,7 +1257,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, | |||
1330 | } | 1257 | } |
1331 | 1258 | ||
1332 | /* spec says at least 5us, but be generous and sleep for 1ms */ | 1259 | /* spec says at least 5us, but be generous and sleep for 1ms */ |
1333 | msleep(1); | 1260 | ata_msleep(ap, 1); |
1334 | 1261 | ||
1335 | /* issue the second D2H Register FIS */ | 1262 | /* issue the second D2H Register FIS */ |
1336 | tf.ctl &= ~ATA_SRST; | 1263 | tf.ctl &= ~ATA_SRST; |
@@ -1660,15 +1587,10 @@ static void ahci_port_intr(struct ata_port *ap) | |||
1660 | if (unlikely(resetting)) | 1587 | if (unlikely(resetting)) |
1661 | status &= ~PORT_IRQ_BAD_PMP; | 1588 | status &= ~PORT_IRQ_BAD_PMP; |
1662 | 1589 | ||
1663 | /* If we are getting PhyRdy, this is | 1590 | /* if LPM is enabled, PHYRDY doesn't mean anything */ |
1664 | * just a power state change, we should | 1591 | if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) { |
1665 | * clear out this, plus the PhyRdy/Comm | ||
1666 | * Wake bits from Serror | ||
1667 | */ | ||
1668 | if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) && | ||
1669 | (status & PORT_IRQ_PHYRDY)) { | ||
1670 | status &= ~PORT_IRQ_PHYRDY; | 1592 | status &= ~PORT_IRQ_PHYRDY; |
1671 | ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18))); | 1593 | ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG); |
1672 | } | 1594 | } |
1673 | 1595 | ||
1674 | if (unlikely(status & PORT_IRQ_ERROR)) { | 1596 | if (unlikely(status & PORT_IRQ_ERROR)) { |
@@ -1830,12 +1752,24 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) | |||
1830 | static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc) | 1752 | static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc) |
1831 | { | 1753 | { |
1832 | struct ahci_port_priv *pp = qc->ap->private_data; | 1754 | struct ahci_port_priv *pp = qc->ap->private_data; |
1833 | u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; | 1755 | u8 *rx_fis = pp->rx_fis; |
1834 | 1756 | ||
1835 | if (pp->fbs_enabled) | 1757 | if (pp->fbs_enabled) |
1836 | d2h_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ; | 1758 | rx_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ; |
1759 | |||
1760 | /* | ||
1761 | * After a successful execution of an ATA PIO data-in command, | ||
1762 | * the device doesn't send D2H Reg FIS to update the TF and | ||
1763 | * the host should take TF and E_Status from the preceding PIO | ||
1764 | * Setup FIS. | ||
1765 | */ | ||
1766 | if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE && | ||
1767 | !(qc->flags & ATA_QCFLAG_FAILED)) { | ||
1768 | ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf); | ||
1769 | qc->result_tf.command = (rx_fis + RX_FIS_PIO_SETUP)[15]; | ||
1770 | } else | ||
1771 | ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf); | ||
1837 | 1772 | ||
1838 | ata_tf_from_fis(d2h_fis, &qc->result_tf); | ||
1839 | return true; | 1773 | return true; |
1840 | } | 1774 | } |
1841 | 1775 | ||