diff --git a/.github/workflows/run_regression_tests.yaml b/.github/workflows/run_regression_tests.yaml index 60f2580fb..a66974c91 100644 --- a/.github/workflows/run_regression_tests.yaml +++ b/.github/workflows/run_regression_tests.yaml @@ -4,6 +4,7 @@ on: push: branches: - master + - nightly/update jobs: regression_tests: @@ -13,24 +14,30 @@ jobs: fail-fast: false matrix: version: [ - '6.8.7', + '6.11', + '6.10.10', + '6.9.12', + '6.8.12', '6.7.12', - '6.6.28', - '6.1.87', - '5.15.156', - '5.10.215', - '5.4.274', - '4.19.312', + '6.6.51', + '6.1.110', + '5.15.167', + '5.10.226', + '5.4.284', + '4.19.322', '4.14.336', '4.9.337', '3.18.140', '3.10.108', + '5.14.0-427.33.1.el9_4^AlmaLinux^9.4', + '5.14.0-362.24.2.el9_3^AlmaLinux^9.3', '5.14.0-284.30.1.el9_2^AlmaLinux^9.2', '4.18.0-513.24.1.el8_9^AlmaLinux^8.9', '4.18.0-477.13.1.el8_8^AlmaLinux^8.8', - '3.10.0-1160.108.1.el7^CentOS^7.9.2009', - '5.15.0-205.149.5.1.el9uek^UEK^9', - '5.4.17-2136.330.7.1.el8uek^UEK^8', + '4.18.0-425.19.2.el8_7^AlmaLinux^8.7', + '3.10.0-1160.118.1.el7^CentOS^7.9.2009', + '5.15.0-210.163.7.el9uek^UEK^9', + '5.4.17-2136.335.4.el8uek^UEK^8', '5.4.17-2102.206.1.el7uek^UEK^7', '4.1.12-124.48.6.el6uek^UEK^6' ] diff --git a/iscsi-scst/README b/iscsi-scst/README index 4a275b195..91ad19109 100644 --- a/iscsi-scst/README +++ b/iscsi-scst/README @@ -200,6 +200,13 @@ is /sys/kernel/scst_tgt/targets/iscsi. It has the following entries: iSCSI-SCST attributes before it starts accepting new connections. 0 by default. + - internal_portal - May designate one or more existing portals as being + internal. This will eliminate the need to supply a CHAP user/secret + during discovery or target login to any targets configured on those + portals. This is particularly useful for internal targets used as + part of ALUA configuration. Multiple addresses may be supplied, + separated by space characters. Empty by default. + - link_local - if set, makes the response to an IPv6 SendTargets include any link local addresses. Default is set. @@ -552,6 +559,7 @@ both iSCSI-SCST targets will look like: | |-- IncomingUser | |-- OutgoingUser | |-- enabled +| |-- internal_portal | |-- iSNSServer | |-- iqn.2006-10.net.vlnb:tgt | | |-- DataDigest diff --git a/iscsi-scst/usr/event.c b/iscsi-scst/usr/event.c index a65a1830f..b2178ae08 100644 --- a/iscsi-scst/usr/event.c +++ b/iscsi-scst/usr/event.c @@ -654,6 +654,18 @@ static int handle_e_get_attr_value(int fd, const struct iscsi_kern_event *event) snprintf(res_str, sizeof(res_str), "%d\n", send_targets_link_local); if (send_targets_link_local != DEFAULT_SEND_TARGETS_LINK_LOCAL) add_key_mark(res_str, sizeof(res_str), 0); + } else if (strcasecmp(ISCSI_INTERNAL_PORTAL_ATTR_NAME, pp) == 0) { + if (target != NULL) { + log_error("Not NULL target %s for global attribute %s", + target->name, pp); + res = -EINVAL; + goto out_free; + } + if (internal_portal) { + snprintf(res_str, sizeof(res_str), "%s\n", internal_portal); + add_key_mark(res_str, sizeof(res_str), 0); + } else + snprintf(res_str, sizeof(res_str), "\n"); } else { log_error("Unknown attribute %s", pp); res = -EINVAL; @@ -669,6 +681,14 @@ static int handle_e_get_attr_value(int fd, const struct iscsi_kern_event *event) return res; } +static bool is_addr(char *addr) +{ + struct in_addr ia; + struct in6_addr ia6; + + return (inet_pton(AF_INET, addr, &ia) == 1) || inet_pton(AF_INET6, addr, &ia6); +} + static int handle_target_redirect(struct target *target, char *p) { int res = 0; @@ -1094,6 +1114,51 @@ static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event) res = -EINVAL; goto out_free; } + } else if (strcasecmp(ISCSI_INTERNAL_PORTAL_ATTR_NAME, pp) == 0) { + if (target != NULL) { + log_error("Not NULL target %s for global attribute %s", + target->name, pp); + res = -EINVAL; + goto out_free; + } + p = config_strip_string(p); + if (!p || *p == '\0') { + free(internal_portal); + internal_portal = NULL; + } else { + /* We have been provided with a string, check the contents. */ + if (strchr(p, ' ')) { + char *portals = strdup(p); + char *portal; + + if (!portals) { + log_error("Memory error (internal_portal)"); + res = -ENOMEM; + goto out_free; + } + + portal = strtok(portals, " "); + while (portal != NULL) { + if (!is_addr(portal)) { + free(portals); + log_error("Invalid address supplied %s", portal); + res = -EINVAL; + goto out_free; + } + portal = strtok(NULL, " "); + } + free(portals); + } else { + /* No spaces */ + if (!is_addr(p)) { + log_error("Invalid address supplied %s", p); + res = -EINVAL; + goto out_free; + } + } + free(internal_portal); + internal_portal = strdup(p); + } } else { log_error("Unknown attribute %s", pp); res = -EINVAL; diff --git a/iscsi-scst/usr/iscsi_scstd.c b/iscsi-scst/usr/iscsi_scstd.c index 97b9143d2..60b83099f 100644 --- a/iscsi-scst/usr/iscsi_scstd.c +++ b/iscsi-scst/usr/iscsi_scstd.c @@ -962,6 +962,9 @@ int main(int argc, char **argv) if (err != 0) exit(err); err = kernel_attr_add(NULL, ISCSI_LINK_LOCAL_ATTR_NAME, 0644, 0); + if (err != 0) + exit(err); + err = kernel_attr_add(NULL, ISCSI_INTERNAL_PORTAL_ATTR_NAME, 0644, 0); if (err != 0) exit(err); diff --git a/iscsi-scst/usr/iscsid.c b/iscsi-scst/usr/iscsid.c index 1ef94ce3c..d32b672ff 100644 --- a/iscsi-scst/usr/iscsid.c +++ b/iscsi-scst/usr/iscsid.c @@ -27,6 +27,7 @@ #include "iscsid.h" int iscsi_enabled; +char *internal_portal; static u32 ttt; @@ -1011,6 +1012,32 @@ static int cmnd_exec_auth(struct connection *conn) return res; } +static bool on_internal_portal(struct connection *conn) +{ + if (!internal_portal) + return false; + + if (strchr(internal_portal, ' ')) { + char *portals = strdup(internal_portal); + + if (portals) { + char *portal = strtok(portals, " "); + + while (portal != NULL) { + if (!strcmp(portal, conn->target_portal)) { + free(portals); + return true; + } + portal = strtok(NULL, " "); + } + free(portals); + } + return false; + } else { + return !strcmp(internal_portal, conn->target_portal); + } +} + static void cmnd_exec_login(struct connection *conn) { struct iscsi_login_req_hdr *req = (struct iscsi_login_req_hdr *)&conn->req.bhs; @@ -1083,7 +1110,8 @@ static void cmnd_exec_login(struct connection *conn) login_start(conn); if (rsp->status_class) return; - if (!accounts_empty(conn->tid, ISCSI_USER_DIR_INCOMING)) + if (!accounts_empty(conn->tid, ISCSI_USER_DIR_INCOMING) && + !on_internal_portal(conn)) goto auth_err; if (rsp->status_class) return; diff --git a/iscsi-scst/usr/iscsid.h b/iscsi-scst/usr/iscsid.h index e68f67d7c..b3beb3a76 100644 --- a/iscsi-scst/usr/iscsid.h +++ b/iscsi-scst/usr/iscsid.h @@ -265,6 +265,7 @@ extern const char *get_error_str(int error); /* iscsid.c */ extern int iscsi_enabled; +extern char *internal_portal; extern int cmnd_execute(struct connection *conn); extern void cmnd_finish(struct connection *conn); diff --git a/iscsi-scst/usr/param.h b/iscsi-scst/usr/param.h index 9c9c62a47..e936c2593 100644 --- a/iscsi-scst/usr/param.h +++ b/iscsi-scst/usr/param.h @@ -21,6 +21,7 @@ #define ISCSI_ENABLED_ATTR_NAME "enabled" #define ISCSI_ISNS_ENTITY_ATTR_NAME "isns_entity_name" #define ISCSI_ALLOWED_PORTAL_ATTR_NAME "allowed_portal" +#define ISCSI_INTERNAL_PORTAL_ATTR_NAME "internal_portal" #define ISCSI_PER_PORTAL_ACL_ATTR_NAME "per_portal_acl" #define ISCSI_TARGET_REDIRECTION_ATTR_NAME "redirect" #define ISCSI_TARGET_REDIRECTION_VALUE_TEMP "temp" diff --git a/nightly/conf/nightly.conf b/nightly/conf/nightly.conf index 841cf72f3..52537f4c2 100644 --- a/nightly/conf/nightly.conf +++ b/nightly/conf/nightly.conf @@ -3,37 +3,40 @@ ABT_DETAILS="x86_64" ABT_JOBS=5 ABT_KERNELS=" \ -6.8.7 \ +6.11 \ +6.10.10-nc \ +6.9.12-nc \ +6.8.12-nc \ 6.7.12-nc \ -6.6.28-nc \ +6.6.51-nc \ 6.5.13-nc \ 6.4.16-nc \ 6.3.13-nc \ 6.2.16-nc \ -6.1.87-nc \ +6.1.110-nc \ 6.0.19-nc \ 5.19.17-nc \ 5.18.19-nc \ 5.17.15-nc \ 5.16.20-nc \ -5.15.156-nc \ +5.15.167-nc \ 5.14.21-nc \ 5.13.19-nc \ 5.12.19-nc \ 5.11.22-nc \ -5.10.215-nc \ +5.10.226-nc \ 5.9.16-nc \ 5.8.18-nc \ 5.7.19-nc \ 5.6.19-nc \ 5.5.19-nc \ -5.4.274-nc \ +5.4.284-nc \ 5.3.18-nc \ 5.2.21-nc \ 5.1.21-nc \ 5.0.21-nc \ 4.20.17-nc \ -4.19.312-nc \ +4.19.322-nc \ 4.18.20-nc \ 4.17.19-nc \ 4.16.18-nc \ @@ -63,7 +66,8 @@ ABT_KERNELS=" \ 3.12.74-nc \ 3.11.10-nc \ 3.10.108-nc \ -5.14.0-362.24.1.el9_3^AlmaLinux^9.3-nc \ +5.14.0-427.33.1.el9_4^AlmaLinux^9.4-nc \ +5.14.0-362.24.2.el9_3^AlmaLinux^9.3-nc \ 5.14.0-284.30.1.el9_2^AlmaLinux^9.2-nc \ 5.14.0-162.23.1.el9_1^AlmaLinux^9.1-nc \ 5.14.0-70.30.1.el9_0^AlmaLinux^9.0-nc \ @@ -77,18 +81,18 @@ ABT_KERNELS=" \ 4.18.0-193.28.1.el8_2^CentOS^8.2.2004-nc \ 4.18.0-147.8.1.el8_1^CentOS^8.1.1911-nc \ 4.18.0-80.11.2.el8_0^CentOS^8.0.1905-nc \ -3.10.0-1160.108.1.el7^CentOS^7.9.2009-nc \ +3.10.0-1160.118.1.el7^CentOS^7.9.2009-nc \ 3.10.0-1127.19.1.el7^CentOS^7.8.2003-nc \ 3.10.0-1062.18.1.el7^CentOS^7.7.1908-nc \ 3.10.0-957.27.2.el7^CentOS^7.6.1810-nc \ 3.10.0-862.14.4.el7^CentOS^7.5.1804-nc \ -5.15.0-205.149.5.1.el9uek^UEK^9-nc \ -5.15.0-205.149.5.1.el8uek^UEK^8-nc \ -5.4.17-2136.330.7.1.el8uek^UEK^8-nc \ +5.15.0-210.163.7.el9uek^UEK^9-nc \ +5.15.0-210.163.7.el8uek^UEK^8-nc \ +5.4.17-2136.335.4.el8uek^UEK^8-nc \ 5.4.17-2102.206.1.el8uek^UEK^8-nc \ 5.4.17-2036.104.5.el8uek^UEK^8-nc \ 5.4.17-2011.7.4.el8uek^UEK^8-nc \ -5.4.17-2136.330.7.1.el7uek^UEK^7-nc \ +5.4.17-2136.335.4.el7uek^UEK^7-nc \ 5.4.17-2102.206.1.el7uek^UEK^7-nc \ 5.4.17-2036.104.5.el7uek^UEK^7-nc \ 5.4.17-2011.7.4.el7uek^UEK^7-nc \ diff --git a/qla2x00t-32gbit/include/trace/events/qla.h b/qla2x00t-32gbit/include/trace/events/qla.h index e3b470023..8708519cd 100644 --- a/qla2x00t-32gbit/include/trace/events/qla.h +++ b/qla2x00t-32gbit/include/trace/events/qla.h @@ -2,6 +2,9 @@ #if !defined(_TRACE_QLA_H_) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_QLA_H_ +#ifndef INSIDE_KERNEL_TREE +#include +#endif #include #undef TRACE_SYSTEM @@ -22,11 +25,23 @@ DECLARE_EVENT_CLASS(qla_log_event, TP_STRUCT__entry( __string(buf, buf) +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) __dynamic_array(char, msg, QLA_MSG_MAX) +#else + __vstring(msg, vaf->fmt, vaf->va) +#endif ), TP_fast_assign( +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 10, 0) __assign_str(buf, buf); +#else + __assign_str(buf); +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) vsnprintf(__get_str(msg), QLA_MSG_MAX, vaf->fmt, *vaf->va); +#else + __assign_vstr(msg, vaf->fmt, vaf->va); +#endif ), TP_printk("%s %s", __get_str(buf), __get_str(msg)) diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index cc8c98d16..315ad1d0d 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -327,7 +327,7 @@ qla2x00_process_els(BSG_JOB_TYPE *bsg_job) "request_sg_cnt=%x reply_sg_cnt=%x.\n", bsg_job->request_payload.sg_cnt, bsg_job->reply_payload.sg_cnt); - rval = -EPERM; + rval = -ENOBUFS; goto done; } @@ -3063,17 +3063,61 @@ qla24xx_bsg_request(BSG_JOB_TYPE *bsg_job) return ret; } -int -qla24xx_bsg_timeout(BSG_JOB_TYPE *bsg_job) +static bool qla_bsg_found(struct qla_qpair *qpair, BSG_JOB_TYPE *bsg_job) { + bool found = false; struct fc_bsg_reply *bsg_reply = bsg_job->reply; scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job)); struct qla_hw_data *ha = vha->hw; - srb_t *sp; - int cnt, que; + srb_t *sp = NULL; + int cnt; unsigned long flags; struct req_que *req; + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + req = qpair->req; + + for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { + sp = req->outstanding_cmds[cnt]; + if (sp && + (sp->type == SRB_CT_CMD || + sp->type == SRB_ELS_CMD_HST || + sp->type == SRB_ELS_CMD_HST_NOLOGIN) && + sp->u.bsg_job == bsg_job) { + req->outstanding_cmds[cnt] = NULL; + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + if (!ha->flags.eeh_busy && ha->isp_ops->abort_command(sp)) { + ql_log(ql_log_warn, vha, 0x7089, + "mbx abort_command failed.\n"); + bsg_reply->result = -EIO; + } else { + ql_dbg(ql_dbg_user, vha, 0x708a, + "mbx abort_command success.\n"); + bsg_reply->result = 0; + } + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); + + found = true; + goto done; + } + } + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + +done: + return found; +} + +int +qla24xx_bsg_timeout(BSG_JOB_TYPE *bsg_job) +{ + struct fc_bsg_reply *bsg_reply = bsg_job->reply; + scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job)); + struct qla_hw_data *ha = vha->hw; + int i; + struct qla_qpair *qpair; + ql_log(ql_log_info, vha, 0x708b, "%s CMD timeout. bsg ptr %p.\n", __func__, bsg_job); @@ -3083,48 +3127,23 @@ qla24xx_bsg_timeout(BSG_JOB_TYPE *bsg_job) qla_pci_set_eeh_busy(vha); } + if (qla_bsg_found(ha->base_qpair, bsg_job)) + goto done; + /* find the bsg job from the active list of commands */ - spin_lock_irqsave(&ha->hardware_lock, flags); - for (que = 0; que < ha->max_req_queues; que++) { - req = ha->req_q_map[que]; - if (!req) + for (i = 0; i < ha->max_qpairs; i++) { + qpair = vha->hw->queue_pair_map[i]; + if (!qpair) continue; - for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { - sp = req->outstanding_cmds[cnt]; - if (sp && - (sp->type == SRB_CT_CMD || - sp->type == SRB_ELS_CMD_HST || - sp->type == SRB_ELS_CMD_HST_NOLOGIN || - sp->type == SRB_FXIOCB_BCMD) && - sp->u.bsg_job == bsg_job) { - req->outstanding_cmds[cnt] = NULL; - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - if (!ha->flags.eeh_busy && ha->isp_ops->abort_command(sp)) { - ql_log(ql_log_warn, vha, 0x7089, - "mbx abort_command failed.\n"); - bsg_reply->result = -EIO; - } else { - ql_dbg(ql_dbg_user, vha, 0x708a, - "mbx abort_command success.\n"); - bsg_reply->result = 0; - } - spin_lock_irqsave(&ha->hardware_lock, flags); - goto done; - - } - } + if (qla_bsg_found(qpair, bsg_job)) + goto done; } - spin_unlock_irqrestore(&ha->hardware_lock, flags); + ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n"); bsg_reply->result = -ENXIO; - return 0; done: - spin_unlock_irqrestore(&ha->hardware_lock, flags); - /* ref: INIT */ - kref_put(&sp->cmd_kref, qla2x00_sp_release); return 0; } diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index a777885be..733086f75 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -3365,9 +3365,20 @@ struct fab_scan_rp { u8 node_name[8]; }; +enum scan_step { + FAB_SCAN_START, + FAB_SCAN_GPNFT_FCP, + FAB_SCAN_GNNFT_FCP, + FAB_SCAN_GPNFT_NVME, + FAB_SCAN_GNNFT_NVME, +}; + struct fab_scan { struct fab_scan_rp *l; u32 size; + u32 rscn_gen_start; + u32 rscn_gen_end; + enum scan_step step; u16 scan_retry; #define MAX_SCAN_RETRIES 5 enum scan_flags_t scan_flags; @@ -3593,9 +3604,8 @@ enum qla_work_type { QLA_EVT_RELOGIN, QLA_EVT_ASYNC_PRLO, QLA_EVT_ASYNC_PRLO_DONE, - QLA_EVT_GPNFT, - QLA_EVT_GPNFT_DONE, - QLA_EVT_GNNFT_DONE, + QLA_EVT_SCAN_CMD, + QLA_EVT_SCAN_FINISH, QLA_EVT_GFPNID, QLA_EVT_SP_RETRY, QLA_EVT_IIDMA, @@ -5088,6 +5098,7 @@ typedef struct scsi_qla_host { /* Counter to detect races between ELS and RSCN events */ atomic_t generation_tick; + atomic_t rscn_gen; /* Time when global fcport update has been scheduled */ int total_fcport_update_gen; /* List of pending LOGOs, protected by tgt_mutex */ diff --git a/qla2x00t-32gbit/qla_dfs.c b/qla2x00t-32gbit/qla_dfs.c index a4715de9c..51e1d145c 100644 --- a/qla2x00t-32gbit/qla_dfs.c +++ b/qla2x00t-32gbit/qla_dfs.c @@ -278,7 +278,7 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) seq_printf(s, "Driver: estimate iocb used [%d] high water limit [%d]\n", iocbs_used, ha->base_qpair->fwres.iocbs_limit); - seq_printf(s, "estimate exchange used[%d] high water limit [%d] n", + seq_printf(s, "estimate exchange used[%d] high water limit [%d]\n", exch_used, ha->base_qpair->fwres.exch_limit); if (ql2xenforce_iocb_limit == 2) { diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 355c64a65..dad7b6697 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -737,9 +737,9 @@ int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *); void qla24xx_handle_gpsc_event(scsi_qla_host_t *, struct event_arg *); int qla2x00_mgmt_svr_login(scsi_qla_host_t *); int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport, bool); -int qla24xx_async_gpnft(scsi_qla_host_t *, u8, srb_t *); -void qla24xx_async_gpnft_done(scsi_qla_host_t *, srb_t *); -void qla24xx_async_gnnft_done(scsi_qla_host_t *, srb_t *); +int qla_fab_async_scan(scsi_qla_host_t *, srb_t *); +void qla_fab_scan_start(struct scsi_qla_host *); +void qla_fab_scan_finish(scsi_qla_host_t *, srb_t *); int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *); void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *); diff --git a/qla2x00t-32gbit/qla_gs.c b/qla2x00t-32gbit/qla_gs.c index 1cf9d200d..d2bddca70 100644 --- a/qla2x00t-32gbit/qla_gs.c +++ b/qla2x00t-32gbit/qla_gs.c @@ -1710,7 +1710,7 @@ qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries, eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION); alen = scnprintf( eiter->a.orom_version, sizeof(eiter->a.orom_version), - "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]); + "%d.%02d", ha->efi_revision[1], ha->efi_revision[0]); alen += FDMI_ATTR_ALIGNMENT(alen); alen += FDMI_ATTR_TYPELEN(eiter); eiter->len = cpu_to_be16(alen); @@ -3168,7 +3168,30 @@ static int qla2x00_is_a_vp(scsi_qla_host_t *vha, u64 wwn) return rc; } -void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) +static bool qla_ok_to_clear_rscn(scsi_qla_host_t *vha, fc_port_t *fcport) +{ + u32 rscn_gen; + + rscn_gen = atomic_read(&vha->rscn_gen); + ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2017, + "%s %d %8phC rscn_gen %x start %x end %x current %x\n", + __func__, __LINE__, fcport->port_name, fcport->rscn_gen, + vha->scan.rscn_gen_start, vha->scan.rscn_gen_end, rscn_gen); + + if (val_is_in_range(fcport->rscn_gen, vha->scan.rscn_gen_start, + vha->scan.rscn_gen_end)) + /* rscn came in before fabric scan */ + return true; + + if (val_is_in_range(fcport->rscn_gen, vha->scan.rscn_gen_end, rscn_gen)) + /* rscn came in after fabric scan */ + return false; + + /* rare: fcport's scan_needed + rscn_gen must be stale */ + return true; +} + +void qla_fab_scan_finish(scsi_qla_host_t *vha, srb_t *sp) { fc_port_t *fcport; u32 i, rc; @@ -3281,10 +3304,10 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) (fcport->scan_needed && fcport->port_type != FCT_INITIATOR && fcport->port_type != FCT_NVME_INITIATOR)) { + fcport->scan_needed = 0; qlt_schedule_sess_for_deletion(fcport); } fcport->d_id.b24 = rp->id.b24; - fcport->scan_needed = 0; break; } @@ -3325,7 +3348,9 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) do_delete = true; } - fcport->scan_needed = 0; + if (qla_ok_to_clear_rscn(vha, fcport)) + fcport->scan_needed = 0; + if (((qla_dual_mode_enabled(vha) || qla_ini_mode_enabled(vha)) && atomic_read(&fcport->state) == FCS_ONLINE) || @@ -3355,7 +3380,9 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) fcport->port_name, fcport->loop_id, fcport->login_retry); } - fcport->scan_needed = 0; + + if (qla_ok_to_clear_rscn(vha, fcport)) + fcport->scan_needed = 0; qla24xx_fcport_handle_login(vha, fcport); } } @@ -3379,14 +3406,11 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) } } -static int qla2x00_post_gnnft_gpnft_done_work(struct scsi_qla_host *vha, +static int qla2x00_post_next_scan_work(struct scsi_qla_host *vha, srb_t *sp, int cmd) { struct qla_work_evt *e; - if (cmd != QLA_EVT_GPNFT_DONE && cmd != QLA_EVT_GNNFT_DONE) - return QLA_PARAMETER_ERROR; - e = qla2x00_alloc_work(vha, cmd); if (!e) return QLA_FUNCTION_FAILED; @@ -3396,37 +3420,15 @@ static int qla2x00_post_gnnft_gpnft_done_work(struct scsi_qla_host *vha, return qla2x00_post_work(vha, e); } -static int qla2x00_post_nvme_gpnft_work(struct scsi_qla_host *vha, - srb_t *sp, int cmd) -{ - struct qla_work_evt *e; - - if (cmd != QLA_EVT_GPNFT) - return QLA_PARAMETER_ERROR; - - e = qla2x00_alloc_work(vha, cmd); - if (!e) - return QLA_FUNCTION_FAILED; - - e->u.gpnft.fc4_type = FC4_TYPE_NVME; - e->u.gpnft.sp = sp; - - return qla2x00_post_work(vha, e); -} - static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha, struct srb *sp) { struct qla_hw_data *ha = vha->hw; int num_fibre_dev = ha->max_fibre_devices; - struct ct_sns_req *ct_req = - (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req; struct ct_sns_gpnft_rsp *ct_rsp = (struct ct_sns_gpnft_rsp *)sp->u.iocb_cmd.u.ctarg.rsp; struct ct_sns_gpn_ft_data *d; struct fab_scan_rp *rp; - u16 cmd = be16_to_cpu(ct_req->command); - u8 fc4_type = sp->gen2; int i, j, k; port_id_t id; u8 found; @@ -3445,85 +3447,83 @@ static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha, if (id.b24 == 0 || wwn == 0) continue; - if (fc4_type == FC4_TYPE_FCP_SCSI) { - if (cmd == GPN_FT_CMD) { - rp = &vha->scan.l[j]; - rp->id = id; - memcpy(rp->port_name, d->port_name, 8); - j++; - rp->fc4type = FS_FC4TYPE_FCP; - } else { - for (k = 0; k < num_fibre_dev; k++) { - rp = &vha->scan.l[k]; - if (id.b24 == rp->id.b24) { - memcpy(rp->node_name, - d->port_name, 8); - break; - } + ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2025, + "%s %06x %8ph \n", + __func__, id.b24, d->port_name); + + switch (vha->scan.step) { + case FAB_SCAN_GPNFT_FCP: + rp = &vha->scan.l[j]; + rp->id = id; + memcpy(rp->port_name, d->port_name, 8); + j++; + rp->fc4type = FS_FC4TYPE_FCP; + break; + case FAB_SCAN_GNNFT_FCP: + for (k = 0; k < num_fibre_dev; k++) { + rp = &vha->scan.l[k]; + if (id.b24 == rp->id.b24) { + memcpy(rp->node_name, + d->port_name, 8); + break; } } - } else { - /* Search if the fibre device supports FC4_TYPE_NVME */ - if (cmd == GPN_FT_CMD) { - found = 0; - - for (k = 0; k < num_fibre_dev; k++) { - rp = &vha->scan.l[k]; - if (!memcmp(rp->port_name, - d->port_name, 8)) { - /* - * Supports FC-NVMe & FCP - */ - rp->fc4type |= FS_FC4TYPE_NVME; - found = 1; - break; - } + break; + case FAB_SCAN_GPNFT_NVME: + found = 0; + + for (k = 0; k < num_fibre_dev; k++) { + rp = &vha->scan.l[k]; + if (!memcmp(rp->port_name, d->port_name, 8)) { + /* + * Supports FC-NVMe & FCP + */ + rp->fc4type |= FS_FC4TYPE_NVME; + found = 1; + break; } + } - /* We found new FC-NVMe only port */ - if (!found) { - for (k = 0; k < num_fibre_dev; k++) { - rp = &vha->scan.l[k]; - if (wwn_to_u64(rp->port_name)) { - continue; - } else { - rp->id = id; - memcpy(rp->port_name, - d->port_name, 8); - rp->fc4type = - FS_FC4TYPE_NVME; - break; - } - } - } - } else { + /* We found new FC-NVMe only port */ + if (!found) { for (k = 0; k < num_fibre_dev; k++) { rp = &vha->scan.l[k]; - if (id.b24 == rp->id.b24) { - memcpy(rp->node_name, - d->port_name, 8); + if (wwn_to_u64(rp->port_name)) { + continue; + } else { + rp->id = id; + memcpy(rp->port_name, d->port_name, 8); + rp->fc4type = FS_FC4TYPE_NVME; break; } } } + break; + case FAB_SCAN_GNNFT_NVME: + for (k = 0; k < num_fibre_dev; k++) { + rp = &vha->scan.l[k]; + if (id.b24 == rp->id.b24) { + memcpy(rp->node_name, d->port_name, 8); + break; + } + } + break; + default: + break; } } } -static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res) +static void qla_async_scan_sp_done(srb_t *sp, int res) { struct scsi_qla_host *vha = sp->vha; - struct ct_sns_req *ct_req = - (struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req; - u16 cmd = be16_to_cpu(ct_req->command); - u8 fc4_type = sp->gen2; unsigned long flags; int rc; /* gen2 field is holding the fc4type */ - ql_dbg(ql_dbg_disc, vha, 0xffff, - "Async done-%s res %x FC4Type %x\n", - sp->name, res, sp->gen2); + ql_dbg(ql_dbg_disc, vha, 0x2026, + "Async done-%s res %x step %x\n", + sp->name, res, vha->scan.step); sp->rc = res; if (res) { @@ -3547,8 +3547,7 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res) * sp for GNNFT_DONE work. This will allow all * the resource to get freed up. */ - rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp, - QLA_EVT_GNNFT_DONE); + rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH); if (rc) { /* Cleanup here to prevent memory leak */ qla24xx_sp_unmap(vha, sp); @@ -3573,28 +3572,30 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res) qla2x00_find_free_fcp_nvme_slot(vha, sp); - if ((fc4_type == FC4_TYPE_FCP_SCSI) && vha->flags.nvme_enabled && - cmd == GNN_FT_CMD) { - spin_lock_irqsave(&vha->work_lock, flags); - vha->scan.scan_flags &= ~SF_SCANNING; - spin_unlock_irqrestore(&vha->work_lock, flags); + spin_lock_irqsave(&vha->work_lock, flags); + vha->scan.scan_flags &= ~SF_SCANNING; + spin_unlock_irqrestore(&vha->work_lock, flags); - sp->rc = res; - rc = qla2x00_post_nvme_gpnft_work(vha, sp, QLA_EVT_GPNFT); - if (rc) { - qla24xx_sp_unmap(vha, sp); - set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); - set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); - } - return; - } + switch (vha->scan.step) { + case FAB_SCAN_GPNFT_FCP: + case FAB_SCAN_GPNFT_NVME: + rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_CMD); + break; + case FAB_SCAN_GNNFT_FCP: + if (vha->flags.nvme_enabled) + rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_CMD); + else + rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH); - if (cmd == GPN_FT_CMD) { - rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp, - QLA_EVT_GPNFT_DONE); - } else { - rc = qla2x00_post_gnnft_gpnft_done_work(vha, sp, - QLA_EVT_GNNFT_DONE); + break; + case FAB_SCAN_GNNFT_NVME: + rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH); + break; + default: + /* should not be here */ + WARN_ON(1); + rc = QLA_FUNCTION_FAILED; + break; } if (rc) { @@ -3605,127 +3606,16 @@ static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res) } } -/* - * Get WWNN list for fc4_type - * - * It is assumed the same SRB is re-used from GPNFT to avoid - * mem free & re-alloc - */ -static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp, - u8 fc4_type) -{ - int rval = QLA_FUNCTION_FAILED; - struct ct_sns_req *ct_req; - struct ct_sns_pkt *ct_sns; - unsigned long flags; - - if (!vha->flags.online) { - spin_lock_irqsave(&vha->work_lock, flags); - vha->scan.scan_flags &= ~SF_SCANNING; - spin_unlock_irqrestore(&vha->work_lock, flags); - goto done_free_sp; - } - - if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) { - ql_log(ql_log_warn, vha, 0xffff, - "%s: req %p rsp %p are not setup\n", - __func__, sp->u.iocb_cmd.u.ctarg.req, - sp->u.iocb_cmd.u.ctarg.rsp); - spin_lock_irqsave(&vha->work_lock, flags); - vha->scan.scan_flags &= ~SF_SCANNING; - spin_unlock_irqrestore(&vha->work_lock, flags); - WARN_ON(1); - set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); - set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); - goto done_free_sp; - } - - ql_dbg(ql_dbg_disc, vha, 0xfffff, - "%s: FC4Type %x, CT-PASSTHRU %s command ctarg rsp size %d, ctarg req size %d\n", - __func__, fc4_type, sp->name, sp->u.iocb_cmd.u.ctarg.rsp_size, - sp->u.iocb_cmd.u.ctarg.req_size); - - sp->type = SRB_CT_PTHRU_CMD; - sp->name = "gnnft"; - sp->gen1 = vha->hw->base_qpair->chip_reset; - sp->gen2 = fc4_type; - qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2, - qla2x00_async_gpnft_gnnft_sp_done); - - memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size); - memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size); - - ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req; - /* CT_IU preamble */ - ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD, - sp->u.iocb_cmd.u.ctarg.rsp_size); - - /* GPN_FT req */ - ct_req->req.gpn_ft.port_type = fc4_type; - - sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE; - sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS; - - ql_dbg(ql_dbg_disc, vha, 0xffff, - "Async-%s hdl=%x FC4Type %x.\n", sp->name, - sp->handle, ct_req->req.gpn_ft.port_type); - - rval = qla2x00_start_sp(sp); - if (rval != QLA_SUCCESS) { - goto done_free_sp; - } - - return rval; - -done_free_sp: - if (sp->u.iocb_cmd.u.ctarg.req) { - dma_free_coherent(&vha->hw->pdev->dev, - sp->u.iocb_cmd.u.ctarg.req_allocated_size, - sp->u.iocb_cmd.u.ctarg.req, - sp->u.iocb_cmd.u.ctarg.req_dma); - sp->u.iocb_cmd.u.ctarg.req = NULL; - } - if (sp->u.iocb_cmd.u.ctarg.rsp) { - dma_free_coherent(&vha->hw->pdev->dev, - sp->u.iocb_cmd.u.ctarg.rsp_allocated_size, - sp->u.iocb_cmd.u.ctarg.rsp, - sp->u.iocb_cmd.u.ctarg.rsp_dma); - sp->u.iocb_cmd.u.ctarg.rsp = NULL; - } - /* ref: INIT */ - kref_put(&sp->cmd_kref, qla2x00_sp_release); - - spin_lock_irqsave(&vha->work_lock, flags); - vha->scan.scan_flags &= ~SF_SCANNING; - if (vha->scan.scan_flags == 0) { - ql_dbg(ql_dbg_disc, vha, 0xffff, - "%s: schedule\n", __func__); - vha->scan.scan_flags |= SF_QUEUED; - schedule_delayed_work(&vha->scan.scan_work, 5); - } - spin_unlock_irqrestore(&vha->work_lock, flags); - - - return rval; -} /* GNNFT */ - -void qla24xx_async_gpnft_done(scsi_qla_host_t *vha, srb_t *sp) -{ - ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff, - "%s enter\n", __func__); - qla24xx_async_gnnft(vha, sp, sp->gen2); -} - /* Get WWPN list for certain fc4_type */ -int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) +int qla_fab_async_scan(scsi_qla_host_t *vha, srb_t *sp) { int rval = QLA_FUNCTION_FAILED; struct ct_sns_req *ct_req; struct ct_sns_pkt *ct_sns; - u32 rspsz; + u32 rspsz = 0; unsigned long flags; - ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff, + ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x200c, "%s enter\n", __func__); if (!vha->flags.online) @@ -3734,22 +3624,21 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) spin_lock_irqsave(&vha->work_lock, flags); if (vha->scan.scan_flags & SF_SCANNING) { spin_unlock_irqrestore(&vha->work_lock, flags); - ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff, + ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2012, "%s: scan active\n", __func__); return rval; } vha->scan.scan_flags |= SF_SCANNING; + if (!sp) + vha->scan.step = FAB_SCAN_START; + spin_unlock_irqrestore(&vha->work_lock, flags); - if (fc4_type == FC4_TYPE_FCP_SCSI) { - ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff, + switch (vha->scan.step) { + case FAB_SCAN_START: + ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2018, "%s: Performing FCP Scan\n", __func__); - if (sp) { - /* ref: INIT */ - kref_put(&sp->cmd_kref, qla2x00_sp_release); - } - /* ref: INIT */ sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL); if (!sp) { @@ -3765,7 +3654,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) GFP_KERNEL); sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt); if (!sp->u.iocb_cmd.u.ctarg.req) { - ql_log(ql_log_warn, vha, 0xffff, + ql_log(ql_log_warn, vha, 0x201a, "Failed to allocate ct_sns request.\n"); spin_lock_irqsave(&vha->work_lock, flags); vha->scan.scan_flags &= ~SF_SCANNING; @@ -3773,7 +3662,6 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) qla2x00_rel_sp(sp); return rval; } - sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE; rspsz = sizeof(struct ct_sns_gpnft_rsp) + vha->hw->max_fibre_devices * @@ -3785,7 +3673,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) GFP_KERNEL); sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = rspsz; if (!sp->u.iocb_cmd.u.ctarg.rsp) { - ql_log(ql_log_warn, vha, 0xffff, + ql_log(ql_log_warn, vha, 0x201b, "Failed to allocate ct_sns request.\n"); spin_lock_irqsave(&vha->work_lock, flags); vha->scan.scan_flags &= ~SF_SCANNING; @@ -3805,35 +3693,95 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) "%s scan list size %d\n", __func__, vha->scan.size); memset(vha->scan.l, 0, vha->scan.size); - } else if (!sp) { - ql_dbg(ql_dbg_disc, vha, 0xffff, - "NVME scan did not provide SP\n"); + + vha->scan.step = FAB_SCAN_GPNFT_FCP; + break; + case FAB_SCAN_GPNFT_FCP: + vha->scan.step = FAB_SCAN_GNNFT_FCP; + break; + case FAB_SCAN_GNNFT_FCP: + vha->scan.step = FAB_SCAN_GPNFT_NVME; + break; + case FAB_SCAN_GPNFT_NVME: + vha->scan.step = FAB_SCAN_GNNFT_NVME; + break; + case FAB_SCAN_GNNFT_NVME: + default: + /* should not be here */ + WARN_ON(1); + goto done_free_sp; + } + + if (!sp) { + ql_dbg(ql_dbg_disc, vha, 0x201c, + "scan did not provide SP\n"); return rval; } + if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) { + ql_log(ql_log_warn, vha, 0x201d, + "%s: req %p rsp %p are not setup\n", + __func__, sp->u.iocb_cmd.u.ctarg.req, + sp->u.iocb_cmd.u.ctarg.rsp); + spin_lock_irqsave(&vha->work_lock, flags); + vha->scan.scan_flags &= ~SF_SCANNING; + spin_unlock_irqrestore(&vha->work_lock, flags); + WARN_ON(1); + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + goto done_free_sp; + } + + rspsz = sp->u.iocb_cmd.u.ctarg.rsp_size; + memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size); + memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size); + sp->type = SRB_CT_PTHRU_CMD; - sp->name = "gpnft"; sp->gen1 = vha->hw->base_qpair->chip_reset; - sp->gen2 = fc4_type; qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2, - qla2x00_async_gpnft_gnnft_sp_done); - - rspsz = sp->u.iocb_cmd.u.ctarg.rsp_size; - memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size); - memset(sp->u.iocb_cmd.u.ctarg.req, 0, sp->u.iocb_cmd.u.ctarg.req_size); + qla_async_scan_sp_done); ct_sns = (struct ct_sns_pkt *)sp->u.iocb_cmd.u.ctarg.req; - /* CT_IU preamble */ - ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz); - /* GPN_FT req */ - ct_req->req.gpn_ft.port_type = fc4_type; + /* CT_IU preamble */ + switch (vha->scan.step) { + case FAB_SCAN_GPNFT_FCP: + sp->name = "gpnft"; + ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz); + ct_req->req.gpn_ft.port_type = FC4_TYPE_FCP_SCSI; + sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE; + break; + case FAB_SCAN_GNNFT_FCP: + sp->name = "gnnft"; + ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD, rspsz); + ct_req->req.gpn_ft.port_type = FC4_TYPE_FCP_SCSI; + sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE; + break; + case FAB_SCAN_GPNFT_NVME: + sp->name = "gpnft"; + ct_req = qla2x00_prep_ct_req(ct_sns, GPN_FT_CMD, rspsz); + ct_req->req.gpn_ft.port_type = FC4_TYPE_NVME; + sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE; + break; + case FAB_SCAN_GNNFT_NVME: + sp->name = "gnnft"; + ct_req = qla2x00_prep_ct_req(ct_sns, GNN_FT_CMD, rspsz); + ct_req->req.gpn_ft.port_type = FC4_TYPE_NVME; + sp->u.iocb_cmd.u.ctarg.req_size = GNN_FT_REQ_SIZE; + break; + default: + /* should not be here */ + WARN_ON(1); + goto done_free_sp; + } sp->u.iocb_cmd.u.ctarg.nport_handle = NPH_SNS; - ql_dbg(ql_dbg_disc, vha, 0xffff, - "Async-%s hdl=%x FC4Type %x.\n", sp->name, - sp->handle, ct_req->req.gpn_ft.port_type); + ql_dbg(ql_dbg_disc, vha, 0x2003, + "%s: step %d, rsp size %d, req size %d hdl %x %s FC4TYPE %x \n", + __func__, vha->scan.step, sp->u.iocb_cmd.u.ctarg.rsp_size, + sp->u.iocb_cmd.u.ctarg.req_size, sp->handle, sp->name, + ct_req->req.gpn_ft.port_type); rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { @@ -3864,7 +3812,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) spin_lock_irqsave(&vha->work_lock, flags); vha->scan.scan_flags &= ~SF_SCANNING; if (vha->scan.scan_flags == 0) { - ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff, + ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2007, "%s: Scan scheduled.\n", __func__); vha->scan.scan_flags |= SF_QUEUED; schedule_delayed_work(&vha->scan.scan_work, 5); @@ -3875,6 +3823,15 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) return rval; } +void qla_fab_scan_start(struct scsi_qla_host *vha) +{ + int rval; + + rval = qla_fab_async_scan(vha, NULL); + if (rval) + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); +} + void qla_scan_work_fn(struct work_struct *work) { struct fab_scan *s = container_of(to_delayed_work(work), diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 6a1af567e..c93e3458c 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -423,7 +423,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) sp->type = SRB_LOGOUT_CMD; sp->name = "logout"; qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2, - qla2x00_async_logout_sp_done), + qla2x00_async_logout_sp_done); ql_dbg(ql_dbg_disc, vha, 0x2070, "Async-logout - hdl=%x loop-id=%x portid=%02x%02x%02x %8phC explicit %d.\n", @@ -1842,10 +1842,18 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id, return qla2x00_post_work(vha, e); } +static void qla_rscn_gen_tick(scsi_qla_host_t *vha, u32 *ret_rscn_gen) +{ + *ret_rscn_gen = atomic_inc_return(&vha->rscn_gen); + /* memory barrier */ + wmb(); +} + void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) { fc_port_t *fcport; unsigned long flags; + u32 rscn_gen; switch (ea->id.b.rsvd_1) { case RSCN_PORT_ADDR: @@ -1875,15 +1883,16 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) * Otherwise we're already in the middle of a relogin */ fcport->scan_needed = 1; - fcport->rscn_gen++; + qla_rscn_gen_tick(vha, &fcport->rscn_gen); } } else { fcport->scan_needed = 1; - fcport->rscn_gen++; + qla_rscn_gen_tick(vha, &fcport->rscn_gen); } } break; case RSCN_AREA_ADDR: + qla_rscn_gen_tick(vha, &rscn_gen); list_for_each_entry(fcport, &vha->vp_fcports, list) { if (fcport->flags & FCF_FCP2_DEVICE && atomic_read(&fcport->state) == FCS_ONLINE) @@ -1891,11 +1900,12 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) if ((ea->id.b24 & 0xffff00) == (fcport->d_id.b24 & 0xffff00)) { fcport->scan_needed = 1; - fcport->rscn_gen++; + fcport->rscn_gen = rscn_gen; } } break; case RSCN_DOM_ADDR: + qla_rscn_gen_tick(vha, &rscn_gen); list_for_each_entry(fcport, &vha->vp_fcports, list) { if (fcport->flags & FCF_FCP2_DEVICE && atomic_read(&fcport->state) == FCS_ONLINE) @@ -1903,19 +1913,20 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) if ((ea->id.b24 & 0xff0000) == (fcport->d_id.b24 & 0xff0000)) { fcport->scan_needed = 1; - fcport->rscn_gen++; + fcport->rscn_gen = rscn_gen; } } break; case RSCN_FAB_ADDR: default: + qla_rscn_gen_tick(vha, &rscn_gen); list_for_each_entry(fcport, &vha->vp_fcports, list) { if (fcport->flags & FCF_FCP2_DEVICE && atomic_read(&fcport->state) == FCS_ONLINE) continue; fcport->scan_needed = 1; - fcport->rscn_gen++; + fcport->rscn_gen = rscn_gen; } break; } @@ -1924,6 +1935,7 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea) if (vha->scan.scan_flags == 0) { ql_dbg(ql_dbg_disc, vha, 0xffff, "%s: schedule\n", __func__); vha->scan.scan_flags |= SF_QUEUED; + vha->scan.rscn_gen_start = atomic_read(&vha->rscn_gen); schedule_delayed_work(&vha->scan.scan_work, 5); } spin_unlock_irqrestore(&vha->work_lock, flags); @@ -6396,10 +6408,9 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) qlt_do_generation_tick(vha, &discovery_gen); if (USE_ASYNC_SCAN(ha)) { - rval = qla24xx_async_gpnft(vha, FC4_TYPE_FCP_SCSI, - NULL); - if (rval) - set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); + /* start of scan begins here */ + vha->scan.rscn_gen_end = atomic_read(&vha->rscn_gen); + qla_fab_scan_start(vha); } else { list_for_each_entry(fcport, &vha->vp_fcports, list) fcport->scan_state = QLA_FCPORT_SCAN; @@ -8210,15 +8221,21 @@ qla28xx_get_aux_images( struct qla27xx_image_status pri_aux_image_status, sec_aux_image_status; bool valid_pri_image = false, valid_sec_image = false; bool active_pri_image = false, active_sec_image = false; + int rc; if (!ha->flt_region_aux_img_status_pri) { ql_dbg(ql_dbg_init, vha, 0x018a, "Primary aux image not addressed\n"); goto check_sec_image; } - qla24xx_read_flash_data(vha, (uint32_t *)&pri_aux_image_status, + rc = qla24xx_read_flash_data(vha, (uint32_t *)&pri_aux_image_status, ha->flt_region_aux_img_status_pri, sizeof(pri_aux_image_status) >> 2); + if (rc) { + ql_log(ql_log_info, vha, 0x01a1, + "Unable to read Primary aux image(%x).\n", rc); + goto check_sec_image; + } qla27xx_print_image(vha, "Primary aux image", &pri_aux_image_status); if (qla28xx_check_aux_image_status_signature(&pri_aux_image_status)) { @@ -8249,9 +8266,15 @@ qla28xx_get_aux_images( goto check_valid_image; } - qla24xx_read_flash_data(vha, (uint32_t *)&sec_aux_image_status, + rc = qla24xx_read_flash_data(vha, (uint32_t *)&sec_aux_image_status, ha->flt_region_aux_img_status_sec, sizeof(sec_aux_image_status) >> 2); + if (rc) { + ql_log(ql_log_info, vha, 0x01a2, + "Unable to read Secondary aux image(%x).\n", rc); + goto check_valid_image; + } + qla27xx_print_image(vha, "Secondary aux image", &sec_aux_image_status); if (qla28xx_check_aux_image_status_signature(&sec_aux_image_status)) { @@ -8309,6 +8332,7 @@ qla27xx_get_active_image(struct scsi_qla_host *vha, struct qla27xx_image_status pri_image_status, sec_image_status; bool valid_pri_image = false, valid_sec_image = false; bool active_pri_image = false, active_sec_image = false; + int rc; if (!ha->flt_region_img_status_pri) { ql_dbg(ql_dbg_init, vha, 0x018a, "Primary image not addressed\n"); @@ -8350,8 +8374,14 @@ qla27xx_get_active_image(struct scsi_qla_host *vha, goto check_valid_image; } - qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status), + rc = qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status), ha->flt_region_img_status_sec, sizeof(sec_image_status) >> 2); + if (rc) { + ql_log(ql_log_info, vha, 0x01a3, + "Unable to read Secondary image status(%x).\n", rc); + goto check_valid_image; + } + qla27xx_print_image(vha, "Secondary image", &sec_image_status); if (qla27xx_check_image_status_signature(&sec_image_status)) { @@ -8423,11 +8453,10 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, "FW: Loading firmware from flash (%x).\n", faddr); dcode = (uint32_t *)req->ring; - qla24xx_read_flash_data(vha, dcode, faddr, 8); - if (qla24xx_risc_firmware_invalid(dcode)) { + rval = qla24xx_read_flash_data(vha, dcode, faddr, 8); + if (rval || qla24xx_risc_firmware_invalid(dcode)) { ql_log(ql_log_fatal, vha, 0x008c, - "Unable to verify the integrity of flash firmware " - "image.\n"); + "Unable to verify the integrity of flash firmware image (rval %x).\n", rval); ql_log(ql_log_fatal, vha, 0x008d, "Firmware data: %08x %08x %08x %08x.\n", dcode[0], dcode[1], dcode[2], dcode[3]); @@ -8441,7 +8470,12 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, for (j = 0; j < segments; j++) { ql_dbg(ql_dbg_init, vha, 0x008d, "-> Loading segment %u...\n", j); - qla24xx_read_flash_data(vha, dcode, faddr, 10); + rval = qla24xx_read_flash_data(vha, dcode, faddr, 10); + if (rval) { + ql_log(ql_log_fatal, vha, 0x016a, + "-> Unable to read segment addr + size .\n"); + return QLA_FUNCTION_FAILED; + } risc_addr = be32_to_cpu((__force __be32)dcode[2]); risc_size = be32_to_cpu((__force __be32)dcode[3]); if (!*srisc_addr) { @@ -8457,7 +8491,13 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, ql_dbg(ql_dbg_init, vha, 0x008e, "-> Loading fragment %u: %#x <- %#x (%#lx dwords)...\n", fragment, risc_addr, faddr, dlen); - qla24xx_read_flash_data(vha, dcode, faddr, dlen); + rval = qla24xx_read_flash_data(vha, dcode, faddr, dlen); + if (rval) { + ql_log(ql_log_fatal, vha, 0x016b, + "-> Unable to read fragment(faddr %#x dlen %#lx).\n", + faddr, dlen); + return QLA_FUNCTION_FAILED; + } for (i = 0; i < dlen; i++) dcode[i] = swab32(dcode[i]); @@ -8486,7 +8526,14 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, fwdt->length = 0; dcode = (uint32_t *)req->ring; - qla24xx_read_flash_data(vha, dcode, faddr, 7); + + rval = qla24xx_read_flash_data(vha, dcode, faddr, 7); + if (rval) { + ql_log(ql_log_fatal, vha, 0x016c, + "-> Unable to read template size.\n"); + goto failed; + } + risc_size = be32_to_cpu((__force __be32)dcode[2]); ql_dbg(ql_dbg_init, vha, 0x0161, "-> fwdt%u template array at %#x (%#x dwords)\n", @@ -8512,11 +8559,12 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, } dcode = fwdt->template; - qla24xx_read_flash_data(vha, dcode, faddr, risc_size); + rval = qla24xx_read_flash_data(vha, dcode, faddr, risc_size); - if (!qla27xx_fwdt_template_valid(dcode)) { + if (rval || !qla27xx_fwdt_template_valid(dcode)) { ql_log(ql_log_warn, vha, 0x0165, - "-> fwdt%u failed template validate\n", j); + "-> fwdt%u failed template validate (rval %x)\n", + j, rval); goto failed; } diff --git a/qla2x00t-32gbit/qla_inline.h b/qla2x00t-32gbit/qla_inline.h index 874618471..ebb33cfe7 100644 --- a/qla2x00t-32gbit/qla_inline.h +++ b/qla2x00t-32gbit/qla_inline.h @@ -643,3 +643,11 @@ static inline int qla_mapq_alloc_qp_cpu_map(struct qla_hw_data *ha) } return 0; } + +static inline bool val_is_in_range(u32 val, u32 start, u32 end) +{ + if (val >= start && val <= end) + return true; + else + return false; +} diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index a6209b2f2..913152b7d 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -3037,12 +3037,6 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, } } -struct scsi_dif_tuple { - __be16 guard; /* Checksum */ - __be16 app_tag; /* APPL identifier */ - __be32 ref_tag; /* Target LBA or indirect LBA */ -}; - /* * Checks the guard or meta-data for the type of error * detected by the HBA. In case of errors, we set the diff --git a/qla2x00t-32gbit/qla_mid.c b/qla2x00t-32gbit/qla_mid.c index b67416951..76703f270 100644 --- a/qla2x00t-32gbit/qla_mid.c +++ b/qla2x00t-32gbit/qla_mid.c @@ -180,7 +180,7 @@ qla24xx_disable_vp(scsi_qla_host_t *vha) atomic_set(&vha->loop_state, LOOP_DOWN); atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); list_for_each_entry(fcport, &vha->vp_fcports, list) - fcport->logout_on_delete = 0; + fcport->logout_on_delete = 1; if (!vha->hw->flags.edif_enabled) qla2x00_wait_for_sess_deletion(vha); diff --git a/qla2x00t-32gbit/qla_mr.c b/qla2x00t-32gbit/qla_mr.c index ba12fdc84..08c5fa6c2 100644 --- a/qla2x00t-32gbit/qla_mr.c +++ b/qla2x00t-32gbit/qla_mr.c @@ -1919,10 +1919,8 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) if (fx_type == FXDISC_GET_CONFIG_INFO) { struct config_info_data *pinfo = (struct config_info_data *) fdisc->u.fxiocb.rsp_addr; - strscpy(vha->hw->model_number, pinfo->model_num, - ARRAY_SIZE(vha->hw->model_number)); - strscpy(vha->hw->model_desc, pinfo->model_description, - ARRAY_SIZE(vha->hw->model_desc)); + memtostr(vha->hw->model_number, pinfo->model_num); + memtostr(vha->hw->model_desc, pinfo->model_description); memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name, sizeof(vha->hw->mr.symbolic_name)); memcpy(&vha->hw->mr.serial_num, pinfo->serial_num, diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index e0a9a4f65..038c10eb6 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -56,7 +56,10 @@ int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport) return 0; } - if (!vha->nvme_local_port && qla_nvme_register_hba(vha)) + if (qla_nvme_register_hba(vha)) + return 0; + + if (!vha->nvme_local_port) return 0; if (!(fcport->nvme_prli_service_param & diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 20742d26b..31dc333f4 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -1920,14 +1920,9 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { sp = req->outstanding_cmds[cnt]; if (sp) { - /* - * perform lockless completion during driver unload - */ if (qla2x00_chip_is_down(vha)) { req->outstanding_cmds[cnt] = NULL; - spin_unlock_irqrestore(qp->qp_lock_ptr, flags); sp->done(sp, res); - spin_lock_irqsave(qp->qp_lock_ptr, flags); continue; } @@ -2002,8 +1997,10 @@ qla2xxx_slave_configure(struct scsi_device *sdev) scsi_qla_host_t *vha = shost_priv(sdev->host); struct req_que *req = vha->req; +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 10, 0) if (IS_T10_PI_CAPABLE(vha->hw)) blk_queue_update_dma_alignment(sdev->request_queue, 0x7); +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) scsi_adjust_queue_depth(sdev, 0, req->max_q_depth); @@ -3637,6 +3634,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) QLA_SG_ALL : 128; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 10, 0) + if (IS_T10_PI_CAPABLE(base_vha->hw)) + host->dma_alignment = 0x7; +#endif + ret = scsi_add_host(host, &pdev->dev); if (ret) goto probe_failed; @@ -4760,7 +4762,7 @@ static void qla2x00_number_of_exch(scsi_qla_host_t *vha, u32 *ret_cnt, u16 max_cnt) { u32 temp; - struct init_cb_81xx *icb = (struct init_cb_81xx *)&vha->hw->init_cb; + struct init_cb_81xx *icb = (struct init_cb_81xx *)vha->hw->init_cb; *ret_cnt = FW_DEF_EXCHANGES_CNT; if (max_cnt > vha->hw->max_exchg) @@ -5636,15 +5638,11 @@ qla2x00_do_work(struct scsi_qla_host *vha) qla2x00_async_prlo_done(vha, e->u.logio.fcport, e->u.logio.data); break; - case QLA_EVT_GPNFT: - qla24xx_async_gpnft(vha, e->u.gpnft.fc4_type, - e->u.gpnft.sp); - break; - case QLA_EVT_GPNFT_DONE: - qla24xx_async_gpnft_done(vha, e->u.iosb.sp); + case QLA_EVT_SCAN_CMD: + qla_fab_async_scan(vha, e->u.iosb.sp); break; - case QLA_EVT_GNNFT_DONE: - qla24xx_async_gnnft_done(vha, e->u.iosb.sp); + case QLA_EVT_SCAN_FINISH: + qla_fab_scan_finish(vha, e->u.iosb.sp); break; case QLA_EVT_GFPNID: qla24xx_async_gfpnid(vha, e->u.fcport.fcport); @@ -8302,9 +8300,6 @@ MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); static struct pci_driver qla2xxx_pci_driver = { .name = QLA2XXX_DRIVER_NAME, - .driver = { - .owner = THIS_MODULE, - }, .id_table = qla2xxx_pci_tbl, .probe = qla2x00_probe_one, .remove = qla2x00_remove_one, diff --git a/qla2x00t-32gbit/qla_sup.c b/qla2x00t-32gbit/qla_sup.c index c092a6b1c..6d16546e1 100644 --- a/qla2x00t-32gbit/qla_sup.c +++ b/qla2x00t-32gbit/qla_sup.c @@ -555,6 +555,7 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) struct qla_flt_location *fltl = (void *)req->ring; uint32_t *dcode = (uint32_t *)req->ring; uint8_t *buf = (void *)req->ring, *bcode, last_image; + int rc; /* * FLT-location structure resides after the last PCI region. @@ -584,14 +585,24 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) pcihdr = 0; do { /* Verify PCI expansion ROM header. */ - qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20); + rc = qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20); + if (rc) { + ql_log(ql_log_info, vha, 0x016d, + "Unable to read PCI Expansion Rom Header (%x).\n", rc); + return QLA_FUNCTION_FAILED; + } bcode = buf + (pcihdr % 4); if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) goto end; /* Locate PCI data structure. */ pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); - qla24xx_read_flash_data(vha, dcode, pcids >> 2, 0x20); + rc = qla24xx_read_flash_data(vha, dcode, pcids >> 2, 0x20); + if (rc) { + ql_log(ql_log_info, vha, 0x0179, + "Unable to read PCI Data Structure (%x).\n", rc); + return QLA_FUNCTION_FAILED; + } bcode = buf + (pcihdr % 4); /* Validate signature of PCI data structure. */ @@ -606,7 +617,12 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start) } while (!last_image); /* Now verify FLT-location structure. */ - qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, sizeof(*fltl) >> 2); + rc = qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, sizeof(*fltl) >> 2); + if (rc) { + ql_log(ql_log_info, vha, 0x017a, + "Unable to read FLT (%x).\n", rc); + return QLA_FUNCTION_FAILED; + } if (memcmp(fltl->sig, "QFLT", 4)) goto end; @@ -2605,13 +2621,18 @@ qla24xx_read_optrom_data(struct scsi_qla_host *vha, void *buf, uint32_t offset, uint32_t length) { struct qla_hw_data *ha = vha->hw; + int rc; /* Suspend HBA. */ scsi_block_requests(vha->host); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with read. */ - qla24xx_read_flash_data(vha, buf, offset >> 2, length >> 2); + rc = qla24xx_read_flash_data(vha, buf, offset >> 2, length >> 2); + if (rc) { + ql_log(ql_log_info, vha, 0x01a0, + "Unable to perform optrom read(%x).\n", rc); + } /* Resume HBA. */ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); @@ -3412,7 +3433,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) struct active_regions active_regions = { }; if (IS_P3P_TYPE(ha)) - return ret; + return QLA_SUCCESS; if (!mbuf) return QLA_FUNCTION_FAILED; @@ -3432,20 +3453,31 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) do { /* Verify PCI expansion ROM header. */ - qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20); + ret = qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20); + if (ret) { + ql_log(ql_log_info, vha, 0x017d, + "Unable to read PCI EXP Rom Header(%x).\n", ret); + return QLA_FUNCTION_FAILED; + } + bcode = mbuf + (pcihdr % 4); if (memcmp(bcode, "\x55\xaa", 2)) { /* No signature */ ql_log(ql_log_fatal, vha, 0x0059, "No matching ROM signature.\n"); - ret = QLA_FUNCTION_FAILED; - break; + return QLA_FUNCTION_FAILED; } /* Locate PCI data structure. */ pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); - qla24xx_read_flash_data(vha, dcode, pcids >> 2, 0x20); + ret = qla24xx_read_flash_data(vha, dcode, pcids >> 2, 0x20); + if (ret) { + ql_log(ql_log_info, vha, 0x018e, + "Unable to read PCI Data Structure (%x).\n", ret); + return QLA_FUNCTION_FAILED; + } + bcode = mbuf + (pcihdr % 4); /* Validate signature of PCI data structure. */ @@ -3454,8 +3486,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) ql_log(ql_log_fatal, vha, 0x005a, "PCI data struct not found pcir_adr=%x.\n", pcids); ql_dump_buffer(ql_dbg_init, vha, 0x0059, dcode, 32); - ret = QLA_FUNCTION_FAILED; - break; + return QLA_FUNCTION_FAILED; } /* Read version */ @@ -3507,20 +3538,26 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) faddr = ha->flt_region_fw_sec; } - qla24xx_read_flash_data(vha, dcode, faddr, 8); - if (qla24xx_risc_firmware_invalid(dcode)) { - ql_log(ql_log_warn, vha, 0x005f, - "Unrecognized fw revision at %x.\n", - ha->flt_region_fw * 4); - ql_dump_buffer(ql_dbg_init, vha, 0x005f, dcode, 32); + ret = qla24xx_read_flash_data(vha, dcode, faddr, 8); + if (ret) { + ql_log(ql_log_info, vha, 0x019e, + "Unable to read FW version (%x).\n", ret); + return ret; } else { - for (i = 0; i < 4; i++) - ha->fw_revision[i] = + if (qla24xx_risc_firmware_invalid(dcode)) { + ql_log(ql_log_warn, vha, 0x005f, + "Unrecognized fw revision at %x.\n", + ha->flt_region_fw * 4); + ql_dump_buffer(ql_dbg_init, vha, 0x005f, dcode, 32); + } else { + for (i = 0; i < 4; i++) + ha->fw_revision[i] = be32_to_cpu((__force __be32)dcode[4+i]); - ql_dbg(ql_dbg_init, vha, 0x0060, - "Firmware revision (flash) %u.%u.%u (%x).\n", - ha->fw_revision[0], ha->fw_revision[1], - ha->fw_revision[2], ha->fw_revision[3]); + ql_dbg(ql_dbg_init, vha, 0x0060, + "Firmware revision (flash) %u.%u.%u (%x).\n", + ha->fw_revision[0], ha->fw_revision[1], + ha->fw_revision[2], ha->fw_revision[3]); + } } /* Check for golden firmware and get version if available */ @@ -3531,18 +3568,23 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf) memset(ha->gold_fw_version, 0, sizeof(ha->gold_fw_version)); faddr = ha->flt_region_gold_fw; - qla24xx_read_flash_data(vha, dcode, ha->flt_region_gold_fw, 8); - if (qla24xx_risc_firmware_invalid(dcode)) { - ql_log(ql_log_warn, vha, 0x0056, - "Unrecognized golden fw at %#x.\n", faddr); - ql_dump_buffer(ql_dbg_init, vha, 0x0056, dcode, 32); + ret = qla24xx_read_flash_data(vha, dcode, ha->flt_region_gold_fw, 8); + if (ret) { + ql_log(ql_log_info, vha, 0x019f, + "Unable to read Gold FW version (%x).\n", ret); return ret; - } - - for (i = 0; i < 4; i++) - ha->gold_fw_version[i] = - be32_to_cpu((__force __be32)dcode[4+i]); + } else { + if (qla24xx_risc_firmware_invalid(dcode)) { + ql_log(ql_log_warn, vha, 0x0056, + "Unrecognized golden fw at %#x.\n", faddr); + ql_dump_buffer(ql_dbg_init, vha, 0x0056, dcode, 32); + return QLA_FUNCTION_FAILED; + } + for (i = 0; i < 4; i++) + ha->gold_fw_version[i] = + be32_to_cpu((__force __be32)dcode[4+i]); + } return ret; } diff --git a/qla2x00t-32gbit/qla_version.h b/qla2x00t-32gbit/qla_version.h index 7627fd807..cf0f9d9db 100644 --- a/qla2x00t-32gbit/qla_version.h +++ b/qla2x00t-32gbit/qla_version.h @@ -6,9 +6,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.02.09.200-k" +#define QLA2XXX_VERSION "10.02.09.300-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 2 #define QLA_DRIVER_PATCH_VER 9 -#define QLA_DRIVER_BETA_VER 200 +#define QLA_DRIVER_BETA_VER 300 diff --git a/scripts/run-regression-tests b/scripts/run-regression-tests index 4d761f1f0..e87bb64f4 100755 --- a/scripts/run-regression-tests +++ b/scripts/run-regression-tests @@ -299,6 +299,7 @@ CONFIG_NET_DROP_MONITOR \ CONFIG_NOP_TRACER \ CONFIG_RETPOLINE \ CONFIG_RH_KABI_SIZE_ALIGN_CHECKS \ +CONFIG_UEK_KABI_SIZE_ALIGN_CHECKS \ CONFIG_SCHED_TRACER \ CONFIG_SECURITY_SELINUX \ CONFIG_STACK_TRACER \ @@ -311,6 +312,8 @@ CONFIG_TRACING \ CONFIG_UNWINDER_ORC \ CONFIG_X86_32 \ CONFIG_X86_X32 \ +CONFIG_X86_KERNEL_IBT \ +CONFIG_LTO_CLANG \ " local enable="CONFIG_UNWINDER_FRAME_POINTER" diff --git a/scst/include/backport.h b/scst/include/backport.h index 97e46c9fa..7c53e9d3e 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -329,6 +329,18 @@ static inline void bdev_release_backport(struct bdev_handle *handle) #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) +/* + * See also commit 6436bd90f76e ("block: add a bdev_nr_bytes helper") # v5.16. + */ +static inline loff_t bdev_nr_bytes_backport(struct block_device *bdev) +{ + return i_size_read(bdev->bd_inode); +} + +#define bdev_nr_bytes bdev_nr_bytes_backport +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0) && \ (!defined(RHEL_RELEASE_CODE) || \ RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(9, 1)) @@ -553,10 +565,12 @@ typedef unsigned int __poll_t; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) + (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) || \ + LINUX_VERSION_CODE >= KERNEL_VERSION(6, 10, 0)) /* * See also commit bb7462b6fd64 ("vfs: use helpers for calling - * f_op->{read,write}_iter()"). + * f_op->{read,write}_iter()") # v4.11. + * See also commit 7c98f7cb8fda ("remove call_{read,write}_iter() functions") # v6.10. */ static inline ssize_t call_read_iter(struct file *file, struct kiocb *kio, struct iov_iter *iter) @@ -1496,6 +1510,25 @@ static inline ssize_t strscpy(char *dest, const char *src, size_t count) } #endif +#ifndef memtostr +/* + * See also commit 0efc5990bca5 ("string.h: Introduce memtostr() and memtostr_pad()") # v6.10. + */ +#define memtostr(dest, src) do { \ + const size_t _dest_len = __builtin_object_size(dest, 1); \ + const size_t _src_len = __builtin_object_size(src, 1); \ + const size_t _src_chars = strnlen(src, _src_len); \ + const size_t _copy_len = min(_dest_len - 1, _src_chars); \ + \ + BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \ + !__builtin_constant_p(_src_len) || \ + _dest_len == 0 || _dest_len == (size_t)-1 || \ + _src_len == 0 || _src_len == (size_t)-1); \ + memcpy(dest, src, _copy_len); \ + dest[_copy_len] = '\0'; \ +} while (0) +#endif + /* */ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) && \ diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 4f65d1ab4..0234743ba 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -983,48 +983,51 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev) #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) bi_profile_name = bi->name; -#else +#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0) bi_profile_name = bi->profile->name; +#else + bi_profile_name = blk_integrity_profile_name(bi); #endif + TRACE_DBG("BI name %s", bi_profile_name); if (!strcmp(bi_profile_name, "T10-DIF-TYPE1-CRC")) { dev->dev_dif_ip_not_supported = 1; if (virt_dev->dif_type != 1) { - PRINT_ERROR("Integrity type mismatch, %d expected, " - "but block device has 1 (dev %s)", - virt_dev->dif_type, dev->virt_name); + PRINT_ERROR( + "Integrity type mismatch, %d expected, but block device has 1 (dev %s)", + virt_dev->dif_type, dev->virt_name); res = -EINVAL; goto out_close; } } else if (!strcmp(bi_profile_name, "T10-DIF-TYPE1-IP")) { if (virt_dev->dif_type != 1) { - PRINT_ERROR("Integrity type mismatch, %d expected, " - "but block device has 1 (dev %s)", - virt_dev->dif_type, dev->virt_name); + PRINT_ERROR( + "Integrity type mismatch, %d expected, but block device has 1 (dev %s)", + virt_dev->dif_type, dev->virt_name); res = -EINVAL; goto out_close; } } else if (!strcmp(bi_profile_name, "T10-DIF-TYPE3-CRC")) { dev->dev_dif_ip_not_supported = 1; if (virt_dev->dif_type != 3) { - PRINT_ERROR("Integrity type mismatch, %d expected, " - "but block device has 1 (dev %s)", - virt_dev->dif_type, dev->virt_name); + PRINT_ERROR( + "Integrity type mismatch, %d expected, but block device has 1 (dev %s)", + virt_dev->dif_type, dev->virt_name); res = -EINVAL; goto out_close; } } else if (!strcmp(bi_profile_name, "T10-DIF-TYPE3-IP")) { if (virt_dev->dif_type != 3) { - PRINT_ERROR("Integrity type mismatch, %d expected, " - "but block device has 3 (dev %s)", - virt_dev->dif_type, dev->virt_name); + PRINT_ERROR( + "Integrity type mismatch, %d expected, but block device has 3 (dev %s)", + virt_dev->dif_type, dev->virt_name); res = -EINVAL; goto out_close; } } else { - PRINT_ERROR("Unable to understand integrity name %s" - "(dev %s)", bi_profile_name, dev->virt_name); + PRINT_ERROR("Unable to understand integrity name %s (dev %s)", + bi_profile_name, dev->virt_name); res = -EINVAL; goto out_close; } @@ -1033,15 +1036,15 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev) if ((virt_dev->dif_mode & SCST_DIF_MODE_DEV_CHECK) && !(virt_dev->dif_mode & SCST_DIF_MODE_DEV_STORE)) { - PRINT_ERROR("Blockio dev_check is not possible without " - "dev_store (dev %s)", dev->virt_name); + PRINT_ERROR("Blockio dev_check is not possible without dev_store (dev %s)", + dev->virt_name); res = -EINVAL; goto out_close; } if (!(virt_dev->dif_mode & SCST_DIF_MODE_DEV_CHECK)) PRINT_WARNING("Blk integrity implies dev_check (dev %s)", - dev->virt_name); + dev->virt_name); out_no_bi: res = 0; diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 88239217e..551afbaf2 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -2094,7 +2094,7 @@ int scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq) if (cmd->cdb[0] == REQUEST_SENSE) res = scst_set_lun_not_supported_request_sense(cmd, key, asc, ascq); - else if (cmd->cdb[0] == INQUIRY) + else if (cmd->cdb[0] == INQUIRY && !(cmd->cdb[1] & 0x01/*EVPD*/)) res = scst_set_lun_not_supported_inquiry(cmd); else if (cmd->cdb[0] == REPORT_LUNS) res = scst_set_lun_not_supported_report_luns(cmd); @@ -6178,7 +6178,7 @@ loff_t scst_bdev_size(const char *path) if (rc) return rc; - res = i_size_read(bdev_desc.bdev->bd_inode); + res = bdev_nr_bytes(bdev_desc.bdev); scst_release_bdev(&bdev_desc); return res; @@ -8431,6 +8431,16 @@ static struct request *blk_make_request(struct request_queue *q, } #endif +static inline unsigned int +queue_dma_pad_mask(const struct request_queue *q) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0) + return q->dma_pad_mask; +#else + return q->limits.dma_pad_mask; +#endif +} + /* __blk_map_kern_sg - map kernel data to a request for REQ_TYPE_BLOCK_PC */ static struct request *__blk_map_kern_sg(struct request_queue *q, struct scatterlist *sgl, int nents, struct blk_kern_sg_work *bw, @@ -8553,7 +8563,7 @@ static struct request *__blk_map_kern_sg(struct request_queue *q, } /* Total length must satisfy DMA padding alignment */ - if ((tot_len & q->dma_pad_mask) && bw != NULL) { + if (bw && (tot_len & queue_dma_pad_mask(q))) { rq = ERR_PTR(-EINVAL); goto out_free_bios; } diff --git a/scst_local/scst_local.c b/scst_local/scst_local.c index a8bf14b6b..902153220 100644 --- a/scst_local/scst_local.c +++ b/scst_local/scst_local.c @@ -1033,6 +1033,7 @@ static int scst_local_change_queue_depth(struct scsi_device *sdev, int depth, #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 10, 0) static int scst_local_slave_alloc(struct scsi_device *sdev) { struct request_queue *q = sdev->request_queue; @@ -1053,10 +1054,11 @@ static int scst_local_slave_alloc(struct scsi_device *sdev) * and supports block sizes from 512 up to 4096. See also * https://github.com/sahlberg/libiscsi/issues/302. */ - blk_queue_dma_alignment(q, 4095); + blk_queue_dma_alignment(q, (4096 - 1)); return 0; } +#endif static int scst_local_slave_configure(struct scsi_device *sdev) { @@ -1379,7 +1381,11 @@ static const struct scsi_host_template scst_lcl_ini_driver_template = { .name = SCST_LOCAL_NAME, .queuecommand = scst_local_queuecommand, .change_queue_depth = scst_local_change_queue_depth, +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 10, 0) .slave_alloc = scst_local_slave_alloc, +#else + .dma_alignment = (4096 - 1), +#endif .slave_configure = scst_local_slave_configure, .eh_abort_handler = scst_local_abort, .eh_device_reset_handler = scst_local_device_reset, @@ -1494,8 +1500,11 @@ static DRIVER_REMOVE_RET scst_local_driver_remove(struct device *dev) return (DRIVER_REMOVE_RET)0; } -static int scst_local_bus_match(struct device *dev, - struct device_driver *dev_driver) +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0) +static int scst_local_bus_match(struct device *dev, struct device_driver *drv) +#else +static int scst_local_bus_match(struct device *dev, const struct device_driver *drv) +#endif { TRACE_ENTRY();