diff options
Diffstat (limited to 'drivers/scsi/qedf/qedf_main.c')
-rw-r--r-- | drivers/scsi/qedf/qedf_main.c | 151 |
1 files changed, 123 insertions, 28 deletions
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 5ca424df355c..46d185cb9ea8 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -41,7 +41,7 @@ MODULE_PARM_DESC(dev_loss_tmo, " dev_loss_tmo setting for attached " "remote ports (default 60)"); uint qedf_debug = QEDF_LOG_INFO; -module_param_named(debug, qedf_debug, uint, S_IRUGO); +module_param_named(debug, qedf_debug, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(debug, " Debug mask. Pass '1' to enable default debugging" " mask"); @@ -105,6 +105,12 @@ module_param_named(dp_level, qedf_dp_level, uint, S_IRUGO); MODULE_PARM_DESC(dp_level, " printk verbosity control passed to qed module " "during probe (0-3: 0 more verbose)."); +static bool qedf_enable_recovery = true; +module_param_named(enable_recovery, qedf_enable_recovery, + bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(enable_recovery, "Enable/disable recovery on driver/firmware " + "interface level errors 0 = Disabled, 1 = Enabled (Default: 1)."); + struct workqueue_struct *qedf_io_wq; static struct fcoe_percpu_s qedf_global; @@ -690,6 +696,7 @@ static struct qed_fcoe_cb_ops qedf_cb_ops = { .dcbx_aen = qedf_dcbx_handler, .get_generic_tlv_data = qedf_get_generic_tlv_data, .get_protocol_tlv_data = qedf_get_protocol_tlv_data, + .schedule_hw_err_handler = qedf_schedule_hw_err_handler, } }; @@ -726,7 +733,7 @@ static int qedf_eh_abort(struct scsi_cmnd *sc_cmd) rdata = fcport->rdata; if (!rdata || !kref_get_unless_zero(&rdata->kref)) { QEDF_ERR(&qedf->dbg_ctx, "stale rport, sc_cmd=%p\n", sc_cmd); - rc = 1; + rc = SUCCESS; goto out; } @@ -1333,7 +1340,7 @@ static int qedf_offload_connection(struct qedf_ctx *qedf, ether_addr_copy(conn_info.dst_mac, qedf->ctlr.dest_addr); conn_info.tx_max_fc_pay_len = fcport->rdata->maxframe_size; - conn_info.e_d_tov_timer_val = qedf->lport->e_d_tov / 20; + conn_info.e_d_tov_timer_val = qedf->lport->e_d_tov; conn_info.rec_tov_timer_val = 3; /* I think this is what E3 was */ conn_info.rx_max_fc_pay_len = fcport->rdata->maxframe_size; @@ -1558,6 +1565,17 @@ static void qedf_rport_event_handler(struct fc_lport *lport, if (port_id == FC_FID_DIR_SERV) break; + if (rdata->spp_type != FC_TYPE_FCP) { + QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, + "No action since spp type isn't FCP\n"); + break; + } + if (!(rdata->ids.roles & FC_RPORT_ROLE_FCP_TARGET)) { + QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, + "Not FCP target so no action\n"); + break; + } + if (!rport) { QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "port_id=%x - rport notcreated Yet!!\n", port_id); @@ -1634,11 +1652,13 @@ static void qedf_fcoe_ctlr_setup(struct qedf_ctx *qedf) static void qedf_setup_fdmi(struct qedf_ctx *qedf) { struct fc_lport *lport = qedf->lport; - struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host); - u64 dsn; + u8 buf[8]; + int pos; + uint32_t i; /* - * fdmi_enabled needs to be set for libfc to execute FDMI registration. + * fdmi_enabled needs to be set for libfc + * to execute FDMI registration */ lport->fdmi_enabled = 1; @@ -1648,32 +1668,53 @@ static void qedf_setup_fdmi(struct qedf_ctx *qedf) */ /* Get the PCI-e Device Serial Number Capability */ - dsn = pci_get_dsn(qedf->pdev); - if (dsn) - snprintf(fc_host->serial_number, - sizeof(fc_host->serial_number), "%016llX", dsn); - else - snprintf(fc_host->serial_number, - sizeof(fc_host->serial_number), "Unknown"); + pos = pci_find_ext_capability(qedf->pdev, PCI_EXT_CAP_ID_DSN); + if (pos) { + pos += 4; + for (i = 0; i < 8; i++) + pci_read_config_byte(qedf->pdev, pos + i, &buf[i]); + + snprintf(fc_host_serial_number(lport->host), + FC_SERIAL_NUMBER_SIZE, + "%02X%02X%02X%02X%02X%02X%02X%02X", + buf[7], buf[6], buf[5], buf[4], + buf[3], buf[2], buf[1], buf[0]); + } else + snprintf(fc_host_serial_number(lport->host), + FC_SERIAL_NUMBER_SIZE, "Unknown"); + + snprintf(fc_host_manufacturer(lport->host), + FC_SERIAL_NUMBER_SIZE, "%s", "Marvell Semiconductor Inc."); + + if (qedf->pdev->device == QL45xxx) { + snprintf(fc_host_model(lport->host), + FC_SYMBOLIC_NAME_SIZE, "%s", "QL45xxx"); + + snprintf(fc_host_model_description(lport->host), + FC_SYMBOLIC_NAME_SIZE, "%s", + "Marvell FastLinQ QL45xxx FCoE Adapter"); + } - snprintf(fc_host->manufacturer, - sizeof(fc_host->manufacturer), "%s", "Cavium Inc."); + if (qedf->pdev->device == QL41xxx) { + snprintf(fc_host_model(lport->host), + FC_SYMBOLIC_NAME_SIZE, "%s", "QL41xxx"); - snprintf(fc_host->model, sizeof(fc_host->model), "%s", "QL41000"); + snprintf(fc_host_model_description(lport->host), + FC_SYMBOLIC_NAME_SIZE, "%s", + "Marvell FastLinQ QL41xxx FCoE Adapter"); + } - snprintf(fc_host->model_description, sizeof(fc_host->model_description), - "%s", "QLogic FastLinQ QL41000 Series 10/25/40/50GGbE Controller" - "(FCoE)"); + snprintf(fc_host_hardware_version(lport->host), + FC_VERSION_STRING_SIZE, "Rev %d", qedf->pdev->revision); - snprintf(fc_host->hardware_version, sizeof(fc_host->hardware_version), - "Rev %d", qedf->pdev->revision); + snprintf(fc_host_driver_version(lport->host), + FC_VERSION_STRING_SIZE, "%s", QEDF_VERSION); - snprintf(fc_host->driver_version, sizeof(fc_host->driver_version), - "%s", QEDF_VERSION); + snprintf(fc_host_firmware_version(lport->host), + FC_VERSION_STRING_SIZE, "%d.%d.%d.%d", + FW_MAJOR_VERSION, FW_MINOR_VERSION, FW_REVISION_VERSION, + FW_ENGINEERING_VERSION); - snprintf(fc_host->firmware_version, sizeof(fc_host->firmware_version), - "%d.%d.%d.%d", FW_MAJOR_VERSION, FW_MINOR_VERSION, - FW_REVISION_VERSION, FW_ENGINEERING_VERSION); } static int qedf_lport_setup(struct qedf_ctx *qedf) @@ -1720,8 +1761,13 @@ static int qedf_lport_setup(struct qedf_ctx *qedf) fc_host_dev_loss_tmo(lport->host) = qedf_dev_loss_tmo; /* Set symbolic node name */ - snprintf(fc_host_symbolic_name(lport->host), 256, - "QLogic %s v%s", QEDF_MODULE_NAME, QEDF_VERSION); + if (qedf->pdev->device == QL45xxx) + snprintf(fc_host_symbolic_name(lport->host), 256, + "Marvell FastLinQ 45xxx FCoE v%s", QEDF_VERSION); + + if (qedf->pdev->device == QL41xxx) + snprintf(fc_host_symbolic_name(lport->host), 256, + "Marvell FastLinQ 41xxx FCoE v%s", QEDF_VERSION); qedf_setup_fdmi(qedf); @@ -3221,11 +3267,16 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) void *task_start, *task_end; struct qed_slowpath_params slowpath_params; struct qed_probe_params qed_params; + u16 retry_cnt = 10; /* * When doing error recovery we didn't reap the lport so don't try * to reallocate it. */ +retry_probe: + if (mode == QEDF_MODE_RECOVERY) + msleep(2000); + if (mode != QEDF_MODE_RECOVERY) { lport = libfc_host_alloc(&qedf_host_template, sizeof(struct qedf_ctx)); @@ -3312,6 +3363,12 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) qed_params.is_vf = is_vf; qedf->cdev = qed_ops->common->probe(pdev, &qed_params); if (!qedf->cdev) { + if ((mode == QEDF_MODE_RECOVERY) && retry_cnt) { + QEDF_ERR(&qedf->dbg_ctx, + "Retry %d initialize hardware\n", retry_cnt); + retry_cnt--; + goto retry_probe; + } QEDF_ERR(&qedf->dbg_ctx, "common probe failed.\n"); rc = -ENODEV; goto err1; @@ -3760,6 +3817,44 @@ void qedf_wq_grcdump(struct work_struct *work) qedf_capture_grc_dump(qedf); } +void qedf_schedule_hw_err_handler(void *dev, enum qed_hw_err_type err_type) +{ + struct qedf_ctx *qedf = dev; + + QEDF_ERR(&(qedf->dbg_ctx), + "Hardware error handler scheduled, event=%d.\n", + err_type); + + if (test_bit(QEDF_IN_RECOVERY, &qedf->flags)) { + QEDF_ERR(&(qedf->dbg_ctx), + "Already in recovery, not scheduling board disable work.\n"); + return; + } + + switch (err_type) { + case QED_HW_ERR_FAN_FAIL: + schedule_delayed_work(&qedf->board_disable_work, 0); + break; + case QED_HW_ERR_MFW_RESP_FAIL: + case QED_HW_ERR_HW_ATTN: + case QED_HW_ERR_DMAE_FAIL: + case QED_HW_ERR_FW_ASSERT: + /* Prevent HW attentions from being reasserted */ + qed_ops->common->attn_clr_enable(qedf->cdev, true); + break; + case QED_HW_ERR_RAMROD_FAIL: + /* Prevent HW attentions from being reasserted */ + qed_ops->common->attn_clr_enable(qedf->cdev, true); + + if (qedf_enable_recovery) + qed_ops->common->recovery_process(qedf->cdev); + + break; + default: + break; + } +} + /* * Protocol TLV handler */ |