mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-18 21:26:31 +00:00
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:
+30
-16
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user