Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
diff --git a/MAINTAINERS b/MAINTAINERS
index 1fc80ec..77bb086 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1636,6 +1636,15 @@
 W:	http://ldm.sourceforge.net
 S:	Maintained
 
+LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
+P:	Eric Moore
+M:	Eric.Moore@lsil.com
+M:	support@lsil.com
+L:	mpt_linux_developer@lsil.com
+L:	linux-scsi@vger.kernel.org
+W:	http://www.lsilogic.com/support
+S:	Supported
+
 LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers
 P:	Matthew Wilcox
 M:	matthew@wil.cx
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 65c2ec5..4262a22 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1118,6 +1118,65 @@
 	return -1;
 }
 
+int
+mpt_alt_ioc_wait(MPT_ADAPTER *ioc)
+{
+	int loop_count = 30 * 4;  /* Wait 30 seconds */
+	int status = -1; /* -1 means failed to get board READY */
+
+	do {
+		spin_lock(&ioc->initializing_hba_lock);
+		if (ioc->initializing_hba_lock_flag == 0) {
+			ioc->initializing_hba_lock_flag=1;
+			spin_unlock(&ioc->initializing_hba_lock);
+			status = 0;
+			break;
+		}
+		spin_unlock(&ioc->initializing_hba_lock);
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ/4);
+	} while (--loop_count);
+
+	return status;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery
+ *	@ioc: Pointer to MPT adapter structure
+ *	@sleepFlag: Use schedule if CAN_SLEEP else use udelay.
+ *
+ *	This routine performs all the steps necessary to bring the IOC
+ *	to a OPERATIONAL state.
+ *
+ *      Special Note: This function was added with spin lock's so as to allow
+ *      the dv(domain validation) work thread to succeed on the other channel
+ *      that maybe occuring at the same time when this function is called.
+ *      Without this lock, the dv would fail when message frames were
+ *      requested during hba bringup on the alternate ioc.
+ */
+static int
+mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag)
+{
+	int r;
+
+	if(ioc->alt_ioc) {
+		if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0))
+			return r;
+	}
+
+	r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
+	    CAN_SLEEP);
+
+	if(ioc->alt_ioc) {
+		spin_lock(&ioc->alt_ioc->initializing_hba_lock);
+		ioc->alt_ioc->initializing_hba_lock_flag=0;
+		spin_unlock(&ioc->alt_ioc->initializing_hba_lock);
+	}
+
+return r;
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	mpt_attach - Install a PCI intelligent MPT adapter.
@@ -1186,6 +1245,7 @@
 	ioc->pcidev = pdev;
 	ioc->diagPending = 0;
 	spin_lock_init(&ioc->diagLock);
+	spin_lock_init(&ioc->initializing_hba_lock);
 
 	/* Initialize the event logging.
 	 */
@@ -1408,8 +1468,7 @@
 	 */
 	mpt_detect_bound_ports(ioc, pdev);
 
