aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c157
1 files changed, 155 insertions, 2 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index c8ab947cf359..ed9b407e42d4 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -49,6 +49,9 @@
49#define DRV_NAME "ahci" 49#define DRV_NAME "ahci"
50#define DRV_VERSION "3.0" 50#define DRV_VERSION "3.0"
51 51
52static int ahci_enable_alpm(struct ata_port *ap,
53 enum link_pm policy);
54static void ahci_disable_alpm(struct ata_port *ap);
52 55
53enum { 56enum {
54 AHCI_PCI_BAR = 5, 57 AHCI_PCI_BAR = 5,
@@ -99,6 +102,7 @@ enum {
99 HOST_CAP_SSC = (1 << 14), /* Slumber capable */ 102 HOST_CAP_SSC = (1 << 14), /* Slumber capable */
100 HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ 103 HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
101 HOST_CAP_CLO = (1 << 24), /* Command List Override support */ 104 HOST_CAP_CLO = (1 << 24), /* Command List Override support */
105 HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
102 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ 106 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
103 HOST_CAP_SNTF = (1 << 29), /* SNotification register */ 107 HOST_CAP_SNTF = (1 << 29), /* SNotification register */
104 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ 108 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
@@ -155,6 +159,8 @@ enum {
155 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS, 159 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
156 160
157 /* PORT_CMD bits */ 161 /* PORT_CMD bits */
162 PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */
163 PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
158 PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ 164 PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
159 PORT_CMD_PMP = (1 << 17), /* PMP attached */ 165 PORT_CMD_PMP = (1 << 17), /* PMP attached */
160 PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ 166 PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
@@ -178,13 +184,14 @@ enum {
178 AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */ 184 AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
179 AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */ 185 AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
180 AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ 186 AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
187 AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */
181 188
182 /* ap->flags bits */ 189 /* ap->flags bits */
183 AHCI_FLAG_NO_HOTPLUG = (1 << 24), /* ignore PxSERR.DIAG.N */
184 190
185 AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 191 AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
186 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | 192 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
187 ATA_FLAG_ACPI_SATA | ATA_FLAG_AN, 193 ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
194 ATA_FLAG_IPM,
188 AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY, 195 AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY,
189}; 196};
190 197
@@ -254,6 +261,11 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
254static int ahci_pci_device_resume(struct pci_dev *pdev); 261static int ahci_pci_device_resume(struct pci_dev *pdev);
255#endif 262#endif
256 263
264static struct class_device_attribute *ahci_shost_attrs[] = {
265 &class_device_attr_link_power_management_policy,
266 NULL
267};
268
257static struct scsi_host_template ahci_sht = { 269static struct scsi_host_template ahci_sht = {
258 .module = THIS_MODULE, 270 .module = THIS_MODULE,
259 .name = DRV_NAME, 271 .name = DRV_NAME,
@@ -271,6 +283,7 @@ static struct scsi_host_template ahci_sht = {
271 .slave_configure = ata_scsi_slave_config, 283 .slave_configure = ata_scsi_slave_config,
272 .slave_destroy = ata_scsi_slave_destroy, 284 .slave_destroy = ata_scsi_slave_destroy,
273 .bios_param = ata_std_bios_param, 285 .bios_param = ata_std_bios_param,
286 .shost_attrs = ahci_shost_attrs,
274}; 287};
275 288
276static const struct ata_port_operations ahci_ops = { 289static const struct ata_port_operations ahci_ops = {
@@ -302,6 +315,8 @@ static const struct ata_port_operations ahci_ops = {
302 .port_suspend = ahci_port_suspend, 315 .port_suspend = ahci_port_suspend,
303 .port_resume = ahci_port_resume, 316 .port_resume = ahci_port_resume,
304#endif 317#endif
318 .enable_pm = ahci_enable_alpm,
319 .disable_pm = ahci_disable_alpm,
305 320
306 .port_start = ahci_port_start, 321 .port_start = ahci_port_start,
307 .port_stop = ahci_port_stop, 322 .port_stop = ahci_port_stop,
@@ -836,6 +851,130 @@ static void ahci_power_up(struct ata_port *ap)
836 writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD); 851 writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
837} 852}
838 853
854static void ahci_disable_alpm(struct ata_port *ap)
855{
856 struct ahci_host_priv *hpriv = ap->host->private_data;
857 void __iomem *port_mmio = ahci_port_base(ap);
858 u32 cmd;
859 struct ahci_port_priv *pp = ap->private_data;
860
861 /* IPM bits should be disabled by libata-core */
862 /* get the existing command bits */
863 cmd = readl(port_mmio + PORT_CMD);
864
865 /* disable ALPM and ASP */
866 cmd &= ~PORT_CMD_ASP;
867 cmd &= ~PORT_CMD_ALPE;
868
869 /* force the interface back to active */
870 cmd |= PORT_CMD_ICC_ACTIVE;
871
872 /* write out new cmd value */
873 writel(cmd, port_mmio + PORT_CMD);
874 cmd = readl(port_mmio + PORT_CMD);
875
876 /* wait 10ms to be sure we've come out of any low power state */
877 msleep(10);
878
879 /* clear out any PhyRdy stuff from interrupt status */
880 writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT);
881
882 /* go ahead and clean out PhyRdy Change from Serror too */
883 ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
884
885 /*
886 * Clear flag to indicate that we should ignore all PhyRdy
887 * state changes
888 */
889 hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG;
890
891 /*
892 * Enable interrupts on Phy Ready.
893 */
894 pp->intr_mask |= PORT_IRQ_PHYRDY;
895 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
896
897 /*
898 * don't change the link pm policy - we can be called
899 * just to turn of link pm temporarily
900 */
901}
902
903static int ahci_enable_alpm(struct ata_port *ap,
904 enum link_pm policy)
905{
906 struct ahci_host_priv *hpriv = ap->host->private_data;
907 void __iomem *port_mmio = ahci_port_base(ap);
908 u32 cmd;
909 struct ahci_port_priv *pp = ap->private_data;
910 u32 asp;
911
912 /* Make sure the host is capable of link power management */
913 if (!(hpriv->cap & HOST_CAP_ALPM))
914 return -EINVAL;
915
916 switch (policy) {
917 case MAX_PERFORMANCE:
918 case NOT_AVAILABLE:
919 /*
920 * if we came here with NOT_AVAILABLE,
921 * it just means this is the first time we
922 * have tried to enable - default to max performance,
923 * and let the user go to lower power modes on request.
924 */
925 ahci_disable_alpm(ap);
926 return 0;
927 case MIN_POWER:
928 /* configure HBA to enter SLUMBER */
929 asp = PORT_CMD_ASP;
930 break;
931 case MEDIUM_POWER:
932 /* configure HBA to enter PARTIAL */
933 asp = 0;
934 break;
935 default:
936 return -EINVAL;
937 }
938
939 /*
940 * Disable interrupts on Phy Ready. This keeps us from
941 * getting woken up due to spurious phy ready interrupts
942 * TBD - Hot plug should be done via polling now, is
943 * that even supported?
944 */
945 pp->intr_mask &= ~PORT_IRQ_PHYRDY;
946 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
947
948 /*
949 * Set a flag to indicate that we should ignore all PhyRdy
950 * state changes since these can happen now whenever we
951 * change link state
952 */
953 hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG;
954
955 /* get the existing command bits */
956 cmd = readl(port_mmio + PORT_CMD);
957
958 /*
959 * Set ASP based on Policy
960 */
961 cmd |= asp;
962
963 /*
964 * Setting this bit will instruct the HBA to aggressively
965 * enter a lower power link state when it's appropriate and
966 * based on the value set above for ASP
967 */
968 cmd |= PORT_CMD_ALPE;
969
970 /* write out new cmd value */
971 writel(cmd, port_mmio + PORT_CMD);
972 cmd = readl(port_mmio + PORT_CMD);
973
974 /* IPM bits should be set by libata-core */
975 return 0;
976}
977
839#ifdef CONFIG_PM 978#ifdef CONFIG_PM
840static void ahci_power_down(struct ata_port *ap) 979static void ahci_power_down(struct ata_port *ap)
841{ 980{
@@ -1504,6 +1643,17 @@ static void ahci_port_intr(struct ata_port *ap)
1504 if (unlikely(resetting)) 1643 if (unlikely(resetting))
1505 status &= ~PORT_IRQ_BAD_PMP; 1644 status &= ~PORT_IRQ_BAD_PMP;
1506 1645
1646 /* If we are getting PhyRdy, this is
1647 * just a power state change, we should
1648 * clear out this, plus the PhyRdy/Comm
1649 * Wake bits from Serror
1650 */
1651 if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) &&
1652 (status & PORT_IRQ_PHYRDY)) {
1653 status &= ~PORT_IRQ_PHYRDY;
1654 ahci_scr_write(ap, SCR_ERROR, ((1 << 16) | (1 << 18)));
1655 }
1656
1507 if (unlikely(status & PORT_IRQ_ERROR)) { 1657 if (unlikely(status & PORT_IRQ_ERROR)) {
1508 ahci_error_intr(ap, status); 1658 ahci_error_intr(ap, status);
1509 return; 1659 return;
@@ -2151,6 +2301,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2151 ata_port_pbar_desc(ap, AHCI_PCI_BAR, 2301 ata_port_pbar_desc(ap, AHCI_PCI_BAR,
2152 0x100 + ap->port_no * 0x80, "port"); 2302 0x100 + ap->port_no * 0x80, "port");
2153 2303
2304 /* set initial link pm policy */
2305 ap->pm_policy = NOT_AVAILABLE;
2306
2154 /* standard SATA port setup */ 2307 /* standard SATA port setup */
2155 if (hpriv->port_map & (1 << i)) 2308 if (hpriv->port_map & (1 << i))
2156 ap->ioaddr.cmd_addr = port_mmio; 2309 ap->ioaddr.cmd_addr = port_mmio;