Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[sfrench/cifs-2.6.git] / drivers / scsi / qla2xxx / qla_init.c
index d4c3baec9172b7c6d77fda6dfb5e3fad8ec0a012..643d2324082e9044f03246792113f65d5f3c7fa3 100644 (file)
@@ -37,8 +37,8 @@ static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
 static int qla84xx_init_chip(scsi_qla_host_t *);
 static int qla25xx_init_queues(struct qla_hw_data *);
 static int qla24xx_post_prli_work(struct scsi_qla_host*, fc_port_t *);
-static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
-    struct event_arg *);
+static void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha,
+                                     struct event_arg *ea);
 static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
     struct event_arg *);
 static void __qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *);
@@ -63,10 +63,8 @@ qla2x00_sp_timeout(struct timer_list *t)
        iocb->timeout(sp);
 }
 
-void
-qla2x00_sp_free(void *ptr)
+void qla2x00_sp_free(srb_t *sp)
 {
-       srb_t *sp = ptr;
        struct srb_iocb *iocb = &sp->u.iocb_cmd;
 
        del_timer(&iocb->timer);
@@ -99,22 +97,33 @@ static void qla24xx_abort_iocb_timeout(void *data)
 {
        srb_t *sp = data;
        struct srb_iocb *abt = &sp->u.iocb_cmd;
+       struct qla_qpair *qpair = sp->qpair;
+       u32 handle;
+       unsigned long flags;
+
+       spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+       for (handle = 1; handle < qpair->req->num_outstanding_cmds; handle++) {
+               /* removing the abort */
+               if (qpair->req->outstanding_cmds[handle] == sp) {
+                       qpair->req->outstanding_cmds[handle] = NULL;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
 
        abt->u.abt.comp_status = CS_TIMEOUT;
-       sp->done(sp, QLA_FUNCTION_TIMEOUT);
+       sp->done(sp, QLA_OS_TIMER_EXPIRED);
 }
 
-static void qla24xx_abort_sp_done(void *ptr, int res)
+static void qla24xx_abort_sp_done(srb_t *sp, int res)
 {
-       srb_t *sp = ptr;
        struct srb_iocb *abt = &sp->u.iocb_cmd;
 
-       if (del_timer(&sp->u.iocb_cmd.timer)) {
-               if (sp->flags & SRB_WAKEUP_ON_COMP)
-                       complete(&abt->u.abt.comp);
-               else
-                       sp->free(sp);
-       }
+       del_timer(&sp->u.iocb_cmd.timer);
+       if (sp->flags & SRB_WAKEUP_ON_COMP)
+               complete(&abt->u.abt.comp);
+       else
+               sp->free(sp);
 }
 
 static int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
@@ -127,7 +136,7 @@ static int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
        sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport,
                                  GFP_ATOMIC);
        if (!sp)
-               goto done;
+               return rval;
 
        abt_iocb = &sp->u.iocb_cmd;
        sp->type = SRB_ABT_CMD;
@@ -151,20 +160,18 @@ static int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
               cmd_sp->type);
 
        rval = qla2x00_start_sp(sp);
-       if (rval != QLA_SUCCESS)
-               goto done_free_sp;
+       if (rval != QLA_SUCCESS) {
+               sp->free(sp);
+               return rval;
+       }
 
        if (wait) {
                wait_for_completion(&abt_iocb->u.abt.comp);
                rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
                        QLA_SUCCESS : QLA_FUNCTION_FAILED;
-       } else {
-               goto done;
+               sp->free(sp);
        }
 
-done_free_sp:
-       sp->free(sp);
-done:
        return rval;
 }
 
@@ -234,13 +241,15 @@ qla2x00_async_iocb_timeout(void *data)
                        sp->done(sp, QLA_FUNCTION_TIMEOUT);
                }
                break;
+       default:
+               WARN_ON_ONCE(true);
+               sp->done(sp, QLA_FUNCTION_TIMEOUT);
+               break;
        }
 }
 
-static void
-qla2x00_async_login_sp_done(void *ptr, int res)
+static void qla2x00_async_login_sp_done(srb_t *sp, int res)
 {
-       srb_t *sp = ptr;
        struct scsi_qla_host *vha = sp->vha;
        struct srb_iocb *lio = &sp->u.iocb_cmd;
        struct event_arg ea;
@@ -252,14 +261,13 @@ qla2x00_async_login_sp_done(void *ptr, int res)
 
        if (!test_bit(UNLOADING, &vha->dpc_flags)) {
                memset(&ea, 0, sizeof(ea));
-               ea.event = FCME_PLOGI_DONE;
                ea.fcport = sp->fcport;
                ea.data[0] = lio->u.logio.data[0];
                ea.data[1] = lio->u.logio.data[1];
                ea.iop[0] = lio->u.logio.iop[0];
                ea.iop[1] = lio->u.logio.iop[1];
                ea.sp = sp;
-               qla2x00_fcport_event_handler(vha, &ea);
+               qla24xx_handle_plogi_done_event(vha, &ea);
        }
 
        sp->free(sp);
@@ -289,8 +297,13 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
        struct srb_iocb *lio;
        int rval = QLA_FUNCTION_FAILED;
 
-       if (!vha->flags.online)
-               goto done;
+       if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT) ||
+           fcport->loop_id == FC_NO_LOOP_ID) {
+               ql_log(ql_log_warn, vha, 0xffff,
+                   "%s: %8phC - not sending command.\n",
+                   __func__, fcport->port_name);
+               return rval;
+       }
 
        sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
        if (!sp)
@@ -341,11 +354,8 @@ done:
        return rval;
 }
 
-static void
-qla2x00_async_logout_sp_done(void *ptr, int res)
+static void qla2x00_async_logout_sp_done(srb_t *sp, int res)
 {
-       srb_t *sp = ptr;
-
        sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
        sp->fcport->login_gen++;
        qlt_logo_completion_handler(sp->fcport, res);
@@ -359,9 +369,6 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
        struct srb_iocb *lio;
        int rval = QLA_FUNCTION_FAILED;
 
-       if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
-               return rval;
-
        fcport->flags |= FCF_ASYNC_SENT;
        sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
        if (!sp)
@@ -405,10 +412,8 @@ qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport,
        qlt_logo_completion_handler(fcport, data[0]);
 }
 
-static void
-qla2x00_async_prlo_sp_done(void *s, int res)
+static void qla2x00_async_prlo_sp_done(srb_t *sp, int res)
 {
-       srb_t *sp = (srb_t *)s;
        struct srb_iocb *lio = &sp->u.iocb_cmd;
        struct scsi_qla_host *vha = sp->vha;
 
@@ -469,6 +474,9 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
            fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
            fcport->rscn_gen, ea->sp->gen1, fcport->loop_id);
 
+       WARN_ONCE(!qla2xxx_is_valid_mbs(ea->data[0]), "mbs: %#x\n",
+                 ea->data[0]);
+
        if (ea->data[0] != MBS_COMMAND_COMPLETE) {
                ql_dbg(ql_dbg_disc, vha, 0x2066,
                    "%s %8phC: adisc fail: post delete\n",
@@ -511,10 +519,8 @@ static int qla_post_els_plogi_work(struct scsi_qla_host *vha, fc_port_t *fcport)
        return qla2x00_post_work(vha, e);
 }
 
-static void
-qla2x00_async_adisc_sp_done(void *ptr, int res)
+static void qla2x00_async_adisc_sp_done(srb_t *sp, int res)
 {
-       srb_t *sp = ptr;
        struct scsi_qla_host *vha = sp->vha;
        struct event_arg ea;
        struct srb_iocb *lio = &sp->u.iocb_cmd;
@@ -526,7 +532,6 @@ qla2x00_async_adisc_sp_done(void *ptr, int res)
        sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
 
        memset(&ea, 0, sizeof(ea));
-       ea.event = FCME_ADISC_DONE;
        ea.rc = res;
        ea.data[0] = lio->u.logio.data[0];
        ea.data[1] = lio->u.logio.data[1];
@@ -535,7 +540,7 @@ qla2x00_async_adisc_sp_done(void *ptr, int res)
        ea.fcport = sp->fcport;
        ea.sp = sp;
 
-       qla2x00_fcport_event_handler(vha, &ea);
+       qla24xx_handle_adisc_event(vha, &ea);
 
        sp->free(sp);
 }
@@ -803,6 +808,15 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
                        fcport->fw_login_state = current_login_state;
                        fcport->d_id = id;
                        switch (current_login_state) {
+                       case DSC_LS_PRLI_PEND:
+                               /*
+                                * In the middle of PRLI. Let it finish.
+                                * Allow relogin code to recheck state again
+                                * with GNL. Push disc_state back to DELETED
+                                * so GNL can go out again
+                                */
+                               fcport->disc_state = DSC_DELETED;
+                               break;
                        case DSC_LS_PRLI_COMP:
                                if ((e->prli_svc_param_word_3[0] & BIT_4) == 0)
                                        fcport->port_type = FCT_INITIATOR;
@@ -917,10 +931,8 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
        }
 } /* gnl_event */
 
