aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-eh.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-11-01 04:39:27 -0500
committerJeff Garzik <jeff@garzik.org>2006-12-01 22:41:31 -0500
commitbaa1e78a834c917984a4659fd282f712c17ee3bf (patch)
tree6c8035d6d49752f7ea81696fa6e61c424b29589c /drivers/ata/libata-eh.c
parentefdaedc443e935eda82e9e78a6e65d1f993d242f (diff)
[PATCH] libata: implement ATA_EHI_SETMODE and ATA_EHI_POST_SETMODE
libata EH used to perform ata_set_mode() iff the EH session performed reset as indicated by ATA_EHI_DID_RESET. This is incorrect because ->dev_config() called by revalidation is allowed to modify transfer mode which ata_set_mode() should take care of. This patch implements the following two flags. * ATA_EHI_SETMODE: set during EH to schedule ata_set_mode(). Both new device attachment and revalidation set this flag. * ATA_EHI_POST_SETMODE: set while the device is revalidated after ata_set_mode(). Post-setmode revalidation is different from initial configuaration and EH revalidation in that ->dev_config() is not allowed tune transfer mode. LLD can use this flag to determine whether it's allowed to tune transfer mode. Note that POST_SETMODE ->dev_config() is guaranteed to be preceded by non-POST_SETMODE ->dev_config(). Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r--drivers/ata/libata-eh.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7c446442616c..477648801a65 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1653,6 +1653,11 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
1653 1653
1654 ata_eh_done(ap, dev, ATA_EH_REVALIDATE); 1654 ata_eh_done(ap, dev, ATA_EH_REVALIDATE);
1655 1655
1656 /* Configuration may have changed, reconfigure
1657 * transfer mode.
1658 */
1659 ehc->i.flags |= ATA_EHI_SETMODE;
1660
1656 /* schedule the scsi_rescan_device() here */ 1661 /* schedule the scsi_rescan_device() here */
1657 queue_work(ata_aux_wq, &(ap->scsi_rescan_task)); 1662 queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
1658 } else if (dev->class == ATA_DEV_UNKNOWN && 1663 } else if (dev->class == ATA_DEV_UNKNOWN &&
@@ -1675,6 +1680,9 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
1675 spin_lock_irqsave(ap->lock, flags); 1680 spin_lock_irqsave(ap->lock, flags);
1676 ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; 1681 ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
1677 spin_unlock_irqrestore(ap->lock, flags); 1682 spin_unlock_irqrestore(ap->lock, flags);
1683
1684 /* new device discovered, configure transfer mode */
1685 ehc->i.flags |= ATA_EHI_SETMODE;
1678 } 1686 }
1679 } 1687 }
1680 1688
@@ -1990,13 +1998,14 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
1990 if (rc) 1998 if (rc)
1991 goto dev_fail; 1999 goto dev_fail;
1992 2000
1993 /* configure transfer mode if the port has been reset */ 2001 /* configure transfer mode if necessary */
1994 if (ehc->i.flags & ATA_EHI_DID_RESET) { 2002 if (ehc->i.flags & ATA_EHI_SETMODE) {
1995 rc = ata_set_mode(ap, &dev); 2003 rc = ata_set_mode(ap, &dev);
1996 if (rc) { 2004 if (rc) {
1997 down_xfermask = 1; 2005 down_xfermask = 1;
1998 goto dev_fail; 2006 goto dev_fail;
1999 } 2007 }
2008 ehc->i.flags &= ~ATA_EHI_SETMODE;
2000 } 2009 }
2001 2010
2002 /* suspend devices */ 2011 /* suspend devices */