📄 mptscsih.c
字号:
if (hd->Targets != NULL) { int max, ii; /* * Free any target structures that were allocated. */ if (hd->is_spi) { max = MPT_MAX_SCSI_DEVICES; } else { max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; } for (ii=0; ii < max; ii++) { if (hd->Targets[ii]) { kfree(hd->Targets[ii]); hd->Targets[ii] = NULL; sztarget += sizeof(VirtDevice); } } /* * Free pointer array. */ sz3 = max * sizeof(void *); kfree(hd->Targets); hd->Targets = NULL; } dprintk((MYIOC_s_INFO_FMT "Free'd ScsiLookup (%d) Target (%d+%d) memory\n", hd->ioc->name, sz1, sz3, sztarget)); dprintk(("Free'd done and free Q (%d) memory\n", szQ)); /* 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 /* Evaluate the command line arguments, if any */ if (mptscsih) mptscsih_setup(mptscsih);#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);}#ifndef MPTSCSIH_DBG_TIMEOUTstatic int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len){ /* Not yet implemented */ return len;}#else#define is_digit(c) ((c) >= '0' && (c) <= '9')#define digit_to_bin(c) ((c) - '0')#define is_space(c) ((c) == ' ' || (c) == '\t')#define UC_DBG_TIMEOUT 0x01#define UC_DBG_HARDRESET 0x02static int skip_spaces(char *ptr, int len){ int cnt, c; for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt --); return (len - cnt);}static int get_int_arg(char *ptr, int len, ulong *pv){ int cnt, c; ulong v; for (v = 0, cnt = len; cnt > 0 && (c=*ptr++) && is_digit(c); cnt --) { v = (v * 10) + digit_to_bin(c); } if (pv) *pv = v; return (len - cnt);}static int is_keyword(char *ptr, int len, char *verb){ int verb_len = strlen(verb); if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len)) return verb_len; else return 0;}#define SKIP_SPACES(min_spaces) \ if ((arg_len = skip_spaces(ptr,len)) < (min_spaces)) \ return -EINVAL; \ ptr += arg_len; \ len -= arg_len;#define GET_INT_ARG(v) \ if (!(arg_len = get_int_arg(ptr,len, &(v)))) \ return -EINVAL; \ ptr += arg_len; \ len -= arg_len;static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length){ char *ptr = buffer; char btmp[24]; /* REMOVE */ int arg_len; int len = length; int cmd; ulong number = 1; ulong delta = 10; if ((len > 0) && (ptr[len -1] == '\n')) --len; if (len < 22) { strncpy(btmp, buffer, len); btmp[len+1]='\0'; } else { strncpy(btmp, buffer, 22); btmp[23]='\0'; } printk("user_command: ioc %d, buffer %s, length %d\n", ioc->id, btmp, length); if ((arg_len = is_keyword(ptr, len, "timeout")) != 0) cmd = UC_DBG_TIMEOUT; else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0) cmd = UC_DBG_HARDRESET; else return -EINVAL; ptr += arg_len; len -= arg_len; switch(cmd) { case UC_DBG_TIMEOUT: SKIP_SPACES(1); GET_INT_ARG(number); SKIP_SPACES(1); GET_INT_ARG(delta); break; } printk("user_command: cnt=%ld delta=%ld\n", number, delta); if (len) return -EINVAL; else { if (cmd == UC_DBG_HARDRESET) { ioc->timeout_hard = 1; } else if (cmd == UC_DBG_TIMEOUT) { /* process this command ... */ ioc->timeout_maxcnt = 0; ioc->timeout_delta = delta < 2 ? 2 : delta; ioc->timeout_cnt = 0; ioc->timeout_maxcnt = number < 8 ? number: 8; } } /* Not yet implemented */ return length;}#endif/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * 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 int mptscsih_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) { size = mptscsih_user_command(ioc, buffer, length); } 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -