qla_init.c

来自「linux 内核源代码」· C语言 代码 · 共 2,472 行 · 第 1/5 页

C
2,472
字号
		if (fcport->vp_idx != ha->vp_idx)			continue;		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;		else			loop_id = le16_to_cpu(			    ((struct gid_list_info *)id_iter)->loop_id);		id_iter += ha->gid_list_info_size;		/* Bypass reserved domain fields. */		if ((domain & 0xf0) == 0xf0)			continue;		/* Bypass if not same domain and area of adapter. */		if (area && domain &&		    (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;		new_fcport->vp_idx = ha->vp_idx;		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));			DEBUG2(printk("scsi(%ld): Scheduling resync...\n",			    ha->host_no));			set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);			continue;		}		/* Check for matching device in port list. */		found = 0;		fcport = NULL;		list_for_each_entry(fcport, &pha->fcports, list) {			if (fcport->vp_idx != ha->vp_idx)				continue;			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;			if (ha->parent) {				new_fcport->ha = ha;				new_fcport->vp_idx = ha->vp_idx;				list_add_tail(&new_fcport->vp_fcport,				    &ha->vp_fcports);			}			list_add_tail(&new_fcport->list, &pha->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;		}		/* Base iIDMA settings on HBA port speed. */		fcport->fp_speed = ha->link_data_rate;		qla2x00_update_fcport(ha, fcport);		found_devs++;	}cleanup_allocation:	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, 0); 	list_for_each_entry(fcport, &ha->fcports, list) {		if (fcport->port_type != FCT_TARGET)			continue;		qla2x00_update_fcport(ha, fcport);	}}static voidqla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport){#define LS_UNKNOWN      2	static char *link_speeds[5] = { "1", "2", "?", "4", "8" };	int rval;	uint16_t mb[6];	if (!IS_IIDMA_CAPABLE(ha))		return;	if (fcport->fp_speed == PORT_SPEED_UNKNOWN ||	    fcport->fp_speed > ha->link_data_rate)		return;	rval = qla2x00_set_idma_speed(ha, fcport->loop_id, fcport->fp_speed,	    mb);	if (rval != QLA_SUCCESS) {		DEBUG2(printk("scsi(%ld): Unable to adjust iIDMA "		    "%02x%02x%02x%02x%02x%02x%02x%02x -- %04x %x %04x %04x.\n",		    ha->host_no, fcport->port_name[0], fcport->port_name[1],		    fcport->port_name[2], fcport->port_name[3],		    fcport->port_name[4], fcport->port_name[5],		    fcport->port_name[6], fcport->port_name[7], rval,		    fcport->fp_speed, mb[0], mb[1]));	} else {		DEBUG2(qla_printk(KERN_INFO, ha,		    "iIDMA adjusted to %s GB/s on "		    "%02x%02x%02x%02x%02x%02x%02x%02x.\n",		    link_speeds[fcport->fp_speed], fcport->port_name[0],		    fcport->port_name[1], fcport->port_name[2],		    fcport->port_name[3], fcport->port_name[4],		    fcport->port_name[5], fcport->port_name[6],		    fcport->port_name[7]));	}}static voidqla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport){	struct fc_rport_identifiers rport_ids;	struct fc_rport *rport;	unsigned long flags;	if (fcport->drport)		qla2x00_rport_del(fcport);	if (fcport->rport)		return;	rport_ids.node_name = wwn_to_u64(fcport->node_name);	rport_ids.port_name = wwn_to_u64(fcport->port_name);	rport_ids.port_id = fcport->d_id.b.domain << 16 |	    fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;	rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;	rport = fc_remote_port_add(ha->host, 0, &rport_ids);	if (!rport) {		qla_printk(KERN_WARNING, ha,		    "Unable to allocate fc remote port!\n");		return;	}	spin_lock_irqsave(&fcport->rport_lock, flags);	fcport->rport = rport;	*((fc_port_t **)rport->dd_data) = fcport;	spin_unlock_irqrestore(&fcport->rport_lock, flags);	rport->supported_classes = fcport->supported_classes;	rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;	if (fcport->port_type == FCT_INITIATOR)		rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;	if (fcport->port_type == FCT_TARGET)		rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;	fc_remote_port_rolechg(rport, rport_ids.roles);	if (rport->scsi_target_id != -1 &&	    rport->scsi_target_id < ha->host->max_id)		fcport->os_target_id = rport->scsi_target_id;}/* * 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. */voidqla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport){	scsi_qla_host_t *pha = to_qla_parent(ha);	fcport->ha = ha;	fcport->login_retry = 0;	fcport->port_login_retry_count = pha->port_down_retry_count *	    PORT_RETRY_TIME;	atomic_set(&fcport->port_down_timer, pha->port_down_retry_count *	    PORT_RETRY_TIME);	fcport->flags &= ~FCF_LOGIN_NEEDED;	qla2x00_iidma_fcport(ha, fcport);	atomic_set(&fcport->state, FCS_ONLINE);	qla2x00_reg_remote_port(ha, fcport);}/* * qla2x00_configure_fabric *      Setup SNS devices with loop ID's. * * Input: *      ha = adapter block pointer. * * Returns: *      0 = success. *      BIT_0 = error */static intqla2x00_configure_fabric(scsi_qla_host_t *ha){	int	rval, rval2;	fc_port_t	*fcport, *fcptemp;	uint16_t	next_loopid;	uint16_t	mb[MAILBOX_REGISTER_COUNT];	uint16_t	loop_id;	LIST_HEAD(new_fcports);	scsi_qla_host_t *pha = to_qla_parent(ha);	/* If FL port exists, then SNS is present */	if (IS_FWI2_CAPABLE(ha))		loop_id = NPH_F_PORT;	else		loop_id = SNS_FL_PORT;	rval = qla2x00_get_port_name(ha, loop_id, ha->fabric_node_name, 1);	if (rval != QLA_SUCCESS) {		DEBUG2(printk("scsi(%ld): MBC_GET_PORT_NAME Failed, No FL "		    "Port\n", ha->host_no));		ha->device_flags &= ~SWITCH_FOUND;		return (QLA_SUCCESS);	}	ha->device_flags |= SWITCH_FOUND;	/* Mark devices that need re-synchronization. */	rval2 = qla2x00_device_resync(ha);	if (rval2 == QLA_RSCNS_HANDLED) {		/* No point doing the scan, just continue. */		return (QLA_SUCCESS);	}	do {		/* FDMI support. */		if (ql2xfdmienable &&		    test_and_clear_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags))			qla2x00_fdmi_register(ha);		/* Ensure we are logged into the SNS. */		if (IS_FWI2_CAPABLE(ha))			loop_id = NPH_SNS;		else			loop_id = SIMPLE_NAME_SERVER;		ha->isp_ops->fabric_login(ha, loop_id, 0xff, 0xff,		    0xfc, mb, BIT_1 | BIT_0);		if (mb[0] != MBS_COMMAND_COMPLETE) {			DEBUG2(qla_printk(KERN_INFO, ha,			    "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x "			    "mb[2]=%x mb[6]=%x mb[7]=%x\n", loop_id,			    mb[0], mb[1], mb[2], mb[6], mb[7]));			return (QLA_SUCCESS);		}		if (test_and_clear_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags)) {			if (qla2x00_rft_id(ha)) {				/* EMPTY */				DEBUG2(printk("scsi(%ld): Register FC-4 "				    "TYPE failed.\n", ha->host_no));			}			if (qla2x00_rff_id(ha)) {				/* EMPTY */				DEBUG2(printk("scsi(%ld): Register FC-4 "				    "Features failed.\n", ha->host_no));			}			if (qla2x00_rnn_id(ha)) {				/* EMPTY */				DEBUG2(printk("scsi(%ld): Register Node Name "				    "failed.\n", ha->host_no));			} else if (qla2x00_rsnn_nn(ha)) {				/* EMPTY */				DEBUG2(printk("scsi(%ld): Register Symbolic "				    "Node Name failed.\n", ha->host_no));			}		}		rval = qla2x00_find_all_fabric_devs(ha, &new_fcports);		if (rval != QLA_SUCCESS)			break;		/*		 * Logout all previous fabric devices marked lost, except		 * tape devices.		 */		list_for_each_entry(fcport, &pha->fcports, list) {			if (fcport->vp_idx !=ha->vp_idx)				continue;			if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))				break;			if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)				continue;			if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) {				qla2x00_mark_device_lost(ha, fcport,				    ql2xplogiabsentdevice, 0);				if (fcport->loop_id != FC_NO_LOOP_ID &&				    (fcport->flags & FCF_TAPE_PRESENT) == 0 &&				    fcport->port_type != FCT_INITIATOR &&				    fcport->port_type != FCT_BROADCAST) {					ha->isp_ops->fabric_logout(ha,					    fcport->loop_id,					    fcport->d_id.b.domain,					    fcport->d_id.b.area,					    fcport->d_id.b.al_pa);					fcport->loop_id = FC_NO_LOOP_ID;				}			}		}		/* Starting free loop ID. */		next_loopid = pha->min_external_loopid;		/*		 * Scan through our port list and login entries that need to be		 * logged in.		 */		list_for_each_entry(fcport, &pha->fcports, list) {			if (fcport->vp_idx != ha->vp_idx)				continue;			if (atomic_read(&ha->loop_down_timer) ||			    test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))				break;			if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||			    (fcport->flags & FCF_LOGIN_NEEDED) == 0)				continue;			if (fcport->loop_id == FC_NO_LOOP_ID) {				fcport->loop_id = next_loopid;				rval = qla2x00_find_new_loop_id(ha, fcport);				if (rval != QLA_SUCCESS) {					/* Ran out of IDs to use */					break;				}			}			/* Login and update database */			qla2x00_fabric_dev_login(ha, fcport, &next_loopid);		}		/* Exit if out of loop IDs. */		if (rval != QLA_SUCCESS) {			break;		}		/*		 * Login and add the new devices to our port list.		 */		list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {			if (atomic_read(&ha->loop_down_timer) ||			    test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))				break;			/* Find a new loop ID to use. */			fcport->loop_id = next_loopid;			rval = qla2x00_find_new_loop_id(ha, fcport);			if (rval != QLA_SUCCESS) {				/* Ran out of IDs to use */				break;			}			/* Login and update database */			qla2x00_fabric_dev_login(ha, fcport, &next_loopid);			if (ha->parent) {				fcport->ha = ha;				fcport->vp_idx = ha->vp_idx;				list_add_tail(&fcport->vp_fcport,				    &ha->vp_fcports);				list_move_tail(&fcport->list,				    &ha->parent->fcports);			} else				list_move_tail(&fcport->list, &ha->fcports);		}	} while (0);	/* Free all new device structures not processed. */	list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) {		list_del(&fcport->list);		kfree(fcport);	}	if (rval) {		DEBUG2(printk("scsi(%ld): Configure fabric error exit: "		    "rval=%d\n", ha->host_no, rval));	}	return (rval);}/* * qla2x00_find_all_fabric_devs * * Input: *	ha = adapter block pointer. *	dev = database device entry pointer. * * Returns: *	0 = success. * * Context: *	Kernel context. */static intqla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports){	int		rval;	uint16_t	loop_id;	fc_port_t	*fcport, *new_fcport, *fcptemp;	int		found;	sw_info_t	*swl;	int		swl_idx;	int		first_dev, last_dev;	port_id_t	wrap, nxt_d_id;	int 		vp_index;	int		empty_vp_index;	int		found_vp;	scsi_qla_host_t *vha;	scsi_qla_host_t *pha = to_qla_parent(ha);	

⌨️ 快捷键说明

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