qla_init.c

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

C
2,472
字号
	DEBUG3(qla2x00_dump_buffer((uint8_t *)&ha->fw_seriallink_options,	    sizeof(ha->fw_seriallink_options)));	ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;	if (ha->fw_seriallink_options[3] & BIT_2) {		ha->fw_options[1] |= FO1_SET_EMPHASIS_SWING;		/*  1G settings */		swing = ha->fw_seriallink_options[2] & (BIT_2 | BIT_1 | BIT_0);		emphasis = (ha->fw_seriallink_options[2] &		    (BIT_4 | BIT_3)) >> 3;		tx_sens = ha->fw_seriallink_options[0] &		    (BIT_3 | BIT_2 | BIT_1 | BIT_0);		rx_sens = (ha->fw_seriallink_options[0] &		    (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4;		ha->fw_options[10] = (emphasis << 14) | (swing << 8);		if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {			if (rx_sens == 0x0)				rx_sens = 0x3;			ha->fw_options[10] |= (tx_sens << 4) | rx_sens;		} else if (IS_QLA2322(ha) || IS_QLA6322(ha))			ha->fw_options[10] |= BIT_5 |			    ((rx_sens & (BIT_1 | BIT_0)) << 2) |			    (tx_sens & (BIT_1 | BIT_0));		/*  2G settings */		swing = (ha->fw_seriallink_options[2] &		    (BIT_7 | BIT_6 | BIT_5)) >> 5;		emphasis = ha->fw_seriallink_options[3] & (BIT_1 | BIT_0);		tx_sens = ha->fw_seriallink_options[1] &		    (BIT_3 | BIT_2 | BIT_1 | BIT_0);		rx_sens = (ha->fw_seriallink_options[1] &		    (BIT_7 | BIT_6 | BIT_5 | BIT_4)) >> 4;		ha->fw_options[11] = (emphasis << 14) | (swing << 8);		if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {			if (rx_sens == 0x0)				rx_sens = 0x3;			ha->fw_options[11] |= (tx_sens << 4) | rx_sens;		} else if (IS_QLA2322(ha) || IS_QLA6322(ha))			ha->fw_options[11] |= BIT_5 |			    ((rx_sens & (BIT_1 | BIT_0)) << 2) |			    (tx_sens & (BIT_1 | BIT_0));	}	/* FCP2 options. */	/*  Return command IOCBs without waiting for an ABTS to complete. */	ha->fw_options[3] |= BIT_13;	/* LED scheme. */	if (ha->flags.enable_led_scheme)		ha->fw_options[2] |= BIT_12;	/* Detect ISP6312. */	if (IS_QLA6312(ha))		ha->fw_options[2] |= BIT_13;	/* Update firmware options. */	qla2x00_set_fw_options(ha, ha->fw_options);}voidqla24xx_update_fw_options(scsi_qla_host_t *ha){	int rval;	/* Update Serial Link options. */	if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)		return;	rval = qla2x00_set_serdes_params(ha,	    le16_to_cpu(ha->fw_seriallink_options24[1]),	    le16_to_cpu(ha->fw_seriallink_options24[2]),	    le16_to_cpu(ha->fw_seriallink_options24[3]));	if (rval != QLA_SUCCESS) {		qla_printk(KERN_WARNING, ha,		    "Unable to update Serial Link options (%x).\n", rval);	}}voidqla2x00_config_rings(struct scsi_qla_host *ha){	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;	/* Setup ring parameters in initialization control block. */	ha->init_cb->request_q_outpointer = __constant_cpu_to_le16(0);	ha->init_cb->response_q_inpointer = __constant_cpu_to_le16(0);	ha->init_cb->request_q_length = cpu_to_le16(ha->request_q_length);	ha->init_cb->response_q_length = cpu_to_le16(ha->response_q_length);	ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma));	ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma));	ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma));	ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma));	WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0);	WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0);	WRT_REG_WORD(ISP_RSP_Q_IN(ha, reg), 0);	WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), 0);	RD_REG_WORD(ISP_RSP_Q_OUT(ha, reg));		/* PCI Posting. */}voidqla24xx_config_rings(struct scsi_qla_host *ha){	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;	struct init_cb_24xx *icb;	/* Setup ring parameters in initialization control block. */	icb = (struct init_cb_24xx *)ha->init_cb;	icb->request_q_outpointer = __constant_cpu_to_le16(0);	icb->response_q_inpointer = __constant_cpu_to_le16(0);	icb->request_q_length = cpu_to_le16(ha->request_q_length);	icb->response_q_length = cpu_to_le16(ha->response_q_length);	icb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma));	icb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma));	icb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma));	icb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma));	WRT_REG_DWORD(&reg->req_q_in, 0);	WRT_REG_DWORD(&reg->req_q_out, 0);	WRT_REG_DWORD(&reg->rsp_q_in, 0);	WRT_REG_DWORD(&reg->rsp_q_out, 0);	RD_REG_DWORD(&reg->rsp_q_out);}/** * qla2x00_init_rings() - Initializes firmware. * @ha: HA context * * Beginning of request ring has initialization control block already built * by nvram config routine. * * Returns 0 on success. */static intqla2x00_init_rings(scsi_qla_host_t *ha){	int	rval;	unsigned long flags = 0;	int cnt;	struct mid_init_cb_24xx *mid_init_cb =	    (struct mid_init_cb_24xx *) ha->init_cb;	spin_lock_irqsave(&ha->hardware_lock, flags);	/* Clear outstanding commands array. */	for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)		ha->outstanding_cmds[cnt] = NULL;	ha->current_outstanding_cmd = 0;	/* Clear RSCN queue. */	ha->rscn_in_ptr = 0;	ha->rscn_out_ptr = 0;	/* Initialize firmware. */	ha->request_ring_ptr  = ha->request_ring;	ha->req_ring_index    = 0;	ha->req_q_cnt         = ha->request_q_length;	ha->response_ring_ptr = ha->response_ring;	ha->rsp_ring_index    = 0;	/* Initialize response queue entries */	qla2x00_init_response_q_entries(ha);	ha->isp_ops->config_rings(ha);	spin_unlock_irqrestore(&ha->hardware_lock, flags);	/* Update any ISP specific firmware options before initialization. */	ha->isp_ops->update_fw_options(ha);	DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no));	mid_init_cb->count = ha->max_npiv_vports;	rval = qla2x00_init_firmware(ha, ha->init_cb_size);	if (rval) {		DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n",		    ha->host_no));	} else {		DEBUG3(printk("scsi(%ld): Init firmware -- success.\n",		    ha->host_no));	}	return (rval);}/** * qla2x00_fw_ready() - Waits for firmware ready. * @ha: HA context * * Returns 0 on success. */static intqla2x00_fw_ready(scsi_qla_host_t *ha){	int		rval;	unsigned long	wtime, mtime;	uint16_t	min_wait;	/* Minimum wait time if loop is down */	uint16_t	wait_time;	/* Wait time if loop is coming ready */	uint16_t	fw_state;	rval = QLA_SUCCESS;	/* 20 seconds for loop down. */	min_wait = 20;	/*	 * Firmware should take at most one RATOV to login, plus 5 seconds for	 * our own processing.	 */	if ((wait_time = (ha->retry_count*ha->login_timeout) + 5) < min_wait) {		wait_time = min_wait;	}	/* Min wait time if loop down */	mtime = jiffies + (min_wait * HZ);	/* wait time before firmware ready */	wtime = jiffies + (wait_time * HZ);	/* Wait for ISP to finish LIP */	if (!ha->flags.init_done) 		qla_printk(KERN_INFO, ha, "Waiting for LIP to complete...\n");	DEBUG3(printk("scsi(%ld): Waiting for LIP to complete...\n",	    ha->host_no));	do {		rval = qla2x00_get_firmware_state(ha, &fw_state);		if (rval == QLA_SUCCESS) {			if (fw_state < FSTATE_LOSS_OF_SYNC) {				ha->device_flags &= ~DFLG_NO_CABLE;			}			if (fw_state == FSTATE_READY) {				DEBUG(printk("scsi(%ld): F/W Ready - OK \n",				    ha->host_no));				qla2x00_get_retry_cnt(ha, &ha->retry_count,				    &ha->login_timeout, &ha->r_a_tov);				rval = QLA_SUCCESS;				break;			}			rval = QLA_FUNCTION_FAILED;			if (atomic_read(&ha->loop_down_timer) &&			    fw_state != FSTATE_READY) {				/* Loop down. Timeout on min_wait for states				 * other than Wait for Login.				 */				if (time_after_eq(jiffies, mtime)) {					qla_printk(KERN_INFO, ha,					    "Cable is unplugged...\n");					ha->device_flags |= DFLG_NO_CABLE;					break;				}			}		} else {			/* Mailbox cmd failed. Timeout on min_wait. */			if (time_after_eq(jiffies, mtime))				break;		}		if (time_after_eq(jiffies, wtime))			break;		/* Delay for a while */		msleep(500);		DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",		    ha->host_no, fw_state, jiffies));	} while (1);	DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",	    ha->host_no, fw_state, jiffies));	if (rval) {		DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n",		    ha->host_no));	}	return (rval);}/**  qla2x00_configure_hba*      Setup adapter context.** Input:*      ha = adapter state pointer.** Returns:*      0 = success** Context:*      Kernel context.*/static intqla2x00_configure_hba(scsi_qla_host_t *ha){	int       rval;	uint16_t      loop_id;	uint16_t      topo;	uint16_t      sw_cap;	uint8_t       al_pa;	uint8_t       area;	uint8_t       domain;	char		connect_type[22];	/* Get host addresses. */	rval = qla2x00_get_adapter_id(ha,	    &loop_id, &al_pa, &area, &domain, &topo, &sw_cap);	if (rval != QLA_SUCCESS) {		if (LOOP_TRANSITION(ha) || atomic_read(&ha->loop_down_timer) ||		    (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) {			DEBUG2(printk("%s(%ld) Loop is in a transition state\n",			    __func__, ha->host_no));		} else {			qla_printk(KERN_WARNING, ha,			    "ERROR -- Unable to get host loop ID.\n");			set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);		}		return (rval);	}	if (topo == 4) {		qla_printk(KERN_INFO, ha,			"Cannot get topology - retrying.\n");		return (QLA_FUNCTION_FAILED);	}	ha->loop_id = loop_id;	/* initialize */	ha->min_external_loopid = SNS_FIRST_LOOP_ID;	ha->operating_mode = LOOP;	ha->switch_cap = 0;	switch (topo) {	case 0:		DEBUG3(printk("scsi(%ld): HBA in NL topology.\n",		    ha->host_no));		ha->current_topology = ISP_CFG_NL;		strcpy(connect_type, "(Loop)");		break;	case 1:		DEBUG3(printk("scsi(%ld): HBA in FL topology.\n",		    ha->host_no));		ha->switch_cap = sw_cap;		ha->current_topology = ISP_CFG_FL;		strcpy(connect_type, "(FL_Port)");		break;	case 2:		DEBUG3(printk("scsi(%ld): HBA in N P2P topology.\n",		    ha->host_no));		ha->operating_mode = P2P;		ha->current_topology = ISP_CFG_N;		strcpy(connect_type, "(N_Port-to-N_Port)");		break;	case 3:		DEBUG3(printk("scsi(%ld): HBA in F P2P topology.\n",		    ha->host_no));		ha->switch_cap = sw_cap;		ha->operating_mode = P2P;		ha->current_topology = ISP_CFG_F;		strcpy(connect_type, "(F_Port)");		break;	default:		DEBUG3(printk("scsi(%ld): HBA in unknown topology %x. "		    "Using NL.\n",		    ha->host_no, topo));		ha->current_topology = ISP_CFG_NL;		strcpy(connect_type, "(Loop)");		break;	}	/* Save Host port and loop ID. */	/* byte order - Big Endian */	ha->d_id.b.domain = domain;	ha->d_id.b.area = area;	ha->d_id.b.al_pa = al_pa;	if (!ha->flags.init_done) 		qla_printk(KERN_INFO, ha,		    "Topology - %s, Host Loop address 0x%x\n", 		    connect_type, ha->loop_id);	if (rval) {		DEBUG2_3(printk("scsi(%ld): FAILED.\n", ha->host_no));	} else {		DEBUG3(printk("scsi(%ld): exiting normally.\n", ha->host_no));	}	return(rval);}static inline voidqla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *def){	char *st, *en;	uint16_t index;	if (memcmp(model, BINZERO, len) != 0) {		strncpy(ha->model_number, model, len);		st = en = ha->model_number;		en += len - 1;		while (en > st) {			if (*en != 0x20 && *en != 0x00)				break;			*en-- = '\0';		}		index = (ha->pdev->subsystem_device & 0xff);		if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&		    index < QLA_MODEL_NAMES)			ha->model_desc = qla2x00_model_name[index * 2 + 1];	} else {		index = (ha->pdev->subsystem_device & 0xff);		if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&		    index < QLA_MODEL_NAMES) {			strcpy(ha->model_number,			    qla2x00_model_name[index * 2]);			ha->model_desc = qla2x00_model_name[index * 2 + 1];		} else {			strcpy(ha->model_number, def);		}	}}/* On sparc systems, obtain port and node WWN from firmware * properties. */static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv){#ifdef CONFIG_SPARC	struct pci_dev *pdev = ha->pdev;	struct device_node *dp = pci_device_to_OF_node(pdev);	const u8 *val;	int len;	val = of_get_property(dp, "port-wwn", &len);	if (val && len >= WWN_SIZE)		memcpy(nv->port_name, val, WWN_SIZE);	val = of_get_property(dp, "node-wwn", &len);	if (val && len >= WWN_SIZE)		memcpy(nv->node_name, val, WWN_SIZE);#endif}/** NVRAM configuration for ISP 2xxx** Input:*      ha                = adapter block pointer.** Output:*      initialization control block in response_ring*      host adapters parameters in host adapter block** Returns:*      0 = success.*/intqla2x00_nvram_config(scsi_qla_host_t *ha){	int             rval;	uint8_t         chksum = 0;	uint16_t        cnt;	uint8_t         *dptr1, *dptr2;	init_cb_t       *icb = ha->init_cb;	nvram_t         *nv = ha->nvram;	uint8_t         *ptr = ha->nvram;	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;	rval = QLA_SUCCESS;	/* Determine NVRAM starting address. */	ha->nvram_size = sizeof(nvram_t);	ha->nvram_base = 0;	if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha))		if ((RD_REG_WORD(&reg->ctrl_status) >> 14) == 1)			ha->nvram_base = 0x80;	/* Get NVRAM data and calculate checksum. */	ha->isp_ops->read_nvram(ha, ptr, ha->nvram_base, ha->nvram_size);	for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++)

⌨️ 快捷键说明

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