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

📄 mptscsih.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	return FAILED;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_host_reset - Perform a SCSI host adapter RESET! *	new_eh variant *	@SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to * *	(linux scsi_host_template.eh_host_reset_handler routine) * *	Returns SUCCESS or FAILED. */intmptscsih_host_reset(struct scsi_cmnd *SCpnt){	MPT_SCSI_HOST *  hd;	int              status = SUCCESS;	/*  If we can't locate the host to reset, then we failed. */	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){		dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "			     "Can't locate host! (sc=%p)\n",			     SCpnt ) );		return FAILED;	}	printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",	       hd->ioc->name, SCpnt);	/*  If our attempts to reset the host failed, then return a failed	 *  status.  The host will be taken off line by the SCSI mid-layer.	 */	if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){		status = FAILED;	} else {		/*  Make sure TM pending is cleared and TM state is set to		 *  NONE.		 */		hd->tmPending = 0;		hd->tmState = TM_STATE_NONE;	}	dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "		     "Status = %s\n",		     (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );	return status;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_tm_pending_wait - wait for pending task management request to *		complete. *	@hd: Pointer to MPT host structure. * *	Returns {SUCCESS,FAILED}. */static intmptscsih_tm_pending_wait(MPT_SCSI_HOST * hd){	unsigned long  flags;	int            loop_count = 4 * 10;  /* Wait 10 seconds */	int            status = FAILED;	do {		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);		if (hd->tmState == TM_STATE_NONE) {			hd->tmState = TM_STATE_IN_PROGRESS;			hd->tmPending = 1;			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);			status = SUCCESS;			break;		}		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);		msleep(250);	} while (--loop_count);	return status;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_tm_wait_for_completion - wait for completion of TM task *	@hd: Pointer to MPT host structure. * *	Returns {SUCCESS,FAILED}. */static intmptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ){	unsigned long  flags;	int            loop_count = 4 * timeout;	int            status = FAILED;	do {		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);		if(hd->tmPending == 0) {			status = SUCCESS; 			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);			break;		}		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);		msleep_interruptible(250);	} while (--loop_count);	return status;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static voidmptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code){	char *desc;	switch (response_code) {	case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:		desc = "The task completed.";		break;	case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:		desc = "The IOC received an invalid frame status.";		break;	case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:		desc = "The task type is not supported.";		break;	case MPI_SCSITASKMGMT_RSP_TM_FAILED:		desc = "The requested task failed.";		break;	case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:		desc = "The task completed successfully.";		break;	case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:		desc = "The LUN request is invalid.";		break;	case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:		desc = "The task is in the IOC queue and has not been sent to target.";		break;	default:		desc = "unknown";		break;	}	printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",		ioc->name, response_code, desc);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver *	@ioc: Pointer to MPT_ADAPTER structure *	@mf: Pointer to SCSI task mgmt request frame *	@mr: Pointer to SCSI task mgmt reply frame * *	This routine is called from mptbase.c::mpt_interrupt() at the completion *	of any SCSI task management request. *	This routine is registered with the MPT (base) driver at driver *	load/init time via the mpt_register() API call. * *	Returns 1 indicating alloc'd request frame ptr should be freed. */intmptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr){	SCSITaskMgmtReply_t	*pScsiTmReply;	SCSITaskMgmt_t		*pScsiTmReq;	MPT_SCSI_HOST		*hd;	unsigned long		 flags;	u16			 iocstatus;	u8			 tmType;	dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",			ioc->name, mf, mr));	if (ioc->sh) {		/* Depending on the thread, a timer is activated for		 * the TM request.  Delete this timer on completion of TM.		 * Decrement count of outstanding TM requests.		 */		hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;	} else {		dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",			ioc->name));		return 1;	}	if (mr == NULL) {		dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",			ioc->name, mf));		return 1;	} else {		pScsiTmReply = (SCSITaskMgmtReply_t*)mr;		pScsiTmReq = (SCSITaskMgmt_t*)mf;		/* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */		tmType = pScsiTmReq->TaskType;		if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&		    pScsiTmReply->ResponseCode)			mptscsih_taskmgmt_response_code(ioc,			    pScsiTmReply->ResponseCode);		dtmprintk((MYIOC_s_WARN_FMT "  TaskType = %d, TerminationCount=%d\n",				ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));		DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);		iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;		dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",			ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));		/* Error?  (anything non-zero?) */		if (iocstatus) {			/* clear flags and continue.			 */			if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)				hd->abortSCpnt = NULL;			/* If an internal command is present			 * or the TM failed - reload the FW.			 * FC FW may respond FAILED to an ABORT			 */			if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {				if ((hd->cmdPtr) ||				    (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {					if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {						printk((KERN_WARNING							" Firmware Reload FAILED!!\n"));					}				}			}		} else {			dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));			hd->abortSCpnt = NULL;		}	}	spin_lock_irqsave(&ioc->FreeQlock, flags);	hd->tmPending = 0;	spin_unlock_irqrestore(&ioc->FreeQlock, flags);	hd->tmState = TM_STATE_NONE;	return 1;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	This is anyones guess quite frankly. */intmptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,		sector_t capacity, int geom[]){	int		heads;	int		sectors;	sector_t	cylinders;	ulong 		dummy;	heads = 64;	sectors = 32;	dummy = heads * sectors;	cylinders = capacity;	sector_div(cylinders,dummy);	/*	 * Handle extended translation size for logical drives	 * > 1Gb	 */	if ((ulong)capacity >= 0x200000) {		heads = 255;		sectors = 63;		dummy = heads * sectors;		cylinders = capacity;		sector_div(cylinders,dummy);	}	/* return result */	geom[0] = heads;	geom[1] = sectors;	geom[2] = cylinders;	dprintk((KERN_NOTICE		": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",		sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));	return 0;}/* Search IOC page 3 to determine if this is hidden physical disk * */intmptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id){	int i;	if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)		return 0;	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {                if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)                        return 1;        }        return 0;}EXPORT_SYMBOL(mptscsih_is_phys_disk);intmptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid){	int i;	if (!hd->ioc->raid_data.isRaid || !hd->ioc->raid_data.pIocPg3)		return -ENXIO;	for (i = 0; i < hd->ioc->raid_data.pIocPg3->NumPhysDisks; i++) {		if (physdiskid ==		    hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)			return hd->ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;	}	return -ENXIO;}EXPORT_SYMBOL(mptscsih_raid_id_to_num);/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	OS entry point to allow host driver to alloc memory *	for each scsi target. Called once per device the bus scan. *	Return non-zero if allocation fails. */intmptscsih_target_alloc(struct scsi_target *starget){	VirtTarget		*vtarget;	vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);	if (!vtarget)		return -ENOMEM;	starget->hostdata = vtarget;	vtarget->starget = starget;	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	OS entry point to allow host driver to alloc memory *	for each scsi device. Called once per device the bus scan. *	Return non-zero if allocation fails. */intmptscsih_slave_alloc(struct scsi_device *sdev){	struct Scsi_Host	*host = sdev->host;	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;	VirtTarget		*vtarget;	VirtDevice		*vdev;	struct scsi_target 	*starget;	vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);	if (!vdev) {		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",				hd->ioc->name, sizeof(VirtDevice));		return -ENOMEM;	}	vdev->lun = sdev->lun;	sdev->hostdata = vdev;	starget = scsi_target(sdev);	vtarget = starget->hostdata;	vdev->vtarget = vtarget;	if (vtarget->num_luns == 0) {		hd->Targets[sdev->id] = vtarget;		vtarget->ioc_id = hd->ioc->id;		vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;		vtarget->target_id = sdev->id;		vtarget->bus_id = sdev->channel;		if (hd->ioc->bus_type == SPI && sdev->channel == 0 &&		    hd->ioc->raid_data.isRaid & (1 << sdev->id)) {			vtarget->raidVolume = 1;			ddvtprintk((KERN_INFO				    "RAID Volume @ id %d\n", sdev->id));		}	}	vtarget->num_luns++;	return 0;}/* *	OS entry point to allow for host driver to free allocated memory *	Called if no device present or device being unloaded */voidmptscsih_target_destroy(struct scsi_target *starget){	if (starget->hostdata)		kfree(starget->hostdata);	starget->hostdata = NULL;}/* *	OS entry point to allow for host driver to free allocated memory *	Called if no device present or device being unloaded */voidmptscsih_slave_destroy(struct scsi_device *sdev){	struct Scsi_Host	*host = sdev->host;	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;	VirtTarget		*vtarget;	VirtDevice		*vdevice;	struct scsi_target 	*starget;	starget = scsi_target(sdev);	vtarget = starget->hostdata;	vdevice = sdev->hostdata;	mptscsih_search_running_cmds(hd, vdevice);	vtarget->luns[0] &= ~(1 << vdevice->lun);	vtarget->num_luns--;	if (vtarget->num_luns == 0) {		hd->Targets[sdev->id] = NULL;	}	mptscsih_synchronize_cache(hd, vdevice);	kfree(vdevice);	sdev->hostdata = NULL;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_change_queue_depth - This function will set a devices queue depth *	@sdev: per scsi_device pointer *	@qdepth: requested queue depth * *	Adding support for new 'change_queue_depth' api.*/intmptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth){	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)sdev->host->hostdata;	VirtTarget 		*vtarget;	struct scsi_target 	*starget;	int			max_depth;	int			tagged;	starget = scsi_target(sdev);	vtarget = starget->hostdata;	if (hd->ioc->bus_type == SPI) {		if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))			

⌨️ 快捷键说明

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