aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-07-10 10:18:46 -0400
committerJeff Garzik <jeff@garzik.org>2006-07-19 14:06:53 -0400
commit13abf50df209008b5d44075bafeeab42ace56aa6 (patch)
tree5e8ea48d61c7e58560b04d33609a4a2bc6cf0012
parent7c8c2cff81b2b7f6dd3f9fd7b77033c1be5d7920 (diff)
[PATCH] libata: improve EH action and EHI flag handling
Update ata_eh_about_to_do() and ata_eh_done() to improve EH action and EHI flag handling. * There are two types of EHI flags - one which expires on successful EH and the other which expires on a successful reset. Make this distinction clear. * Unlike other EH actions, reset actions are represented by two EH action masks and a EHI modifier. Implement correct about_to_do/done semantics for resets. That is, prior to reset, related EH info is sucked in from ehi and cleared, and after reset is complete, related EH info in ehc is cleared. These changes improve consistency and remove unnecessary EH actions caused by stale EH action masks and EHI flags. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-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