diff options
| -rw-r--r-- | drivers/ata/ahci.c | 3 | ||||
| -rw-r--r-- | drivers/ata/ahci.h | 1 | ||||
| -rw-r--r-- | drivers/ata/ahci_platform.c | 3 | ||||
| -rw-r--r-- | drivers/ata/libahci.c | 158 | ||||
| -rw-r--r-- | drivers/ata/libata-core.c | 201 | ||||
| -rw-r--r-- | drivers/ata/libata-eh.c | 164 | ||||
| -rw-r--r-- | drivers/ata/libata-scsi.c | 11 | ||||
| -rw-r--r-- | drivers/ata/libata.h | 4 | ||||
| -rw-r--r-- | include/linux/libata.h | 17 |
9 files changed, 206 insertions, 356 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 68f7b4216501..328826381a2d 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
| @@ -1208,9 +1208,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1208 | ata_port_pbar_desc(ap, AHCI_PCI_BAR, | 1208 | ata_port_pbar_desc(ap, AHCI_PCI_BAR, |
| 1209 | 0x100 + ap->port_no * 0x80, "port"); | 1209 | 0x100 + ap->port_no * 0x80, "port"); |
| 1210 | 1210 | ||
| 1211 | /* set initial link pm policy */ | ||
| 1212 | ap->lpm_policy = ATA_LPM_UNKNOWN; | ||
| 1213 | |||
| 1214 | /* set enclosure management message type */ | 1211 | /* set enclosure management message type */ |
| 1215 | if (ap->flags & ATA_FLAG_EM) | 1212 | if (ap->flags & ATA_FLAG_EM) |
| 1216 | ap->em_message_type = hpriv->em_msg_type; | 1213 | ap->em_message_type = hpriv->em_msg_type; |
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 93867d3f8dd3..1a2aacfdebc5 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h | |||
| @@ -201,7 +201,6 @@ enum { | |||
| 201 | AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */ | 201 | AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */ |
| 202 | AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */ | 202 | AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */ |
| 203 | AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ | 203 | AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */ |
| 204 | AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ | ||
| 205 | AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ | 204 | AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ |
| 206 | AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */ | 205 | AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */ |
| 207 | AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */ | 206 | AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */ |
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 07556853c0d6..6fef1fa75c54 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c | |||
| @@ -129,9 +129,6 @@ static int __init ahci_probe(struct platform_device *pdev) | |||
| 129 | ata_port_desc(ap, "mmio %pR", mem); | 129 | ata_port_desc(ap, "mmio %pR", mem); |
| 130 | ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); | 130 | ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); |
| 131 | 131 | ||
| 132 | /* set initial link pm policy */ | ||
| 133 | ap->lpm_policy = ATA_LPM_UNKNOWN; | ||
| 134 | |||
| 135 | /* set enclosure management message type */ | 132 | /* set enclosure management message type */ |
| 136 | if (ap->flags & ATA_FLAG_EM) | 133 | if (ap->flags & ATA_FLAG_EM) |
| 137 | ap->em_message_type = hpriv->em_msg_type; | 134 | ap->em_message_type = hpriv->em_msg_type; |
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index ed7803f2b4f1..437f92597788 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c | |||
| @@ -56,8 +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, enum ata_lpm_policy policy); | 59 | static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, |
| 60 | static void ahci_disable_alpm(struct ata_port *ap); | 60 | unsigned hints); |
| 61 | 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); |
| 62 | 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, |
| 63 | size_t size); | 63 | size_t size); |
| @@ -163,8 +163,7 @@ struct ata_port_operations ahci_ops = { | |||
| 163 | .pmp_attach = ahci_pmp_attach, | 163 | .pmp_attach = ahci_pmp_attach, |
| 164 | .pmp_detach = ahci_pmp_detach, | 164 | .pmp_detach = ahci_pmp_detach, |
| 165 | 165 | ||
| 166 | .enable_pm = ahci_enable_alpm, | 166 | .set_lpm = ahci_set_lpm, |
| 167 | .disable_pm = ahci_disable_alpm, | ||
| 168 | .em_show = ahci_led_show, | 167 | .em_show = ahci_led_show, |
| 169 | .em_store = ahci_led_store, | 168 | .em_store = ahci_led_store, |
| 170 | .sw_activity_show = ahci_activity_show, | 169 | .sw_activity_show = ahci_activity_show, |
| @@ -641,126 +640,56 @@ static void ahci_power_up(struct ata_port *ap) | |||
| 641 | writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD); | 640 | writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD); |
| 642 | } | 641 | } |
| 643 | 642 | ||
| 644 | 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) | ||
| 645 | { | 645 | { |
| 646 | struct ata_port *ap = link->ap; | ||
| 646 | struct ahci_host_priv *hpriv = ap->host->private_data; | 647 | struct ahci_host_priv *hpriv = ap->host->private_data; |
| 647 | void __iomem *port_mmio = ahci_port_base(ap); | ||
| 648 | u32 cmd; | ||
| 649 | struct ahci_port_priv *pp = ap->private_data; | 648 | struct ahci_port_priv *pp = ap->private_data; |
| 650 | |||
| 651 | /* LPM bits should be disabled by libata-core */ | ||
| 652 | /* get the existing command bits */ | ||
| 653 | cmd = readl(port_mmio + PORT_CMD); | ||
| 654 | |||
| 655 | /* disable ALPM and ASP */ | ||
| 656 | cmd &= ~PORT_CMD_ASP; | ||
| 657 | cmd &= ~PORT_CMD_ALPE; | ||
| 658 | |||
| 659 | /* force the interface back to active */ | ||
| 660 | cmd |= PORT_CMD_ICC_ACTIVE; | ||
| 661 | |||
| 662 | /* write out new cmd value */ | ||
| 663 | writel(cmd, port_mmio + PORT_CMD); | ||
| 664 | cmd = readl(port_mmio + PORT_CMD); | ||
| 665 | |||
| 666 | /* wait 10ms to be sure we've come out of any low power state */ | ||
| 667 | msleep(10); | ||
| 668 | |||
| 669 | /* clear out any PhyRdy stuff from interrupt status */ | ||
| 670 | writel(PORT_IRQ_PHYRDY, port_mmio + PORT_IRQ_STAT); | ||
| 671 | |||
| 672 | /* go ahead and clean out PhyRdy Change from Serror too */ | ||
| 673 | ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18))); | ||
| 674 | |||
| 675 | /* | ||
| 676 | * Clear flag to indicate that we should ignore all PhyRdy | ||
| 677 | * state changes | ||
| 678 | */ | ||
| 679 | hpriv->flags &= ~AHCI_HFLAG_NO_HOTPLUG; | ||
| 680 | |||
| 681 | /* | ||
| 682 | * Enable interrupts on Phy Ready. | ||
| 683 | */ | ||
| 684 | pp->intr_mask |= PORT_IRQ_PHYRDY; | ||
| 685 | writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); | ||
| 686 | |||
| 687 | /* | ||
| 688 | * don't change the link pm policy - we can be called | ||
| 689 | * just to turn of link pm temporarily | ||
| 690 | */ | ||
| 691 | } | ||
| 692 | |||
| 693 | static int ahci_enable_alpm(struct ata_port *ap, enum ata_lpm_policy policy) | ||
| 694 | { | ||
| 695 | struct ahci_host_priv *hpriv = ap->host->private_data; | ||
| 696 | void __iomem *port_mmio = ahci_port_base(ap); | 649 | void __iomem *port_mmio = ahci_port_base(ap); |
| 697 | u32 cmd; | ||
| 698 | struct ahci_port_priv *pp = ap->private_data; | ||
| 699 | u32 asp; | ||
| 700 | |||
| 701 | /* Make sure the host is capable of link power management */ | ||
| 702 | if (!(hpriv->cap & HOST_CAP_ALPM)) | ||
| 703 | return -EINVAL; | ||
| 704 | 650 | ||
| 705 | switch (policy) { | 651 | if (policy != ATA_LPM_MAX_POWER) { |
| 706 | case ATA_LPM_MAX_POWER: | ||
| 707 | case ATA_LPM_UNKNOWN: | ||
| 708 | /* | 652 | /* |
| 709 | * if we came here with ATA_LPM_UNKNOWN, | 653 | * Disable interrupts on Phy Ready. This keeps us from |
| 710 | * it just means this is the first time we | 654 | * getting woken up due to spurious phy ready |
| 711 | * have tried to enable - default to max performance, | 655 | * interrupts. |
| 712 | * and let the user go to lower power modes on request. | ||
| 713 | */ | 656 | */ |
| 714 | ahci_disable_alpm(ap); | 657 | pp->intr_mask &= ~PORT_IRQ_PHYRDY; |
| 715 | return 0; | 658 | writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); |
| 716 | case ATA_LPM_MIN_POWER: | 659 | |
| 717 | /* configure HBA to enter SLUMBER */ | 660 | sata_link_scr_lpm(link, policy, false); |
| 718 | asp = PORT_CMD_ASP; | ||
| 719 | break; | ||
| 720 | case ATA_LPM_MED_POWER: | ||
| 721 | /* configure HBA to enter PARTIAL */ | ||
| 722 | asp = 0; | ||
| 723 | break; | ||
| 724 | default: | ||
| 725 | return -EINVAL; | ||
| 726 | } | 661 | } |
| 727 | 662 | ||
| 728 | /* | 663 | if (hpriv->cap & HOST_CAP_ALPM) { |
| 729 | * Disable interrupts on Phy Ready. This keeps us from | 664 | u32 cmd = readl(port_mmio + PORT_CMD); |
| 730 | * getting woken up due to spurious phy ready interrupts | ||
| 731 | * TBD - Hot plug should be done via polling now, is | ||
| 732 | * that even supported? | ||
| 733 | */ | ||
| 734 | pp->intr_mask &= ~PORT_IRQ_PHYRDY; | ||
| 735 | writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); | ||
| 736 | 665 | ||
| 737 | /* | 666 | if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) { |
| 738 | * Set a flag to indicate that we should ignore all PhyRdy | 667 | cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE); |
| 739 | * state changes since these can happen now whenever we | 668 | cmd |= PORT_CMD_ICC_ACTIVE; |
| 740 | * change link state | ||
| 741 | */ | ||
| 742 | hpriv->flags |= AHCI_HFLAG_NO_HOTPLUG; | ||
| 743 | 669 | ||
| 744 | /* get the existing command bits */ | 670 | writel(cmd, port_mmio + PORT_CMD); |
| 745 | cmd = readl(port_mmio + PORT_CMD); | 671 | readl(port_mmio + PORT_CMD); |
| 746 | 672 | ||
| 747 | /* | 673 | /* wait 10ms to be sure we've come out of LPM state */ |
| 748 | * Set ASP based on Policy | 674 | msleep(10); |
| 749 | */ | 675 | } else { |
| 750 | cmd |= asp; | 676 | cmd |= PORT_CMD_ALPE; |
| 677 | if (policy == ATA_LPM_MIN_POWER) | ||
| 678 | cmd |= PORT_CMD_ASP; | ||
| 751 | 679 | ||
| 752 | /* | 680 | /* write out new cmd value */ |
| 753 | * Setting this bit will instruct the HBA to aggressively | 681 | writel(cmd, port_mmio + PORT_CMD); |
| 754 | * enter a lower power link state when it's appropriate and | 682 | } |
| 755 | * based on the value set above for ASP | 683 | } |
| 756 | */ | ||
| 757 | cmd |= PORT_CMD_ALPE; | ||
| 758 | 684 | ||
| 759 | /* write out new cmd value */ | 685 | if (policy == ATA_LPM_MAX_POWER) { |
| 760 | writel(cmd, port_mmio + PORT_CMD); | 686 | sata_link_scr_lpm(link, policy, false); |
| 761 | 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 | } | ||
| 762 | 692 | ||
| 763 | /* LPM bits should be set by libata-core */ | ||
| 764 | return 0; | 693 | return 0; |
| 765 | } | 694 | } |
| 766 | 695 | ||
| @@ -1658,15 +1587,10 @@ static void ahci_port_intr(struct ata_port *ap) | |||
| 1658 | if (unlikely(resetting)) | 1587 | if (unlikely(resetting)) |
| 1659 | status &= ~PORT_IRQ_BAD_PMP; | 1588 | status &= ~PORT_IRQ_BAD_PMP; |
| 1660 | 1589 | ||
| 1661 | /* If we are getting PhyRdy, this is | 1590 | /* if LPM is enabled, PHYRDY doesn't mean anything */ |
| 1662 | * just a power state change, we should | 1591 | if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) { |
| 1663 | * clear out this, plus the PhyRdy/Comm | ||
| 1664 | * Wake bits from Serror | ||
| 1665 | */ | ||
| 1666 | if ((hpriv->flags & AHCI_HFLAG_NO_HOTPLUG) && | ||
| 1667 | (status & PORT_IRQ_PHYRDY)) { | ||
| 1668 | status &= ~PORT_IRQ_PHYRDY; | 1592 | status &= ~PORT_IRQ_PHYRDY; |
| 1669 | ahci_scr_write(&ap->link, SCR_ERROR, ((1 << 16) | (1 << 18))); | 1593 | ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG); |
| 1670 | } | 1594 | } |
| 1671 | 1595 | ||
| 1672 | if (unlikely(status & PORT_IRQ_ERROR)) { | 1596 | if (unlikely(status & PORT_IRQ_ERROR)) { |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b8024451234c..7c5538b9fa3b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -1028,182 +1028,6 @@ const char *sata_spd_string(unsigned int spd) | |||
| 1028 | return spd_str[spd - 1]; | 1028 | return spd_str[spd - 1]; |
| 1029 | } | 1029 | } |
| 1030 | 1030 | ||
| 1031 | static int ata_dev_set_dipm(struct ata_device *dev, enum ata_lpm_policy policy) | ||
| 1032 | { | ||
| 1033 | struct ata_link *link = dev->link; | ||
| 1034 | struct ata_port *ap = link->ap; | ||
| 1035 | u32 scontrol; | ||
| 1036 | unsigned int err_mask; | ||
| 1037 | int rc; | ||
| 1038 | |||
| 1039 | /* | ||
| 1040 | * disallow DIPM for drivers which haven't set | ||
| 1041 | * ATA_FLAG_LPM. This is because when DIPM is enabled, | ||
| 1042 | * phy ready will be set in the interrupt status on | ||
| 1043 | * state changes, which will cause some drivers to | ||
| 1044 | * think there are errors - additionally drivers will | ||
| 1045 | * need to disable hot plug. | ||
| 1046 | */ | ||
| 1047 | if (!(ap->flags & ATA_FLAG_LPM) || !ata_dev_enabled(dev)) { | ||
| 1048 | ap->lpm_policy = ATA_LPM_UNKNOWN; | ||
| 1049 | return -EINVAL; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | /* | ||
| 1053 | * For DIPM, we will only enable it for the | ||
| 1054 | * min_power setting. | ||
| 1055 | * | ||
| 1056 | * Why? Because Disks are too stupid to know that | ||
| 1057 | * If the host rejects a request to go to SLUMBER | ||
| 1058 | * they should retry at PARTIAL, and instead it | ||
| 1059 | * just would give up. So, for medium_power to | ||
| 1060 | * work at all, we need to only allow HIPM. | ||
| 1061 | */ | ||
| 1062 | rc = sata_scr_read(link, SCR_CONTROL, &scontrol); | ||
| 1063 | if (rc) | ||
| 1064 | return rc; | ||
| 1065 | |||
| 1066 | switch (policy) { | ||
| 1067 | case ATA_LPM_MIN_POWER: | ||
| 1068 | /* no restrictions on LPM transitions */ | ||
| 1069 | scontrol &= ~(0x3 << 8); | ||
| 1070 | rc = sata_scr_write(link, SCR_CONTROL, scontrol); | ||
| 1071 | if (rc) | ||
| 1072 | return rc; | ||
| 1073 | |||
| 1074 | /* enable DIPM */ | ||
| 1075 | if (dev->flags & ATA_DFLAG_DIPM) | ||
| 1076 | err_mask = ata_dev_set_feature(dev, | ||
| 1077 | SETFEATURES_SATA_ENABLE, SATA_DIPM); | ||
| 1078 | break; | ||
| 1079 | case ATA_LPM_MED_POWER: | ||
| 1080 | /* allow LPM to PARTIAL */ | ||
| 1081 | scontrol &= ~(0x1 << 8); | ||
| 1082 | scontrol |= (0x2 << 8); | ||
| 1083 | rc = sata_scr_write(link, SCR_CONTROL, scontrol); | ||
| 1084 | if (rc) | ||
| 1085 | return rc; | ||
| 1086 | |||
| 1087 | /* | ||
| 1088 | * we don't have to disable DIPM since LPM flags | ||
| 1089 | * disallow transitions to SLUMBER, which effectively | ||
| 1090 | * disable DIPM if it does not support PARTIAL | ||
| 1091 | */ | ||
| 1092 | break; | ||
| 1093 | case ATA_LPM_UNKNOWN: | ||
| 1094 | case ATA_LPM_MAX_POWER: | ||
| 1095 | /* disable all LPM transitions */ | ||
| 1096 | scontrol |= (0x3 << 8); | ||
| 1097 | rc = sata_scr_write(link, SCR_CONTROL, scontrol); | ||
| 1098 | if (rc) | ||
| 1099 | return rc; | ||
| 1100 | |||
| 1101 | /* | ||
| 1102 | * we don't have to disable DIPM since LPM flags | ||
| 1103 | * disallow all transitions which effectively | ||
| 1104 | * disable DIPM anyway. | ||
| 1105 | */ | ||
| 1106 | break; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | /* FIXME: handle SET FEATURES failure */ | ||
| 1110 | (void) err_mask; | ||
| 1111 | |||
| 1112 | return 0; | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | /** | ||
| 1116 | * ata_dev_enable_pm - enable SATA interface power management | ||
| 1117 | * @dev: device to enable power management | ||
| 1118 | * @policy: the link power management policy | ||
| 1119 | * | ||
| 1120 | * Enable SATA Interface power management. This will enable | ||
| 1121 | * Device Interface Power Management (DIPM) for min_power | ||
| 1122 | * policy, and then call driver specific callbacks for | ||
| 1123 | * enabling Host Initiated Power management. | ||
| 1124 | * | ||
| 1125 | * Locking: Caller. | ||
| 1126 | * Returns: -EINVAL if LPM is not supported, 0 otherwise. | ||
| 1127 | */ | ||
| 1128 | void ata_dev_enable_pm(struct ata_device *dev, enum ata_lpm_policy policy) | ||
| 1129 | { | ||
| 1130 | int rc = 0; | ||
| 1131 | struct ata_port *ap = dev->link->ap; | ||
| 1132 | |||
| 1133 | /* set HIPM first, then DIPM */ | ||
| 1134 | if (ap->ops->enable_pm) | ||
| 1135 | rc = ap->ops->enable_pm(ap, policy); | ||
| 1136 | if (rc) | ||
| 1137 | goto enable_pm_out; | ||
| 1138 | rc = ata_dev_set_dipm(dev, policy); | ||
| 1139 | |||
| 1140 | enable_pm_out: | ||
| 1141 | if (rc) | ||
| 1142 | ap->lpm_policy = ATA_LPM_MAX_POWER; | ||
| 1143 | else | ||
| 1144 | ap->lpm_policy = policy; | ||
| 1145 | return /* rc */; /* hopefully we can use 'rc' eventually */ | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | #ifdef CONFIG_PM | ||
| 1149 | /** | ||
| 1150 | * ata_dev_disable_pm - disable SATA interface power management | ||
| 1151 | * @dev: device to disable power management | ||
| 1152 | * | ||
| 1153 | * Disable SATA Interface power management. This will disable | ||
| 1154 | * Device Interface Power Management (DIPM) without changing | ||
| 1155 | * policy, call driver specific callbacks for disabling Host | ||
| 1156 | * Initiated Power management. | ||
| 1157 | * | ||
| 1158 | * Locking: Caller. | ||
| 1159 | * Returns: void | ||
| 1160 | */ | ||
| 1161 | static void ata_dev_disable_pm(struct ata_device *dev) | ||
| 1162 | { | ||
| 1163 | struct ata_port *ap = dev->link->ap; | ||
| 1164 | |||
| 1165 | ata_dev_set_dipm(dev, ATA_LPM_MAX_POWER); | ||
| 1166 | if (ap->ops->disable_pm) | ||
| 1167 | ap->ops->disable_pm(ap); | ||
| 1168 | } | ||
| 1169 | #endif /* CONFIG_PM */ | ||
| 1170 | |||
| 1171 | void ata_lpm_schedule(struct ata_port *ap, enum ata_lpm_policy policy) | ||
| 1172 | { | ||
| 1173 | ap->lpm_policy = policy; | ||
| 1174 | ap->link.eh_info.action |= ATA_EH_LPM; | ||
| 1175 | ap->link.eh_info.flags |= ATA_EHI_NO_AUTOPSY; | ||
| 1176 | ata_port_schedule_eh(ap); | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | #ifdef CONFIG_PM | ||
| 1180 | static void ata_lpm_enable(struct ata_host *host) | ||
| 1181 | { | ||
| 1182 | struct ata_link *link; | ||
| 1183 | struct ata_port *ap; | ||
| 1184 | struct ata_device *dev; | ||
| 1185 | int i; | ||
| 1186 | |||
| 1187 | for (i = 0; i < host->n_ports; i++) { | ||
| 1188 | ap = host->ports[i]; | ||
| 1189 | ata_for_each_link(link, ap, EDGE) { | ||
| 1190 | ata_for_each_dev(dev, link, ALL) | ||
| 1191 | ata_dev_disable_pm(dev); | ||
| 1192 | } | ||
| 1193 | } | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | static void ata_lpm_disable(struct ata_host *host) | ||
| 1197 | { | ||
| 1198 | int i; | ||
| 1199 | |||
| 1200 | for (i = 0; i < host->n_ports; i++) { | ||
| 1201 | struct ata_port *ap = host->ports[i]; | ||
| 1202 | ata_lpm_schedule(ap, ap->lpm_policy); | ||
| 1203 | } | ||
| 1204 | } | ||
| 1205 | #endif /* CONFIG_PM */ | ||
| 1206 | |||
| 1207 | /** | 1031 | /** |
| 1208 | * ata_dev_classify - determine device type based on ATA-spec signature | 1032 | * ata_dev_classify - determine device type based on ATA-spec signature |
| 1209 | * @tf: ATA taskfile register set for device to be identified | 1033 | * @tf: ATA taskfile register set for device to be identified |
| @@ -2562,13 +2386,6 @@ int ata_dev_configure(struct ata_device *dev) | |||
| 2562 | if (dev->flags & ATA_DFLAG_LBA48) | 2386 | if (dev->flags & ATA_DFLAG_LBA48) |
| 2563 | dev->max_sectors = ATA_MAX_SECTORS_LBA48; | 2387 | dev->max_sectors = ATA_MAX_SECTORS_LBA48; |
| 2564 | 2388 | ||
| 2565 | if (!(dev->horkage & ATA_HORKAGE_LPM)) { | ||
| 2566 | if (ata_id_has_hipm(dev->id)) | ||
| 2567 | dev->flags |= ATA_DFLAG_HIPM; | ||
| 2568 | if (ata_id_has_dipm(dev->id)) | ||
| 2569 | dev->flags |= ATA_DFLAG_DIPM; | ||
| 2570 | } | ||
| 2571 | |||
| 2572 | /* Limit PATA drive on SATA cable bridge transfers to udma5, | 2389 | /* Limit PATA drive on SATA cable bridge transfers to udma5, |
| 2573 | 200 sectors */ | 2390 | 200 sectors */ |
| 2574 | if (ata_dev_knobble(dev)) { | 2391 | if (ata_dev_knobble(dev)) { |
| @@ -2589,13 +2406,6 @@ int ata_dev_configure(struct ata_device *dev) | |||
| 2589 | dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, | 2406 | dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, |
| 2590 | dev->max_sectors); | 2407 | dev->max_sectors); |
| 2591 | 2408 | ||
| 2592 | if (ata_dev_blacklisted(dev) & ATA_HORKAGE_LPM) { | ||
| 2593 | dev->horkage |= ATA_HORKAGE_LPM; | ||
| 2594 | |||
| 2595 | /* reset link pm_policy for this port to no pm */ | ||
| 2596 | ap->lpm_policy = ATA_LPM_MAX_POWER; | ||
| 2597 | } | ||
| 2598 | |||
| 2599 | if (ap->ops->dev_config) | 2409 | if (ap->ops->dev_config) |
| 2600 | ap->ops->dev_config(dev); | 2410 | ap->ops->dev_config(dev); |
| 2601 | 2411 | ||
| @@ -5495,12 +5305,6 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg) | |||
| 5495 | int rc; | 5305 | int rc; |
| 5496 | 5306 | ||
| 5497 | /* | 5307 | /* |
| 5498 | * disable link pm on all ports before requesting | ||
| 5499 | * any pm activity | ||
| 5500 | */ | ||
| 5501 | ata_lpm_enable(host); | ||
| 5502 | |||
| 5503 | /* | ||
| 5504 | * On some hardware, device fails to respond after spun down | 5308 | * On some hardware, device fails to respond after spun down |
| 5505 | * for suspend. As the device won't be used before being | 5309 | * for suspend. As the device won't be used before being |
| 5506 | * resumed, we don't need to touch the device. Ask EH to skip | 5310 | * resumed, we don't need to touch the device. Ask EH to skip |
| @@ -5533,9 +5337,6 @@ void ata_host_resume(struct ata_host *host) | |||
| 5533 | ata_host_request_pm(host, PMSG_ON, ATA_EH_RESET, | 5337 | ata_host_request_pm(host, PMSG_ON, ATA_EH_RESET, |
| 5534 | ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0); | 5338 | ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0); |
| 5535 | host->dev->power.power_state = PMSG_ON; | 5339 | host->dev->power.power_state = PMSG_ON; |
| 5536 | |||
| 5537 | /* reenable link pm */ | ||
| 5538 | ata_lpm_disable(host); | ||
| 5539 | } | 5340 | } |
| 5540 | #endif | 5341 | #endif |
| 5541 | 5342 | ||
| @@ -6096,7 +5897,7 @@ static void async_port_probe(void *data, async_cookie_t cookie) | |||
| 6096 | spin_lock_irqsave(ap->lock, flags); | 5897 | spin_lock_irqsave(ap->lock, flags); |
| 6097 | 5898 | ||
| 6098 | ehi->probe_mask |= ATA_ALL_DEVICES; | 5899 | ehi->probe_mask |= ATA_ALL_DEVICES; |
| 6099 | ehi->action |= ATA_EH_RESET | ATA_EH_LPM; | 5900 | ehi->action |= ATA_EH_RESET; |
| 6100 | ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; | 5901 | ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; |
| 6101 | 5902 | ||
| 6102 | ap->pflags &= ~ATA_PFLAG_INITIALIZING; | 5903 | ap->pflags &= ~ATA_PFLAG_INITIALIZING; |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 96aa75ddf87f..a645cd3ab163 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
| @@ -1580,9 +1580,9 @@ static void ata_eh_analyze_serror(struct ata_link *link) | |||
| 1580 | * host links. For disabled PMP links, only N bit is | 1580 | * host links. For disabled PMP links, only N bit is |
| 1581 | * considered as X bit is left at 1 for link plugging. | 1581 | * considered as X bit is left at 1 for link plugging. |
| 1582 | */ | 1582 | */ |
| 1583 | hotplug_mask = 0; | 1583 | if (link->lpm_policy != ATA_LPM_MAX_POWER) |
| 1584 | 1584 | hotplug_mask = 0; /* hotplug doesn't work w/ LPM */ | |
| 1585 | if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link)) | 1585 | else if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link)) |
| 1586 | hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG; | 1586 | hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG; |
| 1587 | else | 1587 | else |
| 1588 | hotplug_mask = SERR_PHYRDY_CHG; | 1588 | hotplug_mask = SERR_PHYRDY_CHG; |
| @@ -2784,8 +2784,9 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2784 | ata_eh_done(link, NULL, ATA_EH_RESET); | 2784 | ata_eh_done(link, NULL, ATA_EH_RESET); |
| 2785 | if (slave) | 2785 | if (slave) |
| 2786 | ata_eh_done(slave, NULL, ATA_EH_RESET); | 2786 | ata_eh_done(slave, NULL, ATA_EH_RESET); |
| 2787 | ehc->last_reset = jiffies; /* update to completion time */ | 2787 | ehc->last_reset = jiffies; /* update to completion time */ |
| 2788 | ehc->i.action |= ATA_EH_REVALIDATE; | 2788 | ehc->i.action |= ATA_EH_REVALIDATE; |
| 2789 | link->lpm_policy = ATA_LPM_UNKNOWN; /* reset LPM state */ | ||
| 2789 | 2790 | ||
| 2790 | rc = 0; | 2791 | rc = 0; |
| 2791 | out: | 2792 | out: |
| @@ -3211,6 +3212,121 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev) | |||
| 3211 | return rc; | 3212 | return rc; |
| 3212 | } | 3213 | } |
| 3213 | 3214 | ||
| 3215 | /** | ||
| 3216 | * ata_eh_set_lpm - configure SATA interface power management | ||
| 3217 | * @link: link to configure power management | ||
| 3218 | * @policy: the link power management policy | ||
| 3219 | * @r_failed_dev: out parameter for failed device | ||
| 3220 | * | ||
| 3221 | * Enable SATA Interface power management. This will enable | ||
| 3222 | * Device Interface Power Management (DIPM) for min_power | ||
| 3223 | * policy, and then call driver specific callbacks for | ||
| 3224 | * enabling Host Initiated Power management. | ||
| 3225 | * | ||
| 3226 | * LOCKING: | ||
| 3227 | * EH context. | ||
| 3228 | * | ||
| 3229 | * RETURNS: | ||
| 3230 | * 0 on success, -errno on failure. | ||
| 3231 | */ | ||
| 3232 | static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, | ||
| 3233 | struct ata_device **r_failed_dev) | ||
| 3234 | { | ||
| 3235 | struct ata_port *ap = link->ap; | ||
| 3236 | struct ata_eh_context *ehc = &link->eh_context; | ||
| 3237 | struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL; | ||
| 3238 | unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM; | ||
| 3239 | unsigned int err_mask; | ||
| 3240 | int rc; | ||
| 3241 | |||
| 3242 | /* if the link or host doesn't do LPM, noop */ | ||
| 3243 | if ((link->flags & ATA_LFLAG_NO_LPM) || (ap && !ap->ops->set_lpm)) | ||
| 3244 | return 0; | ||
| 3245 | |||
| 3246 | /* | ||
| 3247 | * DIPM is enabled only for MIN_POWER as some devices | ||
| 3248 | * misbehave when the host NACKs transition to SLUMBER. Order | ||
| 3249 | * device and link configurations such that the host always | ||
| 3250 | * allows DIPM requests. | ||
| 3251 | */ | ||
| 3252 | ata_for_each_dev(dev, link, ENABLED) { | ||
| 3253 | bool hipm = ata_id_has_hipm(dev->id); | ||
| 3254 | bool dipm = ata_id_has_dipm(dev->id); | ||
| 3255 | |||
| 3256 | /* find the first enabled and LPM enabled devices */ | ||
| 3257 | if (!link_dev) | ||
| 3258 | link_dev = dev; | ||
| 3259 | |||
| 3260 | if (!lpm_dev && (hipm || dipm)) | ||
| 3261 | lpm_dev = dev; | ||
| 3262 | |||
| 3263 | hints &= ~ATA_LPM_EMPTY; | ||
| 3264 | if (!hipm) | ||
| 3265 | hints &= ~ATA_LPM_HIPM; | ||
| 3266 | |||
| 3267 | /* disable DIPM before changing link config */ | ||
| 3268 | if (policy != ATA_LPM_MIN_POWER && dipm) { | ||
| 3269 | err_mask = ata_dev_set_feature(dev, | ||
| 3270 | SETFEATURES_SATA_DISABLE, SATA_DIPM); | ||
| 3271 | if (err_mask && err_mask != AC_ERR_DEV) { | ||
| 3272 | ata_dev_printk(dev, KERN_WARNING, | ||
| 3273 | "failed to disable DIPM, Emask 0x%x\n", | ||
| 3274 | err_mask); | ||
| 3275 | rc = -EIO; | ||
| 3276 | goto fail; | ||
| 3277 | } | ||
| 3278 | } | ||
| 3279 | } | ||
| 3280 | |||
| 3281 | rc = ap->ops->set_lpm(link, policy, hints); | ||
| 3282 | if (!rc && ap->slave_link) | ||
| 3283 | rc = ap->ops->set_lpm(ap->slave_link, policy, hints); | ||
| 3284 | |||
| 3285 | /* | ||
| 3286 | * Attribute link config failure to the first (LPM) enabled | ||
| 3287 | * device on the link. | ||
| 3288 | */ | ||
| 3289 | if (rc) { | ||
| 3290 | if (rc == -EOPNOTSUPP) { | ||
| 3291 | link->flags |= ATA_LFLAG_NO_LPM; | ||
| 3292 | return 0; | ||
| 3293 | } | ||
| 3294 | dev = lpm_dev ? lpm_dev : link_dev; | ||
| 3295 | goto fail; | ||
| 3296 | } | ||
| 3297 | |||
| 3298 | /* host config updated, enable DIPM if transitioning to MIN_POWER */ | ||
| 3299 | ata_for_each_dev(dev, link, ENABLED) { | ||
| 3300 | if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) { | ||
| 3301 | err_mask = ata_dev_set_feature(dev, | ||
| 3302 | SETFEATURES_SATA_ENABLE, SATA_DIPM); | ||
| 3303 | if (err_mask && err_mask != AC_ERR_DEV) { | ||
| 3304 | ata_dev_printk(dev, KERN_WARNING, | ||
| 3305 | "failed to enable DIPM, Emask 0x%x\n", | ||
| 3306 | err_mask); | ||
| 3307 | rc = -EIO; | ||
| 3308 | goto fail; | ||
| 3309 | } | ||
| 3310 | } | ||
| 3311 | } | ||
| 3312 | |||
| 3313 | link->lpm_policy = policy; | ||
| 3314 | if (ap && ap->slave_link) | ||
| 3315 | ap->slave_link->lpm_policy = policy; | ||
| 3316 | return 0; | ||
| 3317 | |||
| 3318 | fail: | ||
| 3319 | /* if no device or only one more chance is left, disable LPM */ | ||
| 3320 | if (!dev || ehc->tries[dev->devno] <= 2) { | ||
| 3321 | ata_link_printk(link, KERN_WARNING, | ||
| 3322 | "disabling LPM on the link\n"); | ||
| 3323 | link->flags |= ATA_LFLAG_NO_LPM; | ||
| 3324 | } | ||
| 3325 | if (r_failed_dev) | ||
| 3326 | *r_failed_dev = dev; | ||
| 3327 | return rc; | ||
| 3328 | } | ||
| 3329 | |||
| 3214 | static int ata_link_nr_enabled(struct ata_link *link) | 3330 | static int ata_link_nr_enabled(struct ata_link *link) |
| 3215 | { | 3331 | { |
| 3216 | struct ata_device *dev; | 3332 | struct ata_device *dev; |
| @@ -3295,6 +3411,10 @@ static int ata_eh_schedule_probe(struct ata_device *dev) | |||
| 3295 | ehc->saved_xfer_mode[dev->devno] = 0; | 3411 | ehc->saved_xfer_mode[dev->devno] = 0; |
| 3296 | ehc->saved_ncq_enabled &= ~(1 << dev->devno); | 3412 | ehc->saved_ncq_enabled &= ~(1 << dev->devno); |
| 3297 | 3413 | ||
| 3414 | /* the link maybe in a deep sleep, wake it up */ | ||
| 3415 | if (link->lpm_policy > ATA_LPM_MAX_POWER) | ||
| 3416 | link->ap->ops->set_lpm(link, ATA_LPM_MAX_POWER, ATA_LPM_EMPTY); | ||
| 3417 | |||
| 3298 | /* Record and count probe trials on the ering. The specific | 3418 | /* Record and count probe trials on the ering. The specific |
| 3299 | * error mask used is irrelevant. Because a successful device | 3419 | * error mask used is irrelevant. Because a successful device |
| 3300 | * detection clears the ering, this count accumulates only if | 3420 | * detection clears the ering, this count accumulates only if |
| @@ -3396,8 +3516,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
| 3396 | { | 3516 | { |
| 3397 | struct ata_link *link; | 3517 | struct ata_link *link; |
| 3398 | struct ata_device *dev; | 3518 | struct ata_device *dev; |
| 3399 | int nr_failed_devs; | 3519 | int rc, nr_fails; |
| 3400 | int rc; | ||
| 3401 | unsigned long flags, deadline; | 3520 | unsigned long flags, deadline; |
| 3402 | 3521 | ||
| 3403 | DPRINTK("ENTER\n"); | 3522 | DPRINTK("ENTER\n"); |
| @@ -3438,7 +3557,6 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
| 3438 | 3557 | ||
| 3439 | retry: | 3558 | retry: |
| 3440 | rc = 0; | 3559 | rc = 0; |
| 3441 | nr_failed_devs = 0; | ||
| 3442 | 3560 | ||
| 3443 | /* if UNLOADING, finish immediately */ | 3561 | /* if UNLOADING, finish immediately */ |
| 3444 | if (ap->pflags & ATA_PFLAG_UNLOADING) | 3562 | if (ap->pflags & ATA_PFLAG_UNLOADING) |
| @@ -3523,13 +3641,17 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
| 3523 | } | 3641 | } |
| 3524 | 3642 | ||
| 3525 | /* the rest */ | 3643 | /* the rest */ |
| 3526 | ata_for_each_link(link, ap, EDGE) { | 3644 | nr_fails = 0; |
| 3645 | ata_for_each_link(link, ap, PMP_FIRST) { | ||
| 3527 | struct ata_eh_context *ehc = &link->eh_context; | 3646 | struct ata_eh_context *ehc = &link->eh_context; |
| 3528 | 3647 | ||
| 3648 | if (sata_pmp_attached(ap) && ata_is_host_link(link)) | ||
| 3649 | goto config_lpm; | ||
| 3650 | |||
| 3529 | /* revalidate existing devices and attach new ones */ | 3651 | /* revalidate existing devices and attach new ones */ |
| 3530 | rc = ata_eh_revalidate_and_attach(link, &dev); | 3652 | rc = ata_eh_revalidate_and_attach(link, &dev); |
| 3531 | if (rc) | 3653 | if (rc) |
| 3532 | goto dev_fail; | 3654 | goto rest_fail; |
| 3533 | 3655 | ||
| 3534 | /* if PMP got attached, return, pmp EH will take care of it */ | 3656 | /* if PMP got attached, return, pmp EH will take care of it */ |
| 3535 | if (link->device->class == ATA_DEV_PMP) { | 3657 | if (link->device->class == ATA_DEV_PMP) { |
| @@ -3541,7 +3663,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
| 3541 | if (ehc->i.flags & ATA_EHI_SETMODE) { | 3663 | if (ehc->i.flags & ATA_EHI_SETMODE) { |
| 3542 | rc = ata_set_mode(link, &dev); | 3664 | rc = ata_set_mode(link, &dev); |
| 3543 | if (rc) | 3665 | if (rc) |
| 3544 | goto dev_fail; | 3666 | goto rest_fail; |
| 3545 | ehc->i.flags &= ~ATA_EHI_SETMODE; | 3667 | ehc->i.flags &= ~ATA_EHI_SETMODE; |
| 3546 | } | 3668 | } |
| 3547 | 3669 | ||
| @@ -3554,7 +3676,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
| 3554 | continue; | 3676 | continue; |
| 3555 | rc = atapi_eh_clear_ua(dev); | 3677 | rc = atapi_eh_clear_ua(dev); |
| 3556 | if (rc) | 3678 | if (rc) |
| 3557 | goto dev_fail; | 3679 | goto rest_fail; |
| 3558 | } | 3680 | } |
| 3559 | } | 3681 | } |
| 3560 | 3682 | ||
| @@ -3564,21 +3686,25 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
| 3564 | continue; | 3686 | continue; |
| 3565 | rc = ata_eh_maybe_retry_flush(dev); | 3687 | rc = ata_eh_maybe_retry_flush(dev); |
| 3566 | if (rc) | 3688 | if (rc) |
| 3567 | goto dev_fail; | 3689 | goto rest_fail; |
| 3568 | } | 3690 | } |
| 3569 | 3691 | ||
| 3692 | config_lpm: | ||
| 3570 | /* configure link power saving */ | 3693 | /* configure link power saving */ |
| 3571 | if (ehc->i.action & ATA_EH_LPM) | 3694 | if (link->lpm_policy != ap->target_lpm_policy) { |
| 3572 | ata_for_each_dev(dev, link, ALL) | 3695 | rc = ata_eh_set_lpm(link, ap->target_lpm_policy, &dev); |
| 3573 | ata_dev_enable_pm(dev, ap->lpm_policy); | 3696 | if (rc) |
| 3697 | goto rest_fail; | ||
| 3698 | } | ||
| 3574 | 3699 | ||
| 3575 | /* this link is okay now */ | 3700 | /* this link is okay now */ |
| 3576 | ehc->i.flags = 0; | 3701 | ehc->i.flags = 0; |
| 3577 | continue; | 3702 | continue; |
| 3578 | 3703 | ||
| 3579 | dev_fail: | 3704 | rest_fail: |
| 3580 | nr_failed_devs++; | 3705 | nr_fails++; |
| 3581 | ata_eh_handle_dev_fail(dev, rc); | 3706 | if (dev) |
| 3707 | ata_eh_handle_dev_fail(dev, rc); | ||
| 3582 | 3708 | ||
| 3583 | if (ap->pflags & ATA_PFLAG_FROZEN) { | 3709 | if (ap->pflags & ATA_PFLAG_FROZEN) { |
| 3584 | /* PMP reset requires working host port. | 3710 | /* PMP reset requires working host port. |
| @@ -3590,7 +3716,7 @@ dev_fail: | |||
| 3590 | } | 3716 | } |
| 3591 | } | 3717 | } |
| 3592 | 3718 | ||
| 3593 | if (nr_failed_devs) | 3719 | if (nr_fails) |
| 3594 | goto retry; | 3720 | goto retry; |
| 3595 | 3721 | ||
| 3596 | out: | 3722 | out: |
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index aa56681f68db..56f6224fd6e6 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
| @@ -117,6 +117,7 @@ static ssize_t ata_scsi_lpm_store(struct device *dev, | |||
| 117 | struct Scsi_Host *shost = class_to_shost(dev); | 117 | struct Scsi_Host *shost = class_to_shost(dev); |
| 118 | struct ata_port *ap = ata_shost_to_port(shost); | 118 | struct ata_port *ap = ata_shost_to_port(shost); |
| 119 | enum ata_lpm_policy policy; | 119 | enum ata_lpm_policy policy; |
| 120 | unsigned long flags; | ||
| 120 | 121 | ||
| 121 | /* UNKNOWN is internal state, iterate from MAX_POWER */ | 122 | /* UNKNOWN is internal state, iterate from MAX_POWER */ |
| 122 | for (policy = ATA_LPM_MAX_POWER; | 123 | for (policy = ATA_LPM_MAX_POWER; |
| @@ -129,7 +130,11 @@ static ssize_t ata_scsi_lpm_store(struct device *dev, | |||
| 129 | if (policy == ARRAY_SIZE(ata_lpm_policy_names)) | 130 | if (policy == ARRAY_SIZE(ata_lpm_policy_names)) |
| 130 | return -EINVAL; | 131 | return -EINVAL; |
| 131 | 132 | ||
| 132 | ata_lpm_schedule(ap, policy); | 133 | spin_lock_irqsave(ap->lock, flags); |
| 134 | ap->target_lpm_policy = policy; | ||
| 135 | ata_port_schedule_eh(ap); | ||
| 136 | spin_unlock_irqrestore(ap->lock, flags); | ||
| 137 | |||
| 133 | return count; | 138 | return count; |
| 134 | } | 139 | } |
| 135 | 140 | ||
| @@ -139,11 +144,11 @@ static ssize_t ata_scsi_lpm_show(struct device *dev, | |||
| 139 | struct Scsi_Host *shost = class_to_shost(dev); | 144 | struct Scsi_Host *shost = class_to_shost(dev); |
| 140 | struct ata_port *ap = ata_shost_to_port(shost); | 145 | struct ata_port *ap = ata_shost_to_port(shost); |
| 141 | 146 | ||
| 142 | if (ap->lpm_policy >= ARRAY_SIZE(ata_lpm_policy_names)) | 147 | if (ap->target_lpm_policy >= ARRAY_SIZE(ata_lpm_policy_names)) |
| 143 | return -EINVAL; | 148 | return -EINVAL; |
| 144 | 149 | ||
| 145 | return snprintf(buf, PAGE_SIZE, "%s\n", | 150 | return snprintf(buf, PAGE_SIZE, "%s\n", |
| 146 | ata_lpm_policy_names[ap->lpm_policy]); | 151 | ata_lpm_policy_names[ap->target_lpm_policy]); |
| 147 | } | 152 | } |
| 148 | DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR, | 153 | DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR, |
| 149 | ata_scsi_lpm_show, ata_scsi_lpm_store); | 154 | ata_scsi_lpm_show, ata_scsi_lpm_store); |
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 65b6a73c3ac7..55a6f413a550 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h | |||
| @@ -102,10 +102,6 @@ extern int sata_link_init_spd(struct ata_link *link); | |||
| 102 | extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); | 102 | extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); |
| 103 | extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); | 103 | extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); |
| 104 | extern struct ata_port *ata_port_alloc(struct ata_host *host); | 104 | extern struct ata_port *ata_port_alloc(struct ata_host *host); |
| 105 | extern void ata_dev_enable_pm(struct ata_device *dev, | ||
| 106 | enum ata_lpm_policy policy); | ||
| 107 | extern void ata_lpm_schedule(struct ata_port *ap, | ||
| 108 | enum ata_lpm_policy policy); | ||
| 109 | extern const char *sata_spd_string(unsigned int spd); | 105 | extern const char *sata_spd_string(unsigned int spd); |
| 110 | 106 | ||
| 111 | /* libata-acpi.c */ | 107 | /* libata-acpi.c */ |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 7770eeb21039..bc4ee218b185 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -172,6 +172,7 @@ enum { | |||
| 172 | ATA_LFLAG_NO_RETRY = (1 << 5), /* don't retry this link */ | 172 | ATA_LFLAG_NO_RETRY = (1 << 5), /* don't retry this link */ |
| 173 | ATA_LFLAG_DISABLED = (1 << 6), /* link is disabled */ | 173 | ATA_LFLAG_DISABLED = (1 << 6), /* link is disabled */ |
| 174 | ATA_LFLAG_SW_ACTIVITY = (1 << 7), /* keep activity stats */ | 174 | ATA_LFLAG_SW_ACTIVITY = (1 << 7), /* keep activity stats */ |
| 175 | ATA_LFLAG_NO_LPM = (1 << 8), /* disable LPM on this link */ | ||
| 175 | 176 | ||
| 176 | /* struct ata_port flags */ | 177 | /* struct ata_port flags */ |
| 177 | ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ | 178 | ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ |
| @@ -324,12 +325,11 @@ enum { | |||
| 324 | ATA_EH_HARDRESET = (1 << 2), /* meaningful only in ->prereset */ | 325 | ATA_EH_HARDRESET = (1 << 2), /* meaningful only in ->prereset */ |
| 325 | ATA_EH_RESET = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, | 326 | ATA_EH_RESET = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, |
| 326 | ATA_EH_ENABLE_LINK = (1 << 3), | 327 | ATA_EH_ENABLE_LINK = (1 << 3), |
| 327 | ATA_EH_LPM = (1 << 4), /* link power management action */ | ||
| 328 | ATA_EH_PARK = (1 << 5), /* unload heads and stop I/O */ | 328 | ATA_EH_PARK = (1 << 5), /* unload heads and stop I/O */ |
| 329 | 329 | ||
| 330 | ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK, | 330 | ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK, |
| 331 | ATA_EH_ALL_ACTIONS = ATA_EH_REVALIDATE | ATA_EH_RESET | | 331 | ATA_EH_ALL_ACTIONS = ATA_EH_REVALIDATE | ATA_EH_RESET | |
| 332 | ATA_EH_ENABLE_LINK | ATA_EH_LPM, | 332 | ATA_EH_ENABLE_LINK, |
| 333 | 333 | ||
| 334 | /* ata_eh_info->flags */ | 334 | /* ata_eh_info->flags */ |
| 335 | ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ | 335 | ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ |
| @@ -377,7 +377,6 @@ enum { | |||
| 377 | ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */ | 377 | ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */ |
| 378 | ATA_HORKAGE_DISABLE = (1 << 5), /* Disable it */ | 378 | ATA_HORKAGE_DISABLE = (1 << 5), /* Disable it */ |
| 379 | ATA_HORKAGE_HPA_SIZE = (1 << 6), /* native size off by one */ | 379 | ATA_HORKAGE_HPA_SIZE = (1 << 6), /* native size off by one */ |
| 380 | ATA_HORKAGE_LPM = (1 << 7), /* Link PM problems */ | ||
| 381 | ATA_HORKAGE_IVB = (1 << 8), /* cbl det validity bit bugs */ | 380 | ATA_HORKAGE_IVB = (1 << 8), /* cbl det validity bit bugs */ |
| 382 | ATA_HORKAGE_STUCK_ERR = (1 << 9), /* stuck ERR on next PACKET */ | 381 | ATA_HORKAGE_STUCK_ERR = (1 << 9), /* stuck ERR on next PACKET */ |
| 383 | ATA_HORKAGE_BRIDGE_OK = (1 << 10), /* no bridge limits */ | 382 | ATA_HORKAGE_BRIDGE_OK = (1 << 10), /* no bridge limits */ |
| @@ -475,6 +474,11 @@ enum ata_lpm_policy { | |||
| 475 | ATA_LPM_MIN_POWER, | 474 | ATA_LPM_MIN_POWER, |
| 476 | }; | 475 | }; |
| 477 | 476 | ||
| 477 | enum ata_lpm_hints { | ||
| 478 | ATA_LPM_EMPTY = (1 << 0), /* port empty/probing */ | ||
| 479 | ATA_LPM_HIPM = (1 << 1), /* may use HIPM */ | ||
| 480 | }; | ||
| 481 | |||
| 478 | /* forward declarations */ | 482 | /* forward declarations */ |
| 479 | struct scsi_device; | 483 | struct scsi_device; |
| 480 | struct ata_port_operations; | 484 | struct ata_port_operations; |
| @@ -702,6 +706,7 @@ struct ata_link { | |||
| 702 | unsigned int hw_sata_spd_limit; | 706 | unsigned int hw_sata_spd_limit; |
| 703 | unsigned int sata_spd_limit; | 707 | unsigned int sata_spd_limit; |
| 704 | unsigned int sata_spd; /* current SATA PHY speed */ | 708 | unsigned int sata_spd; /* current SATA PHY speed */ |
| 709 | enum ata_lpm_policy lpm_policy; | ||
| 705 | 710 | ||
| 706 | /* record runtime error info, protected by host_set lock */ | 711 | /* record runtime error info, protected by host_set lock */ |
| 707 | struct ata_eh_info eh_info; | 712 | struct ata_eh_info eh_info; |
| @@ -773,7 +778,7 @@ struct ata_port { | |||
| 773 | 778 | ||
| 774 | pm_message_t pm_mesg; | 779 | pm_message_t pm_mesg; |
| 775 | int *pm_result; | 780 | int *pm_result; |
| 776 | enum ata_lpm_policy lpm_policy; | 781 | enum ata_lpm_policy target_lpm_policy; |
| 777 | 782 | ||
| 778 | struct timer_list fastdrain_timer; | 783 | struct timer_list fastdrain_timer; |
| 779 | unsigned long fastdrain_cnt; | 784 | unsigned long fastdrain_cnt; |
| @@ -839,8 +844,8 @@ struct ata_port_operations { | |||
| 839 | int (*scr_write)(struct ata_link *link, unsigned int sc_reg, u32 val); | 844 | int (*scr_write)(struct ata_link *link, unsigned int sc_reg, u32 val); |
| 840 | void (*pmp_attach)(struct ata_port *ap); | 845 | void (*pmp_attach)(struct ata_port *ap); |
| 841 | void (*pmp_detach)(struct ata_port *ap); | 846 | void (*pmp_detach)(struct ata_port *ap); |
| 842 | int (*enable_pm)(struct ata_port *ap, enum ata_lpm_policy policy); | 847 | int (*set_lpm)(struct ata_link *link, enum ata_lpm_policy policy, |
| 843 | void (*disable_pm)(struct ata_port *ap); | 848 | unsigned hints); |
| 844 | 849 | ||
| 845 | /* | 850 | /* |
| 846 | * Start, stop, suspend and resume | 851 | * Start, stop, suspend and resume |
