diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/scsi_scan.c | 20 | ||||
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 9 |
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 | ||
1467 | void scsi_forget_host(struct Scsi_Host *shost) | 1467 | void 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); |