-static void
-qla24xx_async_gnl_sp_done(void *s, int res)
+static void qla24xx_async_gnl_sp_done(srb_t *sp, int res)
 {
-       struct srb *sp = s;
        struct scsi_qla_host *vha = sp->vha;
        unsigned long flags;
        struct fc_port *fcport = NULL, *tf;
@@ -943,7 +955,6 @@ qla24xx_async_gnl_sp_done(void *s, int res)
        memset(&ea, 0, sizeof(ea));
        ea.sp = sp;
        ea.rc = res;
-       ea.event = FCME_GNL_DONE;
 
        if (sp->u.iocb_cmd.u.mbx.in_mb[1] >=
            sizeof(struct get_name_list_extended)) {
@@ -982,7 +993,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
                spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
                ea.fcport = fcport;
 
-               qla2x00_fcport_event_handler(vha, &ea);
+               qla24xx_handle_gnl_done_event(vha, &ea);
        }
 
        /* create new fcport if fw has knowledge of new sessions */
@@ -1107,10 +1118,8 @@ int qla24xx_post_gnl_work(struct scsi_qla_host *vha, fc_port_t *fcport)
        return qla2x00_post_work(vha, e);
 }
 
-static
-void qla24xx_async_gpdb_sp_done(void *s, int res)
+static void qla24xx_async_gpdb_sp_done(srb_t *sp, int res)
 {
-       struct srb *sp = s;
        struct scsi_qla_host *vha = sp->vha;
        struct qla_hw_data *ha = vha->hw;
        fc_port_t *fcport = sp->fcport;
@@ -1129,11 +1138,10 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
 
        fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
        memset(&ea, 0, sizeof(ea));
-       ea.event = FCME_GPDB_DONE;
        ea.fcport = fcport;
        ea.sp = sp;
 
-       qla2x00_fcport_event_handler(vha, &ea);
+       qla24xx_handle_gpdb_event(vha, &ea);
 
        dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
                sp->u.iocb_cmd.u.mbx.in_dma);
@@ -1154,10 +1162,8 @@ static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
        return qla2x00_post_work(vha, e);
 }
 
-static void
-qla2x00_async_prli_sp_done(void *ptr, int res)
+static void qla2x00_async_prli_sp_done(srb_t *sp, int res)
 {
-       srb_t *sp = ptr;
        struct scsi_qla_host *vha = sp->vha;
        struct srb_iocb *lio = &sp->u.iocb_cmd;
        struct event_arg ea;
@@ -1170,7 +1176,6 @@ qla2x00_async_prli_sp_done(void *ptr, int res)
 
        if (!test_bit(UNLOADING, &vha->dpc_flags)) {
                memset(&ea, 0, sizeof(ea));
-               ea.event = FCME_PRLI_DONE;
                ea.fcport = sp->fcport;
                ea.data[0] = lio->u.logio.data[0];
                ea.data[1] = lio->u.logio.data[1];
@@ -1178,7 +1183,7 @@ qla2x00_async_prli_sp_done(void *ptr, int res)
                ea.iop[1] = lio->u.logio.iop[1];
                ea.sp = sp;
 
-               qla2x00_fcport_event_handler(vha, &ea);
+               qla24xx_handle_prli_done_event(vha, &ea);
        }
 
        sp->free(sp);
@@ -1262,8 +1267,13 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
        struct port_database_24xx *pd;
        struct qla_hw_data *ha = vha->hw;
 
-       if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+       if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT) ||
+           fcport->loop_id == FC_NO_LOOP_ID) {
+               ql_log(ql_log_warn, vha, 0xffff,
+                   "%s: %8phC - not sending command.\n",
+                   __func__, fcport->port_name);
                return rval;
+       }
 
        fcport->disc_state = DSC_GPDB;
 
@@ -1473,7 +1483,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
        u64 wwn;
        u16 sec;
 
-       ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x20d8,
+       ql_dbg(ql_dbg_disc, vha, 0x20d8,
            "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d lid %d scan %d\n",
            __func__, fcport->port_name, fcport->disc_state,
            fcport->fw_login_state, fcport->login_pause, fcport->flags,
@@ -1484,6 +1494,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
                return 0;
 
        if ((fcport->loop_id != FC_NO_LOOP_ID) &&
+           qla_dual_mode_enabled(vha) &&
            ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
             (fcport->fw_login_state == DSC_LS_PRLI_PEND)))
                return 0;
