aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libata-eh.c33
-rw-r--r--include/linux/libata.h4
2 files changed, 31 insertions, 6 deletions
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 1dcb2c13ffa9..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,
790static void ata_eh_done(struct ata_port *ap, struct ata_device *dev, 805static 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
@@ -1478,6 +1499,9 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
1478 ata_reset_fn_t reset; 1499 ata_reset_fn_t reset;
1479 int i, did_followup_srst, rc; 1500 int i, did_followup_srst, rc;
1480 1501
1502 /* about to reset */
1503 ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
1504
1481 /* Determine which reset to use and record in ehc->i.action. 1505 /* Determine which reset to use and record in ehc->i.action.
1482 * prereset() may examine and modify it. 1506 * prereset() may examine and modify it.
1483 */ 1507 */
@@ -1526,8 +1550,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
1526 ata_port_printk(ap, KERN_INFO, "%s resetting port\n", 1550 ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
1527 reset == softreset ? "soft" : "hard"); 1551 reset == softreset ? "soft" : "hard");
1528 1552
1529 /* reset */ 1553 /* mark that this EH session started with reset */
1530 ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
1531 ehc->i.flags |= ATA_EHI_DID_RESET; 1554 ehc->i.flags |= ATA_EHI_DID_RESET;
1532 1555
1533 rc = ata_do_reset(ap, reset, classes); 1556 rc = ata_do_reset(ap, reset, classes);
@@ -1590,7 +1613,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
1590 postreset(ap, classes); 1613 postreset(ap, classes);
1591 1614
1592 /* reset successful, schedule revalidation */ 1615 /* reset successful, schedule revalidation */
1593 ata_eh_done(ap, NULL, ATA_EH_RESET_MASK); 1616 ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
1594 ehc->i.action |= ATA_EH_REVALIDATE; 1617 ehc->i.action |= ATA_EH_REVALIDATE;
1595 } 1618 }
1596 1619
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 6cc497a2b6da..66c3100c2b94 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -265,12 +265,14 @@ enum {
265 265
266 /* ata_eh_info->flags */ 266 /* ata_eh_info->flags */
267 ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ 267 ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */
268 ATA_EHI_RESUME_LINK = (1 << 1), /* need to resume link */ 268 ATA_EHI_RESUME_LINK = (1 << 1), /* resume link (reset modifier) */
269 ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */ 269 ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */
270 ATA_EHI_QUIET = (1 << 3), /* be quiet */ 270 ATA_EHI_QUIET = (1 << 3), /* be quiet */
271 271
272 ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */ 272 ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */
273 273
274 ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
275
274 /* max repeat if error condition is still set after ->error_handler */ 276 /* max repeat if error condition is still set after ->error_handler */
275 ATA_EH_MAX_REPEAT = 5, 277 ATA_EH_MAX_REPEAT = 5,
276 278