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 | |
| 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>
| -rw-r--r-- | drivers/ata/libata-eh.c | 30 | ||||
| -rw-r--r-- | include/linux/libata.h | 3 |
2 files changed, 32 insertions, 1 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8f8ed4dfb171..fbbf79163900 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; |
diff --git a/include/linux/libata.h b/include/linux/libata.h index adeee7397cdb..2bd1d26c9c8d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -170,6 +170,7 @@ enum { | |||
| 170 | ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */ | 170 | ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */ |
| 171 | ATA_LFLAG_ASSUME_CLASS = ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB, | 171 | ATA_LFLAG_ASSUME_CLASS = ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB, |
| 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 | 174 | ||
| 174 | /* struct ata_port flags */ | 175 | /* struct ata_port flags */ |
| 175 | ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ | 176 | ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ |
| @@ -289,6 +290,7 @@ enum { | |||
| 289 | ATA_EH_REVALIDATE = (1 << 0), | 290 | ATA_EH_REVALIDATE = (1 << 0), |
| 290 | ATA_EH_SOFTRESET = (1 << 1), | 291 | ATA_EH_SOFTRESET = (1 << 1), |
| 291 | ATA_EH_HARDRESET = (1 << 2), | 292 | ATA_EH_HARDRESET = (1 << 2), |
| 293 | ATA_EH_ENABLE_LINK = (1 << 3), | ||
| 292 | 294 | ||
| 293 | ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, | 295 | ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, |
| 294 | ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE, | 296 | ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE, |
| @@ -999,6 +1001,7 @@ static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi) | |||
| 999 | { | 1001 | { |
| 1000 | ata_ehi_schedule_probe(ehi); | 1002 | ata_ehi_schedule_probe(ehi); |
| 1001 | ehi->flags |= ATA_EHI_HOTPLUGGED; | 1003 | ehi->flags |= ATA_EHI_HOTPLUGGED; |
| 1004 | ehi->action |= ATA_EH_ENABLE_LINK; | ||
| 1002 | ehi->err_mask |= AC_ERR_ATA_BUS; | 1005 | ehi->err_mask |= AC_ERR_ATA_BUS; |
| 1003 | } | 1006 | } |
| 1004 | 1007 | ||
