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 <[EMAIL PROTECTED]>
--- 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 [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html