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

📄 qla_init.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
{	int			rval;	uint32_t		len, cnt;	uint16_t		lun;	/* Assume a failed status */	rval = QLA_FUNCTION_FAILED;	/* No point in continuing if the device doesn't support RLC */	if ((fcport->flags & FCF_RLC_SUPPORT) == 0)		return (rval);	rval = qla2x00_report_lun(ha, fcport);	if (rval != QLA_SUCCESS)		return (rval);	/* Configure LUN list. */	len = be32_to_cpu(ha->rlc_rsp->list.hdr.len);	len /= 8;	for (cnt = 0; cnt < len; cnt++) {		lun = CHAR_TO_SHORT(ha->rlc_rsp->list.lst[cnt].lsb,		    ha->rlc_rsp->list.lst[cnt].msb.b);		DEBUG3(printk("scsi(%ld): RLC lun = (%d)\n", ha->host_no, lun));		/* We only support 0 through MAX_LUNS-1 range */		if (lun < MAX_LUNS) {			qla2x00_cfg_lun(ha, fcport, lun, inq, inq_dma);		}	}	atomic_set(&fcport->state, FCS_ONLINE);	return (rval);}/* * qla2x00_report_lun *	Issue SCSI report LUN command. * * Input: *	ha:		adapter state pointer. *	fcport:		FC port structure pointer. * * Returns: *	qla2x00 local function return status code. * * Context: *	Kernel context. */static intqla2x00_report_lun(scsi_qla_host_t *ha, fc_port_t *fcport){	int rval;	uint16_t retries;	uint16_t comp_status;	uint16_t scsi_status;	rpt_lun_cmd_rsp_t *rlc;	dma_addr_t rlc_dma;	rval = QLA_FUNCTION_FAILED;	rlc = ha->rlc_rsp;	rlc_dma = ha->rlc_rsp_dma;	for (retries = 3; retries; retries--) {		memset(rlc, 0, sizeof(rpt_lun_cmd_rsp_t));		rlc->p.cmd.entry_type = COMMAND_A64_TYPE;		rlc->p.cmd.entry_count = 1;		SET_TARGET_ID(ha, rlc->p.cmd.target, fcport->loop_id);		rlc->p.cmd.control_flags =		    __constant_cpu_to_le16(CF_READ | CF_SIMPLE_TAG);		rlc->p.cmd.scsi_cdb[0] = REPORT_LUNS;		rlc->p.cmd.scsi_cdb[8] = MSB(sizeof(rpt_lun_lst_t));		rlc->p.cmd.scsi_cdb[9] = LSB(sizeof(rpt_lun_lst_t));		rlc->p.cmd.dseg_count = __constant_cpu_to_le16(1);		rlc->p.cmd.timeout = __constant_cpu_to_le16(10);		rlc->p.cmd.byte_count =		    __constant_cpu_to_le32(sizeof(rpt_lun_lst_t));		rlc->p.cmd.dseg_0_address[0] = cpu_to_le32(		    LSD(rlc_dma + sizeof(sts_entry_t)));		rlc->p.cmd.dseg_0_address[1] = cpu_to_le32(		    MSD(rlc_dma + sizeof(sts_entry_t)));		rlc->p.cmd.dseg_0_length =		    __constant_cpu_to_le32(sizeof(rpt_lun_lst_t));		rval = qla2x00_issue_iocb(ha, rlc, rlc_dma,		    sizeof(rpt_lun_cmd_rsp_t));		comp_status = le16_to_cpu(rlc->p.rsp.comp_status);		scsi_status = le16_to_cpu(rlc->p.rsp.scsi_status);		if (rval != QLA_SUCCESS || comp_status != CS_COMPLETE ||		    scsi_status & SS_CHECK_CONDITION) {			/* Device underrun, treat as OK. */			if (rval == QLA_SUCCESS &&			    comp_status == CS_DATA_UNDERRUN &&			    scsi_status & SS_RESIDUAL_UNDER) {				rval = QLA_SUCCESS;				break;			}			DEBUG(printk("scsi(%ld): RLC failed to issue iocb! "			    "fcport=[%04x/%p] rval=%x cs=%x ss=%x\n",			    ha->host_no, fcport->loop_id, fcport, rval,			    comp_status, scsi_status));			rval = QLA_FUNCTION_FAILED;			if (scsi_status & SS_CHECK_CONDITION) {				DEBUG2(printk("scsi(%ld): RLC "				    "SS_CHECK_CONDITION Sense Data "				    "%02x %02x %02x %02x %02x %02x %02x %02x\n",				    ha->host_no,				    rlc->p.rsp.req_sense_data[0],				    rlc->p.rsp.req_sense_data[1],				    rlc->p.rsp.req_sense_data[2],				    rlc->p.rsp.req_sense_data[3],				    rlc->p.rsp.req_sense_data[4],				    rlc->p.rsp.req_sense_data[5],				    rlc->p.rsp.req_sense_data[6],				    rlc->p.rsp.req_sense_data[7]));				if (rlc->p.rsp.req_sense_data[2] ==				    ILLEGAL_REQUEST) {					fcport->flags &= ~(FCF_RLC_SUPPORT);					break;				}			}		} else {			break;		}	}	return (rval);}/* * qla2x00_cfg_lun *	Configures LUN into fcport LUN list. * * Input: *	fcport:		FC port structure pointer. *	lun:		LUN number. * * Context: *	Kernel context. */static fc_lun_t *qla2x00_cfg_lun(scsi_qla_host_t *ha, fc_port_t *fcport, uint16_t lun,    inq_cmd_rsp_t *inq, dma_addr_t inq_dma) {	fc_lun_t *fclun;	uint8_t	  device_type;	/* Bypass LUNs that failed. */	if (qla2x00_inquiry(ha, fcport, lun, inq, inq_dma) != QLA_SUCCESS) {		DEBUG2(printk("scsi(%ld): Failed inquiry - loop id=0x%04x "		    "lun=%d\n", ha->host_no, fcport->loop_id, lun));		return (NULL);	}	device_type = (inq->inq[0] & 0x1f);	switch (device_type) {	case TYPE_DISK:	case TYPE_PROCESSOR:	case TYPE_WORM:	case TYPE_ROM:	case TYPE_SCANNER:	case TYPE_MOD:	case TYPE_MEDIUM_CHANGER:	case TYPE_ENCLOSURE:	case 0x20:	case 0x0C:		break;	case TYPE_TAPE:		fcport->flags |= FCF_TAPE_PRESENT;		break;	default:		DEBUG2(printk("scsi(%ld): Unsupported lun type -- "		    "loop id=0x%04x lun=%d type=%x\n",		    ha->host_no, fcport->loop_id, lun, device_type));		return (NULL);	}	fcport->device_type = device_type;	fclun = qla2x00_add_lun(fcport, lun);	if (fclun != NULL) {		atomic_set(&fcport->state, FCS_ONLINE);	}	return (fclun);}/* * qla2x00_add_lun *	Adds LUN to database * * Input: *	fcport:		FC port structure pointer. *	lun:		LUN number. * * Context: *	Kernel context. */static fc_lun_t *qla2x00_add_lun(fc_port_t *fcport, uint16_t lun){	int		found;	fc_lun_t	*fclun;	if (fcport == NULL) {		DEBUG(printk("scsi: Unable to add lun to NULL port\n"));		return (NULL);	}	/* Allocate LUN if not already allocated. */	found = 0;	list_for_each_entry(fclun, &fcport->fcluns, list) {		if (fclun->lun == lun) {			found++;			break;		}	}	if (found)		return (NULL);	fclun = kmalloc(sizeof(fc_lun_t), GFP_ATOMIC);	if (fclun == NULL) {		printk(KERN_WARNING		    "%s(): Memory Allocation failed - FCLUN\n",		    __func__);		return (NULL);	}	/* Setup LUN structure. */	memset(fclun, 0, sizeof(fc_lun_t));	fclun->lun = lun;	fclun->fcport = fcport;	fclun->o_fcport = fcport;	fclun->device_type = fcport->device_type;	atomic_set(&fcport->state, FCS_UNCONFIGURED);	list_add_tail(&fclun->list, &fcport->fcluns);	return (fclun);}/* * qla2x00_inquiry *	Issue SCSI inquiry command. * * Input: *	ha = adapter block pointer. *	fcport = FC port structure pointer. * * Return: *	0  - Success *  BIT_0 - error * * Context: *	Kernel context. */static intqla2x00_inquiry(scsi_qla_host_t *ha,    fc_port_t *fcport, uint16_t lun, inq_cmd_rsp_t *inq, dma_addr_t inq_dma){	int rval;	uint16_t retries;	uint16_t comp_status;	uint16_t scsi_status;	rval = QLA_FUNCTION_FAILED;	for (retries = 3; retries; retries--) {		memset(inq, 0, sizeof(inq_cmd_rsp_t));		inq->p.cmd.entry_type = COMMAND_A64_TYPE;		inq->p.cmd.entry_count = 1;		inq->p.cmd.lun = cpu_to_le16(lun);		SET_TARGET_ID(ha, inq->p.cmd.target, fcport->loop_id);		inq->p.cmd.control_flags =		    __constant_cpu_to_le16(CF_READ | CF_SIMPLE_TAG);		inq->p.cmd.scsi_cdb[0] = INQUIRY;		inq->p.cmd.scsi_cdb[4] = INQ_DATA_SIZE;		inq->p.cmd.dseg_count = __constant_cpu_to_le16(1);		inq->p.cmd.timeout = __constant_cpu_to_le16(10);		inq->p.cmd.byte_count =		    __constant_cpu_to_le32(INQ_DATA_SIZE);		inq->p.cmd.dseg_0_address[0] = cpu_to_le32(		    LSD(inq_dma + sizeof(sts_entry_t)));		inq->p.cmd.dseg_0_address[1] = cpu_to_le32(		    MSD(inq_dma + sizeof(sts_entry_t)));		inq->p.cmd.dseg_0_length =		    __constant_cpu_to_le32(INQ_DATA_SIZE);		DEBUG5(printk("scsi(%ld): Lun Inquiry - fcport=[%04x/%p],"		    " lun (%d)\n",		    ha->host_no, fcport->loop_id, fcport, lun));		rval = qla2x00_issue_iocb(ha, inq, inq_dma,		    sizeof(inq_cmd_rsp_t));		comp_status = le16_to_cpu(inq->p.rsp.comp_status);		scsi_status = le16_to_cpu(inq->p.rsp.scsi_status);		DEBUG5(printk("scsi(%ld): lun (%d) inquiry - "		    "inq[0]= 0x%x, comp status 0x%x, scsi status 0x%x, "		    "rval=%d\n",		    ha->host_no, lun, inq->inq[0], comp_status, scsi_status,		    rval));		if (rval != QLA_SUCCESS || comp_status != CS_COMPLETE ||		    scsi_status & SS_CHECK_CONDITION) {			DEBUG(printk("scsi(%ld): INQ failed to issue iocb! "			    "fcport=[%04x/%p] rval=%x cs=%x ss=%x\n",			    ha->host_no, fcport->loop_id, fcport, rval,			    comp_status, scsi_status));			if (rval == QLA_SUCCESS)				rval = QLA_FUNCTION_FAILED;			if (scsi_status & SS_CHECK_CONDITION) {				DEBUG2(printk("scsi(%ld): INQ "				    "SS_CHECK_CONDITION Sense Data "				    "%02x %02x %02x %02x %02x %02x %02x %02x\n",				    ha->host_no,				    inq->p.rsp.req_sense_data[0],				    inq->p.rsp.req_sense_data[1],				    inq->p.rsp.req_sense_data[2],				    inq->p.rsp.req_sense_data[3],				    inq->p.rsp.req_sense_data[4],				    inq->p.rsp.req_sense_data[5],				    inq->p.rsp.req_sense_data[6],				    inq->p.rsp.req_sense_data[7]));			}			/* Device underrun drop LUN. */			if (comp_status == CS_DATA_UNDERRUN &&			    scsi_status & SS_RESIDUAL_UNDER) {				break;			}		} else {			break;		}	}	return (rval);}/* * 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];	LIST_HEAD(new_fcports);	/* If FL port exists, then SNS is present */	rval = qla2x00_get_port_name(ha, SNS_FL_PORT, NULL, 0);	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);	}	/* 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 {		/* Ensure we are logged into the SNS. */		qla2x00_login_fabric(ha, SIMPLE_NAME_SERVER, 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", SIMPLE_NAME_SERVER,			    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, &ha->fcports, list) {			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);				if (fcport->loop_id != FC_NO_LOOP_ID &&				    (fcport->flags & FCF_TAPE_PRESENT) == 0 &&				    fcport->port_type != FCT_INITIATOR &&				    fcport->port_type != FCT_BROADCAST) {					qla2x00_fabric_logout(ha,					    fcport->loop_id);					fcport->loop_id = FC_NO_LOOP_ID;				}			}		}		/* Starting free loop ID. */		next_loopid = ha->min_external_loopid;		/*		 * Scan through our port list and login entries that need to be		 * logged in.		 */		list_for_each_entry(fcport, &ha->fcports, list) {			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-

⌨️ 快捷键说明

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