diff options
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r-- | drivers/ata/libata-eh.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 5d687d7cffae..32da9a93ce44 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -603,13 +603,13 @@ void ata_scsi_error(struct Scsi_Host *host) | |||
603 | ata_link_for_each_dev(dev, link) { | 603 | ata_link_for_each_dev(dev, link) { |
604 | int devno = dev->devno; | 604 | int devno = dev->devno; |
605 | 605 | ||
606 | if (!ata_dev_enabled(dev)) | ||
607 | continue; | ||
608 | |||
606 | ehc->saved_xfer_mode[devno] = dev->xfer_mode; | 609 | ehc->saved_xfer_mode[devno] = dev->xfer_mode; |
607 | if (ata_ncq_enabled(dev)) | 610 | if (ata_ncq_enabled(dev)) |
608 | ehc->saved_ncq_enabled |= 1 << devno; | 611 | ehc->saved_ncq_enabled |= 1 << devno; |
609 | } | 612 | } |
610 | |||
611 | /* set last reset timestamp to some time in the past */ | ||
612 | ehc->last_reset = jiffies - 60 * HZ; | ||
613 | } | 613 | } |
614 | 614 | ||
615 | ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; | 615 | ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; |
@@ -1161,6 +1161,7 @@ void ata_eh_detach_dev(struct ata_device *dev) | |||
1161 | { | 1161 | { |
1162 | struct ata_link *link = dev->link; | 1162 | struct ata_link *link = dev->link; |
1163 | struct ata_port *ap = link->ap; | 1163 | struct ata_port *ap = link->ap; |
1164 | struct ata_eh_context *ehc = &link->eh_context; | ||
1164 | unsigned long flags; | 1165 | unsigned long flags; |
1165 | 1166 | ||
1166 | ata_dev_disable(dev); | 1167 | ata_dev_disable(dev); |
@@ -1174,9 +1175,11 @@ void ata_eh_detach_dev(struct ata_device *dev) | |||
1174 | ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; | 1175 | ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; |
1175 | } | 1176 | } |
1176 | 1177 | ||
1177 | /* clear per-dev EH actions */ | 1178 | /* clear per-dev EH info */ |
1178 | ata_eh_clear_action(link, dev, &link->eh_info, ATA_EH_PERDEV_MASK); | 1179 | ata_eh_clear_action(link, dev, &link->eh_info, ATA_EH_PERDEV_MASK); |
1179 | ata_eh_clear_action(link, dev, &link->eh_context.i, ATA_EH_PERDEV_MASK); | 1180 | ata_eh_clear_action(link, dev, &link->eh_context.i, ATA_EH_PERDEV_MASK); |
1181 | ehc->saved_xfer_mode[dev->devno] = 0; | ||
1182 | ehc->saved_ncq_enabled &= ~(1 << dev->devno); | ||
1180 | 1183 | ||
1181 | spin_unlock_irqrestore(ap->lock, flags); | 1184 | spin_unlock_irqrestore(ap->lock, flags); |
1182 | } | 1185 | } |
@@ -2275,17 +2278,21 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
2275 | if (link->flags & ATA_LFLAG_NO_SRST) | 2278 | if (link->flags & ATA_LFLAG_NO_SRST) |
2276 | softreset = NULL; | 2279 | softreset = NULL; |
2277 | 2280 | ||
2278 | now = jiffies; | 2281 | /* make sure each reset attemp is at least COOL_DOWN apart */ |
2279 | deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN); | 2282 | if (ehc->i.flags & ATA_EHI_DID_RESET) { |
2280 | if (time_before(now, deadline)) | 2283 | now = jiffies; |
2281 | schedule_timeout_uninterruptible(deadline - now); | 2284 | WARN_ON(time_after(ehc->last_reset, now)); |
2285 | deadline = ata_deadline(ehc->last_reset, | ||
2286 | ATA_EH_RESET_COOL_DOWN); | ||
2287 | if (time_before(now, deadline)) | ||
2288 | schedule_timeout_uninterruptible(deadline - now); | ||
2289 | } | ||
2282 | 2290 | ||
2283 | spin_lock_irqsave(ap->lock, flags); | 2291 | spin_lock_irqsave(ap->lock, flags); |
2284 | ap->pflags |= ATA_PFLAG_RESETTING; | 2292 | ap->pflags |= ATA_PFLAG_RESETTING; |
2285 | spin_unlock_irqrestore(ap->lock, flags); | 2293 | spin_unlock_irqrestore(ap->lock, flags); |
2286 | 2294 | ||
2287 | ata_eh_about_to_do(link, NULL, ATA_EH_RESET); | 2295 | ata_eh_about_to_do(link, NULL, ATA_EH_RESET); |
2288 | ehc->last_reset = jiffies; | ||
2289 | 2296 | ||
2290 | ata_link_for_each_dev(dev, link) { | 2297 | ata_link_for_each_dev(dev, link) { |
2291 | /* If we issue an SRST then an ATA drive (not ATAPI) | 2298 | /* If we issue an SRST then an ATA drive (not ATAPI) |
@@ -2373,7 +2380,6 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
2373 | /* | 2380 | /* |
2374 | * Perform reset | 2381 | * Perform reset |
2375 | */ | 2382 | */ |
2376 | ehc->last_reset = jiffies; | ||
2377 | if (ata_is_host_link(link)) | 2383 | if (ata_is_host_link(link)) |
2378 | ata_eh_freeze_port(ap); | 2384 | ata_eh_freeze_port(ap); |
2379 | 2385 | ||
@@ -2385,6 +2391,7 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
2385 | reset == softreset ? "soft" : "hard"); | 2391 | reset == softreset ? "soft" : "hard"); |
2386 | 2392 | ||
2387 | /* mark that this EH session started with reset */ | 2393 | /* mark that this EH session started with reset */ |
2394 | ehc->last_reset = jiffies; | ||
2388 | if (reset == hardreset) | 2395 | if (reset == hardreset) |
2389 | ehc->i.flags |= ATA_EHI_DID_HARDRESET; | 2396 | ehc->i.flags |= ATA_EHI_DID_HARDRESET; |
2390 | else | 2397 | else |
@@ -2529,7 +2536,7 @@ int ata_eh_reset(struct ata_link *link, int classify, | |||
2529 | ata_eh_done(link, NULL, ATA_EH_RESET); | 2536 | ata_eh_done(link, NULL, ATA_EH_RESET); |
2530 | if (slave) | 2537 | if (slave) |
2531 | ata_eh_done(slave, NULL, ATA_EH_RESET); | 2538 | ata_eh_done(slave, NULL, ATA_EH_RESET); |
2532 | ehc->last_reset = jiffies; | 2539 | ehc->last_reset = jiffies; /* update to completion time */ |
2533 | ehc->i.action |= ATA_EH_REVALIDATE; | 2540 | ehc->i.action |= ATA_EH_REVALIDATE; |
2534 | 2541 | ||
2535 | rc = 0; | 2542 | rc = 0; |
@@ -2787,6 +2794,9 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) | |||
2787 | 2794 | ||
2788 | /* if data transfer is verified, clear DUBIOUS_XFER on ering top */ | 2795 | /* if data transfer is verified, clear DUBIOUS_XFER on ering top */ |
2789 | ata_link_for_each_dev(dev, link) { | 2796 | ata_link_for_each_dev(dev, link) { |
2797 | if (!ata_dev_enabled(dev)) | ||
2798 | continue; | ||
2799 | |||
2790 | if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) { | 2800 | if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) { |
2791 | struct ata_ering_entry *ent; | 2801 | struct ata_ering_entry *ent; |
2792 | 2802 | ||
@@ -2808,6 +2818,9 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) | |||
2808 | u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno]; | 2818 | u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno]; |
2809 | u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno)); | 2819 | u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno)); |
2810 | 2820 | ||
2821 | if (!ata_dev_enabled(dev)) | ||
2822 | continue; | ||
2823 | |||
2811 | if (dev->xfer_mode != saved_xfer_mode || | 2824 | if (dev->xfer_mode != saved_xfer_mode || |
2812 | ata_ncq_enabled(dev) != saved_ncq) | 2825 | ata_ncq_enabled(dev) != saved_ncq) |
2813 | dev->flags |= ATA_DFLAG_DUBIOUS_XFER; | 2826 | dev->flags |= ATA_DFLAG_DUBIOUS_XFER; |