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

📄 qla_fo.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 3 页
字号:
			rval = qla2x00_fo_get_lun_data(&cmd_struct,						&buff.lun_data, mode);			if (rval != 0)				out_size = 0;			break;		case FO_CC_SET_LUN_DATA:			DEBUG4(printk("calling qla2x00_fo_set_lun_data\n");)			DEBUG4(printk("	((EXT_IOCTL*)arg)->RequestAdr (%p):\n",					(((EXT_IOCTL*)arg)->RequestAdr));)			rval = qla2x00_fo_set_lun_data(&cmd_struct,						&buff.lun_data, mode);			break;		case FO_CC_GET_TARGET_DATA:			DEBUG4(printk("calling qla2x00_fo_get_target_data\n");)			DEBUG4(printk("	((EXT_IOCTL*)arg)->RequestAdr (%p):\n",					(((EXT_IOCTL*)arg)->RequestAdr));)			rval = qla2x00_fo_get_target_data(&cmd_struct,						&buff.target_data, mode);			if (rval != 0) {				out_size = 0;			}			break;		case FO_CC_SET_TARGET_DATA:			DEBUG4(printk("calling qla2x00_fo_set_target_data\n");)			DEBUG4(printk("	((EXT_IOCTL*)arg)->RequestAdr (%p):\n",					(((EXT_IOCTL*)arg)->RequestAdr));)			rval = qla2x00_fo_set_target_data(&cmd_struct,						&buff.target_data, mode);			break;	}	if ((cmd_struct.ResponseLen = out_size) != 0) {		copy_to_user(&(((EXT_IOCTL*)arg)->ResponseAdr),				&buff, out_size);	}	/* Set Status and DetailStatus fields in application EXT_IOCTL */	(((EXT_IOCTL*)arg)->Status) 		= cmd_struct.Status;	(((EXT_IOCTL*)arg)->DetailStatus)	= cmd_struct.DetailStatus;	(((EXT_IOCTL*)arg)->ResponseLen)	= cmd_struct.ResponseLen;	if (rval != 0) {		/*EMPTY*/		DEBUG4(printk("qla2x00_fo_ioctl: **** FAILED ****\n");)	} else {		/*EMPTY*/		DEBUG4(printk("qla2x00_fo_ioctl: exiting normally\n");)	}	return rval;}/* * qla2x00_fo_count_retries *	Increment the retry counter for the command. *      Set or reset the SRB_RETRY flag. * * Input: *	sp = Pointer to command. * * Returns: *	TRUE -- retry * 	FALSE -- don't retry * * Context: *	Kernel context. */static BOOLqla2x00_fo_count_retries(scsi_qla_host_t *ha, srb_t *sp){	BOOL		retry = TRUE;	os_lun_t	*lq;	os_tgt_t	*tq;	if (++sp->fo_retry_cnt >  qla_fo_params.MaxRetriesPerIo) {		/* no more failovers for this request */		retry = FALSE;		sp->fo_retry_cnt = 0;		printk(KERN_INFO			"qla2x00: no more failovers for request - "			"pid= %ld\n", sp->cmd->serial_number);	} else {		/*		 * We haven't exceeded the max retries for this request, check		 * max retries this path		 */		if ((sp->fo_retry_cnt % qla_fo_params.MaxRetriesPerPath) == 0) {			DEBUG(printk(" qla2x00_fo_count_retries: FAILOVER - "					"queuing ha=%ld, sp=%p, pid =%ld, "					"fo retry= %d \n",					ha->host_no,					sp, sp->cmd->serial_number,					sp->fo_retry_cnt);)			/*			 * Note: we don't want it to timeout, so it is			 * recycling on the retry queue and the fialover queue.			 */			lq = sp->lun_queue;			tq = sp->tgt_queue;			set_bit(LUN_MPIO_BUSY, &lq->q_flag);			/*			 * ??? We can get a path error on any ha, but always			 * queue failover on originating ha. This will allow us			 * to syncronized the requests for a given lun.			 */			sp->f_start=jiffies;/*ra 10/29/01*/			/* Now queue it on to be failover */			sp->ha = ha;			add_to_failover_queue(ha,sp);		}	}	return retry ;}/* * qla2x00_fo_check *	This function is called from the done routine to see if *  the SRB requires a failover. * *	This function examines the available os returned status and *  if meets condition, the command(srb) is placed ont the failover *  queue for processing. * * Input: *	sp  = Pointer to the SCSI Request Block * * Output: *      sp->flags SRB_RETRY bit id command is to *      be retried otherwise bit is reset. * * Returns: *      None. * * Context: *	Kernel/Interrupt context. */BOOLqla2x00_fo_check(scsi_qla_host_t *ha, srb_t *sp){	BOOL		retry = FALSE;	int host_status;#if DEBUG_QLA2100	STATIC char *reason[] = {		"DID_OK",		"DID_NO_CONNECT",		"DID_BUS_BUSY",		"DID_TIME_OUT",		"DID_BAD_TARGET",		"DID_ABORT",		"DID_PARITY",		"DID_ERROR",		"DID_RESET",		"DID_BAD_INTR"	};#endif	/* we failover on selction timeouts only */	host_status = CMD_RESULT(sp->cmd) >>16;	if( host_status == DID_NO_CONNECT) {		if( qla2x00_fo_count_retries(ha,sp) ) {			/* Force a retry  on this request, it will			 * cause the LINUX timer to get reset, while we			 * we are processing the failover.			 */			CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16;			retry = TRUE;		}		DEBUG(printk("qla2x00_fo_check: pid= %ld sp %p "				"retry count=%d, retry flag = %d, "				"host status (%s)\n\r",				sp->cmd->serial_number,				sp, sp->fo_retry_cnt,				retry, reason[host_status]);)	}	return retry;}/* * qla2x00_fo_path_change *	This function is called from configuration mgr to notify *	of a path change. * * Input: *      type    = Failover notify type, FO_NOTIFY_LUN_RESET or FO_NOTIFY_LOGOUT *      newlunp = Pointer to the fc_lun struct for current path. *      oldlunp = Pointer to fc_lun struct for previous path. * * Returns: * * Context: *	Kernel context. */uint32_tqla2x00_fo_path_change(uint32_t type, fc_lun_t *newlunp, fc_lun_t *oldlunp){	uint32_t	ret = QLA2X00_SUCCESS;	newlunp->max_path_retries = 0;	return ret;}/* * qla2x00_fo_get_params *	Process an ioctl request to get system wide failover parameters. * * Input: *	pp = Pointer to FO_PARAMS structure. * * Returns: *	EXT_STATUS code. * * Context: *	Kernel context. */static uint32_tqla2x00_fo_get_params(PFO_PARAMS pp){	pp->MaxPathsPerDevice = qla_fo_params.MaxPathsPerDevice;	pp->MaxRetriesPerPath = qla_fo_params.MaxRetriesPerPath;	pp->MaxRetriesPerIo = qla_fo_params.MaxRetriesPerIo;	pp->Flags = qla_fo_params.Flags;	pp->FailoverNotifyType = qla_fo_params.FailoverNotifyType;	pp->FailoverNotifyCdbLength = qla_fo_params.FailoverNotifyCdbLength;	memset(pp->FailoverNotifyCdb, 0, sizeof(pp->FailoverNotifyCdb));	memcpy(pp->FailoverNotifyCdb,			&qla_fo_params.FailoverNotifyCdb[0],			sizeof(pp->FailoverNotifyCdb));	return EXT_STATUS_OK;}/* * qla2x00_fo_set_params *	Process an ioctl request to set system wide failover parameters. * * Input: *	pp = Pointer to FO_PARAMS structure. * * Returns: *	EXT_STATUS code. * * Context: *	Kernel context. */static uint32_tqla2x00_fo_set_params(PFO_PARAMS pp){	/* Check values for defined MIN and MAX */	if ((pp->MaxPathsPerDevice > SDM_DEF_MAX_PATHS_PER_DEVICE) ||			(pp->MaxRetriesPerPath < FO_MAX_RETRIES_PER_PATH_MIN) ||			(pp->MaxRetriesPerPath > FO_MAX_RETRIES_PER_PATH_MAX) ||			(pp->MaxRetriesPerIo < FO_MAX_RETRIES_PER_IO_MIN) ||			(pp->MaxRetriesPerPath > FO_MAX_RETRIES_PER_IO_MAX))		return EXT_STATUS_INVALID_PARAM;	/* Update the global structure. */	qla_fo_params.MaxPathsPerDevice = pp->MaxPathsPerDevice;	qla_fo_params.MaxRetriesPerPath = pp->MaxRetriesPerPath;	qla_fo_params.MaxRetriesPerIo = pp->MaxRetriesPerIo;	qla_fo_params.Flags = pp->Flags;	qla_fo_params.FailoverNotifyType = pp->FailoverNotifyType;	qla_fo_params.FailoverNotifyCdbLength = pp->FailoverNotifyCdbLength;	if (pp->FailoverNotifyType & FO_NOTIFY_TYPE_CDB) {		if (pp->FailoverNotifyCdbLength >				sizeof(qla_fo_params.FailoverNotifyCdb))			return EXT_STATUS_INVALID_PARAM;		memcpy(qla_fo_params.FailoverNotifyCdb,				pp->FailoverNotifyCdb,				sizeof(qla_fo_params.FailoverNotifyCdb));	}	return EXT_STATUS_OK;}/* * qla2x00_fo_init_params *	Gets driver configuration file failover properties to initalize *	the global failover parameters structure. * * Input: *	ha = adapter block pointer. * * Context: *	Kernel context. */voidqla2x00_fo_init_params(scsi_qla_host_t *ha){	/* For parameters that are not completely implemented yet, */	memset(&qla_fo_params, 0, sizeof(qla_fo_params));	if(MaxPathsPerDevice) {		qla_fo_params.MaxPathsPerDevice = MaxPathsPerDevice;	} else		qla_fo_params.MaxPathsPerDevice =FO_MAX_PATHS_PER_DEVICE_DEF ;	if(MaxRetriesPerPath) {		qla_fo_params.MaxRetriesPerPath = MaxRetriesPerPath;	} else		qla_fo_params.MaxRetriesPerPath =FO_MAX_RETRIES_PER_PATH_DEF;	if(MaxRetriesPerIo) {		qla_fo_params.MaxRetriesPerIo =MaxRetriesPerIo;	} else		qla_fo_params.MaxRetriesPerIo =FO_MAX_RETRIES_PER_IO_DEF;	qla_fo_params.Flags =  0;	qla_fo_params.FailoverNotifyType = FO_NOTIFY_TYPE_NONE;}/* * qla2x00_send_fo_notification *      Sends failover notification if needed.  Change the fc_lun pointer *      in the old path lun queue. * * Input: *      old_lp = Pointer to old fc_lun. *      new_lp = Pointer to new fc_lun. * * Returns: *      Local function status code. * * Context: *      Kernel context. */uint32_tqla2x00_send_fo_notification(fc_lun_t *old_lp, fc_lun_t *new_lp){	scsi_qla_host_t	*old_ha = old_lp->fcport->ha;	int		rval = QLA2X00_SUCCESS;	inq_cmd_rsp_t	*pkt;	uint16_t	loop_id, lun;	dma_addr_t	phys_address;	ENTER("qla2x00_send_fo_notification");	loop_id = old_lp->fcport->loop_id;	lun = old_lp->lun;	if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_LUN_RESET) {		rval = qla2x00_lun_reset(old_ha, loop_id, lun);		if (rval == QLA2X00_SUCCESS) {			DEBUG4(printk("qla2x00_send_fo_notification: LUN "					"reset succeded\n");)		} else {			DEBUG4(printk("qla2x00_send_fo_notification: LUN "					"reset failed\n");)		}	}	if ( (qla_fo_params.FailoverNotifyType ==			 FO_NOTIFY_TYPE_LOGOUT_OR_LUN_RESET) ||			(qla_fo_params.FailoverNotifyType ==			 FO_NOTIFY_TYPE_LOGOUT_OR_CDB) )  {		rval = qla2x00_fabric_logout(old_ha, loop_id);		if (rval == QLA2X00_SUCCESS) {			DEBUG4(printk("qla2x00_send_fo_failover_notify: "					"logout succeded\n");)		} else {			DEBUG4(printk("qla2x00_send_fo_failover_notify: "					"logout failed\n");)		}	}	if (qla_fo_params.FailoverNotifyType == FO_NOTIFY_TYPE_CDB) {		pkt = pci_alloc_consistent(old_ha->pdev,				sizeof(inq_cmd_rsp_t), &phys_address);		if (pkt == NULL) {			DEBUG4(printk("qla2x00_send_fo_failover_notify: "					"memory allocation failed\n");)			return(QLA2X00_FUNCTION_FAILED);		}		memset(pkt,0, sizeof(inq_cmd_rsp_t));		/* Fix Me-COMMAND_A64_TYPE ??? */		pkt->p.cmd.entry_type = COMMAND_TYPE;		pkt->p.cmd.entry_count = 1;		pkt->p.cmd.lun = lun;		pkt->p.cmd.target = (uint8_t)loop_id;		pkt->p.cmd.control_flags = CF_SIMPLE_TAG;		memcpy(qla_fo_params.FailoverNotifyCdb,				pkt->p.cmd.scsi_cdb,				qla_fo_params.FailoverNotifyCdbLength);		/* FIXME This setup needs to be verified with Dennis. */		pkt->p.cmd.dseg_count = 1;		pkt->p.cmd.byte_count = 0;		LITTLE_ENDIAN_32(pkt->p.cmd.byte_count);		pkt->p.cmd.dseg_0_address = (uint32_t)			(phys_address + sizeof (sts_entry_t));		LITTLE_ENDIAN_32(pkt->p.cmd.dseg_0_address);		pkt->p.cmd.dseg_0_length = 0;		LITTLE_ENDIAN_32(pkt->p.cmd.dseg_0_length);		rval = qla2x00_issue_iocb(old_ha, pkt, phys_address,				sizeof (inq_cmd_rsp_t));		if (rval != QLA2X00_SUCCESS ||				pkt->p.rsp.comp_status != CS_COMPLETE ||				pkt->p.rsp.scsi_status & SS_CHECK_CONDITION ||				pkt->inq[0] == 0x7f) {			DEBUG4(printk("qla2x00_fo_notification: send CDB "					"failed: comp_status = %x"					"scsi_status = %x inq[0] = %x\n",					pkt->p.rsp.comp_status,					pkt->p.rsp.scsi_status,					pkt->inq[0]);)		}		pci_free_consistent(old_ha->pdev,				sizeof(inq_cmd_rsp_t), pkt, phys_address);	}	return rval;}/* * qla2100_fo_enabled *      Reads and validates the failover enabled property. * * Input: *      ha = adapter state pointer. *      instance = HBA number. * * Returns: *      TRUE when failover is authorized else FALSE * * Context: *      Kernel context. */BOOLqla2x00_fo_enabled(scsi_qla_host_t *ha, int instance){	BOOL enable = FALSE;	if (ha->flags.failover_enabled)		enable = TRUE;	return enable;}

⌨️ 快捷键说明

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