@@ -1636,12 +1647,34 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
        return qla2x00_post_work(vha, e);
 }
 
-static
+void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+       fc_port_t *fcport;
+       unsigned long flags;
+
+       fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
+       if (fcport) {
+               fcport->scan_needed = 1;
+               fcport->rscn_gen++;
+       }
+
+       spin_lock_irqsave(&vha->work_lock, flags);
+       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);
+}
+
 void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
        struct event_arg *ea)
 {
        fc_port_t *fcport = ea->fcport;
 
+       if (test_bit(UNLOADING, &vha->dpc_flags))
+               return;
+
        ql_dbg(ql_dbg_disc, vha, 0x2102,
            "%s %8phC DS %d LS %d P %d del %d cnfl %p rscn %d|%d login %d|%d fl %x\n",
            __func__, fcport->port_name, fcport->disc_state,
@@ -1651,110 +1684,16 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
            fcport->last_login_gen, fcport->login_gen,
            fcport->flags);
 
-       if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
-           (fcport->fw_login_state == DSC_LS_PRLI_PEND))
-               return;
-
-       if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
-               if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) {
-                       set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
-                       return;
-               }
-       }
-
        if (fcport->last_rscn_gen != fcport->rscn_gen) {
-               ql_dbg(ql_dbg_disc, vha, 0x20e9, "%s %d %8phC post gidpn\n",
+               ql_dbg(ql_dbg_disc, vha, 0x20e9, "%s %d %8phC post gnl\n",
                    __func__, __LINE__, fcport->port_name);
-
+               qla24xx_post_gnl_work(vha, fcport);
                return;
        }
 
        qla24xx_fcport_handle_login(vha, fcport);
 }
 
-
-static void qla_handle_els_plogi_done(scsi_qla_host_t *vha,
-                                     struct event_arg *ea)
-{
-       ql_dbg(ql_dbg_disc, vha, 0x2118,
-           "%s %d %8phC post PRLI\n",
-           __func__, __LINE__, ea->fcport->port_name);
-       qla24xx_post_prli_work(vha, ea->fcport);
-}
-
-void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
-{
-       fc_port_t *fcport;
-
-       switch (ea->event) {
-       case FCME_RELOGIN:
-               if (test_bit(UNLOADING, &vha->dpc_flags))
-                       return;
-
-               qla24xx_handle_relogin_event(vha, ea);
-               break;
-       case FCME_RSCN:
-               if (test_bit(UNLOADING, &vha->dpc_flags))
-                       return;
-               {
-                       unsigned long flags;
-
-                       fcport = qla2x00_find_fcport_by_nportid
-                               (vha, &ea->id, 1);
-                       if (fcport) {
-                               fcport->scan_needed = 1;
-                               fcport->rscn_gen++;
-                       }
-
-                       spin_lock_irqsave(&vha->work_lock, flags);
-                       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);
-               }
-               break;
-       case FCME_GNL_DONE:
-               qla24xx_handle_gnl_done_event(vha, ea);
-               break;
-       case FCME_GPSC_DONE:
-               qla24xx_handle_gpsc_event(vha, ea);
-               break;
-       case FCME_PLOGI_DONE:   /* Initiator side sent LLIOCB */
-               qla24xx_handle_plogi_done_event(vha, ea);
-               break;
-       case FCME_PRLI_DONE:
-               qla24xx_handle_prli_done_event(vha, ea);
-               break;
-       case FCME_GPDB_DONE:
-               qla24xx_handle_gpdb_event(vha, ea);
-               break;
-       case FCME_GPNID_DONE:
-               qla24xx_handle_gpnid_event(vha, ea);
-               break;
-       case FCME_GFFID_DONE:
-               qla24xx_handle_gffid_event(vha, ea);
-               break;
-       case FCME_ADISC_DONE:
-               qla24xx_handle_adisc_event(vha, ea);
-               break;
-       case FCME_GNNID_DONE:
-               qla24xx_handle_gnnid_event(vha, ea);
-               break;
-       case FCME_GFPNID_DONE:
-               qla24xx_handle_gfpnid_event(vha, ea);
-               break;
-       case FCME_ELS_PLOGI_DONE:
-               qla_handle_els_plogi_done(vha, ea);
-               break;
-       default:
-               BUG_ON(1);
-               break;
-       }
-}
-
 /*
  * RSCN(s) came in for this fcport, but the RSCN(s) was not able
  * to be consumed by the fcport
@@ -1772,10 +1711,9 @@ void qla_rscn_replay(fc_port_t *fcport)
 
        if (fcport->scan_needed) {
                memset(&ea, 0, sizeof(ea));
-               ea.event = FCME_RSCN;
                ea.id = fcport->d_id;
                ea.id.b.rsvd_1 = RSCN_PORT_ADDR;
-               qla2x00_fcport_event_handler(fcport->vha, &ea);
+               qla2x00_handle_rscn(fcport->vha, &ea);
        }
 }
 
@@ -1789,10 +1727,8 @@ qla2x00_tmf_iocb_timeout(void *data)
        complete(&tmf->u.tmf.comp);
 }
 
-static void
-qla2x00_tmf_sp_done(void *ptr, int res)
+static void qla2x00_tmf_sp_done(srb_t *sp, int res)
 {
-       srb_t *sp = ptr;
        struct srb_iocb *tmf = &sp->u.iocb_cmd;
 
        complete(&tmf->u.tmf.comp);
@@ -1890,6 +1826,9 @@ qla24xx_async_abort_command(srb_t *sp)
 static void
 qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 {
+       WARN_ONCE(!qla2xxx_is_valid_mbs(ea->data[0]), "mbs: %#x\n",
+                 ea->data[0]);
+
        switch (ea->data[0]) {
        case MBS_COMMAND_COMPLETE:
                ql_dbg(ql_dbg_disc, vha, 0x2118,
@@ -1929,7 +1868,7 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
        }
 }
 
-static void
+void
 qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
 {
        port_id_t cid;  /* conflict Nport id */
@@ -1953,8 +1892,11 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
                return;
        }
 
-       if (fcport->disc_state == DSC_DELETE_PEND)
+       if ((fcport->disc_state == DSC_DELETE_PEND) ||
+           (fcport->disc_state == DSC_DELETED)) {
+               set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
                return;
+       }
 
        if (ea->sp->gen2 != fcport->login_gen) {
                /* target side must have changed it. */
@@ -1972,6 +1914,9 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
                return;
        }
 
+       WARN_ONCE(!qla2xxx_is_valid_mbs(ea->data[0]), "mbs: %#x\n",
+                 ea->data[0]);
+
        switch (ea->data[0]) {
        case MBS_COMMAND_COMPLETE:
                /*
@@ -2266,6 +2211,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
        if (qla_ini_mode_enabled(vha) || qla_dual_mode_enabled(vha))
                rval = qla2x00_init_rings(vha);
 
+       /* No point in continuing if firmware initialization failed. */
+       if (rval != QLA_SUCCESS)
+               return rval;
+
        ha->flags.chip_reset_done = 1;
 
        if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) {
@@ -3082,103 +3031,113 @@ qla24xx_chip_diag(scsi_qla_host_t *vha)
 }
 
 static void
-qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
+qla2x00_init_fce_trace(scsi_qla_host_t *vha)
 {
        int rval;
        dma_addr_t tc_dma;
        void *tc;
        struct qla_hw_data *ha = vha->hw;
 
-       if (ha->eft) {
+       if (!IS_FWI2_CAPABLE(ha))
+               return;
+
+       if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
+           !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+               return;
+
+       if (ha->fce) {
                ql_dbg(ql_dbg_init, vha, 0x00bd,
-                   "%s: Offload Mem is already allocated.\n",
-                   __func__);
+                      "%s: FCE Mem is already allocated.\n",
+                      __func__);
                return;
        }
 
-       if (IS_FWI2_CAPABLE(ha)) {
-               /* Allocate memory for Fibre Channel Event Buffer. */
-               if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
-                   !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
-                       goto try_eft;
+       /* Allocate memory for Fibre Channel Event Buffer. */
+       tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
+                               GFP_KERNEL);
+       if (!tc) {
+               ql_log(ql_log_warn, vha, 0x00be,
+                      "Unable to allocate (%d KB) for FCE.\n",
+                      FCE_SIZE / 1024);
+               return;
+       }
 
-               if (ha->fce)
-                       dma_free_coherent(&ha->pdev->dev,
-                           FCE_SIZE, ha->fce, ha->fce_dma);
+       rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
+                                       ha->fce_mb, &ha->fce_bufs);
+       if (rval) {
+               ql_log(ql_log_warn, vha, 0x00bf,
+                      "Unable to initialize FCE (%d).\n", rval);
+               dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc, tc_dma);
+               return;
+       }
 
