[PATCH 7/9] mpt fusion: error recovery improvements, and synchronizing internal commands

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



1) cleanup ioc_reset callback handlers, introducing wrappers for synronizing error recovery (mpt_set_taskmgmt_in_progress_flag, mpt_clear_taskmgmt_in_progress_flag), as the fusion firmware only handles one task management request at a time.
2) rewrite of all internal generated functions that issue commands to firmware, porting them to be single threaded using the generic MPT_MGMT struct.

Signed-off-by: Eric Moore <Eric.Moore@xxxxxxx>

--- b/drivers/message/fusion/mptsas.c	2007-09-17 16:35:06.000000000 -0600
+++ a/drivers/message/fusion/mptsas.c	2007-09-17 19:35:03.000000000 -0600
@@ -600,12 +600,12 @@ mptsas_target_reset_queue(MPT_ADAPTER *i
 		sizeof(*sas_event_data));
 	list_add_tail(&target_reset_list->list, &hd->target_reset_list);
 
-	if (hd->resetPending)
+	if (ioc->ioc_reset_in_progress)
 		return;
 
 	if (mptsas_target_reset(ioc, channel, id)) {
 		target_reset_list->target_reset_issued = 1;
-		hd->resetPending = 1;
+		ioc->ioc_reset_in_progress = 1;
 	}
 }
 
@@ -638,7 +638,7 @@ mptsas_dev_reset_complete(MPT_ADAPTER *i
 	sas_event_data = &target_reset_list->sas_event_data;
 	id = sas_event_data->TargetID;
 	channel = sas_event_data->Bus;
-	hd->resetPending = 0;
+	ioc->ioc_reset_in_progress = 0;
 
 	/*
 	 * retry target reset
@@ -646,7 +646,7 @@ mptsas_dev_reset_complete(MPT_ADAPTER *i
 	if (!target_reset_list->target_reset_issued) {
 		if (mptsas_target_reset(ioc, channel, id)) {
 			target_reset_list->target_reset_issued = 1;
-			hd->resetPending = 1;
+			ioc->ioc_reset_in_progress = 1;
 		}
 		return;
 	}
@@ -696,7 +696,7 @@ mptsas_dev_reset_complete(MPT_ADAPTER *i
 
 	if (mptsas_target_reset(ioc, channel, id)) {
 		target_reset_list->target_reset_issued = 1;
-		hd->resetPending = 1;
+		ioc->ioc_reset_in_progress = 1;
 	}
 }
 
@@ -716,41 +716,56 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *io
 }
 
 /**
- * mptscsih_ioc_reset
- *
- * @ioc
- * @reset_phase
+ *	mptsas_ioc_reset -
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@reset_phase:
  *
  **/
 static int
 mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
-	MPT_SCSI_HOST	*hd;
+	MPT_SCSI_HOST   *hd;
 	struct mptsas_target_reset_event *target_reset_list, *n;
 	int rc;
 
 	rc = mptscsih_ioc_reset(ioc, reset_phase);
+	if ((ioc->bus_type != SAS) || (!rc))
+		return rc;
 
-	if (ioc->bus_type != SAS)
-		goto out;
-
-	if (reset_phase != MPT_IOC_POST_RESET)
-		goto out;
-
-	if (!ioc->sh || !ioc->sh->hostdata)
-		goto out;
-	hd = shost_priv(ioc->sh);
-	if (!hd->ioc)
-		goto out;
-
-	if (list_empty(&hd->target_reset_list))
-		goto out;
-
-	/* flush the target_reset_list */
-	list_for_each_entry_safe(target_reset_list, n,
-	    &hd->target_reset_list, list) {
-		list_del(&target_reset_list->list);
-		kfree(target_reset_list);
+	switch(reset_phase) {
+	case MPT_IOC_SETUP_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __FUNCTION__));
+		break;
+	case MPT_IOC_PRE_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_PRE_RESET\n", ioc->name, __FUNCTION__));
+		break;
+	case MPT_IOC_POST_RESET:
+		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+		    "%s: MPT_IOC_POST_RESET\n", ioc->name, __FUNCTION__));
+		if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
+			ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET;
+			complete(&ioc->sas_mgmt.done);
+		}
+		hd = shost_priv(ioc->sh);
+		if (!hd->ioc)
+			goto out;
+		if (list_empty(&hd->target_reset_list))
+			break;
+		/* flush the target_reset_list */
+		list_for_each_entry_safe(target_reset_list, n,
+		    &hd->target_reset_list, list) {
+			dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
+			    "%s: removing target reset for id=%d\n",
+			    ioc->name, __FUNCTION__,
+			    target_reset_list->sas_event_data.TargetID));
+			list_del(&target_reset_list->list);
+			kfree(target_reset_list);
+		}
+		break;
+	default:
+		break;
 	}
 
  out:
