📄 mptscsih.c
字号:
struct scsi_cmnd *sc; dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n", target, lun, max)); for (ii=0; ii < max; ii++) { if ((sc = hd->ScsiLookup[ii]) != NULL) { mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); 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)target)) || (mf->LUN[1] != ((u8) lun))) continue; /* Cleanup */ hd->ScsiLookup[ii] = NULL; mptscsih_freeChainBuffers(hd->ioc, ii); mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf); if (sc->use_sg) { pci_unmap_sg(hd->ioc->pcidev, (struct scatterlist *) sc->request_buffer, sc->use_sg, sc->sc_data_direction); } else if (sc->request_bufflen) { pci_unmap_single(hd->ioc->pcidev, sc->SCp.dma_handle, sc->request_bufflen, sc->sc_data_direction); } sc->host_scribble = NULL; sc->result = DID_NO_CONNECT << 16; sc->scsi_done(sc); } } return;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptscsih_report_queue_full - Report QUEUE_FULL status returned * from a SCSI target device. * @sc: Pointer to scsi_cmnd structure * @pScsiReply: Pointer to SCSIIOReply_t * @pScsiReq: Pointer to original SCSI request * * This routine periodically reports QUEUE_FULL status returned from a * SCSI target device. It reports this to the console via kernel * printk() API call, not more than once every 10 seconds. */static voidmptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq){ long time = jiffies; MPT_SCSI_HOST *hd; if (sc->device == NULL) return; if (sc->device->host == NULL) return; if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL) return; if (time - hd->last_queue_full > 10 * HZ) { dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", hd->ioc->name, 0, sc->device->id, sc->device->lun)); hd->last_queue_full = time; }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptscsih_remove - Removed scsi devices * @pdev: Pointer to pci_dev structure * * */voidmptscsih_remove(struct pci_dev *pdev){ MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct Scsi_Host *host = ioc->sh; MPT_SCSI_HOST *hd; int count; unsigned long flags; int sz1; if(!host) { mpt_detach(pdev); return; } scsi_remove_host(host); if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL) return;#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION /* Check DV thread active */ count = 10 * HZ; spin_lock_irqsave(&dvtaskQ_lock, flags); if (dvtaskQ_active) { spin_unlock_irqrestore(&dvtaskQ_lock, flags); while(dvtaskQ_active && --count) schedule_timeout_interruptible(1); } else { spin_unlock_irqrestore(&dvtaskQ_lock, flags); } if (!count) printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) else printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);#endif#endif mptscsih_shutdown(pdev); sz1=0; if (hd->ScsiLookup != NULL) { sz1 = hd->ioc->req_depth * sizeof(void *); kfree(hd->ScsiLookup); 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)); kfree(hd->info_kbuf); /* NULL the Scsi_Host pointer */ hd->ioc->sh = NULL; scsi_host_put(host); mpt_detach(pdev);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptscsih_shutdown - reboot notifier * */voidmptscsih_shutdown(struct pci_dev *pdev){ MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct Scsi_Host *host = ioc->sh; MPT_SCSI_HOST *hd; if(!host) return; hd = (MPT_SCSI_HOST *)host->hostdata; /* Flush the cache of this adapter */ if(hd != NULL) mptscsih_synchronize_cache(hd, 0);}#ifdef CONFIG_PM/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptscsih_suspend - Fusion MPT scsi driver suspend routine. * * */intmptscsih_suspend(struct pci_dev *pdev, pm_message_t state){ mptscsih_shutdown(pdev); return mpt_suspend(pdev,state);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptscsih_resume - Fusion MPT scsi driver resume routine. * * */intmptscsih_resume(struct pci_dev *pdev){ MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct Scsi_Host *host = ioc->sh; MPT_SCSI_HOST *hd; mpt_resume(pdev); if(!host) return 0; hd = (MPT_SCSI_HOST *)host->hostdata; if(!hd) return 0;#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION { unsigned long lflags; spin_lock_irqsave(&dvtaskQ_lock, lflags); if (!dvtaskQ_active) { dvtaskQ_active = 1; spin_unlock_irqrestore(&dvtaskQ_lock, lflags); INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd); schedule_work(&dvTaskQ_task); } else { spin_unlock_irqrestore(&dvtaskQ_lock, lflags); } }#endif return 0;}#endif/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptscsih_info - Return information about MPT adapter * @SChost: Pointer to Scsi_Host structure * * (linux scsi_host_template.info routine) * * Returns pointer to buffer where information was written. */const char *mptscsih_info(struct Scsi_Host *SChost){ MPT_SCSI_HOST *h; int size = 0; h = (MPT_SCSI_HOST *)SChost->hostdata; if (h) { if (h->info_kbuf == NULL) if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL) return h->info_kbuf; h->info_kbuf[0] = '\0'; mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0); h->info_kbuf[size-1] = '\0'; } return h->info_kbuf;}struct info_str { char *buffer; int length; int offset; int pos;};static voidmptscsih_copy_mem_info(struct info_str *info, char *data, int len){ if (info->pos + len > info->length) len = info->length - info->pos; if (info->pos + len < info->offset) { info->pos += len; return; } if (info->pos < info->offset) { data += (info->offset - info->pos); len -= (info->offset - info->pos); } if (len > 0) { memcpy(info->buffer + info->pos, data, len); info->pos += len; }}static intmptscsih_copy_info(struct info_str *info, char *fmt, ...){ va_list args; char buf[81]; int len; va_start(args, fmt); len = vsprintf(buf, fmt, args); va_end(args); mptscsih_copy_mem_info(info, buf, len); return len;}static intmptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len){ struct info_str info; info.buffer = pbuf; info.length = len; info.offset = offset; info.pos = 0; mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name); mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word); mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts); mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth); return ((info.pos > info.offset) ? info.pos - info.offset : 0);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptscsih_proc_info - Return information about MPT adapter * * (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 */intmptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func){ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; int size = 0; if (func) { /* * write is not supported */ } else { if (start) *start = buffer; size = mptscsih_host_info(ioc, buffer, offset, length); } return size;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/#define ADD_INDEX_LOG(req_ent) do { } while(0)/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine. * @SCpnt: Pointer to scsi_cmnd structure * @done: Pointer SCSI mid-layer IO completion function * * (linux scsi_host_template.queuecommand routine) * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest * from a linux scsi_cmnd request and send it to the IOC. * * Returns 0. (rtn value discarded by linux scsi mid-layer) */intmptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)){ MPT_SCSI_HOST *hd; MPT_FRAME_HDR *mf; SCSIIORequest_t *pScsiReq; VirtDevice *pTarget = SCpnt->device->hostdata; int lun; u32 datalen; u32 scsictl; u32 scsidir; u32 cmd_len; int my_idx; int ii; hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; lun = SCpnt->device->lun; SCpnt->scsi_done = done; dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n", (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done)); if (hd->resetPending) { dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt)); return SCSI_MLQUEUE_HOST_BUSY; } /* * Put together a MPT SCSI request... */ if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) { dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n", hd->ioc->name)); return SCSI_MLQUEUE_HOST_BUSY; } pScsiReq = (SCSIIORequest_t *) mf; my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); ADD_INDEX_LOG(my_idx); /* TUR's being issued with scsictl=0x02000000 (DATA_IN)! * Seems we may receive a buffer (datalen>0) even when there * will be no data transfer! GRRRRR... */ if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) { datalen = SCpnt->request_bufflen; scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */ } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) { datalen = SCpnt->request_bufflen; scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */ } else { datalen = 0; scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER; } /* Default to untagged. Once a target structure has been allocated, * use the Inquiry data to determine if device supports tagged. */ if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES) && (SCpnt->device->tagged_supported)) { scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; } else { scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED; } /* Use the above information to set up the message frame */ pScsiReq->TargetID = (u8) pTarget->target_id; pScsiReq->Bus = pTarget->bus_id; pScsiReq->ChainOffset = 0; pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; pScsiReq->CDBLength = SCpnt->cmd_len; pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; pScsiReq->Reserved = 0; pScsiReq->MsgFlags = mpt_msg_flags(); pScsiReq->LUN[0] = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -