diff options
Diffstat (limited to 'drivers/ata/libata-eh.c')
| -rw-r--r-- | drivers/ata/libata-eh.c | 207 |
1 files changed, 113 insertions, 94 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 62e033146bed..7894d83ea1eb 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
| @@ -1308,12 +1308,7 @@ static void ata_eh_analyze_serror(struct ata_link *link) | |||
| 1308 | unsigned int err_mask = 0, action = 0; | 1308 | unsigned int err_mask = 0, action = 0; |
| 1309 | u32 hotplug_mask; | 1309 | u32 hotplug_mask; |
| 1310 | 1310 | ||
| 1311 | if (serror & SERR_PERSISTENT) { | 1311 | if (serror & (SERR_PERSISTENT | SERR_DATA)) { |
| 1312 | err_mask |= AC_ERR_ATA_BUS; | ||
| 1313 | action |= ATA_EH_RESET; | ||
| 1314 | } | ||
| 1315 | if (serror & | ||
| 1316 | (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) { | ||
| 1317 | err_mask |= AC_ERR_ATA_BUS; | 1312 | err_mask |= AC_ERR_ATA_BUS; |
| 1318 | action |= ATA_EH_RESET; | 1313 | action |= ATA_EH_RESET; |
| 1319 | } | 1314 | } |
| @@ -2047,19 +2042,11 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset, | |||
| 2047 | unsigned int *classes, unsigned long deadline) | 2042 | unsigned int *classes, unsigned long deadline) |
| 2048 | { | 2043 | { |
| 2049 | struct ata_device *dev; | 2044 | struct ata_device *dev; |
| 2050 | int rc; | ||
| 2051 | 2045 | ||
| 2052 | ata_link_for_each_dev(dev, link) | 2046 | ata_link_for_each_dev(dev, link) |
| 2053 | classes[dev->devno] = ATA_DEV_UNKNOWN; | 2047 | classes[dev->devno] = ATA_DEV_UNKNOWN; |
| 2054 | 2048 | ||
| 2055 | rc = reset(link, classes, deadline); | 2049 | return reset(link, classes, deadline); |
| 2056 | |||
| 2057 | /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */ | ||
| 2058 | ata_link_for_each_dev(dev, link) | ||
| 2059 | if (classes[dev->devno] == ATA_DEV_UNKNOWN) | ||
| 2060 | classes[dev->devno] = ATA_DEV_NONE; | ||
| 2061 | |||
| 2062 | return rc; | ||
| 2063 | } | 2050 | } |
| 2064 | 2051 | ||
| 2065 | static int ata_eh_followup_srst_needed(struct ata_link *link, | 2052 | static int ata_eh_followup_srst_needed(struct ata_link *link, |
| @@ -2096,9 +2083,11 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2096 | ata_reset_fn_t reset; | 2083 | ata_reset_fn_t reset; |
| 2097 | unsigned long flags; | 2084 | unsigned long flags; |
| 2098 | u32 sstatus; | 2085 | u32 sstatus; |
| 2099 | int rc; | 2086 | int nr_known, rc; |
| 2100 | 2087 | ||
| 2101 | /* about to reset */ | 2088 | /* |
| 2089 | * Prepare to reset | ||
| 2090 | */ | ||
| 2102 | spin_lock_irqsave(ap->lock, flags); | 2091 | spin_lock_irqsave(ap->lock, flags); |
| 2103 | ap->pflags |= ATA_PFLAG_RESETTING; | 2092 | ap->pflags |= ATA_PFLAG_RESETTING; |
| 2104 | spin_unlock_irqrestore(ap->lock, flags); | 2093 | spin_unlock_irqrestore(ap->lock, flags); |
| @@ -2124,16 +2113,8 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2124 | ap->ops->set_piomode(ap, dev); | 2113 | ap->ops->set_piomode(ap, dev); |
| 2125 | } | 2114 | } |
| 2126 | 2115 | ||
| 2127 | if (!softreset && !hardreset) { | ||
| 2128 | if (verbose) | ||
| 2129 | ata_link_printk(link, KERN_INFO, "no reset method " | ||
| 2130 | "available, skipping reset\n"); | ||
| 2131 | if (!(lflags & ATA_LFLAG_ASSUME_CLASS)) | ||
| 2132 | lflags |= ATA_LFLAG_ASSUME_ATA; | ||
| 2133 | goto done; | ||
| 2134 | } | ||
| 2135 | |||
| 2136 | /* prefer hardreset */ | 2116 | /* prefer hardreset */ |
| 2117 | reset = NULL; | ||
| 2137 | ehc->i.action &= ~ATA_EH_RESET; | 2118 | ehc->i.action &= ~ATA_EH_RESET; |
| 2138 | if (hardreset) { | 2119 | if (hardreset) { |
| 2139 | reset = hardreset; | 2120 | reset = hardreset; |
| @@ -2141,11 +2122,6 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2141 | } else if (softreset) { | 2122 | } else if (softreset) { |
| 2142 | reset = softreset; | 2123 | reset = softreset; |
| 2143 | ehc->i.action = ATA_EH_SOFTRESET; | 2124 | ehc->i.action = ATA_EH_SOFTRESET; |
| 2144 | } else { | ||
| 2145 | ata_link_printk(link, KERN_ERR, "BUG: no reset method, " | ||
| 2146 | "please report to linux-ide@vger.kernel.org\n"); | ||
| 2147 | dump_stack(); | ||
| 2148 | return -EINVAL; | ||
| 2149 | } | 2125 | } |
| 2150 | 2126 | ||
| 2151 | if (prereset) { | 2127 | if (prereset) { |
| @@ -2165,55 +2141,71 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2165 | "prereset failed (errno=%d)\n", rc); | 2141 | "prereset failed (errno=%d)\n", rc); |
| 2166 | goto out; | 2142 | goto out; |
| 2167 | } | 2143 | } |
| 2168 | } | ||
| 2169 | 2144 | ||
| 2170 | /* prereset() might have cleared ATA_EH_RESET */ | 2145 | /* prereset() might have cleared ATA_EH_RESET. If so, |
| 2171 | if (!(ehc->i.action & ATA_EH_RESET)) { | 2146 | * bang classes and return. |
| 2172 | /* prereset told us not to reset, bang classes and return */ | 2147 | */ |
| 2173 | ata_link_for_each_dev(dev, link) | 2148 | if (reset && !(ehc->i.action & ATA_EH_RESET)) { |
| 2174 | classes[dev->devno] = ATA_DEV_NONE; | 2149 | ata_link_for_each_dev(dev, link) |
| 2175 | rc = 0; | 2150 | classes[dev->devno] = ATA_DEV_NONE; |
| 2176 | goto out; | 2151 | rc = 0; |
| 2152 | goto out; | ||
| 2153 | } | ||
| 2177 | } | 2154 | } |
| 2178 | 2155 | ||
| 2179 | retry: | 2156 | retry: |
| 2157 | /* | ||
| 2158 | * Perform reset | ||
| 2159 | */ | ||
| 2160 | if (ata_is_host_link(link)) | ||
| 2161 | ata_eh_freeze_port(ap); | ||
| 2162 | |||
| 2180 | deadline = jiffies + ata_eh_reset_timeouts[try++]; | 2163 | deadline = jiffies + ata_eh_reset_timeouts[try++]; |
| 2181 | 2164 | ||
| 2182 | /* shut up during boot probing */ | 2165 | if (reset) { |
| 2183 | if (verbose) | 2166 | if (verbose) |
| 2184 | ata_link_printk(link, KERN_INFO, "%s resetting link\n", | 2167 | ata_link_printk(link, KERN_INFO, "%s resetting link\n", |
| 2185 | reset == softreset ? "soft" : "hard"); | 2168 | reset == softreset ? "soft" : "hard"); |
| 2186 | 2169 | ||
| 2187 | /* mark that this EH session started with reset */ | 2170 | /* mark that this EH session started with reset */ |
| 2188 | if (reset == hardreset) | 2171 | if (reset == hardreset) |
| 2189 | ehc->i.flags |= ATA_EHI_DID_HARDRESET; | 2172 | ehc->i.flags |= ATA_EHI_DID_HARDRESET; |
| 2190 | else | 2173 | else |
| 2191 | ehc->i.flags |= ATA_EHI_DID_SOFTRESET; | 2174 | ehc->i.flags |= ATA_EHI_DID_SOFTRESET; |
| 2192 | 2175 | ||
| 2193 | rc = ata_do_reset(link, reset, classes, deadline); | 2176 | rc = ata_do_reset(link, reset, classes, deadline); |
| 2194 | 2177 | ||
| 2195 | if (reset == hardreset && | 2178 | if (reset == hardreset && |
| 2196 | ata_eh_followup_srst_needed(link, rc, classify, classes)) { | 2179 | ata_eh_followup_srst_needed(link, rc, classify, classes)) { |
| 2197 | /* okay, let's do follow-up softreset */ | 2180 | /* okay, let's do follow-up softreset */ |
| 2198 | reset = softreset; | 2181 | reset = softreset; |
| 2199 | 2182 | ||
| 2200 | if (!reset) { | 2183 | if (!reset) { |
| 2201 | ata_link_printk(link, KERN_ERR, | 2184 | ata_link_printk(link, KERN_ERR, |
| 2202 | "follow-up softreset required " | 2185 | "follow-up softreset required " |
| 2203 | "but no softreset avaliable\n"); | 2186 | "but no softreset avaliable\n"); |
| 2204 | rc = -EINVAL; | 2187 | rc = -EINVAL; |
| 2205 | goto fail; | 2188 | goto fail; |
| 2189 | } | ||
| 2190 | |||
| 2191 | ata_eh_about_to_do(link, NULL, ATA_EH_RESET); | ||
| 2192 | rc = ata_do_reset(link, reset, classes, deadline); | ||
| 2206 | } | 2193 | } |
| 2207 | 2194 | ||
| 2208 | ata_eh_about_to_do(link, NULL, ATA_EH_RESET); | 2195 | /* -EAGAIN can happen if we skipped followup SRST */ |
| 2209 | rc = ata_do_reset(link, reset, classes, deadline); | 2196 | if (rc && rc != -EAGAIN) |
| 2197 | goto fail; | ||
| 2198 | } else { | ||
| 2199 | if (verbose) | ||
| 2200 | ata_link_printk(link, KERN_INFO, "no reset method " | ||
| 2201 | "available, skipping reset\n"); | ||
| 2202 | if (!(lflags & ATA_LFLAG_ASSUME_CLASS)) | ||
| 2203 | lflags |= ATA_LFLAG_ASSUME_ATA; | ||
| 2210 | } | 2204 | } |
| 2211 | 2205 | ||
| 2212 | /* -EAGAIN can happen if we skipped followup SRST */ | 2206 | /* |
| 2213 | if (rc && rc != -EAGAIN) | 2207 | * Post-reset processing |
| 2214 | goto fail; | 2208 | */ |
| 2215 | |||
| 2216 | done: | ||
| 2217 | ata_link_for_each_dev(dev, link) { | 2209 | ata_link_for_each_dev(dev, link) { |
| 2218 | /* After the reset, the device state is PIO 0 and the | 2210 | /* After the reset, the device state is PIO 0 and the |
| 2219 | * controller state is undefined. Reset also wakes up | 2211 | * controller state is undefined. Reset also wakes up |
| @@ -2236,9 +2228,53 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
| 2236 | if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0) | 2228 | if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0) |
| 2237 | link->sata_spd = (sstatus >> 4) & 0xf; | 2229 | link->sata_spd = (sstatus >> 4) & 0xf; |
| 2238 | 2230 | ||
| 2231 | /* thaw the port */ | ||
| 2232 | if (ata_is_host_link(link)) | ||
| 2233 | ata_eh_thaw_port(ap); | ||
| 2234 | |||
| 2235 | /* postreset() should clear hardware SError. Although SError | ||
| 2236 | * is cleared during link resume, clearing SError here is | ||
| 2237 | * necessary as some PHYs raise hotplug events after SRST. | ||
| 2238 | * This introduces race condition where hotplug occurs between | ||
| 2239 | * reset and here. This race is mediated by cross checking | ||
| 2240 | * link onlineness and classification result later. | ||
| 2241 | */ | ||
| 2239 | if (postreset) | 2242 | if (postreset) |
| 2240 | postreset(link, classes); | 2243 | postreset(link, classes); |
| 2241 | 2244 | ||
| 2245 | /* clear cached SError */ | ||
| 2246 | spin_lock_irqsave(link->ap->lock, flags); | ||
| 2247 | link->eh_info.serror = 0; | ||
| 2248 | spin_unlock_irqrestore(link->ap->lock, flags); | ||
| 2249 | |||
| 2250 | /* Make sure onlineness and classification result correspond. | ||
| 2251 | * Hotplug could have happened during reset and some | ||
| 2252 | * controllers fail to wait while a drive is spinning up after | ||
| 2253 | * being hotplugged causing misdetection. By cross checking | ||
| 2254 | * link onlineness and classification result, those conditions | ||
| 2255 | * can be reliably detected and retried. | ||
| 2256 | */ | ||
| 2257 | nr_known = 0; | ||
| 2258 | ata_link_for_each_dev(dev, link) { | ||
| 2259 | /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */ | ||
| 2260 | if (classes[dev->devno] == ATA_DEV_UNKNOWN) | ||
| 2261 | classes[dev->devno] = ATA_DEV_NONE; | ||
| 2262 | else | ||
| 2263 | nr_known++; | ||
| 2264 | } | ||
| 2265 | |||
| 2266 | if (classify && !nr_known && ata_link_online(link)) { | ||
| 2267 | if (try < max_tries) { | ||
| 2268 | ata_link_printk(link, KERN_WARNING, "link online but " | ||
| 2269 | "device misclassified, retrying\n"); | ||
| 2270 | rc = -EAGAIN; | ||
| 2271 | goto fail; | ||
| 2272 | } | ||
| 2273 | ata_link_printk(link, KERN_WARNING, | ||
| 2274 | "link online but device misclassified, " | ||
| 2275 | "device detection might fail\n"); | ||
| 2276 | } | ||
| 2277 | |||
| 2242 | /* reset successful, schedule revalidation */ | 2278 | /* reset successful, schedule revalidation */ |
| 2243 | ata_eh_done(link, NULL, ATA_EH_RESET); | 2279 | ata_eh_done(link, NULL, ATA_EH_RESET); |
| 2244 | ehc->i.action |= ATA_EH_REVALIDATE; | 2280 | ehc->i.action |= ATA_EH_REVALIDATE; |
| @@ -2587,7 +2623,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
| 2587 | struct ata_link *link; | 2623 | struct ata_link *link; |
| 2588 | struct ata_device *dev; | 2624 | struct ata_device *dev; |
| 2589 | int nr_failed_devs, nr_disabled_devs; | 2625 | int nr_failed_devs, nr_disabled_devs; |
| 2590 | int reset, rc; | 2626 | int rc; |
| 2591 | unsigned long flags; | 2627 | unsigned long flags; |
| 2592 | 2628 | ||
| 2593 | DPRINTK("ENTER\n"); | 2629 | DPRINTK("ENTER\n"); |
| @@ -2630,7 +2666,6 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
| 2630 | rc = 0; | 2666 | rc = 0; |
| 2631 | nr_failed_devs = 0; | 2667 | nr_failed_devs = 0; |
| 2632 | nr_disabled_devs = 0; | 2668 | nr_disabled_devs = 0; |
| 2633 | reset = 0; | ||
| 2634 | 2669 | ||
| 2635 | /* if UNLOADING, finish immediately */ | 2670 | /* if UNLOADING, finish immediately */ |
| 2636 | if (ap->pflags & ATA_PFLAG_UNLOADING) | 2671 | if (ap->pflags & ATA_PFLAG_UNLOADING) |
| @@ -2644,40 +2679,24 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
| 2644 | if (ata_eh_skip_recovery(link)) | 2679 | if (ata_eh_skip_recovery(link)) |
| 2645 | ehc->i.action = 0; | 2680 | ehc->i.action = 0; |
| 2646 | 2681 | ||
| 2647 | /* do we need to reset? */ | ||
| 2648 | if (ehc->i.action & ATA_EH_RESET) | ||
| 2649 | reset = 1; | ||
| 2650 | |||
| 2651 | ata_link_for_each_dev(dev, link) | 2682 | ata_link_for_each_dev(dev, link) |
| 2652 | ehc->classes[dev->devno] = ATA_DEV_UNKNOWN; | 2683 | ehc->classes[dev->devno] = ATA_DEV_UNKNOWN; |
| 2653 | } | 2684 | } |
| 2654 | 2685 | ||
| 2655 | /* reset */ | 2686 | /* reset */ |
| 2656 | if (reset) { | 2687 | ata_port_for_each_link(link, ap) { |
| 2657 | /* if PMP is attached, this function only deals with | 2688 | struct ata_eh_context *ehc = &link->eh_context; |
| 2658 | * downstream links, port should stay thawed. | ||
| 2659 | */ | ||
| 2660 | if (!sata_pmp_attached(ap)) | ||
| 2661 | ata_eh_freeze_port(ap); | ||
| 2662 | |||
| 2663 | ata_port_for_each_link(link, ap) { | ||
| 2664 | struct ata_eh_context *ehc = &link->eh_context; | ||
| 2665 | 2689 | ||
| 2666 | if (!(ehc->i.action & ATA_EH_RESET)) | 2690 | if (!(ehc->i.action & ATA_EH_RESET)) |
| 2667 | continue; | 2691 | continue; |
| 2668 | 2692 | ||
| 2669 | rc = ata_eh_reset(link, ata_link_nr_vacant(link), | 2693 | rc = ata_eh_reset(link, ata_link_nr_vacant(link), |
| 2670 | prereset, softreset, hardreset, | 2694 | prereset, softreset, hardreset, postreset); |
| 2671 | postreset); | 2695 | if (rc) { |
| 2672 | if (rc) { | 2696 | ata_link_printk(link, KERN_ERR, |
| 2673 | ata_link_printk(link, KERN_ERR, | 2697 | "reset failed, giving up\n"); |
| 2674 | "reset failed, giving up\n"); | 2698 | goto out; |
| 2675 | goto out; | ||
| 2676 | } | ||
| 2677 | } | 2699 | } |
| 2678 | |||
| 2679 | if (!sata_pmp_attached(ap)) | ||
| 2680 | ata_eh_thaw_port(ap); | ||
| 2681 | } | 2700 | } |
| 2682 | 2701 | ||
| 2683 | /* the rest */ | 2702 | /* the rest */ |
