summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/Kconfig42
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c11
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c98
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h17
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h6
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c467
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c92
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h8
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_mr.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_nvme.c5
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c28
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c108
13 files changed, 479 insertions, 411 deletions
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index a584708d30..a8b4314bfd 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -7,29 +7,29 @@ config SCSI_QLA_FC
select FW_LOADER
select BTREE
help
- This qla2xxx driver supports all QLogic Fibre Channel
- PCI and PCIe host adapters.
+ This qla2xxx driver supports all QLogic Fibre Channel
+ PCI and PCIe host adapters.
- By default, firmware for the ISP parts will be loaded
- via the Firmware Loader interface.
+ By default, firmware for the ISP parts will be loaded
+ via the Firmware Loader interface.
- ISP Firmware Filename
- ---------- -----------------
- 21xx ql2100_fw.bin
- 22xx ql2200_fw.bin
- 2300, 2312, 6312 ql2300_fw.bin
- 2322, 6322 ql2322_fw.bin
- 24xx, 54xx ql2400_fw.bin
- 25xx ql2500_fw.bin
+ ISP Firmware Filename
+ ---------- -----------------
+ 21xx ql2100_fw.bin
+ 22xx ql2200_fw.bin
+ 2300, 2312, 6312 ql2300_fw.bin
+ 2322, 6322 ql2322_fw.bin
+ 24xx, 54xx ql2400_fw.bin
+ 25xx ql2500_fw.bin
- Upon request, the driver caches the firmware image until
- the driver is unloaded.
+ Upon request, the driver caches the firmware image until
+ the driver is unloaded.
- Firmware images can be retrieved from:
+ Firmware images can be retrieved from:
- http://ldriver.qlogic.com/firmware/
+ http://ldriver.qlogic.com/firmware/
- They are also included in the linux-firmware tree as well.
+ They are also included in the linux-firmware tree as well.
config TCM_QLA2XXX
tristate "TCM_QLA2XXX fabric module for QLogic 24xx+ series target mode HBAs"
@@ -38,13 +38,15 @@ config TCM_QLA2XXX
select BTREE
default n
help
- Say Y here to enable the TCM_QLA2XXX fabric module for QLogic 24xx+ series target mode HBAs
+ Say Y here to enable the TCM_QLA2XXX fabric module for QLogic 24xx+
+ series target mode HBAs.
if TCM_QLA2XXX
config TCM_QLA2XXX_DEBUG
bool "TCM_QLA2XXX fabric module DEBUG mode for QLogic 24xx+ series target mode HBAs"
default n
help
- Say Y here to enable the TCM_QLA2XXX fabric module DEBUG for QLogic 24xx+ series target mode HBAs
- This will include code to enable the SCSI command jammer
+ Say Y here to enable the TCM_QLA2XXX fabric module DEBUG for
+ QLogic 24xx+ series target mode HBAs.
+ This will include code to enable the SCSI command jammer.
endif
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 76eeba435f..2810608acd 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1068,13 +1068,6 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon)
/* Scsi_Host attributes. */
static ssize_t
-qla2x00_driver_version_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return scnprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
-}
-
-static ssize_t
qla2x00_fw_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -2412,7 +2405,7 @@ qla2x00_dport_diagnostics_show(struct device *dev,
static DEVICE_ATTR(dport_diagnostics, 0444,
qla2x00_dport_diagnostics_show, NULL);
-static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_driver_version_show, NULL);
+static DEVICE_STRING_ATTR_RO(driver_version, S_IRUGO, qla2x00_version_str);
static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
static DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
@@ -2478,7 +2471,7 @@ static DEVICE_ATTR(port_no, 0444, qla2x00_port_no_show, NULL);
static DEVICE_ATTR(fw_attr, 0444, qla2x00_fw_attr_show, NULL);
static struct attribute *qla2x00_host_attrs[] = {
- &dev_attr_driver_version.attr,
+ &dev_attr_driver_version.attr.attr,
&dev_attr_fw_version.attr,
&dev_attr_serial_num.attr,
&dev_attr_isp_name.attr,
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 19bb64bdd8..52dc9604f5 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -324,7 +324,7 @@ qla2x00_process_els(struct bsg_job *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;
}
@@ -3059,17 +3059,61 @@ skip_chip_chk:
return ret;
}
-int
-qla24xx_bsg_timeout(struct bsg_job *bsg_job)
+static bool qla_bsg_found(struct qla_qpair *qpair, struct bsg_job *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(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));
+ 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);
@@ -3079,48 +3123,22 @@ qla24xx_bsg_timeout(struct bsg_job *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/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 2f49baf131..7cf998e3cc 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -3309,9 +3309,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;
@@ -3537,9 +3548,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,
@@ -5030,6 +5040,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/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 7309310d2a..cededfda9d 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -728,9 +728,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/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 1cf9d200d5..d2bddca704 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/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 @@ login_logout:
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 @@ login_logout:
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 @@ out:
}
}
-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 @@ done_free_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 @@ done_free_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/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 8377624d76..eda3bdab93 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -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);
@@ -6393,10 +6405,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;
@@ -8207,15 +8218,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)) {
@@ -8246,9 +8263,15 @@ check_sec_image:
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)) {
@@ -8306,6 +8329,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");
@@ -8347,8 +8371,14 @@ check_sec_image:
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)) {
@@ -8420,11 +8450,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]);
@@ -8438,7 +8467,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) {
@@ -8454,7 +8488,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]);
@@ -8483,7 +8523,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",
@@ -8509,11 +8556,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/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index a4a56ab0ba..ef4b3cc1cd 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -631,3 +631,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/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index b67416951a..76703f2706 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/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/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index 083f94e43f..82a7e21ddc 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -1909,10 +1909,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/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index a8ddf356e6..8f4cc136a9 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -49,7 +49,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/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 1e2f52210f..bc3b2aea3f 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1875,14 +1875,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;
}
@@ -1957,9 +1952,6 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
scsi_qla_host_t *vha = shost_priv(sdev->host);
struct req_que *req = vha->req;
- if (IS_T10_PI_CAPABLE(vha->hw))
- blk_queue_update_dma_alignment(sdev->request_queue, 0x7);
-
scsi_change_queue_depth(sdev, req->max_q_depth);
return 0;
}
@@ -3575,6 +3567,9 @@ skip_dpc:
QLA_SG_ALL : 128;
}
+ if (IS_T10_PI_CAPABLE(base_vha->hw))
+ host->dma_alignment = 0x7;
+
ret = scsi_add_host(host, &pdev->dev);
if (ret)
goto probe_failed;
@@ -4689,7 +4684,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)
@@ -5563,15 +5558,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);
@@ -8156,9 +8147,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/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index c092a6b1ce..6d16546e17 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/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;
}