mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-19 03:31:26 +00:00
Added possibility to coexist if both target driver and dev handler need custom memory allocation. Direct consequences:
1. scst_local can work with scst_user's devices 2. scst_user now compatible with iscsi-scst if put_page_callback not applied + some cosmetics git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@567 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -1322,13 +1322,13 @@ static int scsi_cmnd_start(struct iscsi_cmnd *req)
|
||||
req->scst_cmd = scst_cmd;
|
||||
scst_cmd_set_tag(scst_cmd, req_hdr->itt);
|
||||
scst_cmd_set_tgt_priv(scst_cmd, req);
|
||||
#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
|
||||
scst_cmd_set_data_buf_tgt_alloc(scst_cmd);
|
||||
#endif
|
||||
|
||||
if (req_hdr->flags & ISCSI_CMD_READ)
|
||||
if (req_hdr->flags & ISCSI_CMD_READ) {
|
||||
dir = SCST_DATA_READ;
|
||||
else if (req_hdr->flags & ISCSI_CMD_WRITE)
|
||||
#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
|
||||
scst_cmd_set_tgt_need_alloc_data_buf(scst_cmd);
|
||||
#endif
|
||||
} else if (req_hdr->flags & ISCSI_CMD_WRITE)
|
||||
dir = SCST_DATA_WRITE;
|
||||
else
|
||||
dir = SCST_DATA_NONE;
|
||||
@@ -2451,16 +2451,15 @@ out_rejected:
|
||||
#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
|
||||
static int iscsi_alloc_data_buf(struct scst_cmd *cmd)
|
||||
{
|
||||
if (scst_cmd_get_data_direction(cmd) == SCST_DATA_READ) {
|
||||
/*
|
||||
* sock->ops->sendpage() is async zero copy operation,
|
||||
* so we must be sure not to free and reuse
|
||||
* the command's buffer before the sending was completed
|
||||
* by the network layers. It is possible only if we
|
||||
* don't use SGV cache.
|
||||
*/
|
||||
scst_cmd_set_no_sgv(cmd);
|
||||
}
|
||||
/*
|
||||
* sock->ops->sendpage() is async zero copy operation,
|
||||
* so we must be sure not to free and reuse
|
||||
* the command's buffer before the sending was completed
|
||||
* by the network layers. It is possible only if we
|
||||
* don't use SGV cache.
|
||||
*/
|
||||
EXTRACHECKS_BUG_ON(scst_cmd_get_data_direction(cmd) != SCST_DATA_READ);
|
||||
scst_cmd_set_no_sgv(cmd);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
@@ -2982,9 +2981,9 @@ out_reg:
|
||||
out_callb:
|
||||
#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
|
||||
net_set_get_put_page_callbacks(NULL, NULL);
|
||||
#endif
|
||||
|
||||
out_free_dummy:
|
||||
#endif
|
||||
__free_pages(dummy_page, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1046,7 +1046,7 @@ static int write_data(struct iscsi_conn *conn)
|
||||
sock_sendpage = sock->ops->sendpage;
|
||||
#else
|
||||
if ((write_cmnd->parent_req->scst_cmd != NULL) &&
|
||||
scst_cmd_get_data_buff_alloced(write_cmnd->parent_req->scst_cmd))
|
||||
scst_cmd_get_dh_data_buff_alloced(write_cmnd->parent_req->scst_cmd))
|
||||
sock_sendpage = sock_no_sendpage;
|
||||
else
|
||||
sock_sendpage = sock->ops->sendpage;
|
||||
|
||||
@@ -548,9 +548,13 @@ struct scst_tgt_template {
|
||||
*
|
||||
* Shall return 0 in case of success or < 0 (preferrably -ENOMEM)
|
||||
* in case of error, or > 0 if the regular SCST allocation should be
|
||||
* done. In case of returning successfully, scst_cmd->data_buf_alloced
|
||||
* done. In case of returning successfully, scst_cmd->tgt_data_buf_alloced
|
||||
* will be set by SCST.
|
||||
*
|
||||
* It is possible that both target driver and dev handler request own
|
||||
* memory allocation. In this case, data will be memcpy() between
|
||||
* buffers, where necessary.
|
||||
*
|
||||
* If allocation in atomic context - cf. scst_cmd_atomic() - is not
|
||||
* desired or fails and consequently < 0 is returned, this function
|
||||
* will be re-called in thread context.
|
||||
@@ -1051,13 +1055,16 @@ struct scst_cmd {
|
||||
* In this case alloc_data_buf() must be provided in the target driver
|
||||
* template.
|
||||
*/
|
||||
unsigned int data_buf_tgt_alloc:1;
|
||||
unsigned int tgt_need_alloc_data_buf:1;
|
||||
|
||||
/*
|
||||
* Set by SCST if the custom data buffer allocation by the target driver
|
||||
* succeeded.
|
||||
*/
|
||||
unsigned int data_buf_alloced:1;
|
||||
unsigned int tgt_data_buf_alloced:1;
|
||||
|
||||
/* Set if custom data buffer allocated by dev handler */
|
||||
unsigned int dh_data_buf_alloced:1;
|
||||
|
||||
/* Set if the target driver called scst_set_expected() */
|
||||
unsigned int expected_values_set:1;
|
||||
@@ -1208,6 +1215,18 @@ struct scst_cmd {
|
||||
*/
|
||||
int resp_data_len;
|
||||
|
||||
/*
|
||||
* Used if both target driver and dev handler request own memory
|
||||
* allocation. In other cases, both are equal to sg and sg_cnt
|
||||
* correspondingly.
|
||||
*
|
||||
* If target driver requests own memory allocations, it MUST use
|
||||
* functions scst_cmd_get_tgt_sg*() to get sg and sg_cnt! Otherwise,
|
||||
* it may use functions scst_cmd_get_sg*().
|
||||
*/
|
||||
struct scatterlist *tgt_sg;
|
||||
int tgt_sg_cnt;
|
||||
|
||||
/*
|
||||
* The status fields in case of errors must be set using
|
||||
* scst_set_cmd_error_status()!
|
||||
@@ -2073,6 +2092,17 @@ static inline struct scatterlist *scst_cmd_get_sg(struct scst_cmd *cmd)
|
||||
return cmd->sg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns cmd's sg_cnt.
|
||||
*
|
||||
* Usage of this function is not recommended, use scst_get_buf_*()
|
||||
* family of functions instead.
|
||||
*/
|
||||
static inline unsigned int scst_cmd_get_sg_cnt(struct scst_cmd *cmd)
|
||||
{
|
||||
return cmd->sg_cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns cmd's data buffer length.
|
||||
*
|
||||
@@ -2085,15 +2115,25 @@ static inline unsigned int scst_cmd_get_bufflen(struct scst_cmd *cmd)
|
||||
return cmd->bufflen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns cmd's sg_cnt.
|
||||
*
|
||||
* Usage of this function is not recommended, use scst_get_buf_*()
|
||||
* family of functions instead.
|
||||
*/
|
||||
static inline unsigned short scst_cmd_get_sg_cnt(struct scst_cmd *cmd)
|
||||
/* Returns pointer to cmd's target's SG data buffer */
|
||||
static inline struct scatterlist *scst_cmd_get_tgt_sg(struct scst_cmd *cmd)
|
||||
{
|
||||
return cmd->sg_cnt;
|
||||
return cmd->tgt_sg;
|
||||
}
|
||||
|
||||
/* Returns cmd's target's sg_cnt */
|
||||
static inline unsigned int scst_cmd_get_tgt_sg_cnt(struct scst_cmd *cmd)
|
||||
{
|
||||
return cmd->tgt_sg_cnt;
|
||||
}
|
||||
|
||||
/* Sets cmd's target's SG data buffer */
|
||||
static inline void scst_cmd_set_tgt_sg(struct scst_cmd *cmd,
|
||||
struct scatterlist *sg, unsigned int sg_cnt)
|
||||
{
|
||||
cmd->tgt_sg = sg;
|
||||
cmd->tgt_sg_cnt = sg_cnt;
|
||||
cmd->tgt_data_buf_alloced = 1;
|
||||
}
|
||||
|
||||
/* Returns cmd's data direction */
|
||||
@@ -2172,29 +2212,42 @@ void *scst_cmd_get_tgt_priv_lock(struct scst_cmd *cmd);
|
||||
void scst_cmd_set_tgt_priv_lock(struct scst_cmd *cmd, void *val);
|
||||
|
||||
/*
|
||||
* Get/Set functions for data_buf_tgt_alloc flag
|
||||
* Get/Set functions for tgt_need_alloc_data_buf flag
|
||||
*/
|
||||
static inline int scst_cmd_get_data_buf_tgt_alloc(struct scst_cmd *cmd)
|
||||
static inline int scst_cmd_get_tgt_need_alloc_data_buf(struct scst_cmd *cmd)
|
||||
{
|
||||
return cmd->data_buf_tgt_alloc;
|
||||
return cmd->tgt_need_alloc_data_buf;
|
||||
}
|
||||
|
||||
static inline void scst_cmd_set_data_buf_tgt_alloc(struct scst_cmd *cmd)
|
||||
static inline void scst_cmd_set_tgt_need_alloc_data_buf(struct scst_cmd *cmd)
|
||||
{
|
||||
cmd->data_buf_tgt_alloc = 1;
|
||||
cmd->tgt_need_alloc_data_buf = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get/Set functions for data_buf_alloced flag
|
||||
* Get/Set functions for tgt_data_buf_alloced flag
|
||||
*/
|
||||
static inline int scst_cmd_get_data_buff_alloced(struct scst_cmd *cmd)
|
||||
static inline int scst_cmd_get_tgt_data_buff_alloced(struct scst_cmd *cmd)
|
||||
{
|
||||
return cmd->data_buf_alloced;
|
||||
return cmd->tgt_data_buf_alloced;
|
||||
}
|
||||
|
||||
static inline void scst_cmd_set_data_buff_alloced(struct scst_cmd *cmd)
|
||||
static inline void scst_cmd_set_tgt_data_buff_alloced(struct scst_cmd *cmd)
|
||||
{
|
||||
cmd->data_buf_alloced = 1;
|
||||
cmd->tgt_data_buf_alloced = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get/Set functions for dh_data_buf_alloced flag
|
||||
*/
|
||||
static inline int scst_cmd_get_dh_data_buff_alloced(struct scst_cmd *cmd)
|
||||
{
|
||||
return cmd->dh_data_buf_alloced;
|
||||
}
|
||||
|
||||
static inline void scst_cmd_set_dh_data_buff_alloced(struct scst_cmd *cmd)
|
||||
{
|
||||
cmd->dh_data_buf_alloced = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -609,17 +609,8 @@ static int dev_user_alloc_space(struct scst_user_cmd *ucmd)
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (unlikely(ucmd->cmd->data_buf_tgt_alloc)) {
|
||||
PRINT_ERROR("Target driver %s requested own memory "
|
||||
"allocation", ucmd->cmd->tgtt->name);
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_hardw_error));
|
||||
res = scst_get_cmd_abnormal_done_state(cmd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ucmd->state = UCMD_STATE_BUF_ALLOCING;
|
||||
cmd->data_buf_alloced = 1;
|
||||
cmd->dh_data_buf_alloced = 1;
|
||||
|
||||
rc = dev_user_alloc_sg(ucmd, is_buff_cached(ucmd));
|
||||
if (rc == 0)
|
||||
|
||||
@@ -1700,8 +1700,8 @@ void scst_release_space(struct scst_cmd *cmd)
|
||||
if (cmd->sgv == NULL)
|
||||
goto out;
|
||||
|
||||
if (cmd->data_buf_alloced) {
|
||||
TRACE_MEM("%s", "data_buf_alloced set, returning");
|
||||
if (cmd->tgt_data_buf_alloced || cmd->dh_data_buf_alloced) {
|
||||
TRACE_MEM("%s", "*data_buf_alloced set, returning");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1718,6 +1718,91 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir)
|
||||
{
|
||||
struct scatterlist *src_sg, *dst_sg;
|
||||
unsigned int src_sg_cnt, src_len, dst_len, src_offs, dst_offs;
|
||||
struct page *src, *dst;
|
||||
int s, d, to_copy;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (copy_dir == SCST_SG_COPY_FROM_TARGET) {
|
||||
src_sg = cmd->tgt_sg;
|
||||
src_sg_cnt = cmd->tgt_sg_cnt;
|
||||
dst_sg = cmd->sg;
|
||||
to_copy = cmd->bufflen;
|
||||
} else {
|
||||
src_sg = cmd->sg;
|
||||
src_sg_cnt = cmd->sg_cnt;
|
||||
dst_sg = cmd->tgt_sg;
|
||||
to_copy = cmd->resp_data_len;
|
||||
}
|
||||
|
||||
TRACE_MEM("cmd %p, copy_dir %d, src_sg %p, src_sg_cnt %d, dst_sg %p, "
|
||||
"to_copy %d", cmd, copy_dir, src_sg, src_sg_cnt, dst_sg,
|
||||
to_copy);
|
||||
|
||||
dst = sg_page(dst_sg);
|
||||
dst_len = dst_sg->length;
|
||||
dst_offs = dst_sg->offset;
|
||||
|
||||
s = 0;
|
||||
d = 0;
|
||||
src_offs = 0;
|
||||
while (s < src_sg_cnt) {
|
||||
src = sg_page(&src_sg[s]);
|
||||
src_len = src_sg[s].length;
|
||||
src_offs += src_sg[s].offset;
|
||||
|
||||
do {
|
||||
unsigned int n;
|
||||
|
||||
TRACE_MEM("cmd %p, to_copy %d, src %p, src_len %d, "
|
||||
"src_offs %d, dst %p, dst_len %d, dst_offs %d",
|
||||
cmd, to_copy, src, src_len, src_offs, dst,
|
||||
dst_len, dst_offs);
|
||||
|
||||
if ((src_offs == 0) && (dst_offs == 0) &&
|
||||
(src_len >= PAGE_SIZE) && (dst_len >= PAGE_SIZE) &&
|
||||
!PageHighMem(dst) && !PageHighMem(src)) {
|
||||
copy_page(page_address(dst), page_address(src));
|
||||
n = PAGE_SIZE;
|
||||
} else {
|
||||
n = min(PAGE_SIZE - dst_offs,
|
||||
PAGE_SIZE - src_offs);
|
||||
n = min(n, src_len);
|
||||
n = min(n, dst_len);
|
||||
memcpy(page_address(dst) + dst_offs,
|
||||
page_address(src) + src_offs, n);
|
||||
dst_offs -= min(n, dst_offs);
|
||||
src_offs -= min(n, src_offs);
|
||||
}
|
||||
|
||||
TRACE_MEM("cmd %p, n %d, s %d", cmd, n, s);
|
||||
|
||||
to_copy -= n;
|
||||
if (to_copy <= 0)
|
||||
goto out;
|
||||
|
||||
src_len -= n;
|
||||
dst_len -= n;
|
||||
if (dst_len == 0) {
|
||||
d++;
|
||||
dst = sg_page(&dst_sg[d]);
|
||||
dst_len = dst_sg[d].length;
|
||||
dst_offs += dst_sg[d].offset;
|
||||
}
|
||||
} while (src_len > 0);
|
||||
|
||||
s++;
|
||||
}
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
static const int SCST_CDB_LENGTH[8] = { 6, 10, 10, -1, 16, 12, -1, -1 };
|
||||
|
||||
#define SCST_CDB_GROUP(opcode) ((opcode >> 5) & 0x7)
|
||||
|
||||
@@ -341,6 +341,12 @@ int scst_alloc_space(struct scst_cmd *cmd);
|
||||
void scst_release_space(struct scst_cmd *cmd);
|
||||
void scst_scsi_op_list_init(void);
|
||||
|
||||
enum scst_sg_copy_dir {
|
||||
SCST_SG_COPY_FROM_TARGET,
|
||||
SCST_SG_COPY_TO_TARGET
|
||||
};
|
||||
void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir);
|
||||
|
||||
uint64_t scst_unpack_lun(const uint8_t *lun, int len);
|
||||
|
||||
struct scst_cmd *__scst_find_cmd_by_tag(struct scst_session *sess,
|
||||
|
||||
@@ -199,10 +199,10 @@ void scst_cmd_init_done(struct scst_cmd *cmd,
|
||||
#endif
|
||||
|
||||
TRACE_DBG("Preferred context: %d (cmd %p)", pref_context, cmd);
|
||||
TRACE(TRACE_SCSI, "tag=%llu, lun=%lld, CDB len=%d",
|
||||
(long long unsigned int)cmd->tag,
|
||||
(long long unsigned int)cmd->lun,
|
||||
cmd->cdb_len);
|
||||
TRACE(TRACE_SCSI, "tag=%llu, lun=%lld, CDB len=%d, queue_type=%x "
|
||||
"(cmd %p)", (long long unsigned int)cmd->tag,
|
||||
(long long unsigned int)cmd->lun, cmd->cdb_len,
|
||||
cmd->queue_type, cmd);
|
||||
PRINT_BUFF_FLAG(TRACE_SCSI|TRACE_RCV_BOT, "Recieving CDB",
|
||||
cmd->cdb, cmd->cdb_len);
|
||||
|
||||
@@ -389,10 +389,10 @@ static int scst_pre_parse(struct scst_cmd *cmd)
|
||||
goto out_xmit;
|
||||
#endif
|
||||
} else {
|
||||
TRACE(TRACE_SCSI, "op_name <%s>, direction=%d (expected %d, "
|
||||
"set %s), transfer_len=%d (expected len %d), flags=%d",
|
||||
cmd->op_name, cmd->data_direction,
|
||||
cmd->expected_data_direction,
|
||||
TRACE(TRACE_SCSI, "op_name <%s> (cmd %p), direction=%d "
|
||||
"(expected %d, set %s), transfer_len=%d (expected "
|
||||
"len %d), flags=%d", cmd->op_name, cmd,
|
||||
cmd->data_direction, cmd->expected_data_direction,
|
||||
scst_cmd_is_expected_set(cmd) ? "yes" : "no",
|
||||
cmd->bufflen, cmd->expected_transfer_len,
|
||||
cmd->op_flags);
|
||||
@@ -521,7 +521,8 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
||||
if (cmd->data_len == -1)
|
||||
cmd->data_len = cmd->bufflen;
|
||||
|
||||
if (cmd->data_buf_alloced && unlikely((orig_bufflen > cmd->bufflen))) {
|
||||
if (cmd->dh_data_buf_alloced &&
|
||||
unlikely((orig_bufflen > cmd->bufflen))) {
|
||||
PRINT_ERROR("Dev handler supplied data buffer (size %d), "
|
||||
"is less, than required (size %d)", cmd->bufflen,
|
||||
orig_bufflen);
|
||||
@@ -688,10 +689,11 @@ static int scst_prepare_space(struct scst_cmd *cmd)
|
||||
if (cmd->data_direction == SCST_DATA_NONE)
|
||||
goto prep_done;
|
||||
|
||||
if (cmd->data_buf_tgt_alloc) {
|
||||
if (cmd->tgt_need_alloc_data_buf) {
|
||||
int orig_bufflen = cmd->bufflen;
|
||||
|
||||
TRACE_MEM("%s", "Custom tgt data buf allocation requested");
|
||||
TRACE_MEM("Custom tgt data buf allocation requested (cmd %p)",
|
||||
cmd);
|
||||
|
||||
r = cmd->tgtt->alloc_data_buf(cmd);
|
||||
if (r > 0)
|
||||
@@ -702,7 +704,9 @@ static int scst_prepare_space(struct scst_cmd *cmd)
|
||||
if (cmd->sg == NULL)
|
||||
goto alloc;
|
||||
}
|
||||
cmd->data_buf_alloced = 1;
|
||||
|
||||
cmd->tgt_data_buf_alloced = 1;
|
||||
|
||||
if (unlikely(orig_bufflen < cmd->bufflen)) {
|
||||
PRINT_ERROR("Target driver allocated data "
|
||||
"buffer (size %d), is less, than "
|
||||
@@ -710,16 +714,32 @@ static int scst_prepare_space(struct scst_cmd *cmd)
|
||||
cmd->bufflen);
|
||||
goto out_error;
|
||||
}
|
||||
TRACE_MEM("%s", "data_buf_alloced, returning");
|
||||
}
|
||||
goto check;
|
||||
TRACE_MEM("tgt_data_buf_alloced (cmd %p)", cmd);
|
||||
} else
|
||||
goto check;
|
||||
}
|
||||
|
||||
alloc:
|
||||
if (!cmd->data_buf_alloced)
|
||||
if (!cmd->tgt_data_buf_alloced && !cmd->dh_data_buf_alloced) {
|
||||
r = scst_alloc_space(cmd);
|
||||
else
|
||||
TRACE_MEM("%s", "data_buf_alloced set, returning");
|
||||
cmd->tgt_sg = cmd->sg;
|
||||
cmd->tgt_sg_cnt = cmd->sg_cnt;
|
||||
} else if (cmd->dh_data_buf_alloced && !cmd->tgt_data_buf_alloced) {
|
||||
TRACE_MEM("dh_data_buf_alloced set (cmd %p)", cmd);
|
||||
cmd->tgt_sg = cmd->sg;
|
||||
cmd->tgt_sg_cnt = cmd->sg_cnt;
|
||||
r = 0;
|
||||
} else if (cmd->tgt_data_buf_alloced && !cmd->dh_data_buf_alloced) {
|
||||
TRACE_MEM("tgt_data_buf_alloced set (cmd %p)", cmd);
|
||||
cmd->sg = cmd->tgt_sg;
|
||||
cmd->sg_cnt = cmd->tgt_sg_cnt;
|
||||
r = 0;
|
||||
} else {
|
||||
TRACE_MEM("Both *_data_buf_alloced set (cmd %p, sg %p, "
|
||||
"sg_cnt %d, tgt_sg %p, tgt_sg_cnt %d)", cmd, cmd->sg,
|
||||
cmd->sg_cnt, cmd->tgt_sg, cmd->tgt_sg_cnt);
|
||||
r = 0;
|
||||
}
|
||||
|
||||
check:
|
||||
if (r != 0) {
|
||||
@@ -1049,9 +1069,7 @@ void scst_rx_data(struct scst_cmd *cmd, int status,
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("Preferred context: %d", pref_context);
|
||||
TRACE(TRACE_SCSI, "tag=%llu status=%#x",
|
||||
(long long unsigned int)scst_cmd_get_tag(cmd),
|
||||
status);
|
||||
TRACE(TRACE_SCSI, "cmd %p, status %#x", cmd, status);
|
||||
|
||||
#ifdef CONFIG_SCST_EXTRACHECKS
|
||||
if ((in_irq() || irqs_disabled()) &&
|
||||
@@ -1066,6 +1084,19 @@ void scst_rx_data(struct scst_cmd *cmd, int status,
|
||||
|
||||
switch (status) {
|
||||
case SCST_RX_STATUS_SUCCESS:
|
||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||
if (cmd->tgt_sg) {
|
||||
int i;
|
||||
struct scatterlist *sg = cmd->tgt_sg;
|
||||
TRACE_RECV_BOT("RX data for cmd %p "
|
||||
"(sg_cnt %d, sg %p, sg[0].page %p)", cmd,
|
||||
cmd->tgt_sg_cnt, sg, (void *)sg_page(&sg[0]));
|
||||
for (i = 0; i < cmd->tgt_sg_cnt; ++i) {
|
||||
PRINT_BUFF_FLAG(TRACE_RCV_BOT, "RX sg",
|
||||
sg_virt(&sg[i]), sg[i].length);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
cmd->state = SCST_CMD_STATE_TGT_PRE_EXEC;
|
||||
/* Small context optimization */
|
||||
if ((pref_context == SCST_CONTEXT_TASKLET) ||
|
||||
@@ -1190,10 +1221,10 @@ static void scst_do_cmd_done(struct scst_cmd *cmd, int result,
|
||||
scst_alloc_set_sense(cmd, 1, rq_sense, rq_sense_len);
|
||||
}
|
||||
|
||||
TRACE(TRACE_SCSI, "cmd%p, result=%x, cmd->status=%x, resid=%d, "
|
||||
TRACE(TRACE_SCSI, "cmd %p, result=%x, cmd->status=%x, resid=%d, "
|
||||
"cmd->msg_status=%x, cmd->host_status=%x, "
|
||||
"cmd->driver_status=%x", cmd, result, cmd->status, resid,
|
||||
cmd->msg_status, cmd->host_status, cmd->driver_status);
|
||||
"cmd->driver_status=%x (cmd %p)",cmd, result, cmd->status, resid,
|
||||
cmd->msg_status, cmd->host_status, cmd->driver_status, cmd);
|
||||
|
||||
cmd->completed = 1;
|
||||
|
||||
@@ -2041,6 +2072,10 @@ static int scst_exec(struct scst_cmd **active_cmd)
|
||||
cmd->scst_cmd_done = scst_cmd_done_local;
|
||||
cmd->state = SCST_CMD_STATE_LOCAL_EXEC;
|
||||
|
||||
if (cmd->tgt_data_buf_alloced && cmd->dh_data_buf_alloced &&
|
||||
(cmd->data_direction == SCST_DATA_WRITE))
|
||||
scst_copy_sg(cmd, SCST_SG_COPY_FROM_TARGET);
|
||||
|
||||
rc = scst_do_local_exec(cmd);
|
||||
if (likely(rc == SCST_EXEC_NOT_COMPLETED))
|
||||
/* Nothing to do */;
|
||||
@@ -2272,8 +2307,9 @@ static int scst_check_auto_sense(struct scst_cmd *cmd)
|
||||
SCST_NO_SENSE(cmd->sense))) {
|
||||
TRACE(TRACE_SCSI|TRACE_MINOR, "CHECK_CONDITION, but no sense: "
|
||||
"cmd->status=%x, cmd->msg_status=%x, "
|
||||
"cmd->host_status=%x, cmd->driver_status=%x", cmd->status,
|
||||
cmd->msg_status, cmd->host_status, cmd->driver_status);
|
||||
"cmd->host_status=%x, cmd->driver_status=%x (cmd %p)",
|
||||
cmd->status, cmd->msg_status, cmd->host_status,
|
||||
cmd->driver_status, cmd);
|
||||
res = 1;
|
||||
} else if (unlikely(cmd->host_status)) {
|
||||
if ((cmd->host_status == DID_REQUEUE) ||
|
||||
@@ -2283,8 +2319,8 @@ static int scst_check_auto_sense(struct scst_cmd *cmd)
|
||||
scst_set_busy(cmd);
|
||||
} else {
|
||||
TRACE(TRACE_SCSI|TRACE_MINOR, "Host status %x "
|
||||
"received, returning HARDWARE ERROR instead",
|
||||
cmd->host_status);
|
||||
"received, returning HARDWARE ERROR instead "
|
||||
"(cmd %p)", cmd->host_status, cmd);
|
||||
scst_set_cmd_error(cmd,
|
||||
SCST_LOAD_SENSE(scst_sense_hardw_error));
|
||||
}
|
||||
@@ -2685,6 +2721,10 @@ static int scst_pre_xmit_response(struct scst_cmd *cmd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cmd->tgt_data_buf_alloced && cmd->dh_data_buf_alloced &&
|
||||
(cmd->data_direction == SCST_DATA_READ))
|
||||
scst_copy_sg(cmd, SCST_SG_COPY_TO_TARGET);
|
||||
|
||||
cmd->state = SCST_CMD_STATE_XMIT_RESP;
|
||||
res = SCST_CMD_STATE_RES_CONT_SAME;
|
||||
|
||||
@@ -2746,16 +2786,16 @@ static int scst_xmit_response(struct scst_cmd *cmd)
|
||||
|
||||
TRACE_DBG("Calling xmit_response(%p)", cmd);
|
||||
|
||||
#if defined(CONFIG_SCST_DEBUG)
|
||||
if (cmd->sg) {
|
||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||
if (cmd->tgt_sg) {
|
||||
int i;
|
||||
struct scatterlist *sg = cmd->sg;
|
||||
TRACE_SEND_BOT("Xmitting %d S/G(s) at %p sg[0].page at "
|
||||
"%p", cmd->sg_cnt, sg, (void *)sg_page(&sg[0]));
|
||||
for (i = 0; i < cmd->sg_cnt; ++i) {
|
||||
TRACE_BUFF_FLAG(TRACE_SND_BOT,
|
||||
"Xmitting sg", sg_virt(&sg[i]),
|
||||
sg[i].length);
|
||||
struct scatterlist *sg = cmd->tgt_sg;
|
||||
TRACE(TRACE_SND_BOT, "Xmitting data for cmd %p "
|
||||
"(sg_cnt %d, sg %p, sg[0].page %p)", cmd,
|
||||
cmd->tgt_sg_cnt, sg, (void *)sg_page(&sg[0]));
|
||||
for (i = 0; i < cmd->tgt_sg_cnt; ++i) {
|
||||
PRINT_BUFF_FLAG(TRACE_SND_BOT, "Xmitting sg",
|
||||
sg_virt(&sg[i]), sg[i].length);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -2878,8 +2918,7 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (scst_is_implicit_hq(cmd)) {
|
||||
TRACE(TRACE_SCSI|TRACE_SCSI_SERIALIZING,
|
||||
"Implicit HQ cmd %p", cmd);
|
||||
TRACE_SN("Implicit HQ cmd %p", cmd);
|
||||
cmd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE;
|
||||
}
|
||||
|
||||
@@ -2932,8 +2971,7 @@ static void scst_cmd_set_sn(struct scst_cmd *cmd)
|
||||
break;
|
||||
|
||||
case SCST_CMD_QUEUE_ORDERED:
|
||||
TRACE(TRACE_SCSI|TRACE_SCSI_SERIALIZING, "ORDERED cmd %p "
|
||||
"(op %x)", cmd, cmd->cdb[0]);
|
||||
TRACE_SN("ORDERED cmd %p (op %x)", cmd, cmd->cdb[0]);
|
||||
ordered:
|
||||
if (!tgt_dev->prev_cmd_ordered) {
|
||||
spin_lock_irqsave(&tgt_dev->sn_lock, flags);
|
||||
@@ -2969,8 +3007,7 @@ ordered:
|
||||
break;
|
||||
|
||||
case SCST_CMD_QUEUE_HEAD_OF_QUEUE:
|
||||
TRACE(TRACE_SCSI|TRACE_SCSI_SERIALIZING, "HQ cmd %p "
|
||||
"(op %x)", cmd, cmd->cdb[0]);
|
||||
TRACE_SN("HQ cmd %p (op %x)", cmd, cmd->cdb[0]);
|
||||
spin_lock_irqsave(&tgt_dev->sn_lock, flags);
|
||||
tgt_dev->hq_cmd_count++;
|
||||
spin_unlock_irqrestore(&tgt_dev->sn_lock, flags);
|
||||
|
||||
@@ -490,11 +490,6 @@ static int scst_local_queuecommand(struct scsi_cmnd *SCpnt,
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We get given data buffers by the SML
|
||||
*/
|
||||
scst_cmd_set_data_buff_alloced(scst_cmd);
|
||||
|
||||
dir = SCST_DATA_NONE;
|
||||
switch (SCpnt->sc_data_direction) {
|
||||
case DMA_TO_DEVICE:
|
||||
@@ -517,11 +512,8 @@ static int scst_local_queuecommand(struct scsi_cmnd *SCpnt,
|
||||
}
|
||||
scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt));
|
||||
|
||||
/*
|
||||
* Set the SGL things directly ...
|
||||
*/
|
||||
scst_cmd->sg_cnt = scsi_sg_count(SCpnt);
|
||||
scst_cmd->sg = scsi_sglist(SCpnt);
|
||||
/* Set the SGL things directly ... */
|
||||
scst_cmd_set_tgt_sg(scst_cmd, scsi_sglist(SCpnt), scsi_sg_count(SCpnt));
|
||||
|
||||
/*
|
||||
* Unfortunately, we called with IRQs disabled, so have no choice,
|
||||
|
||||
Reference in New Issue
Block a user