-	if ((r = mpt_do_ioc_recovery(ioc,
-	  MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) {
+	if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){
 		printk(KERN_WARNING MYNAM
 		  ": WARNING - %s did not initialize properly! (%d)\n",
 		  ioc->name, r);
@@ -6298,6 +6357,7 @@
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
 EXPORT_SYMBOL(mptbase_sas_persist_operation);
+EXPORT_SYMBOL(mpt_alt_ioc_wait);
 
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 5f5b3fb..bac8eb4 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -611,6 +611,8 @@
 	int			 DoneCtx;
 	int			 TaskCtx;
 	int			 InternalCtx;
+	spinlock_t		 initializing_hba_lock;
+	int 	 		 initializing_hba_lock_flag;
 	struct list_head	 list;
 	struct net_device	*netdev;
 	struct list_head	 sas_topology;
@@ -1001,6 +1003,7 @@
 extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
 extern int	 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
 extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+extern int	 mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
 
 /*
  *  Public data decl's...
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 4330ed0..b7b9846 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -4162,6 +4162,12 @@
 						}
 					}
 
+					if(mpt_alt_ioc_wait(hd->ioc)!=0) {
+						ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n",
+						    hd->ioc->name));
+						continue;
+					}
+
 					if (mptscsih_doDv(hd, 0, id) == 1) {
 						/* Untagged device was busy, try again
 						 */
@@ -4173,6 +4179,10 @@
 						hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
 					}
 
+					spin_lock(&hd->ioc->initializing_hba_lock);
+					hd->ioc->initializing_hba_lock_flag=0;
+					spin_unlock(&hd->ioc->initializing_hba_lock);
+
 					if (isPhysDisk) {
 						for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
 							if (hd->ioc->raid_data.isRaid & (1 << ii)) {
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index c218b5c..5e84c5a 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -996,6 +996,20 @@
 	spin_lock_init(&adapter->fsf_req_list_lock);
 	INIT_LIST_HEAD(&adapter->fsf_req_list_head);
 
+	/* initialize debug locks */
+
+	spin_lock_init(&adapter->erp_dbf_lock);
+	spin_lock_init(&adapter->hba_dbf_lock);
+	spin_lock_init(&adapter->san_dbf_lock);
+	spin_lock_init(&adapter->scsi_dbf_lock);
+
+	/* initialize error recovery stuff */
+
+	rwlock_init(&adapter->erp_lock);
+	sema_init(&adapter->erp_ready_sem, 0);
+	INIT_LIST_HEAD(&adapter->erp_ready_head);
+	INIT_LIST_HEAD(&adapter->erp_running_head);
+
 	/* initialize abort lock */
 	rwlock_init(&adapter->abort_lock);
 
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 826fb3b..9559971 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -926,7 +926,6 @@
 	char dbf_name[DEBUG_MAX_NAME_LEN];
 
 	/* debug feature area which records recovery activity */
-	spin_lock_init(&adapter->erp_dbf_lock);
 	sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter));
 	adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2,
 					  sizeof(struct zfcp_erp_dbf_record));
@@ -936,7 +935,6 @@
 	debug_set_level(adapter->erp_dbf, 3);
 
 	/* debug feature area which records HBA (FSF and QDIO) conditions */
-	spin_lock_init(&adapter->hba_dbf_lock);
 	sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter));
 	adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1,
 					  sizeof(struct zfcp_hba_dbf_record));
@@ -947,7 +945,6 @@
 	debug_set_level(adapter->hba_dbf, 3);
 
 	/* debug feature area which records SAN command failures and recovery */
-	spin_lock_init(&adapter->san_dbf_lock);
 	sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter));
 	adapter->san_dbf = debug_register(dbf_name, dbfsize, 1,
 					  sizeof(struct zfcp_san_dbf_record));
@@ -958,7 +955,6 @@
 	debug_set_level(adapter->san_dbf, 6);
 
 	/* debug feature area which records SCSI command failures and recovery */
-	spin_lock_init(&adapter->scsi_dbf_lock);
 	sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter));
 	adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1,
 					   sizeof(struct zfcp_scsi_dbf_record));
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 023f4e5..ee7314d 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1071,11 +1071,6 @@
 
 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
 
-	rwlock_init(&adapter->erp_lock);
-	INIT_LIST_HEAD(&adapter->erp_ready_head);
-	INIT_LIST_HEAD(&adapter->erp_running_head);
-	sema_init(&adapter->erp_ready_sem, 0);
-
 	retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD);
 	if (retval < 0) {
 		ZFCP_LOG_NORMAL("error: creation of erp thread failed for "
@@ -2248,29 +2243,26 @@
 	return retval;
 }
 
-/*
- * function:    zfcp_fsf_init
- *
- * purpose:	initializes FSF operation for the specified adapter
- *
- * returns:	0 - succesful initialization of FSF operation
- *		!0 - failed to initialize FSF operation
- */
 static int
 zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
 {
-	int xconfig, xport;
+	int retval;
 
-	if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
-			     &erp_action->adapter->status)) {
+	if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+			      &erp_action->adapter->status)) &&
+	    (erp_action->adapter->adapter_features &
+	     FSF_FEATURE_HBAAPI_MANAGEMENT)) {
 		zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
 		atomic_set(&erp_action->adapter->erp_counter, 0);
 		return ZFCP_ERP_FAILED;
 	}
 
