ieee1394: sbp2: prevent rare deadlock in shutdown

Scsi_remove_device() may go into uninterruptible sleep if blocked.
Therefore sbp2_remove() unblocks the Scsi_Host before the device is
requested to be removed.  But there could be another 1394 bus reset
after that which would block the host again.  The 1394 subsystem won't
call sbp2_update() concurrently to sbp2_remove(), which is why there is
no chance for sbp2_remove() to be unblocked by sbp2_update().

The fix is to tell sbp2's bus reset handler when a device is to be shut
down so that it skips scsi_block_requests() on that host.  As before,
any new commands after a reset without reconnect will be failed quickly
by sbp2scsi_queuecommand().

In the long term, means to go without scsi_block_requests() should be
found.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 3cb6b47..017259c 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -478,7 +478,7 @@
 	 * There is a small window after a bus reset within which the node
 	 * entry's generation is current but the reconnect wasn't completed.
 	 */
-	if (atomic_read(&scsi_id->unfinished_reset))
+	if (unlikely(atomic_read(&scsi_id->state) == SBP2LU_STATE_IN_RESET))
 		return;
 
 	if (hpsb_node_write(scsi_id->ne,
@@ -489,7 +489,7 @@
 	 * Now accept new SCSI commands, unless a bus reset happended during
 	 * hpsb_node_write.
 	 */
-	if (!atomic_read(&scsi_id->unfinished_reset))
+	if (likely(atomic_read(&scsi_id->state) != SBP2LU_STATE_IN_RESET))
 		scsi_unblock_requests(scsi_id->scsi_host);
 }
 
@@ -756,7 +756,7 @@
 			sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT);
 		/* scsi_remove_device() will trigger shutdown functions of SCSI
 		 * highlevel drivers which would deadlock if blocked. */
-		atomic_set(&scsi_id->unfinished_reset, 0);
+		atomic_set(&scsi_id->state, SBP2LU_STATE_IN_SHUTDOWN);
 		scsi_unblock_requests(scsi_id->scsi_host);
 	}
 	sdev = scsi_id->sdev;
@@ -811,7 +811,7 @@
 	/* Accept new commands unless there was another bus reset in the
 	 * meantime. */
 	if (hpsb_node_entry_valid(scsi_id->ne)) {
-		atomic_set(&scsi_id->unfinished_reset, 0);
+		atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING);
 		scsi_unblock_requests(scsi_id->scsi_host);
 	}
 	return 0;
@@ -842,7 +842,7 @@
 	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
 	INIT_LIST_HEAD(&scsi_id->scsi_list);
 	spin_lock_init(&scsi_id->sbp2_command_orb_lock);
-	atomic_set(&scsi_id->unfinished_reset, 0);
+	atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING);
 	INIT_WORK(&scsi_id->protocol_work, NULL, NULL);
 
 	ud->device.driver_data = scsi_id;
@@ -926,13 +926,14 @@
 	struct scsi_id_instance_data *scsi_id;
 
 	hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
-
-	if (hi) {
-		list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list) {
-			atomic_set(&scsi_id->unfinished_reset, 1);
+	if (!hi)
+		return;
+	list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list)
+		if (likely(atomic_read(&scsi_id->state) !=
+			   SBP2LU_STATE_IN_SHUTDOWN)) {
+			atomic_set(&scsi_id->state, SBP2LU_STATE_IN_RESET);
 			scsi_block_requests(scsi_id->scsi_host);
 		}
-	}
 }
 
 /*
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 34c52bf..abbe48e 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -347,10 +347,17 @@
 	/* Device specific workarounds/brokeness */
 	unsigned workarounds;
 
-	atomic_t unfinished_reset;
+	atomic_t state;
 	struct work_struct protocol_work;
 };
 
+/* For use in scsi_id_instance_data.state */
+enum sbp2lu_state_types {
+	SBP2LU_STATE_RUNNING,		/* all normal */
+	SBP2LU_STATE_IN_RESET,		/* between bus reset and reconnect */
+	SBP2LU_STATE_IN_SHUTDOWN	/* when sbp2_remove was called */
+};
+
 /* Sbp2 host data structure (one per IEEE1394 host) */
 struct sbp2scsi_host_info {
 	struct hpsb_host *host;		/* IEEE1394 host */