📄 mptscsih.c
字号:
} //return SUCCESS; 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(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 ": IOs outstanding = %d\n", atomic_read(&queue_depth)); hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata; if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {/* SCpnt->result = DID_SOFT_ERROR << 16; */ SCpnt->result = STS_BUSY; SCpnt->scsi_done(SCpnt); return FAILED; } pScsiTm = (SCSITaskMgmt_t *) mf; msg = (u32*)mf; pScsiTm->TargetID = SCpnt->target; pScsiTm->Bus = hd->port; pScsiTm->ChainOffset = 0; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; pScsiTm->Reserved = 0; 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; /* Control: No data direction, set task mgmt bit? */ for (i = 0; i < 7; i++) pScsiTm->Reserved2[i] = 0; pScsiTm->TaskMsgContext = cpu_to_le32(0);/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake mpt_put_msg_frame(hd->ioc->id, mf);*//* FIXME! Check return status! */ 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 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(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 ": IOs outstanding = %d\n", atomic_read(&queue_depth)); hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata; if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {/* SCpnt->result = DID_SOFT_ERROR << 16; */ SCpnt->result = STS_BUSY; SCpnt->scsi_done(SCpnt); return FAILED; } pScsiTm = (SCSITaskMgmt_t *) mf; msg = (u32 *) mf; pScsiTm->TargetID = SCpnt->target; pScsiTm->Bus = hd->port; pScsiTm->ChainOffset = 0; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; pScsiTm->Reserved = 0; pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; pScsiTm->Reserved1 = 0; pScsiTm->MsgFlags = 0; for (i = 0; i < 8; i++) pScsiTm->LUN[i] = 0; /* Control: No data direction, set task mgmt bit? */ for (i = 0; i < 7; i++) pScsiTm->Reserved2[i] = 0; pScsiTm->TaskMsgContext = cpu_to_le32(0);/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake mpt_put_msg_frame(hd->ioc->id, mf);*//* FIXME! Check return status! */ 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;}#if 0 /* { *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * 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(Scsi_Cmnd * SCpnt){ return FAILED;}#endif /* } */#else /* MPT_SCSI old EH stuff... *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptscsih_old_abort - Abort linux Scsi_Cmnd routine * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted * * (linux Scsi_Host_Template.abort routine) * * Returns SCSI_ABORT_{SUCCESS,BUSY,PENDING}. */intmptscsih_old_abort(Scsi_Cmnd *SCpnt){ MPT_SCSI_HOST *hd; MPT_FRAME_HDR *mf; struct tq_struct *ptaskfoo; unsigned long flags; printk(KERN_WARNING MYNAM ": Scheduling _ABORT SCSI IO (=%p)\n", SCpnt); printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth)); if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) { SCpnt->result = DID_ABORT << 16; SCpnt->scsi_done(SCpnt); return SCSI_ABORT_SUCCESS; } /* * Check to see if there's already an ABORT queued for this guy. */ mf = search_taskQ(0,SCpnt,MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK); if (mf != NULL) { return SCSI_ABORT_PENDING; } if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {/* SCpnt->result = DID_SOFT_ERROR << 16; */ SCpnt->result = STS_BUSY; SCpnt->scsi_done(SCpnt); return SCSI_ABORT_BUSY; } /* * Add ourselves to (end of) mpt_scsih_taskQ. * Check to see if our _bh is running. If NOT, schedule it. */ dslprintk((KERN_INFO MYNAM ": spinlock#2\n")); spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags); Q_ADD_TAIL(&mpt_scsih_taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR); mpt_scsih_taskQ_cnt++; /* Yikes - linkage! *//* SCpnt->host_scribble = (unsigned char *)mf; */ mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK; mf->u.frame.linkage.argp1 = SCpnt; if (! mpt_scsih_taskQ_bh_active) { mpt_scsih_taskQ_bh_active = 1; /* * Oh how cute, no alloc/free/mgmt needed if we use * (bottom/unused portion of) MPT request frame. */ ptaskfoo = (struct tq_struct *) ((u8*)mf + hd->ioc->req_sz - sizeof(*ptaskfoo)); ptaskfoo->sync = 0; ptaskfoo->routine = mptscsih_taskmgmt_bh; ptaskfoo->data = SCpnt; SCHEDULE_TASK(ptaskfoo); } spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags); return SCSI_ABORT_PENDING;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptscsih_old_reset - Perform a SCSI BUS_RESET! * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to * @reset_flags: (not used?) * * (linux Scsi_Host_Template.reset routine) * * Returns SCSI_RESET_{SUCCESS,PUNT,PENDING}. */intmptscsih_old_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags){ MPT_SCSI_HOST *hd; MPT_FRAME_HDR *mf; struct tq_struct *ptaskfoo; unsigned long flags; printk(KERN_WARNING MYNAM ": Scheduling _BUS_RESET (=%p)\n", SCpnt); printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth)); if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) { SCpnt->result = DID_RESET << 16; SCpnt->scsi_done(SCpnt); return SCSI_RESET_SUCCESS; } /* * Check to see if there's already a BUS_RESET queued for this guy. */ mf = search_taskQ(0,SCpnt,MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS); if (mf != NULL) { return SCSI_RESET_PENDING; } if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {/* SCpnt->result = DID_SOFT_ERROR << 16; */ SCpnt->result = STS_BUSY; SCpnt->scsi_done(SCpnt); return SCSI_RESET_PUNT; } /* * Add ourselves to (end of) mpt_scsih_taskQ. * Check to see if our _bh is running. If NOT, schedule it. */ dslprintk((KERN_INFO MYNAM ": spinlock#3\n")); spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags); Q_ADD_TAIL(&mpt_scsih_taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR); mpt_scsih_taskQ_cnt++; /* Yikes - linkage! *//* SCpnt->host_scribble = (unsigned char *)mf; */ mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; mf->u.frame.linkage.argp1 = SCpnt; if (! mpt_scsih_taskQ_bh_active) { mpt_scsih_taskQ_bh_active = 1; /* * Oh how cute, no alloc/free/mgmt needed if we use * (bottom/unused portion of) MPT request frame. */ ptaskfoo = (struct tq_struct *) ((u8*)mf + hd->ioc->req_sz - sizeof(*ptaskfoo)); ptaskfoo->sync = 0; ptaskfoo->routine = mptscsih_taskmgmt_bh; ptaskfoo->data = SCpnt; SCHEDULE_TASK(ptaskfoo); } spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags); return SCSI_RESET_PENDING;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptscsih_taskmgmt_bh - SCSI task mgmt bottom half handler * @sc: (unused) * * This routine (thread) is active whenever there are any outstanding * SCSI task management requests for a SCSI host adapter. * IMPORTANT! This routine is scheduled therefore should never be * running in ISR context. i.e., it's safe to sleep here. */voidmptscsih_taskmgmt_bh(void *sc){ Scsi_Cmnd *SCpnt; MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; MPT_SCSI_HOST *hd; u32 ctx2abort = 0; int i; unsigned long flags; u8 task_type; dslprintk((KERN_INFO MYNAM ": spinlock#4\n")); spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags); mpt_scsih_taskQ_bh_active = 1; 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. */ dslprintk((KERN_INFO MYNAM ": spinlock#5\n")); spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags); if (Q_IS_EMPTY(&mpt_scsih_taskQ)) { spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags); break; } mf = mpt_scsih_taskQ.head; Q_DEL_ITEM(&mf->u.frame.linkage); mpt_scsih_taskQ_cnt--; mpt_scsih_active_taskmgmt_mf = mf; spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags); 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); continue; } hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata; pScsiTm = (SCSITaskMgmt_t *) mf; for (i = 0; i < 8; i++) { pScsiTm->LUN[i] = 0; } task_type = mf->u.frame.linkage.arg1; 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) * * 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 */ 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=%p:sc=%p)\n", mf, SCpnt); }#if 0 else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {} else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET) {}#endif printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth)); pScsiTm->TargetID = SCpnt->target; pScsiTm->Bus = hd->port; pScsiTm->ChainOffset = 0; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; pScsiTm->Reserved = 0; pScsiTm->TaskType = task_type; pScsiTm->Reserved1 = 0; pScsiTm->MsgFlags = 0; for (i = 0; i < 7; i++) pScsiTm->Reserved2[i] = 0; dprintk((KERN_INFO MYNAM ":DbG: ctx2abort = %08x\n", ctx2abort)); pScsiTm->TaskMsgContext = ctx2abort; /* Control: No data direction, set task mgmt bit? */ /* * As of MPI v0.10 this request can NOT be sent (normally) * via FIFOs. So we can't: * mpt_put_msg_frame(ScsiTaskCtx, hd->ioc->id, mf); * SCSITaskMgmt requests MUST be sent ONLY via * Doorbell/handshake now. :-( */ 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); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -