mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-17 10:41:26 +00:00
Micro-optimization: allow target drivers to prealloc scst_cmd + update qla2x00t to use this facility
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4779 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -2453,7 +2453,7 @@ static int q2t_pre_xmit_response(struct q2t_cmd *cmd,
|
||||
scsi_qla_host_t *ha = tgt->ha;
|
||||
scsi_qla_host_t *pha = to_qla_parent(ha);
|
||||
uint16_t full_req_cnt;
|
||||
struct scst_cmd *scst_cmd = cmd->scst_cmd;
|
||||
struct scst_cmd *scst_cmd = &cmd->scst_cmd;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -2751,7 +2751,7 @@ static int q2x_xmit_response(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
int xmit_type = Q2T_XMIT_DATA, res;
|
||||
int is_send_status = scst_cmd_get_is_send_status(scst_cmd);
|
||||
struct q2t_cmd *cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
|
||||
struct q2t_cmd *cmd = container_of(scst_cmd, struct q2t_cmd, scst_cmd);
|
||||
|
||||
#ifdef CONFIG_SCST_EXTRACHECKS
|
||||
sBUG_ON(!q2t_has_data(cmd) && !is_send_status);
|
||||
@@ -3026,7 +3026,7 @@ static int q2t_rdy_to_xfer(struct scst_cmd *scst_cmd)
|
||||
|
||||
TRACE(TRACE_SCSI, "qla2x00t: tag=%lld", scst_cmd_get_tag(scst_cmd));
|
||||
|
||||
cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
|
||||
cmd = container_of(scst_cmd, struct q2t_cmd, scst_cmd);
|
||||
cmd->bufflen = scst_cmd_get_write_fields(scst_cmd, &cmd->sg,
|
||||
&cmd->sg_cnt);
|
||||
cmd->data_direction = scst_cmd_get_data_direction(scst_cmd);
|
||||
@@ -3100,9 +3100,9 @@ out_unlock:
|
||||
|
||||
if (do_tgt_cmd_done) {
|
||||
if (!ha_locked && !in_interrupt())
|
||||
scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_DIRECT);
|
||||
scst_tgt_cmd_done(&cmd->scst_cmd, SCST_CONTEXT_DIRECT);
|
||||
else
|
||||
scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_TASKLET);
|
||||
scst_tgt_cmd_done(&cmd->scst_cmd, SCST_CONTEXT_TASKLET);
|
||||
/* !! At this point cmd could be already freed !! */
|
||||
}
|
||||
|
||||
@@ -3177,9 +3177,9 @@ out_unlock:
|
||||
|
||||
if (do_tgt_cmd_done) {
|
||||
if (!ha_locked && !in_interrupt())
|
||||
scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_DIRECT);
|
||||
scst_tgt_cmd_done(&cmd->scst_cmd, SCST_CONTEXT_DIRECT);
|
||||
else
|
||||
scst_tgt_cmd_done(cmd->scst_cmd, SCST_CONTEXT_TASKLET);
|
||||
scst_tgt_cmd_done(&cmd->scst_cmd, SCST_CONTEXT_TASKLET);
|
||||
/* !! At this point cmd could be already freed !! */
|
||||
}
|
||||
|
||||
@@ -3206,8 +3206,7 @@ static void q2t_on_free_cmd(struct scst_cmd *scst_cmd)
|
||||
TRACE(TRACE_SCSI, "qla2x00t: Freeing command %p, tag %lld",
|
||||
scst_cmd, scst_cmd_get_tag(scst_cmd));
|
||||
|
||||
cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
|
||||
scst_cmd_set_tgt_priv(scst_cmd, NULL);
|
||||
cmd = container_of(scst_cmd, struct q2t_cmd, scst_cmd);
|
||||
|
||||
q2t_free_cmd(cmd);
|
||||
|
||||
@@ -3236,8 +3235,7 @@ static int q2t_prepare_srr_ctio(scsi_qla_host_t *ha, struct q2t_cmd *cmd,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cmd->scst_cmd != NULL)
|
||||
scst_update_hw_pending_start(cmd->scst_cmd);
|
||||
scst_update_hw_pending_start(&cmd->scst_cmd);
|
||||
|
||||
sc = kzalloc(sizeof(*sc), GFP_ATOMIC);
|
||||
if (sc != NULL) {
|
||||
@@ -3410,7 +3408,7 @@ static struct q2t_cmd *q2t_ctio_to_cmd(scsi_qla_host_t *ha, uint32_t handle,
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
|
||||
cmd = container_of(scst_cmd, struct q2t_cmd, scst_cmd);
|
||||
TRACE_DBG("Found q2t_cmd %p (tag %d)", cmd, tag);
|
||||
}
|
||||
|
||||
@@ -3455,7 +3453,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, uint32_t handle,
|
||||
goto out;
|
||||
}
|
||||
|
||||
scst_cmd = cmd->scst_cmd;
|
||||
scst_cmd = &cmd->scst_cmd;
|
||||
|
||||
if (cmd->sg_mapped)
|
||||
q2t_unmap_sg(ha, cmd);
|
||||
@@ -3565,7 +3563,7 @@ static void q2x_ctio_completion(scsi_qla_host_t *ha, uint32_t handle)
|
||||
/* pha->hardware_lock supposed to be held on entry */
|
||||
static int q2x_do_send_cmd_to_scst(struct q2t_cmd *cmd)
|
||||
{
|
||||
int res = 0;
|
||||
int res;
|
||||
struct q2t_sess *sess = cmd->sess;
|
||||
uint16_t lun;
|
||||
atio_entry_t *atio = &cmd->atio.atio2x;
|
||||
@@ -3576,19 +3574,14 @@ static int q2x_do_send_cmd_to_scst(struct q2t_cmd *cmd)
|
||||
|
||||
/* make it be in network byte order */
|
||||
lun = swab16(le16_to_cpu(atio->lun));
|
||||
cmd->scst_cmd = scst_rx_cmd(sess->scst_sess, (uint8_t *)&lun,
|
||||
sizeof(lun), atio->cdb, Q2T_MAX_CDB_LEN,
|
||||
SCST_ATOMIC);
|
||||
|
||||
if (cmd->scst_cmd == NULL) {
|
||||
PRINT_ERROR("%s", "qla2x00t: scst_rx_cmd() failed");
|
||||
res = -EFAULT;
|
||||
res = scst_rx_cmd_prealloced(&cmd->scst_cmd, sess->scst_sess,
|
||||
(uint8_t *)&lun, sizeof(lun), atio->cdb,
|
||||
Q2T_MAX_CDB_LEN, SCST_ATOMIC);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->tag = atio->rx_id;
|
||||
scst_cmd_set_tag(cmd->scst_cmd, cmd->tag);
|
||||
scst_cmd_set_tgt_priv(cmd->scst_cmd, cmd);
|
||||
scst_cmd_set_tag(&cmd->scst_cmd, cmd->tag);
|
||||
|
||||
if ((atio->execution_codes & (ATIO_EXEC_READ | ATIO_EXEC_WRITE)) ==
|
||||
(ATIO_EXEC_READ | ATIO_EXEC_WRITE))
|
||||
@@ -3599,29 +3592,29 @@ static int q2x_do_send_cmd_to_scst(struct q2t_cmd *cmd)
|
||||
dir = SCST_DATA_WRITE;
|
||||
else
|
||||
dir = SCST_DATA_NONE;
|
||||
scst_cmd_set_expected(cmd->scst_cmd, dir,
|
||||
scst_cmd_set_expected(&cmd->scst_cmd, dir,
|
||||
le32_to_cpu(atio->data_length));
|
||||
|
||||
switch (atio->task_codes) {
|
||||
case ATIO_SIMPLE_QUEUE:
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_SIMPLE);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_SIMPLE);
|
||||
break;
|
||||
case ATIO_HEAD_OF_QUEUE:
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
|
||||
break;
|
||||
case ATIO_ORDERED_QUEUE:
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
|
||||
break;
|
||||
case ATIO_ACA_QUEUE:
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ACA);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_ACA);
|
||||
break;
|
||||
case ATIO_UNTAGGED:
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
|
||||
break;
|
||||
default:
|
||||
PRINT_WARNING("qla2x00t: unknown task code %x, use "
|
||||
"ORDERED instead", atio->task_codes);
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3633,8 +3626,8 @@ static int q2x_do_send_cmd_to_scst(struct q2t_cmd *cmd)
|
||||
|
||||
TRACE_DBG("Context %x", context);
|
||||
TRACE(TRACE_SCSI, "qla2x00t: START Command (tag %d, queue_type %d)",
|
||||
cmd->tag, scst_cmd_get_queue_type(cmd->scst_cmd));
|
||||
scst_cmd_init_done(cmd->scst_cmd, context);
|
||||
cmd->tag, scst_cmd_get_queue_type(&cmd->scst_cmd));
|
||||
scst_cmd_init_done(&cmd->scst_cmd, context);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
@@ -3644,7 +3637,7 @@ out:
|
||||
/* pha->hardware_lock supposed to be held on entry */
|
||||
static int q24_do_send_cmd_to_scst(struct q2t_cmd *cmd)
|
||||
{
|
||||
int res = 0;
|
||||
int res;
|
||||
struct q2t_sess *sess = cmd->sess;
|
||||
atio7_entry_t *atio = &cmd->atio.atio7;
|
||||
scst_data_direction dir;
|
||||
@@ -3652,20 +3645,15 @@ static int q24_do_send_cmd_to_scst(struct q2t_cmd *cmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
cmd->scst_cmd = scst_rx_cmd(sess->scst_sess,
|
||||
res = scst_rx_cmd_prealloced(&cmd->scst_cmd, sess->scst_sess,
|
||||
(uint8_t *)&atio->fcp_cmnd.lun, sizeof(atio->fcp_cmnd.lun),
|
||||
atio->fcp_cmnd.cdb, sizeof(atio->fcp_cmnd.cdb) +
|
||||
atio->fcp_cmnd.add_cdb_len, SCST_ATOMIC);
|
||||
|
||||
if (cmd->scst_cmd == NULL) {
|
||||
PRINT_ERROR("%s", "qla2x00t: scst_rx_cmd() failed");
|
||||
res = -EFAULT;
|
||||
if (res != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->tag = atio->exchange_addr;
|
||||
scst_cmd_set_tag(cmd->scst_cmd, cmd->tag);
|
||||
scst_cmd_set_tgt_priv(cmd->scst_cmd, cmd);
|
||||
scst_cmd_set_tag(&cmd->scst_cmd, cmd->tag);
|
||||
|
||||
if (atio->fcp_cmnd.rddata && atio->fcp_cmnd.wrdata)
|
||||
dir = SCST_DATA_BIDI;
|
||||
@@ -3675,30 +3663,30 @@ static int q24_do_send_cmd_to_scst(struct q2t_cmd *cmd)
|
||||
dir = SCST_DATA_WRITE;
|
||||
else
|
||||
dir = SCST_DATA_NONE;
|
||||
scst_cmd_set_expected(cmd->scst_cmd, dir,
|
||||
scst_cmd_set_expected(&cmd->scst_cmd, dir,
|
||||
get_unaligned_be32(
|
||||
&atio->fcp_cmnd.add_cdb[atio->fcp_cmnd.add_cdb_len]));
|
||||
|
||||
switch (atio->fcp_cmnd.task_attr) {
|
||||
case ATIO_SIMPLE_QUEUE:
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_SIMPLE);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_SIMPLE);
|
||||
break;
|
||||
case ATIO_HEAD_OF_QUEUE:
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_HEAD_OF_QUEUE);
|
||||
break;
|
||||
case ATIO_ORDERED_QUEUE:
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
|
||||
break;
|
||||
case ATIO_ACA_QUEUE:
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ACA);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_ACA);
|
||||
break;
|
||||
case ATIO_UNTAGGED:
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_UNTAGGED);
|
||||
break;
|
||||
default:
|
||||
PRINT_WARNING("qla2x00t: unknown task code %x, use "
|
||||
"ORDERED instead", atio->fcp_cmnd.task_attr);
|
||||
scst_cmd_set_queue_type(cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
|
||||
scst_cmd_set_queue_type(&cmd->scst_cmd, SCST_CMD_QUEUE_ORDERED);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3710,8 +3698,8 @@ static int q24_do_send_cmd_to_scst(struct q2t_cmd *cmd)
|
||||
|
||||
TRACE_DBG("Context %x", context);
|
||||
TRACE(TRACE_SCSI, "qla2x00t: START Command %p (tag %d, queue type %x)",
|
||||
cmd, cmd->tag, scst_cmd_get_queue_type(cmd->scst_cmd));
|
||||
scst_cmd_init_done(cmd->scst_cmd, context);
|
||||
cmd, cmd->tag, scst_cmd_get_queue_type(&cmd->scst_cmd));
|
||||
scst_cmd_init_done(&cmd->scst_cmd, context);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
@@ -4293,9 +4281,9 @@ static void q24_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
|
||||
__q24_xmit_response(cmd, Q2T_XMIT_STATUS);
|
||||
break;
|
||||
case SRR_IU_DATA_IN:
|
||||
cmd->bufflen = scst_cmd_get_adjusted_resp_data_len(cmd->scst_cmd);
|
||||
cmd->bufflen = scst_cmd_get_adjusted_resp_data_len(&cmd->scst_cmd);
|
||||
if (q2t_has_data(cmd) &&
|
||||
(scst_cmd_get_data_direction(cmd->scst_cmd) & SCST_DATA_READ)) {
|
||||
(scst_cmd_get_data_direction(&cmd->scst_cmd) & SCST_DATA_READ)) {
|
||||
uint32_t offset;
|
||||
int xmit_type;
|
||||
offset = le32_to_cpu(imm->imm.notify_entry24.srr_rel_offs);
|
||||
@@ -4310,16 +4298,16 @@ static void q24_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
|
||||
PRINT_ERROR("qla2x00t(%ld): SRR for in data for cmd "
|
||||
"without them (tag %d, SCSI status %d, dir %d),"
|
||||
" reject", ha->instance, cmd->tag,
|
||||
scst_cmd_get_status(cmd->scst_cmd),
|
||||
scst_cmd_get_data_direction(cmd->scst_cmd));
|
||||
scst_cmd_get_status(&cmd->scst_cmd),
|
||||
scst_cmd_get_data_direction(&cmd->scst_cmd));
|
||||
goto out_reject;
|
||||
}
|
||||
break;
|
||||
case SRR_IU_DATA_OUT:
|
||||
cmd->bufflen = scst_cmd_get_write_fields(cmd->scst_cmd,
|
||||
cmd->bufflen = scst_cmd_get_write_fields(&cmd->scst_cmd,
|
||||
&cmd->sg, &cmd->sg_cnt);
|
||||
if (q2t_has_data(cmd) &&
|
||||
(scst_cmd_get_data_direction(cmd->scst_cmd) & SCST_DATA_WRITE)) {
|
||||
(scst_cmd_get_data_direction(&cmd->scst_cmd) & SCST_DATA_WRITE)) {
|
||||
uint32_t offset;
|
||||
int xmit_type;
|
||||
offset = le32_to_cpu(imm->imm.notify_entry24.srr_rel_offs);
|
||||
@@ -4335,8 +4323,8 @@ static void q24_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
|
||||
PRINT_ERROR("qla2x00t(%ld): SRR for out data for cmd "
|
||||
"without them (tag %d, SCSI status %d, dir %d),"
|
||||
" reject", ha->instance, cmd->tag,
|
||||
scst_cmd_get_status(cmd->scst_cmd),
|
||||
scst_cmd_get_data_direction(cmd->scst_cmd));
|
||||
scst_cmd_get_status(&cmd->scst_cmd),
|
||||
scst_cmd_get_data_direction(&cmd->scst_cmd));
|
||||
goto out_reject;
|
||||
}
|
||||
break;
|
||||
@@ -4357,7 +4345,7 @@ out_reject:
|
||||
NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
|
||||
if (cmd->state == Q2T_STATE_NEED_DATA) {
|
||||
cmd->state = Q2T_STATE_DATA_IN;
|
||||
scst_rx_data(cmd->scst_cmd, SCST_RX_STATUS_ERROR,
|
||||
scst_rx_data(&cmd->scst_cmd, SCST_RX_STATUS_ERROR,
|
||||
SCST_CONTEXT_THREAD);
|
||||
} else
|
||||
q24_send_term_exchange(ha, cmd, &cmd->atio.atio7, 1);
|
||||
@@ -4386,7 +4374,7 @@ static void q2x_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
|
||||
__q2x_xmit_response(cmd, Q2T_XMIT_STATUS);
|
||||
break;
|
||||
case SRR_IU_DATA_IN:
|
||||
cmd->bufflen = scst_cmd_get_adjusted_resp_data_len(cmd->scst_cmd);
|
||||
cmd->bufflen = scst_cmd_get_adjusted_resp_data_len(&cmd->scst_cmd);
|
||||
if (q2t_has_data(cmd)) {
|
||||
uint32_t offset;
|
||||
int xmit_type;
|
||||
@@ -4402,12 +4390,12 @@ static void q2x_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
|
||||
PRINT_ERROR("qla2x00t(%ld): SRR for in data for cmd "
|
||||
"without them (tag %d, SCSI status %d), "
|
||||
"reject", ha->instance, cmd->tag,
|
||||
scst_cmd_get_status(cmd->scst_cmd));
|
||||
scst_cmd_get_status(&cmd->scst_cmd));
|
||||
goto out_reject;
|
||||
}
|
||||
break;
|
||||
case SRR_IU_DATA_OUT:
|
||||
cmd->bufflen = scst_cmd_get_write_fields(cmd->scst_cmd,
|
||||
cmd->bufflen = scst_cmd_get_write_fields(&cmd->scst_cmd,
|
||||
&cmd->sg, &cmd->sg_cnt);
|
||||
if (q2t_has_data(cmd)) {
|
||||
uint32_t offset;
|
||||
@@ -4425,7 +4413,7 @@ static void q2x_handle_srr(scsi_qla_host_t *ha, struct srr_ctio *sctio,
|
||||
PRINT_ERROR("qla2x00t(%ld): SRR for out data for cmd "
|
||||
"without them (tag %d, SCSI status %d), "
|
||||
"reject", ha->instance, cmd->tag,
|
||||
scst_cmd_get_status(cmd->scst_cmd));
|
||||
scst_cmd_get_status(&cmd->scst_cmd));
|
||||
goto out_reject;
|
||||
}
|
||||
break;
|
||||
@@ -4446,7 +4434,7 @@ out_reject:
|
||||
NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL);
|
||||
if (cmd->state == Q2T_STATE_NEED_DATA) {
|
||||
cmd->state = Q2T_STATE_DATA_IN;
|
||||
scst_rx_data(cmd->scst_cmd, SCST_RX_STATUS_ERROR,
|
||||
scst_rx_data(&cmd->scst_cmd, SCST_RX_STATUS_ERROR,
|
||||
SCST_CONTEXT_THREAD);
|
||||
} else
|
||||
q2x_send_term_exchange(ha, cmd, &cmd->atio.atio2x, 1);
|
||||
@@ -4529,17 +4517,17 @@ restart:
|
||||
cmd = sctio->cmd;
|
||||
|
||||
/* Restore the originals, except bufflen */
|
||||
cmd->offset = scst_cmd_get_ppl_offset(cmd->scst_cmd);
|
||||
cmd->offset = scst_cmd_get_ppl_offset(&cmd->scst_cmd);
|
||||
if (cmd->free_sg) {
|
||||
kfree(cmd->sg);
|
||||
cmd->free_sg = 0;
|
||||
}
|
||||
cmd->sg = scst_cmd_get_sg(cmd->scst_cmd);
|
||||
cmd->sg_cnt = scst_cmd_get_sg_cnt(cmd->scst_cmd);
|
||||
cmd->sg = scst_cmd_get_sg(&cmd->scst_cmd);
|
||||
cmd->sg_cnt = scst_cmd_get_sg_cnt(&cmd->scst_cmd);
|
||||
|
||||
TRACE_MGMT_DBG("SRR cmd %p (scst_cmd %p, tag %d, op %x), "
|
||||
"sg_cnt=%d, offset=%d", cmd, cmd->scst_cmd,
|
||||
cmd->tag, cmd->scst_cmd->cdb[0], cmd->sg_cnt,
|
||||
"sg_cnt=%d, offset=%d", cmd, &cmd->scst_cmd,
|
||||
cmd->tag, cmd->scst_cmd.cdb[0], cmd->sg_cnt,
|
||||
cmd->offset);
|
||||
|
||||
if (IS_FWI2_CAPABLE(ha))
|
||||
@@ -5685,7 +5673,7 @@ static void q2t_cleanup_hw_pending_cmd(scsi_qla_host_t *ha, struct q2t_cmd *cmd)
|
||||
|
||||
static void q2t_on_hw_pending_cmd_timeout(struct scst_cmd *scst_cmd)
|
||||
{
|
||||
struct q2t_cmd *cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
|
||||
struct q2t_cmd *cmd = container_of(scst_cmd, struct q2t_cmd, scst_cmd);
|
||||
struct q2t_tgt *tgt = cmd->tgt;
|
||||
scsi_qla_host_t *ha = tgt->ha;
|
||||
scsi_qla_host_t *pha = to_qla_parent(ha);
|
||||
|
||||
@@ -196,7 +196,6 @@ struct q2t_sess {
|
||||
struct q2t_cmd {
|
||||
struct q2t_sess *sess;
|
||||
int state;
|
||||
struct scst_cmd *scst_cmd;
|
||||
|
||||
unsigned int conf_compl_supported:1;/* to save extra sess dereferences */
|
||||
unsigned int sg_mapped:1;
|
||||
@@ -220,6 +219,8 @@ struct q2t_cmd {
|
||||
atio7_entry_t atio7;
|
||||
atio_entry_t atio2x;
|
||||
} __packed atio;
|
||||
|
||||
struct scst_cmd scst_cmd;
|
||||
};
|
||||
|
||||
struct q2t_sess_work_param {
|
||||
|
||||
@@ -753,6 +753,13 @@ struct scst_tgt_template {
|
||||
* Necessary, because for aborted commands xmit_response() could not
|
||||
* be called. Could be called on IRQ context.
|
||||
*
|
||||
* This callback is called when the last reference to cmd is dropped,
|
||||
* which can be much later after scst_tgt_cmd_done() called by the
|
||||
* target driver, so it is not recommended that the target driver
|
||||
* clean hardware or connection related cmd resources in this callback.
|
||||
* It is recommended to clean them before calling scst_tgt_cmd_done()
|
||||
* instead.
|
||||
*
|
||||
* OPTIONAL
|
||||
*/
|
||||
void (*on_free_cmd) (struct scst_cmd *cmd);
|
||||
@@ -1984,6 +1991,9 @@ struct scst_cmd {
|
||||
*/
|
||||
unsigned int finished:1;
|
||||
|
||||
/* Set if cmd was pre-alloced by target driver */
|
||||
unsigned int pre_alloced:1;
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
/* cmd's async flags */
|
||||
@@ -2867,7 +2877,10 @@ bool scst_initiator_has_luns(struct scst_tgt *tgt, const char *initiator_name);
|
||||
|
||||
struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
|
||||
const uint8_t *lun, int lun_len, const uint8_t *cdb,
|
||||
unsigned int cdb_len, int atomic);
|
||||
unsigned int cdb_len, bool atomic);
|
||||
int scst_rx_cmd_prealloced(struct scst_cmd *cmd, struct scst_session *sess,
|
||||
const uint8_t *lun, int lun_len, const uint8_t *cdb,
|
||||
unsigned int cdb_len, bool atomic);
|
||||
void scst_cmd_init_done(struct scst_cmd *cmd,
|
||||
enum scst_exec_context pref_context);
|
||||
|
||||
|
||||
@@ -5273,18 +5273,22 @@ out_err:
|
||||
}
|
||||
EXPORT_SYMBOL(scst_cmd_set_ext_cdb);
|
||||
|
||||
struct scst_cmd *scst_alloc_cmd(const uint8_t *cdb,
|
||||
int scst_pre_init_cmd(struct scst_cmd *cmd, const uint8_t *cdb,
|
||||
unsigned int cdb_len, gfp_t gfp_mask)
|
||||
{
|
||||
struct scst_cmd *cmd;
|
||||
int res;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
cmd = kmem_cache_zalloc(scst_cmd_cachep, gfp_mask);
|
||||
if (cmd == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of scst_cmd failed");
|
||||
goto out;
|
||||
#ifdef CONFIG_SCST_EXTRACHECKS
|
||||
/* cmd supposed to be zeroed */
|
||||
{
|
||||
int i;
|
||||
uint8_t *b = (uint8_t *)cmd;
|
||||
for (i = 0; i < sizeof(*cmd); i++)
|
||||
EXTRACHECKS_BUG_ON(b[i] != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
cmd->state = SCST_CMD_STATE_INIT_WAIT;
|
||||
cmd->start_time = jiffies;
|
||||
@@ -5310,26 +5314,54 @@ struct scst_cmd *scst_alloc_cmd(const uint8_t *cdb,
|
||||
|
||||
if (unlikely(cdb_len == 0)) {
|
||||
PRINT_ERROR("%s", "Wrong CDB len 0, finishing cmd");
|
||||
goto out_free;
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
} else if (cdb_len <= SCST_MAX_CDB_SIZE) {
|
||||
/* Duplicate memcpy to save a branch on the most common path */
|
||||
memcpy(cmd->cdb, cdb, cdb_len);
|
||||
} else {
|
||||
if (unlikely(cdb_len > SCST_MAX_LONG_CDB_SIZE)) {
|
||||
PRINT_ERROR("Too big CDB (%d), finishing cmd", cdb_len);
|
||||
goto out_free;
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
cmd->cdb = kmalloc(cdb_len, gfp_mask);
|
||||
if (unlikely(cmd->cdb == NULL)) {
|
||||
PRINT_ERROR("Unable to alloc extended CDB (size %d)",
|
||||
cdb_len);
|
||||
goto out_free;
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memcpy(cmd->cdb, cdb, cdb_len);
|
||||
}
|
||||
|
||||
cmd->cdb_len = cdb_len;
|
||||
|
||||
res = 0;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
struct scst_cmd *scst_alloc_cmd(const uint8_t *cdb,
|
||||
unsigned int cdb_len, gfp_t gfp_mask)
|
||||
{
|
||||
struct scst_cmd *cmd;
|
||||
int rc;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
cmd = kmem_cache_zalloc(scst_cmd_cachep, gfp_mask);
|
||||
if (cmd == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of scst_cmd failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = scst_pre_init_cmd(cmd, cdb, cdb_len, gfp_mask);
|
||||
if (unlikely(rc != 0))
|
||||
goto out_free;
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return cmd;
|
||||
@@ -5342,6 +5374,8 @@ out_free:
|
||||
|
||||
static void scst_destroy_cmd(struct scst_cmd *cmd)
|
||||
{
|
||||
bool pre_alloced = cmd->pre_alloced;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("Destroying cmd %p", cmd);
|
||||
@@ -5354,7 +5388,20 @@ static void scst_destroy_cmd(struct scst_cmd *cmd)
|
||||
if (likely(cmd->tgt_dev != NULL))
|
||||
scst_put(cmd->cpu_cmd_counter);
|
||||
|
||||
kmem_cache_free(scst_cmd_cachep, cmd);
|
||||
EXTRACHECKS_BUG_ON(cmd->pre_alloced && cmd->internal);
|
||||
|
||||
if ((cmd->tgtt->on_free_cmd != NULL) && likely(!cmd->internal)) {
|
||||
TRACE_DBG("Calling target's on_free_cmd(%p)", cmd);
|
||||
scst_set_cur_start(cmd);
|
||||
cmd->tgtt->on_free_cmd(cmd);
|
||||
scst_set_tgt_on_free_time(cmd);
|
||||
TRACE_DBG("%s", "Target's on_free_cmd() returned");
|
||||
}
|
||||
|
||||
/* At this point cmd can be already freed! */
|
||||
|
||||
if (!pre_alloced)
|
||||
kmem_cache_free(scst_cmd_cachep, cmd);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
@@ -5383,14 +5430,6 @@ void scst_free_cmd(struct scst_cmd *cmd)
|
||||
if (!cmd->tgt_i_data_buf_alloced)
|
||||
scst_check_restore_sg_buff(cmd);
|
||||
|
||||
if ((cmd->tgtt->on_free_cmd != NULL) && likely(!cmd->internal)) {
|
||||
TRACE_DBG("Calling target's on_free_cmd(%p)", cmd);
|
||||
scst_set_cur_start(cmd);
|
||||
cmd->tgtt->on_free_cmd(cmd);
|
||||
scst_set_tgt_on_free_time(cmd);
|
||||
TRACE_DBG("%s", "Target's on_free_cmd() returned");
|
||||
}
|
||||
|
||||
if (likely(cmd->dev != NULL)) {
|
||||
struct scst_dev_type *devt = cmd->devt;
|
||||
if (devt->on_free_cmd != NULL) {
|
||||
|
||||
@@ -666,6 +666,8 @@ static inline void scst_sess_put(struct scst_session *sess)
|
||||
|
||||
struct scst_cmd *scst_alloc_cmd(const uint8_t *cdb,
|
||||
unsigned int cdb_len, gfp_t gfp_mask);
|
||||
int scst_pre_init_cmd(struct scst_cmd *cmd, const uint8_t *cdb,
|
||||
unsigned int cdb_len, gfp_t gfp_mask);
|
||||
void scst_free_cmd(struct scst_cmd *cmd);
|
||||
|
||||
static inline void __scst_cmd_get(struct scst_cmd *cmd)
|
||||
|
||||
@@ -179,6 +179,78 @@ static void scst_check_unblock_dev(struct scst_cmd *cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
static void __scst_rx_cmd(struct scst_cmd *cmd, struct scst_session *sess,
|
||||
const uint8_t *lun, int lun_len, gfp_t gfp_mask)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
cmd->sess = sess;
|
||||
scst_sess_get(sess);
|
||||
|
||||
cmd->tgt = sess->tgt;
|
||||
cmd->tgtt = sess->tgt->tgtt;
|
||||
|
||||
cmd->lun = scst_unpack_lun(lun, lun_len);
|
||||
if (unlikely(cmd->lun == NO_SUCH_LUN))
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_lun_not_supported));
|
||||
|
||||
TRACE_DBG("cmd %p, sess %p", cmd, sess);
|
||||
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* scst_rx_cmd_prealloced() - notify SCST that new command received
|
||||
* @cmd: new cmd to initialized
|
||||
* @sess: SCST session
|
||||
* @lun: LUN for the command
|
||||
* @lun_len: length of the LUN in bytes
|
||||
* @cdb: CDB of the command
|
||||
* @cdb_len: length of the CDB in bytes
|
||||
* @atomic: true, if current context is atomic
|
||||
*
|
||||
* Description:
|
||||
* Initializes new prealloced SCST command. Returns 0 on success or
|
||||
* negative error code otherwise.
|
||||
*
|
||||
* Must not be called in parallel with scst_unregister_session() for the
|
||||
* same session.
|
||||
*
|
||||
* Cmd supposed to be zeroed!
|
||||
*/
|
||||
int scst_rx_cmd_prealloced(struct scst_cmd *cmd, struct scst_session *sess,
|
||||
const uint8_t *lun, int lun_len, const uint8_t *cdb,
|
||||
unsigned int cdb_len, bool atomic)
|
||||
{
|
||||
int res;
|
||||
gfp_t gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
#ifdef CONFIG_SCST_EXTRACHECKS
|
||||
if (unlikely(sess->shut_phase != SCST_SESS_SPH_READY)) {
|
||||
PRINT_CRIT_ERROR("%s",
|
||||
"New cmd while shutting down the session");
|
||||
sBUG();
|
||||
}
|
||||
#endif
|
||||
|
||||
res = scst_pre_init_cmd(cmd, cdb, cdb_len, gfp_mask);
|
||||
if (unlikely(res != 0))
|
||||
goto out;
|
||||
|
||||
__scst_rx_cmd(cmd, sess, lun, lun_len, gfp_mask);
|
||||
|
||||
cmd->pre_alloced = 1;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_rx_cmd_prealloced);
|
||||
|
||||
/**
|
||||
* scst_rx_cmd() - create new command
|
||||
* @sess: SCST session
|
||||
@@ -197,9 +269,10 @@ static void scst_check_unblock_dev(struct scst_cmd *cmd)
|
||||
*/
|
||||
struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
|
||||
const uint8_t *lun, int lun_len, const uint8_t *cdb,
|
||||
unsigned int cdb_len, int atomic)
|
||||
unsigned int cdb_len, bool atomic)
|
||||
{
|
||||
struct scst_cmd *cmd;
|
||||
gfp_t gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
@@ -211,22 +284,15 @@ struct scst_cmd *scst_rx_cmd(struct scst_session *sess,
|
||||
}
|
||||
#endif
|
||||
|
||||
cmd = scst_alloc_cmd(cdb, cdb_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
|
||||
if (unlikely(cmd == NULL))
|
||||
cmd = scst_alloc_cmd(cdb, cdb_len, gfp_mask);
|
||||
if (cmd == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of scst_cmd failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->sess = sess;
|
||||
scst_sess_get(sess);
|
||||
__scst_rx_cmd(cmd, sess, lun, lun_len, gfp_mask);
|
||||
|
||||
cmd->tgt = sess->tgt;
|
||||
cmd->tgtt = sess->tgt->tgtt;
|
||||
|
||||
cmd->lun = scst_unpack_lun(lun, lun_len);
|
||||
if (unlikely(cmd->lun == NO_SUCH_LUN))
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_lun_not_supported));
|
||||
|
||||
TRACE_DBG("cmd %p, sess %p", cmd, sess);
|
||||
cmd->pre_alloced = 0;
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
|
||||
Reference in New Issue
Block a user