-	xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
-	xport   = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
-	if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED))
+	retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
+	if (retval == ZFCP_ERP_FAILED)
+		return ZFCP_ERP_FAILED;
+
+	retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
+	if (retval == ZFCP_ERP_FAILED)
 		return ZFCP_ERP_FAILED;
 
 	return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
@@ -2359,41 +2351,29 @@
 static int
 zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
 {
-	int retval = ZFCP_ERP_SUCCEEDED;
+	int ret;
 	int retries;
 	int sleep;
 	struct zfcp_adapter *adapter = erp_action->adapter;
 
 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
 
-	for (retries = 0; ; retries++) {
-		ZFCP_LOG_DEBUG("Doing exchange port data\n");
+	retries = 0;
+	do {
+		write_lock(&adapter->erp_lock);
 		zfcp_erp_action_to_running(erp_action);
+		write_unlock(&adapter->erp_lock);
 		zfcp_erp_timeout_init(erp_action);
-		if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) {
-			retval = ZFCP_ERP_FAILED;
-			debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
-			ZFCP_LOG_INFO("error: initiation of exchange of "
-				      "port data failed for adapter %s\n",
-				      zfcp_get_busid_by_adapter(adapter));
-			break;
+		ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
+		if (ret == -EOPNOTSUPP) {
+			debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
+			return ZFCP_ERP_SUCCEEDED;
+		} else if (ret) {
+			debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
+			return ZFCP_ERP_FAILED;
 		}
-		debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok");
-		ZFCP_LOG_DEBUG("Xchange underway\n");
+		debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
 
-		/*
-		 * Why this works:
-		 * Both the normal completion handler as well as the timeout
-		 * handler will do an 'up' when the 'exchange port data'
-		 * request completes or times out. Thus, the signal to go on
-		 * won't be lost utilizing this semaphore.
-		 * Furthermore, this 'adapter_reopen' action is
-		 * guaranteed to be the only action being there (highest action
-		 * which prevents other actions from being created).
-		 * Resulting from that, the wake signal recognized here
-		 * _must_ be the one belonging to the 'exchange port
-		 * data' request.
-		 */
 		down(&adapter->erp_ready_sem);
 		if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
 			ZFCP_LOG_INFO("error: exchange of port data "
@@ -2401,29 +2381,19 @@
 				      zfcp_get_busid_by_adapter(adapter));
 			break;
 		}
-
 		if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
 				      &adapter->status))
 			break;
 
-		ZFCP_LOG_DEBUG("host connection still initialising... "
-			       "waiting and retrying...\n");
-		/* sleep a little bit before retry */
-		sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ?
-				ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP :
-				ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
-		msleep(jiffies_to_msecs(sleep));
-	}
+		if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) {
+			sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP;
+			retries++;
+		} else
+			sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
+		schedule_timeout(sleep);
+	} while (1);
 
