patch-2.4.25 linux-2.4.25/drivers/message/fusion/mptscsih.c

Next file: linux-2.4.25/drivers/message/fusion/mptscsih.h
Previous file: linux-2.4.25/drivers/message/fusion/mptctl.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.24/drivers/message/fusion/mptscsih.c linux-2.4.25/drivers/message/fusion/mptscsih.c
@@ -24,7 +24,7 @@
  *  Copyright (c) 1999-2002 LSI Logic Corporation
  *  Original author: Steven J. Ralston
  *  (mailto:sjralston1@netscape.net)
- *  (mailto:lstephens@lsil.com)
+ *  (mailto:mpt_linux_developer@lsil.com)
  *
  *  $Id: mptscsih.c,v 1.1.2.4 2003/05/07 14:08:34 pdelaney Exp $
  */
@@ -180,12 +180,13 @@
 static int	mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 static int	mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
-static VirtDevice	*mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
+static void	mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
 void		mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
 static void	mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
 static void	mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
 static void	mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
 static int	mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
+static int	mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
 static int	mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static void	mptscsih_timer_expired(unsigned long data);
 static void	mptscsih_taskmgmt_timeout(unsigned long data);
@@ -438,10 +439,10 @@
 static inline int
 mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
 {
-	MPT_FRAME_HDR *chainBuf = NULL;
+	MPT_FRAME_HDR *chainBuf;
 	unsigned long flags;
-	int rc = FAILED;
-	int chain_idx = MPT_HOST_NO_CHAIN;
+	int rc;
+	int chain_idx;
 
 	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
 	if (!Q_IS_EMPTY(&hd->FreeChainQ)) {
@@ -454,6 +455,10 @@
 		chain_idx = offset / hd->ioc->req_sz;
 		rc = SUCCESS;
 	}
+	else {
+		rc = FAILED;
+		chain_idx = MPT_HOST_NO_CHAIN;
+	}
 	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
 
 
@@ -506,12 +511,13 @@
 	/* Map the data portion, if any.
 	 * sges_left  = 0 if no data transfer.
 	 */
-	sges_left = SCpnt->use_sg;
-	if (SCpnt->use_sg) {
-		sges_left = pci_map_sg(hd->ioc->pcidev,
+	if ( (sges_left = SCpnt->use_sg) ) {
+		if ( (sges_left = pci_map_sg(hd->ioc->pcidev,
 			       (struct scatterlist *) SCpnt->request_buffer,
 			       SCpnt->use_sg,
-			       scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+			       scsi_to_pci_dma_dir(SCpnt->sc_data_direction)))
+			== 0 )
+				return FAILED;
 	} else if (SCpnt->request_bufflen) {
 		dma_addr_t	 buf_dma_addr;
 		scPrivate	*my_priv;
@@ -730,13 +736,6 @@
 
 	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
 
-	if ((mf == NULL) ||
-	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
-		printk(MYIOC_s_ERR_FMT "%s req frame ptr! (=%p)!\n",
-				ioc->name, mf?"BAD":"NULL", (void *) mf);
-		return 0;
-	}
-
 	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
 	sc = hd->ScsiLookup[req_idx];
 	if (sc == NULL) {
@@ -878,7 +877,6 @@
 				mptscsih_no_negotiate(hd, sc->target);
 			break;
 
-		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
 		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
 			/*
 			 *  YIKES!  I just discovered that SCSI IO which
@@ -916,6 +914,9 @@
 			sc->resid = sc->request_bufflen - xfer_cnt;
 			dprintk((KERN_NOTICE "  SET sc->resid=%02xh\n", sc->resid));
 #endif
+			if((xfer_cnt == 0 ) || (sc->underflow > xfer_cnt)) {
+				sc->result = DID_SOFT_ERROR << 16;
+			}
 
 			/* Report Queue Full
 			 */
@@ -1036,6 +1037,7 @@
 		case MPI_IOCSTATUS_INVALID_STATE:		/* 0x0008 */
 		case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:		/* 0x0044 */
 		case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:		/* 0x0046 */
+		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
 		case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:	/* 0x004A */
 		default:
 			/*
@@ -1156,8 +1158,8 @@
 static void
 clean_taskQ(MPT_SCSI_HOST *hd)
 {
-	MPT_FRAME_HDR *mf = NULL;
-	MPT_FRAME_HDR *nextmf = NULL;
+	MPT_FRAME_HDR *mf;
+	MPT_FRAME_HDR *nextmf;
 	MPT_ADAPTER *ioc = hd->ioc;
 	unsigned long flags;
 
@@ -1196,7 +1198,7 @@
 static void
 search_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd)
 {
-	MPT_FRAME_HDR *mf = NULL;
+	MPT_FRAME_HDR *mf;
 	unsigned long flags;
 	int count = 0;
 
@@ -1320,7 +1322,7 @@
 static void
 mptscsih_reset_timeouts (MPT_SCSI_HOST *hd)
 {
-	Scsi_Cmnd	*SCpnt = NULL;
+	Scsi_Cmnd	*SCpnt;
 	int		 ii;
 	int		 max = hd->ioc->req_depth;
 
@@ -1346,9 +1348,9 @@
 static void
 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
 {
-	Scsi_Cmnd	*SCpnt = NULL;
-	MPT_FRAME_HDR	*mf = NULL;
-	MPT_DONE_Q	*buffer = NULL;
+	Scsi_Cmnd	*SCpnt;
+	MPT_FRAME_HDR	*mf;
+	MPT_DONE_Q	*buffer;
 	int		 ii;
 	int		 max = hd->ioc->req_depth;
 
@@ -1457,18 +1459,16 @@
 	/* ReqToChain size must equal the req_depth
 	 * index = req_idx
 	 */
-	sz = hd->ioc->req_depth * sizeof(int);
 	if (hd->ReqToChain == NULL) {
+		sz = hd->ioc->req_depth * sizeof(int);
 		mem = kmalloc(sz, GFP_ATOMIC);
 		if (mem == NULL)
 			return -1;
 
 		hd->ReqToChain = (int *) mem;
-	} else {
-		mem = (u8 *) hd->ReqToChain;
 	}
-	memset(mem, 0xFF, sz);
-
+	for (ii = 0; ii < hd->ioc->req_depth; ii++)
+		hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
 
 	/* ChainToChain size must equal the total number
 	 * of chain buffers to be allocated.
@@ -1606,9 +1606,9 @@
 int
 mptscsih_detect(Scsi_Host_Template *tpnt)
 {
-	struct Scsi_Host	*sh = NULL;
-	MPT_SCSI_HOST		*hd = NULL;
-	MPT_ADAPTER		*this;
+	struct Scsi_Host	*sh;
+	MPT_SCSI_HOST		*hd;
+	MPT_ADAPTER		*ioc;
 	MPT_DONE_Q		*freedoneQ;
 	unsigned long		 flags;
 	int			 sz, ii;
@@ -1651,20 +1651,19 @@
 	atomic_set(&mpt_taskQdepth, 0);
 #endif
 
-	this = mpt_adapter_find_first();
-	while (this != NULL) {
+	for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
 		/* 20010202 -sralston
 		 *  Added sanity check on readiness of the MPT adapter.
 		 */
-		if (this->last_state != MPI_IOC_STATE_OPERATIONAL) {
+		if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
 			printk(MYIOC_s_WARN_FMT "Skipping because it's not operational!\n",
-					this->name);
+					ioc->name);
 			continue;
 		}
 
-		if (!this->active) {
+		if (!ioc->active) {
 			printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
-					this->name);
+					ioc->name);
 			continue;
 		}
 
@@ -1672,14 +1671,14 @@
 		/*  Sanity check - ensure at least 1 port is INITIATOR capable
 		 */
 		ioc_cap = 0;
-		for (ii=0; ii < this->facts.NumberOfPorts; ii++) {
-			if (this->pfacts[ii].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)
+		for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+			if (ioc->pfacts[ii].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)
 				ioc_cap ++;
 		}
 
 		if (!ioc_cap) {
-			printk(MYIOC_s_WARN_FMT "Skipping because SCSI Initiator mode is NOT enabled!\n",
-					this->name);
+			printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
+					ioc->name, ioc);
 			continue;
 		}
 
@@ -1690,7 +1689,7 @@
 		tpnt->proc_info = mptscsih_proc_info;
 		sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST));
 		if (sh != NULL) {
-			spin_lock_irqsave(&this->FreeQlock, flags);
+			spin_lock_irqsave(&ioc->FreeQlock, flags);
 			sh->io_port = 0;
 			sh->n_io_port = 0;
 			sh->irq = 0;
@@ -1705,7 +1704,7 @@
 			 * max_lun = 1 + actual last lun,
 			 *	see hosts.h :o(
 			 */
-			if ((int)this->chip_type > (int)FC929)
+			if ((int)ioc->chip_type > (int)FC929)
 				sh->max_id = MPT_MAX_SCSI_DEVICES;
 			else {
 				/* For FC, increase the queue depth
@@ -1732,7 +1731,7 @@
 			 * and all access to VirtDev
 			 */
 			sh->max_channel = 0;
-			sh->this_id = this->pfacts[0].PortSCSIID;
+			sh->this_id = ioc->pfacts[0].PortSCSIID;
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
 			/* OS entry to allow host drivers to force
@@ -1742,7 +1741,7 @@
 #endif
 			/* Required entry.
 			 */
-			sh->unique_id = this->id;
+			sh->unique_id = ioc->id;
 
 			/* Verify that we won't exceed the maximum
 			 * number of chain buffers
@@ -1753,38 +1752,38 @@
 			 * A slightly different algorithm is required for
 			 * 64bit SGEs.
 			 */
-			scale = this->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
+			scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
 			if (sizeof(dma_addr_t) == sizeof(u64)) {
-				numSGE = (scale - 1) * (this->facts.MaxChainDepth-1) + scale +
-					(this->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
+				numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
+					(ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
 			} else {
-				numSGE = 1 + (scale - 1) * (this->facts.MaxChainDepth-1) + scale +
-					(this->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+				numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
+					(ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
 			}
 
 			if (numSGE < sh->sg_tablesize) {
 				/* Reset this value */
 				dprintk((MYIOC_s_INFO_FMT
 					 "Resetting sg_tablesize to %d from %d\n",
-					 this->name, numSGE, sh->sg_tablesize));
+					 ioc->name, numSGE, sh->sg_tablesize));
 				sh->sg_tablesize = numSGE;
 			}
 
 			/* Set the pci device pointer in Scsi_Host structure.
 			 */
-			scsi_set_pci_device(sh, this->pcidev);
+			scsi_set_pci_device(sh, ioc->pcidev);
 
-			spin_unlock_irqrestore(&this->FreeQlock, flags);
+			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 			hd = (MPT_SCSI_HOST *) sh->hostdata;
-			hd->ioc = this;
+			hd->ioc = ioc;
 			hd->max_sge = sh->sg_tablesize;
 
-			if ((int)this->chip_type > (int)FC929)
+			if ((int)ioc->chip_type > (int)FC929)
 				hd->is_spi = 1;
 
 			if (DmpService &&
-			    (this->chip_type == FC919 || this->chip_type == FC929))
+			    (ioc->chip_type == FC919 || ioc->chip_type == FC929))
 				hd->is_multipath = 1;
 
 			/* SCSI needs Scsi_Cmnd lookup table!
@@ -1799,7 +1798,7 @@
 			hd->ScsiLookup = (struct scsi_cmnd **) mem;
 
 			dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
-				 this->name, hd->ScsiLookup, sz));
+				 ioc->name, hd->ScsiLookup, sz));
 
 			if (mptscsih_initChainBuffers(hd, 1) < 0)
 				goto done;
@@ -1870,7 +1869,7 @@
 
 			/* Attach the SCSI Host to the IOC structure
 			 */
-			this->sh = sh;
+			ioc->sh = sh;
 
 			/* Initialize this SCSI Hosts' timers
 			 * To use, set the timer expires field
@@ -1886,7 +1885,7 @@
 			hd->qtag_tick = jiffies;
 
 			/* Moved Earlier Pam D */
-			/* this->sh = sh;	*/
+			/* ioc->sh = sh;	*/
 
 #ifdef MPTSCSIH_DBG_TIMEOUT
 			hd->ioc->timeout_hard = 0;
@@ -1909,6 +1908,8 @@
 				if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC)
 					hd->ioc->spi_data.maxSyncOffset = 0;
 
+				hd->ioc->spi_data.Saf_Te = driver_setup.saf_te;
+
 				hd->negoNvram = 0;
 #ifdef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
 				hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
@@ -1926,16 +1927,15 @@
 				}
 
 				ddvprintk((MYIOC_s_INFO_FMT
-					"dv %x width %x factor %x \n",
+					"dv %x width %x factor %x saf_te %x\n",
 					hd->ioc->name, driver_setup.dv,
 					driver_setup.max_width,
-					driver_setup.min_sync_fac));
+					driver_setup.min_sync_fac,
+					driver_setup.saf_te));
 			}
 
 			mpt_scsi_hosts++;
 		}
-
-		this = mpt_adapter_find_next(this);
 	}
 
 done:
@@ -2146,8 +2146,8 @@
 static int
 mptscsih_halt(struct notifier_block *nb, ulong event, void *buf)
 {
-	MPT_ADAPTER *ioc = NULL;
-	MPT_SCSI_HOST *hd = NULL;
+	MPT_ADAPTER *ioc;
+	MPT_SCSI_HOST *hd;
 
 	/* Ignore all messages other than reboot message
 	 */
@@ -2182,7 +2182,7 @@
 const char *
 mptscsih_info(struct Scsi_Host *SChost)
 {
-	MPT_SCSI_HOST *h = NULL;
+	MPT_SCSI_HOST *h;
 	int size = 0;
 
 	if (info_kbuf == NULL)
@@ -2398,7 +2398,7 @@
 int mptscsih_proc_info(char *buffer, char **start, off_t offset,
 			int length, int hostno, int func)
 {
-	MPT_ADAPTER	*ioc = NULL;
+	MPT_ADAPTER	*ioc;
 	MPT_SCSI_HOST	*hd = NULL;
 	int size = 0;
 
@@ -2489,7 +2489,7 @@
 	MPT_FRAME_HDR		*mf;
 	SCSIIORequest_t		*pScsiReq;
 	VirtDevice		*pTarget;
-	MPT_DONE_Q		*buffer = NULL;
+	MPT_DONE_Q		*buffer;
 	unsigned long		 flags;
 	int	 target;
 	int	 lun;
@@ -2774,7 +2774,7 @@
 static void
 mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
 {
-	MPT_FRAME_HDR *chain = NULL;
+	MPT_FRAME_HDR *chain;
 	unsigned long flags;
 	int chain_idx;
 	int next;
@@ -2839,7 +2839,7 @@
 static int
 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, int sleepFlag)
 {
-	MPT_ADAPTER	*ioc = NULL;
+	MPT_ADAPTER	*ioc;
 	int		 rc = -1;
 	int		 doTask = 1;
 	u32		 ioc_raw_state;
@@ -3088,7 +3088,6 @@
 		search_doneQ_for_cmd(hd, SCpnt);
 
 		SCpnt->result = DID_RESET << 16;
-		SCpnt->scsi_done(SCpnt);
 		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
 			   "Command not in the active list! (sc=%p)\n",
 			   hd->ioc->name, SCpnt));
@@ -3345,7 +3344,6 @@
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
 		printk(KERN_WARNING "  WARNING - OldAbort, NULL hostdata ptr!!\n");
 		SCpnt->result = DID_ERROR << 16;
-		SCpnt->scsi_done(SCpnt);
 		return SCSI_ABORT_NOT_RUNNING;
 	}
 
@@ -3359,18 +3357,19 @@
 		 */
 		search_doneQ_for_cmd(hd, SCpnt);
 
-		SCpnt->result = DID_RESET << 16;
-		SCpnt->scsi_done(SCpnt);
+		SCpnt->result = DID_ABORT << 16;
 		return SCSI_ABORT_SUCCESS;
 	} else {
 		/* If this command is pended, then timeout/hang occurred
 		 * during DV. Force bus reset by posting command to F/W
 		 * and then following up with the reset request.
 		 */
+#ifndef MPTSCSIH_DBG_TIMEOUT
 		if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
 			mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
 			post_pendingQ_commands(hd);
 		}
+#endif
 	}
 
 	/*
@@ -3476,8 +3475,7 @@
 	printk(KERN_WARNING "  IOs outstanding = %d\n", atomic_read(&queue_depth));
 
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
-		SCpnt->result = DID_RESET << 16;
-		SCpnt->scsi_done(SCpnt);
+		SCpnt->result = DID_ERROR << 16;
 		return SCSI_RESET_SUCCESS;
 	}
 
@@ -3492,17 +3490,18 @@
 		search_doneQ_for_cmd(hd, SCpnt);
 
 		SCpnt->result = DID_RESET << 16;
-		SCpnt->scsi_done(SCpnt);
 		return SCSI_RESET_SUCCESS;
 	} else {
 		/* If this command is pended, then timeout/hang occurred
 		 * during DV. Force bus reset by posting command to F/W
 		 * and then following up with the reset request.
 		 */
+#ifndef MPTSCSIH_DBG_TIMEOUT
 		if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
 			mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
 			post_pendingQ_commands(hd);
 		}
+#endif
 	}
 
 	/*
@@ -3628,8 +3627,8 @@
 
 #ifdef MPTSCSIH_DBG_TIMEOUT
 				if (ioc->timeout_hard == 1) {
-					mptscsih_TMHandler(hd, 
-						MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, 
+					mptscsih_TMHandler(hd,
+						MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
 						0, 0, 0, 0, CAN_SLEEP);
 
 				}
@@ -3727,6 +3726,9 @@
 				mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
 				mf = NULL;
 
+#ifndef MPTSCSIH_DBG_TIMEOUT
+				post_pendingQ_commands(hd);
+#endif
 				if (mptscsih_TMHandler(hd, task_type, SCpnt->channel,
 						      SCpnt->target, SCpnt->lun,
 						       ctx2abort, CAN_SLEEP) < 0) {
@@ -3784,7 +3786,7 @@
 {
 	SCSITaskMgmtReply_t	*pScsiTmReply;
 	SCSITaskMgmt_t		*pScsiTmReq;
-	MPT_SCSI_HOST		*hd = NULL;
+	MPT_SCSI_HOST		*hd;
 	unsigned long		 flags;
 	u8			 tmType = 0;
 
@@ -3962,10 +3964,10 @@
 			}
 
 			if (pTarget != NULL) {
-				printk(MYIOC_s_INFO_FMT
+				dprintk((MYIOC_s_INFO_FMT
 					 "scsi%d: Id=%d Lun=%d: Queue depth=%d\n",
-					 hd->ioc->name, sh->host_no,
-					 device->id, device->lun, device->queue_depth);
+					 hd->ioc->name, 
+					 device->id, device->lun, device->queue_depth));
 
 				dprintk((MYIOC_s_INFO_FMT
 					 "Id = %d, sync factor = %x\n",
@@ -4041,11 +4043,10 @@
 		thisIo.SCSIStatus = pScsiReply->SCSIStatus;
 		thisIo.DoDisplay = 1;
 		if (hd->is_multipath)
-			sprintf(devFoo, "%d:%d:%d \"%s\"",
+			sprintf(devFoo, "%d:%d:%d",
 					hd->ioc->id,
 					pReq->TargetID,
-					pReq->LUN[1],
-					target->dev_vol_name);
+					pReq->LUN[1]);
 		else
 			sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->target, sc->lun);
 		thisIo.DevIDStr = devFoo;
@@ -4102,7 +4103,7 @@
 	unsigned long	 flags;
 	MPT_DONE_Q	*buffer;
 	MPT_FRAME_HDR	*mf = NULL;
-	MPT_FRAME_HDR	*cmdMfPtr = NULL;
+	MPT_FRAME_HDR	*cmdMfPtr;
 
 	ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name));
 	cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
@@ -4190,7 +4191,7 @@
 static int
 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
-	MPT_SCSI_HOST	*hd = NULL;
+	MPT_SCSI_HOST	*hd;
 	unsigned long	 flags;
 
 	dtmprintk((KERN_WARNING MYNAM
@@ -4263,7 +4264,7 @@
 
 		dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
 	} else {
-		ScsiCfgData	*pSpi = NULL;
+		ScsiCfgData	*pSpi;
 
 		dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
 
@@ -4971,13 +4972,12 @@
  *	Allocate and initialize memory for this target.
  *	Save inquiry data.
  *
- *	Returns pointer to VirtDevice structure.
  */
-static VirtDevice *
+static void 
 mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
 {
+	int		indexed_lun, lun_index;
 	VirtDevice	*vdev;
-	int		 sz;
 
 	dprintk((MYIOC_s_INFO_FMT "initTarget (%d,%d,%d) called, hd=%p\n",
 			hd->ioc->name, bus_id, target_id, lun, hd));
@@ -4986,6 +4986,7 @@
 		if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) {
 			printk(MYIOC_s_ERR_FMT "initTarget kmalloc(%d) FAILED!\n",
 					hd->ioc->name, (int)sizeof(VirtDevice));
+			return;
 		} else {
 			memset(vdev, 0, sizeof(VirtDevice));
 			rwlock_init(&vdev->VdevLock);
@@ -5004,24 +5005,44 @@
 	}
 
 	vdev->raidVolume = 0;
-	if (vdev && hd->is_spi) {
+	if (hd->is_spi) {
 		if (hd->ioc->spi_data.isRaid & (1 << target_id)) {
 			vdev->raidVolume = 1;
 			ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
 		}
 	}
 
-	if (vdev && data) {
-		if ((!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) ||
-		((dlen > 56) && (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56)))) {
-
-			/* Copy the inquiry data  - if we haven't yet.
-			*/
-			sz = MIN(dlen, SCSI_STD_INQUIRY_BYTES);
+	if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
+		/* Copy the inquiry data  - if we haven't yet.
+		*/
+
+		memcpy (vdev->inq_data, data, 8);
 
-			memcpy (vdev->inq_data, data, sz);
+		if ( (data[0] == SCSI_TYPE_PROC) && 
+			!(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
+			if ( dlen > 49 ) {
+				vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+				if ( data[44] == 'S' && 
+				     data[45] == 'A' && 
+				     data[46] == 'F' && 
+				     data[47] == '-' && 
+				     data[48] == 'T' && 
+				     data[49] == 'E' ) {
+					vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+					mptscsih_writeIOCPage4(hd, target_id, bus_id);
+				}
+			} else {
+				/* Treat all Processors as SAF-TE if 
+				 * command line option is set */
+				if ( hd->ioc->spi_data.Saf_Te ) {
+					vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+					mptscsih_writeIOCPage4(hd, target_id, bus_id);
+				}
+			}
+		} else 
 			vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
 
+		if ((dlen > 56) && (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
 			/* Update the target capabilities
 			 */
 			if (dlen > 56) {
@@ -5038,17 +5059,19 @@
 					pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
 			}
 		}
-
-		/* Is LUN supported? If so, upper 3 bits will be 0
-		 * in first byte of inquiry data.
-		 */
-		if ((*data & 0xe0) == 0)
-			vdev->luns |= (1 << lun);
 	}
 
+	/* Is LUN supported? If so, upper 3 bits will be 0
+	 * in first byte of inquiry data.
+	 */
+	if ((*data & 0xe0) == 0) {
+		lun_index = (lun >> 5);  /* 32 luns per lun_index */
+		indexed_lun = (lun % 32);
+		vdev->luns[lun_index] |= (1 << indexed_lun);
+	}
 
 	dprintk((KERN_INFO "  target = %p\n", vdev));
-	return vdev;
+	return;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5063,13 +5086,13 @@
 	int  id = (int) target->target_id;
 	int  nvram;
 	char canQ = 0;
+	VirtDevice	*vdev;
+	int ii;
 	u8 width = MPT_NARROW;
 	u8 factor = MPT_ASYNC;
 	u8 offset = 0;
 	u8 version, nfactor;
-	u8 noQas = 0;
-
-	ddvtprintk((KERN_INFO "set Target: (id %d) byte56 0x%x\n", id, byte56));
+	u8 noQas = 1;
 
 	if (!hd->is_spi) {
 		if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
@@ -5079,19 +5102,16 @@
 		return;
 	}
 
+	target->negoFlags = pspi_data->noQas;
+
 	/* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
 	 * support. If available, default QAS to off and allow enabling.
 	 * If not available, default QAS to on, turn off for non-disks.
 	 */
-	if (target->tflags & MPT_TARGET_FLAGS_VALID_56)
-		noQas = 1;
 
 	/* Set flags based on Inquiry data
 	 */
 	if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-		if ((target->inq_data[0] & 0x1F) != 0x00)
-			noQas = 1;
-
 		version = target->inq_data[2] & 0x07;
 		if (version < 2) {
 			width = 0;
@@ -5111,6 +5131,7 @@
 					factor = MPT_ULTRA160;
 				else
 					factor = MPT_ULTRA320;
+				offset = pspi_data->maxSyncOffset;
 
 				/* If RAID, never disable QAS
 				 * else if non RAID, do not disable
@@ -5120,8 +5141,6 @@
 				 */
 				if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0))
 					noQas = 0;
-
-				offset = pspi_data->maxSyncOffset;
 			} else {
 				factor = MPT_ASYNC;
 				offset = 0;
@@ -5180,35 +5199,31 @@
 
 		/* Disable unused features.
 		 */
-		target->negoFlags = pspi_data->noQas;
 		if (!width)
 			target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
 
 		if (!offset)
 			target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
 
-		if (noQas)
-			target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-
 		/* GEM, processor WORKAROUND
 		 */
-		if (((target->inq_data[0] & 0x1F) == 0x03) || ((target->inq_data[0] & 0x1F) > 0x08)){
+		if (((target->inq_data[0] & 0x1F) == 0x03) || ((target->inq_data[0] & 0x1F) > 0x08)) {
 			target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
 			pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
-		}
-
-		/* Disable QAS if mixed configuration case
-		 */
-		if ((noQas) && (!pspi_data->noQas) && ((target->inq_data[0] & 0x1F) != 0x03)){
-			VirtDevice	*vdev;
-			int ii;
-
-			ddvtprintk((KERN_INFO "Disabling QAS!\n"));
-			pspi_data->noQas = MPT_TARGET_NO_NEGO_QAS;
-			for (ii = 0; ii < id; ii++) {
-				vdev = hd->Targets[id];
-				if (vdev != NULL)
-					vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+		} else {
+			if (noQas && (pspi_data->noQas == 0)) {
+				pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
+				target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+
+				/* Disable QAS in a mixed configuration case
+		 		*/
+
+//				ddvtprintk((KERN_INFO "Disabling QAS!\n"));
+				for (ii = 0; ii < id; ii++) {
+					if ( (vdev = hd->Targets[ii]) ) {
+						vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+					}	
+				}
 			}
 		}
 	}
@@ -5334,9 +5349,9 @@
 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
 {
 	MPT_ADAPTER		*ioc = hd->ioc;
-	Config_t		*pReq = NULL;
-	SCSIDevicePage1_t	*pData = NULL;
-	VirtDevice		*pTarget = NULL;
+	Config_t		*pReq;
+	SCSIDevicePage1_t	*pData;
+	VirtDevice		*pTarget;
 	MPT_FRAME_HDR		*mf;
 	dma_addr_t		 dataDma;
 	u16			 req_idx;
@@ -5432,7 +5447,6 @@
 			factor = pTarget->minSyncFactor;
 			offset = pTarget->maxOffset;
 			negoFlags = pTarget->negoFlags;
-			pTarget = NULL;
 		}
 
 		if (flags & MPT_SCSICFG_BLK_NEGO)
@@ -5515,6 +5529,86 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*	mptscsih_writeIOCPage4  - write IOC Page 4
+ *	@hd: Pointer to a SCSI Host Structure
+ *	@target_id: write IOC Page4 for this ID & Bus
+ *
+ *	Return: -EAGAIN if unable to obtain a Message Frame
+ *		or 0 if success.
+ *
+ *	Remark: We do not wait for a return, write pages sequentially.
+ */
+static int
+mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
+{
+	MPT_ADAPTER		*ioc = hd->ioc;
+	Config_t		*pReq;
+	IOCPage4_t		*IOCPage4Ptr;
+	MPT_FRAME_HDR		*mf;
+	dma_addr_t		 dataDma;
+	u16			 req_idx;
+	u32			 frameOffset;
+	u32			 flagsLength;
+	int			 ii;
+
+	/* Get a MF for this command.
+	 */
+	if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
+		dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
+					ioc->name));
+		return -EAGAIN;
+	}
+
+	ddvprintk((MYIOC_s_INFO_FMT "writeIOCPage4 (mf=%p, id=%d)\n",
+		ioc->name, mf, target_id));
+
+	/* Set the request and the data pointers.
+	 * Place data at end of MF.
+	 */
+	pReq = (Config_t *)mf;
+
+	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
+	frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
+
+	/* Complete the request frame (same for all requests).
+	 */
+	pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+	pReq->Reserved = 0;
+	pReq->ChainOffset = 0;
+	pReq->Function = MPI_FUNCTION_CONFIG;
+	pReq->Reserved1[0] = 0;
+	pReq->Reserved1[1] = 0;
+	pReq->Reserved1[2] = 0;
+	pReq->MsgFlags = 0;
+	for (ii=0; ii < 8; ii++) {
+		pReq->Reserved2[ii] = 0;
+	}
+
+       	IOCPage4Ptr = ioc->spi_data.pIocPg4;
+       	dataDma = ioc->spi_data.IocPg4_dma;
+       	ii = IOCPage4Ptr->ActiveSEP++;
+       	IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
+       	IOCPage4Ptr->SEP[ii].SEPBus = bus;
+       	pReq->Header = IOCPage4Ptr->Header;
+	pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
+
+	/* Add a SGE to the config request.
+	 */
+	flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | 
+		(IOCPage4Ptr->Header.PageLength + ii) * 4;
+
+	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
+
+	dsprintk((MYIOC_s_INFO_FMT
+		"writeIOCPage4: pgaddr 0x%x\n",
+			ioc->name, (target_id | (bus<<8))));
+
+	mptscsih_put_msgframe(ScsiDoneCtx, ioc->id, mf);
+
+	return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*	mptscsih_taskmgmt_timeout - Call back for timeout on a
  *	task management request.
  *	@data: Pointer to MPT_SCSI_HOST recast as an unsigned long
@@ -6138,7 +6232,7 @@
 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
 {
 	MPT_ADAPTER		*ioc= hd->ioc;
-	VirtDevice		*pTarget = NULL;
+	VirtDevice		*pTarget;
 	SCSIDevicePage1_t	*pcfg1Data = NULL;
 	INTERNAL_CMD		 iocmd;
 	CONFIGPARMS		 cfg;
@@ -6146,7 +6240,8 @@
 	ConfigPageHeader_t	 header1;
 	int			 bus = 0;
 	int			 id = 0;
-	int			 lun = 0;
+	int			 lun;
+	int			 indexed_lun, lun_index;
 	int			 hostId = ioc->pfacts[portnum].PortSCSIID;
 	int			 max_id;
 	int			 requested, configuration, data;
@@ -6237,12 +6332,13 @@
 
 		/* If target Ptr NULL or if this target is NOT a disk, skip.
 		 */
-	//	if (pTarget && ((pTarget->inq_data[0] & 0x1F) == 0)) {
 		if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
 			for (lun=0; lun <= MPT_LAST_LUN; lun++) {
 				/* If LUN present, issue the command
 				 */
-				if (pTarget->luns & (1<<lun)) {
+				lun_index = (lun >> 5);  /* 32 luns per lun_index */
+				indexed_lun = (lun % 32);
+				if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
 					iocmd.lun = lun;
 					(void) mptscsih_do_cmd(hd, &iocmd);
 				}
@@ -6283,8 +6379,8 @@
 static void
 mptscsih_domainValidation(void *arg)
 {
-	MPT_SCSI_HOST		*hd = NULL;
-	MPT_ADAPTER		*ioc = NULL;
+	MPT_SCSI_HOST		*hd;
+	MPT_ADAPTER		*ioc;
 	unsigned long		 flags;
 	int 			 id, maxid, dvStatus, did;
 	int			 ii, isPhysDisk;
@@ -6441,7 +6537,7 @@
  */
 static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
 {
-	VirtDevice *pTarget = NULL;
+	VirtDevice *pTarget;
 	int ii;
 
 	if (hd->Targets == NULL)
@@ -6495,12 +6591,12 @@
 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 {
 	MPT_ADAPTER		*ioc = hd->ioc;
-	VirtDevice		*pTarget = NULL;
-	SCSIDevicePage1_t	*pcfg1Data = NULL;
-	SCSIDevicePage0_t	*pcfg0Data = NULL;
-	u8			*pbuf1 = NULL;
-	u8			*pbuf2 = NULL;
-	u8			*pDvBuf = NULL;
+	VirtDevice		*pTarget;
+	SCSIDevicePage1_t	*pcfg1Data;
+	SCSIDevicePage0_t	*pcfg0Data;
+	u8			*pbuf1;
+	u8			*pbuf2;
+	u8			*pDvBuf;
 	dma_addr_t		 dvbuf_dma = -1;
 	dma_addr_t		 buf1_dma = -1;
 	dma_addr_t		 buf2_dma = -1;
@@ -6653,7 +6749,8 @@
 			if (nfactor < pspi_data->minSyncFactor )
 				nfactor = pspi_data->minSyncFactor;
 	
-			if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE)) {
+			if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
+				(pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
 	
 				ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
 					ioc->name, bus, id, lun));
@@ -6921,6 +7018,9 @@
 	if (inq0 != 0)
 		goto target_done;
 
+	if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
+		goto target_done;
+
 	/* Start the Enhanced Test.
 	 * 0) issue TUR to clear out check conditions
 	 * 1) read capacity of echo (regular) buffer
@@ -7377,9 +7477,9 @@
 static void
 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
 {
-	VirtDevice		*pTarget = NULL;
-	SCSIDevicePage0_t	*pPage0 = NULL;
-	SCSIDevicePage1_t	*pPage1 = NULL;
+	VirtDevice		*pTarget;
+	SCSIDevicePage0_t	*pPage0;
+	SCSIDevicePage1_t	*pPage1;
 	int			val = 0, data, configuration;
 	u8			width = 0;
 	u8			offset = 0;
@@ -7762,9 +7862,9 @@
 /* Commandline Parsing routines and defines.
  *
  * insmod format:
- *	insmod mptscsih mptscsih="width:1 dv:n factor:0x09"
+ *	insmod mptscsih mptscsih="width:1 dv:n factor:0x09 saf-te:1"
  *  boot format:
- *	mptscsih=width:1,dv:n,factor:0x8
+ *	mptscsih=width:1,dv:n,factor:0x8,saf-te:1
  *
  */
 #ifdef MODULE
@@ -7777,11 +7877,13 @@
 	"dv:"
 	"width:"
 	"factor:"
-       ;	/* DONNOT REMOVE THIS ';' */
+	"saf-te:"
+       ;	/* DO NOT REMOVE THIS ';' */
 
 #define OPT_DV			1
 #define OPT_MAX_WIDTH		2
 #define OPT_MIN_SYNC_FACTOR	3
+#define OPT_SAF_TE		4
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
@@ -7838,6 +7940,10 @@
 			driver_setup.min_sync_fac = val;
 			break;
 
+		case OPT_SAF_TE:
+			driver_setup.saf_te = val;
+			break;
+
 		default:
 			printk("mptscsih_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
 			break;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)