--- /dev/null
+From e47f8976d8e573928824a06748f7bc82c58d747f Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bvanassche@acm.org>
+Date: Fri, 24 Aug 2012 09:08:41 +0000
+Subject: SCSI: scsi_dh_alua: Enable STPG for unavailable ports
+
+From: Bart Van Assche <bvanassche@acm.org>
+
+commit e47f8976d8e573928824a06748f7bc82c58d747f upstream.
+
+A quote from SPC-4: "While in the unavailable primary target port
+asymmetric access state, the device server shall support those of
+the following commands that it supports while in the active/optimized
+state: [ ... ] d) SET TARGET PORT GROUPS; [ ... ]". Hence enable
+sending STPG to a target port group that is in the unavailable state.
+
+Signed-off-by: Bart Van Assche <bvanassche@acm.org>
+Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
+Acked-by: Hannes Reinecke <hare@suse.de>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/device_handler/scsi_dh_alua.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/scsi/device_handler/scsi_dh_alua.c
++++ b/drivers/scsi/device_handler/scsi_dh_alua.c
+@@ -583,8 +583,7 @@ static int alua_rtpg(struct scsi_device
+ h->state = TPGS_STATE_STANDBY;
+ break;
+ case TPGS_STATE_OFFLINE:
+- case TPGS_STATE_UNAVAILABLE:
+- /* Path unusable for unavailable/offline */
++ /* Path unusable */
+ err = SCSI_DH_DEV_OFFLINED;
+ break;
+ default:
--- /dev/null
+From bc3f02a795d3b4faa99d37390174be2a75d091bd Mon Sep 17 00:00:00 2001
+From: Dan Williams <djbw@fb.com>
+Date: Tue, 28 Aug 2012 22:12:10 -0700
+Subject: SCSI: scsi_remove_target: fix softlockup regression on hot remove
+
+From: Dan Williams <djbw@fb.com>
+
+commit bc3f02a795d3b4faa99d37390174be2a75d091bd upstream.
+
+John reports:
+ BUG: soft lockup - CPU#2 stuck for 23s! [kworker/u:8:2202]
+ [..]
+ Call Trace:
+ [<ffffffff8141782a>] scsi_remove_target+0xda/0x1f0
+ [<ffffffff81421de5>] sas_rphy_remove+0x55/0x60
+ [<ffffffff81421e01>] sas_rphy_delete+0x11/0x20
+ [<ffffffff81421e35>] sas_port_delete+0x25/0x160
+ [<ffffffff814549a3>] mptsas_del_end_device+0x183/0x270
+
+...introduced by commit 3b661a9 "[SCSI] fix hot unplug vs async scan race".
+
+Don't restart lookup of more stargets in the multi-target case, just
+arrange to traverse the list once, on the assumption that new targets
+are always added at the end. There is no guarantee that the target will
+change state in scsi_target_reap() so we can end up spinning if we
+restart.
+
+Acked-by: Jack Wang <jack_wang@usish.com>
+LKML-Reference: <CAEhu1-6wq1YsNiscGMwP4ud0Q+MrViRzv=kcWCQSBNc8c68N5Q@mail.gmail.com>
+Reported-by: John Drescher <drescherjm@gmail.com>
+Tested-by: John Drescher <drescherjm@gmail.com>
+Signed-off-by: Dan Williams <djbw@fb.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/scsi_sysfs.c | 30 ++++++++++++++----------------
+ 1 file changed, 14 insertions(+), 16 deletions(-)
+
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -1023,33 +1023,31 @@ static void __scsi_remove_target(struct
+ void scsi_remove_target(struct device *dev)
+ {
+ struct Scsi_Host *shost = dev_to_shost(dev->parent);
+- struct scsi_target *starget, *found;
++ struct scsi_target *starget, *last = NULL;
+ unsigned long flags;
+
+- restart:
+- found = NULL;
++ /* remove targets being careful to lookup next entry before
++ * deleting the last
++ */
+ spin_lock_irqsave(shost->host_lock, flags);
+ list_for_each_entry(starget, &shost->__targets, siblings) {
+ if (starget->state == STARGET_DEL)
+ continue;
+ if (starget->dev.parent == dev || &starget->dev == dev) {
+- found = starget;
+- found->reap_ref++;
+- break;
++ /* assuming new targets arrive at the end */
++ starget->reap_ref++;
++ spin_unlock_irqrestore(shost->host_lock, flags);
++ if (last)
++ scsi_target_reap(last);
++ last = starget;
++ __scsi_remove_target(starget);
++ spin_lock_irqsave(shost->host_lock, flags);
+ }
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+- if (found) {
+- __scsi_remove_target(found);
+- scsi_target_reap(found);
+- /* in the case where @dev has multiple starget children,
+- * continue removing.
+- *
+- * FIXME: does such a case exist?
+- */
+- goto restart;
+- }
++ if (last)
++ scsi_target_reap(last);
+ }
+ EXPORT_SYMBOL(scsi_remove_target);
+