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

📄 qla_init.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	icb->timeout = __constant_cpu_to_le16(0);	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {		/* Enable RIO */		icb->firmware_options[0] &= ~BIT_3;		icb->add_firmware_options[0] &=		    ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);		icb->add_firmware_options[0] |= BIT_2;		icb->response_accumulation_timer = 3;		icb->interrupt_delay_timer = 5;		ha->flags.process_response_queue = 1;	} else {		/* Enable ZIO -- Support mode 5 only. */		timer_mode = icb->add_firmware_options[0] &		    (BIT_3 | BIT_2 | BIT_1 | BIT_0);		icb->add_firmware_options[0] &=		    ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);		if (ql2xenablezio)			timer_mode = BIT_2 | BIT_0;		if (timer_mode == (BIT_2 | BIT_0)) {			DEBUG2(printk("scsi(%ld): ZIO enabled; timer delay "			    "(%d).\n", ha->host_no, ql2xintrdelaytimer));			qla_printk(KERN_INFO, ha,			    "ZIO enabled; timer delay (%d).\n",			    ql2xintrdelaytimer);			icb->add_firmware_options[0] |= timer_mode;			icb->interrupt_delay_timer = ql2xintrdelaytimer;			ha->flags.process_response_queue = 1;		}	}	if (rval) {		DEBUG2_3(printk(KERN_WARNING		    "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));	}	return (rval);}/** qla2x00_init_tgt_map*      Initializes target map.** Input:*      ha = adapter block pointer.** Output:*      TGT_Q initialized*/static voidqla2x00_init_tgt_map(scsi_qla_host_t *ha){	uint32_t t;	for (t = 0; t < MAX_TARGETS; t++)		TGT_Q(ha, t) = (os_tgt_t *)NULL;}/** * qla2x00_alloc_fcport() - Allocate a generic fcport. * @ha: HA context * @flags: allocation flags * * Returns a pointer to the allocated fcport, or NULL, if none available. */fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags){	fc_port_t *fcport;	fcport = kmalloc(sizeof(fc_port_t), flags);	if (fcport == NULL)		return (fcport);	/* Setup fcport template structure. */	memset(fcport, 0, sizeof (fc_port_t));	fcport->ha = ha;	fcport->port_type = FCT_UNKNOWN;	fcport->loop_id = FC_NO_LOOP_ID;	fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;	atomic_set(&fcport->state, FCS_UNCONFIGURED);	fcport->flags = FCF_RLC_SUPPORT;	INIT_LIST_HEAD(&fcport->fcluns);	return (fcport);}/* * qla2x00_configure_loop *      Updates Fibre Channel Device Database with what is actually on loop. * * Input: *      ha                = adapter block pointer. * * Returns: *      0 = success. *      1 = error. *      2 = database was full and device was not configured. */static intqla2x00_configure_loop(scsi_qla_host_t *ha) {	int  rval;	unsigned long flags, save_flags;	rval = QLA_SUCCESS;	/* Get Initiator ID */	if (test_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags)) {		rval = qla2x00_configure_hba(ha);		if (rval != QLA_SUCCESS) {			DEBUG(printk("scsi(%ld): Unable to configure HBA.\n",			    ha->host_no));			return (rval);		}	}	save_flags = flags = ha->dpc_flags;	DEBUG(printk("scsi(%ld): Configure loop -- dpc flags =0x%lx\n",	    ha->host_no, flags));	/*	 * If we have both an RSCN and PORT UPDATE pending then handle them	 * both at the same time.	 */	clear_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);	clear_bit(RSCN_UPDATE, &ha->dpc_flags);	ha->mem_err = 0 ;	/* Determine what we need to do */	if (ha->current_topology == ISP_CFG_FL &&	    (test_bit(LOCAL_LOOP_UPDATE, &flags))) {		ha->flags.rscn_queue_overflow = 1;		set_bit(RSCN_UPDATE, &flags);	} else if (ha->current_topology == ISP_CFG_F &&	    (test_bit(LOCAL_LOOP_UPDATE, &flags))) {		ha->flags.rscn_queue_overflow = 1;		set_bit(RSCN_UPDATE, &flags);		clear_bit(LOCAL_LOOP_UPDATE, &flags);	} else if (!ha->flags.online ||	    (test_bit(ABORT_ISP_ACTIVE, &flags))) {		ha->flags.rscn_queue_overflow = 1;		set_bit(RSCN_UPDATE, &flags);		set_bit(LOCAL_LOOP_UPDATE, &flags);	}	if (test_bit(LOCAL_LOOP_UPDATE, &flags)) {		if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {			rval = QLA_FUNCTION_FAILED;		} else {			rval = qla2x00_configure_local_loop(ha);		}	}	if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) {		if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {			rval = QLA_FUNCTION_FAILED;		} else {			rval = qla2x00_configure_fabric(ha);		}	}	if (rval == QLA_SUCCESS) {		if (atomic_read(&ha->loop_down_timer) ||		    test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {			rval = QLA_FUNCTION_FAILED;		} else {			qla2x00_config_os(ha);			atomic_set(&ha->loop_state, LOOP_READY);			DEBUG(printk("scsi(%ld): LOOP READY\n", ha->host_no));		}	}	if (rval) {		DEBUG2_3(printk("%s(%ld): *** FAILED ***\n",		    __func__, ha->host_no));	} else {		DEBUG3(printk("%s: exiting normally\n", __func__));	}	/* Restore state if a resync event occured during processing */	if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {		if (test_bit(LOCAL_LOOP_UPDATE, &save_flags))			set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);		if (test_bit(RSCN_UPDATE, &save_flags))			set_bit(RSCN_UPDATE, &ha->dpc_flags);	}	return (rval);}/* * qla2x00_configure_local_loop *	Updates Fibre Channel Device Database with local loop devices. * * Input: *	ha = adapter block pointer. * * Returns: *	0 = success. */static intqla2x00_configure_local_loop(scsi_qla_host_t *ha) {	int		rval, rval2;	int		found_devs;	int		found;	fc_port_t	*fcport, *new_fcport;	uint16_t	index;	uint16_t	entries;	char		*id_iter;	uint16_t	loop_id;	uint8_t		domain, area, al_pa;	found_devs = 0;	new_fcport = NULL;	entries = MAX_FIBRE_DEVICES;	DEBUG3(printk("scsi(%ld): Getting FCAL position map\n", ha->host_no));	DEBUG3(qla2x00_get_fcal_position_map(ha, NULL));	/* Get list of logged in devices. */	memset(ha->gid_list, 0, GID_LIST_SIZE);	rval = qla2x00_get_id_list(ha, ha->gid_list, ha->gid_list_dma,	    &entries);	if (rval != QLA_SUCCESS)		goto cleanup_allocation;	DEBUG3(printk("scsi(%ld): Entries in ID list (%d)\n",	    ha->host_no, entries));	DEBUG3(qla2x00_dump_buffer((uint8_t *)ha->gid_list,	    entries * sizeof(struct gid_list_info)));	/* Allocate temporary fcport for any new fcports discovered. */	new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL);	if (new_fcport == NULL) {		rval = QLA_MEMORY_ALLOC_FAILED;		goto cleanup_allocation;	}	new_fcport->flags &= ~FCF_FABRIC_DEVICE;	/*	 * Mark local devices that were present with FCF_DEVICE_LOST for now.	 */	list_for_each_entry(fcport, &ha->fcports, list) {		if (atomic_read(&fcport->state) == FCS_ONLINE &&		    fcport->port_type != FCT_BROADCAST &&		    (fcport->flags & FCF_FABRIC_DEVICE) == 0) {			DEBUG(printk("scsi(%ld): Marking port lost, "			    "loop_id=0x%04x\n",			    ha->host_no, fcport->loop_id));			atomic_set(&fcport->state, FCS_DEVICE_LOST);			fcport->flags &= ~FCF_FARP_DONE;		}	}	/* Add devices to port list. */	id_iter = (char *)ha->gid_list;	for (index = 0; index < entries; index++) {		domain = ((struct gid_list_info *)id_iter)->domain;		area = ((struct gid_list_info *)id_iter)->area;		al_pa = ((struct gid_list_info *)id_iter)->al_pa;		if (IS_QLA2100(ha) || IS_QLA2200(ha)) {			loop_id = (uint16_t)			    ((struct gid_list_info *)id_iter)->loop_id_2100;			id_iter += 4;		} else {			loop_id = le16_to_cpu(			    ((struct gid_list_info *)id_iter)->loop_id);			id_iter += 6;		}		/* Bypass reserved domain fields. */		if ((domain & 0xf0) == 0xf0)			continue;		/* Bypass if not same domain and area of adapter. */		if (area != ha->d_id.b.area || domain != ha->d_id.b.domain)			continue;		/* Bypass invalid local loop ID. */		if (loop_id > LAST_LOCAL_LOOP_ID)			continue;		/* Fill in member data. */		new_fcport->d_id.b.domain = domain;		new_fcport->d_id.b.area = area;		new_fcport->d_id.b.al_pa = al_pa;		new_fcport->loop_id = loop_id;		rval2 = qla2x00_get_port_database(ha, new_fcport, 0);		if (rval2 != QLA_SUCCESS) {			DEBUG2(printk("scsi(%ld): Failed to retrieve fcport "			    "information -- get_port_database=%x, "			    "loop_id=0x%04x\n",			    ha->host_no, rval2, new_fcport->loop_id));			continue;		}		/* Check for matching device in port list. */		found = 0;		fcport = NULL;		list_for_each_entry(fcport, &ha->fcports, list) {			if (memcmp(new_fcport->port_name, fcport->port_name,			    WWN_SIZE))				continue;			fcport->flags &= ~(FCF_FABRIC_DEVICE |			    FCF_PERSISTENT_BOUND);			fcport->loop_id = new_fcport->loop_id;			fcport->port_type = new_fcport->port_type;			fcport->d_id.b24 = new_fcport->d_id.b24;			memcpy(fcport->node_name, new_fcport->node_name,			    WWN_SIZE);			found++;			break;		}		if (!found) {			/* New device, add to fcports list. */			new_fcport->flags &= ~FCF_PERSISTENT_BOUND;			list_add_tail(&new_fcport->list, &ha->fcports);			/* Allocate a new replacement fcport. */			fcport = new_fcport;			new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL);			if (new_fcport == NULL) {				rval = QLA_MEMORY_ALLOC_FAILED;				goto cleanup_allocation;			}			new_fcport->flags &= ~FCF_FABRIC_DEVICE;		}		qla2x00_update_fcport(ha, fcport);		found_devs++;	}cleanup_allocation:	if (new_fcport)		kfree(new_fcport);	if (rval != QLA_SUCCESS) {		DEBUG2(printk("scsi(%ld): Configure local loop error exit: "		    "rval=%x\n", ha->host_no, rval));	}	if (found_devs) {		ha->device_flags |= DFLG_LOCAL_DEVICES;		ha->device_flags &= ~DFLG_RETRY_LOCAL_DEVICES;	}	return (rval);}static voidqla2x00_probe_for_all_luns(scsi_qla_host_t *ha) {	fc_port_t	*fcport;	qla2x00_mark_all_devices_lost(ha);  	list_for_each_entry(fcport, &ha->fcports, list) {		if (fcport->port_type != FCT_TARGET)			continue;		qla2x00_update_fcport(ha, fcport); 	}}/* * qla2x00_update_fcport *	Updates device on list. * * Input: *	ha = adapter block pointer. *	fcport = port structure pointer. * * Return: *	0  - Success *  BIT_0 - error * * Context: *	Kernel context. */static voidqla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport){	uint16_t	index;	unsigned long flags;	srb_t *sp;	fcport->ha = ha;	fcport->login_retry = 0;	fcport->port_login_retry_count = ha->port_down_retry_count *	    PORT_RETRY_TIME;	atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *	    PORT_RETRY_TIME);	fcport->flags &= ~FCF_LOGIN_NEEDED;	/*	 * Check for outstanding cmd on tape Bypass LUN discovery if active	 * command on tape.	 */	if (fcport->flags & FCF_TAPE_PRESENT) {		spin_lock_irqsave(&ha->hardware_lock, flags);		for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {			if ((sp = ha->outstanding_cmds[index]) != 0) {				if (sp->fclun->fcport == fcport) {					atomic_set(&fcport->state, FCS_ONLINE);					spin_unlock_irqrestore(					    &ha->hardware_lock, flags);					return;				}			}		}		spin_unlock_irqrestore(&ha->hardware_lock, flags);	}	/* Do LUN discovery. */	if (fcport->port_type == FCT_INITIATOR ||	    fcport->port_type == FCT_BROADCAST) {		fcport->device_type = TYPE_PROCESSOR;	} else {		qla2x00_lun_discovery(ha, fcport);	}	atomic_set(&fcport->state, FCS_ONLINE);}/* * qla2x00_lun_discovery *	Issue SCSI inquiry command for LUN discovery. * * Input: *	ha:		adapter state pointer. *	fcport:		FC port structure pointer. * * Context: *	Kernel context. */static voidqla2x00_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport){	inq_cmd_rsp_t	*inq;	dma_addr_t	inq_dma;	uint16_t	lun;	inq = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &inq_dma);	if (inq == NULL) {		qla_printk(KERN_WARNING, ha,		    "Memory Allocation failed - INQ\n");		return;	}	/* Always add a fc_lun_t structure for lun 0 -- mid-layer requirement */	qla2x00_add_lun(fcport, 0);	/* If report LUN works, exit. */	if (qla2x00_rpt_lun_discovery(ha, fcport, inq, inq_dma) !=	    QLA_SUCCESS) {		for (lun = 0; lun < ha->max_probe_luns; lun++) {			/* Configure LUN. */			qla2x00_cfg_lun(ha, fcport, lun, inq, inq_dma);		}	}	dma_pool_free(ha->s_dma_pool, inq, inq_dma);}/* * qla2x00_rpt_lun_discovery *	Issue SCSI report LUN command for LUN discovery. * * Input: *	ha:		adapter state pointer. *	fcport:		FC port structure pointer. * * Returns: *	qla2x00 local function return status code. * * Context: *	Kernel context. */static intqla2x00_rpt_lun_discovery(scsi_qla_host_t *ha, fc_port_t *fcport,    inq_cmd_rsp_t *inq, dma_addr_t inq_dma)

⌨️ 快捷键说明

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