diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 212 | 
1 files changed, 200 insertions, 12 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2c6dd3dfe0f..a083715843b 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -47,6 +47,7 @@ MODULE_PARM_DESC(ql2xenableclass2,  		"Specify if Class 2 operations are supported from the very "  		"beginning. Default is 0 - class 2 not supported."); +  int ql2xlogintimeout = 20;  module_param(ql2xlogintimeout, int, S_IRUGO);  MODULE_PARM_DESC(ql2xlogintimeout, @@ -354,7 +355,12 @@ fail_req_map:  static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)  { -	if (req && req->ring) +	if (IS_QLAFX00(ha)) { +		if (req && req->ring_fx00) +			dma_free_coherent(&ha->pdev->dev, +			    (req->length_fx00 + 1) * sizeof(request_t), +			    req->ring_fx00, req->dma_fx00); +	} else if (req && req->ring)  		dma_free_coherent(&ha->pdev->dev,  		(req->length + 1) * sizeof(request_t),  		req->ring, req->dma); @@ -368,11 +374,16 @@ static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)  static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)  { -	if (rsp && rsp->ring) +	if (IS_QLAFX00(ha)) { +		if (rsp && rsp->ring) +			dma_free_coherent(&ha->pdev->dev, +			    (rsp->length_fx00 + 1) * sizeof(request_t), +			    rsp->ring_fx00, rsp->dma_fx00); +	} else if (rsp && rsp->ring) {  		dma_free_coherent(&ha->pdev->dev,  		(rsp->length + 1) * sizeof(response_t),  		rsp->ring, rsp->dma); - +	}  	kfree(rsp);  	rsp = NULL;  } @@ -633,7 +644,7 @@ qla2x00_sp_free_dma(void *vha, void *ptr)  	qla2x00_rel_sp(sp->fcport->vha, sp);  } -static void +void  qla2x00_sp_compl(void *data, void *ptr, int res)  {  	struct qla_hw_data *ha = (struct qla_hw_data *)data; @@ -657,6 +668,9 @@ qla2x00_sp_compl(void *data, void *ptr, int res)  	cmd->scsi_done(cmd);  } +/* If we are SP1 here, we need to still take and release the host_lock as SP1 + * does not have the changes necessary to avoid taking host->host_lock. + */  static int  qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)  { @@ -1304,6 +1318,9 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)  		}  	} +	if (IS_QLAFX00(ha)) +		return QLA_SUCCESS; +  	if (ha->flags.enable_lip_full_login && !IS_CNA_CAPABLE(ha)) {  		atomic_set(&vha->loop_state, LOOP_DOWN);  		atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); @@ -1858,6 +1875,7 @@ static struct isp_operations qla2100_isp_ops = {  	.start_scsi		= qla2x00_start_scsi,  	.abort_isp		= qla2x00_abort_isp,  	.iospace_config     	= qla2x00_iospace_config, +	.initialize_adapter	= qla2x00_initialize_adapter,  };  static struct isp_operations qla2300_isp_ops = { @@ -1895,6 +1913,7 @@ static struct isp_operations qla2300_isp_ops = {  	.start_scsi		= qla2x00_start_scsi,  	.abort_isp		= qla2x00_abort_isp,  	.iospace_config     	= qla2x00_iospace_config, +	.initialize_adapter	= qla2x00_initialize_adapter,  };  static struct isp_operations qla24xx_isp_ops = { @@ -1932,6 +1951,7 @@ static struct isp_operations qla24xx_isp_ops = {  	.start_scsi		= qla24xx_start_scsi,  	.abort_isp		= qla2x00_abort_isp,  	.iospace_config     	= qla2x00_iospace_config, +	.initialize_adapter	= qla2x00_initialize_adapter,  };  static struct isp_operations qla25xx_isp_ops = { @@ -1969,6 +1989,7 @@ static struct isp_operations qla25xx_isp_ops = {  	.start_scsi		= qla24xx_dif_start_scsi,  	.abort_isp		= qla2x00_abort_isp,  	.iospace_config     	= qla2x00_iospace_config, +	.initialize_adapter	= qla2x00_initialize_adapter,  };  static struct isp_operations qla81xx_isp_ops = { @@ -2006,6 +2027,7 @@ static struct isp_operations qla81xx_isp_ops = {  	.start_scsi		= qla24xx_dif_start_scsi,  	.abort_isp		= qla2x00_abort_isp,  	.iospace_config     	= qla2x00_iospace_config, +	.initialize_adapter	= qla2x00_initialize_adapter,  };  static struct isp_operations qla82xx_isp_ops = { @@ -2043,6 +2065,7 @@ static struct isp_operations qla82xx_isp_ops = {  	.start_scsi             = qla82xx_start_scsi,  	.abort_isp		= qla82xx_abort_isp,  	.iospace_config     	= qla82xx_iospace_config, +	.initialize_adapter	= qla2x00_initialize_adapter,  };  static struct isp_operations qla83xx_isp_ops = { @@ -2080,6 +2103,45 @@ static struct isp_operations qla83xx_isp_ops = {  	.start_scsi		= qla24xx_dif_start_scsi,  	.abort_isp		= qla2x00_abort_isp,  	.iospace_config		= qla83xx_iospace_config, +	.initialize_adapter	= qla2x00_initialize_adapter, +}; + +static struct isp_operations qlafx00_isp_ops = { +	.pci_config		= qlafx00_pci_config, +	.reset_chip		= qlafx00_soft_reset, +	.chip_diag		= qlafx00_chip_diag, +	.config_rings		= qlafx00_config_rings, +	.reset_adapter		= qlafx00_soft_reset, +	.nvram_config		= NULL, +	.update_fw_options	= NULL, +	.load_risc		= NULL, +	.pci_info_str		= qlafx00_pci_info_str, +	.fw_version_str		= qlafx00_fw_version_str, +	.intr_handler		= qlafx00_intr_handler, +	.enable_intrs		= qlafx00_enable_intrs, +	.disable_intrs		= qlafx00_disable_intrs, +	.abort_command		= qlafx00_abort_command, +	.target_reset		= qlafx00_abort_target, +	.lun_reset		= qlafx00_lun_reset, +	.fabric_login		= NULL, +	.fabric_logout		= NULL, +	.calc_req_entries	= NULL, +	.build_iocbs		= NULL, +	.prep_ms_iocb		= qla24xx_prep_ms_iocb, +	.prep_ms_fdmi_iocb	= qla24xx_prep_ms_fdmi_iocb, +	.read_nvram		= qla24xx_read_nvram_data, +	.write_nvram		= qla24xx_write_nvram_data, +	.fw_dump		= NULL, +	.beacon_on		= qla24xx_beacon_on, +	.beacon_off		= qla24xx_beacon_off, +	.beacon_blink		= NULL, +	.read_optrom		= qla24xx_read_optrom_data, +	.write_optrom		= qla24xx_write_optrom_data, +	.get_flash_version	= qla24xx_get_flash_version, +	.start_scsi		= qlafx00_start_scsi, +	.abort_isp		= qlafx00_abort_isp, +	.iospace_config		= qlafx00_iospace_config, +	.initialize_adapter	= qlafx00_initialize_adapter,  };  static inline void @@ -2192,6 +2254,9 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)  		ha->device_type |= DT_T10_PI;  		ha->fw_srisc_address = RISC_START_ADDRESS_2400;  		break; +	case PCI_DEVICE_ID_QLOGIC_ISPF001: +		ha->device_type |= DT_ISPFX00; +		break;  	}  	if (IS_QLA82XX(ha)) @@ -2265,7 +2330,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)  	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001 ||  	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021 ||  	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2031 || -	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8031) { +	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8031 || +	    pdev->device == PCI_DEVICE_ID_QLOGIC_ISPF001) {  		bars = pci_select_bars(pdev, IORESOURCE_MEM);  		mem_only = 1;  		ql_dbg_pci(ql_dbg_init, pdev, 0x0007, @@ -2436,6 +2502,18 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)  		ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX;  		ha->nvram_conf_off = ~0;  		ha->nvram_data_off = ~0; +	}  else if (IS_QLAFX00(ha)) { +		ha->max_fibre_devices = MAX_FIBRE_DEVICES_FX00; +		ha->mbx_count = MAILBOX_REGISTER_COUNT_FX00; +		ha->aen_mbx_count = AEN_MAILBOX_REGISTER_COUNT_FX00; +		req_length = REQUEST_ENTRY_CNT_FX00; +		rsp_length = RESPONSE_ENTRY_CNT_FX00; +		ha->init_cb_size = sizeof(struct init_cb_fx); +		ha->isp_ops = &qlafx00_isp_ops; +		ha->port_down_retry_count = 30; /* default value */ +		ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL; +		ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL; +		ha->mr.fw_hbt_en = 1;  	}  	ql_dbg_pci(ql_dbg_init, pdev, 0x001e, @@ -2500,13 +2578,24 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)  	host = base_vha->host;  	base_vha->req = req; -	host->can_queue = req->length + 128; +	if (IS_QLAFX00(ha)) +		host->can_queue = 1024; +	else +		host->can_queue = req->length + 128;  	if (IS_QLA2XXX_MIDTYPE(ha))  		base_vha->mgmt_svr_loop_id = 10 + base_vha->vp_idx;  	else  		base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER +  						base_vha->vp_idx; +	/* Setup fcport template structure. */ +	ha->mr.fcport.vha = base_vha; +	ha->mr.fcport.port_type = FCT_UNKNOWN; +	ha->mr.fcport.loop_id = FC_NO_LOOP_ID; +	qla2x00_set_fcport_state(&ha->mr.fcport, FCS_UNCONFIGURED); +	ha->mr.fcport.supported_classes = FC_COS_UNSPECIFIED; +	ha->mr.fcport.scan_state = 1; +  	/* Set the SG table size based on ISP type */  	if (!IS_FWI2_CAPABLE(ha)) {  		if (IS_QLA2100(ha)) @@ -2562,6 +2651,13 @@ que_init:  	rsp->req = req;  	req->rsp = rsp; +	if (IS_QLAFX00(ha)) { +		ha->rsp_q_map[0] = rsp; +		ha->req_q_map[0] = req; +		set_bit(0, ha->req_qid_map); +		set_bit(0, ha->rsp_qid_map); +	} +  	/* FWI2-capable only. */  	req->req_q_in = &ha->iobase->isp24.req_q_in;  	req->req_q_out = &ha->iobase->isp24.req_q_out; @@ -2574,6 +2670,13 @@ que_init:  		rsp->rsp_q_out =  &ha->mqiobase->isp25mq.rsp_q_out;  	} +	if (IS_QLAFX00(ha)) { +		req->req_q_in = &ha->iobase->ispfx00.req_q_in; +		req->req_q_out = &ha->iobase->ispfx00.req_q_out; +		rsp->rsp_q_in = &ha->iobase->ispfx00.rsp_q_in; +		rsp->rsp_q_out = &ha->iobase->ispfx00.rsp_q_out; +	} +  	if (IS_QLA82XX(ha)) {  		req->req_q_out = &ha->iobase->isp82.req_q_out[0];  		rsp->rsp_q_in = &ha->iobase->isp82.rsp_q_in[0]; @@ -2595,7 +2698,7 @@ que_init:  	    "req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n",  	    req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out); -	if (qla2x00_initialize_adapter(base_vha)) { +	if (ha->isp_ops->initialize_adapter(base_vha)) {  		ql_log(ql_log_fatal, base_vha, 0x00d6,  		    "Failed to initialize adapter - Adapter flags %x.\n",  		    base_vha->device_flags); @@ -2720,6 +2823,18 @@ skip_dpc:  	qla2x00_alloc_sysfs_attr(base_vha); +	if (IS_QLAFX00(ha)) { +		ret = qlafx00_fx_disc(base_vha, +			&base_vha->hw->mr.fcport, FXDISC_GET_CONFIG_INFO); + +		ret = qlafx00_fx_disc(base_vha, +			&base_vha->hw->mr.fcport, FXDISC_GET_PORT_INFO); + +		/* Register system information */ +		ret =  qlafx00_fx_disc(base_vha, +			&base_vha->hw->mr.fcport, FXDISC_REG_HOST_INFO); +	} +  	qla2x00_init_host_attr(base_vha);  	qla2x00_dfs_setup(base_vha); @@ -2777,6 +2892,8 @@ iospace_config_failed:  	} else {  		if (ha->iobase)  			iounmap(ha->iobase); +		if (ha->cregbase) +			iounmap(ha->cregbase);  	}  	pci_release_selected_regions(ha->pdev, ha->bars);  	kfree(ha); @@ -2960,6 +3077,9 @@ qla2x00_remove_one(struct pci_dev *pdev)  		if (ha->iobase)  			iounmap(ha->iobase); +		if (ha->cregbase) +			iounmap(ha->cregbase); +  		if (ha->mqiobase)  			iounmap(ha->mqiobase); @@ -3068,6 +3188,12 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,  void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,      int do_login, int defer)  { +	if (IS_QLAFX00(vha->hw)) { +		qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); +		qla2x00_schedule_rport_del(vha, fcport, defer); +		return; +	} +  	if (atomic_read(&fcport->state) == FCS_ONLINE &&  	    vha->vp_idx == fcport->vha->vp_idx) {  		qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); @@ -3710,6 +3836,22 @@ qla2x00_uevent_emit(struct scsi_qla_host *vha, u32 code)  	kobject_uevent_env(&vha->hw->pdev->dev.kobj, KOBJ_CHANGE, envp);  } +int +qlafx00_post_aenfx_work(struct scsi_qla_host *vha,  uint32_t evtcode, +			uint32_t *data, int cnt) +{ +	struct qla_work_evt *e; + +	e = qla2x00_alloc_work(vha, QLA_EVT_AENFX); +	if (!e) +		return QLA_FUNCTION_FAILED; + +	e->u.aenfx.evtcode = evtcode; +	e->u.aenfx.count = cnt; +	memcpy(e->u.aenfx.mbx, data, sizeof(*data) * cnt); +	return qla2x00_post_work(vha, e); +} +  void  qla2x00_do_work(struct scsi_qla_host *vha)  { @@ -3758,6 +3900,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)  		case QLA_EVT_UEVENT:  			qla2x00_uevent_emit(vha, e->u.uevent.code);  			break; +		case QLA_EVT_AENFX: +			qlafx00_process_aen(vha, e); +			break;  		}  		if (e->flags & QLA_EVT_FLAG_FREE)  			kfree(e); @@ -4592,6 +4737,38 @@ qla2x00_do_dpc(void *data)  				ql_dbg(ql_dbg_dpc, base_vha, 0x4006,  				    "FCoE context reset end.\n");  			} +		} else if (IS_QLAFX00(ha)) { +			if (test_and_clear_bit(ISP_UNRECOVERABLE, +				&base_vha->dpc_flags)) { +				ql_dbg(ql_dbg_dpc, base_vha, 0x4020, +				    "Firmware Reset Recovery\n"); +				if (qlafx00_reset_initialize(base_vha)) { +					/* Failed. Abort isp later. */ +					if (!test_bit(UNLOADING, +					    &base_vha->dpc_flags)) +						set_bit(ISP_UNRECOVERABLE, +						    &base_vha->dpc_flags); +						ql_dbg(ql_dbg_dpc, base_vha, +						    0x4021, +						    "Reset Recovery Failed\n"); +				} +			} + +			if (test_and_clear_bit(FX00_TARGET_SCAN, +				&base_vha->dpc_flags)) { +				ql_dbg(ql_dbg_dpc, base_vha, 0x4022, +				    "ISPFx00 Target Scan scheduled\n"); +				if (qlafx00_rescan_isp(base_vha)) { +					if (!test_bit(UNLOADING, +					    &base_vha->dpc_flags)) +						set_bit(ISP_UNRECOVERABLE, +						    &base_vha->dpc_flags); +					ql_dbg(ql_dbg_dpc, base_vha, 0x401e, +					    "ISPFx00 Target Scan Failed\n"); +				} +				ql_dbg(ql_dbg_dpc, base_vha, 0x401f, +				    "ISPFx00 Target Scan End\n"); +			}  		}  		if (test_and_clear_bit(ISP_ABORT_NEEDED, @@ -4630,6 +4807,9 @@ qla2x00_do_dpc(void *data)  			clear_bit(SCR_PENDING, &base_vha->dpc_flags);  		} +		if (IS_QLAFX00(ha)) +			goto loop_resync_check; +  		if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {  			ql_dbg(ql_dbg_dpc, base_vha, 0x4009,  			    "Quiescence mode scheduled.\n"); @@ -4654,7 +4834,7 @@ qla2x00_do_dpc(void *data)  		}  		if (test_and_clear_bit(RESET_MARKER_NEEDED, -							&base_vha->dpc_flags) && +				&base_vha->dpc_flags) &&  		    (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {  			ql_dbg(ql_dbg_dpc, base_vha, 0x400b, @@ -4677,9 +4857,9 @@ qla2x00_do_dpc(void *data)  			ql_dbg(ql_dbg_dpc, base_vha, 0x400e,  			    "Relogin end.\n");  		} - +loop_resync_check:  		if (test_and_clear_bit(LOOP_RESYNC_NEEDED, -							&base_vha->dpc_flags)) { +		    &base_vha->dpc_flags)) {  			ql_dbg(ql_dbg_dpc, base_vha, 0x400f,  			    "Loop resync scheduled.\n"); @@ -4697,6 +4877,9 @@ qla2x00_do_dpc(void *data)  			    "Loop resync end.\n");  		} +		if (IS_QLAFX00(ha)) +			goto intr_on_check; +  		if (test_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags) &&  		    atomic_read(&base_vha->loop_state) == LOOP_READY) {  			clear_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags); @@ -4714,7 +4897,7 @@ qla2x00_do_dpc(void *data)  		if (test_and_clear_bit(HOST_RAMP_UP_QUEUE_DEPTH,  		    &base_vha->dpc_flags))  			qla2x00_host_ramp_up_queuedepth(base_vha); - +intr_on_check:  		if (!ha->interrupts_on)  			ha->isp_ops->enable_intrs(ha); @@ -4722,7 +4905,8 @@ qla2x00_do_dpc(void *data)  					&base_vha->dpc_flags))  			ha->isp_ops->beacon_blink(base_vha); -		qla2x00_do_dpc_all_vps(base_vha); +		if (!IS_QLAFX00(ha)) +			qla2x00_do_dpc_all_vps(base_vha);  		ha->dpc_active = 0;  end_loop: @@ -4818,6 +5002,9 @@ qla2x00_timer(scsi_qla_host_t *vha)  		qla82xx_watchdog(vha);  	} +	if (!vha->vp_idx && IS_QLAFX00(ha)) +		qlafx00_timer_routine(vha); +  	/* Loop down handler. */  	if (atomic_read(&vha->loop_down_timer) > 0 &&  	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) && @@ -5335,6 +5522,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) },  	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8021) },  	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8031) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISPF001) },  	{ 0 },  };  MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);  |