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 | ||
