diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 206 | 
1 files changed, 152 insertions, 54 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index bd7dd84c064..26202612932 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -634,7 +634,7 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)  		goto chip_diag_failed;  	DEBUG3(printk("scsi(%ld): Reset register cleared by chip reset\n", -	    ha->host_no)); +	    vha->host_no));  	/* Reset RISC processor. */  	WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); @@ -655,7 +655,7 @@ qla2x00_chip_diag(scsi_qla_host_t *vha)  		goto chip_diag_failed;  	/* Check product ID of chip */ -	DEBUG3(printk("scsi(%ld): Checking product ID of chip\n", ha->host_no)); +	DEBUG3(printk("scsi(%ld): Checking product ID of chip\n", vha->host_no));  	mb[1] = RD_MAILBOX_REG(ha, reg, 1);  	mb[2] = RD_MAILBOX_REG(ha, reg, 2); @@ -730,9 +730,6 @@ qla24xx_chip_diag(scsi_qla_host_t *vha)  	struct qla_hw_data *ha = vha->hw;  	struct req_que *req = ha->req_q_map[0]; -	/* Perform RISC reset. */ -	qla24xx_reset_risc(vha); -  	ha->fw_transfer_size = REQUEST_ENTRY_SIZE * req->length;  	rval = qla2x00_mbx_reg_test(vha); @@ -786,7 +783,6 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)  		    sizeof(uint32_t);  		if (ha->mqenable)  			mq_size = sizeof(struct qla2xxx_mq_chain); -  		/* Allocate memory for Fibre Channel Event Buffer. */  		if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))  			goto try_eft; @@ -850,8 +846,7 @@ cont_alloc:  	rsp_q_size = rsp->length * sizeof(response_t);  	dump_size = offsetof(struct qla2xxx_fw_dump, isp); -	dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + -	    eft_size; +	dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + eft_size;  	ha->chain_offset = dump_size;  	dump_size += mq_size + fce_size; @@ -891,6 +886,56 @@ cont_alloc:  	    htonl(offsetof(struct qla2xxx_fw_dump, isp));  } +static int +qla81xx_mpi_sync(scsi_qla_host_t *vha) +{ +#define MPS_MASK	0xe0 +	int rval; +	uint16_t dc; +	uint32_t dw; +	struct qla_hw_data *ha = vha->hw; + +	if (!IS_QLA81XX(vha->hw)) +		return QLA_SUCCESS; + +	rval = qla2x00_write_ram_word(vha, 0x7c00, 1); +	if (rval != QLA_SUCCESS) { +		DEBUG2(qla_printk(KERN_WARNING, ha, +		    "Sync-MPI: Unable to acquire semaphore.\n")); +		goto done; +	} + +	pci_read_config_word(vha->hw->pdev, 0x54, &dc); +	rval = qla2x00_read_ram_word(vha, 0x7a15, &dw); +	if (rval != QLA_SUCCESS) { +		DEBUG2(qla_printk(KERN_WARNING, ha, +		    "Sync-MPI: Unable to read sync.\n")); +		goto done_release; +	} + +	dc &= MPS_MASK; +	if (dc == (dw & MPS_MASK)) +		goto done_release; + +	dw &= ~MPS_MASK; +	dw |= dc; +	rval = qla2x00_write_ram_word(vha, 0x7a15, dw); +	if (rval != QLA_SUCCESS) { +		DEBUG2(qla_printk(KERN_WARNING, ha, +		    "Sync-MPI: Unable to gain sync.\n")); +	} + +done_release: +	rval = qla2x00_write_ram_word(vha, 0x7c00, 0); +	if (rval != QLA_SUCCESS) { +		DEBUG2(qla_printk(KERN_WARNING, ha, +		    "Sync-MPI: Unable to release semaphore.\n")); +	} + +done: +	return rval; +} +  /**   * qla2x00_setup_chip() - Load and start RISC firmware.   * @ha: HA context @@ -915,6 +960,8 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)  		spin_unlock_irqrestore(&ha->hardware_lock, flags);  	} +	qla81xx_mpi_sync(vha); +  	/* Load firmware sequences */  	rval = ha->isp_ops->load_risc(vha, &srisc_address);  	if (rval == QLA_SUCCESS) { @@ -931,13 +978,16 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)  			/* Retrieve firmware information. */  			if (rval == QLA_SUCCESS) {  				fw_major_version = ha->fw_major_version; -				qla2x00_get_fw_version(vha, +				rval = qla2x00_get_fw_version(vha,  				    &ha->fw_major_version,  				    &ha->fw_minor_version,  				    &ha->fw_subminor_version,  				    &ha->fw_attributes, &ha->fw_memory_size,  				    ha->mpi_version, &ha->mpi_capabilities,  				    ha->phy_version); +				if (rval != QLA_SUCCESS) +					goto failed; +  				ha->flags.npiv_supported = 0;  				if (IS_QLA2XXX_MIDTYPE(ha) &&  					 (ha->fw_attributes & BIT_2)) { @@ -989,7 +1039,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)  			    ha->fw_subminor_version);  		}  	} - +failed:  	if (rval) {  		DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n",  		    vha->host_no)); @@ -1013,12 +1063,14 @@ qla2x00_init_response_q_entries(struct rsp_que *rsp)  	uint16_t cnt;  	response_t *pkt; +	rsp->ring_ptr = rsp->ring; +	rsp->ring_index    = 0; +	rsp->status_srb = NULL;  	pkt = rsp->ring_ptr;  	for (cnt = 0; cnt < rsp->length; cnt++) {  		pkt->signature = RESPONSE_PROCESSED;  		pkt++;  	} -  }  /** @@ -1176,7 +1228,7 @@ qla24xx_config_rings(struct scsi_qla_host *vha)  		if (ha->flags.msix_enabled) {  			msix = &ha->msix_entries[1];  			DEBUG2_17(printk(KERN_INFO -			"Reistering vector 0x%x for base que\n", msix->entry)); +			"Registering vector 0x%x for base que\n", msix->entry));  			icb->msix = cpu_to_le16(msix->entry);  		}  		/* Use alternate PCI bus number */ @@ -1230,14 +1282,14 @@ qla2x00_init_rings(scsi_qla_host_t *vha)  	spin_lock_irqsave(&ha->hardware_lock, flags);  	/* Clear outstanding commands array. */ -	for (que = 0; que < ha->max_queues; que++) { +	for (que = 0; que < ha->max_req_queues; que++) {  		req = ha->req_q_map[que];  		if (!req)  			continue; -		for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) +		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)  			req->outstanding_cmds[cnt] = NULL; -		req->current_outstanding_cmd = 0; +		req->current_outstanding_cmd = 1;  		/* Initialize firmware. */  		req->ring_ptr  = req->ring; @@ -1245,13 +1297,10 @@ qla2x00_init_rings(scsi_qla_host_t *vha)  		req->cnt      = req->length;  	} -	for (que = 0; que < ha->max_queues; que++) { +	for (que = 0; que < ha->max_rsp_queues; que++) {  		rsp = ha->rsp_q_map[que];  		if (!rsp)  			continue; -		rsp->ring_ptr = rsp->ring; -		rsp->ring_index    = 0; -  		/* Initialize response queue entries */  		qla2x00_init_response_q_entries(rsp);  	} @@ -1307,7 +1356,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)  	unsigned long	wtime, mtime, cs84xx_time;  	uint16_t	min_wait;	/* Minimum wait time if loop is down */  	uint16_t	wait_time;	/* Wait time if loop is coming ready */ -	uint16_t	state[3]; +	uint16_t	state[5];  	struct qla_hw_data *ha = vha->hw;  	rval = QLA_SUCCESS; @@ -1406,8 +1455,9 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)  		    vha->host_no, state[0], jiffies));  	} while (1); -	DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n", -	    vha->host_no, state[0], jiffies)); +	DEBUG(printk("scsi(%ld): fw_state=%x (%x, %x, %x, %x) curr time=%lx.\n", +	    vha->host_no, state[0], state[1], state[2], state[3], state[4], +	    jiffies));  	if (rval) {  		DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n", @@ -1541,6 +1591,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,  	char *st, *en;  	uint16_t index;  	struct qla_hw_data *ha = vha->hw; +	int use_tbl = !IS_QLA25XX(ha) && !IS_QLA81XX(ha);  	if (memcmp(model, BINZERO, len) != 0) {  		strncpy(ha->model_number, model, len); @@ -1553,14 +1604,16 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,  		}  		index = (ha->pdev->subsystem_device & 0xff); -		if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && +		if (use_tbl && +		    ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&  		    index < QLA_MODEL_NAMES)  			strncpy(ha->model_desc,  			    qla2x00_model_name[index * 2 + 1],  			    sizeof(ha->model_desc) - 1);  	} else {  		index = (ha->pdev->subsystem_device & 0xff); -		if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && +		if (use_tbl && +		    ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&  		    index < QLA_MODEL_NAMES) {  			strcpy(ha->model_number,  			    qla2x00_model_name[index * 2]); @@ -2061,8 +2114,10 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)  	if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {  		if (test_bit(LOCAL_LOOP_UPDATE, &save_flags))  			set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); -		if (test_bit(RSCN_UPDATE, &save_flags)) +		if (test_bit(RSCN_UPDATE, &save_flags)) {  			set_bit(RSCN_UPDATE, &vha->dpc_flags); +			vha->flags.rscn_queue_overflow = 1; +		}  	}  	return (rval); @@ -2110,7 +2165,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)  		goto cleanup_allocation;  	DEBUG3(printk("scsi(%ld): Entries in ID list (%d)\n", -	    ha->host_no, entries)); +	    vha->host_no, entries));  	DEBUG3(qla2x00_dump_buffer((uint8_t *)ha->gid_list,  	    entries * sizeof(struct gid_list_info))); @@ -2243,7 +2298,8 @@ static void  qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)  {  #define LS_UNKNOWN      2 -	static char *link_speeds[5] = { "1", "2", "?", "4", "8" }; +	static char *link_speeds[] = { "1", "2", "?", "4", "8", "10" }; +	char *link_speed;  	int rval;  	uint16_t mb[6];  	struct qla_hw_data *ha = vha->hw; @@ -2266,10 +2322,15 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)  		    fcport->port_name[6], fcport->port_name[7], rval,  		    fcport->fp_speed, mb[0], mb[1]));  	} else { +		link_speed = link_speeds[LS_UNKNOWN]; +		if (fcport->fp_speed < 5) +			link_speed = link_speeds[fcport->fp_speed]; +		else if (fcport->fp_speed == 0x13) +			link_speed = link_speeds[5];  		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], +		    link_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], @@ -3180,9 +3241,14 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)  {  	int rval = QLA_SUCCESS;  	uint32_t wait_time; -	struct qla_hw_data *ha = vha->hw; -	struct req_que *req = ha->req_q_map[vha->req_ques[0]]; -	struct rsp_que *rsp = req->rsp; +	struct req_que *req; +	struct rsp_que *rsp; + +	if (ql2xmultique_tag) +		req = vha->hw->req_q_map[0]; +	else +		req = vha->req; +	rsp = req->rsp;  	atomic_set(&vha->loop_state, LOOP_UPDATE);  	clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); @@ -3448,7 +3514,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)  	int ret = -1;  	int i; -	for (i = 1; i < ha->max_queues; i++) { +	for (i = 1; i < ha->max_rsp_queues; i++) {  		rsp = ha->rsp_q_map[i];  		if (rsp) {  			rsp->options &= ~BIT_0; @@ -3462,6 +3528,8 @@ qla25xx_init_queues(struct qla_hw_data *ha)  					"%s Rsp que:%d inited\n", __func__,  						rsp->id));  		} +	} +	for (i = 1; i < ha->max_req_queues; i++) {  		req = ha->req_q_map[i];  		if (req) {  		/* Clear outstanding commands array. */ @@ -3566,14 +3634,15 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)  	nv = ha->nvram;  	/* Determine NVRAM starting address. */ -	ha->nvram_size = sizeof(struct nvram_24xx); -	ha->nvram_base = FA_NVRAM_FUNC0_ADDR; -	ha->vpd_size = FA_NVRAM_VPD_SIZE; -	ha->vpd_base = FA_NVRAM_VPD0_ADDR; -	if (PCI_FUNC(ha->pdev->devfn)) { +	if (ha->flags.port0) { +		ha->nvram_base = FA_NVRAM_FUNC0_ADDR; +		ha->vpd_base = FA_NVRAM_VPD0_ADDR; +	} else {  		ha->nvram_base = FA_NVRAM_FUNC1_ADDR;  		ha->vpd_base = FA_NVRAM_VPD1_ADDR;  	} +	ha->nvram_size = sizeof(struct nvram_24xx); +	ha->vpd_size = FA_NVRAM_VPD_SIZE;  	/* Get VPD data into cache */  	ha->vpd = ha->nvram + VPD_OFFSET; @@ -3587,7 +3656,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)  	for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)  		chksum += le32_to_cpu(*dptr++); -	DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); +	DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", vha->host_no));  	DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));  	/* Bad NVRAM data, set defaults parameters. */ @@ -3612,7 +3681,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)  		nv->exchange_count = __constant_cpu_to_le16(0);  		nv->hard_address = __constant_cpu_to_le16(124);  		nv->port_name[0] = 0x21; -		nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn); +		nv->port_name[1] = 0x00 + ha->port_no;  		nv->port_name[2] = 0x00;  		nv->port_name[3] = 0xe0;  		nv->port_name[4] = 0x8b; @@ -3798,11 +3867,11 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)  }  static int -qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr) +qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, +    uint32_t faddr)  {  	int	rval = QLA_SUCCESS;  	int	segments, fragment; -	uint32_t faddr;  	uint32_t *dcode, dlen;  	uint32_t risc_addr;  	uint32_t risc_size; @@ -3811,12 +3880,11 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr)  	struct req_que *req = ha->req_q_map[0];  	qla_printk(KERN_INFO, ha, -	    "FW: Loading from flash (%x)...\n", ha->flt_region_fw); +	    "FW: Loading from flash (%x)...\n", faddr);  	rval = QLA_SUCCESS;  	segments = FA_RISC_CODE_SEGMENTS; -	faddr = ha->flt_region_fw;  	dcode = (uint32_t *)req->ring;  	*srisc_addr = 0; @@ -4104,6 +4172,9 @@ qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)  {  	int rval; +	if (ql2xfwloadbin == 1) +		return qla81xx_load_risc(vha, srisc_addr); +  	/*  	 * FW Load priority:  	 * 1) Firmware via request-firmware interface (.bin file). @@ -4113,24 +4184,45 @@ qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)  	if (rval == QLA_SUCCESS)  		return rval; -	return qla24xx_load_risc_flash(vha, srisc_addr); +	return qla24xx_load_risc_flash(vha, srisc_addr, +	    vha->hw->flt_region_fw);  }  int  qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)  {  	int rval; +	struct qla_hw_data *ha = vha->hw; + +	if (ql2xfwloadbin == 2) +		goto try_blob_fw;  	/*  	 * FW Load priority:  	 * 1) Firmware residing in flash.  	 * 2) Firmware via request-firmware interface (.bin file). +	 * 3) Golden-Firmware residing in flash -- limited operation.  	 */ -	rval = qla24xx_load_risc_flash(vha, srisc_addr); +	rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw);  	if (rval == QLA_SUCCESS)  		return rval; -	return qla24xx_load_risc_blob(vha, srisc_addr); +try_blob_fw: +	rval = qla24xx_load_risc_blob(vha, srisc_addr); +	if (rval == QLA_SUCCESS || !ha->flt_region_gold_fw) +		return rval; + +	qla_printk(KERN_ERR, ha, +	    "FW: Attempting to fallback to golden firmware...\n"); +	rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_gold_fw); +	if (rval != QLA_SUCCESS) +		return rval; + +	qla_printk(KERN_ERR, ha, +	    "FW: Please update operational firmware...\n"); +	ha->flags.running_gold_fw = 1; + +	return rval;  }  void @@ -4146,7 +4238,7 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)  	ret = qla2x00_stop_firmware(vha);  	for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT && -	    retries ; retries--) { +	    ret != QLA_INVALID_COMMAND && retries ; retries--) {  		ha->isp_ops->reset_chip(vha);  		if (ha->isp_ops->chip_diag(vha) != QLA_SUCCESS)  			continue; @@ -4165,13 +4257,19 @@ qla24xx_configure_vhba(scsi_qla_host_t *vha)  	uint16_t mb[MAILBOX_REGISTER_COUNT];  	struct qla_hw_data *ha = vha->hw;  	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); -	struct req_que *req = ha->req_q_map[vha->req_ques[0]]; -	struct rsp_que *rsp = req->rsp; +	struct req_que *req; +	struct rsp_que *rsp;  	if (!vha->vp_idx)  		return -EINVAL;  	rval = qla2x00_fw_ready(base_vha); +	if (ql2xmultique_tag) +		req = ha->req_q_map[0]; +	else +		req = vha->req; +	rsp = req->rsp; +  	if (rval == QLA_SUCCESS) {  		clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);  		qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL); @@ -4305,7 +4403,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)  	for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)  		chksum += le32_to_cpu(*dptr++); -	DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); +	DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", vha->host_no));  	DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));  	/* Bad NVRAM data, set defaults parameters. */ @@ -4329,7 +4427,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)  		nv->execution_throttle = __constant_cpu_to_le16(0xFFFF);  		nv->exchange_count = __constant_cpu_to_le16(0);  		nv->port_name[0] = 0x21; -		nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn); +		nv->port_name[1] = 0x00 + ha->port_no;  		nv->port_name[2] = 0x00;  		nv->port_name[3] = 0xe0;  		nv->port_name[4] = 0x8b; @@ -4358,12 +4456,12 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)  		nv->max_luns_per_target = __constant_cpu_to_le16(128);  		nv->port_down_retry_count = __constant_cpu_to_le16(30);  		nv->link_down_timeout = __constant_cpu_to_le16(30); -		nv->enode_mac[0] = 0x01; +		nv->enode_mac[0] = 0x00;  		nv->enode_mac[1] = 0x02;  		nv->enode_mac[2] = 0x03;  		nv->enode_mac[3] = 0x04;  		nv->enode_mac[4] = 0x05; -		nv->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn); +		nv->enode_mac[5] = 0x06 + ha->port_no;  		rval = 1;  	} @@ -4396,7 +4494,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)  		icb->enode_mac[2] = 0x03;  		icb->enode_mac[3] = 0x04;  		icb->enode_mac[4] = 0x05; -		icb->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn); +		icb->enode_mac[5] = 0x06 + ha->port_no;  	}  	/* Use extended-initialization control block. */  |