aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_scan.c20
-rw-r--r--drivers/scsi/scsi_sysfs.c9
2 files changed, 13 insertions, 16 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index b86f170fa8ed..fcf9f6cbb142 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1466,23 +1466,17 @@ EXPORT_SYMBOL(scsi_scan_single_target);
1466 1466
1467void scsi_forget_host(struct Scsi_Host *shost) 1467void scsi_forget_host(struct Scsi_Host *shost)
1468{ 1468{
1469 struct scsi_target *starget, *tmp; 1469 struct scsi_device *sdev;
1470 unsigned long flags; 1470 unsigned long flags;
1471 1471
1472 /* 1472 restart:
1473 * Ok, this look a bit strange. We always look for the first device
1474 * on the list as scsi_remove_device removes them from it - thus we
1475 * also have to release the lock.
1476 * We don't need to get another reference to the device before
1477 * releasing the lock as we already own the reference from
1478 * scsi_register_device that's release in scsi_remove_device. And
1479 * after that we don't look at sdev anymore.
1480 */
1481 spin_lock_irqsave(shost->host_lock, flags); 1473 spin_lock_irqsave(shost->host_lock, flags);
1482 list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) { 1474 list_for_each_entry(sdev, &shost->__devices, siblings) {
1475 if (sdev->sdev_state == SDEV_DEL)
1476 continue;
1483 spin_unlock_irqrestore(shost->host_lock, flags); 1477 spin_unlock_irqrestore(shost->host_lock, flags);
1484 scsi_remove_target(&starget->dev); 1478 __scsi_remove_device(sdev);
1485 spin_lock_irqsave(shost->host_lock, flags); 1479 goto restart;
1486 } 1480 }
1487 spin_unlock_irqrestore(shost->host_lock, flags); 1481 spin_unlock_irqrestore(shost->host_lock, flags);
1488} 1482}
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 83f87c41b18d..1e47b7eddef4 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -719,17 +719,20 @@ void __scsi_remove_target(struct scsi_target *starget)
719{ 719{
720 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 720 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
721 unsigned long flags; 721 unsigned long flags;
722 struct scsi_device *sdev, *tmp; 722 struct scsi_device *sdev;
723 723
724 spin_lock_irqsave(shost->host_lock, flags); 724 spin_lock_irqsave(shost->host_lock, flags);
725 starget->reap_ref++; 725 starget->reap_ref++;
726 list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) { 726 restart:
727 list_for_each_entry(sdev, &shost->__devices, siblings) {
727 if (sdev->channel != starget->channel || 728 if (sdev->channel != starget->channel ||
728 sdev->id != starget->id) 729 sdev->id != starget->id ||
730 sdev->sdev_state == SDEV_DEL)
729 continue; 731 continue;
730 spin_unlock_irqrestore(shost->host_lock, flags); 732 spin_unlock_irqrestore(shost->host_lock, flags);
731 scsi_remove_device(sdev); 733 scsi_remove_device(sdev);
732 spin_lock_irqsave(shost->host_lock, flags); 734 spin_lock_irqsave(shost->host_lock, flags);
735 goto restart;
733 } 736 }
734 spin_unlock_irqrestore(shost->host_lock, flags); 737 spin_unlock_irqrestore(shost->host_lock, flags);
735 scsi_target_reap(starget); 738 scsi_target_reap(starget);