aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-eh.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-08-06 05:36:24 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-12 14:55:32 -0400
commit9b1e2658faf3f3095a96558c333b333c0e29dbc0 (patch)
tree38553202d35e9a82b2e943df525d482892fef505 /drivers/ata/libata-eh.c
parentcf1b86c8ab41fe2b2a2eb59c9a2ea9a7e463653a (diff)
libata-link: update EH to deal with PMP links
Update ata_eh_autopsy(), ata_eh_report(), ata_eh_revalidate_and_attach() and ata_eh_recover() to deal with PMP links. ata_eh_autopsy() and ata_eh_report() updates are straightforward. They just repeat the same operation over all configured links. The only change to ata_eh_revalidate_and_attach() is avoiding calling ->cable_select() on non-host ports. ata_eh_recover() update is more complex as it first processes all resets and then performs the rest. This is necessary as thawing with some links in unknown state can be dangerous. ehi->action is cleared on successful recovery of a link to avoid repeating recovery due to failures in other links. ata_eh_recover() iterates over only PMP links if PMP is attached, and, on failure, the failing link is returned in @failed_link instead of disabling devices directly. These are to integrate ata_eh_recover() into PMP EH later. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r--drivers/ata/libata-eh.c228
1 files changed, 158 insertions, 70 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 45eb932c3935..2ddc2ed9c29d 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1578,8 +1578,8 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
1578} 1578}
1579 1579
1580/** 1580/**
1581 * ata_eh_autopsy - analyze error and determine recovery action 1581 * ata_eh_link_autopsy - analyze error and determine recovery action
1582 * @link: ATA link to perform autopsy on 1582 * @link: host link to perform autopsy on
1583 * 1583 *
1584 * Analyze why @link failed and determine which recovery actions 1584 * Analyze why @link failed and determine which recovery actions
1585 * are needed. This function also sets more detailed AC_ERR_* 1585 * are needed. This function also sets more detailed AC_ERR_*
@@ -1588,7 +1588,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
1588 * LOCKING: 1588 * LOCKING:
1589 * Kernel thread context (may sleep). 1589 * Kernel thread context (may sleep).
1590 */ 1590 */
1591static void ata_eh_autopsy(struct ata_link *link) 1591static void ata_eh_link_autopsy(struct ata_link *link)
1592{ 1592{
1593 struct ata_port *ap = link->ap; 1593 struct ata_port *ap = link->ap;
1594 struct ata_eh_context *ehc = &link->eh_context; 1594 struct ata_eh_context *ehc = &link->eh_context;
@@ -1680,7 +1680,25 @@ static void ata_eh_autopsy(struct ata_link *link)
1680} 1680}
1681 1681
1682/** 1682/**
1683 * ata_eh_report - report error handling to user 1683 * ata_eh_autopsy - analyze error and determine recovery action
1684 * @ap: host port to perform autopsy on
1685 *
1686 * Analyze all links of @ap and determine why they failed and
1687 * which recovery actions are needed.
1688 *
1689 * LOCKING:
1690 * Kernel thread context (may sleep).
1691 */
1692static void ata_eh_autopsy(struct ata_port *ap)
1693{
1694 struct ata_link *link;
1695
1696 __ata_port_for_each_link(link, ap)
1697 ata_eh_link_autopsy(link);
1698}
1699
1700/**
1701 * ata_eh_link_report - report error handling to user
1684 * @link: ATA link EH is going on 1702 * @link: ATA link EH is going on
1685 * 1703 *
1686 * Report EH to user. 1704 * Report EH to user.
@@ -1688,7 +1706,7 @@ static void ata_eh_autopsy(struct ata_link *link)
1688 * LOCKING: 1706 * LOCKING:
1689 * None. 1707 * None.
1690 */ 1708 */
1691static void ata_eh_report(struct ata_link *link) 1709static void ata_eh_link_report(struct ata_link *link)
1692{ 1710{
1693 struct ata_port *ap = link->ap; 1711 struct ata_port *ap = link->ap;
1694 struct ata_eh_context *ehc = &link->eh_context; 1712 struct ata_eh_context *ehc = &link->eh_context;
@@ -1767,6 +1785,23 @@ static void ata_eh_report(struct ata_link *link)
1767 } 1785 }
1768} 1786}
1769 1787
1788/**
1789 * ata_eh_report - report error handling to user
1790 * @ap: ATA port to report EH about
1791 *
1792 * Report EH to user.
1793 *
1794 * LOCKING:
1795 * None.
1796 */
1797static void ata_eh_report(struct ata_port *ap)
1798{
1799 struct ata_link *link;
1800
1801 __ata_port_for_each_link(link, ap)
1802 ata_eh_link_report(link);
1803}
1804
1770static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset, 1805static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
1771 unsigned int *classes, unsigned long deadline) 1806 unsigned int *classes, unsigned long deadline)
1772{ 1807{
@@ -2036,7 +2071,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
2036 } 2071 }
2037 2072
2038 /* PDIAG- should have been released, ask cable type if post-reset */ 2073 /* PDIAG- should have been released, ask cable type if post-reset */
2039 if ((ehc->i.flags & ATA_EHI_DID_RESET) && ap->ops->cable_detect) 2074 if (ata_is_host_link(link) && ap->ops->cable_detect &&
2075 (ehc->i.flags & ATA_EHI_DID_RESET))
2040 ap->cbl = ap->ops->cable_detect(ap); 2076 ap->cbl = ap->ops->cable_detect(ap);
2041 2077
2042 /* Configure new devices forward such that user doesn't see 2078 /* Configure new devices forward such that user doesn't see
@@ -2110,7 +2146,7 @@ static int ata_eh_skip_recovery(struct ata_link *link)
2110 return 1; 2146 return 1;
2111} 2147}
2112 2148
2113static void ata_eh_handle_dev_fail(struct ata_device *dev, int err) 2149static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
2114{ 2150{
2115 struct ata_eh_context *ehc = &dev->link->eh_context; 2151 struct ata_eh_context *ehc = &dev->link->eh_context;
2116 2152
@@ -2151,12 +2187,16 @@ static void ata_eh_handle_dev_fail(struct ata_device *dev, int err)
2151 ehc->did_probe_mask |= (1 << dev->devno); 2187 ehc->did_probe_mask |= (1 << dev->devno);
2152 ehc->i.action |= ATA_EH_SOFTRESET; 2188 ehc->i.action |= ATA_EH_SOFTRESET;
2153 } 2189 }
2190
2191 return 1;
2154 } else { 2192 } else {
2155 /* soft didn't work? be haaaaard */ 2193 /* soft didn't work? be haaaaard */
2156 if (ehc->i.flags & ATA_EHI_DID_RESET) 2194 if (ehc->i.flags & ATA_EHI_DID_RESET)
2157 ehc->i.action |= ATA_EH_HARDRESET; 2195 ehc->i.action |= ATA_EH_HARDRESET;
2158 else 2196 else
2159 ehc->i.action |= ATA_EH_SOFTRESET; 2197 ehc->i.action |= ATA_EH_SOFTRESET;
2198
2199 return 0;
2160 } 2200 }
2161} 2201}
2162 2202
@@ -2167,12 +2207,13 @@ static void ata_eh_handle_dev_fail(struct ata_device *dev, int err)
2167 * @softreset: softreset method (can be NULL) 2207 * @softreset: softreset method (can be NULL)
2168 * @hardreset: hardreset method (can be NULL) 2208 * @hardreset: hardreset method (can be NULL)
2169 * @postreset: postreset method (can be NULL) 2209 * @postreset: postreset method (can be NULL)
2210 * @r_failed_link: out parameter for failed link
2170 * 2211 *
2171 * This is the alpha and omega, eum and yang, heart and soul of 2212 * This is the alpha and omega, eum and yang, heart and soul of
2172 * libata exception handling. On entry, actions required to 2213 * libata exception handling. On entry, actions required to
2173 * recover the port and hotplug requests are recorded in 2214 * recover each link and hotplug requests are recorded in the
2174 * eh_context. This function executes all the operations with 2215 * link's eh_context. This function executes all the operations
2175 * appropriate retrials and fallbacks to resurrect failed 2216 * with appropriate retrials and fallbacks to resurrect failed
2176 * devices, detach goners and greet newcomers. 2217 * devices, detach goners and greet newcomers.
2177 * 2218 *
2178 * LOCKING: 2219 * LOCKING:
@@ -2183,102 +2224,139 @@ static void ata_eh_handle_dev_fail(struct ata_device *dev, int err)
2183 */ 2224 */
2184static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, 2225static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
2185 ata_reset_fn_t softreset, ata_reset_fn_t hardreset, 2226 ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
2186 ata_postreset_fn_t postreset) 2227 ata_postreset_fn_t postreset,
2228 struct ata_link **r_failed_link)
2187{ 2229{
2188 struct ata_link *link = &ap->link; 2230 struct ata_link *link;
2189 struct ata_eh_context *ehc = &link->eh_context;
2190 struct ata_device *dev; 2231 struct ata_device *dev;
2191 int rc; 2232 int nr_failed_devs, nr_disabled_devs;
2233 int reset, rc;
2192 2234
2193 DPRINTK("ENTER\n"); 2235 DPRINTK("ENTER\n");
2194 2236
2195 /* prep for recovery */ 2237 /* prep for recovery */
2196 ata_link_for_each_dev(dev, link) { 2238 ata_port_for_each_link(link, ap) {
2197 ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; 2239 struct ata_eh_context *ehc = &link->eh_context;
2198 2240
2199 /* collect port action mask recorded in dev actions */ 2241 ata_link_for_each_dev(dev, link) {
2200 ehc->i.action |= 2242 ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
2201 ehc->i.dev_action[dev->devno] & ~ATA_EH_PERDEV_MASK;
2202 ehc->i.dev_action[dev->devno] &= ATA_EH_PERDEV_MASK;
2203
2204 /* process hotplug request */
2205 if (dev->flags & ATA_DFLAG_DETACH)
2206 ata_eh_detach_dev(dev);
2207 2243
2208 if (!ata_dev_enabled(dev) && 2244 /* collect port action mask recorded in dev actions */
2209 ((ehc->i.probe_mask & (1 << dev->devno)) && 2245 ehc->i.action |= ehc->i.dev_action[dev->devno] &
2210 !(ehc->did_probe_mask & (1 << dev->devno)))) { 2246 ~ATA_EH_PERDEV_MASK;
2211 ata_eh_detach_dev(dev); 2247 ehc->i.dev_action[dev->devno] &= ATA_EH_PERDEV_MASK;
2212 ata_dev_init(dev); 2248
2213 ehc->did_probe_mask |= (1 << dev->devno); 2249 /* process hotplug request */
2214 ehc->i.action |= ATA_EH_SOFTRESET; 2250 if (dev->flags & ATA_DFLAG_DETACH)
2251 ata_eh_detach_dev(dev);
2252
2253 if (!ata_dev_enabled(dev) &&
2254 ((ehc->i.probe_mask & (1 << dev->devno)) &&
2255 !(ehc->did_probe_mask & (1 << dev->devno)))) {
2256 ata_eh_detach_dev(dev);
2257 ata_dev_init(dev);
2258 ehc->did_probe_mask |= (1 << dev->devno);
2259 ehc->i.action |= ATA_EH_SOFTRESET;
2260 }
2215 } 2261 }
2216 } 2262 }
2217 2263
2218 retry: 2264 retry:
2219 rc = 0; 2265 rc = 0;
2266 nr_failed_devs = 0;
2267 nr_disabled_devs = 0;
2268 reset = 0;
2220 2269
2221 /* if UNLOADING, finish immediately */ 2270 /* if UNLOADING, finish immediately */
2222 if (ap->pflags & ATA_PFLAG_UNLOADING) 2271 if (ap->pflags & ATA_PFLAG_UNLOADING)
2223 goto out; 2272 goto out;
2224 2273
2225 /* skip EH if possible. */ 2274 /* prep for EH */
2226 if (ata_eh_skip_recovery(link)) 2275 ata_port_for_each_link(link, ap) {
2227 ehc->i.action = 0; 2276 struct ata_eh_context *ehc = &link->eh_context;
2228 2277
2229 ata_link_for_each_dev(dev, link) 2278 /* skip EH if possible. */
2230 ehc->classes[dev->devno] = ATA_DEV_UNKNOWN; 2279 if (ata_eh_skip_recovery(link))
2280 ehc->i.action = 0;
2281
2282 /* do we need to reset? */
2283 if (ehc->i.action & ATA_EH_RESET_MASK)
2284 reset = 1;
2285
2286 ata_link_for_each_dev(dev, link)
2287 ehc->classes[dev->devno] = ATA_DEV_UNKNOWN;
2288 }
2231 2289
2232 /* reset */ 2290 /* reset */
2233 if (ehc->i.action & ATA_EH_RESET_MASK) { 2291 if (reset) {
2234 ata_eh_freeze_port(ap); 2292 ata_eh_freeze_port(ap);
2235 2293
2236 rc = ata_eh_reset(link, ata_link_nr_vacant(link), prereset, 2294 ata_port_for_each_link(link, ap) {
2237 softreset, hardreset, postreset); 2295 struct ata_eh_context *ehc = &link->eh_context;
2238 if (rc) { 2296
2239 ata_link_printk(link, KERN_ERR, 2297 if (!(ehc->i.action & ATA_EH_RESET_MASK))
2240 "reset failed, giving up\n"); 2298 continue;
2241 goto out; 2299
2300 rc = ata_eh_reset(link, ata_link_nr_vacant(link),
2301 prereset, softreset, hardreset,
2302 postreset);
2303 if (rc) {
2304 ata_link_printk(link, KERN_ERR,
2305 "reset failed, giving up\n");
2306 goto out;
2307 }
2242 } 2308 }
2243 2309
2244 ata_eh_thaw_port(ap); 2310 ata_eh_thaw_port(ap);
2245 } 2311 }
2246 2312
2247 /* revalidate existing devices and attach new ones */ 2313 /* the rest */
2248 rc = ata_eh_revalidate_and_attach(link, &dev); 2314 ata_port_for_each_link(link, ap) {
2249 if (rc) 2315 struct ata_eh_context *ehc = &link->eh_context;
2250 goto dev_fail;
2251 2316
2252 /* configure transfer mode if necessary */ 2317 /* revalidate existing devices and attach new ones */
2253 if (ehc->i.flags & ATA_EHI_SETMODE) { 2318 rc = ata_eh_revalidate_and_attach(link, &dev);
2254 rc = ata_set_mode(link, &dev);
2255 if (rc) 2319 if (rc)
2256 goto dev_fail; 2320 goto dev_fail;
2257 ehc->i.flags &= ~ATA_EHI_SETMODE;
2258 }
2259 2321
2260 goto out; 2322 /* configure transfer mode if necessary */
2323 if (ehc->i.flags & ATA_EHI_SETMODE) {
2324 rc = ata_set_mode(link, &dev);
2325 if (rc)
2326 goto dev_fail;
2327 ehc->i.flags &= ~ATA_EHI_SETMODE;
2328 }
2329
2330 /* this link is okay now */
2331 ehc->i.flags = 0;
2332 continue;
2261 2333
2262 dev_fail: 2334 dev_fail:
2263 ata_eh_handle_dev_fail(dev, rc); 2335 nr_failed_devs++;
2336 if (ata_eh_handle_dev_fail(dev, rc))
2337 nr_disabled_devs++;
2264 2338
2265 if (ata_link_nr_enabled(link)) { 2339 if (ap->pflags & ATA_PFLAG_FROZEN)
2266 ata_link_printk(link, KERN_WARNING, "failed to recover some " 2340 break;
2267 "devices, retrying in 5 secs\n");
2268 ssleep(5);
2269 } else {
2270 /* no device left, repeat fast */
2271 msleep(500);
2272 } 2341 }
2273 2342
2274 goto retry; 2343 if (nr_failed_devs) {
2344 if (nr_failed_devs != nr_disabled_devs) {
2345 ata_port_printk(ap, KERN_WARNING, "failed to recover "
2346 "some devices, retrying in 5 secs\n");
2347 ssleep(5);
2348 } else {
2349 /* no device left to recover, repeat fast */
2350 msleep(500);
2351 }
2275 2352
2276 out: 2353 goto retry;
2277 if (rc) {
2278 ata_link_for_each_dev(dev, link);
2279 ata_dev_disable(dev);
2280 } 2354 }
2281 2355
2356 out:
2357 if (rc && r_failed_link)
2358 *r_failed_link = link;
2359
2282 DPRINTK("EXIT, rc=%d\n", rc); 2360 DPRINTK("EXIT, rc=%d\n", rc);
2283 return rc; 2361 return rc;
2284} 2362}
@@ -2342,9 +2420,19 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
2342 ata_reset_fn_t softreset, ata_reset_fn_t hardreset, 2420 ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
2343 ata_postreset_fn_t postreset) 2421 ata_postreset_fn_t postreset)
2344{ 2422{
2345 ata_eh_autopsy(&ap->link); 2423 struct ata_device *dev;
2346 ata_eh_report(&ap->link); 2424 int rc;
2347 ata_eh_recover(ap, prereset, softreset, hardreset, postreset); 2425
2426 ata_eh_autopsy(ap);
2427 ata_eh_report(ap);
2428
2429 rc = ata_eh_recover(ap, prereset, softreset, hardreset, postreset,
2430 NULL);
2431 if (rc) {
2432 ata_link_for_each_dev(dev, &ap->link)
2433 ata_dev_disable(dev);
2434 }
2435
2348 ata_eh_finish(ap); 2436 ata_eh_finish(ap);
2349} 2437}
2350 2438