scsi: qla2xxx: Enable type checking for the SRB free and done callback functions
[linux-2.6-block.git] / drivers / scsi / qla2xxx / qla_init.c
index 4059655639d909e8799fe991a6f4d0961820215c..3fa8ca63429c7f80c9719eac550ced8384fa1d62 100644 (file)
@@ -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)
@@ -237,10 +246,8 @@ qla2x00_async_iocb_timeout(void *data)
        }
 }
 
-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;
@@ -289,8 +296,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 +353,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 +368,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 +411,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;
 
@@ -511,10 +515,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;
@@ -917,10 +919,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;
@@ -1107,10 +1107,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;
@@ -1154,10 +1152,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;
@@ -1262,8 +1258,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;
 
@@ -1663,9 +1664,9 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
        }
 
        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;
        }
 
@@ -1789,10 +1790,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);
@@ -1953,8 +1952,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. */
@@ -2266,6 +2268,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)) {
@@ -4400,7 +4406,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 +4418,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 +4431,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))
@@ -5058,7 +5066,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;
@@ -5133,18 +5141,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)
@@ -5369,7 +5375,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);
 }
@@ -6610,7 +6616,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
@@ -6698,8 +6705,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);
@@ -7533,8 +7542,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)) {