-               /* Allocate memory for Fibre Channel Event Buffer. */
-               tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
-                                       GFP_KERNEL);
-               if (!tc) {
-                       ql_log(ql_log_warn, vha, 0x00be,
-                           "Unable to allocate (%d KB) for FCE.\n",
-                           FCE_SIZE / 1024);
-                       goto try_eft;
-               }
-
-               rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
-                   ha->fce_mb, &ha->fce_bufs);
-               if (rval) {
-                       ql_log(ql_log_warn, vha, 0x00bf,
-                           "Unable to initialize FCE (%d).\n", rval);
-                       dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
-                           tc_dma);
-                       ha->flags.fce_enabled = 0;
-                       goto try_eft;
-               }
-               ql_dbg(ql_dbg_init, vha, 0x00c0,
-                   "Allocate (%d KB) for FCE...\n", FCE_SIZE / 1024);
-
-               ha->flags.fce_enabled = 1;
-               ha->fce_dma = tc_dma;
-               ha->fce = tc;
-
-try_eft:
-               if (ha->eft)
-                       dma_free_coherent(&ha->pdev->dev,
-                           EFT_SIZE, ha->eft, ha->eft_dma);
+       ql_dbg(ql_dbg_init, vha, 0x00c0,
+              "Allocated (%d KB) for FCE...\n", FCE_SIZE / 1024);
 
-               /* Allocate memory for Extended Trace Buffer. */
-               tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
-                                       GFP_KERNEL);
-               if (!tc) {
-                       ql_log(ql_log_warn, vha, 0x00c1,
-                           "Unable to allocate (%d KB) for EFT.\n",
-                           EFT_SIZE / 1024);
-                       goto eft_err;
-               }
+       ha->flags.fce_enabled = 1;
+       ha->fce_dma = tc_dma;
+       ha->fce = tc;
+}
 
-               rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
-               if (rval) {
-                       ql_log(ql_log_warn, vha, 0x00c2,
-                           "Unable to initialize EFT (%d).\n", rval);
-                       dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
-                           tc_dma);
-                       goto eft_err;
-               }
-               ql_dbg(ql_dbg_init, vha, 0x00c3,
-                   "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
+static void
+qla2x00_init_eft_trace(scsi_qla_host_t *vha)
+{
+       int rval;
+       dma_addr_t tc_dma;
+       void *tc;
+       struct qla_hw_data *ha = vha->hw;
+
+       if (!IS_FWI2_CAPABLE(ha))
+               return;
 
-               ha->eft_dma = tc_dma;
-               ha->eft = tc;
+       if (ha->eft) {
+               ql_dbg(ql_dbg_init, vha, 0x00bd,
+                   "%s: EFT Mem is already allocated.\n",
+                   __func__);
+               return;
        }
 
-eft_err:
-       return;
+       /* Allocate memory for Extended Trace Buffer. */
+       tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
+                               GFP_KERNEL);
+       if (!tc) {
+               ql_log(ql_log_warn, vha, 0x00c1,
+                      "Unable to allocate (%d KB) for EFT.\n",
+                      EFT_SIZE / 1024);
+               return;
+       }
+
+       rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
+       if (rval) {
+               ql_log(ql_log_warn, vha, 0x00c2,
+                      "Unable to initialize EFT (%d).\n", rval);
+               dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc, tc_dma);
+               return;
+       }
+
+       ql_dbg(ql_dbg_init, vha, 0x00c3,
+              "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
+
+       ha->eft_dma = tc_dma;
+       ha->eft = tc;
+}
+
+static void
+qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
+{
+       qla2x00_init_fce_trace(vha);
+       qla2x00_init_eft_trace(vha);
 }
 
 void
 qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
 {
-       int rval;
        uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size,
            eft_size, fce_size, mq_size;
        struct qla_hw_data *ha = vha->hw;
        struct req_que *req = ha->req_q_map[0];
        struct rsp_que *rsp = ha->rsp_q_map[0];
        struct qla2xxx_fw_dump *fw_dump;
-       dma_addr_t tc_dma;
-       void *tc;
 
        dump_size = fixed_size = mem_size = eft_size = fce_size = mq_size = 0;
        req_q_size = rsp_q_size = 0;
@@ -3216,37 +3175,13 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
                }
                if (ha->tgt.atio_ring)
                        mq_size += ha->tgt.atio_q_length * sizeof(request_t);
-               /* Allocate memory for Fibre Channel Event Buffer. */
-               if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
-                   !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
-                       goto try_eft;
 
