From: Brian King <brking@linux.vnet.ibm.com>
Subject: ipr: Fix target id allocation re-use problem
Git-commit: 0ee1d714c285aabaadf7495bf5820114ad0959b1
Patch-mainline: yes
References: bnc#794550,fate#314040

    For the latest ipr SAS adapters, target id's are a completely
    logical construct that are managed in the ipr driver. This fixes
    an issue that can arise if a device is deleted via sysfs. If
    a new device is then physically added, it will use the previous
    device's target id. If the host is then rescanned, the device
    that had been deleted, since it is using the same target id as
    the new device is using, will never be found, resulting in
    a missing device. Fix this by only freeing the target id
    only if the resource is actually gone.
    
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Acked-by: Torsten Duwe <duwe@suse.de>

---
 drivers/scsi/ipr.c |   17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

Index: b/drivers/scsi/ipr.c
===================================================================
--- a/drivers/scsi/ipr.c	2012-12-07 11:13:31.174289707 -0600
+++ b/drivers/scsi/ipr.c	2012-12-07 11:13:58.286404437 -0600
@@ -4339,8 +4339,7 @@ static struct ipr_resource_entry *ipr_fi
 
 	list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
 		if ((res->bus == starget->channel) &&
-		    (res->target == starget->id) &&
-		    (res->lun == 0)) {
+		    (res->target == starget->id)) {
 			return res;
 		}
 	}
@@ -4414,12 +4413,14 @@ static void ipr_target_destroy(struct sc
 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *) shost->hostdata;
 
 	if (ioa_cfg->sis64) {
-		if (starget->channel == IPR_ARRAY_VIRTUAL_BUS)
-			clear_bit(starget->id, ioa_cfg->array_ids);
-		else if (starget->channel == IPR_VSET_VIRTUAL_BUS)
-			clear_bit(starget->id, ioa_cfg->vset_ids);
-		else if (starget->channel == 0)
-			clear_bit(starget->id, ioa_cfg->target_ids);
+		if (!ipr_find_starget(starget)) {
+			if (starget->channel == IPR_ARRAY_VIRTUAL_BUS)
+				clear_bit(starget->id, ioa_cfg->array_ids);
+			else if (starget->channel == IPR_VSET_VIRTUAL_BUS)
+				clear_bit(starget->id, ioa_cfg->vset_ids);
+			else if (starget->channel == 0)
+				clear_bit(starget->id, ioa_cfg->target_ids);
+		}
 	}
 
 	if (sata_port) {
