📄 mptscsih.c
字号:
*/ if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: hidden raid component (sc=%p)\n", ioc->name, SCpnt)); SCpnt->result = DID_RESET << 16; retval = FAILED; goto out; } /* Find this command */ if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) { /* Cmd not found in ScsiLookup. * Do OS callback. */ SCpnt->result = DID_RESET << 16; dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: " "Command not in the active list! (sc=%p)\n", ioc->name, SCpnt)); retval = 0; goto out; } if (hd->resetPending) { retval = FAILED; goto out; } if (hd->timeouts < -1) hd->timeouts++; /* Most important! Set TaskMsgContext to SCpnt's MsgContext! * (the IO to be ABORT'd) * * NOTE: Since we do not byteswap MsgContext, we do not * swap it here either. It is an opaque cookie to * the controller, so it does not matter. -DaveM */ mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx); ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; hd->abortSCpnt = SCpnt; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, ctx2abort, mptscsih_get_tm_timeout(ioc)); if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx && SCpnt->serial_number == sn) retval = FAILED; out: printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n", ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); if (retval == 0) return SUCCESS; else return FAILED;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * 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_dev_reset_handler routine) * * Returns SUCCESS or FAILED. **/intmptscsih_dev_reset(struct scsi_cmnd * SCpnt){ MPT_SCSI_HOST *hd; int retval; VirtDevice *vdevice; MPT_ADAPTER *ioc; /* If we can't locate our host adapter structure, return FAILED status. */ if ((hd = shost_priv(SCpnt->device->host)) == NULL){ printk(KERN_ERR MYNAM ": target reset: " "Can't locate host! (sc=%p)\n", SCpnt); return FAILED; } ioc = hd->ioc; printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n", ioc->name, SCpnt); scsi_print_command(SCpnt); if (hd->resetPending) { retval = FAILED; goto out; } vdevice = SCpnt->device->hostdata; if (!vdevice || !vdevice->vtarget) { retval = 0; goto out; } /* Target reset to hidden raid component is not supported */ if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { retval = FAILED; goto out; } retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0, mptscsih_get_tm_timeout(ioc)); out: printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n", ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); if (retval == 0) return SUCCESS; else return FAILED;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * 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_bus_reset_handler routine) * * Returns SUCCESS or FAILED. **/intmptscsih_bus_reset(struct scsi_cmnd * SCpnt){ MPT_SCSI_HOST *hd; int retval; VirtDevice *vdevice; MPT_ADAPTER *ioc; /* If we can't locate our host adapter structure, return FAILED status. */ if ((hd = shost_priv(SCpnt->device->host)) == NULL){ printk(KERN_ERR MYNAM ": bus reset: " "Can't locate host! (sc=%p)\n", SCpnt); return FAILED; } ioc = hd->ioc; printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n", ioc->name, SCpnt); scsi_print_command(SCpnt); if (hd->timeouts < -1) hd->timeouts++; vdevice = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc)); printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n", ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); if (retval == 0) return SUCCESS; else return FAILED;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * 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) * * Returns SUCCESS or FAILED. */intmptscsih_host_reset(struct scsi_cmnd *SCpnt){ MPT_SCSI_HOST * hd; int retval; MPT_ADAPTER *ioc; /* If we can't locate the host to reset, then we failed. */ if ((hd = shost_priv(SCpnt->device->host)) == NULL){ printk(KERN_ERR MYNAM ": host reset: " "Can't locate host! (sc=%p)\n", SCpnt); return FAILED; } ioc = hd->ioc; printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n", ioc->name, SCpnt); /* If our attempts to reset the host failed, then return a failed * status. The host will be taken off line by the SCSI mid-layer. */ if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) { retval = FAILED; } else { /* Make sure TM pending is cleared and TM state is set to * NONE. */ retval = 0; hd->tmPending = 0; hd->tmState = TM_STATE_NONE; } printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n", ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); return retval;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptscsih_tm_pending_wait - wait for pending task management request to complete * @hd: Pointer to MPT host structure. * * Returns {SUCCESS,FAILED}. */static intmptscsih_tm_pending_wait(MPT_SCSI_HOST * hd){ unsigned long flags; int loop_count = 4 * 10; /* Wait 10 seconds */ int status = FAILED; MPT_ADAPTER *ioc = hd->ioc; do { spin_lock_irqsave(&ioc->FreeQlock, flags); if (hd->tmState == TM_STATE_NONE) { hd->tmState = TM_STATE_IN_PROGRESS; hd->tmPending = 1; spin_unlock_irqrestore(&ioc->FreeQlock, flags); status = SUCCESS; break; } spin_unlock_irqrestore(&ioc->FreeQlock, flags); msleep(250); } while (--loop_count); return status;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptscsih_tm_wait_for_completion - wait for completion of TM task * @hd: Pointer to MPT host structure. * @timeout: timeout value * * Returns {SUCCESS,FAILED}. */static intmptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ){ unsigned long flags; int loop_count = 4 * timeout; int status = FAILED; MPT_ADAPTER *ioc = hd->ioc; do { spin_lock_irqsave(&ioc->FreeQlock, flags); if(hd->tmPending == 0) { status = SUCCESS; spin_unlock_irqrestore(&ioc->FreeQlock, flags); break; } spin_unlock_irqrestore(&ioc->FreeQlock, flags); msleep(250); } while (--loop_count); return status;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static voidmptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code){ char *desc; switch (response_code) { case MPI_SCSITASKMGMT_RSP_TM_COMPLETE: desc = "The task completed."; break; case MPI_SCSITASKMGMT_RSP_INVALID_FRAME: desc = "The IOC received an invalid frame status."; break; case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: desc = "The task type is not supported."; break; case MPI_SCSITASKMGMT_RSP_TM_FAILED: desc = "The requested task failed."; break; case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED: desc = "The task completed successfully."; break; case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN: desc = "The LUN request is invalid."; break; case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: desc = "The task is in the IOC queue and has not been sent to target."; break; default: desc = "unknown"; break; } printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n", ioc->name, response_code, desc);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver * @ioc: Pointer to MPT_ADAPTER structure * @mf: Pointer to SCSI task mgmt request frame * @mr: Pointer to SCSI task mgmt reply frame * * This routine is called from mptbase.c::mpt_interrupt() at the completion * of any SCSI task management request. * This routine is registered with the MPT (base) driver at driver * load/init time via the mpt_register() API call. * * Returns 1 indicating alloc'd request frame ptr should be freed. **/intmptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr){ SCSITaskMgmtReply_t *pScsiTmReply; SCSITaskMgmt_t *pScsiTmReq; MPT_SCSI_HOST *hd; unsigned long flags; u16 iocstatus; u8 tmType; u32 termination_count; dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", ioc->name, mf, mr)); if (!ioc->sh) { dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); return 1; } if (mr == NULL) { dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf)); return 1; } hd = shost_priv(ioc->sh); 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(ioc, (u32 *)pScsiTmReply);#ifdef CONFIG_FUSION_LOGGING if ((ioc->debug_level & MPT_DEBUG_REPLY) || (ioc->debug_level & 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(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name)); hd->abortSCpnt = NULL; goto out; } /* Error? (anything non-zero?) */ /* clear flags and continue. */ switch (tmType) { case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK: if (termination_count == 1) iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED; hd->abortSCpnt = NULL; break; case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS: /* 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(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name); break; case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: default: break; } out: spin_lock_irqsave(&ioc->FreeQlock, flags); hd->tmPending = 0; hd->tmState = TM_STATE_NONE; hd->tm_iocstatus = iocstatus; spin_unlock_irqrestore(&ioc->FreeQlock, flags); return 1;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * This is anyones guess quite frankly. */intmptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, sector_t capacity, int geom[]){ int heads; int sectors; sector_t cylinders; ulong dummy; heads = 64; sectors = 32; dummy = heads * sectors; cylinders = capacity; sector_div(cylinders,dummy); /* * Handle extended translation size for logical drives * > 1Gb */ if ((ulong)capacity >=
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -