diff options
author | Dave Jones <davej@redhat.com> | 2006-09-05 17:20:21 -0400 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2006-09-05 17:20:21 -0400 |
commit | 115b384cf87249d76adb0b21aca11ee22128927d (patch) | |
tree | f39a2a54863e9d82d1196906f92c82ab5991c6af /drivers/scsi/libata-eh.c | |
parent | 8eb7925f93af75e66a240d148efdec212f95bcb7 (diff) | |
parent | c336923b668fdcf0312efbec3b44895d713f4d81 (diff) |
Merge ../linus
Diffstat (limited to 'drivers/scsi/libata-eh.c')
-rw-r--r-- | drivers/scsi/libata-eh.c | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 4b6aa30f4d68..29f59345305d 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c | |||
@@ -764,12 +764,27 @@ static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev, | |||
764 | unsigned int action) | 764 | unsigned int action) |
765 | { | 765 | { |
766 | unsigned long flags; | 766 | unsigned long flags; |
767 | struct ata_eh_info *ehi = &ap->eh_info; | ||
768 | struct ata_eh_context *ehc = &ap->eh_context; | ||
767 | 769 | ||
768 | spin_lock_irqsave(ap->lock, flags); | 770 | spin_lock_irqsave(ap->lock, flags); |
769 | 771 | ||
770 | ata_eh_clear_action(dev, &ap->eh_info, action); | 772 | /* Reset is represented by combination of actions and EHI |
773 | * flags. Suck in all related bits before clearing eh_info to | ||
774 | * avoid losing requested action. | ||
775 | */ | ||
776 | if (action & ATA_EH_RESET_MASK) { | ||
777 | ehc->i.action |= ehi->action & ATA_EH_RESET_MASK; | ||
778 | ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK; | ||
779 | |||
780 | /* make sure all reset actions are cleared & clear EHI flags */ | ||
781 | action |= ATA_EH_RESET_MASK; | ||
782 | ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK; | ||
783 | } | ||
784 | |||
785 | ata_eh_clear_action(dev, ehi, action); | ||
771 | 786 | ||
772 | if (!(ap->eh_context.i.flags & ATA_EHI_QUIET)) | 787 | if (!(ehc->i.flags & ATA_EHI_QUIET)) |
773 | ap->pflags |= ATA_PFLAG_RECOVERED; | 788 | ap->pflags |= ATA_PFLAG_RECOVERED; |
774 | 789 | ||
775 | spin_unlock_irqrestore(ap->lock, flags); | 790 | spin_unlock_irqrestore(ap->lock, flags); |
@@ -790,6 +805,12 @@ static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev, | |||
790 | static void ata_eh_done(struct ata_port *ap, struct ata_device *dev, | 805 | static void ata_eh_done(struct ata_port *ap, struct ata_device *dev, |
791 | unsigned int action) | 806 | unsigned int action) |
792 | { | 807 | { |
808 | /* if reset is complete, clear all reset actions & reset modifier */ | ||
809 | if (action & ATA_EH_RESET_MASK) { | ||
810 | action |= ATA_EH_RESET_MASK; | ||
811 | ap->eh_context.i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK; | ||
812 | } | ||
813 | |||
793 | ata_eh_clear_action(dev, &ap->eh_context.i, action); | 814 | ata_eh_clear_action(dev, &ap->eh_context.i, action); |
794 | } | 815 | } |
795 | 816 | ||
@@ -1276,8 +1297,6 @@ static int ata_eh_speed_down(struct ata_device *dev, int is_io, | |||
1276 | static void ata_eh_autopsy(struct ata_port *ap) | 1297 | static void ata_eh_autopsy(struct ata_port *ap) |
1277 | { | 1298 | { |
1278 | struct ata_eh_context *ehc = &ap->eh_context; | 1299 | struct ata_eh_context *ehc = &ap->eh_context; |
1279 | unsigned int action = ehc->i.action; | ||
1280 | struct ata_device *failed_dev = NULL; | ||
1281 | unsigned int all_err_mask = 0; | 1300 | unsigned int all_err_mask = 0; |
1282 | int tag, is_io = 0; | 1301 | int tag, is_io = 0; |
1283 | u32 serror; | 1302 | u32 serror; |
@@ -1294,7 +1313,7 @@ static void ata_eh_autopsy(struct ata_port *ap) | |||
1294 | ehc->i.serror |= serror; | 1313 | ehc->i.serror |= serror; |
1295 | ata_eh_analyze_serror(ap); | 1314 | ata_eh_analyze_serror(ap); |
1296 | } else if (rc != -EOPNOTSUPP) | 1315 | } else if (rc != -EOPNOTSUPP) |
1297 | action |= ATA_EH_HARDRESET; | 1316 | ehc->i.action |= ATA_EH_HARDRESET; |
1298 | 1317 | ||
1299 | /* analyze NCQ failure */ | 1318 | /* analyze NCQ failure */ |
1300 | ata_eh_analyze_ncq_error(ap); | 1319 | ata_eh_analyze_ncq_error(ap); |
@@ -1315,7 +1334,7 @@ static void ata_eh_autopsy(struct ata_port *ap) | |||
1315 | qc->err_mask |= ehc->i.err_mask; | 1334 | qc->err_mask |= ehc->i.err_mask; |
1316 | 1335 | ||
1317 | /* analyze TF */ | 1336 | /* analyze TF */ |
1318 | action |= ata_eh_analyze_tf(qc, &qc->result_tf); | 1337 | ehc->i.action |= ata_eh_analyze_tf(qc, &qc->result_tf); |
1319 | 1338 | ||
1320 | /* DEV errors are probably spurious in case of ATA_BUS error */ | 1339 | /* DEV errors are probably spurious in case of ATA_BUS error */ |
1321 | if (qc->err_mask & AC_ERR_ATA_BUS) | 1340 | if (qc->err_mask & AC_ERR_ATA_BUS) |
@@ -1329,11 +1348,11 @@ static void ata_eh_autopsy(struct ata_port *ap) | |||
1329 | /* SENSE_VALID trumps dev/unknown error and revalidation */ | 1348 | /* SENSE_VALID trumps dev/unknown error and revalidation */ |
1330 | if (qc->flags & ATA_QCFLAG_SENSE_VALID) { | 1349 | if (qc->flags & ATA_QCFLAG_SENSE_VALID) { |
1331 | qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); | 1350 | qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); |
1332 | action &= ~ATA_EH_REVALIDATE; | 1351 | ehc->i.action &= ~ATA_EH_REVALIDATE; |
1333 | } | 1352 | } |
1334 | 1353 | ||
1335 | /* accumulate error info */ | 1354 | /* accumulate error info */ |
1336 | failed_dev = qc->dev; | 1355 | ehc->i.dev = qc->dev; |
1337 | all_err_mask |= qc->err_mask; | 1356 | all_err_mask |= qc->err_mask; |
1338 | if (qc->flags & ATA_QCFLAG_IO) | 1357 | if (qc->flags & ATA_QCFLAG_IO) |
1339 | is_io = 1; | 1358 | is_io = 1; |
@@ -1342,25 +1361,22 @@ static void ata_eh_autopsy(struct ata_port *ap) | |||
1342 | /* enforce default EH actions */ | 1361 | /* enforce default EH actions */ |
1343 | if (ap->pflags & ATA_PFLAG_FROZEN || | 1362 | if (ap->pflags & ATA_PFLAG_FROZEN || |
1344 | all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) | 1363 | all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) |
1345 | action |= ATA_EH_SOFTRESET; | 1364 | ehc->i.action |= ATA_EH_SOFTRESET; |
1346 | else if (all_err_mask) | 1365 | else if (all_err_mask) |
1347 | action |= ATA_EH_REVALIDATE; | 1366 | ehc->i.action |= ATA_EH_REVALIDATE; |
1348 | 1367 | ||
1349 | /* if we have offending qcs and the associated failed device */ | 1368 | /* if we have offending qcs and the associated failed device */ |
1350 | if (failed_dev) { | 1369 | if (ehc->i.dev) { |
1351 | /* speed down */ | 1370 | /* speed down */ |
1352 | action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask); | 1371 | ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io, |
1372 | all_err_mask); | ||
1353 | 1373 | ||
1354 | /* perform per-dev EH action only on the offending device */ | 1374 | /* perform per-dev EH action only on the offending device */ |
1355 | ehc->i.dev_action[failed_dev->devno] |= | 1375 | ehc->i.dev_action[ehc->i.dev->devno] |= |
1356 | action & ATA_EH_PERDEV_MASK; | 1376 | ehc->i.action & ATA_EH_PERDEV_MASK; |
1357 | action &= ~ATA_EH_PERDEV_MASK; | 1377 | ehc->i.action &= ~ATA_EH_PERDEV_MASK; |
1358 | } | 1378 | } |
1359 | 1379 | ||
1360 | /* record autopsy result */ | ||
1361 | ehc->i.dev = failed_dev; | ||
1362 | ehc->i.action |= action; | ||
1363 | |||
1364 | DPRINTK("EXIT\n"); | 1380 | DPRINTK("EXIT\n"); |
1365 | } | 1381 | } |
1366 | 1382 | ||
@@ -1483,6 +1499,9 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1483 | ata_reset_fn_t reset; | 1499 | ata_reset_fn_t reset; |
1484 | int i, did_followup_srst, rc; | 1500 | int i, did_followup_srst, rc; |
1485 | 1501 | ||
1502 | /* about to reset */ | ||
1503 | ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK); | ||
1504 | |||
1486 | /* Determine which reset to use and record in ehc->i.action. | 1505 | /* Determine which reset to use and record in ehc->i.action. |
1487 | * prereset() may examine and modify it. | 1506 | * prereset() may examine and modify it. |
1488 | */ | 1507 | */ |
@@ -1531,8 +1550,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1531 | ata_port_printk(ap, KERN_INFO, "%s resetting port\n", | 1550 | ata_port_printk(ap, KERN_INFO, "%s resetting port\n", |
1532 | reset == softreset ? "soft" : "hard"); | 1551 | reset == softreset ? "soft" : "hard"); |
1533 | 1552 | ||
1534 | /* reset */ | 1553 | /* mark that this EH session started with reset */ |
1535 | ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK); | ||
1536 | ehc->i.flags |= ATA_EHI_DID_RESET; | 1554 | ehc->i.flags |= ATA_EHI_DID_RESET; |
1537 | 1555 | ||
1538 | rc = ata_do_reset(ap, reset, classes); | 1556 | rc = ata_do_reset(ap, reset, classes); |
@@ -1595,7 +1613,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1595 | postreset(ap, classes); | 1613 | postreset(ap, classes); |
1596 | 1614 | ||
1597 | /* reset successful, schedule revalidation */ | 1615 | /* reset successful, schedule revalidation */ |
1598 | ata_eh_done(ap, NULL, ATA_EH_RESET_MASK); | 1616 | ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK); |
1599 | ehc->i.action |= ATA_EH_REVALIDATE; | 1617 | ehc->i.action |= ATA_EH_REVALIDATE; |
1600 | } | 1618 | } |
1601 | 1619 | ||
@@ -1848,15 +1866,16 @@ static int ata_eh_skip_recovery(struct ata_port *ap) | |||
1848 | for (i = 0; i < ata_port_max_devices(ap); i++) { | 1866 | for (i = 0; i < ata_port_max_devices(ap); i++) { |
1849 | struct ata_device *dev = &ap->device[i]; | 1867 | struct ata_device *dev = &ap->device[i]; |
1850 | 1868 | ||
1851 | if (ata_dev_absent(dev) || ata_dev_ready(dev)) | 1869 | if (!(dev->flags & ATA_DFLAG_SUSPENDED)) |
1852 | break; | 1870 | break; |
1853 | } | 1871 | } |
1854 | 1872 | ||
1855 | if (i == ata_port_max_devices(ap)) | 1873 | if (i == ata_port_max_devices(ap)) |
1856 | return 1; | 1874 | return 1; |
1857 | 1875 | ||
1858 | /* always thaw frozen port and recover failed devices */ | 1876 | /* thaw frozen port, resume link and recover failed devices */ |
1859 | if (ap->pflags & ATA_PFLAG_FROZEN || ata_port_nr_enabled(ap)) | 1877 | if ((ap->pflags & ATA_PFLAG_FROZEN) || |
1878 | (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_port_nr_enabled(ap)) | ||
1860 | return 0; | 1879 | return 0; |
1861 | 1880 | ||
1862 | /* skip if class codes for all vacant slots are ATA_DEV_NONE */ | 1881 | /* skip if class codes for all vacant slots are ATA_DEV_NONE */ |