-	if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
-			     &adapter->status)) {
-		ZFCP_LOG_INFO("error: exchange of port data for "
-			      "adapter %s failed\n",
-			      zfcp_get_busid_by_adapter(adapter));
-		retval = ZFCP_ERP_FAILED;
-	}
-
-	return retval;
+	return ZFCP_ERP_SUCCEEDED;
 }
 
 /*
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 3b0fc11..5958795 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -554,6 +554,17 @@
 zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
 			     struct fsf_link_down_info *link_down)
 {
+	if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+	                     &adapter->status))
+		return;
+
+	atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
+
+	if (link_down == NULL) {
+		zfcp_erp_adapter_reopen(adapter, 0);
+		return;
+	}
+
 	switch (link_down->error_code) {
 	case FSF_PSQ_LINK_NO_LIGHT:
 		ZFCP_LOG_NORMAL("The local link to adapter %s is down "
@@ -634,20 +645,15 @@
 				link_down->explanation_code,
 				link_down->vendor_specific_code);
 
-	if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
-			      &adapter->status)) {
-		atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
-				&adapter->status);
-		switch (link_down->error_code) {
-		case FSF_PSQ_LINK_NO_LIGHT:
-		case FSF_PSQ_LINK_WRAP_PLUG:
-		case FSF_PSQ_LINK_NO_FCP:
-		case FSF_PSQ_LINK_FIRMWARE_UPDATE:
-			zfcp_erp_adapter_reopen(adapter, 0);
-			break;
-		default:
-			zfcp_erp_adapter_failed(adapter);
-		}
+	switch (link_down->error_code) {
+	case FSF_PSQ_LINK_NO_LIGHT:
+	case FSF_PSQ_LINK_WRAP_PLUG:
+	case FSF_PSQ_LINK_NO_FCP:
+	case FSF_PSQ_LINK_FIRMWARE_UPDATE:
+		zfcp_erp_adapter_reopen(adapter, 0);
+		break;
+	default:
+		zfcp_erp_adapter_failed(adapter);
 	}
 }
 
@@ -919,30 +925,36 @@
 		case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
 			ZFCP_LOG_INFO("Physical link to adapter %s is down\n",
 				      zfcp_get_busid_by_adapter(adapter));
+			zfcp_fsf_link_down_info_eval(adapter,
+				(struct fsf_link_down_info *)
+				&status_buffer->payload);
 			break;
 		case FSF_STATUS_READ_SUB_FDISC_FAILED:
 			ZFCP_LOG_INFO("Local link to adapter %s is down "
 				      "due to failed FDISC login\n",
-			      zfcp_get_busid_by_adapter(adapter));
+				      zfcp_get_busid_by_adapter(adapter));
+			zfcp_fsf_link_down_info_eval(adapter,
+				(struct fsf_link_down_info *)
+				&status_buffer->payload);
 			break;
 		case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
 			ZFCP_LOG_INFO("Local link to adapter %s is down "
 				      "due to firmware update on adapter\n",
 				      zfcp_get_busid_by_adapter(adapter));
+			zfcp_fsf_link_down_info_eval(adapter, NULL);
 			break;
 		default:
 			ZFCP_LOG_INFO("Local link to adapter %s is down "
 				      "due to unknown reason\n",
 				      zfcp_get_busid_by_adapter(adapter));
+			zfcp_fsf_link_down_info_eval(adapter, NULL);
 		};
-		zfcp_fsf_link_down_info_eval(adapter,
-			(struct fsf_link_down_info *) &status_buffer->payload);
 		break;
 
 	case FSF_STATUS_READ_LINK_UP:
 		ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. "
-			      "Restarting operations on this adapter\n",
-			      zfcp_get_busid_by_adapter(adapter));
+				"Restarting operations on this adapter\n",
+				zfcp_get_busid_by_adapter(adapter));
 		/* All ports should be marked as ready to run again */
 		zfcp_erp_modify_adapter_status(adapter,
 					       ZFCP_STATUS_COMMON_RUNNING,
@@ -2191,13 +2203,10 @@
                 return -EOPNOTSUPP;
         }
 
-	timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
-	if (!timer)
-		return -ENOMEM;
-
 	/* setup new FSF request */
 	retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
