📄 mptscsih.c
字号:
sc->target, pScsiReq->LUN[1], sc->buffer, xfer_cnt); } if (hd->is_spi) mptscsih_set_dvflags(hd, pScsiReq, sc->buffer); break; case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus; clear_sense_flag(hd, pScsiReq); if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { /* * If running agains circa 200003dd 909 MPT f/w, * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL * (QUEUE_FULL) returned from device! --> get 0x0000?128 * and with SenseBytes set to 0. */ if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL) mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);#ifndef MPT_SCSI_USE_NEW_EH /* ADDED 20011120 -sralston * Scsi mid-layer (old_eh) doesn't seem to like it * when RAID returns SCSIStatus=02 (CHECK CONDITION), * SenseKey=01 (RECOVERED ERROR), ASC/ASCQ=95/01. * Seems to be * treating this as a IO error:-( * * So just lie about it altogether here. * * NOTE: It still gets reported to syslog via * mpt_ScsiHost_ErrorReport from copy_sense_data * call far above. */ if ( pScsiReply->SCSIStatus == STS_CHECK_CONDITION && SD_Sense_Key(sc->sense_buffer) == SK_RECOVERED_ERROR ) { sc->result = 0; }#endif } else if (pScsiReply->SCSIState & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS) ) { /* * What to do? */ sc->result = DID_SOFT_ERROR << 16; } else if (pScsiReply->SCSIState & MPI_SCSI_STATE_TERMINATED) { /* Not real sure here either... */ sc->result = DID_RESET << 16; } else if (pScsiReply->SCSIState & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) { /* Device Inq. data indicates that it supports * QTags, but rejects QTag messages. * This command completed OK. * * Not real sure here either so do nothing... */ } if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL) mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); /* Add handling of: * Reservation Conflict, Busy, * Command Terminated, CHECK */ /* If regular Inquiry cmd - save inquiry data */ xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); if ( sc->result == (DID_OK << 16) && pScsiReq->CDB[0] == INQUIRY && !(pScsiReq->CDB[1] & 0x3) && xfer_cnt >= SCSI_STD_INQUIRY_BYTES ) { mptscsih_initTarget(hd, hd->port, sc->target, pScsiReq->LUN[1], sc->buffer, xfer_cnt); } if (hd->is_spi) mptscsih_set_dvflags(hd, pScsiReq, sc->buffer); break; case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ if (pScsiReply->SCSIState & MPI_SCSI_STATE_TERMINATED) { /* Not real sure here either... */ sc->result = DID_RESET << 16; } else sc->result = DID_SOFT_ERROR << 16; break; case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */ case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */ case MPI_IOCSTATUS_RESERVED: /* 0x0005 */ case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */ case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */ case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */ case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ default: /* * What to do? */ sc->result = DID_SOFT_ERROR << 16; break; } /* switch(status) */ dprintk((KERN_NOTICE " sc->result set to %08xh\n", sc->result)); } /* end of address reply case */ /* Unmap the DMA buffers, if any. */ if (sc->use_sg) { pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer, sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction)); } else if (sc->request_bufflen) { scPrivate *my_priv; my_priv = (scPrivate *) &sc->SCp; pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1, sc->request_bufflen, scsi_to_pci_dma_dir(sc->sc_data_direction)); } hd->ScsiLookup[req_idx] = NULL; sc->host_scribble = NULL; /* CHECKME! - Do we need to clear this??? */ spin_lock_irqsave(&io_request_lock, flags); sc->scsi_done(sc); /* Issue the command callback */ spin_unlock_irqrestore(&io_request_lock, flags); /* Free Chain buffers */ mptscsih_freeChainBuffers(hd, req_idx); return 1;}#ifndef MPT_SCSI_USE_NEW_EH /* { *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * search_taskQ - Search SCSI task mgmt request queue for specific * request type. * @remove: (Boolean) Should request be removed if found? * @sc: Pointer to Scsi_Cmnd structure * @task_type: Task type to search for * * Returns pointer to MPT request frame if found, or %NULL if request * was not found. */static MPT_FRAME_HDR *search_taskQ(int remove, Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, u8 task_type){ MPT_FRAME_HDR *mf = NULL; unsigned long flags; int count = 0; int list_sz; dprintk((KERN_INFO MYNAM ": search_taskQ(%d,sc=%p,%d) called\n", remove, sc, task_type)); spin_lock_irqsave(&hd->ioc->FreeQlock, flags); list_sz = hd->taskQcnt; if (! Q_IS_EMPTY(&hd->taskQ)) { mf = hd->taskQ.head; do { count++; if (mf->u.frame.linkage.argp1 == sc && mf->u.frame.linkage.arg1 == task_type) { if (remove) { Q_DEL_ITEM(&mf->u.frame.linkage); hd->taskQcnt--; atomic_dec(&mpt_taskQdepth); /* Don't save mf into nextmf because * exit after command has been deleted. */ /* Place the MF back on the FreeQ */ Q_ADD_TAIL(&hd->ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);#ifdef MFCNT hd->ioc->mfcnt--;#endif } break; } } while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&hd->taskQ); if (mf == (MPT_FRAME_HDR*)&hd->taskQ) { mf = NULL; } } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); if (list_sz) { dprintk((KERN_INFO " Results=%p (%sFOUND%s)!\n", mf, mf ? "" : "NOT_", (mf && remove) ? "+REMOVED" : "" )); dprintk((KERN_INFO " (searched thru %d of %d items on taskQ)\n", count, list_sz )); } return mf;}/* * clean_taskQ - Clean the SCSI task mgmt request for * this SCSI host instance. * @hd: MPT_SCSI_HOST pointer * * Returns: None. */static voidclean_taskQ(MPT_SCSI_HOST *hd){ MPT_FRAME_HDR *mf = NULL; MPT_FRAME_HDR *nextmf = NULL; MPT_ADAPTER *ioc = hd->ioc; unsigned long flags; dprintk((KERN_INFO MYNAM ": clean_taskQ called\n")); spin_lock_irqsave(&ioc->FreeQlock, flags); if (! Q_IS_EMPTY(&hd->taskQ)) { mf = hd->taskQ.head; do { Q_DEL_ITEM(&mf->u.frame.linkage); hd->taskQcnt--; atomic_dec(&mpt_taskQdepth); nextmf = mf->u.frame.linkage.forw; /* Place the MF back on the FreeQ */ Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);#ifdef MFCNT hd->ioc->mfcnt--;#endif } while ((mf = nextmf) != (MPT_FRAME_HDR*)&hd->taskQ); } spin_unlock_irqrestore(&ioc->FreeQlock, flags); return;}/* * search_taskQ_for_cmd - Search the SCSI task mgmt request queue for * the specified command. If found, delete * @hd: MPT_SCSI_HOST pointer * * Returns: None. */static voidsearch_taskQ_for_cmd(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd){ MPT_FRAME_HDR *mf = NULL; unsigned long flags; int count = 0; dprintk((KERN_INFO MYNAM ": search_taskQ_for_cmd(sc=%p) called\n", sc)); spin_lock_irqsave(&hd->ioc->FreeQlock, flags); if (! Q_IS_EMPTY(&hd->taskQ)) { mf = hd->taskQ.head; do { count++; if (mf->u.frame.linkage.argp1 == sc) { Q_DEL_ITEM(&mf->u.frame.linkage); hd->taskQcnt--; atomic_dec(&mpt_taskQdepth); dprintk((KERN_INFO MYNAM ": Cmd %p found! Deleting.\n", sc)); /* Don't save mf into nextmf because * exit after command has been deleted. */ /* Place the MF back on the FreeQ */ Q_ADD_TAIL(&hd->ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);#ifdef MFCNT hd->ioc->mfcnt--;#endif break; } } while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&hd->taskQ); } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); return;}#endif /* } MPT_SCSI_USE_NEW_EH *//* * Flush all commands on the doneQ. * Lock Q when deleting/adding members * Lock io_request_lock for OS callback. */static voidflush_doneQ(MPT_SCSI_HOST *hd){ MPT_DONE_Q *buffer; Scsi_Cmnd *SCpnt; unsigned long flags; /* Flush the doneQ. */ dprintk((KERN_INFO MYNAM ": flush_doneQ called\n")); while (1) { spin_lock_irqsave(&hd->freedoneQlock, flags); if (Q_IS_EMPTY(&hd->doneQ)) { spin_unlock_irqrestore(&hd->freedoneQlock, flags); break; } buffer = hd->doneQ.head; /* Delete from Q */ Q_DEL_ITEM(buffer); /* Set the Scsi_Cmnd pointer */ SCpnt = (Scsi_Cmnd *) buffer->argp; buffer->argp = NULL; /* Add to the freeQ */ Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); spin_unlock_irqrestore(&hd->freedoneQlock, flags); /* Do the OS callback. */ spin_lock_irqsave(&io_request_lock, flags); SCpnt->scsi_done(SCpnt); spin_unlock_irqrestore(&io_request_lock, flags); } return;}/* * Search the doneQ for a specific command. If found, delete from Q. * Calling function will finish processing. */static voidsearch_doneQ_for_cmd(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt){ unsigned long flags; MPT_DONE_Q *buffer; spin_lock_irqsave(&hd->freedoneQlock, flags); if (!Q_IS_EMPTY(&hd->doneQ)) { buffer = hd->doneQ.head; do { Scsi_Cmnd *sc = (Scsi_Cmnd *) buffer->argp; if (SCpnt == sc) { Q_DEL_ITEM(buffer); SCpnt->result = sc->result; /* Set the Scsi_Cmnd pointer */ buffer->argp = NULL; /* Add to the freeQ */ Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q); break; } } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ); } spin_unlock_irqrestore(&hd->freedoneQlock, flags); return;}/* * mptscsih_flush_running_cmds - For each command found, search * Scsi_Host instance taskQ and reply to OS. * Called only if recovering from a FW reload. * @hd: Pointer to a SCSI HOST structure * * Returns: None. * * Must be called while new I/Os are being queued. */static voidmptscsih_flush_running_cmds(MPT_SCSI_HOST *hd){ Scsi_Cmnd *SCpnt = NULL; MPT_FRAME_HDR *mf = NULL; int ii; int max = hd->ioc->req_depth; unsigned long flags; dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n")); for (ii= 0; ii < max; ii++) { if ((SCpnt = hd->ScsiLookup[ii]) != NULL) { /* Command found. */#ifndef MPT_SCSI_USE_NEW_EH /* Search taskQ, if found, delete. */ search_taskQ_for_cmd(SCpnt, hd);#endif /* Search pendingQ, if found, * delete from Q. If found, do not decrement * queue_depth, command never posted. */ if (mptscsih_search_pendingQ(hd, ii) == NULL) atomic_dec(&queue_depth); /* Null ScsiLookup index */ hd->ScsiLookup[ii] = NULL; mf = MPT_INDEX_2_MFPTR(hd->ioc, ii); dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n", mf, SCpnt)); /* Set status * Do OS callback * Free chain buffers * Free message frame */ SCpnt->result = DID_RESET << 16; SCpnt->host_scribble = NULL; spin_lock_irqsave(&io_request_lock, flags); SCpnt->scsi_done(SCpnt); /* Issue the command callback */ spin_unlock_irqrestore(&io_request_lock, flags); /* Free Chain buffers */ mptscsih_freeChainBuffers(hd, ii); /* Free Message frames */ mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf); } } return;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptscsih_initChainBuffers - Allocate memory for and initialize * chain buffers, chain buffer control arrays and spinlock. * @hd: Pointer to MPT_SCSI_HOST structure * @init: If set, initialize the spin lock. */static intmptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -