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

Next file: linux/drivers/message/fusion/scsi3.h
Previous file: linux/drivers/message/fusion/mptlan.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.9/linux/drivers/message/fusion/mptscsih.c linux/drivers/message/fusion/mptscsih.c
@@ -19,7 +19,7 @@
  *  Original author: Steven J. Ralston
  *  (mailto:Steve.Ralston@lsil.com)
  *
- *  $Id: mptscsih.c,v 1.24 2001/03/22 08:45:08 sralston Exp $
+ *  $Id: mptscsih.c,v 1.29 2001/06/18 18:59:05 sralston Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -95,7 +95,6 @@
 	u8			 *SgHunks;
 	dma_addr_t		  SgHunksDMA;
 	u32			  qtag_tick;
-	FCDEV_TRACKER		  TargetsQ;
 } MPT_SCSI_HOST;
 
 typedef struct _MPT_SCSI_DEV {
@@ -119,6 +118,7 @@
 static void	copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
 static u32	SCPNT_TO_MSGCTX(Scsi_Cmnd *sc);
 
+static int	mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 static int	mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
 
@@ -205,7 +205,7 @@
 			dprintk((KERN_INFO MYNAM ": *NEW* SCSI device (%d:%d:%d)!\n",
 					   sc->device->id, sc->device->lun, sc->device->channel));
 			if ((sc->device->hostdata = kmalloc(sizeof(MPT_SCSI_DEV), GFP_ATOMIC)) == NULL) {
-				printk(KERN_ERR MYNAM ": ERROR: kmalloc(%d) FAILED!\n", (int)sizeof(MPT_SCSI_DEV));
+				printk(KERN_ERR MYNAM ": ERROR - kmalloc(%d) FAILED!\n", (int)sizeof(MPT_SCSI_DEV));
 			} else {
 				memset(sc->device->hostdata, 0, sizeof(MPT_SCSI_DEV));
 				mpt_sdev = (MPT_SCSI_DEV *) sc->device->hostdata;
@@ -555,8 +555,14 @@
 	if (! BeenHereDoneThat++) {
 		show_mptmod_ver(my_NAME, my_VERSION);
 
-		ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
-		ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
+		if ((ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER)) <= 0) {
+			printk(KERN_ERR MYNAM ": Failed to register callback1 with MPT base driver\n");
+			return mpt_scsi_hosts;
+		}
+		if ((ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER)) <= 0) {
+			printk(KERN_ERR MYNAM ": Failed to register callback2 with MPT base driver\n");
+			return mpt_scsi_hosts;
+		}
 
 #ifndef MPT_SCSI_USE_NEW_EH
 		Q_INIT(&mpt_scsih_taskQ, MPT_FRAME_HDR);
@@ -568,6 +574,12 @@
 		} else {
 			/* FIXME! */
 		}
+
+		if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
+			dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
+		} else {
+			/* FIXME! */
+		}
 	}
 
 	dprintk((KERN_INFO MYNAM ": mpt_scsih_detect()\n"));
@@ -582,7 +594,7 @@
 		 *  Added sanity check on SCSI Initiator-mode enabled
 		 *  for this MPT adapter.
 		 */
-		if (!(this->pfacts0.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
+		if (!(this->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
 			printk(KERN_ERR MYNAM ": Skipping %s because SCSI Initiator mode is NOT enabled!\n",
 					this->name);
 			this = mpt_adapter_find_next(this);
@@ -612,10 +624,18 @@
 
 			/* Yikes!  This is important!
 			 * Otherwise, by default, linux only scans target IDs 0-7!
+			 *
+			 * BUG FIX!  20010618 -sralston & pdelaney
+			 * FC919 testing was encountering "duplicate" FC devices,
+			 * as it turns out because the 919 was returning 512
+			 * for PortFacts.MaxDevices, causing a wraparound effect
+			 * in SCSI IO requests.  So instead of using:
+			 *     sh->max_id = this->pfacts[0].MaxDevices - 1
+			 * we'll use a definitive max here.
 			 */
-			sh->max_id = this->pfacts0.MaxDevices - 1;
+			sh->max_id = MPT_MAX_FC_DEVICES;
 
-			sh->this_id = this->pfacts0.PortSCSIID;
+			sh->this_id = this->pfacts[0].PortSCSIID;
 
 			restore_flags(flags);
 
@@ -730,6 +750,9 @@
 #if 0
 			mptscsih_flush_pending();
 #endif
+			mpt_reset_deregister(ScsiDoneCtx);
+			dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n"));
+
 			mpt_event_deregister(ScsiDoneCtx);
 			dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n"));
 
@@ -765,7 +788,7 @@
 
 	h = (MPT_SCSI_HOST *)SChost->hostdata;
 	info_kbuf[0] = '\0';
-	mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0);
+	mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
 	info_kbuf[size-1] = '\0';
 
 	return info_kbuf;
@@ -1235,7 +1258,6 @@
 		dprintk((KERN_INFO MYNAM ": Queue depth now %d.\n", max_qd));
 	}
 
-	mb();
 	dmfprintk((KERN_INFO MYNAM ": Issued SCSI cmd (%p)\n", SCpnt));
 
 	return 0;
@@ -1265,6 +1287,7 @@
 	u32		*msg;
 	u32		 ctx2abort;
 	int		 i;
+	unsigned long	 flags;
 
 	printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO (=%p)\n", SCpnt);
 	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
@@ -1309,41 +1332,59 @@
 	 *	 the controller, so it does not matter. -DaveM
 	 */
 	ctx2abort = SCPNT_TO_MSGCTX(SCpnt);
-	dprintk((KERN_INFO MYNAM ":DbG: ctx2abort = %08x\n", ctx2abort));
-	pScsiTm->TaskMsgContext = ctx2abort;
-
-	wmb();
+	if (ctx2abort == -1) {
+		printk(KERN_ERR MYNAM ": ERROR - ScsiLookup fail(#2) for SCpnt=%p\n", SCpnt);
+		SCpnt->result = DID_SOFT_ERROR << 16;
+		spin_lock_irqsave(&io_request_lock, flags);
+		SCpnt->scsi_done(SCpnt);
+		spin_unlock_irqrestore(&io_request_lock, flags);
+		mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
+	} else {
+		dprintk((KERN_INFO MYNAM ":DbG: ctx2abort = %08x\n", ctx2abort));
+		pScsiTm->TaskMsgContext = ctx2abort;
 
-/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
-	mpt_put_msg_frame(hd->ioc->id, mf);
-*/
-/* FIXME!  Check return status! */
-	(void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), msg);
 
-	wmb();
+		/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
+			mpt_put_msg_frame(hd->ioc->id, mf);
+		*/
+		if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
+					sizeof(SCSITaskMgmt_t), msg))
+		    != 0) {
+			printk(KERN_WARNING MYNAM
+					": WARNING[2] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n",
+					i, mf, SCpnt);
+			SCpnt->result = DID_SOFT_ERROR << 16;
+			spin_lock_irqsave(&io_request_lock, flags);
+			SCpnt->scsi_done(SCpnt);
+			spin_unlock_irqrestore(&io_request_lock, flags);
+			mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
+		}
+	}
 
-	return SUCCESS;
+	//return SUCCESS;
+	return FAILED;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *	mptscsih_bus_reset - Perform a SCSI BUS_RESET!	new_eh variant
+ *	mptscsih_dev_reset - Perform a SCSI TARGET_RESET!  new_eh variant
  *	@SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
  *
- *	(linux Scsi_Host_Template.eh_bus_reset_handler routine)
+ *	(linux Scsi_Host_Template.eh_dev_reset_handler routine)
  *
  *	Returns SUCCESS or FAILED.
  */
 int
-mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
+mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
 {
 	MPT_FRAME_HDR	*mf;
 	SCSITaskMgmt_t	*pScsiTm;
 	MPT_SCSI_HOST	*hd;
 	u32		*msg;
 	int		 i;
+	unsigned long	 flags;
 
-	printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET (%p)\n", SCpnt);
+	printk(KERN_WARNING MYNAM ": Attempting _TARGET_RESET (%p)\n", SCpnt);
 	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
 
 	hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
@@ -1356,7 +1397,7 @@
 	}
 
 	pScsiTm = (SCSITaskMgmt_t *) mf;
-	msg = (u32 *) mf;
+	msg = (u32*)mf;
 
 	pScsiTm->TargetID = SCpnt->target;
 	pScsiTm->Bus = hd->port;
@@ -1364,10 +1405,11 @@
 	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
 
 	pScsiTm->Reserved = 0;
-	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
+	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
 	pScsiTm->Reserved1 = 0;
 	pScsiTm->MsgFlags = 0;
 
+	/* _TARGET_RESET goes to LUN 0 always! */
 	for (i = 0; i < 8; i++)
 		pScsiTm->LUN[i] = 0;
 
@@ -1377,38 +1419,47 @@
 
 	pScsiTm->TaskMsgContext = cpu_to_le32(0);
 
-	wmb();
-
 /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
 	mpt_put_msg_frame(hd->ioc->id, mf);
 */
 /* FIXME!  Check return status! */
-	(void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), msg);
-
-	wmb();
+	if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
+				sizeof(SCSITaskMgmt_t), msg))
+	    != 0) {
+		printk(KERN_WARNING MYNAM
+				": WARNING[3] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n",
+				i, mf, SCpnt);
+		SCpnt->result = DID_SOFT_ERROR << 16;
+		spin_lock_irqsave(&io_request_lock, flags);
+		SCpnt->scsi_done(SCpnt);
+		spin_unlock_irqrestore(&io_request_lock, flags);
+		mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
+	}
 
-	return SUCCESS;
+	//return SUCCESS;
+	return FAILED;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *	mptscsih_dev_reset - Perform a SCSI TARGET_RESET!  new_eh variant
+ *	mptscsih_bus_reset - Perform a SCSI BUS_RESET!	new_eh variant
  *	@SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
  *
- *	(linux Scsi_Host_Template.eh_dev_reset_handler routine)
+ *	(linux Scsi_Host_Template.eh_bus_reset_handler routine)
  *
  *	Returns SUCCESS or FAILED.
  */
 int
-mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
+mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
 {
 	MPT_FRAME_HDR	*mf;
 	SCSITaskMgmt_t	*pScsiTm;
 	MPT_SCSI_HOST	*hd;
 	u32		*msg;
 	int		 i;
+	unsigned long	 flags;
 
-	printk(KERN_WARNING MYNAM ": Attempting _TARGET_RESET (%p)\n", SCpnt);
+	printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET (%p)\n", SCpnt);
 	printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
 
 	hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
@@ -1421,7 +1472,7 @@
 	}
 
 	pScsiTm = (SCSITaskMgmt_t *) mf;
-	msg = (u32*)mf;
+	msg = (u32 *) mf;
 
 	pScsiTm->TargetID = SCpnt->target;
 	pScsiTm->Bus = hd->port;
@@ -1429,11 +1480,10 @@
 	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
 
 	pScsiTm->Reserved = 0;
-	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
 	pScsiTm->Reserved1 = 0;
 	pScsiTm->MsgFlags = 0;
 
-	/* _TARGET_RESET goes to LUN 0 always! */
 	for (i = 0; i < 8; i++)
 		pScsiTm->LUN[i] = 0;
 
@@ -1443,15 +1493,22 @@
 
 	pScsiTm->TaskMsgContext = cpu_to_le32(0);
 
-	wmb();
-
 /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
 	mpt_put_msg_frame(hd->ioc->id, mf);
 */
 /* FIXME!  Check return status! */
-	(void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), msg);
-
-	wmb();
+	if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
+				sizeof(SCSITaskMgmt_t), msg))
+	    != 0) {
+		printk(KERN_WARNING MYNAM
+				": WARNING[4] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n",
+				i, mf, SCpnt);
+		SCpnt->result = DID_SOFT_ERROR << 16;
+		spin_lock_irqsave(&io_request_lock, flags);
+		SCpnt->scsi_done(SCpnt);
+		spin_unlock_irqrestore(&io_request_lock, flags);
+		mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
+	}
 
 	return SUCCESS;
 }
@@ -1646,6 +1703,9 @@
 	spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
 
 	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(HZ/4);
+
 		/*
 		 *  We MUST remove item from taskQ *before* we format the
 		 *  frame as a SCSITaskMgmt request and send it down to the IOC.
@@ -1664,9 +1724,10 @@
 
 		SCpnt = (Scsi_Cmnd*)mf->u.frame.linkage.argp1;
 		if (SCpnt == NULL) {
-			printk(KERN_ERR MYNAM ": ERROR: TaskMgmt has NULL SCpnt! (%p:%p)\n", mf, SCpnt);
+			printk(KERN_ERR MYNAM ": ERROR - TaskMgmt has NULL SCpnt! (%p:%p)\n", mf, SCpnt);
 			continue;
 		}
+		hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
 		pScsiTm = (SCSITaskMgmt_t *) mf;
 
 		for (i = 0; i < 8; i++) {
@@ -1674,9 +1735,9 @@
 		}
 
 		task_type = mf->u.frame.linkage.arg1;
-		if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
-		{
-			printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO! (mf:sc=%p:%p)\n", mf, SCpnt);
+		if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
+			printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO! (mf=%p:sc=%p)\n",
+					mf, SCpnt);
 
 			/* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
 			 * (the IO to be ABORT'd)
@@ -1686,11 +1747,20 @@
 			 *	 the controller, so it does not matter. -DaveM
 			 */
 			ctx2abort = SCPNT_TO_MSGCTX(SCpnt);
+			if (ctx2abort == -1) {
+				printk(KERN_ERR MYNAM ": ERROR - ScsiLookup fail(#1) for SCpnt=%p\n", SCpnt);
+				SCpnt->result = DID_SOFT_ERROR << 16;
+				spin_lock_irqsave(&io_request_lock, flags);
+				SCpnt->scsi_done(SCpnt);
+				spin_unlock_irqrestore(&io_request_lock, flags);
+				mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
+				continue;
+			}
 			pScsiTm->LUN[1] = SCpnt->lun;
 		}
 		else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
 		{
-			printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET! (against SCSI IO mf:sc=%p:%p)\n", mf, SCpnt);
+			printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET! (against SCSI IO mf=%p:sc=%p)\n", mf, SCpnt);
 		}
 #if 0
 		else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {}
@@ -1699,8 +1769,6 @@
 
 		printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
 
-		hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
-
 		pScsiTm->TargetID = SCpnt->target;
 		pScsiTm->Bus = hd->port;
 		pScsiTm->ChainOffset = 0;
@@ -1725,15 +1793,22 @@
 		 *		mpt_put_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
 		 *  SCSITaskMgmt requests MUST be sent ONLY via
 		 *  Doorbell/handshake now.   :-(
-		 *
-		 *  FIXME!  Check return status!
 		 */
-		(void) mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), (u32*)mf);
-
-		/* Spin-Wait for TaskMgmt complete!!! */
-		while (mpt_scsih_active_taskmgmt_mf != NULL) {
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(HZ/2);
+		if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
+					sizeof(SCSITaskMgmt_t), (u32*) mf))
+		    != 0) {
+			printk(KERN_WARNING MYNAM ": WARNING[1] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n", i, mf, SCpnt);
+			SCpnt->result = DID_SOFT_ERROR << 16;
+			spin_lock_irqsave(&io_request_lock, flags);
+			SCpnt->scsi_done(SCpnt);
+			spin_unlock_irqrestore(&io_request_lock, flags);
+			mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
+		} else {
+			/* Spin-Wait for TaskMgmt complete!!! */
+			while (mpt_scsih_active_taskmgmt_mf != NULL) {
+				current->state = TASK_INTERRUPTIBLE;
+				schedule_timeout(HZ/4);
+			}
 		}
 	}
 
@@ -2002,6 +2077,22 @@
 #	include "../../scsi/scsi_module.c"
 #endif
 
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int
+mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
+{
+	dprintk((KERN_INFO MYNAM ": IOC %s_reset routed to SCSI host driver!\n",
+			reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"));
+
+	if (reset_phase == MPT_IOC_PRE_RESET) {
+		/* FIXME! Do pre-reset cleanup */
+	} else {
+		/* FIXME! Do post-reset cleanup */
+	}
+
+	return 1;		/* currently means nothing really */
+}
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int

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