-                                     0, 0, &lock_flags, &fsf_req);
+				     erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0,
+				     0, &lock_flags, &fsf_req);
 	if (retval < 0) {
 		ZFCP_LOG_INFO("error: Out of resources. Could not create an "
                               "exchange port data request for"
@@ -2205,25 +2214,33 @@
 			      zfcp_get_busid_by_adapter(adapter));
 		write_unlock_irqrestore(&adapter->request_queue.queue_lock,
 					lock_flags);
-		goto out;
-	}
-
-	if (erp_action) {
-		erp_action->fsf_req = fsf_req;
-		fsf_req->erp_action = erp_action;
+		return retval;
 	}
 
 	if (data)
-	fsf_req->data = (unsigned long) data;
+		fsf_req->data = (unsigned long) data;
 
 	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
         sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
         sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
 
-	init_timer(timer);
-	timer->function = zfcp_fsf_request_timeout_handler;
-	timer->data = (unsigned long) adapter;
-	timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
+	if (erp_action) {
+		erp_action->fsf_req = fsf_req;
+		fsf_req->erp_action = erp_action;
+		timer = &erp_action->timer;
+	} else {
+		timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC);
+		if (!timer) {
+			write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+						lock_flags);
+			zfcp_fsf_req_free(fsf_req);
+			return -ENOMEM;
+		}
+		init_timer(timer);
+		timer->function = zfcp_fsf_request_timeout_handler;
+		timer->data = (unsigned long) adapter;
+		timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
+	}
 
 	retval = zfcp_fsf_req_send(fsf_req, timer);
 	if (retval) {
@@ -2233,23 +2250,22 @@
 		zfcp_fsf_req_free(fsf_req);
 		if (erp_action)
 			erp_action->fsf_req = NULL;
+		else
+			kfree(timer);
 		write_unlock_irqrestore(&adapter->request_queue.queue_lock,
 					lock_flags);
-		goto out;
+		return retval;
 	}
 
-	ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n",
-		       zfcp_get_busid_by_adapter(adapter));
+	write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
 
-	write_unlock_irqrestore(&adapter->request_queue.queue_lock,
-				lock_flags);
-
-	wait_event(fsf_req->completion_wq,
-		   fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
-	del_timer_sync(timer);
-	zfcp_fsf_req_free(fsf_req);
- out:
-	kfree(timer);
+	if (!erp_action) {
+		wait_event(fsf_req->completion_wq,
+			   fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+		del_timer_sync(timer);
+		zfcp_fsf_req_free(fsf_req);
+		kfree(timer);
+	}
 	return retval;
 }
 
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 3dcd1bf..66608d1 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -179,7 +179,7 @@
 	struct zfcp_adapter *adapter;
 	struct zfcp_unit *unit;
 	unsigned long flags;
-	int retval = -ENODEV;
+	int retval = -ENXIO;
 
 	adapter = (struct zfcp_adapter *) sdp->host->hostdata[0];
 	if (!adapter)
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index ab383d1..3cb68af 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -325,6 +325,8 @@
 	 *	translations ( 64/32, 128/32, 255/63 ).
 	 */
 	buf = scsi_bios_ptable(bdev);
+	if (!buf)
+		return 0;
 	if(*(__le16 *)(buf + 0x40) == cpu_to_le16(0xaa55)) {
 		struct partition *first = (struct partition * )buf;
 		struct partition *entry = first;
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 31e9f40..6aab9da 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -2105,7 +2105,7 @@
 					  scmd_id(cmd),
 					  scmd_channel(cmd) + 'A',
 					  CAM_LUN_WILDCARD,
-					  SCB_LIST_NULL, ROLE_INITIATOR) == 0)
+					  SCB_LIST_NULL, ROLE_INITIATOR))
 				break;
 		}
 	}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 7fc6454..d866213 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -2169,7 +2169,7 @@
 		  	if (ahc_match_scb(ahc, pending_scb, scmd_id(cmd),
 					  scmd_channel(cmd) + 'A',
 					  CAM_LUN_WILDCARD,
-					  SCB_LIST_NULL, ROLE_INITIATOR) == 0)
+					  SCB_LIST_NULL, ROLE_INITIATOR))
 				break;
 		}
 	}
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 718a2bc..38a53b5 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -812,12 +812,10 @@
 	if (!scsi_device_sync(sdev) && !scsi_device_dt(sdev))
 		return;
 
