if (!sp)
return sp;
+ atomic_set(&sp->ref_count, 1);
sp->fcport = fcport;
sp->cmd = cmd;
sp->flags = 0;
return (return_status);
}
+static void
+sp_get(struct srb *sp)
+{
+ atomic_inc(&sp->ref_count);
+}
+
/**************************************************************************
* qla2xxx_eh_abort
*
struct qla_hw_data *ha = vha->hw;
struct req_que *req = vha->req;
srb_t *spt;
+ int got_ref = 0;
fc_block_scsi_eh(cmd);
DEBUG2(printk("%s(%ld): aborting sp %p from RISC."
" pid=%ld.\n", __func__, vha->host_no, sp, serial));
+ /* Get a reference to the sp and drop the lock.*/
+ sp_get(sp);
+ got_ref++;
+
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (ha->isp_ops->abort_command(sp)) {
DEBUG2(printk("%s(%ld): abort_command "
}
}
+ if (got_ref)
+ qla2x00_sp_compl(ha, sp);
+
qla_printk(KERN_INFO, ha,
"scsi(%ld:%d:%d): Abort command issued -- %d %lx %x.\n",
vha->host_no, id, lun, wait, serial, ret);
}
void
-qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
+qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp)
{
struct scsi_cmnd *cmd = sp->cmd;
cmd->scsi_done(cmd);
}
+void
+qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
+{
+ if (atomic_read(&sp->ref_count) == 0) {
+ DEBUG2(qla_printk(KERN_WARNING, ha,
+ "SP reference-count to ZERO -- sp=%p\n", sp));
+ DEBUG2(BUG());
+ return;
+ }
+ if (!atomic_dec_and_test(&sp->ref_count))
+ return;
+ qla2x00_sp_final_compl(ha, sp);
+}
+
/**************************************************************************
* qla2x00_timer
*