"%s: sp hdl %x, result=%x bsg ptr %p\n",
__func__, sp->handle, res, bsg_job);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
bsg_reply->result = res;
bsg_job_done(bsg_job, bsg_reply->result,
done:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
return 0;
}
* code.
*/
void (*put_fn)(struct kref *kref);
+
+ /*
+ * Report completion for asynchronous commands.
+ */
+ void (*async_done)(struct srb *sp, int res);
} srb_t;
#define GET_CMD_SP(sp) (sp->u.scmd.cmd)
static void qla_noop_sp_done(srb_t *sp, int res)
{
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
/*
extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
extern int qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha,
struct qla_work_evt *e);
+void qla2x00_sp_release(struct kref *kref);
/*
* Global Function Prototypes in qla_mbx.c source file.
if (!e)
goto err2;
- del_timer(&sp->u.iocb_cmd.timer);
e->u.iosb.sp = sp;
qla2x00_post_work(vha, e);
return;
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
- sp->free(sp);
-
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
return;
}
if (!vha->flags.online)
goto done;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
if (!sp)
goto done;
}
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
srb_t *sp;
struct ct_sns_pkt *ct_sns;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
if (!sp)
goto done;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
srb_t *sp;
struct ct_sns_pkt *ct_sns;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
if (!sp)
goto done;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
srb_t *sp;
struct ct_sns_pkt *ct_sns;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
if (!sp)
goto done;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
qla24xx_handle_gpsc_event(vha, &ea);
done:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
return rval;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
break;
}
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
if (res) {
if (res == QLA_FUNCTION_TIMEOUT) {
qla24xx_post_gpnid_work(sp->vha, &ea.id);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
return;
}
} else if (sp->gen1) {
/* There was another RSCN for this Nport ID */
qla24xx_post_gpnid_work(sp->vha, &ea.id);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
return;
}
sp->u.iocb_cmd.u.ctarg.rsp_dma);
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
return;
}
if (!vha->flags.online)
goto done;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
if (!sp)
goto done;
if (tsp->u.iocb_cmd.u.ctarg.id.b24 == id->b24) {
tsp->gen1++;
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
goto done;
}
}
sp->u.iocb_cmd.u.ctarg.rsp_dma);
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
-
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
ea.rc = res;
qla24xx_handle_gffid_event(vha, &ea);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
/* Get FC4 Feature with Nport ID. */
if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
return rval;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
return rval;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
}
"Async done-%s res %x FC4Type %x\n",
sp->name, res, sp->gen2);
- del_timer(&sp->u.iocb_cmd.timer);
sp->rc = res;
if (res) {
unsigned long flags;
sp->u.iocb_cmd.u.ctarg.rsp_dma);
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
-
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
"%s: Performing FCP Scan\n", __func__);
- if (sp)
- sp->free(sp); /* should not happen */
+ if (sp) {
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
if (!sp) {
spin_lock_irqsave(&vha->work_lock, flags);
sp->u.iocb_cmd.u.ctarg.req,
sp->u.iocb_cmd.u.ctarg.req_dma);
sp->u.iocb_cmd.u.ctarg.req = NULL;
+ /* ref: INIT */
qla2x00_rel_sp(sp);
return rval;
}
sp->u.iocb_cmd.u.ctarg.rsp = NULL;
}
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
qla24xx_handle_gnnid_event(vha, &ea);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
return rval;
qla2x00_set_fcport_disc_state(fcport, DSC_GNN_ID);
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
if (!sp)
goto done;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
fcport->flags &= ~FCF_ASYNC_SENT;
done:
return rval;
qla24xx_handle_gfpnid_event(vha, &ea);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
return rval;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
if (!sp)
goto done;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
WARN_ON(irqs_disabled());
iocb = &sp->u.iocb_cmd;
iocb->timeout(sp);
+
+ /* ref: TMR */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
void qla2x00_sp_free(srb_t *sp)
}
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
- if (sp->cmd_sp)
+ if (sp->cmd_sp) {
+ /*
+ * This done function should take care of
+ * original command ref: INIT
+ */
sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED);
+ }
abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT);
sp->done(sp, QLA_OS_TIMER_EXPIRED);
if (orig_sp)
qla_wait_nvme_release_cmd_kref(orig_sp);
- del_timer(&sp->u.iocb_cmd.timer);
if (sp->flags & SRB_WAKEUP_ON_COMP)
complete(&abt->u.abt.comp);
else
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
srb_t *sp;
int rval = QLA_FUNCTION_FAILED;
+ /* ref: INIT for ABTS command */
sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport,
GFP_ATOMIC);
if (!sp)
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
return rval;
}
wait_for_completion(&abt_iocb->u.abt.comp);
rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
QLA_SUCCESS : QLA_ERR_FROM_FW;
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
return rval;
qla24xx_handle_plogi_done_event(vha, &ea);
}
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int
return rval;
}
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
fcport->flags &= ~FCF_ASYNC_SENT;
done:
fcport->flags &= ~FCF_ASYNC_ACTIVE;
sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
sp->fcport->login_gen++;
qlt_logo_completion_handler(sp->fcport, sp->u.iocb_cmd.u.logio.data[0]);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int
int rval = QLA_FUNCTION_FAILED;
fcport->flags |= FCF_ASYNC_SENT;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
return rval;
if (!test_bit(UNLOADING, &vha->dpc_flags))
qla2x00_post_async_prlo_done_work(sp->fcport->vha, sp->fcport,
lio->u.logio.data);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int
int rval;
rval = QLA_FUNCTION_FAILED;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
fcport->flags &= ~FCF_ASYNC_ACTIVE;
return rval;
ea.sp = sp;
qla24xx_handle_adisc_event(vha, &ea);
-
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int
return rval;
fcport->flags |= FCF_ASYNC_SENT;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
qla2x00_post_async_adisc_work(vha, fcport, data);
}
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
vha->gnl.sent = 1;
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
fcport->flags &= ~(FCF_ASYNC_ACTIVE | FCF_ASYNC_SENT);
return rval;
dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
sp->u.iocb_cmd.u.mbx.in_dma);
- sp->free(sp);
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
qla24xx_handle_prli_done_event(vha, &ea);
}
- sp->free(sp);
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int
return rval;
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;
}
if (pd)
dma_pool_free(ha->s_dma_pool, pd, pd_dma);
- sp->free(sp);
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
fcport->flags &= ~FCF_ASYNC_SENT;
done:
fcport->flags &= ~FCF_ASYNC_ACTIVE;
srb_t *sp;
int rval = QLA_FUNCTION_FAILED;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
}
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
fcport->flags &= ~FCF_ASYNC_SENT;
done:
return rval;
sp->vha = vha;
sp->qpair = qpair;
sp->cmd_type = TYPE_SRB;
+ /* ref : INIT - normal flow */
+ kref_init(&sp->cmd_kref);
INIT_LIST_HEAD(&sp->elem);
}
}
}
+void
+qla2x00_sp_release(struct kref *kref)
+{
+ struct srb *sp = container_of(kref, struct srb, cmd_kref);
+
+ sp->free(sp);
+}
+
void
qla2x00_init_async_sp(srb_t *sp, unsigned long tmo,
void (*done)(struct srb *sp, int res))
return -ENOMEM;
}
- /* Alloc SRB structure */
+ /* Alloc SRB structure
+ * ref: INIT
+ */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp) {
kfree(fcport);
GFP_KERNEL);
if (!elsio->u.els_logo.els_logo_pyld) {
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
return QLA_FUNCTION_FAILED;
}
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
return QLA_FUNCTION_FAILED;
}
wait_for_completion(&elsio->u.els_logo.comp);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
return rval;
}
sp->name, res, sp->handle, fcport->d_id.b24, fcport->port_name);
fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
- del_timer(&sp->u.iocb_cmd.timer);
if (sp->flags & SRB_WAKEUP_ON_COMP)
complete(&lio->u.els_plogi.comp);
struct srb_iocb *elsio = &sp->u.iocb_cmd;
qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
return;
}
e->u.iosb.sp = sp;
int rval = QLA_SUCCESS;
void *ptr, *resp_ptr;
- /* Alloc SRB structure */
+ /* Alloc SRB structure
+ * ref: INIT
+ */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp) {
ql_log(ql_log_info, vha, 0x70e6,
out:
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
break;
}
- if (sp->start_timer)
+ if (sp->start_timer) {
+ /* ref: TMR timer ref
+ * this code should be just before start_iocbs function
+ * This will make sure that caller function don't to do
+ * kref_put even on failure
+ */
+ kref_get(&sp->cmd_kref);
add_timer(&sp->u.iocb_cmd.timer);
+ }
wmb();
qla2x00_start_iocbs(vha, qp->req);
if (!vha->hw->flags.fw_started)
goto done;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
if (!sp)
goto done;
}
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
if (vp_index == 0 || vp_index >= ha->max_npiv_vports)
return QLA_PARAMETER_ERROR;
+ /* ref: INIT */
sp = qla2x00_get_sp(base_vha, NULL, GFP_KERNEL);
if (!sp)
return rval;
break;
}
done:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
return rval;
}
struct register_host_info *preg_hsi;
struct new_utsname *p_sysid = NULL;
+ /* ref: INIT */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
goto done;
dma_free_coherent(&ha->pdev->dev, fdisc->u.fxiocb.req_len,
fdisc->u.fxiocb.req_addr, fdisc->u.fxiocb.req_dma_handle);
done_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
return rval;
}
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
struct completion *comp = sp->comp;
- sp->free(sp);
+ /* kref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
cmd->result = res;
CMD_SP(cmd) = NULL;
scsi_done(cmd);
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
struct completion *comp = sp->comp;
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
cmd->result = res;
CMD_SP(cmd) = NULL;
scsi_done(cmd);
goto qc24_target_busy;
sp = scsi_cmd_priv(cmd);
+ /* ref: INIT */
qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport);
sp->u.scmd.cmd = cmd;
return 0;
qc24_host_busy_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
qc24_target_busy:
return SCSI_MLQUEUE_TARGET_BUSY;
goto qc24_target_busy;
sp = scsi_cmd_priv(cmd);
+ /* ref: INIT */
qla2xxx_init_sp(sp, vha, qpair, fcport);
sp->u.scmd.cmd = cmd;
return 0;
qc24_host_busy_free_sp:
- sp->free(sp);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
qc24_target_busy:
return SCSI_MLQUEUE_TARGET_BUSY;
}
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
- sp->free(sp);
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
}
int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
return rval;
done_free_sp:
- sp->free(sp);
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
fcport->flags &= ~FCF_ASYNC_SENT;
return rval;