📄 mptscsih.c
字号:
/* 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 */ break; case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ 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_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) */#ifdef CONFIG_FUSION_LOGGING if (sc->result && (ioc->debug_level & MPT_DEBUG_REPLY)) mptscsih_info_scsiio(ioc, sc, pScsiReply);#endif } /* end of address reply case */ /* Unmap the DMA buffers, if any. */ scsi_dma_unmap(sc); sc->scsi_done(sc); /* Issue the command callback */ /* Free Chain buffers */ mptscsih_freeChainBuffers(ioc, req_idx); return 1;}/* * 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){ MPT_ADAPTER *ioc = hd->ioc; struct scsi_cmnd *sc; SCSIIORequest_t *mf = NULL; int ii; int channel, id; for (ii= 0; ii < ioc->req_depth; ii++) { sc = mptscsih_getclear_scsi_lookup(ioc, ii); if (!sc) continue; mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii); if (!mf) continue; channel = mf->Bus; id = mf->TargetID; mptscsih_freeChainBuffers(ioc, ii); mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf); if ((unsigned char *)mf != sc->host_scribble) continue; scsi_dma_unmap(sc); sc->result = DID_RESET << 16; sc->host_scribble = NULL; sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT "completing cmds: fw_channel %d, fw_id %d, sc=%p," " mf = %p, idx=%x\n", ioc->name, channel, id, sc, mf, ii); sc->scsi_done(sc); }}/* * mptscsih_search_running_cmds - Delete any commands associated * with the specified target and lun. Function called only * when a lun is disable by mid-layer. * Do NOT access the referenced scsi_cmnd structure or * members. Will cause either a paging or NULL ptr error. * (BUT, BUT, BUT, the code does reference it! - mdr) * @hd: Pointer to a SCSI HOST structure * @vdevice: per device private data * * Returns: None. * * Called from slave_destroy. */static voidmptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice){ SCSIIORequest_t *mf = NULL; int ii; struct scsi_cmnd *sc; struct scsi_lun lun; MPT_ADAPTER *ioc = hd->ioc; unsigned long flags; spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); for (ii = 0; ii < ioc->req_depth; ii++) { if ((sc = ioc->ScsiLookup[ii]) != NULL) { mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii); if (mf == NULL) continue; /* If the device is a hidden raid component, then its * expected that the mf->function will be RAID_SCSI_IO */ if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function != MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) continue; int_to_scsilun(vdevice->lun, &lun); if ((mf->Bus != vdevice->vtarget->channel) || (mf->TargetID != vdevice->vtarget->id) || memcmp(lun.scsi_lun, mf->LUN, 8)) continue; if ((unsigned char *)mf != sc->host_scribble) continue; ioc->ScsiLookup[ii] = NULL; spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); mptscsih_freeChainBuffers(ioc, ii); mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf); scsi_dma_unmap(sc); sc->host_scribble = NULL; sc->result = DID_NO_CONNECT << 16; sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT "completing cmds: fw_channel %d," "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel, vdevice->vtarget->id, sc, mf, ii); sc->scsi_done(sc); spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); } } spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 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; MPT_ADAPTER *ioc; if (sc->device == NULL) return; if (sc->device->host == NULL) return; if ((hd = shost_priv(sc->device->host)) == NULL) return; ioc = hd->ioc; if (time - hd->last_queue_full > 10 * HZ) { dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", 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 sz1; if(!host) { mpt_detach(pdev); return; } scsi_remove_host(host); if((hd = shost_priv(host)) == NULL) return; mptscsih_shutdown(pdev); sz1=0; if (ioc->ScsiLookup != NULL) { sz1 = ioc->req_depth * sizeof(void *); kfree(ioc->ScsiLookup); ioc->ScsiLookup = NULL; } dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Free'd ScsiLookup (%d) memory\n", ioc->name, sz1)); kfree(hd->info_kbuf); /* NULL the Scsi_Host pointer */ ioc->sh = NULL; scsi_host_put(host); mpt_detach(pdev);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptscsih_shutdown - reboot notifier * */voidmptscsih_shutdown(struct pci_dev *pdev){}#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){ return mpt_resume(pdev);}#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 = shost_priv(SChost); 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 * @host: scsi host struct * @buffer: if write, user data; if read, buffer for user * @start: returns the buffer address * @offset: if write, 0; if read, the current offset into the buffer from * the previous read. * @length: if write, return length; * @func: write = 1; read = 0 * * (linux scsi_host_template.info routine) */intmptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func){ MPT_SCSI_HOST *hd = shost_priv(host); 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 *vdevice = SCpnt->device->hostdata; int lun; u32 datalen; u32 scsictl; u32 scsidir; u32 cmd_len; int my_idx; int ii; MPT_ADAPTER *ioc; hd = shost_priv(SCpnt->device->host); ioc = hd->ioc; lun = SCpnt->device->lun; SCpnt->scsi_done = done; dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n", ioc->name, SCpnt, done));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -