diff options
author | Tejun Heo <htejun@gmail.com> | 2007-09-23 00:14:13 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-10-12 14:55:41 -0400 |
commit | f9df58cb27dfd605eced643bb3aa599fe4feeee8 (patch) | |
tree | 23b5151855d07f3b25c081e29d14f5d353367248 /drivers/ata/libata-eh.c | |
parent | fd995f7039f1955ccc6b43e1e2d168060b31e4b2 (diff) |
libata-pmp-prep: implement ATA_LFLAG_DISABLED
Implement ATA_LFLAG_DISABLED. The flag indicates the link is disabled
due to EH recovery failure. While a link is disabled, no EH action is
taken on the link and suspend/resume become noop too.
This will be used by PMP links to manage failed links.
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.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8f8ed4dfb17..fbbf7916390 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -1308,6 +1308,7 @@ static void ata_eh_analyze_serror(struct ata_link *link) | |||
1308 | struct ata_eh_context *ehc = &link->eh_context; | 1308 | struct ata_eh_context *ehc = &link->eh_context; |
1309 | u32 serror = ehc->i.serror; | 1309 | u32 serror = ehc->i.serror; |
1310 | unsigned int err_mask = 0, action = 0; | 1310 | unsigned int err_mask = 0, action = 0; |
1311 | u32 hotplug_mask; | ||
1311 | 1312 | ||
1312 | if (serror & SERR_PERSISTENT) { | 1313 | if (serror & SERR_PERSISTENT) { |
1313 | err_mask |= AC_ERR_ATA_BUS; | 1314 | err_mask |= AC_ERR_ATA_BUS; |
@@ -1326,7 +1327,20 @@ static void ata_eh_analyze_serror(struct ata_link *link) | |||
1326 | err_mask |= AC_ERR_SYSTEM; | 1327 | err_mask |= AC_ERR_SYSTEM; |
1327 | action |= ATA_EH_HARDRESET; | 1328 | action |= ATA_EH_HARDRESET; |
1328 | } | 1329 | } |
1329 | if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) | 1330 | |
1331 | /* Determine whether a hotplug event has occurred. Both | ||
1332 | * SError.N/X are considered hotplug events for enabled or | ||
1333 | * host links. For disabled PMP links, only N bit is | ||
1334 | * considered as X bit is left at 1 for link plugging. | ||
1335 | */ | ||
1336 | hotplug_mask = 0; | ||
1337 | |||
1338 | if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link)) | ||
1339 | hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG; | ||
1340 | else | ||
1341 | hotplug_mask = SERR_PHYRDY_CHG; | ||
1342 | |||
1343 | if (serror & hotplug_mask) | ||
1330 | ata_ehi_hotplugged(&ehc->i); | 1344 | ata_ehi_hotplugged(&ehc->i); |
1331 | 1345 | ||
1332 | ehc->i.err_mask |= err_mask; | 1346 | ehc->i.err_mask |= err_mask; |
@@ -2227,6 +2241,10 @@ static int ata_eh_skip_recovery(struct ata_link *link) | |||
2227 | struct ata_eh_context *ehc = &link->eh_context; | 2241 | struct ata_eh_context *ehc = &link->eh_context; |
2228 | struct ata_device *dev; | 2242 | struct ata_device *dev; |
2229 | 2243 | ||
2244 | /* skip disabled links */ | ||
2245 | if (link->flags & ATA_LFLAG_DISABLED) | ||
2246 | return 1; | ||
2247 | |||
2230 | /* thaw frozen port, resume link and recover failed devices */ | 2248 | /* thaw frozen port, resume link and recover failed devices */ |
2231 | if ((link->ap->pflags & ATA_PFLAG_FROZEN) || | 2249 | if ((link->ap->pflags & ATA_PFLAG_FROZEN) || |
2232 | (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_link_nr_enabled(link)) | 2250 | (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_link_nr_enabled(link)) |
@@ -2327,6 +2345,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
2327 | struct ata_device *dev; | 2345 | struct ata_device *dev; |
2328 | int nr_failed_devs, nr_disabled_devs; | 2346 | int nr_failed_devs, nr_disabled_devs; |
2329 | int reset, rc; | 2347 | int reset, rc; |
2348 | unsigned long flags; | ||
2330 | 2349 | ||
2331 | DPRINTK("ENTER\n"); | 2350 | DPRINTK("ENTER\n"); |
2332 | 2351 | ||
@@ -2334,6 +2353,15 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
2334 | ata_port_for_each_link(link, ap) { | 2353 | ata_port_for_each_link(link, ap) { |
2335 | struct ata_eh_context *ehc = &link->eh_context; | 2354 | struct ata_eh_context *ehc = &link->eh_context; |
2336 | 2355 | ||
2356 | /* re-enable link? */ | ||
2357 | if (ehc->i.action & ATA_EH_ENABLE_LINK) { | ||
2358 | ata_eh_about_to_do(link, NULL, ATA_EH_ENABLE_LINK); | ||
2359 | spin_lock_irqsave(ap->lock, flags); | ||
2360 | link->flags &= ~ATA_LFLAG_DISABLED; | ||
2361 | spin_unlock_irqrestore(ap->lock, flags); | ||
2362 | ata_eh_done(link, NULL, ATA_EH_ENABLE_LINK); | ||
2363 | } | ||
2364 | |||
2337 | ata_link_for_each_dev(dev, link) { | 2365 | ata_link_for_each_dev(dev, link) { |
2338 | if (link->flags & ATA_LFLAG_NO_RETRY) | 2366 | if (link->flags & ATA_LFLAG_NO_RETRY) |
2339 | ehc->tries[dev->devno] = 1; | 2367 | ehc->tries[dev->devno] = 1; |