Merge patch series "qla2xxx misc. bug fixes"

Nilesh Javali <njavali@marvell.com> says:

Martin,

Please apply the qla2xxx driver miscellaneous bug fixes to the scsi
tree at your earliest convenience.

Link: https://lore.kernel.org/r/20240710171057.35066-1-njavali@marvell.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Martin K. Petersen 2024-07-10 22:45:08 -04:00
commit 22b8d89b9d
11 changed files with 455 additions and 377 deletions

View File

@ -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,16 +3059,60 @@ skip_chip_chk:
return ret;
}
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 = 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;
srb_t *sp;
int cnt, que;
unsigned long flags;
struct req_que *req;
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;
}

View File

@ -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 */

View File

@ -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 *);

View File

@ -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 {
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;
}
}
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 (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;
}
}
}
} 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;
}
}
/* 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 {
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;
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");
return rval;
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;
}
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);
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.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);
memset(sp->u.iocb_cmd.u.ctarg.rsp, 0, sp->u.iocb_cmd.u.ctarg.rsp_size);
sp->type = SRB_CT_PTHRU_CMD;
sp->gen1 = vha->hw->base_qpair->chip_reset;
qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha) + 2,
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),

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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 &

View File

@ -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;
}
@ -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);
case QLA_EVT_SCAN_CMD:
qla_fab_async_scan(vha, e->u.iosb.sp);
break;
case QLA_EVT_GPNFT_DONE:
qla24xx_async_gpnft_done(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);

View File

@ -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;
} 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]);
}
for (i = 0; i < 4; i++)
ha->gold_fw_version[i] =
be32_to_cpu((__force __be32)dcode[4+i]);
return ret;
}

View File

@ -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