📄 mptscsih.c
字号:
if (sg) dest = (u8 *) (unsigned long)sg_dma_address(sg); } if (dest && mpt_sdev->sense_sz) { memcpy(dest, mpt_sdev->CachedSense.data, mpt_sdev->sense_sz);#ifdef MPT_DEBUG { int i; u8 *sb; sb = mpt_sdev->CachedSense.data; if (sb && ((sb[0] & 0x70) == 0x70)) { printk(KERN_WARNING MYNAM ": Returning last cached SCSI (hex) SenseData:\n"); printk(KERN_WARNING " "); for (i = 0; i < (8 + sb[7]); i++) printk("%s%02x", i == 13 ? "-" : " ", sb[i]); printk("\n"); } }#endif } SCpnt->resid = SCpnt->request_bufflen - mpt_sdev->sense_sz; SCpnt->result = 0;/* spin_lock(&io_request_lock); */ SCpnt->scsi_done(SCpnt);/* spin_unlock(&io_request_lock); */ return 0; } }#endif if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {/* SCpnt->result = DID_SOFT_ERROR << 16; */ SCpnt->result = STS_BUSY; SCpnt->scsi_done(SCpnt);/* return 1; */ return 0; } pScsiReq = (SCSIIORequest_t *) mf; my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); ADD_INDEX_LOG(my_idx); /* Map the data portion, if any. */ sges_left = SCpnt->use_sg; if (sges_left) { sges_left = pci_map_sg(hd->ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, sges_left, scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); } else if (SCpnt->request_bufflen) { dma_addr_t buf_dma_addr; buf_dma_addr = pci_map_single(hd->ioc->pcidev, SCpnt->request_buffer, SCpnt->request_bufflen, scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); /* We hide it here for later unmap. */ SCpnt->SCp.ptr = (char *)(unsigned long) buf_dma_addr; } /* * Put together a MPT SCSI request... */ /* Assume SimpleQ, NO DATA XFER for now */ len = SCpnt->request_bufflen; sgdir = 0x00000000; /* SGL IN (host<--ioc) */ scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER; /* * The scsi layer should be handling this stuff * (In 2.3.x it does -DaveM) */ /* BUG FIX! 19991030 -sralston * TUR's being issued with scsictl=0x02000000 (DATA_IN)! * Seems we may receive a buffer (len>0) even when there * will be no data transfer! GRRRRR... */ datadir = mptscsih_io_direction(SCpnt); if (datadir < 0) { scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */ } else if (datadir > 0) { sgdir = 0x04000000; /* SGL OUT (host-->ioc) */ scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */ } else { len = 0; } qtag = MPI_SCSIIO_CONTROL_SIMPLEQ; /* * Attach tags to the devices */ if (SCpnt->device->tagged_supported) { /* * Some drives are too stupid to handle fairness issues * with tagged queueing. We throw in the odd ordered * tag to stop them starving themselves. */ if ((jiffies - hd->qtag_tick) > (5*HZ)) { qtag = MPI_SCSIIO_CONTROL_ORDEREDQ; hd->qtag_tick = jiffies;#if 0 /* These are ALWAYS zero! * (Because this is a place for the device driver to dynamically * assign tag numbers any way it sees fit. That's why -DaveM) */ dprintk((KERN_DEBUG MYNAM ": sc->device->current_tag = %08x\n", SCpnt->device->current_tag)); dprintk((KERN_DEBUG MYNAM ": sc->tag = %08x\n", SCpnt->tag));#endif }#if 0 else { /* Hmmm... I always see value of 0 here, * of which {HEAD_OF, ORDERED, SIMPLE} are NOT! -sralston * (Because this is a place for the device driver to dynamically * assign tag numbers any way it sees fit. That's why -DaveM) * * if (SCpnt->tag == HEAD_OF_QUEUE_TAG) */ if (SCpnt->device->current_tag == HEAD_OF_QUEUE_TAG) qtag = MPI_SCSIIO_CONTROL_HEADOFQ; else if (SCpnt->tag == ORDERED_QUEUE_TAG) qtag = MPI_SCSIIO_CONTROL_ORDEREDQ; }#endif } scsictl = scsidir | qtag; frm_sz = hd->ioc->req_sz; /* Ack! * sge_spill1 = 9; */ sge_spill1 = (frm_sz - (sizeof(SCSIIORequest_t) - sizeof(SGEIOUnion_t) + sizeof(SGEChain32_t))) / 8; /* spill1: for req_sz == 128 (128-48==80, 80/8==10 SGEs max, first time!), --> use 9 * spill1: for req_sz == 96 ( 96-48==48, 48/8== 6 SGEs max, first time!), --> use 5 */ dsgprintk((KERN_INFO MYNAM ": SG: %x spill1 = %d\n", my_idx, sge_spill1));#ifdef MPT_DEBUG if (sges_left > max_sges) { max_sges = sges_left; dprintk((KERN_INFO MYNAM ": MPT_MaxSges = %d\n", max_sges)); }#endif#if 0 if (sges_left > max_num_sges) { max_num_sges = sges_left; printk(KERN_INFO MYNAM ": MPT_MaxNumSges = %d\n", max_num_sges); }#endif dsgprintk((KERN_INFO MYNAM ": SG: %x sges_left = %d (initially)\n", my_idx, sges_left)); chain_offset = 0; if (sges_left > (sge_spill1+1)) {#if 0 chain_offset = 0x1E;#endif chain_offset = (frm_sz - 8) / 4; } pScsiReq->TargetID = SCpnt->target; pScsiReq->Bus = hd->port; pScsiReq->ChainOffset = chain_offset; pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; pScsiReq->CDBLength = SCpnt->cmd_len;/* We have 256 bytes alloc'd per IO; let's use it. *//* pScsiReq->SenseBufferLength = SNS_LEN(SCpnt); */ pScsiReq->SenseBufferLength = 255; pScsiReq->Reserved = 0; pScsiReq->MsgFlags = 0; pScsiReq->LUN[0] = 0; pScsiReq->LUN[1] = SCpnt->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; pScsiReq->Control = cpu_to_le32(scsictl); /* * Write SCSI CDB into the message */ for (i = 0; i < 12; i++) pScsiReq->CDB[i] = SCpnt->cmnd[i]; for (i = 12; i < 16; i++) pScsiReq->CDB[i] = 0; /* DataLength */ pScsiReq->DataLength = cpu_to_le32(len); /* SenseBuffer low address */ pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_pool_dma + (my_idx * 256)); mptr = (u32 *) &pScsiReq->SGL; /* * Now fill in the SGList... * NOTES: For 128 byte req_sz, we can hold up to 10 simple SGE's * in the remaining request frame. We -could- do unlimited chains * but each chain buffer can only be req_sz bytes in size, and * we lose one SGE whenever we chain. * For 128 req_sz, we can hold up to 16 SGE's per chain buffer. * For practical reasons, limit ourselves to 1 overflow chain buffer; * giving us 9 + 16 == 25 SGE's max. * At 4 Kb per SGE, that yields 100 Kb max transfer. * * (This code needs to be completely changed when/if 64-bit DMA * addressing is used, since we will be able to fit much less than * 10 embedded SG entries. -DaveM) */ if (sges_left) { struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer; u32 v1, v2; int sge_spill2; int sge_cur_spill; int sgCnt; u8 *pSgBucket; int chain_sz; len = 0; /* sge_spill2 = 15; * spill2: for req_sz == 128 (128/8==16 SGEs max, first time!), --> use 15 * spill2: for req_sz == 96 ( 96/8==12 SGEs max, first time!), --> use 11 */ sge_spill2 = frm_sz / 8 - 1; dsgprintk((KERN_INFO MYNAM ": SG: %x spill2 = %d\n", my_idx, sge_spill2)); pSgBucket = NULL; sgCnt = 0; sge_cur_spill = sge_spill1; while (sges_left) {#if 0 if (sg_dma_len(sg) > max_sgent_len) { max_sgent_len = sg_dma_len(sg); printk(KERN_INFO MYNAM ": MPT_MaxSgentLen = %d\n", max_sgent_len); }#endif /* Write one simple SGE */ v1 = sgdir | 0x10000000 | sg_dma_len(sg); len += sg_dma_len(sg); v2 = sg_dma_address(sg); dsgprintk((KERN_INFO MYNAM ": SG: %x Writing SGE @%p: %08x %08x, sges_left=%d\n", my_idx, mptr, v1, v2, sges_left)); *mptr++ = cpu_to_le32(v1); *mptr++ = cpu_to_le32(v2); sg++; sgCnt++; if (--sges_left == 0) { /* re-write 1st word of previous SGE with SIMPLE, * LE, EOB, and EOL bits! */ v1 = 0xD1000000 | sgdir | sg_dma_len(sg-1); dsgprintk((KERN_INFO MYNAM ": SG: %x (re)Writing SGE @%p: %08x (VERY LAST SGE!)\n", my_idx, mptr-2, v1)); *(mptr - 2) = cpu_to_le32(v1); } else { if ((sges_left > 1) && ((sgCnt % sge_cur_spill) == 0)) { dsgprintk((KERN_INFO MYNAM ": SG: %x SG spill at modulo 0!\n", my_idx)); /* Fixup previous SGE with LE bit! */ v1 = sgdir | 0x90000000 | sg_dma_len(sg-1); dsgprintk((KERN_INFO MYNAM ": SG: %x (re)Writing SGE @%p: %08x (LAST BUCKET SGE!)\n", my_idx, mptr-2, v1)); *(mptr - 2) = cpu_to_le32(v1); chain_offset = 0; /* Going to need another chain? */ if (sges_left > (sge_spill2+1)) {#if 0 chain_offset = 0x1E;#endif chain_offset = (frm_sz - 8) / 4; chain_sz = frm_sz; } else { chain_sz = sges_left * 8; } /* write chain SGE at mptr. */ v1 = 0x30000000 | chain_offset<<16 | chain_sz; if (pSgBucket == NULL) { pSgBucket = hd->SgHunks + (my_idx * frm_sz * MPT_SG_BUCKETS_PER_HUNK); } else { pSgBucket += frm_sz; } v2 = (hd->SgHunksDMA + ((u8 *)pSgBucket - (u8 *)hd->SgHunks)); dsgprintk((KERN_INFO MYNAM ": SG: %x Writing SGE @%p: %08x %08x (CHAIN!)\n", my_idx, mptr, v1, v2)); *(mptr++) = cpu_to_le32(v1); *(mptr) = cpu_to_le32(v2); mptr = (u32 *) pSgBucket; sgCnt = 0; sge_cur_spill = sge_spill2; } } } } else { dsgprintk((KERN_INFO MYNAM ": SG: non-SG for %p, len=%d\n", SCpnt, SCpnt->request_bufflen)); if (len > 0) { dma_addr_t buf_dma_addr; buf_dma_addr = (dma_addr_t) (unsigned long)SCpnt->SCp.ptr; *(mptr++) = cpu_to_le32(0xD1000000|sgdir|SCpnt->request_bufflen); *(mptr++) = cpu_to_le32(buf_dma_addr); } }#ifdef MPT_DEBUG /* if (SCpnt->request_bufflen > max_xfer) */ if (len > max_xfer) { max_xfer = len; dprintk((KERN_INFO MYNAM ": MPT_MaxXfer = %d\n", max_xfer)); }#endif hd->ScsiLookup[my_idx] = SCpnt; /* Main banana... */ mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf); atomic_inc(&queue_depth); if (atomic_read(&queue_depth) > max_qd) { max_qd = atomic_read(&queue_depth); dprintk((KERN_INFO MYNAM ": Queue depth now %d.\n", max_qd)); } dmfprintk((KERN_INFO MYNAM ": Issued SCSI cmd (%p)\n", SCpnt)); return 0;}#ifdef MPT_SCSI_USE_NEW_EH /* { *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* mptscsih_abort Returns: 0=SUCCESS, else FAILED*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted * * (linux Scsi_Host_Template.eh_abort_handler routine) * * Returns SUCCESS or FAILED. */intmptscsih_abort(Scsi_Cmnd * SCpnt){ MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; MPT_SCSI_HOST *hd; u32 *msg; u32 ctx2abort; int i; unsigned long flags; printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO (=%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_ABORT_TASK; pScsiTm->Reserved1 = 0; pScsiTm->MsgFlags = 0; for (i = 0; i < 8; i++) { u8 val = 0; if (i == 1) val = SCpnt->lun; pScsiTm->LUN[i] = val; } for (i = 0; i < 7; i++) pScsiTm->Reserved2[i] = 0; /* 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(#2) 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); } else { dprintk((KERN_INFO MYNAM ":DbG: ctx2abort = %08x\n", ctx2abort)); pScsiTm->TaskMsgContext = ctx2abort; /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake mpt_put_msg_frame(hd->ioc->id, mf); */ if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id, sizeof(SCSITaskMgmt_t), msg)) != 0) { printk(KERN_WARNING MYNAM ": WARNING[2] - 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); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -