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

📄 mptscsih.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (scsi_device_online(SCpnt->device)) {				if (SCpnt->use_sg) {					pci_unmap_sg(ioc->pcidev,						(struct scatterlist *) SCpnt->request_buffer,						SCpnt->use_sg,						SCpnt->sc_data_direction);				} else if (SCpnt->request_bufflen) {					pci_unmap_single(ioc->pcidev,						SCpnt->SCp.dma_handle,						SCpnt->request_bufflen,						SCpnt->sc_data_direction);				}			}			SCpnt->result = DID_RESET << 16;			SCpnt->host_scribble = NULL;			/* Free Chain buffers */			mptscsih_freeChainBuffers(ioc, ii);			/* Free Message frames */			mpt_free_msg_frame(ioc, mf);			SCpnt->scsi_done(SCpnt);	/* Issue the command callback */		}	}	return;}/* *	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. *	@hd: Pointer to a SCSI HOST structure *	@target: target id *	@lun: lun * *	Returns: None. * *	Called from slave_destroy. */static voidmptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun){	SCSIIORequest_t	*mf = NULL;	int		 ii;	int		 max = hd->ioc->req_depth;	dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",			target, lun, max));	for (ii=0; ii < max; ii++) {		if (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);		}	}	return;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *  Hack! It might be nice to report if a device is returning QUEUE_FULL *  but maybe not each and every time... */static long last_queue_full = 0;/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	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;	if (time - last_queue_full > 10 * HZ) {		char *ioc_str = "ioc?";		if (sc->device && sc->device->host != NULL && sc->device->host->hostdata != NULL)			ioc_str = ((MPT_SCSI_HOST *)sc->device->host->hostdata)->ioc->name;		dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",				ioc_str, 0, sc->device->id, sc->device->lun));		last_queue_full = time;	}}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static char *info_kbuf = NULL;/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_probe - Installs scsi devices per bus. *	@pdev: Pointer to pci_dev structure * *	Returns 0 for success, non-zero for failure. * */static intmptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id){	struct Scsi_Host	*sh;	MPT_SCSI_HOST		*hd;	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);	unsigned long		 flags;	int			 sz, ii;	int			 numSGE = 0;	int			 scale;	int			 ioc_cap;	u8			*mem;	int			error=0;	/* 20010202 -sralston	 *  Added sanity check on readiness of the MPT adapter.	 */	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {		printk(MYIOC_s_WARN_FMT		  "Skipping because it's not operational!\n",		  ioc->name);		return -ENODEV;	}	if (!ioc->active) {		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",		  ioc->name);		return -ENODEV;	}	/*  Sanity check - ensure at least 1 port is INITIATOR capable	 */	ioc_cap = 0;	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {		if (ioc->pfacts[ii].ProtocolFlags &		    MPI_PORTFACTS_PROTOCOL_INITIATOR)			ioc_cap ++;	}	if (!ioc_cap) {		printk(MYIOC_s_WARN_FMT			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",			ioc->name, ioc);		return -ENODEV;	}	sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST));        	if (!sh) {		printk(MYIOC_s_WARN_FMT			"Unable to register controller with SCSI subsystem\n",			ioc->name);                return -1;        }		spin_lock_irqsave(&ioc->FreeQlock, flags);	/* Attach the SCSI Host to the IOC structure	 */	ioc->sh = sh;	sh->io_port = 0;	sh->n_io_port = 0;	sh->irq = 0;	/* set 16 byte cdb's */	sh->max_cmd_len = 16;	/* Yikes!  This is important!	 * Otherwise, by default, linux	 * only scans target IDs 0-7!	 * pfactsN->MaxDevices unreliable	 * (not supported in early	 *	versions of the FW).	 * max_id = 1 + actual max id,	 * max_lun = 1 + actual last lun,	 *	see hosts.h :o(	 */	if (ioc->bus_type == SCSI) {		sh->max_id = MPT_MAX_SCSI_DEVICES;	} else {	/* For FC, increase the queue depth	 * from MPT_SCSI_CAN_QUEUE (31)	 * to MPT_FC_CAN_QUEUE (63).	 */		sh->can_queue = MPT_FC_CAN_QUEUE;		sh->max_id =		  MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;	}			sh->max_lun = MPT_LAST_LUN + 1;	sh->max_channel = 0;	sh->this_id = ioc->pfacts[0].PortSCSIID;			/* Required entry.	 */	sh->unique_id = ioc->id;	/* Verify that we won't exceed the maximum	 * number of chain buffers	 * We can optimize:  ZZ = req_sz/sizeof(SGE)	 * For 32bit SGE's:	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ	 *               + (req_sz - 64)/sizeof(SGE)	 * A slightly different algorithm is required for	 * 64bit SGEs.	 */	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));	if (sizeof(dma_addr_t) == sizeof(u64)) {		numSGE = (scale - 1) *		  (ioc->facts.MaxChainDepth-1) + scale +		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +		  sizeof(u32));	} else {		numSGE = 1 + (scale - 1) *		  (ioc->facts.MaxChainDepth-1) + scale +		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +		  sizeof(u32));	}			if (numSGE < sh->sg_tablesize) {		/* Reset this value */		dprintk((MYIOC_s_INFO_FMT		  "Resetting sg_tablesize to %d from %d\n",		  ioc->name, numSGE, sh->sg_tablesize));		sh->sg_tablesize = numSGE;	}	/* Set the pci device pointer in Scsi_Host structure.	 */	scsi_set_device(sh, &ioc->pcidev->dev);	spin_unlock_irqrestore(&ioc->FreeQlock, flags);	hd = (MPT_SCSI_HOST *) sh->hostdata;	hd->ioc = ioc;	/* SCSI needs scsi_cmnd lookup table!	 * (with size equal to req_depth*PtrSz!)	 */	sz = ioc->req_depth * sizeof(void *);	mem = kmalloc(sz, GFP_ATOMIC);	if (mem == NULL) {		error = -ENOMEM;		goto mptscsih_probe_failed;	}	memset(mem, 0, sz);	hd->ScsiLookup = (struct scsi_cmnd **) mem;	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",		 ioc->name, hd->ScsiLookup, sz));			/* Allocate memory for the device structures.	 * A non-Null pointer at an offset	 * indicates a device exists.	 * max_id = 1 + maximum id (hosts.h)	 */	sz = sh->max_id * sizeof(void *);	mem = kmalloc(sz, GFP_ATOMIC);	if (mem == NULL) {		error = -ENOMEM;		goto mptscsih_probe_failed;	}	memset(mem, 0, sz);	hd->Targets = (VirtDevice **) mem;	dprintk((KERN_INFO	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));	/* Clear the TM flags	 */	hd->tmPending = 0;	hd->tmState = TM_STATE_NONE;	hd->resetPending = 0;	hd->abortSCpnt = NULL;	hd->tmPtr = NULL;	/* Clear the pointer used to store	 * single-threaded commands, i.e., those	 * issued during a bus scan, dv and	 * configuration pages.	 */	hd->cmdPtr = NULL;	/* Initialize this SCSI Hosts' timers	 * To use, set the timer expires field	 * and add_timer	 */	init_timer(&hd->timer);	hd->timer.data = (unsigned long) hd;	hd->timer.function = mptscsih_timer_expired;	init_timer(&hd->TMtimer);	hd->TMtimer.data = (unsigned long) hd;	hd->TMtimer.function = mptscsih_taskmgmt_timeout;	hd->qtag_tick = jiffies;	/* Moved Earlier Pam D */	/* ioc->sh = sh;	*/	if (ioc->bus_type == SCSI) {		/* Update with the driver setup		 * values.		 */		if (ioc->spi_data.maxBusWidth >		  driver_setup.max_width) {			ioc->spi_data.maxBusWidth =			  driver_setup.max_width;		}		if (ioc->spi_data.minSyncFactor <		  driver_setup.min_sync_factor) {			ioc->spi_data.minSyncFactor =			  driver_setup.min_sync_factor;		}		if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {			ioc->spi_data.maxSyncOffset = 0;		}		ioc->spi_data.Saf_Te = driver_setup.saf_te;		hd->negoNvram = 0;#ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION		hd->negoNvram = MPT_SCSICFG_USE_NVRAM;#endif		ioc->spi_data.forceDv = 0;		for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {			ioc->spi_data.dvStatus[ii] =			  MPT_SCSICFG_NEGOTIATE;		}		for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)			ioc->spi_data.dvStatus[ii] |=			  MPT_SCSICFG_DV_NOT_DONE;		ddvprintk((MYIOC_s_INFO_FMT			"dv %x width %x factor %x saf_te %x\n",			ioc->name, driver_setup.dv,			driver_setup.max_width,			driver_setup.min_sync_factor,			driver_setup.saf_te));	}	mpt_scsi_hosts++;	error = scsi_add_host (sh, &ioc->pcidev->dev);	if(error) {		dprintk((KERN_ERR MYNAM		  "scsi_add_host failed\n"));		goto mptscsih_probe_failed;	}	scsi_scan_host(sh);	return 0;mptscsih_probe_failed:	mptscsih_remove(pdev);	return error;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_remove - Removed scsi devices *	@pdev: Pointer to pci_dev structure * * */static 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;	if(!host)		return;	scsi_remove_host(host);#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) {			set_current_state(TASK_INTERRUPTIBLE);			schedule_timeout(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	hd = (MPT_SCSI_HOST *)host->hostdata;	if (hd != NULL) {		int sz1;		mptscsih_shutdown(&pdev->dev);		sz1=0;		if (hd->ScsiLookup != NULL) {			sz1 = hd->ioc->req_depth * sizeof(void *);			kfree(hd->ScsiLookup);			hd->ScsiLookup = NULL;		}		if (hd->Targets != NULL) {			/*			 * Free pointer array.			 */			kfree(hd->Targets);			hd->Targets = NULL;		}		dprintk((MYIOC_s_INFO_FMT 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -