SG chaining implemented

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2113 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2010-09-13 20:47:44 +00:00
parent 1f5ff3e5ed
commit 98b09a7a26
4 changed files with 72 additions and 46 deletions
+30 -16
View File
@@ -1808,6 +1808,7 @@ struct scst_cmd {
int *write_sg_cnt;
/* scst_get_sg_buf_[first,next]() support */
struct scatterlist *get_sg_buf_cur_sg_entry;
int get_sg_buf_entry_num;
/* Bidirectional transfers support */
@@ -3345,31 +3346,35 @@ enum scst_sg_copy_dir {
void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir);
/*
* Functions for access to the commands data (SG) buffer,
* including HIGHMEM environment. Should be used instead of direct
* access. Returns the mapped buffer length for success, 0 for EOD,
* Functions for access to the commands data (SG) buffer. Should be used
* instead of direct access. Returns the buffer length for success, 0 for EOD,
* negative error code otherwise.
*
* "Buf" argument returns the mapped buffer
*
* The "put" function unmaps the buffer.
*/
static inline int __scst_get_buf(struct scst_cmd *cmd, struct scatterlist *sg,
int sg_cnt, uint8_t **buf)
static inline int __scst_get_buf(struct scst_cmd *cmd, int sg_cnt,
uint8_t **buf)
{
int res = 0;
int i = cmd->get_sg_buf_entry_num;
struct scatterlist *sg = cmd->get_sg_buf_cur_sg_entry;
*buf = NULL;
if ((i >= sg_cnt) || unlikely(sg == NULL))
if (cmd->get_sg_buf_entry_num >= sg_cnt)
goto out;
*buf = page_address(sg_page(&sg[i]));
*buf += sg[i].offset;
if (unlikely(sg_is_chain(sg)))
sg = sg_chain_ptr(sg);
*buf = page_address(sg_page(sg));
*buf += sg->offset;
res = sg->length;
res = sg[i].length;
cmd->get_sg_buf_entry_num++;
cmd->get_sg_buf_cur_sg_entry = ++sg;
out:
return res;
@@ -3377,14 +3382,17 @@ out:
static inline int scst_get_buf_first(struct scst_cmd *cmd, uint8_t **buf)
{
if (unlikely(cmd->sg == NULL))
return 0;
cmd->get_sg_buf_entry_num = 0;
cmd->get_sg_buf_cur_sg_entry = cmd->sg;
cmd->may_need_dma_sync = 1;
return __scst_get_buf(cmd, cmd->sg, cmd->sg_cnt, buf);
return __scst_get_buf(cmd, cmd->sg_cnt, buf);
}
static inline int scst_get_buf_next(struct scst_cmd *cmd, uint8_t **buf)
{
return __scst_get_buf(cmd, cmd->sg, cmd->sg_cnt, buf);
return __scst_get_buf(cmd, cmd->sg_cnt, buf);
}
static inline void scst_put_buf(struct scst_cmd *cmd, void *buf)
@@ -3394,14 +3402,17 @@ static inline void scst_put_buf(struct scst_cmd *cmd, void *buf)
static inline int scst_get_out_buf_first(struct scst_cmd *cmd, uint8_t **buf)
{
if (unlikely(cmd->out_sg == NULL))
return 0;
cmd->get_sg_buf_entry_num = 0;
cmd->get_sg_buf_cur_sg_entry = cmd->out_sg;
cmd->may_need_dma_sync = 1;
return __scst_get_buf(cmd, cmd->out_sg, cmd->out_sg_cnt, buf);
return __scst_get_buf(cmd, cmd->out_sg_cnt, buf);
}
static inline int scst_get_out_buf_next(struct scst_cmd *cmd, uint8_t **buf)
{
return __scst_get_buf(cmd, cmd->out_sg, cmd->out_sg_cnt, buf);
return __scst_get_buf(cmd, cmd->out_sg_cnt, buf);
}
static inline void scst_put_out_buf(struct scst_cmd *cmd, void *buf)
@@ -3412,15 +3423,18 @@ static inline void scst_put_out_buf(struct scst_cmd *cmd, void *buf)
static inline int scst_get_sg_buf_first(struct scst_cmd *cmd, uint8_t **buf,
struct scatterlist *sg, int sg_cnt)
{
if (unlikely(sg == NULL))
return 0;
cmd->get_sg_buf_entry_num = 0;
cmd->get_sg_buf_cur_sg_entry = cmd->sg;
cmd->may_need_dma_sync = 1;
return __scst_get_buf(cmd, sg, sg_cnt, buf);
return __scst_get_buf(cmd, sg_cnt, buf);
}
static inline int scst_get_sg_buf_next(struct scst_cmd *cmd, uint8_t **buf,
struct scatterlist *sg, int sg_cnt)
{
return __scst_get_buf(cmd, sg, sg_cnt, buf);
return __scst_get_buf(cmd, sg_cnt, buf);
}
static inline void scst_put_sg_buf(struct scst_cmd *cmd, void *buf,
+18 -12
View File
@@ -2028,30 +2028,36 @@ next:
static void scst_adjust_sg(struct scst_cmd *cmd, struct scatterlist *sg,
int *sg_cnt, int adjust_len)
{
int i, l;
int i, j, l;
TRACE_ENTRY();
l = 0;
for (i = 0; i < *sg_cnt; i++) {
l += sg[i].length;
for (i = 0, j = 0; i < *sg_cnt; i++, j++) {
TRACE_DBG("i %d, j %d, sg_cnt %d, sg %p, page_link %lx", i, j,
*sg_cnt, sg, sg[j].page_link);
if (unlikely(sg_is_chain(&sg[j]))) {
sg = sg_chain_ptr(&sg[j]);
j = 0;
}
l += sg[j].length;
if (l >= adjust_len) {
int left = adjust_len - (l - sg[i].length);
int left = adjust_len - (l - sg[j].length);
#ifdef CONFIG_SCST_DEBUG
TRACE(TRACE_SG_OP|TRACE_MEMORY, "cmd %p (tag %llu), "
"sg %p, sg_cnt %d, adjust_len %d, i %d, "
"sg[i].length %d, left %d",
"sg %p, sg_cnt %d, adjust_len %d, i %d, j %d, "
"sg[j].length %d, left %d",
cmd, (long long unsigned int)cmd->tag,
sg, *sg_cnt, adjust_len, i,
sg[i].length, left);
sg, *sg_cnt, adjust_len, i, j,
sg[j].length, left);
#endif
cmd->orig_sg = sg;
cmd->p_orig_sg_cnt = sg_cnt;
cmd->orig_sg_cnt = *sg_cnt;
cmd->orig_sg_entry = i;
cmd->orig_entry_len = sg[i].length;
*sg_cnt = (left > 0) ? i+1 : i;
sg[i].length = left;
cmd->orig_sg_entry = j;
cmd->orig_entry_len = sg[j].length;
*sg_cnt = (left > 0) ? j+1 : j;
sg[j].length = left;
cmd->sg_buff_modified = 1;
break;
}
+23 -11
View File
@@ -1332,7 +1332,7 @@ void scst_rx_data(struct scst_cmd *cmd, int status,
case SCST_RX_STATUS_SUCCESS:
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
if (trace_flag & TRACE_RCV_BOT) {
int i;
int i, j;
struct scatterlist *sg;
if (cmd->out_sg != NULL)
sg = cmd->out_sg;
@@ -1347,9 +1347,13 @@ void scst_rx_data(struct scst_cmd *cmd, int status,
"(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) {
for (i = 0, j = 0; i < cmd->tgt_sg_cnt; ++i, ++j) {
if (unlikely(sg_is_chain(&sg[j]))) {
sg = sg_chain_ptr(&sg[j]);
j = 0;
}
PRINT_BUFF_FLAG(TRACE_RCV_BOT, "RX sg",
sg_virt(&sg[i]), sg[i].length);
sg_virt(&sg[j]), sg[j].length);
}
}
}
@@ -1607,14 +1611,18 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state,
#if defined(CONFIG_SCST_DEBUG)
if (next_state == SCST_CMD_STATE_PRE_DEV_DONE) {
if ((trace_flag & TRACE_RCV_TOP) && (cmd->sg != NULL)) {
int i;
int i, j;
struct scatterlist *sg = cmd->sg;
TRACE_RECV_TOP("Exec'd %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) {
for (i = 0, j = 0; i < cmd->sg_cnt; ++i, ++j) {
if (unlikely(sg_is_chain(&sg[j]))) {
sg = sg_chain_ptr(&sg[j]);
j = 0;
}
TRACE_BUFF_FLAG(TRACE_RCV_TOP,
"Exec'd sg", sg_virt(&sg[i]),
sg[i].length);
"Exec'd sg", sg_virt(&sg[j]),
sg[j].length);
}
}
}
@@ -3480,7 +3488,7 @@ static int scst_xmit_response(struct scst_cmd *cmd)
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
if (trace_flag & TRACE_SND_BOT) {
int i;
int i, j;
struct scatterlist *sg;
if (cmd->tgt_sg != NULL)
sg = cmd->tgt_sg;
@@ -3491,10 +3499,14 @@ static int scst_xmit_response(struct scst_cmd *cmd)
"(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) {
for (i = 0, j = 0; i < cmd->tgt_sg_cnt; ++i, ++j) {
if (unlikely(sg_is_chain(&sg[j]))) {
sg = sg_chain_ptr(&sg[j]);
j = 0;
}
PRINT_BUFF_FLAG(TRACE_SND_BOT,
"Xmitting sg", sg_virt(&sg[i]),
sg[i].length);
"Xmitting sg", sg_virt(&sg[j]),
sg[j].length);
}
}
}
+1 -7
View File
@@ -43,10 +43,6 @@
#include <scst_debug.h>
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
#define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist))
#endif
#ifndef INSIDE_KERNEL_TREE
#if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G)
#warning "HIGHMEM kernel configurations are not supported by this module,\
@@ -1368,11 +1364,9 @@ static struct scsi_host_template scst_lcl_ini_driver_template = {
#endif
.can_queue = 256,
.this_id = -1,
/* SCST doesn't support sg chaining */
.sg_tablesize = SG_MAX_SINGLE_ALLOC,
.sg_tablesize = 0xFFFF,
.cmd_per_lun = 32,
.max_sectors = 0xffff,
/* SCST doesn't support sg chaining */
.use_clustering = ENABLE_CLUSTERING,
.skip_settle_delay = 1,
.module = THIS_MODULE,