-	/* see if the device has an echo buffer.  If it does we can
-	 * do the SPI pattern write tests */
-
-	len = 0;
-	if (scsi_device_dt(sdev))
-		len = spi_dv_device_get_echo_buffer(sdev, buffer);
+	/* len == -1 is the signal that we need to ascertain the
+	 * presence of an echo buffer before trying to use it.  len ==
+	 * 0 means we don't have an echo buffer */
+	len = -1;
 
  retry:
 
@@ -840,11 +838,23 @@
 		if (spi_min_period(starget) == 8)
 			DV_SET(pcomp_en, 1);
 	}
+	/* Do the read only INQUIRY tests */
+	spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len,
+		       spi_dv_device_compare_inquiry);
+	/* See if we actually managed to negotiate and sustain DT */
+	if (i->f->get_dt)
+		i->f->get_dt(starget);
 
-	if (len == 0) {
+	/* see if the device has an echo buffer.  If it does we can do
+	 * the SPI pattern write tests.  Because of some broken
+	 * devices, we *only* try this on a device that has actually
+	 * negotiated DT */
+
+	if (len == -1 && spi_dt(starget))
+		len = spi_dv_device_get_echo_buffer(sdev, buffer);
+
+	if (len <= 0) {
 		starget_printk(KERN_INFO, starget, "Domain Validation skipping write tests\n");
-		spi_dv_retrain(sdev, buffer, buffer + len,
-			       spi_dv_device_compare_inquiry);
 		return;
 	}
 
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 72ec594..b55c2a8 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1860,9 +1860,11 @@
 	   unlock_page(pages[j]); */
 	res = 0;
  out_unmap:
-	if (res > 0)
+	if (res > 0) {
 		for (j=0; j < res; j++)
 			page_cache_release(pages[j]);
+		res = 0;
+	}
 	kfree(pages);
 	return res;
 }
@@ -1878,8 +1880,6 @@
 	for (i=0; i < nr_pages; i++) {
 		struct page *page = sgl[i].page;
 
-		/* XXX: just for debug. Remove when PageReserved is removed */
-		BUG_ON(PageReserved(page));
 		if (dirtied)
 			SetPageDirty(page);
 		/* unlock_page(page); */
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 770c432..7ac6ea1 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4509,6 +4509,7 @@
 	if (res > 0) {
 		for (j=0; j < res; j++)
 			page_cache_release(pages[j]);
+		res = 0;
 	}
 	kfree(pages);
 	return res;
@@ -4524,8 +4525,6 @@
 	for (i=0; i < nr_pages; i++) {
 		struct page *page = sgl[i].page;
 
-		/* XXX: just for debug. Remove when PageReserved is removed */
-		BUG_ON(PageReserved(page));
 		if (dirtied)
 			SetPageDirty(page);
 		/* FIXME: cache flush missing for rw==READ
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index d76766c..7fc0b97 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -2086,6 +2086,7 @@
 	tp->tgoal.check_nego = 1;
 }
 
+#if 0
 static void sym2_set_iu(struct scsi_target *starget, int iu)
 {
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -2111,7 +2112,7 @@
 		tp->tgoal.qas = 0;
 	tp->tgoal.check_nego = 1;
 }
-
+#endif
 
 static struct spi_function_template sym2_transport_functions = {
 	.set_offset	= sym2_set_offset,
@@ -2122,10 +2123,12 @@
 	.show_width	= 1,
 	.set_dt		= sym2_set_dt,
 	.show_dt	= 1,
+#if 0
 	.set_iu		= sym2_set_iu,
 	.show_iu	= 1,
 	.set_qas	= sym2_set_qas,
 	.show_qas	= 1,
+#endif
 	.get_signalling	= sym2_get_signalling,
 };