aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_expander.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-11-17 20:59:51 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-19 14:52:34 -0500
commit87c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2 (patch)
tree4ed0e98760c977010fe54778c1a25625840b4583 /drivers/scsi/libsas/sas_expander.c
parente139942d77a6e3ac83bc322e826668054a8601d6 (diff)
[SCSI] libsas: prevent domain rediscovery competing with ata error handling
libata error handling provides for a timeout for link recovery. libsas must not rescan for previously known devices in this interval otherwise it may remove a device that is simply waiting for its link to recover. Let libata-eh make the determination of when the link is stable and prevent libsas (host workqueue) from taking action while this determination is pending. Using a mutex (ha->disco_mutex) to flush and disable revalidation while eh is running requires any discovery action that may block on eh be moved to its own context outside the lock. Probing ATA devices explicitly waits on ata-eh and the cache-flush-io issued during device removal may also pend awaiting eh completion. Essentially any rphy add/remove activity needs to run outside the lock. This adds two new cleanup states for sas_unregister_domain_devices() 'allocated-but-not-probed', and 'flagged-for-destruction'. In the 'allocated-but-not-probed' state dev->rphy points to a rphy that is known to have not been through a sas_rphy_add() event. At domain teardown check if this device is still pending probe and cleanup accordingly. Similarly if a device has already been queued for removal then sas_unregister_domain_devices has nothing to do. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/libsas/sas_expander.c')
-rw-r--r--drivers/scsi/libsas/sas_expander.c5
1 files changed, 2 insertions, 3 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index f33d0c9911c4..e45b259dac4c 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -704,9 +704,7 @@ static struct domain_device *sas_ex_discover_end_dev(
704 704
705 child->rphy = rphy; 705 child->rphy = rphy;
706 706
707 spin_lock_irq(&parent->port->dev_list_lock); 707 list_add_tail(&child->disco_list_node, &parent->port->disco_list);
708 list_add_tail(&child->dev_list_node, &parent->port->dev_list);
709 spin_unlock_irq(&parent->port->dev_list_lock);
710 708
711 res = sas_discover_sata(child); 709 res = sas_discover_sata(child);
712 if (res) { 710 if (res) {
@@ -756,6 +754,7 @@ static struct domain_device *sas_ex_discover_end_dev(
756 sas_rphy_free(child->rphy); 754 sas_rphy_free(child->rphy);
757 child->rphy = NULL; 755 child->rphy = NULL;
758 756
757 list_del(&child->disco_list_node);
759 spin_lock_irq(&parent->port->dev_list_lock); 758 spin_lock_irq(&parent->port->dev_list_lock);
760 list_del(&child->dev_list_node); 759 list_del(&child->dev_list_node);
761 spin_unlock_irq(&parent->port->dev_list_lock); 760 spin_unlock_irq(&parent->port->dev_list_lock);