-               fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
-try_eft:
+               qla2x00_init_fce_trace(vha);
+               if (ha->fce)
+                       fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
+               qla2x00_init_eft_trace(vha);
                if (ha->eft)
-                       dma_free_coherent(&ha->pdev->dev,
-                           EFT_SIZE, ha->eft, ha->eft_dma);
-
-               /* Allocate memory for Extended Trace Buffer. */
-               tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
-                                        GFP_KERNEL);
-               if (!tc) {
-                       ql_log(ql_log_warn, vha, 0x00c1,
-                           "Unable to allocate (%d KB) for EFT.\n",
-                           EFT_SIZE / 1024);
-                       goto allocate;
-               }
-
-               rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
-               if (rval) {
-                       ql_log(ql_log_warn, vha, 0x00c2,
-                           "Unable to initialize EFT (%d).\n", rval);
-                       dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
-                           tc_dma);
-               }
-               ql_dbg(ql_dbg_init, vha, 0x00c3,
-                   "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
-               eft_size = EFT_SIZE;
+                       eft_size = EFT_SIZE;
        }
 
        if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
@@ -3268,24 +3203,22 @@ try_eft:
                            j, fwdt->dump_size);
                        dump_size += fwdt->dump_size;
                }
-               goto allocate;
+       } else {
+               req_q_size = req->length * sizeof(request_t);
+               rsp_q_size = rsp->length * sizeof(response_t);
+               dump_size = offsetof(struct qla2xxx_fw_dump, isp);
+               dump_size += fixed_size + mem_size + req_q_size + rsp_q_size
+                       + eft_size;
+               ha->chain_offset = dump_size;
+               dump_size += mq_size + fce_size;
+               if (ha->exchoffld_buf)
+                       dump_size += sizeof(struct qla2xxx_offld_chain) +
+                               ha->exchoffld_size;
+               if (ha->exlogin_buf)
+                       dump_size += sizeof(struct qla2xxx_offld_chain) +
+                               ha->exlogin_size;
        }
 
-       req_q_size = req->length * sizeof(request_t);
-       rsp_q_size = rsp->length * sizeof(response_t);
-       dump_size = offsetof(struct qla2xxx_fw_dump, isp);
-       dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + eft_size;
-       ha->chain_offset = dump_size;
-       dump_size += mq_size + fce_size;
-
-       if (ha->exchoffld_buf)
-               dump_size += sizeof(struct qla2xxx_offld_chain) +
-                       ha->exchoffld_size;
-       if (ha->exlogin_buf)
-               dump_size += sizeof(struct qla2xxx_offld_chain) +
-                       ha->exlogin_size;
-
-allocate:
        if (!ha->fw_dump_len || dump_size > ha->fw_dump_alloc_len) {
 
                ql_dbg(ql_dbg_init, vha, 0x00c5,
@@ -4400,7 +4333,7 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
 
 inline void
 qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
-       char *def)
+                      const char *def)
 {
        char *st, *en;
        uint16_t index;
@@ -4412,7 +4345,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
        if (len > sizeof(zero))
                len = sizeof(zero);
        if (memcmp(model, &zero, len) != 0) {
-               strncpy(ha->model_number, model, len);
+               memcpy(ha->model_number, model, len);
                st = en = ha->model_number;
                en += len - 1;
                while (en > st) {
@@ -4425,21 +4358,23 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
                if (use_tbl &&
                    ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
                    index < QLA_MODEL_NAMES)
-                       strncpy(ha->model_desc,
+                       strlcpy(ha->model_desc,
                            qla2x00_model_name[index * 2 + 1],
-                           sizeof(ha->model_desc) - 1);
+                           sizeof(ha->model_desc));
        } else {
                index = (ha->pdev->subsystem_device & 0xff);
                if (use_tbl &&
                    ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
                    index < QLA_MODEL_NAMES) {
-                       strcpy(ha->model_number,
-                           qla2x00_model_name[index * 2]);
-                       strncpy(ha->model_desc,
+                       strlcpy(ha->model_number,
+                               qla2x00_model_name[index * 2],
+                               sizeof(ha->model_number));
+                       strlcpy(ha->model_desc,
                            qla2x00_model_name[index * 2 + 1],
-                           sizeof(ha->model_desc) - 1);
+                           sizeof(ha->model_desc));
                } else {
-                       strcpy(ha->model_number, def);
+                       strlcpy(ha->model_number, def,
+                               sizeof(ha->model_number));
                }
        }
        if (IS_FWI2_CAPABLE(ha))
@@ -5044,7 +4979,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
 
        uint16_t        index;
        uint16_t        entries;
-       char            *id_iter;
+       struct gid_list_info *gid;
        uint16_t        loop_id;
        uint8_t         domain, area, al_pa;
        struct qla_hw_data *ha = vha->hw;
@@ -5119,18 +5054,16 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
        new_fcport->flags &= ~FCF_FABRIC_DEVICE;
 
        /* Add devices to port list. */
-       id_iter = (char *)ha->gid_list;
+       gid = ha->gid_list;
        for (index = 0; index < entries; index++) {
-               domain = ((struct gid_list_info *)id_iter)->domain;
-               area = ((struct gid_list_info *)id_iter)->area;
-               al_pa = ((struct gid_list_info *)id_iter)->al_pa;
+               domain = gid->domain;
+               area = gid->area;
+               al_pa = gid->al_pa;
                if (IS_QLA2100(ha) || IS_QLA2200(ha))
-                       loop_id = (uint16_t)
-                           ((struct gid_list_info *)id_iter)->loop_id_2100;
+                       loop_id = gid->loop_id_2100;
                else
-                       loop_id = le16_to_cpu(
-                           ((struct gid_list_info *)id_iter)->loop_id);
-               id_iter += ha->gid_list_info_size;
+                       loop_id = le16_to_cpu(gid->loop_id);
+               gid = (void *)gid + ha->gid_list_info_size;
 
                /* Bypass reserved domain fields. */
                if ((domain & 0xf0) == 0xf0)
@@ -5355,7 +5288,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
            "%s %8phN. rport %p is %s mode\n",
            __func__, fcport->port_name, rport,
            (fcport->port_type == FCT_TARGET) ? "tgt" :
-           ((fcport->port_type & FCT_NVME) ? "nvme" :"ini"));
+           ((fcport->port_type & FCT_NVME) ? "nvme" : "ini"));
 
        fc_remote_port_rolechg(rport, rport_ids.roles);
 }
@@ -6596,7 +6529,8 @@ qla2x00_quiesce_io(scsi_qla_host_t *vha)
                                        LOOP_DOWN_TIME);
        }
        /* Wait for pending cmds to complete */
-       qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST);
+       WARN_ON_ONCE(qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST)
+                    != QLA_SUCCESS);
 }
 
 void
@@ -6684,8 +6618,10 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
        }
 
        /* Clear all async request states across all VPs. */
-       list_for_each_entry(fcport, &vha->vp_fcports, list)
+       list_for_each_entry(fcport, &vha->vp_fcports, list) {
                fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
+               fcport->scan_state = 0;
+       }
        spin_lock_irqsave(&ha->vport_slock, flags);
        list_for_each_entry(vp, &ha->vp_list, list) {
                atomic_inc(&vp->vref_count);
@@ -7519,8 +7455,12 @@ qla27xx_get_active_image(struct scsi_qla_host *vha,
                goto check_sec_image;
        }
 
-       qla24xx_read_flash_data(vha, (void *)(&pri_image_status),
-           ha->flt_region_img_status_pri, sizeof(pri_image_status) >> 2);
+       if (qla24xx_read_flash_data(vha, (void *)(&pri_image_status),
+           ha->flt_region_img_status_pri, sizeof(pri_image_status) >> 2) !=
+           QLA_SUCCESS) {
+               WARN_ON_ONCE(true);
+               goto check_sec_image;
+       }
        qla27xx_print_image(vha, "Primary image", &pri_image_status);
 
        if (qla27xx_check_image_status_signature(&pri_image_status)) {
@@ -8274,7 +8214,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
                    active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ?
                    "primary" : "secondary");
        }
-       qla24xx_read_flash_data(vha, ha->vpd, faddr, ha->vpd_size >> 2);
+       ha->isp_ops->read_optrom(vha, ha->vpd, faddr << 2, ha->vpd_size);
 
        /* Get NVRAM data into cache and calculate checksum. */
        faddr = ha->flt_region_nvram;
@@ -8286,7 +8226,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
            "Loading %s nvram image.\n",
            active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ?
            "primary" : "secondary");
-       qla24xx_read_flash_data(vha, ha->nvram, faddr, ha->nvram_size >> 2);
+       ha->isp_ops->read_optrom(vha, ha->nvram, faddr << 2, ha->nvram_size);
 
        dptr = (uint32_t *)nv;
        for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)