📄 mptscsih.c
字号:
"Free'd ScsiLookup (%d) memory\n", hd->ioc->name, sz1)); /* NULL the Scsi_Host pointer */ hd->ioc->sh = NULL; } scsi_host_put(host); mpt_scsi_hosts--;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptscsih_shutdown - reboot notifier * */static voidmptscsih_shutdown(struct device * dev){ MPT_ADAPTER *ioc = pci_get_drvdata(to_pci_dev(dev)); 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 scsie driver suspend routine. * * */static intmptscsih_suspend(struct pci_dev *pdev, u32 state){ mptscsih_shutdown(&pdev->dev); return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptscsih_resume - Fusion MPT scsi driver resume routine. * * */static intmptscsih_resume(struct pci_dev *pdev){ MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct Scsi_Host *host = ioc->sh; MPT_SCSI_HOST *hd; 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(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd); schedule_work(&mptscsih_dvTask); } else { spin_unlock_irqrestore(&dvtaskQ_lock, lflags); } }#endif return 0;}#endifstatic struct mpt_pci_driver mptscsih_driver = { .probe = mptscsih_probe, .remove = mptscsih_remove, .shutdown = mptscsih_shutdown,#ifdef CONFIG_PM .suspend = mptscsih_suspend, .resume = mptscsih_resume,#endif};/* SCSI host fops start here... *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptscsih_init - Register MPT adapter(s) as SCSI host(s) with * linux scsi mid-layer. * * Returns 0 for success, non-zero for failure. */static int __initmptscsih_init(void){ show_mptmod_ver(my_NAME, my_VERSION); ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER); ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER); ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER); if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) { devtprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) { dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); }#ifdef MODULE dinitprintk((KERN_INFO MYNAM ": Command Line Args: dv=%d max_width=%d " "factor=0x%x saf_te=%d\n", dv, width, factor, saf_te)); driver_setup.dv = (dv) ? 1 : 0; driver_setup.max_width = (width) ? 1 : 0; driver_setup.min_sync_factor = factor; driver_setup.saf_te = (saf_te) ? 1 : 0;;#endif if(mpt_device_driver_register(&mptscsih_driver, MPTSCSIH_DRIVER) != 0 ) { dprintk((KERN_INFO MYNAM ": failed to register dd callbacks\n")); } return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptscsih_exit - Unregisters MPT adapter(s) * */static void __exitmptscsih_exit(void){ mpt_device_driver_deregister(MPTSCSIH_DRIVER); mpt_reset_deregister(ScsiDoneCtx); dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n")); mpt_event_deregister(ScsiDoneCtx); dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n")); mpt_deregister(ScsiScanDvCtx); mpt_deregister(ScsiTaskCtx); mpt_deregister(ScsiDoneCtx); if (info_kbuf != NULL) kfree(info_kbuf);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * 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. */static const char *mptscsih_info(struct Scsi_Host *SChost){ MPT_SCSI_HOST *h; int size = 0; if (info_kbuf == NULL) if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL) return info_kbuf; h = (MPT_SCSI_HOST *)SChost->hostdata; info_kbuf[0] = '\0'; if (h) { mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0); info_kbuf[size-1] = '\0'; } return info_kbuf;}struct info_str { char *buffer; int length; int offset; int pos;};static void 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 int 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); copy_mem_info(info, buf, len); return len;}static int mptscsih_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; copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name); copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word); copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts); 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 */static 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) */static intmptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)){ MPT_SCSI_HOST *hd; MPT_FRAME_HDR *mf; SCSIIORequest_t *pScsiReq; VirtDevice *pTarget; int target; int lun; u32 datalen; u32 scsictl; u32 scsidir; u32 cmd_len; int my_idx; int ii; hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; target = SCpnt->device->id; lun = SCpnt->device->lun; SCpnt->scsi_done = done; pTarget = hd->Targets[target]; 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(ScsiDoneCtx, 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); /* BUG FIX! 19991030 -sralston * 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) target; pScsiReq->Bus = (u8) SCpnt->device->channel; 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; pScsiReq->LUN[1] = 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 */ cmd_len = SCpnt->cmd_len; for (ii=0; ii < cmd_len; ii++) pScsiReq->CDB[ii] = SCpnt->cmnd[ii]; for (ii=cmd_len; ii < 16; ii++) pScsiReq->CDB[ii] = 0; /* DataLength */ pScsiReq->DataLength = cpu_to_le32(datalen); /* SenseBuffer low address */ pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma + (my_idx * MPT_SENSE_BUFFER_ALLOC)); /* Now add the SG list * Always have a SGE even if null length. */ if (datalen == 0) { /* Add a NULL SGE */ mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); } else { /* Add a 32 or 64 bit SGE */ if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS) goto fail; } hd->ScsiLookup[my_idx] = SCpnt; SCpnt->host_scribble = NULL;#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION if (hd->ioc->bus_type == SCSI) { int dvStatus = hd->ioc->spi_data.dvStatus[target]; int issueCmd = 1; if (dvStatus || hd->ioc->spi_data.forceDv) { if ((dvStatus & MPT_SCSICFG_NEED_DV) || (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) { unsigned long lflags;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -