diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 156 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.c | 48 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_bsg.h | 7 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 8 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_edif.c | 328 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_edif.h | 13 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_edif_bsg.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 12 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gs.c | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 123 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 41 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mr.c | 23 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_nvme.c | 20 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 140 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/tcm_qla2xxx.c | 73 |
19 files changed, 568 insertions, 443 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index d09776b77af2..032efb294ee5 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1868,6 +1868,18 @@ qla2x00_port_speed_store(struct device *dev, struct device_attribute *attr, return strlen(buf); } +static const struct { + u16 rate; + char *str; +} port_speed_str[] = { + { PORT_SPEED_4GB, "4" }, + { PORT_SPEED_8GB, "8" }, + { PORT_SPEED_16GB, "16" }, + { PORT_SPEED_32GB, "32" }, + { PORT_SPEED_64GB, "64" }, + { PORT_SPEED_10GB, "10" }, +}; + static ssize_t qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1875,7 +1887,8 @@ qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr, struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev)); struct qla_hw_data *ha = vha->hw; ssize_t rval; - char *spd[7] = {"0", "0", "0", "4", "8", "16", "32"}; + u16 i; + char *speed = "Unknown"; rval = qla2x00_get_data_rate(vha); if (rval != QLA_SUCCESS) { @@ -1884,7 +1897,14 @@ qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr, return -EINVAL; } - return scnprintf(buf, PAGE_SIZE, "%s\n", spd[ha->link_data_rate]); + for (i = 0; i < ARRAY_SIZE(port_speed_str); i++) { + if (port_speed_str[i].rate != ha->link_data_rate) + continue; + speed = port_speed_str[i].str; + break; + } + + return scnprintf(buf, PAGE_SIZE, "%s\n", speed); } static ssize_t @@ -2461,72 +2481,77 @@ static DEVICE_ATTR(port_no, 0444, qla2x00_port_no_show, NULL); static DEVICE_ATTR(fw_attr, 0444, qla2x00_fw_attr_show, NULL); static DEVICE_ATTR_RO(edif_doorbell); - -struct device_attribute *qla2x00_host_attrs[] = { - &dev_attr_driver_version, - &dev_attr_fw_version, - &dev_attr_serial_num, - &dev_attr_isp_name, - &dev_attr_isp_id, - &dev_attr_model_name, - &dev_attr_model_desc, - &dev_attr_pci_info, - &dev_attr_link_state, - &dev_attr_zio, - &dev_attr_zio_timer, - &dev_attr_beacon, - &dev_attr_beacon_config, - &dev_attr_optrom_bios_version, - &dev_attr_optrom_efi_version, - &dev_attr_optrom_fcode_version, - &dev_attr_optrom_fw_version, - &dev_attr_84xx_fw_version, - &dev_attr_total_isp_aborts, - &dev_attr_serdes_version, - &dev_attr_mpi_version, - &dev_attr_phy_version, - &dev_attr_flash_block_size, - &dev_attr_vlan_id, - &dev_attr_vn_port_mac_address, - &dev_attr_fabric_param, - &dev_attr_fw_state, - &dev_attr_optrom_gold_fw_version, - &dev_attr_thermal_temp, - &dev_attr_diag_requests, - &dev_attr_diag_megabytes, - &dev_attr_fw_dump_size, - &dev_attr_allow_cna_fw_dump, - &dev_attr_pep_version, - &dev_attr_min_supported_speed, - &dev_attr_max_supported_speed, - &dev_attr_zio_threshold, - &dev_attr_dif_bundle_statistics, - &dev_attr_port_speed, - &dev_attr_port_no, - &dev_attr_fw_attr, - &dev_attr_dport_diagnostics, - &dev_attr_edif_doorbell, - &dev_attr_mpi_pause, - NULL, /* reserve for qlini_mode */ - NULL, /* reserve for ql2xiniexchg */ - NULL, /* reserve for ql2xexchoffld */ +static struct attribute *qla2x00_host_attrs[] = { + &dev_attr_driver_version.attr, + &dev_attr_fw_version.attr, + &dev_attr_serial_num.attr, + &dev_attr_isp_name.attr, + &dev_attr_isp_id.attr, + &dev_attr_model_name.attr, + &dev_attr_model_desc.attr, + &dev_attr_pci_info.attr, + &dev_attr_link_state.attr, + &dev_attr_zio.attr, + &dev_attr_zio_timer.attr, + &dev_attr_beacon.attr, + &dev_attr_beacon_config.attr, + &dev_attr_optrom_bios_version.attr, + &dev_attr_optrom_efi_version.attr, + &dev_attr_optrom_fcode_version.attr, + &dev_attr_optrom_fw_version.attr, + &dev_attr_84xx_fw_version.attr, + &dev_attr_total_isp_aborts.attr, + &dev_attr_serdes_version.attr, + &dev_attr_mpi_version.attr, + &dev_attr_phy_version.attr, + &dev_attr_flash_block_size.attr, + &dev_attr_vlan_id.attr, + &dev_attr_vn_port_mac_address.attr, + &dev_attr_fabric_param.attr, + &dev_attr_fw_state.attr, + &dev_attr_optrom_gold_fw_version.attr, + &dev_attr_thermal_temp.attr, + &dev_attr_diag_requests.attr, + &dev_attr_diag_megabytes.attr, + &dev_attr_fw_dump_size.attr, + &dev_attr_allow_cna_fw_dump.attr, + &dev_attr_pep_version.attr, + &dev_attr_min_supported_speed.attr, + &dev_attr_max_supported_speed.attr, + &dev_attr_zio_threshold.attr, + &dev_attr_dif_bundle_statistics.attr, + &dev_attr_port_speed.attr, + &dev_attr_port_no.attr, + &dev_attr_fw_attr.attr, + &dev_attr_dport_diagnostics.attr, + &dev_attr_edif_doorbell.attr, + &dev_attr_mpi_pause.attr, + &dev_attr_qlini_mode.attr, + &dev_attr_ql2xiniexchg.attr, + &dev_attr_ql2xexchoffld.attr, NULL, }; -void qla_insert_tgt_attrs(void) +static umode_t qla_host_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int i) { - struct device_attribute **attr; + if (ql2x_ini_mode != QLA2XXX_INI_MODE_DUAL && + (attr == &dev_attr_qlini_mode.attr || + attr == &dev_attr_ql2xiniexchg.attr || + attr == &dev_attr_ql2xexchoffld.attr)) + return 0; + return attr->mode; +} - /* advance to empty slot */ - for (attr = &qla2x00_host_attrs[0]; *attr; ++attr) - continue; +static const struct attribute_group qla2x00_host_attr_group = { + .is_visible = qla_host_attr_is_visible, + .attrs = qla2x00_host_attrs +}; - *attr = &dev_attr_qlini_mode; - attr++; - *attr = &dev_attr_ql2xiniexchg; - attr++; - *attr = &dev_attr_ql2xexchoffld; -} +const struct attribute_group *qla2x00_host_groups[] = { + &qla2x00_host_attr_group, + NULL +}; /* Host attributes. */ @@ -2737,7 +2762,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) if (fcport->loop_id != FC_NO_LOOP_ID) fcport->logout_on_delete = 1; - qlt_schedule_sess_for_deletion(fcport); + if (!EDIF_NEGOTIATION_PENDING(fcport)) { + ql_dbg(ql_dbg_disc, fcport->vha, 0x911e, + "%s %d schedule session deletion\n", __func__, + __LINE__); + qlt_schedule_sess_for_deletion(fcport); + } } else { qla2x00_port_logout(fcport->vha, fcport); } diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 655cf5de604b..9da8034ccad4 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -2877,6 +2877,9 @@ qla2x00_process_vendor_specific(struct scsi_qla_host *vha, struct bsg_job *bsg_j case QL_VND_MANAGE_HOST_PORT: return qla2x00_manage_host_port(bsg_job); + case QL_VND_MBX_PASSTHRU: + return qla2x00_mailbox_passthru(bsg_job); + default: return -ENOSYS; } @@ -3013,3 +3016,48 @@ done: sp->free(sp); return 0; } + +int qla2x00_mailbox_passthru(struct bsg_job *bsg_job) +{ + struct fc_bsg_reply *bsg_reply = bsg_job->reply; + scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job)); + int ret = -EINVAL; + int ptsize = sizeof(struct qla_mbx_passthru); + struct qla_mbx_passthru *req_data = NULL; + uint32_t req_data_len; + + req_data_len = bsg_job->request_payload.payload_len; + if (req_data_len != ptsize) { + ql_log(ql_log_warn, vha, 0xf0a3, "req_data_len invalid.\n"); + return -EIO; + } + req_data = kzalloc(ptsize, GFP_KERNEL); + if (!req_data) { + ql_log(ql_log_warn, vha, 0xf0a4, + "req_data memory allocation failure.\n"); + return -ENOMEM; + } + + /* Copy the request buffer in req_data */ + sg_copy_to_buffer(bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, req_data, ptsize); + ret = qla_mailbox_passthru(vha, req_data->mbx_in, req_data->mbx_out); + + /* Copy the req_data in request buffer */ + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, req_data, ptsize); + + bsg_reply->reply_payload_rcv_len = ptsize; + if (ret == QLA_SUCCESS) + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; + else + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_ERR; + + bsg_job->reply_len = sizeof(*bsg_job->reply); + bsg_reply->result = DID_OK << 16; + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); + + kfree(req_data); + + return ret; +} diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h index dd793cf8bc1e..0f8a4c7e52a2 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.h +++ b/drivers/scsi/qla2xxx/qla_bsg.h @@ -36,6 +36,7 @@ #define QL_VND_GET_HOST_STATS 0x24 #define QL_VND_GET_TGT_STATS 0x25 #define QL_VND_MANAGE_HOST_PORT 0x26 +#define QL_VND_MBX_PASSTHRU 0x2B /* BSG Vendor specific subcode returns */ #define EXT_STATUS_OK 0 @@ -187,6 +188,12 @@ struct qla_port_param { uint16_t speed; } __attribute__ ((packed)); +struct qla_mbx_passthru { + uint16_t reserved1[2]; + uint16_t mbx_in[32]; + uint16_t mbx_out[32]; + uint32_t reserved2[16]; +} __packed; /* FRU VPD */ diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index be2eb75ee1a3..9ebf4a234d9a 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -639,9 +639,9 @@ struct qla_els_pt_arg { u8 els_opcode; u8 vp_idx; __le16 nport_handle; - u16 control_flags; + u16 control_flags, ox_id; __le32 rx_xchg_address; - port_id_t did; + port_id_t did, sid; u32 tx_len, tx_byte_count, rx_len, rx_byte_count; dma_addr_t tx_addr, rx_addr; @@ -3750,6 +3750,7 @@ struct qla_qpair { struct qla_fw_resources fwres ____cacheline_aligned; u32 cmd_cnt; u32 cmd_completion_cnt; + u32 prev_completion_cnt; }; /* Place holder for FW buffer parameters */ @@ -4607,6 +4608,7 @@ struct qla_hw_data { struct qla_chip_state_84xx *cs84xx; struct isp_operations *isp_ops; struct workqueue_struct *wq; + struct work_struct heartbeat_work; struct qlfc_fw fw_buf; /* FCP_CMND priority support */ @@ -4708,7 +4710,6 @@ struct qla_hw_data { struct qla_hw_data_stat stat; pci_error_state_t pci_error_state; - u64 prev_cmd_cnt; struct dma_pool *purex_dma_pool; struct btree_head32 host_map; @@ -4854,7 +4855,6 @@ typedef struct scsi_qla_host { #define SET_ZIO_THRESHOLD_NEEDED 32 #define ISP_ABORT_TO_ROM 33 #define VPORT_DELETE 34 -#define HEARTBEAT_CHK 38 #define PROCESS_PUREX_IOCB 63 diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c index ad746c62f0d4..2e37b189cb75 100644 --- a/drivers/scsi/qla2xxx/qla_edif.c +++ b/drivers/scsi/qla2xxx/qla_edif.c @@ -218,7 +218,7 @@ fc_port_t *fcport) "%s edif not enabled\n", __func__); goto done; } - if (vha->e_dbell.db_flags != EDB_ACTIVE) { + if (DBELL_INACTIVE(vha)) { ql_dbg(ql_dbg_edif, vha, 0x09102, "%s doorbell not enabled\n", __func__); goto done; @@ -290,63 +290,6 @@ qla_edif_app_check(scsi_qla_host_t *vha, struct app_id appid) return false; } -static void qla_edif_reset_auth_wait(struct fc_port *fcport, int state, - int waitonly) -{ - int cnt, max_cnt = 200; - bool traced = false; - - fcport->keep_nport_handle = 1; - - if (!waitonly) { - qla2x00_set_fcport_disc_state(fcport, state); - qlt_schedule_sess_for_deletion(fcport); - } else { - qla2x00_set_fcport_disc_state(fcport, state); - } - - ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, - "%s: waiting for session, max_cnt=%u\n", - __func__, max_cnt); - - cnt = 0; - - if (waitonly) { - /* Marker wait min 10 msecs. */ - msleep(50); - cnt += 50; - } - while (1) { - if (!traced) { - ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, - "%s: session sleep.\n", - __func__); - traced = true; - } - msleep(20); - cnt++; - if (waitonly && (fcport->disc_state == state || - fcport->disc_state == DSC_LOGIN_COMPLETE)) - break; - if (fcport->disc_state == DSC_LOGIN_AUTH_PEND) - break; - if (cnt > max_cnt) - break; - } - - if (!waitonly) { - ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, - "%s: waited for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n", - __func__, fcport->port_name, fcport->loop_id, - fcport->d_id.b24, fcport, fcport->disc_state, cnt); - } else { - ql_dbg(ql_dbg_edif, fcport->vha, 0xf086, - "%s: waited ONLY for session - %8phC, loopid=%x portid=%06x fcport=%p state=%u, cnt=%u\n", - __func__, fcport->port_name, fcport->loop_id, - fcport->d_id.b24, fcport, fcport->disc_state, cnt); - } -} - static void qla_edif_free_sa_ctl(fc_port_t *fcport, struct edif_sa_ctl *sa_ctl, int index) @@ -529,7 +472,8 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) struct app_start_reply appreply; struct fc_port *fcport, *tf; - ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app start\n", __func__); + ql_log(ql_log_info, vha, 0x1313, + "EDIF application registration with driver, FC device connections will be re-established.\n"); sg_copy_to_buffer(bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, &appstart, @@ -538,9 +482,9 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app_vid=%x app_start_flags %x\n", __func__, appstart.app_info.app_vid, appstart.app_start_flags); - if (vha->e_dbell.db_flags != EDB_ACTIVE) { + if (DBELL_INACTIVE(vha)) { /* mark doorbell as active since an app is now present */ - vha->e_dbell.db_flags = EDB_ACTIVE; + vha->e_dbell.db_flags |= EDB_ACTIVE; } else { ql_dbg(ql_dbg_edif, vha, 0x911e, "%s doorbell already active\n", __func__); @@ -554,37 +498,36 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) qla2xxx_wake_dpc(vha); } else { list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) { + ql_dbg(ql_dbg_edif, vha, 0x2058, + "FCSP - nn %8phN pn %8phN portid=%06x.\n", + fcport->node_name, fcport->port_name, + fcport->d_id.b24); ql_dbg(ql_dbg_edif, vha, 0xf084, - "%s: sess %p %8phC lid %#04x s_id %06x logout %d\n", - __func__, fcport, fcport->port_name, - fcport->loop_id, fcport->d_id.b24, - fcport->logout_on_delete); - - ql_dbg(ql_dbg_edif, vha, 0xf084, - "keep %d els_logo %d disc state %d auth state %d stop state %d\n", - fcport->keep_nport_handle, - fcport->send_els_logo, fcport->disc_state, - fcport->edif.auth_state, fcport->edif.app_stop); + "%s: se_sess %p / sess %p from port %8phC " + "loop_id %#04x s_id %06x logout %d " + "keep %d els_logo %d disc state %d auth state %d" + "stop state %d\n", + __func__, fcport->se_sess, fcport, + fcport->port_name, fcport->loop_id, + fcport->d_id.b24, fcport->logout_on_delete, + fcport->keep_nport_handle, fcport->send_els_logo, + fcport->disc_state, fcport->edif.auth_state, + fcport->edif.app_stop); if (atomic_read(&vha->loop_state) == LOOP_DOWN) break; - if (!(fcport->flags & FCF_FCSP_DEVICE)) - continue; fcport->edif.app_started = 1; - if (fcport->edif.app_stop || - (fcport->disc_state != DSC_LOGIN_COMPLETE && - fcport->disc_state != DSC_LOGIN_PEND && - fcport->disc_state != DSC_DELETED)) { - /* no activity */ - fcport->edif.app_stop = 0; - - ql_dbg(ql_dbg_edif, vha, 0x911e, - "%s wwpn %8phC calling qla_edif_reset_auth_wait\n", - __func__, fcport->port_name); - fcport->edif.app_sess_online = 1; - qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0); - } + fcport->login_retry = vha->hw->login_retry_count; + + /* no activity */ + fcport->edif.app_stop = 0; + + ql_dbg(ql_dbg_edif, vha, 0x911e, + "%s wwpn %8phC calling qla_edif_reset_auth_wait\n", + __func__, fcport->port_name); + fcport->edif.app_sess_online = 0; + qlt_schedule_sess_for_deletion(fcport); qla_edif_sa_ctl_init(vha, fcport); } } @@ -601,14 +544,14 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) appreply.edif_enode_active = vha->pur_cinfo.enode_flags; appreply.edif_edb_active = vha->e_dbell.db_flags; - bsg_job->reply_len = sizeof(struct fc_bsg_reply) + - sizeof(struct app_start_reply); + bsg_job->reply_len = sizeof(struct fc_bsg_reply); SET_DID_STATUS(bsg_reply->result, DID_OK); - sg_copy_from_buffer(bsg_job->reply_payload.sg_list, - bsg_job->reply_payload.sg_cnt, &appreply, - sizeof(struct app_start_reply)); + bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, + &appreply, + sizeof(struct app_start_reply)); ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app start completed with 0x%x\n", @@ -800,15 +743,15 @@ qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job) ql_dbg(ql_dbg_edif, vha, 0x911e, "%s AUTH complete - RESUME with prli for wwpn %8phC\n", __func__, fcport->port_name); - qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 1); qla24xx_post_prli_work(vha, fcport); } errstate_exit: bsg_job->reply_len = sizeof(struct fc_bsg_reply); - sg_copy_from_buffer(bsg_job->reply_payload.sg_list, - bsg_job->reply_payload.sg_cnt, &appplogireply, - sizeof(struct app_plogi_reply)); + bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, + &appplogireply, + sizeof(struct app_plogi_reply)); return rval; } @@ -873,7 +816,7 @@ qla_edif_app_authfail(scsi_qla_host_t *vha, struct bsg_job *bsg_job) if (qla_ini_mode_enabled(fcport->vha)) { fcport->send_els_logo = 1; - qla_edif_reset_auth_wait(fcport, DSC_LOGIN_PEND, 0); + qlt_schedule_sess_for_deletion(fcport); } } @@ -891,7 +834,7 @@ static int qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) { int32_t rval = 0; - int32_t num_cnt; + int32_t pcnt = 0; struct fc_bsg_reply *bsg_reply = bsg_job->reply; struct app_pinfo_req app_req; struct app_pinfo_reply *app_reply; @@ -903,16 +846,14 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) bsg_job->request_payload.sg_cnt, &app_req, sizeof(struct app_pinfo_req)); - num_cnt = app_req.num_ports; /* num of ports alloc'd by app */ - app_reply = kzalloc((sizeof(struct app_pinfo_reply) + - sizeof(struct app_pinfo) * num_cnt), GFP_KERNEL); + sizeof(struct app_pinfo) * app_req.num_ports), GFP_KERNEL); + if (!app_reply) { SET_DID_STATUS(bsg_reply->result, DID_ERROR); rval = -1; } else { struct fc_port *fcport = NULL, *tf; - uint32_t pcnt = 0; list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) { if (!(fcport->flags & FCF_FCSP_DEVICE)) @@ -981,9 +922,11 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) SET_DID_STATUS(bsg_reply->result, DID_OK); } - sg_copy_from_buffer(bsg_job->reply_payload.sg_list, - bsg_job->reply_payload.sg_cnt, app_reply, - sizeof(struct app_pinfo_reply) + sizeof(struct app_pinfo) * num_cnt); + bsg_job->reply_len = sizeof(struct fc_bsg_reply); + bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, + app_reply, + sizeof(struct app_pinfo_reply) + sizeof(struct app_pinfo) * pcnt); kfree(app_reply); @@ -1000,10 +943,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job) { int32_t rval = 0; struct fc_bsg_reply *bsg_reply = bsg_job->reply; - uint32_t ret_size, size; + uint32_t size; struct app_sinfo_req app_req; struct app_stats_reply *app_reply; + uint32_t pcnt = 0; sg_copy_to_buffer(bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, &app_req, @@ -1019,18 +963,12 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job) size = sizeof(struct app_stats_reply) + (sizeof(struct app_sinfo) * app_req.num_ports); - if (size > bsg_job->reply_payload.payload_len) - ret_size = bsg_job->reply_payload.payload_len; - else - ret_size = size; - app_reply = kzalloc(size, GFP_KERNEL); if (!app_reply) { SET_DID_STATUS(bsg_reply->result, DID_ERROR); rval = -1; } else { struct fc_port *fcport = NULL, *tf; - uint32_t pcnt = 0; list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) { if (fcport->edif.enable) { @@ -1054,9 +992,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job) SET_DID_STATUS(bsg_reply->result, DID_OK); } + bsg_job->reply_len = sizeof(struct fc_bsg_reply); bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list, - bsg_job->reply_payload.sg_cnt, app_reply, ret_size); + bsg_job->reply_payload.sg_cnt, app_reply, + sizeof(struct app_stats_reply) + (sizeof(struct app_sinfo) * pcnt)); kfree(app_reply); @@ -1130,8 +1070,7 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job) __func__, bsg_request->rqst_data.h_vendor.vendor_cmd[1]); rval = EXT_STATUS_INVALID_PARAM; - bsg_job->reply_len = sizeof(struct fc_bsg_reply); - SET_DID_STATUS(bsg_reply->result, DID_ERROR); + done = false; break; } @@ -1330,7 +1269,7 @@ qla24xx_sadb_update(struct bsg_job *bsg_job) goto done; } - if (vha->e_dbell.db_flags != EDB_ACTIVE) { + if (DBELL_INACTIVE(vha)) { ql_log(ql_log_warn, vha, 0x70a1, "App not started\n"); rval = -EIO; SET_DID_STATUS(bsg_reply->result, DID_ERROR); @@ -1651,6 +1590,40 @@ qla_enode_stop(scsi_qla_host_t *vha) spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags); } +static void qla_enode_clear(scsi_qla_host_t *vha, port_id_t portid) +{ + unsigned long flags; + struct enode *e, *tmp; + struct purexevent *purex; + LIST_HEAD(enode_list); + + if (vha->pur_cinfo.enode_flags != ENODE_ACTIVE) { + ql_dbg(ql_dbg_edif, vha, 0x09102, + "%s enode not active\n", __func__); + return; + } + spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags); + list_for_each_entry_safe(e, tmp, &vha->pur_cinfo.head, list) { + purex = &e->u.purexinfo; + if (purex->pur_info.pur_sid.b24 == portid.b24) { + ql_dbg(ql_dbg_edif, vha, 0x911d, + "%s free ELS sid=%06x. xchg %x, nb=%xh\n", + __func__, portid.b24, + purex->pur_info.pur_rx_xchg_address, + purex->pur_info.pur_bytes_rcvd); + + list_del_init(&e->list); + list_add_tail(&e->list, &enode_list); + } + } + spin_unlock_irqrestore(&vha->pur_cinfo.pur_lock, flags); + + list_for_each_entry_safe(e, tmp, &enode_list, list) { + list_del_init(&e->list); + qla_enode_free(vha, e); + } +} + /* * allocate enode struct and populate buffer * returns: enode pointer with buffers @@ -1695,41 +1668,25 @@ static struct enode * qla_enode_find(scsi_qla_host_t *vha, uint32_t ntype, uint32_t p1, uint32_t p2) { struct enode *node_rtn = NULL; - struct enode *list_node = NULL; + struct enode *list_node, *q; unsigned long flags; - struct list_head *pos, *q; uint32_t sid; - uint32_t rw_flag; struct purexevent *purex; /* secure the list from moving under us */ spin_lock_irqsave(&vha->pur_cinfo.pur_lock, flags); - list_for_each_safe(pos, q, &vha->pur_cinfo.head) { - list_node = list_entry(pos, struct enode, list); + list_for_each_entry_safe(list_node, q, &vha->pur_cinfo.head, list) { /* node type determines what p1 and p2 are */ purex = &list_node->u.purexinfo; sid = p1; - rw_flag = p2; if (purex->pur_info.pur_sid.b24 == sid) { - if (purex->pur_info.pur_pend == 1 && - rw_flag == PUR_GET) { - /* - * if the receive is in progress - * and its a read/get then can't - * transfer yet - */ - ql_dbg(ql_dbg_edif, vha, 0x9106, - "%s purex xfer in progress for sid=%x\n", - __func__, sid); - } else { - /* found it and its complete */ - node_rtn = list_node; - list_del(pos); - break; - } + /* found it and its complete */ + node_rtn = list_node; + list_del(&list_node->list); + break; } } @@ -1802,7 +1759,8 @@ qla_els_reject_iocb(scsi_qla_host_t *vha, struct qla_qpair *qp, qla_els_pt_iocb(vha, els_iocb, a); ql_dbg(ql_dbg_edif, vha, 0x0183, - "Sending ELS reject...\n"); + "Sending ELS reject ox_id %04x s:%06x -> d:%06x\n", + a->ox_id, a->sid.b24, a->did.b24); ql_dump_buffer(ql_dbg_edif + ql_dbg_verbose, vha, 0x0185, vha->hw->elsrej.c, sizeof(*vha->hw->elsrej.c)); /* flush iocb to mem before notifying hw doorbell */ @@ -1814,7 +1772,7 @@ qla_els_reject_iocb(scsi_qla_host_t *vha, struct qla_qpair *qp, void qla_edb_init(scsi_qla_host_t *vha) { - if (vha->e_dbell.db_flags == EDB_ACTIVE) { + if (DBELL_ACTIVE(vha)) { /* list already init'd - error */ ql_dbg(ql_dbg_edif, vha, 0x09102, "edif db already initialized, cannot reinit\n"); @@ -1850,6 +1808,57 @@ qla_edb_node_free(scsi_qla_host_t *vha, struct edb_node *node) node->ntype = N_UNDEF; } +static void qla_edb_clear(scsi_qla_host_t *vha, port_id_t portid) +{ + unsigned long flags; + struct edb_node *e, *tmp; + port_id_t sid; + LIST_HEAD(edb_list); + + if (DBELL_INACTIVE(vha)) { + /* doorbell list not enabled */ + ql_dbg(ql_dbg_edif, vha, 0x09102, + "%s doorbell not enabled\n", __func__); + return; + } + + /* grab lock so list doesn't move */ + spin_lock_irqsave(&vha->e_dbell.db_lock, flags); + list_for_each_entry_safe(e, tmp, &vha->e_dbell.head, list) { + switch (e->ntype) { + case VND_CMD_AUTH_STATE_NEEDED: + case VND_CMD_AUTH_STATE_SESSION_SHUTDOWN: + sid = e->u.plogi_did; + break; + case VND_CMD_AUTH_STATE_ELS_RCVD: + sid = e->u.els_sid; + break; + case VND_CMD_AUTH_STATE_SAUPDATE_COMPL: + /* app wants to see this */ + continue; + default: + ql_log(ql_log_warn, vha, 0x09102, + "%s unknown node type: %x\n", __func__, e->ntype); + sid.b24 = 0; + break; + } + if (sid.b24 == portid.b24) { + ql_dbg(ql_dbg_edif, vha, 0x910f, + "%s free doorbell event : node type = %x %p\n", + __func__, e->ntype, e); + list_del_init(&e->list); + list_add_tail(&e->list, &edb_list); + } + } + spin_unlock_irqrestore(&vha->e_dbell.db_lock, flags); + + list_for_each_entry_safe(e, tmp, &edb_list, list) { + qla_edb_node_free(vha, e); + list_del_init(&e->list); + kfree(e); + } +} + /* function called when app is stopping */ void @@ -1858,7 +1867,7 @@ qla_edb_stop(scsi_qla_host_t *vha) unsigned long flags; struct edb_node *node, *q; - if (vha->e_dbell.db_flags != EDB_ACTIVE) { + if (DBELL_INACTIVE(vha)) { /* doorbell list not enabled */ ql_dbg(ql_dbg_edif, vha, 0x09102, "%s doorbell not enabled\n", __func__); @@ -1909,7 +1918,7 @@ qla_edb_node_add(scsi_qla_host_t *vha, struct edb_node *ptr) { unsigned long flags; - if (vha->e_dbell.db_flags != EDB_ACTIVE) { + if (DBELL_INACTIVE(vha)) { /* doorbell list not enabled */ ql_dbg(ql_dbg_edif, vha, 0x09102, "%s doorbell not enabled\n", __func__); @@ -1940,7 +1949,7 @@ qla_edb_eventcreate(scsi_qla_host_t *vha, uint32_t dbtype, return; } - if (vha->e_dbell.db_flags != EDB_ACTIVE) { + if (DBELL_INACTIVE(vha)) { if (fcport) fcport->edif.auth_state = dbtype; /* doorbell list not enabled */ @@ -2035,7 +2044,7 @@ qla_edif_timer(scsi_qla_host_t *vha) struct qla_hw_data *ha = vha->hw; if (!vha->vp_idx && N2N_TOPO(ha) && ha->flags.n2n_fw_acc_sec) { - if (vha->e_dbell.db_flags != EDB_ACTIVE && + if (DBELL_INACTIVE(vha) && ha->edif_post_stop_cnt_down) { ha->edif_post_stop_cnt_down--; @@ -2073,7 +2082,7 @@ edif_doorbell_show(struct device *dev, struct device_attribute *attr, sz = 256; /* stop new threads from waiting if we're not init'd */ - if (vha->e_dbell.db_flags != EDB_ACTIVE) { + if (DBELL_INACTIVE(vha)) { ql_dbg(ql_dbg_edif + ql_dbg_verbose, vha, 0x09122, "%s error - edif db not enabled\n", __func__); return 0; @@ -2346,6 +2355,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) a.tx_addr = vha->hw->elsrej.cdma; a.vp_idx = vha->vp_idx; a.control_flags = EPD_ELS_RJT; + a.ox_id = le16_to_cpu(p->ox_id); sid = p->s_id[0] | (p->s_id[1] << 8) | (p->s_id[2] << 16); @@ -2357,7 +2367,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) return; } - if (totlen > MAX_PAYLOAD) { + if (totlen > ELS_MAX_PAYLOAD) { ql_dbg(ql_dbg_edif, vha, 0x0910d, "%s WARNING: verbose ELS frame received (totlen=%x)\n", __func__, totlen); @@ -2387,7 +2397,6 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) purex = &ptr->u.purexinfo; purex->pur_info.pur_sid = a.did; - purex->pur_info.pur_pend = 0; purex->pur_info.pur_bytes_rcvd = totlen; purex->pur_info.pur_rx_xchg_address = le32_to_cpu(p->rx_xchg_addr); purex->pur_info.pur_nphdl = le16_to_cpu(p->nport_handle); @@ -2396,6 +2405,8 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) purex->pur_info.pur_did.b.al_pa = p->d_id[0]; purex->pur_info.vp_idx = p->vp_idx; + a.sid = purex->pur_info.pur_did; + rc = __qla_copy_purex_to_buffer(vha, pkt, rsp, purex->msgp, purex->msgp_len); if (rc) { @@ -2419,7 +2430,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) fcport = qla2x00_find_fcport_by_pid(host, &purex->pur_info.pur_sid); - if (host->e_dbell.db_flags != EDB_ACTIVE || + if (DBELL_INACTIVE(vha) || (fcport && EDIF_SESSION_DOWN(fcport))) { ql_dbg(ql_dbg_edif, host, 0x0910c, "%s e_dbell.db_flags =%x %06x\n", __func__, host->e_dbell.db_flags, @@ -2436,7 +2447,7 @@ void qla24xx_auth_els(scsi_qla_host_t *vha, void **pkt, struct rsp_que **rsp) ql_dbg(ql_dbg_edif, host, 0x0910c, "%s COMPLETE purex->pur_info.pur_bytes_rcvd =%xh s:%06x -> d:%06x xchg=%xh\n", __func__, purex->pur_info.pur_bytes_rcvd, purex->pur_info.pur_sid.b24, - purex->pur_info.pur_did.b24, p->rx_xchg_addr); + purex->pur_info.pur_did.b24, purex->pur_info.pur_rx_xchg_address); qla_edb_eventcreate(host, VND_CMD_AUTH_STATE_ELS_RCVD, sid, 0, NULL); } @@ -3139,18 +3150,14 @@ static uint16_t qla_edif_sadb_get_sa_index(fc_port_t *fcport, /* release any sadb entries -- only done at teardown */ void qla_edif_sadb_release(struct qla_hw_data *ha) { - struct list_head *pos; - struct list_head *tmp; - struct edif_sa_index_entry *entry; + struct edif_sa_index_entry *entry, *tmp; - list_for_each_safe(pos, tmp, &ha->sadb_rx_index_list) { - entry = list_entry(pos, struct edif_sa_index_entry, next); + list_for_each_entry_safe(entry, tmp, &ha->sadb_rx_index_list, next) { list_del(&entry->next); kfree(entry); } - list_for_each_safe(pos, tmp, &ha->sadb_tx_index_list) { - entry = list_entry(pos, struct edif_sa_index_entry, next); + list_for_each_entry_safe(entry, tmp, &ha->sadb_tx_index_list, next) { list_del(&entry->next); kfree(entry); } @@ -3449,7 +3456,7 @@ done: void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess) { - if (sess->edif.app_sess_online && vha->e_dbell.db_flags & EDB_ACTIVE) { + if (sess->edif.app_sess_online && DBELL_ACTIVE(vha)) { ql_dbg(ql_dbg_disc, vha, 0xf09c, "%s: sess %8phN send port_offline event\n", __func__, sess->port_name); @@ -3459,3 +3466,12 @@ void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess) qla2x00_post_aen_work(vha, FCH_EVT_PORT_OFFLINE, sess->d_id.b24); } } + +void qla_edif_clear_appdata(struct scsi_qla_host *vha, struct fc_port *fcport) +{ + if (!(fcport->flags & FCF_FCSP_DEVICE)) + return; + + qla_edb_clear(vha, fcport->d_id); + qla_enode_clear(vha, fcport->d_id); +} diff --git a/drivers/scsi/qla2xxx/qla_edif.h b/drivers/scsi/qla2xxx/qla_edif.h index 9e8f28d0caa1..a965ca8e47ce 100644 --- a/drivers/scsi/qla2xxx/qla_edif.h +++ b/drivers/scsi/qla2xxx/qla_edif.h @@ -41,9 +41,12 @@ struct pur_core { }; enum db_flags_t { - EDB_ACTIVE = 0x1, + EDB_ACTIVE = BIT_0, }; +#define DBELL_ACTIVE(_v) (_v->e_dbell.db_flags & EDB_ACTIVE) +#define DBELL_INACTIVE(_v) (!(_v->e_dbell.db_flags & EDB_ACTIVE)) + struct edif_dbell { enum db_flags_t db_flags; spinlock_t db_lock; @@ -93,7 +96,6 @@ struct sa_update_28xx { }; #define NUM_ENTRIES 256 -#define MAX_PAYLOAD 1024 #define PUR_GET 1 struct dinfo { @@ -102,7 +104,6 @@ struct dinfo { }; struct pur_ninfo { - unsigned int pur_pend:1; port_id_t pur_sid; port_id_t pur_did; uint8_t vp_idx; @@ -128,9 +129,15 @@ struct enode { } u; }; +#define RX_ELS_SIZE (roundup(sizeof(struct enode) + ELS_MAX_PAYLOAD, SMP_CACHE_BYTES)) + #define EDIF_SESSION_DOWN(_s) \ (qla_ini_mode_enabled(_s->vha) && (_s->disc_state == DSC_DELETE_PEND || \ _s->disc_state == DSC_DELETED || \ !_s->edif.app_sess_online)) +#define EDIF_NEGOTIATION_PENDING(_fcport) \ + (DBELL_ACTIVE(_fcport->vha) && \ + (_fcport->disc_state == DSC_LOGIN_AUTH_PEND)) + #endif /* __QLA_EDIF_H */ diff --git a/drivers/scsi/qla2xxx/qla_edif_bsg.h b/drivers/scsi/qla2xxx/qla_edif_bsg.h index 58b718d35d19..53026d82ebff 100644 --- a/drivers/scsi/qla2xxx/qla_edif_bsg.h +++ b/drivers/scsi/qla2xxx/qla_edif_bsg.h @@ -8,7 +8,7 @@ #define __QLA_EDIF_BSG_H /* BSG Vendor specific commands */ -#define ELS_MAX_PAYLOAD 1024 +#define ELS_MAX_PAYLOAD 2112 #ifndef WWN_SIZE #define WWN_SIZE 8 #endif diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 1c3f055d41b8..8d8503a28479 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -142,6 +142,8 @@ void qlt_chk_edif_rx_sa_delete_pending(scsi_qla_host_t *vha, fc_port_t *fcport, void qla2x00_release_all_sadb(struct scsi_qla_host *vha, struct fc_port *fcport); int qla_edif_process_els(scsi_qla_host_t *vha, struct bsg_job *bsgjob); void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess); +void qla_edif_clear_appdata(struct scsi_qla_host *vha, + struct fc_port *fcport); const char *sc_to_str(uint16_t cmd); /* @@ -171,7 +173,6 @@ extern int ql2xasynctmfenable; extern int ql2xgffidenable; extern int ql2xenabledif; extern int ql2xenablehba_err_chk; -extern int ql2xtargetreset; extern int ql2xdontresethba; extern uint64_t ql2xmaxlun; extern int ql2xmdcapmask; @@ -662,9 +663,13 @@ extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *); extern int qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *); +extern int qla2x00_mailbox_passthru(struct bsg_job *bsg_job); int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha, void **pkt, struct rsp_que **rsp, u8 *buf, u32 buf_len); +int qla_mailbox_passthru(scsi_qla_host_t *vha, uint16_t *mbx_in, + uint16_t *mbx_out); + /* * Global Function Prototypes in qla_dbg.c source file. */ @@ -738,8 +743,7 @@ uint qla25xx_fdmi_port_speed_currently(struct qla_hw_data *); * Global Function Prototypes in qla_attr.c source file. */ struct device_attribute; -extern struct device_attribute *qla2x00_host_attrs[]; -extern struct device_attribute *qla2x00_host_attrs_dm[]; +extern const struct attribute_group *qla2x00_host_groups[]; struct fc_function_template; extern struct fc_function_template qla2xxx_transport_functions; extern struct fc_function_template qla2xxx_transport_vport_functions; @@ -753,7 +757,6 @@ extern int qla2x00_echo_test(scsi_qla_host_t *, extern int qla24xx_update_all_fcp_prio(scsi_qla_host_t *); extern int qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *, struct qla_fcp_prio_cfg *, uint8_t); -void qla_insert_tgt_attrs(void); /* * Global Function Prototypes in qla_dfs.c source file. */ @@ -816,7 +819,6 @@ extern void qlafx00_abort_iocb(srb_t *, struct abort_iocb_entry_fx00 *); extern void qlafx00_fxdisc_iocb(srb_t *, struct fxdisc_entry_fx00 *); extern void qlafx00_timer_routine(scsi_qla_host_t *); extern int qlafx00_rescan_isp(scsi_qla_host_t *); -extern int qlafx00_loop_reset(scsi_qla_host_t *vha); /* qla82xx related functions */ diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index ebc8fdb0b43d..28b574e20ef3 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -1537,7 +1537,8 @@ qla25xx_fdmi_port_speed_capability(struct qla_hw_data *ha) } if (IS_QLA2031(ha)) { if ((ha->pdev->subsystem_vendor == 0x103C) && - (ha->pdev->subsystem_device == 0x8002)) { + ((ha->pdev->subsystem_device == 0x8002) || + (ha->pdev->subsystem_device == 0x8086))) { speeds = FDMI_PORT_SPEED_16GB; } else { speeds = FDMI_PORT_SPEED_16GB|FDMI_PORT_SPEED_8GB| diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 5fc7697f0af4..070b636802d0 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -330,12 +330,9 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, lio->u.logio.flags |= SRB_LOGIN_PRLI_ONLY; } else { if (vha->hw->flags.edif_enabled && - vha->e_dbell.db_flags & EDB_ACTIVE) { + DBELL_ACTIVE(vha)) { lio->u.logio.flags |= (SRB_LOGIN_FCSP | SRB_LOGIN_SKIP_PRLI); - ql_dbg(ql_dbg_disc, vha, 0x2072, - "Async-login: w/ FCSP %8phC hdl=%x, loopid=%x portid=%06x\n", - fcport->port_name, sp->handle, fcport->loop_id, fcport->d_id.b24); } else { lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI; } @@ -344,12 +341,14 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, if (NVME_TARGET(vha->hw, fcport)) lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI; + rval = qla2x00_start_sp(sp); + ql_dbg(ql_dbg_disc, vha, 0x2072, - "Async-login - %8phC hdl=%x, loopid=%x portid=%06x retries=%d.\n", + "Async-login - %8phC hdl=%x, loopid=%x portid=%06x retries=%d %s.\n", fcport->port_name, sp->handle, fcport->loop_id, - fcport->d_id.b24, fcport->login_retry); + fcport->d_id.b24, fcport->login_retry, + lio->u.logio.flags & SRB_LOGIN_FCSP ? "FCSP" : ""); - rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { fcport->flags |= FCF_LOGIN_NEEDED; set_bit(RELOGIN_NEEDED, &vha->dpc_flags); @@ -862,7 +861,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, break; case DSC_LS_PLOGI_COMP: if (vha->hw->flags.edif_enabled && - vha->e_dbell.db_flags & EDB_ACTIVE) { + DBELL_ACTIVE(vha)) { /* check to see if App support secure or not */ qla24xx_post_gpdb_work(vha, fcport, 0); break; @@ -987,8 +986,6 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) sp->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1], sp->u.iocb_cmd.u.mbx.in_mb[2]); - if (res == QLA_FUNCTION_TIMEOUT) - return; sp->fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE); memset(&ea, 0, sizeof(ea)); @@ -1026,8 +1023,8 @@ static void qla24xx_async_gnl_sp_done(srb_t *sp, int res) spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); list_for_each_entry_safe(fcport, tf, &h, gnl_entry) { - list_del_init(&fcport->gnl_entry); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); + list_del_init(&fcport->gnl_entry); fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); ea.fcport = fcport; @@ -1454,7 +1451,7 @@ static int qla_chk_secure_login(scsi_qla_host_t *vha, fc_port_t *fcport, qla2x00_post_aen_work(vha, FCH_EVT_PORT_ONLINE, fcport->d_id.b24); - if (vha->e_dbell.db_flags == EDB_ACTIVE) { + if (DBELL_ACTIVE(vha)) { ql_dbg(ql_dbg_disc, vha, 0x20ef, "%s %d %8phC EDIF: post DB_AUTH: AUTH needed\n", __func__, __LINE__, fcport->port_name); @@ -1786,16 +1783,72 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) fc_port_t *fcport; unsigned long flags; - fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1); - if (fcport) { - if (fcport->flags & FCF_FCP2_DEVICE) { - ql_dbg(ql_dbg_disc, vha, 0x2115, - "Delaying session delete for FCP2 portid=%06x %8phC ", - fcport->d_id.b24, fcport->port_name); - return; + switch (ea->id.b.rsvd_1) { + case RSCN_PORT_ADDR: + fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1); + if (fcport) { + if (fcport->flags & FCF_FCP2_DEVICE) { + ql_dbg(ql_dbg_disc, vha, 0x2115, + "Delaying session delete for FCP2 portid=%06x %8phC ", + fcport->d_id.b24, fcport->port_name); + return; + } + + if (vha->hw->flags.edif_enabled && DBELL_ACTIVE(vha)) { + /* + * On ipsec start by remote port, Target port + * may use RSCN to trigger initiator to + * relogin. If driver is already in the + * process of a relogin, then ignore the RSCN + * and allow the current relogin to continue. + * This reduces thrashing of the connection. + */ + if (atomic_read(&fcport->state) == FCS_ONLINE) { + /* + * If state = online, then set scan_needed=1 to do relogin. + * Otherwise we're already in the middle of a relogin + */ + fcport->scan_needed = 1; + fcport->rscn_gen++; + } + } else { + fcport->scan_needed = 1; + fcport->rscn_gen++; + } } - fcport->scan_needed = 1; - fcport->rscn_gen++; + break; + case RSCN_AREA_ADDR: + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (fcport->flags & FCF_FCP2_DEVICE) + continue; + + if ((ea->id.b24 & 0xffff00) == (fcport->d_id.b24 & 0xffff00)) { + fcport->scan_needed = 1; + fcport->rscn_gen++; + } + } + break; + case RSCN_DOM_ADDR: + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (fcport->flags & FCF_FCP2_DEVICE) + continue; + + if ((ea->id.b24 & 0xff0000) == (fcport->d_id.b24 & 0xff0000)) { + fcport->scan_needed = 1; + fcport->rscn_gen++; + } + } + break; + case RSCN_FAB_ADDR: + default: + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (fcport->flags & FCF_FCP2_DEVICE) + continue; + + fcport->scan_needed = 1; + fcport->rscn_gen++; + } + break; } spin_lock_irqsave(&vha->work_lock, flags); @@ -4187,7 +4240,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha) * fw shal not send PRLI after PLOGI Acc */ if (ha->flags.edif_enabled && - vha->e_dbell.db_flags & EDB_ACTIVE) { + DBELL_ACTIVE(vha)) { ha->fw_options[3] |= BIT_15; ha->flags.n2n_fw_acc_sec = 1; } else { @@ -4433,6 +4486,10 @@ qla2x00_init_rings(scsi_qla_host_t *vha) (ha->flags.fawwpn_enabled) ? "enabled" : "disabled"); } + /* ELS pass through payload is limit by frame size. */ + if (ha->flags.edif_enabled) + mid_init_cb->init_cb.frame_payload_size = cpu_to_le16(ELS_MAX_PAYLOAD); + rval = qla2x00_init_firmware(vha, ha->init_cb_size); next_check: if (rval) { @@ -5335,15 +5392,13 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) "LOOP READY.\n"); ha->flags.fw_init_done = 1; - if (ha->flags.edif_enabled && - !(vha->e_dbell.db_flags & EDB_ACTIVE) && - N2N_TOPO(vha->hw)) { - /* - * use port online to wake up app to get ready - * for authentication - */ - qla2x00_post_aen_work(vha, FCH_EVT_PORT_ONLINE, 0); - } + /* + * use link up to wake up app to get ready for + * authentication. + */ + if (ha->flags.edif_enabled && DBELL_INACTIVE(vha)) + qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, + ha->link_data_rate); /* * Process any ATIO queue entries that came in @@ -5834,6 +5889,10 @@ void qla_register_fcport_fn(struct work_struct *work) qla2x00_update_fcport(fcport->vha, fcport); + ql_dbg(ql_dbg_disc, fcport->vha, 0x911e, + "%s rscn gen %d/%d next DS %d\n", __func__, + rscn_gen, fcport->rscn_gen, fcport->next_disc_state); + if (rscn_gen != fcport->rscn_gen) { /* RSCN(s) came in while registration */ switch (fcport->next_disc_state) { @@ -7026,12 +7085,14 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) ha->chip_reset++; ha->base_qpair->chip_reset = ha->chip_reset; ha->base_qpair->cmd_cnt = ha->base_qpair->cmd_completion_cnt = 0; + ha->base_qpair->prev_completion_cnt = 0; for (i = 0; i < ha->max_qpairs; i++) { if (ha->queue_pair_map[i]) { ha->queue_pair_map[i]->chip_reset = ha->base_qpair->chip_reset; ha->queue_pair_map[i]->cmd_cnt = ha->queue_pair_map[i]->cmd_completion_cnt = 0; + ha->base_qpair->prev_completion_cnt = 0; } } diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 9d4ad1d2b00a..ed604f2185bf 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -3034,8 +3034,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, elsio->u.els_plogi.els_cmd = els_opcode; elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode; - if (els_opcode == ELS_DCMD_PLOGI && vha->hw->flags.edif_enabled && - vha->e_dbell.db_flags & EDB_ACTIVE) { + if (els_opcode == ELS_DCMD_PLOGI && DBELL_ACTIVE(vha)) { struct fc_els_flogi *p = ptr; p->fl_csp.sp_features |= cpu_to_be16(FC_SP_FT_SEC); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index b26f2699adb2..aaf6504570fd 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2233,6 +2233,10 @@ qla24xx_els_ct_entry(scsi_qla_host_t *v, struct req_que *req, } } else if (comp_status == CS_PORT_LOGGED_OUT) { + ql_dbg(ql_dbg_disc, vha, 0x911e, + "%s %d schedule session deletion\n", + __func__, __LINE__); + els->u.els_plogi.len = 0; res = DID_IMM_RETRY << 16; qlt_schedule_sess_for_deletion(sp->fcport); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 7811c4952035..10d2655ef676 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1695,10 +1695,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10; if (IS_FWI2_CAPABLE(vha->hw)) mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16; - if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) { - mcp->in_mb |= MBX_15; - mcp->out_mb |= MBX_7|MBX_21|MBX_22|MBX_23; - } + if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) + mcp->in_mb |= MBX_15|MBX_21|MBX_22|MBX_23; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; @@ -3236,7 +3234,7 @@ qla24xx_abort_command(srb_t *sp) fc_port_t *fcport = sp->fcport; struct scsi_qla_host *vha = fcport->vha; struct qla_hw_data *ha = vha->hw; - struct req_que *req = vha->req; + struct req_que *req; struct qla_qpair *qpair = sp->qpair; ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108c, @@ -7011,3 +7009,36 @@ void qla_no_op_mb(struct scsi_qla_host *vha) "Failed %s %x\n", __func__, rval); } } + +int qla_mailbox_passthru(scsi_qla_host_t *vha, + uint16_t *mbx_in, uint16_t *mbx_out) +{ + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + int rval = -EINVAL; + + memset(&mc, 0, sizeof(mc)); + /* Receiving all 32 register's contents */ + memcpy(&mcp->mb, (char *)mbx_in, (32 * sizeof(uint16_t))); + + mcp->out_mb = 0xFFFFFFFF; + mcp->in_mb = 0xFFFFFFFF; + + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + mcp->bufp = NULL; + + rval = qla2x00_mailbox_command(vha, mcp); + + if (rval != QLA_SUCCESS) { + ql_dbg(ql_dbg_mbx, vha, 0xf0a2, + "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + } else { + ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xf0a3, "Done %s.\n", + __func__); + /* passing all 32 register's contents */ + memcpy(mbx_out, &mcp->mb, 32 * sizeof(uint16_t)); + } + + return rval; +} diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 6e920da64863..350b0c4346fb 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -739,29 +739,6 @@ qlafx00_lun_reset(fc_port_t *fcport, uint64_t l, int tag) } int -qlafx00_loop_reset(scsi_qla_host_t *vha) -{ - int ret; - struct fc_port *fcport; - struct qla_hw_data *ha = vha->hw; - - if (ql2xtargetreset) { - list_for_each_entry(fcport, &vha->vp_fcports, list) { - if (fcport->port_type != FCT_TARGET) - continue; - - ret = ha->isp_ops->target_reset(fcport, 0, 0); - if (ret != QLA_SUCCESS) { - ql_dbg(ql_dbg_taskm, vha, 0x803d, - "Bus Reset failed: Reset=%d " - "d_id=%x.\n", ret, fcport->d_id.b24); - } - } - } - return QLA_SUCCESS; -} - -int qlafx00_iospace_config(struct qla_hw_data *ha) { if (pci_request_selected_regions(ha->pdev, ha->bars, diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 253055cf9daf..138ffdb5c92c 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -230,6 +230,8 @@ static void qla_nvme_abort_work(struct work_struct *work) fc_port_t *fcport = sp->fcport; struct qla_hw_data *ha = fcport->vha->hw; int rval, abts_done_called = 1; + bool io_wait_for_abort_done; + uint32_t handle; ql_dbg(ql_dbg_io, fcport->vha, 0xffff, "%s called for sp=%p, hndl=%x on fcport=%p desc=%p deleted=%d\n", @@ -246,12 +248,20 @@ static void qla_nvme_abort_work(struct work_struct *work) goto out; } + /* + * sp may not be valid after abort_command if return code is either + * SUCCESS or ERR_FROM_FW codes, so cache the value here. + */ + io_wait_for_abort_done = ql2xabts_wait_nvme && + QLA_ABTS_WAIT_ENABLED(sp); + handle = sp->handle; + rval = ha->isp_ops->abort_command(sp); ql_dbg(ql_dbg_io, fcport->vha, 0x212b, "%s: %s command for sp=%p, handle=%x on fcport=%p rval=%x\n", __func__, (rval != QLA_SUCCESS) ? "Failed to abort" : "Aborted", - sp, sp->handle, fcport, rval); + sp, handle, fcport, rval); /* * If async tmf is enabled, the abort callback is called only on @@ -266,7 +276,7 @@ static void qla_nvme_abort_work(struct work_struct *work) * are waited until ABTS complete. This kref is decreased * at qla24xx_abort_sp_done function. */ - if (abts_done_called && ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(sp)) + if (abts_done_called && io_wait_for_abort_done) return; out: /* kref_get was done before work was schedule. */ @@ -391,6 +401,7 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) uint16_t avail_dsds; struct dsd64 *cur_dsd; struct req_que *req = NULL; + struct rsp_que *rsp = NULL; struct scsi_qla_host *vha = sp->fcport->vha; struct qla_hw_data *ha = vha->hw; struct qla_qpair *qpair = sp->qpair; @@ -402,6 +413,7 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) /* Setup qpair pointers */ req = qpair->req; + rsp = qpair->rsp; tot_dsds = fd->sg_cnt; /* Acquire qpair specific lock */ @@ -563,6 +575,10 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp) /* Set chip new ring index. */ wrt_reg_dword(req->req_q_in, req->ring_index); + if (vha->flags.process_response_queue && + rsp->ring_ptr->signature != RESPONSE_PROCESSED) + qla24xx_process_response_queue(vha, rsp); + queuing_error: spin_unlock_irqrestore(&qpair->qp_lock, flags); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 836fedcea241..abcd30917263 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -202,12 +202,6 @@ MODULE_PARM_DESC(ql2xdbwr, " 0 -- Regular doorbell.\n" " 1 -- CAMRAM doorbell (faster).\n"); -int ql2xtargetreset = 1; -module_param(ql2xtargetreset, int, S_IRUGO); -MODULE_PARM_DESC(ql2xtargetreset, - "Enable target reset." - "Default is 1 - use hw defaults."); - int ql2xgffidenable; module_param(ql2xgffidenable, int, S_IRUGO); MODULE_PARM_DESC(ql2xgffidenable, @@ -737,7 +731,7 @@ void qla2x00_sp_compl(srb_t *sp, int res) sp->free(sp); cmd->result = res; CMD_SP(cmd) = NULL; - cmd->scsi_done(cmd); + scsi_done(cmd); if (comp) complete(comp); } @@ -828,7 +822,7 @@ void qla2xxx_qpair_sp_compl(srb_t *sp, int res) sp->free(sp); cmd->result = res; CMD_SP(cmd) = NULL; - cmd->scsi_done(cmd); + scsi_done(cmd); if (comp) complete(comp); } @@ -950,7 +944,7 @@ qc24_target_busy: return SCSI_MLQUEUE_TARGET_BUSY; qc24_fail_command: - cmd->scsi_done(cmd); + scsi_done(cmd); return 0; } @@ -1038,7 +1032,7 @@ qc24_target_busy: return SCSI_MLQUEUE_TARGET_BUSY; qc24_fail_command: - cmd->scsi_done(cmd); + scsi_done(cmd); return 0; } @@ -1258,6 +1252,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) uint32_t ratov_j; struct qla_qpair *qpair; unsigned long flags; + int fast_fail_status = SUCCESS; if (qla2x00_isp_reg_stat(ha)) { ql_log(ql_log_info, vha, 0x8042, @@ -1266,9 +1261,10 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return FAILED; } + /* Save any FAST_IO_FAIL value to return later if abort succeeds */ ret = fc_block_scsi_eh(cmd); if (ret != 0) - return ret; + fast_fail_status = ret; sp = scsi_cmd_priv(cmd); qpair = sp->qpair; @@ -1276,7 +1272,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) vha->cmd_timeout_cnt++; if ((sp->fcport && sp->fcport->deleted) || !qpair) - return SUCCESS; + return fast_fail_status != SUCCESS ? fast_fail_status : FAILED; spin_lock_irqsave(qpair->qp_lock_ptr, flags); sp->comp = ∁ @@ -1311,7 +1307,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) __func__, ha->r_a_tov/10); ret = FAILED; } else { - ret = SUCCESS; + ret = fast_fail_status; } break; default: @@ -1693,27 +1689,10 @@ int qla2x00_loop_reset(scsi_qla_host_t *vha) { int ret; - struct fc_port *fcport; struct qla_hw_data *ha = vha->hw; - if (IS_QLAFX00(ha)) { - return qlafx00_loop_reset(vha); - } - - if (ql2xtargetreset == 1 && ha->flags.enable_target_reset) { - list_for_each_entry(fcport, &vha->vp_fcports, list) { - if (fcport->port_type != FCT_TARGET) - continue; - - ret = ha->isp_ops->target_reset(fcport, 0, 0); - if (ret != QLA_SUCCESS) { - ql_dbg(ql_dbg_taskm, vha, 0x802c, - "Bus Reset failed: Reset=%d " - "d_id=%x.\n", ret, fcport->d_id.b24); - } - } - } - + 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); @@ -2794,6 +2773,16 @@ qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time) return atomic_read(&vha->loop_state) == LOOP_READY; } +static void qla_heartbeat_work_fn(struct work_struct *work) +{ + struct qla_hw_data *ha = container_of(work, + struct qla_hw_data, heartbeat_work); + struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); + + if (!ha->flags.mbox_busy && base_vha->flags.init_done) + qla_no_op_mb(base_vha); +} + static void qla2x00_iocb_work_fn(struct work_struct *work) { struct scsi_qla_host *vha = container_of(work, @@ -3232,6 +3221,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host->transportt, sht->vendor_id); INIT_WORK(&base_vha->iocb_work, qla2x00_iocb_work_fn); + INIT_WORK(&ha->heartbeat_work, qla_heartbeat_work_fn); /* Set up the irqs */ ret = qla2x00_request_irqs(ha, rsp); @@ -3364,6 +3354,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host->can_queue, base_vha->req, base_vha->mgmt_svr_loop_id, host->sg_tablesize); + /* Check if FW supports MQ or not for ISP25xx */ + if (IS_QLA25XX(ha) && !(ha->fw_attributes & BIT_6)) + ha->mqenable = 0; + if (ha->mqenable) { bool startit = false; @@ -3891,13 +3885,13 @@ qla2x00_remove_one(struct pci_dev *pdev) static inline void qla24xx_free_purex_list(struct purex_list *list) { - struct list_head *item, *next; + struct purex_item *item, *next; ulong flags; spin_lock_irqsave(&list->lock, flags); - list_for_each_safe(item, next, &list->head) { - list_del(item); - kfree(list_entry(item, struct purex_item, list)); + list_for_each_entry_safe(item, next, &list->head, list) { + list_del(&item->list); + kfree(item); } spin_unlock_irqrestore(&list->lock, flags); } @@ -4358,7 +4352,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, /* allocate the purex dma pool */ ha->purex_dma_pool = dma_pool_create(name, &ha->pdev->dev, - MAX_PAYLOAD, 8, 0); + ELS_MAX_PAYLOAD, 8, 0); if (!ha->purex_dma_pool) { ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b, @@ -7114,17 +7108,6 @@ intr_on_check: qla2x00_lip_reset(base_vha); } - if (test_bit(HEARTBEAT_CHK, &base_vha->dpc_flags)) { - /* - * if there is a mb in progress then that's - * enough of a check to see if fw is still ticking. - */ - if (!ha->flags.mbox_busy && base_vha->flags.init_done) - qla_no_op_mb(base_vha); - - clear_bit(HEARTBEAT_CHK, &base_vha->dpc_flags); - } - ha->dpc_active = 0; end_loop: set_current_state(TASK_INTERRUPTIBLE); @@ -7183,57 +7166,51 @@ qla2x00_rst_aen(scsi_qla_host_t *vha) static bool qla_do_heartbeat(struct scsi_qla_host *vha) { - u64 cmd_cnt, prev_cmd_cnt; - bool do_hb = false; struct qla_hw_data *ha = vha->hw; - int i; + u32 cmpl_cnt; + u16 i; + bool do_heartbeat = false; - /* if cmds are still pending down in fw, then do hb */ - if (ha->base_qpair->cmd_cnt != ha->base_qpair->cmd_completion_cnt) { - do_hb = true; + /* + * Allow do_heartbeat only if we don’t have any active interrupts, + * but there are still IOs outstanding with firmware. + */ + cmpl_cnt = ha->base_qpair->cmd_completion_cnt; + if (cmpl_cnt == ha->base_qpair->prev_completion_cnt && + cmpl_cnt != ha->base_qpair->cmd_cnt) { + do_heartbeat = true; goto skip; } + ha->base_qpair->prev_completion_cnt = cmpl_cnt; for (i = 0; i < ha->max_qpairs; i++) { - if (ha->queue_pair_map[i] && - ha->queue_pair_map[i]->cmd_cnt != - ha->queue_pair_map[i]->cmd_completion_cnt) { - do_hb = true; - break; + if (ha->queue_pair_map[i]) { + cmpl_cnt = ha->queue_pair_map[i]->cmd_completion_cnt; + if (cmpl_cnt == ha->queue_pair_map[i]->prev_completion_cnt && + cmpl_cnt != ha->queue_pair_map[i]->cmd_cnt) { + do_heartbeat = true; + break; + } + ha->queue_pair_map[i]->prev_completion_cnt = cmpl_cnt; } } skip: - prev_cmd_cnt = ha->prev_cmd_cnt; - cmd_cnt = ha->base_qpair->cmd_cnt; - for (i = 0; i < ha->max_qpairs; i++) { - if (ha->queue_pair_map[i]) - cmd_cnt += ha->queue_pair_map[i]->cmd_cnt; - } - ha->prev_cmd_cnt = cmd_cnt; - - if (!do_hb && ((cmd_cnt - prev_cmd_cnt) > 50)) - /* - * IOs are completing before periodic hb check. - * IOs seems to be running, do hb for sanity check. - */ - do_hb = true; - - return do_hb; + return do_heartbeat; } static void qla_heart_beat(struct scsi_qla_host *vha) { + struct qla_hw_data *ha = vha->hw; + if (vha->vp_idx) return; if (vha->hw->flags.eeh_busy || qla2x00_chip_is_down(vha)) return; - if (qla_do_heartbeat(vha)) { - set_bit(HEARTBEAT_CHK, &vha->dpc_flags); - qla2xxx_wake_dpc(vha); - } + if (qla_do_heartbeat(vha)) + queue_work(ha->wq, &ha->heartbeat_work); } /************************************************************************** @@ -7943,7 +7920,7 @@ struct scsi_host_template qla2xxx_driver_template = { .sg_tablesize = SG_ALL, .max_sectors = 0xFFFF, - .shost_attrs = qla2x00_host_attrs, + .shost_groups = qla2x00_host_groups, .supported_mode = MODE_INITIATOR, .track_queue_depth = 1, @@ -8131,9 +8108,6 @@ qla2x00_module_init(void) if (ql2xextended_error_logging == 1) ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK; - if (ql2x_ini_mode == QLA2XXX_INI_MODE_DUAL) - qla_insert_tgt_attrs(); - qla2xxx_transport_template = fc_attach_transport(&qla2xxx_transport_functions); if (!qla2xxx_transport_template) { diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 7d8242c120fc..8993d438e0b7 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1003,6 +1003,7 @@ void qlt_free_session_done(struct work_struct *work) "%s bypassing release_all_sadb\n", __func__); } + qla_edif_clear_appdata(vha, sess); qla_edif_sess_down(vha, sess); } qla2x00_mark_device_lost(vha, sess, 0); @@ -4812,7 +4813,7 @@ static int qlt_handle_login(struct scsi_qla_host *vha, } if (vha->hw->flags.edif_enabled) { - if (!(vha->e_dbell.db_flags & EDB_ACTIVE)) { + if (DBELL_INACTIVE(vha)) { ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %d Term INOT due to app not started lid=%d, NportID %06X ", __func__, __LINE__, loop_id, port_id.b24); diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 055040cbef9b..27e440f8a702 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -6,9 +6,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.02.06.200-k" +#define QLA2XXX_VERSION "10.02.07.200-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 2 -#define QLA_DRIVER_PATCH_VER 6 +#define QLA_DRIVER_PATCH_VER 7 #define QLA_DRIVER_BETA_VER 200 diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 03de1bcf1461..8fa0056b56dd 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -915,40 +915,17 @@ static struct configfs_attribute *tcm_qla2xxx_tpg_attrib_attrs[] = { /* End items for tcm_qla2xxx_tpg_attrib_cit */ -static ssize_t tcm_qla2xxx_tpg_enable_show(struct config_item *item, - char *page) -{ - struct se_portal_group *se_tpg = to_tpg(item); - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - - return snprintf(page, PAGE_SIZE, "%d\n", - atomic_read(&tpg->lport_tpg_enabled)); -} - -static ssize_t tcm_qla2xxx_tpg_enable_store(struct config_item *item, - const char *page, size_t count) +static int tcm_qla2xxx_enable_tpg(struct se_portal_group *se_tpg, + bool enable) { - struct se_portal_group *se_tpg = to_tpg(item); struct se_wwn *se_wwn = se_tpg->se_tpg_wwn; struct tcm_qla2xxx_lport *lport = container_of(se_wwn, struct tcm_qla2xxx_lport, lport_wwn); struct scsi_qla_host *vha = lport->qla_vha; struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, struct tcm_qla2xxx_tpg, se_tpg); - unsigned long op; - int rc; - rc = kstrtoul(page, 0, &op); - if (rc < 0) { - pr_err("kstrtoul() returned %d\n", rc); - return -EINVAL; - } - if ((op != 1) && (op != 0)) { - pr_err("Illegal value for tpg_enable: %lu\n", op); - return -EINVAL; - } - if (op) { + if (enable) { if (atomic_read(&tpg->lport_tpg_enabled)) return -EEXIST; @@ -956,14 +933,14 @@ static ssize_t tcm_qla2xxx_tpg_enable_store(struct config_item *item, qlt_enable_vha(vha); } else { if (!atomic_read(&tpg->lport_tpg_enabled)) - return count; + return 0; atomic_set(&tpg->lport_tpg_enabled, 0); qlt_stop_phase1(vha->vha_tgt.qla_tgt); qlt_stop_phase2(vha->vha_tgt.qla_tgt); } - return count; + return 0; } static ssize_t tcm_qla2xxx_tpg_dynamic_sessions_show(struct config_item *item, @@ -1004,12 +981,10 @@ static ssize_t tcm_qla2xxx_tpg_fabric_prot_type_show(struct config_item *item, return sprintf(page, "%d\n", tpg->tpg_attrib.fabric_prot_type); } -CONFIGFS_ATTR(tcm_qla2xxx_tpg_, enable); CONFIGFS_ATTR_RO(tcm_qla2xxx_tpg_, dynamic_sessions); CONFIGFS_ATTR(tcm_qla2xxx_tpg_, fabric_prot_type); static struct configfs_attribute *tcm_qla2xxx_tpg_attrs[] = { - &tcm_qla2xxx_tpg_attr_enable, &tcm_qla2xxx_tpg_attr_dynamic_sessions, &tcm_qla2xxx_tpg_attr_fabric_prot_type, NULL, @@ -1083,35 +1058,17 @@ static void tcm_qla2xxx_drop_tpg(struct se_portal_group *se_tpg) kfree(tpg); } -static ssize_t tcm_qla2xxx_npiv_tpg_enable_show(struct config_item *item, - char *page) -{ - return tcm_qla2xxx_tpg_enable_show(item, page); -} - -static ssize_t tcm_qla2xxx_npiv_tpg_enable_store(struct config_item *item, - const char *page, size_t count) +static int tcm_qla2xxx_npiv_enable_tpg(struct se_portal_group *se_tpg, + bool enable) { - struct se_portal_group *se_tpg = to_tpg(item); struct se_wwn *se_wwn = se_tpg->se_tpg_wwn; struct tcm_qla2xxx_lport *lport = container_of(se_wwn, struct tcm_qla2xxx_lport, lport_wwn); struct scsi_qla_host *vha = lport->qla_vha; struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, struct tcm_qla2xxx_tpg, se_tpg); - unsigned long op; - int rc; - rc = kstrtoul(page, 0, &op); - if (rc < 0) { - pr_err("kstrtoul() returned %d\n", rc); - return -EINVAL; - } - if ((op != 1) && (op != 0)) { - pr_err("Illegal value for tpg_enable: %lu\n", op); - return -EINVAL; - } - if (op) { + if (enable) { if (atomic_read(&tpg->lport_tpg_enabled)) return -EEXIST; @@ -1119,23 +1076,16 @@ static ssize_t tcm_qla2xxx_npiv_tpg_enable_store(struct config_item *item, qlt_enable_vha(vha); } else { if (!atomic_read(&tpg->lport_tpg_enabled)) - return count; + return 0; atomic_set(&tpg->lport_tpg_enabled, 0); qlt_stop_phase1(vha->vha_tgt.qla_tgt); qlt_stop_phase2(vha->vha_tgt.qla_tgt); } - return count; + return 0; } -CONFIGFS_ATTR(tcm_qla2xxx_npiv_tpg_, enable); - -static struct configfs_attribute *tcm_qla2xxx_npiv_tpg_attrs[] = { - &tcm_qla2xxx_npiv_tpg_attr_enable, - NULL, -}; - static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(struct se_wwn *wwn, const char *name) { @@ -1878,6 +1828,7 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = { .fabric_make_wwn = tcm_qla2xxx_make_lport, .fabric_drop_wwn = tcm_qla2xxx_drop_lport, .fabric_make_tpg = tcm_qla2xxx_make_tpg, + .fabric_enable_tpg = tcm_qla2xxx_enable_tpg, .fabric_drop_tpg = tcm_qla2xxx_drop_tpg, .fabric_init_nodeacl = tcm_qla2xxx_init_nodeacl, @@ -1918,11 +1869,11 @@ static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { .fabric_make_wwn = tcm_qla2xxx_npiv_make_lport, .fabric_drop_wwn = tcm_qla2xxx_npiv_drop_lport, .fabric_make_tpg = tcm_qla2xxx_npiv_make_tpg, + .fabric_enable_tpg = tcm_qla2xxx_npiv_enable_tpg, .fabric_drop_tpg = tcm_qla2xxx_drop_tpg, .fabric_init_nodeacl = tcm_qla2xxx_init_nodeacl, .tfc_wwn_attrs = tcm_qla2xxx_wwn_attrs, - .tfc_tpg_base_attrs = tcm_qla2xxx_npiv_tpg_attrs, }; static int tcm_qla2xxx_register_configfs(void) |