@@ -861,9 +876,14 @@ mptsas_target_alloc(struct scsi_target *
 	 * RAID volumes placed beyond the last expected port.
 	 */
 	if (starget->channel == MPTSAS_RAID_CHANNEL) {
+		if (!ioc->raid_data.pIocPg2) {
+			kfree(vtarget);
+			return -ENXIO;
+		}
 		for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
 			if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
 				channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
+		vtarget->raidVolume = 1;
 		goto out;
 	}
 
@@ -1100,14 +1120,19 @@ static int mptsas_get_linkerrors(struct 
 static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
 		MPT_FRAME_HDR *reply)
 {
-	ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
+	ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
 	if (reply != NULL) {
-		ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
+		ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID;
 		memcpy(ioc->sas_mgmt.reply, reply,
 		    min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
 	}
-	complete(&ioc->sas_mgmt.done);
-	return 1;
+
+	if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
+		ioc->sas_mgmt.status &= ~MPT_MGMT_STATUS_PENDING;
+		complete(&ioc->sas_mgmt.done);
+		return 1;
+	}
+	return 0;
 }
 
 static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
@@ -1146,21 +1171,24 @@ static int mptsas_phy_reset(struct sas_p
 		MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
 	req->PhyNum = phy->identify.phy_identifier;
 
+	INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
 	mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
-
-	timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
-			10 * HZ);
-	if (!timeleft) {
-		/* On timeout reset the board */
+	timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10*HZ);
+	if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		error = -ETIME;
 		mpt_free_msg_frame(ioc, mf);
-		mpt_HardResetHandler(ioc, CAN_SLEEP);
-		error = -ETIMEDOUT;
+		if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
+			goto out;
+		if (!timeleft) {
+			if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
+				mpt_HardResetHandler(ioc, CAN_SLEEP);
+		}
 		goto out_unlock;
 	}
 
 	/* a reply frame is expected */
 	if ((ioc->sas_mgmt.status &
-	    MPT_IOCTL_STATUS_RF_VALID) == 0) {
+	    MPT_MGMT_STATUS_RF_VALID) == 0) {
 		error = -ENXIO;
 		goto out_unlock;
 	}
@@ -1177,6 +1205,7 @@ static int mptsas_phy_reset(struct sas_p
 	error = 0;
 
  out_unlock:
+	CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
 	mutex_unlock(&ioc->sas_mgmt.mutex);
  out:
 	return error;
@@ -1325,19 +1354,24 @@ static int mptsas_smp_handler(struct Scs
 		goto unmap;
 	mpt_add_sge(psge, flagsLength, dma_addr_in);
 
+	INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
 	mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
-
 	timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
-	if (!timeleft) {
-		printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __FUNCTION__);
-		/* On timeout reset the board */
-		mpt_HardResetHandler(ioc, CAN_SLEEP);
-		ret = -ETIMEDOUT;
+	if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
+		ret = -ETIME;
+		mpt_free_msg_frame(ioc, mf);
+		if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
+			goto out;
+		if (!timeleft) {
+			if (mpt_SoftResetHandler(ioc, CAN_SLEEP) != 0)
+				mpt_HardResetHandler(ioc, CAN_SLEEP);
+		}
 		goto unmap;
 	}
+
 	mf = NULL;
 
-	if (ioc->sas_mgmt.status & MPT_IOCTL_STATUS_RF_VALID) {
+	if ((ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) == 0) {
 		SmpPassthroughReply_t *smprep;
 
 		smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
@@ -1349,6 +1383,7 @@ static int mptsas_smp_handler(struct Scs
 		ret = -ENXIO;
 	}
 unmap:
+	CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
 	if (dma_addr_out)
 		pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len,
 				 PCI_DMA_BIDIRECTIONAL);
@@ -3232,32 +3267,8 @@ mptsas_probe(struct pci_dev *pdev, const
 	dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
 		 ioc->name, ioc->ScsiLookup));
 
-	/* Clear the TM flags
-	 */
-	hd->tmPending = 0;
-	hd->tmState = TM_STATE_NONE;
-	hd->resetPending = 0;
-	hd->abortSCpnt = NULL;
-
-	/* Clear the pointer used to store
-	 * single-threaded commands, i.e., those
-	 * issued during a bus scan, dv and
-	 * configuration pages.
-	 */
-	hd->cmdPtr = NULL;
-
-	/* Initialize this SCSI Hosts' timers
-	 * To use, set the timer expires field
-	 * and add_timer
-	 */
-	init_timer(&hd->timer);
-	hd->timer.data = (unsigned long) hd;
-	hd->timer.function = mptscsih_timer_expired;
-
 	ioc->sas_data.ptClear = mpt_pt_clear;
 
-	init_waitqueue_head(&hd->scandv_waitq);
-	hd->scandv_wait_done = 0;
 	hd->last_queue_full = 0;
 	INIT_LIST_HEAD(&hd->target_reset_list);
 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux