diff options
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r-- | drivers/ata/libata-eh.c | 148 |
1 files changed, 81 insertions, 67 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8d64f8fd8f1d..ed8813b222a0 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -1747,6 +1747,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) | |||
1747 | { | 1747 | { |
1748 | struct ata_port *ap = link->ap; | 1748 | struct ata_port *ap = link->ap; |
1749 | struct ata_eh_context *ehc = &link->eh_context; | 1749 | struct ata_eh_context *ehc = &link->eh_context; |
1750 | struct ata_device *dev; | ||
1750 | unsigned int all_err_mask = 0; | 1751 | unsigned int all_err_mask = 0; |
1751 | int tag, is_io = 0; | 1752 | int tag, is_io = 0; |
1752 | u32 serror; | 1753 | u32 serror; |
@@ -1818,18 +1819,24 @@ static void ata_eh_link_autopsy(struct ata_link *link) | |||
1818 | (!is_io && (all_err_mask & ~AC_ERR_DEV))) | 1819 | (!is_io && (all_err_mask & ~AC_ERR_DEV))) |
1819 | ehc->i.action |= ATA_EH_REVALIDATE; | 1820 | ehc->i.action |= ATA_EH_REVALIDATE; |
1820 | 1821 | ||
1821 | /* if we have offending qcs and the associated failed device */ | 1822 | /* If we have offending qcs and the associated failed device, |
1823 | * perform per-dev EH action only on the offending device. | ||
1824 | */ | ||
1822 | if (ehc->i.dev) { | 1825 | if (ehc->i.dev) { |
1823 | /* speed down */ | ||
1824 | ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io, | ||
1825 | all_err_mask); | ||
1826 | |||
1827 | /* perform per-dev EH action only on the offending device */ | ||
1828 | ehc->i.dev_action[ehc->i.dev->devno] |= | 1826 | ehc->i.dev_action[ehc->i.dev->devno] |= |
1829 | ehc->i.action & ATA_EH_PERDEV_MASK; | 1827 | ehc->i.action & ATA_EH_PERDEV_MASK; |
1830 | ehc->i.action &= ~ATA_EH_PERDEV_MASK; | 1828 | ehc->i.action &= ~ATA_EH_PERDEV_MASK; |
1831 | } | 1829 | } |
1832 | 1830 | ||
1831 | /* consider speeding down */ | ||
1832 | dev = ehc->i.dev; | ||
1833 | if (!dev && ata_link_max_devices(link) == 1 && | ||
1834 | ata_dev_enabled(link->device)) | ||
1835 | dev = link->device; | ||
1836 | |||
1837 | if (dev) | ||
1838 | ehc->i.action |= ata_eh_speed_down(dev, is_io, all_err_mask); | ||
1839 | |||
1833 | DPRINTK("EXIT\n"); | 1840 | DPRINTK("EXIT\n"); |
1834 | } | 1841 | } |
1835 | 1842 | ||
@@ -2065,16 +2072,19 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
2065 | ata_prereset_fn_t prereset, ata_reset_fn_t softreset, | 2072 | ata_prereset_fn_t prereset, ata_reset_fn_t softreset, |
2066 | ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) | 2073 | ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) |
2067 | { | 2074 | { |
2075 | const int max_tries = ARRAY_SIZE(ata_eh_reset_timeouts); | ||
2068 | struct ata_port *ap = link->ap; | 2076 | struct ata_port *ap = link->ap; |
2069 | struct ata_eh_context *ehc = &link->eh_context; | 2077 | struct ata_eh_context *ehc = &link->eh_context; |
2070 | unsigned int *classes = ehc->classes; | 2078 | unsigned int *classes = ehc->classes; |
2079 | unsigned int lflags = link->flags; | ||
2071 | int verbose = !(ehc->i.flags & ATA_EHI_QUIET); | 2080 | int verbose = !(ehc->i.flags & ATA_EHI_QUIET); |
2072 | int try = 0; | 2081 | int try = 0; |
2073 | struct ata_device *dev; | 2082 | struct ata_device *dev; |
2074 | unsigned long deadline; | 2083 | unsigned long deadline, now; |
2075 | unsigned int tmp_action; | 2084 | unsigned int tmp_action; |
2076 | ata_reset_fn_t reset; | 2085 | ata_reset_fn_t reset; |
2077 | unsigned long flags; | 2086 | unsigned long flags; |
2087 | u32 sstatus; | ||
2078 | int rc; | 2088 | int rc; |
2079 | 2089 | ||
2080 | /* about to reset */ | 2090 | /* about to reset */ |
@@ -2106,7 +2116,7 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
2106 | /* Determine which reset to use and record in ehc->i.action. | 2116 | /* Determine which reset to use and record in ehc->i.action. |
2107 | * prereset() may examine and modify it. | 2117 | * prereset() may examine and modify it. |
2108 | */ | 2118 | */ |
2109 | if (softreset && (!hardreset || (!(link->flags & ATA_LFLAG_NO_SRST) && | 2119 | if (softreset && (!hardreset || (!(lflags & ATA_LFLAG_NO_SRST) && |
2110 | !sata_set_spd_needed(link) && | 2120 | !sata_set_spd_needed(link) && |
2111 | !(ehc->i.action & ATA_EH_HARDRESET)))) | 2121 | !(ehc->i.action & ATA_EH_HARDRESET)))) |
2112 | tmp_action = ATA_EH_SOFTRESET; | 2122 | tmp_action = ATA_EH_SOFTRESET; |
@@ -2181,82 +2191,64 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
2181 | "follow-up softreset required " | 2191 | "follow-up softreset required " |
2182 | "but no softreset avaliable\n"); | 2192 | "but no softreset avaliable\n"); |
2183 | rc = -EINVAL; | 2193 | rc = -EINVAL; |
2184 | goto out; | 2194 | goto fail; |
2185 | } | 2195 | } |
2186 | 2196 | ||
2187 | ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK); | 2197 | ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK); |
2188 | rc = ata_do_reset(link, reset, classes, deadline); | 2198 | rc = ata_do_reset(link, reset, classes, deadline); |
2189 | |||
2190 | if (rc == 0 && classify && classes[0] == ATA_DEV_UNKNOWN && | ||
2191 | !(link->flags & ATA_LFLAG_ASSUME_CLASS)) { | ||
2192 | ata_link_printk(link, KERN_ERR, | ||
2193 | "classification failed\n"); | ||
2194 | rc = -EINVAL; | ||
2195 | goto out; | ||
2196 | } | ||
2197 | } | 2199 | } |
2198 | 2200 | ||
2199 | /* if we skipped follow-up srst, clear rc */ | 2201 | /* -EAGAIN can happen if we skipped followup SRST */ |
2200 | if (rc == -EAGAIN) | 2202 | if (rc && rc != -EAGAIN) |
2201 | rc = 0; | 2203 | goto fail; |
2202 | |||
2203 | if (rc && rc != -ERESTART && try < ARRAY_SIZE(ata_eh_reset_timeouts)) { | ||
2204 | unsigned long now = jiffies; | ||
2205 | |||
2206 | if (time_before(now, deadline)) { | ||
2207 | unsigned long delta = deadline - jiffies; | ||
2208 | |||
2209 | ata_link_printk(link, KERN_WARNING, "reset failed " | ||
2210 | "(errno=%d), retrying in %u secs\n", | ||
2211 | rc, (jiffies_to_msecs(delta) + 999) / 1000); | ||
2212 | 2204 | ||
2213 | while (delta) | 2205 | /* was classification successful? */ |
2214 | delta = schedule_timeout_uninterruptible(delta); | 2206 | if (classify && classes[0] == ATA_DEV_UNKNOWN && |
2207 | !(lflags & ATA_LFLAG_ASSUME_CLASS)) { | ||
2208 | if (try < max_tries) { | ||
2209 | ata_link_printk(link, KERN_WARNING, | ||
2210 | "classification failed\n"); | ||
2211 | rc = -EINVAL; | ||
2212 | goto fail; | ||
2215 | } | 2213 | } |
2216 | 2214 | ||
2217 | if (rc == -EPIPE || | 2215 | ata_link_printk(link, KERN_WARNING, |
2218 | try == ARRAY_SIZE(ata_eh_reset_timeouts) - 1) | 2216 | "classfication failed, assuming ATA\n"); |
2219 | sata_down_spd_limit(link); | 2217 | lflags |= ATA_LFLAG_ASSUME_ATA; |
2220 | if (hardreset) | ||
2221 | reset = hardreset; | ||
2222 | goto retry; | ||
2223 | } | 2218 | } |
2224 | 2219 | ||
2225 | if (rc == 0) { | 2220 | ata_link_for_each_dev(dev, link) { |
2226 | u32 sstatus; | 2221 | /* After the reset, the device state is PIO 0 and the |
2222 | * controller state is undefined. Reset also wakes up | ||
2223 | * drives from sleeping mode. | ||
2224 | */ | ||
2225 | dev->pio_mode = XFER_PIO_0; | ||
2226 | dev->flags &= ~ATA_DFLAG_SLEEPING; | ||
2227 | 2227 | ||
2228 | ata_link_for_each_dev(dev, link) { | 2228 | if (ata_link_offline(link)) |
2229 | /* After the reset, the device state is PIO 0 | 2229 | continue; |
2230 | * and the controller state is undefined. | ||
2231 | * Reset also wakes up drives from sleeping | ||
2232 | * mode. | ||
2233 | */ | ||
2234 | dev->pio_mode = XFER_PIO_0; | ||
2235 | dev->flags &= ~ATA_DFLAG_SLEEPING; | ||
2236 | 2230 | ||
2237 | if (ata_link_offline(link)) | 2231 | /* apply class override and convert UNKNOWN to NONE */ |
2238 | continue; | 2232 | if (lflags & ATA_LFLAG_ASSUME_ATA) |
2233 | classes[dev->devno] = ATA_DEV_ATA; | ||
2234 | else if (lflags & ATA_LFLAG_ASSUME_SEMB) | ||
2235 | classes[dev->devno] = ATA_DEV_SEMB_UNSUP; /* not yet */ | ||
2236 | else if (classes[dev->devno] == ATA_DEV_UNKNOWN) | ||
2237 | classes[dev->devno] = ATA_DEV_NONE; | ||
2238 | } | ||
2239 | 2239 | ||
2240 | /* apply class override and convert UNKNOWN to NONE */ | 2240 | /* record current link speed */ |
2241 | if (link->flags & ATA_LFLAG_ASSUME_ATA) | 2241 | if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0) |
2242 | classes[dev->devno] = ATA_DEV_ATA; | 2242 | link->sata_spd = (sstatus >> 4) & 0xf; |
2243 | else if (link->flags & ATA_LFLAG_ASSUME_SEMB) | ||
2244 | classes[dev->devno] = ATA_DEV_SEMB_UNSUP; /* not yet */ | ||
2245 | else if (classes[dev->devno] == ATA_DEV_UNKNOWN) | ||
2246 | classes[dev->devno] = ATA_DEV_NONE; | ||
2247 | } | ||
2248 | 2243 | ||
2249 | /* record current link speed */ | 2244 | if (postreset) |
2250 | if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0) | 2245 | postreset(link, classes); |
2251 | link->sata_spd = (sstatus >> 4) & 0xf; | ||
2252 | 2246 | ||
2253 | if (postreset) | 2247 | /* reset successful, schedule revalidation */ |
2254 | postreset(link, classes); | 2248 | ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK); |
2249 | ehc->i.action |= ATA_EH_REVALIDATE; | ||
2255 | 2250 | ||
2256 | /* reset successful, schedule revalidation */ | 2251 | rc = 0; |
2257 | ata_eh_done(link, NULL, ehc->i.action & ATA_EH_RESET_MASK); | ||
2258 | ehc->i.action |= ATA_EH_REVALIDATE; | ||
2259 | } | ||
2260 | out: | 2252 | out: |
2261 | /* clear hotplug flag */ | 2253 | /* clear hotplug flag */ |
2262 | ehc->i.flags &= ~ATA_EHI_HOTPLUGGED; | 2254 | ehc->i.flags &= ~ATA_EHI_HOTPLUGGED; |
@@ -2266,6 +2258,28 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
2266 | spin_unlock_irqrestore(ap->lock, flags); | 2258 | spin_unlock_irqrestore(ap->lock, flags); |
2267 | 2259 | ||
2268 | return rc; | 2260 | return rc; |
2261 | |||
2262 | fail: | ||
2263 | if (rc == -ERESTART || try >= max_tries) | ||
2264 | goto out; | ||
2265 | |||
2266 | now = jiffies; | ||
2267 | if (time_before(now, deadline)) { | ||
2268 | unsigned long delta = deadline - now; | ||
2269 | |||
2270 | ata_link_printk(link, KERN_WARNING, "reset failed " | ||
2271 | "(errno=%d), retrying in %u secs\n", | ||
2272 | rc, (jiffies_to_msecs(delta) + 999) / 1000); | ||
2273 | |||
2274 | while (delta) | ||
2275 | delta = schedule_timeout_uninterruptible(delta); | ||
2276 | } | ||
2277 | |||
2278 | if (rc == -EPIPE || try == max_tries - 1) | ||
2279 | sata_down_spd_limit(link); | ||
2280 | if (hardreset) | ||
2281 | reset = hardreset; | ||
2282 | goto retry; | ||
2269 | } | 2283 | } |
2270 | 2284 | ||
2271 | static int ata_eh_revalidate_and_attach(struct ata_link *link, | 2285 | static int ata_eh_revalidate_and_attach(struct ata_link *link, |