X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fmessage%2Ffusion%2Fmptscsih.c;h=2a3e9e66d4ef7ed49c535597da34a8073417c219;hb=59b8175c771040afcd4ad67022b0cc80c216b866;hp=30524dc54b16b720dea158f45c5f477ff446cf19;hpb=af652c26f5f0eceb6d8cb97eb9b86fba6f1f3b85;p=linux-2.6-omap-h63xx.git diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 30524dc54b1..2a3e9e66d4e 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -3,8 +3,8 @@ * For use with LSI Logic PCI chip/adapter(s) * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2005 LSI Logic Corporation - * (mailto:mpt_linux_developer@lsil.com) + * Copyright (c) 1999-2007 LSI Logic Corporation + * (mailto:mpt_linux_developer@lsi.com) * */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -54,7 +54,6 @@ #include /* for mdelay */ #include /* needed for in_interrupt() proto */ #include /* notifier code */ -#include #include #include @@ -76,45 +75,9 @@ MODULE_AUTHOR(MODULEAUTHOR); MODULE_DESCRIPTION(my_NAME); MODULE_LICENSE("GPL"); +MODULE_VERSION(my_VERSION); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -typedef struct _BIG_SENSE_BUF { - u8 data[MPT_SENSE_BUFFER_ALLOC]; -} BIG_SENSE_BUF; - -#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */ -#define MPT_SCANDV_DID_RESET (0x00000001) -#define MPT_SCANDV_SENSE (0x00000002) -#define MPT_SCANDV_SOME_ERROR (0x00000004) -#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) -#define MPT_SCANDV_ISSUE_SENSE (0x00000010) -#define MPT_SCANDV_FALLBACK (0x00000020) - -#define MPT_SCANDV_MAX_RETRIES (10) - -#define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */ -#define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */ -#define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */ -#define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */ -#define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */ -#define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */ -#define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */ - -typedef struct _internal_cmd { - char *data; /* data pointer */ - dma_addr_t data_dma; /* data dma address */ - int size; /* transfer size */ - u8 cmd; /* SCSI Op Code */ - u8 bus; /* bus number */ - u8 id; /* SCSI ID (virtual) */ - u8 lun; - u8 flags; /* Bit Field - See above */ - u8 physDiskNum; /* Phys disk number, -1 else */ - u8 rsvd2; - u8 rsvd; -} INTERNAL_CMD; - /* * Other private/forward protos... */ @@ -130,14 +93,11 @@ static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); -static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); +static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); -static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); -static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev); -static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); @@ -516,16 +476,100 @@ mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget, SEPMsg = (SEPRequest_t *)mf; SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; - SEPMsg->Bus = vtarget->bus_id; - SEPMsg->TargetID = vtarget->target_id; + SEPMsg->Bus = vtarget->channel; + SEPMsg->TargetID = vtarget->id; SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS; SEPMsg->SlotStatus = SlotStatus; devtverboseprintk((MYIOC_s_WARN_FMT - "Sending SEP cmd=%x id=%d bus=%d\n", - ioc->name, SlotStatus, SEPMsg->TargetID, SEPMsg->Bus)); + "Sending SEP cmd=%x channel=%d id=%d\n", + ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID)); mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); } +#ifdef MPT_DEBUG_REPLY +/** + * mptscsih_iocstatus_info_scsiio - IOCSTATUS information for SCSIIO + * @ioc: Pointer to MPT_ADAPTER structure + * @ioc_status: U32 IOCStatus word from IOC + * @scsi_status: U8 sam status from target + * @scsi_state: U8 scsi state + * @sc: original scsi cmnd pointer + * @mf: Pointer to MPT request frame + * + * Refer to lsi/mpi.h. + **/ +static void +mptscsih_iocstatus_info_scsiio(MPT_ADAPTER *ioc, u32 ioc_status, + u8 scsi_status, u8 scsi_state, struct scsi_cmnd *sc) +{ + char extend_desc[EVENT_DESCR_STR_SZ]; + char *desc = NULL; + + switch (ioc_status) { + + case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ + desc = "SCSI Invalid Bus"; + break; + + case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ + desc = "SCSI Invalid TargetID"; + break; + + case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ + /* + * Inquiry is issued for device scanning + */ + if (sc->cmnd[0] != 0x12) + desc = "SCSI Device Not There"; + break; + + case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ + desc = "SCSI Data Overrun"; + break; + + case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ + desc = "SCSI I/O Data Error"; + break; + + case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ + desc = "SCSI Protocol Error"; + break; + + case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ + desc = "SCSI Task Terminated"; + break; + + case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ + desc = "SCSI Residual Mismatch"; + break; + + case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ + desc = "SCSI Task Management Failed"; + break; + + case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ + desc = "SCSI IOC Terminated"; + break; + + case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ + desc = "SCSI Ext Terminated"; + break; + } + + if (!desc) + return; + + snprintf(extend_desc, EVENT_DESCR_STR_SZ, + "[%d:%d:%d:%d] cmd=%02Xh, sam_status=%02Xh state=%02Xh", + sc->device->host->host_no, + sc->device->channel, sc->device->id, sc->device->lun, + sc->cmnd[0], scsi_status, scsi_state); + + printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n", + ioc->name, ioc_status, desc, extend_desc); +} +#endif + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * mptscsih_io_done - Main SCSI IO callback routine registered to @@ -612,12 +656,14 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) u32 xfer_cnt; u16 status; u8 scsi_state, scsi_status; + u32 log_info; status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; scsi_state = pScsiReply->SCSIState; scsi_status = pScsiReply->SCSIStatus; xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); sc->resid = sc->request_bufflen - xfer_cnt; + log_info = le32_to_cpu(pScsiReply->IOCLogInfo); /* * if we get a data underrun indication, yet no data was @@ -632,13 +678,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) status = MPI_IOCSTATUS_SUCCESS; } - dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n" - "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n" - "resid=%d bufflen=%d xfer_cnt=%d\n", - ioc->id, sc->device->id, sc->device->lun, - status, scsi_state, scsi_status, sc->resid, - sc->request_bufflen, xfer_cnt)); - if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) mptscsih_copy_sense_data(sc, hd, mf, pScsiReply); @@ -647,9 +686,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) */ if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && pScsiReply->ResponseInfo) { - printk(KERN_NOTICE "ha=%d id=%d lun=%d: " + printk(KERN_NOTICE "[%d:%d:%d:%d] " "FCP_ResponseInfo=%08xh\n", - ioc->id, sc->device->id, sc->device->lun, + sc->device->host->host_no, sc->device->channel, + sc->device->id, sc->device->lun, le32_to_cpu(pScsiReply->ResponseInfo)); } @@ -694,13 +734,23 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) if ( ioc->bus_type == SAS ) { u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus); if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { - u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); - log_info &=SAS_LOGINFO_MASK; - if (log_info == SAS_LOGINFO_NEXUS_LOSS) { + if ((log_info & SAS_LOGINFO_MASK) + == SAS_LOGINFO_NEXUS_LOSS) { sc->result = (DID_BUS_BUSY << 16); break; } } + } else if (ioc->bus_type == FC) { + /* + * The FC IOC may kill a request for variety of + * reasons, some of which may be recovered by a + * retry, some which are unlikely to be + * recovered. Return DID_ERROR instead of + * DID_RESET to permit retry of the command, + * just not an infinite number of them + */ + sc->result = DID_ERROR << 16; + break; } /* @@ -723,7 +773,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) else /* Sufficient data transfer occurred */ sc->result = (DID_OK << 16) | scsi_status; dreplyprintk((KERN_NOTICE - "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id)); + "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n", + sc->result, sc->device->channel, sc->device->id)); break; case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ @@ -836,7 +887,28 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } /* switch(status) */ - dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result)); +#ifdef MPT_DEBUG_REPLY + if (sc->result) { + + mptscsih_iocstatus_info_scsiio(ioc, status, + scsi_status, scsi_state, sc); + + dreplyprintk(("%s: [%d:%d:%d:%d] cmd=0x%02x " + "result=0x%08x\n\tiocstatus=0x%04X " + "scsi_state=0x%02X scsi_status=0x%02X " + "loginfo=0x%08X\n", __FUNCTION__, + sc->device->host->host_no, sc->device->channel, sc->device->id, + sc->device->lun, sc->cmnd[0], sc->result, status, + scsi_state, scsi_status, log_info)); + + dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d " + "bufflen=%d xfer_cnt=%d\n", __FUNCTION__, + sc->device->host->host_no, sc->device->channel, sc->device->id, + sc->device->lun, sc->resid, sc->request_bufflen, + xfer_cnt)); + } +#endif + } /* end of address reply case */ /* Unmap the DMA buffers, if any. */ @@ -943,9 +1015,10 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) int ii; int max = hd->ioc->req_depth; struct scsi_cmnd *sc; + struct scsi_lun lun; - dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n", - vdevice->vtarget->target_id, vdevice->lun, max)); + dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n", + vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max)); for (ii=0; ii < max; ii++) { if ((sc = hd->ScsiLookup[ii]) != NULL) { @@ -953,10 +1026,14 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); if (mf == NULL) continue; - dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n", - hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); - if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) + int_to_scsilun(vdevice->lun, &lun); + if ((mf->Bus != vdevice->vtarget->channel) || + (mf->TargetID != vdevice->vtarget->id) || + memcmp(lun.scsi_lun, mf->LUN, 8)) continue; + dsprintk(( "search_running: found (sc=%p, mf = %p) " + "channel %d id %d, lun %d \n", hd->ScsiLookup[ii], + mf, mf->Bus, mf->TargetID, vdevice->lun)); /* Cleanup */ @@ -1053,12 +1130,6 @@ mptscsih_remove(struct pci_dev *pdev) hd->ScsiLookup = NULL; } - /* - * Free pointer array. - */ - kfree(hd->Targets); - hd->Targets = NULL; - dprintk((MYIOC_s_INFO_FMT "Free'd ScsiLookup (%d) memory\n", hd->ioc->name, sz1)); @@ -1230,15 +1301,15 @@ mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_proc_info - Return information about MPT adapter + * @host: scsi host struct + * @buffer: if write, user data; if read, buffer for user + * @start: returns the buffer address + * @offset: if write, 0; if read, the current offset into the buffer from + * the previous read. + * @length: if write, return length; + * @func: write = 1; read = 0 * * (linux scsi_host_template.info routine) - * - * buffer: if write, user data; if read, buffer for user - * length: if write, return length; - * offset: if write, 0; if read, the current offset into the buffer from - * the previous read. - * hostno: scsi host number - * func: if write = 1; if read = 0 */ int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, @@ -1305,14 +1376,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return SCSI_MLQUEUE_HOST_BUSY; } - if ((hd->ioc->bus_type == SPI) && - vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && - mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) { - SCpnt->result = DID_NO_CONNECT << 16; - done(SCpnt); - return 0; - } - /* * Put together a MPT SCSI request... */ @@ -1356,8 +1419,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* Use the above information to set up the message frame */ - pScsiReq->TargetID = (u8) vdev->vtarget->target_id; - pScsiReq->Bus = vdev->vtarget->bus_id; + pScsiReq->TargetID = (u8) vdev->vtarget->id; + pScsiReq->Bus = vdev->vtarget->channel; pScsiReq->ChainOffset = 0; if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; @@ -1367,14 +1430,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; pScsiReq->Reserved = 0; pScsiReq->MsgFlags = mpt_msg_flags(); - pScsiReq->LUN[0] = 0; - pScsiReq->LUN[1] = lun; - pScsiReq->LUN[2] = 0; - pScsiReq->LUN[3] = 0; - pScsiReq->LUN[4] = 0; - pScsiReq->LUN[5] = 0; - pScsiReq->LUN[6] = 0; - pScsiReq->LUN[7] = 0; + int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN); pScsiReq->Control = cpu_to_le32(scsictl); /* @@ -1479,14 +1535,14 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mptscsih_TMHandler - Generic handler for SCSI Task Management. * Fall through to mpt_HardResetHandler if: not operational, too many * failed TM requests or handshake failure. * * @ioc: Pointer to MPT_ADAPTER structure * @type: Task Management type - * @target: Logical Target ID for reset (if appropriate) + * @id: Logical Target ID for reset (if appropriate) * @lun: Logical Unit for reset (if appropriate) * @ctx2abort: Context for the task to be aborted (if appropriate) * @@ -1495,28 +1551,17 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC * will be active. * - * Returns 0 for SUCCESS or -1 if FAILED. - */ + * Returns 0 for SUCCESS, or FAILED. + **/ int -mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) +mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) { MPT_ADAPTER *ioc; int rc = -1; - int doTask = 1; u32 ioc_raw_state; unsigned long flags; - /* If FW is being reloaded currently, return success to - * the calling function. - */ - if (hd == NULL) - return 0; - ioc = hd->ioc; - if (ioc == NULL) { - printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n"); - return FAILED; - } dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name)); // SJR - CHECKME - Can we avoid this here? @@ -1529,8 +1574,10 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in spin_unlock_irqrestore(&ioc->diagLock, flags); /* Wait a fixed amount of time for the TM pending flag to be cleared. - * If we time out and not bus reset, then we return a FAILED status to the caller. - * The call to mptscsih_tm_pending_wait() will set the pending flag if we are + * If we time out and not bus reset, then we return a FAILED status + * to the caller. + * The call to mptscsih_tm_pending_wait() will set the pending flag + * if we are * successful. Otherwise, reload the FW. */ if (mptscsih_tm_pending_wait(hd) == FAILED) { @@ -1540,18 +1587,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in hd->ioc->name, hd->tmPending)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { - dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: " - "Timed out waiting for last TM (%d) to complete! \n", - hd->ioc->name, hd->tmPending)); + dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target " + "reset: Timed out waiting for last TM (%d) " + "to complete! \n", hd->ioc->name, + hd->tmPending)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: " "Timed out waiting for last TM (%d) to complete! \n", hd->ioc->name, hd->tmPending)); - if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)) - return FAILED; - - doTask = 0; + return FAILED; } } else { spin_lock_irqsave(&hd->ioc->FreeQlock, flags); @@ -1559,47 +1604,40 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); } - /* Is operational? - */ ioc_raw_state = mpt_GetIocState(hd->ioc, 0); -#ifdef MPT_DEBUG_RESET if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { printk(MYIOC_s_WARN_FMT - "TM Handler: IOC Not operational(0x%x)!\n", - hd->ioc->name, ioc_raw_state); - } -#endif - - if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) - && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) { - - /* Isse the Task Mgmt request. - */ - if (hd->hard_resets < -1) - hd->hard_resets++; - rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout); - if (rc) { - printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); - } else { - dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name)); - } + "TM Handler for type=%x: IOC Not operational (0x%x)!\n", + ioc->name, type, ioc_raw_state); + printk(KERN_WARNING " Issuing HardReset!!\n"); + if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) + printk((KERN_WARNING "TMHandler: HardReset " + "FAILED!!\n")); + return FAILED; } - /* Only fall through to the HRH if this is a bus reset - */ - if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc || - ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) { - dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", - hd->ioc->name)); - rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); + if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { + printk(MYIOC_s_WARN_FMT + "TM Handler for type=%x: ioc_state: " + "DOORBELL_ACTIVE (0x%x)!\n", + ioc->name, type, ioc_raw_state); + return FAILED; } - /* - * Check IOCStatus from TM reply message + /* Isse the Task Mgmt request. */ - if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS) - rc = FAILED; + if (hd->hard_resets < -1) + hd->hard_resets++; + + rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, + ctx2abort, timeout); + if (rc) + printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", + hd->ioc->name); + else + dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", + hd->ioc->name)); dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc)); @@ -1608,11 +1646,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mptscsih_IssueTaskMgmt - Generic send Task Management function. * @hd: Pointer to MPT_SCSI_HOST structure * @type: Task Management type - * @target: Logical Target ID for reset (if appropriate) + * @id: Logical Target ID for reset (if appropriate) * @lun: Logical Unit for reset (if appropriate) * @ctx2abort: Context for the task to be aborted (if appropriate) * @@ -1621,11 +1659,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in * * Not all fields are meaningfull for all task types. * - * Returns 0 for SUCCESS, -999 for "no msg frames", - * else other non-zero value returned. - */ + * Returns 0 for SUCCESS, or FAILED. + * + **/ static int -mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) +mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) { MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; @@ -1645,7 +1683,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun /* Format the Request */ pScsiTm = (SCSITaskMgmt_t *) mf; - pScsiTm->TargetID = target; + pScsiTm->TargetID = id; pScsiTm->Bus = channel; pScsiTm->ChainOffset = 0; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; @@ -1656,42 +1694,59 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0; - for (ii= 0; ii < 8; ii++) { - pScsiTm->LUN[ii] = 0; - } - pScsiTm->LUN[1] = lun; + int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN); for (ii=0; ii < 7; ii++) pScsiTm->Reserved2[ii] = 0; pScsiTm->TaskMsgContext = ctx2abort; - dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n", - hd->ioc->name, ctx2abort, type)); + dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " + "type=%d\n", hd->ioc->name, ctx2abort, type)); DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm); if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc, - sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, - CAN_SLEEP)) != 0) { - dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" - " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, - hd->ioc, mf)); - mpt_free_msg_frame(hd->ioc, mf); - return retval; + sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { + dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!" + " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd, + hd->ioc, mf, retval)); + goto fail_out; } if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { - dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!" + dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!" " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf)); - mpt_free_msg_frame(hd->ioc, mf); dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", hd->ioc->name)); retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); + dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n", + hd->ioc->name, retval)); + goto fail_out; } + /* + * Handle success case, see if theres a non-zero ioc_status. + */ + if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS || + hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || + hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) + retval = 0; + else + retval = FAILED; + return retval; + + fail_out: + + /* + * Free task managment mf, and corresponding tm flags + */ + mpt_free_msg_frame(hd->ioc, mf); + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; + return FAILED; } static int @@ -1716,7 +1771,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) * (linux scsi_host_template.eh_abort_handler routine) * * Returns SUCCESS or FAILED. - */ + **/ int mptscsih_abort(struct scsi_cmnd * SCpnt) { @@ -1752,9 +1807,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) return SUCCESS; } - if (hd->resetPending) { + if (hd->resetPending) return FAILED; - } if (hd->timeouts < -1) hd->timeouts++; @@ -1777,13 +1831,12 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, - vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun, + vdev->vtarget->channel, vdev->vtarget->id, vdev->lun, ctx2abort, mptscsih_get_tm_timeout(hd->ioc)); if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx && - SCpnt->serial_number == sn) { + SCpnt->serial_number == sn) retval = FAILED; - } printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", hd->ioc->name, @@ -1791,12 +1844,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) if (retval == 0) return SUCCESS; - - if(retval != FAILED ) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - } - return FAILED; + else + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1807,7 +1856,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) * (linux scsi_host_template.eh_dev_reset_handler routine) * * Returns SUCCESS or FAILED. - */ + **/ int mptscsih_dev_reset(struct scsi_cmnd * SCpnt) { @@ -1833,7 +1882,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - vdev->vtarget->bus_id, vdev->vtarget->target_id, + vdev->vtarget->channel, vdev->vtarget->id, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", @@ -1842,14 +1891,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) if (retval == 0) return SUCCESS; - - if(retval != FAILED ) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - } - return FAILED; + else + return FAILED; } + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant @@ -1858,7 +1904,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) * (linux scsi_host_template.eh_bus_reset_handler routine) * * Returns SUCCESS or FAILED. - */ + **/ int mptscsih_bus_reset(struct scsi_cmnd * SCpnt) { @@ -1884,7 +1930,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); + vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", hd->ioc->name, @@ -1892,18 +1938,13 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) if (retval == 0) return SUCCESS; - - if(retval != FAILED ) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - } - return FAILED; + else + return FAILED; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mptscsih_host_reset - Perform a SCSI host adapter RESET! - * new_eh variant + * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant) * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to * * (linux scsi_host_template.eh_host_reset_handler routine) @@ -1949,8 +1990,7 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mptscsih_tm_pending_wait - wait for pending task management request to - * complete. + * mptscsih_tm_pending_wait - wait for pending task management request to complete * @hd: Pointer to MPT host structure. * * Returns {SUCCESS,FAILED}. @@ -2055,7 +2095,7 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) * load/init time via the mpt_register() API call. * * Returns 1 indicating alloc'd request frame ptr should be freed. - */ + **/ int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) { @@ -2065,78 +2105,85 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m unsigned long flags; u16 iocstatus; u8 tmType; + u32 termination_count; dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", - ioc->name, mf, mr)); - if (ioc->sh) { - /* Depending on the thread, a timer is activated for - * the TM request. Delete this timer on completion of TM. - * Decrement count of outstanding TM requests. - */ - hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; - } else { - dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n", - ioc->name)); + ioc->name, mf, mr)); + if (!ioc->sh) { + dtmprintk((MYIOC_s_WARN_FMT + "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); return 1; } if (mr == NULL) { - dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n", - ioc->name, mf)); + dtmprintk((MYIOC_s_WARN_FMT + "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf)); return 1; - } else { - pScsiTmReply = (SCSITaskMgmtReply_t*)mr; - pScsiTmReq = (SCSITaskMgmt_t*)mf; - - /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */ - tmType = pScsiTmReq->TaskType; + } - if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && - pScsiTmReply->ResponseCode) - mptscsih_taskmgmt_response_code(ioc, - pScsiTmReply->ResponseCode); + hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + pScsiTmReply = (SCSITaskMgmtReply_t*)mr; + pScsiTmReq = (SCSITaskMgmt_t*)mf; + tmType = pScsiTmReq->TaskType; + iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; + termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); + + if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && + pScsiTmReply->ResponseCode) + mptscsih_taskmgmt_response_code(ioc, + pScsiTmReply->ResponseCode); + DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); + +#if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM) + printk("%s: ha=%d [%d:%d:0] task_type=0x%02X " + "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X " + "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus, + pScsiTmReply->TargetID, pScsiTmReq->TaskType, + le16_to_cpu(pScsiTmReply->IOCStatus), + le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode, + le32_to_cpu(pScsiTmReply->TerminationCount)); +#endif + if (!iocstatus) { + dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name)); + hd->abortSCpnt = NULL; + goto out; + } - dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n", - ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount))); - DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); + /* Error? (anything non-zero?) */ - iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; - hd->tm_iocstatus = iocstatus; - dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n", - ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo))); - /* Error? (anything non-zero?) */ - if (iocstatus) { + /* clear flags and continue. + */ + switch (tmType) { - /* clear flags and continue. - */ - if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) - hd->abortSCpnt = NULL; + case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK: + if (termination_count == 1) + iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED; + hd->abortSCpnt = NULL; + break; - /* If an internal command is present - * or the TM failed - reload the FW. - * FC FW may respond FAILED to an ABORT - */ - if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { - if ((hd->cmdPtr) || - (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) { - if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) { - printk((KERN_WARNING - " Firmware Reload FAILED!!\n")); - } - } - } - } else { - dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name)); + case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS: - hd->abortSCpnt = NULL; + /* If an internal command is present + * or the TM failed - reload the FW. + * FC FW may respond FAILED to an ABORT + */ + if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED || + hd->cmdPtr) + if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) + printk((KERN_WARNING " Firmware Reload FAILED!!\n")); + break; - } + case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: + default: + break; } + out: spin_lock_irqsave(&ioc->FreeQlock, flags); hd->tmPending = 0; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); hd->tmState = TM_STATE_NONE; + hd->tm_iocstatus = iocstatus; + spin_unlock_irqrestore(&ioc->FreeQlock, flags); return 1; } @@ -2180,7 +2227,7 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, dprintk((KERN_NOTICE ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n", - sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors)); + sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors)); return 0; } @@ -2189,115 +2236,78 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, * */ int -mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) +mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) { + struct inactive_raid_component_info *component_info; int i; + int rc = 0; - if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) - return 0; + if (!ioc->raid_data.pIocPg3) + goto out; for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { - if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) - return 1; - } - return 0; -} -EXPORT_SYMBOL(mptscsih_is_phys_disk); - -int -mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) -{ - int i; - - if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3) - return -ENXIO; - - for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) { - if (physdiskid == - hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) - return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; + if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && + (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { + rc = 1; + goto out; + } } - return -ENXIO; -} -EXPORT_SYMBOL(mptscsih_raid_id_to_num); + /* + * Check inactive list for matching phys disks + */ + if (list_empty(&ioc->raid_data.inactive_list)) + goto out; -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * OS entry point to allow host driver to alloc memory - * for each scsi target. Called once per device the bus scan. - * Return non-zero if allocation fails. - */ -int -mptscsih_target_alloc(struct scsi_target *starget) -{ - VirtTarget *vtarget; + down(&ioc->raid_data.inactive_list_mutex); + list_for_each_entry(component_info, &ioc->raid_data.inactive_list, + list) { + if ((component_info->d.PhysDiskID == id) && + (component_info->d.PhysDiskBus == channel)) + rc = 1; + } + up(&ioc->raid_data.inactive_list_mutex); - vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); - if (!vtarget) - return -ENOMEM; - starget->hostdata = vtarget; - vtarget->starget = starget; - return 0; + out: + return rc; } +EXPORT_SYMBOL(mptscsih_is_phys_disk); -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * OS entry point to allow host driver to alloc memory - * for each scsi device. Called once per device the bus scan. - * Return non-zero if allocation fails. - */ -int -mptscsih_slave_alloc(struct scsi_device *sdev) +u8 +mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) { - struct Scsi_Host *host = sdev->host; - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; - VirtTarget *vtarget; - VirtDevice *vdev; - struct scsi_target *starget; + struct inactive_raid_component_info *component_info; + int i; + int rc = -ENXIO; - vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); - if (!vdev) { - printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", - hd->ioc->name, sizeof(VirtDevice)); - return -ENOMEM; + if (!ioc->raid_data.pIocPg3) + goto out; + for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { + if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && + (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { + rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; + goto out; + } } - vdev->lun = sdev->lun; - sdev->hostdata = vdev; - - starget = scsi_target(sdev); - vtarget = starget->hostdata; + /* + * Check inactive list for matching phys disks + */ + if (list_empty(&ioc->raid_data.inactive_list)) + goto out; - vdev->vtarget = vtarget; - - if (vtarget->num_luns == 0) { - hd->Targets[sdev->id] = vtarget; - vtarget->ioc_id = hd->ioc->id; - vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; - vtarget->target_id = sdev->id; - vtarget->bus_id = sdev->channel; - if (hd->ioc->bus_type == SPI && sdev->channel == 0 && - hd->ioc->raid_data.isRaid & (1 << sdev->id)) { - vtarget->raidVolume = 1; - ddvtprintk((KERN_INFO - "RAID Volume @ id %d\n", sdev->id)); - } + down(&ioc->raid_data.inactive_list_mutex); + list_for_each_entry(component_info, &ioc->raid_data.inactive_list, + list) { + if ((component_info->d.PhysDiskID == id) && + (component_info->d.PhysDiskBus == channel)) + rc = component_info->d.PhysDiskNum; } - vtarget->num_luns++; - return 0; -} + up(&ioc->raid_data.inactive_list_mutex); -/* - * OS entry point to allow for host driver to free allocated memory - * Called if no device present or device being unloaded - */ -void -mptscsih_target_destroy(struct scsi_target *starget) -{ - if (starget->hostdata) - kfree(starget->hostdata); - starget->hostdata = NULL; + out: + return rc; } +EXPORT_SYMBOL(mptscsih_raid_id_to_num); /* * OS entry point to allow for host driver to free allocated memory @@ -2317,11 +2327,7 @@ mptscsih_slave_destroy(struct scsi_device *sdev) vdevice = sdev->hostdata; mptscsih_search_running_cmds(hd, vdevice); - vtarget->luns[0] &= ~(1 << vdevice->lun); vtarget->num_luns--; - if (vtarget->num_luns == 0) { - hd->Targets[sdev->id] = NULL; - } mptscsih_synchronize_cache(hd, vdevice); kfree(vdevice); sdev->hostdata = NULL; @@ -2383,15 +2389,14 @@ mptscsih_slave_configure(struct scsi_device *sdev) VirtDevice *vdevice; struct scsi_target *starget; MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata; - int indexed_lun, lun_index; starget = scsi_target(sdev); vtarget = starget->hostdata; vdevice = sdev->hostdata; dsprintk((MYIOC_s_INFO_FMT - "device @ %p, id=%d, LUN=%d, channel=%d\n", - hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel)); + "device @ %p, channel=%d, id=%d, lun=%d\n", + hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun)); if (hd->ioc->bus_type == SPI) dsprintk((MYIOC_s_INFO_FMT "sdtr %d wdtr %d ppr %d inq length=%d\n", @@ -2404,11 +2409,7 @@ mptscsih_slave_configure(struct scsi_device *sdev) goto slave_configure_exit; } - vdevice->configured_lun=1; - lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */ - indexed_lun = (vdevice->lun % 32); - vtarget->luns[lun_index] |= (1 << indexed_lun); - mptscsih_initTarget(hd, vtarget, sdev); + vdevice->configured_lun = 1; mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); dsprintk((MYIOC_s_INFO_FMT @@ -2670,284 +2671,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) return 1; /* currently means nothing really */ } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptscsih_initTarget - Target, LUN alloc/free functionality. - * @hd: Pointer to MPT_SCSI_HOST structure - * @vtarget: per target private data - * @sdev: SCSI device - * - * NOTE: It's only SAFE to call this routine if data points to - * sane & valid STANDARD INQUIRY data! - * - * Allocate and initialize memory for this target. - * Save inquiry data. - * - */ -static void -mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, - struct scsi_device *sdev) -{ - dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", - hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd)); - - /* Is LUN supported? If so, upper 2 bits will be 0 - * in first byte of inquiry data. - */ - if (sdev->inq_periph_qual != 0) - return; - - if (vtarget == NULL) - return; - - vtarget->type = sdev->type; - - if (hd->ioc->bus_type != SPI) - return; - - if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) { - /* Treat all Processors as SAF-TE if - * command line option is set */ - vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; - mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); - }else if ((sdev->type == TYPE_PROCESSOR) && - !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { - if (sdev->inquiry_len > 49 ) { - if (sdev->inquiry[44] == 'S' && - sdev->inquiry[45] == 'A' && - sdev->inquiry[46] == 'F' && - sdev->inquiry[47] == '-' && - sdev->inquiry[48] == 'T' && - sdev->inquiry[49] == 'E' ) { - vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; - mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id); - } - } - } - mptscsih_setTargetNegoParms(hd, vtarget, sdev); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Update the target negotiation parameters based on the - * the Inquiry data, adapter capabilities, and NVRAM settings. - * - */ -static void -mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, - struct scsi_device *sdev) -{ - SpiCfgData *pspi_data = &hd->ioc->spi_data; - int id = (int) target->target_id; - int nvram; - u8 width = MPT_NARROW; - u8 factor = MPT_ASYNC; - u8 offset = 0; - u8 nfactor; - u8 noQas = 1; - - target->negoFlags = pspi_data->noQas; - - /* noQas == 0 => device supports QAS. */ - - if (sdev->scsi_level < SCSI_2) { - width = 0; - factor = MPT_ULTRA2; - offset = pspi_data->maxSyncOffset; - target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; - } else { - if (scsi_device_wide(sdev)) { - width = 1; - } - - if (scsi_device_sync(sdev)) { - factor = pspi_data->minSyncFactor; - if (!scsi_device_dt(sdev)) - factor = MPT_ULTRA2; - else { - if (!scsi_device_ius(sdev) && - !scsi_device_qas(sdev)) - factor = MPT_ULTRA160; - else { - factor = MPT_ULTRA320; - if (scsi_device_qas(sdev)) { - ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id)); - noQas = 0; - } - if (sdev->type == TYPE_TAPE && - scsi_device_ius(sdev)) - target->negoFlags |= MPT_TAPE_NEGO_IDP; - } - } - offset = pspi_data->maxSyncOffset; - - /* If RAID, never disable QAS - * else if non RAID, do not disable - * QAS if bit 1 is set - * bit 1 QAS support, non-raid only - * bit 0 IU support - */ - if (target->raidVolume == 1) { - noQas = 0; - } - } else { - factor = MPT_ASYNC; - offset = 0; - } - } - - if (!sdev->tagged_supported) { - target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; - } - - /* Update tflags based on NVRAM settings. (SCSI only) - */ - if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { - nvram = pspi_data->nvram[id]; - nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; - - if (width) - width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; - - if (offset > 0) { - /* Ensure factor is set to the - * maximum of: adapter, nvram, inquiry - */ - if (nfactor) { - if (nfactor < pspi_data->minSyncFactor ) - nfactor = pspi_data->minSyncFactor; - - factor = max(factor, nfactor); - if (factor == MPT_ASYNC) - offset = 0; - } else { - offset = 0; - factor = MPT_ASYNC; - } - } else { - factor = MPT_ASYNC; - } - } - - /* Make sure data is consistent - */ - if ((!width) && (factor < MPT_ULTRA2)) { - factor = MPT_ULTRA2; - } - - /* Save the data to the target structure. - */ - target->minSyncFactor = factor; - target->maxOffset = offset; - target->maxWidth = width; - - target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; - - /* Disable unused features. - */ - if (!width) - target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; - - if (!offset) - target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; - - if ( factor > MPT_ULTRA320 ) - noQas = 0; - - 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 due to noQas=%02x on id=%d!\n", noQas, id)); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SCSI Config Page functionality ... - */ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* 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(ioc->DoneCtx, ioc)) == NULL) { - dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n", - ioc->name)); - return -EAGAIN; - } - - /* 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->ExtPageLength = 0; - pReq->ExtPageType = 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); - - dinitprintk((MYIOC_s_INFO_FMT - "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", - ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus)); - - mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); - - return 0; -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Bus Scan and Domain Validation functionality ... @@ -3331,7 +3054,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; } else { pScsiReq->TargetID = io->id; - pScsiReq->Bus = io->bus; + pScsiReq->Bus = io->channel; pScsiReq->ChainOffset = 0; pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; } @@ -3344,9 +3067,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) pScsiReq->MsgFlags = mpt_msg_flags(); /* MsgContext set in mpt_get_msg_fram call */ - for (ii=0; ii < 8; ii++) - pScsiReq->LUN[ii] = 0; - pScsiReq->LUN[1] = io->lun; + int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN); if (io->flags & MPT_ICFLAG_TAGGED_CMD) pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ); @@ -3367,7 +3088,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) + (my_idx * MPT_SENSE_BUFFER_ALLOC)); ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n", - hd->ioc->name, cmd, io->bus, io->id, io->lun)); + hd->ioc->name, cmd, io->channel, io->id, io->lun)); if (dir == MPI_SCSIIO_CONTROL_READ) { mpt_add_sge((char *) &pScsiReq->SGL, @@ -3429,8 +3150,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) /** * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks. * @hd: Pointer to a SCSI HOST structure - * @vtarget: per device private data - * @lun: lun + * @vdevice: virtual target device * * Uses the ISR, but with special processing. * MUST be single-threaded. @@ -3451,9 +3171,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) iocmd.data_dma = -1; iocmd.size = 0; iocmd.rsvd = iocmd.rsvd2 = 0; - iocmd.bus = vdevice->vtarget->bus_id; - iocmd.id = vdevice->vtarget->target_id; - iocmd.lun = (u8)vdevice->lun; + iocmd.channel = vdevice->vtarget->channel; + iocmd.id = vdevice->vtarget->id; + iocmd.lun = vdevice->lun; if ((vdevice->vtarget->type == TYPE_DISK) && (vdevice->configured_lun)) @@ -3469,9 +3189,6 @@ EXPORT_SYMBOL(mptscsih_resume); EXPORT_SYMBOL(mptscsih_proc_info); EXPORT_SYMBOL(mptscsih_info); EXPORT_SYMBOL(mptscsih_qcmd); -EXPORT_SYMBOL(mptscsih_target_alloc); -EXPORT_SYMBOL(mptscsih_slave_alloc); -EXPORT_SYMBOL(mptscsih_target_destroy); EXPORT_SYMBOL(mptscsih_slave_destroy); EXPORT_SYMBOL(mptscsih_slave_configure); EXPORT_SYMBOL(mptscsih_abort);