⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mptscsih.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				/* 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 + -