mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-17 20:56:24 +00:00
- Update to work on 2.6.24
- Minor cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@251 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -56,13 +56,6 @@ int digest_init(struct iscsi_conn *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copied from linux-iscsi initiator and slightly adjusted */
|
||||
#define SETSG(sg, p, l) do { \
|
||||
(sg).page = virt_to_page((p)); \
|
||||
(sg).offset = ((unsigned long)(p) & ~PAGE_MASK); \
|
||||
(sg).length = (l); \
|
||||
} while (0)
|
||||
|
||||
static u32 evaluate_crc32_from_sg(struct scatterlist *sg, int total,
|
||||
int pad_bytes)
|
||||
{
|
||||
@@ -80,7 +73,7 @@ static u32 evaluate_crc32_from_sg(struct scatterlist *sg, int total,
|
||||
int d = min(min(total, (int)(sg->length)),
|
||||
(int)(PAGE_SIZE - sg->offset));
|
||||
|
||||
crc = crc32c(crc, page_address(sg->page) + sg->offset, d);
|
||||
crc = crc32c(crc, sg_virt(sg), d);
|
||||
total -= d;
|
||||
sg++;
|
||||
}
|
||||
@@ -103,9 +96,11 @@ static u32 digest_header(struct iscsi_pdu *pdu)
|
||||
struct scatterlist sg[2];
|
||||
unsigned int nbytes = sizeof(struct iscsi_hdr);
|
||||
|
||||
SETSG(sg[0], &pdu->bhs, nbytes);
|
||||
sg_init_table(sg, 2);
|
||||
|
||||
sg_set_buf(&sg[0], &pdu->bhs, nbytes);
|
||||
if (pdu->ahssize) {
|
||||
SETSG(sg[1], pdu->ahs, pdu->ahssize);
|
||||
sg_set_buf(&sg[1], pdu->ahs, pdu->ahssize);
|
||||
nbytes += pdu->ahssize;
|
||||
}
|
||||
return evaluate_crc32_from_sg(sg, nbytes, 0);
|
||||
|
||||
@@ -39,7 +39,11 @@ static int event_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
|
||||
static int event_recv_skb(struct sk_buff *skb)
|
||||
#else
|
||||
static void event_recv_skb(struct sk_buff *skb)
|
||||
#endif
|
||||
{
|
||||
int err;
|
||||
struct nlmsghdr *nlh;
|
||||
@@ -48,7 +52,7 @@ static int event_recv_skb(struct sk_buff *skb)
|
||||
while (skb->len >= NLMSG_SPACE(0)) {
|
||||
nlh = (struct nlmsghdr *)skb->data;
|
||||
if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
|
||||
return 0;
|
||||
goto out;
|
||||
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
|
||||
if (rlen > skb->len)
|
||||
rlen = skb->len;
|
||||
@@ -58,9 +62,16 @@ static int event_recv_skb(struct sk_buff *skb)
|
||||
netlink_ack(skb, nlh, 0);
|
||||
skb_pull(skb, rlen);
|
||||
}
|
||||
|
||||
out:
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
|
||||
return 0;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
|
||||
static void event_recv(struct sock *sk, int length)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
@@ -72,6 +83,7 @@ static void event_recv(struct sock *sk, int length)
|
||||
kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int notify(void *data, int len, int gfp_mask)
|
||||
{
|
||||
@@ -107,10 +119,16 @@ int event_send(u32 tid, u64 sid, u32 cid, u32 state, int atomic)
|
||||
int __init event_init(void)
|
||||
{
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
|
||||
nl = netlink_kernel_create(NETLINK_ISCSI_SCST, 1, event_recv, THIS_MODULE);
|
||||
#else
|
||||
nl = netlink_kernel_create(NETLINK_ISCSI_SCST, 1, event_recv, NULL,
|
||||
nl = netlink_kernel_create(NETLINK_ISCSI_SCST, 1, event_recv,
|
||||
THIS_MODULE);
|
||||
#else
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
|
||||
nl = netlink_kernel_create(NETLINK_ISCSI_SCST, 1, event_recv, NULL,
|
||||
THIS_MODULE);
|
||||
#else
|
||||
nl = netlink_kernel_create(&init_net, NETLINK_ISCSI_SCST, 1,
|
||||
event_recv_skb, NULL, THIS_MODULE);
|
||||
#endif
|
||||
#endif
|
||||
if (!nl) {
|
||||
PRINT_ERROR("%s", "netlink_kernel_create() failed");
|
||||
|
||||
@@ -531,7 +531,7 @@ static void iscsi_set_datasize(struct iscsi_cmnd *cmnd, u32 offset, u32 size)
|
||||
|
||||
if (cmnd->pdu.datasize & 3) {
|
||||
int idx = (offset + cmnd->pdu.datasize) >> PAGE_SHIFT;
|
||||
u8 *p = (u8 *)page_address(cmnd->sg[idx].page) +
|
||||
u8 *p = (u8 *)page_address(sg_page(&cmnd->sg[idx])) +
|
||||
((offset + cmnd->pdu.datasize) & ~PAGE_MASK);
|
||||
int i = 4 - (cmnd->pdu.datasize & 3);
|
||||
while (i--)
|
||||
@@ -627,7 +627,7 @@ static struct iscsi_cmnd *create_status_rsp(struct iscsi_cmnd *req, int status,
|
||||
/* ToDo(); */
|
||||
}
|
||||
rsp->own_sg = 1;
|
||||
sense = (struct iscsi_sense_data *)page_address(sg[0].page);
|
||||
sense = (struct iscsi_sense_data *)page_address(sg_page(&sg[0]));
|
||||
sense->length = cpu_to_be16(sense_len);
|
||||
memcpy(sense->data, sense_buf, sense_len);
|
||||
rsp->pdu.datasize = sizeof(struct iscsi_sense_data) + sense_len;
|
||||
@@ -686,7 +686,7 @@ static void iscsi_cmnd_reject(struct iscsi_cmnd *req, int reason)
|
||||
/* ToDo(); */
|
||||
}
|
||||
rsp->own_sg = 1;
|
||||
addr = page_address(sg[0].page);
|
||||
addr = page_address(sg_page(&sg[0]));
|
||||
clear_page(addr);
|
||||
memcpy(addr, &req->pdu.bhs, sizeof(struct iscsi_hdr));
|
||||
rsp->bufflen = rsp->pdu.datasize = sizeof(struct iscsi_hdr);
|
||||
@@ -817,6 +817,8 @@ static int cmnd_insert_hash(struct iscsi_cmnd *cmnd)
|
||||
TRACE_DBG("%p:%x", cmnd, itt);
|
||||
if (unlikely(itt == ISCSI_RESERVED_TAG)) {
|
||||
PRINT_ERROR("%s", "ITT is RESERVED_TAG");
|
||||
PRINT_BUFFER("Incorrect BHS", &cmnd->pdu.bhs,
|
||||
sizeof(cmnd->pdu.bhs));
|
||||
err = -ISCSI_REASON_PROTOCOL_ERROR;
|
||||
goto out;
|
||||
}
|
||||
@@ -894,7 +896,7 @@ static void cmnd_prepare_skip_pdu(struct iscsi_cmnd *cmnd)
|
||||
cmnd->bufflen = PAGE_SIZE;
|
||||
}
|
||||
|
||||
addr = page_address(sg[0].page);
|
||||
addr = page_address(sg_page(&sg[0]));
|
||||
sBUG_ON(addr == NULL);
|
||||
size = (size + 3) & -4;
|
||||
conn->read_size = size;
|
||||
@@ -975,8 +977,7 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn,
|
||||
|
||||
i = 0;
|
||||
while (1) {
|
||||
sBUG_ON(sg[idx].page == NULL);
|
||||
addr = page_address(sg[idx].page);
|
||||
addr = page_address(sg_page(&sg[idx]));
|
||||
sBUG_ON(addr == NULL);
|
||||
conn->read_iov[i].iov_base = addr + offset;
|
||||
if (offset + size <= PAGE_SIZE) {
|
||||
@@ -1162,7 +1163,7 @@ static int noop_out_start(struct iscsi_cmnd *cmnd)
|
||||
|
||||
for (i = 0; i < cmnd->sg_cnt; i++) {
|
||||
conn->read_iov[i].iov_base =
|
||||
page_address(sg[i].page);
|
||||
page_address(sg_page(&sg[i]));
|
||||
tmp = min_t(u32, size, PAGE_SIZE);
|
||||
conn->read_iov[i].iov_len = tmp;
|
||||
conn->read_size += tmp;
|
||||
|
||||
+32
-30
@@ -96,17 +96,18 @@ again:
|
||||
if (cmnd_get_check(cmnd))
|
||||
continue;
|
||||
for(i = 0; i < sg_cnt; i++) {
|
||||
TRACE_CONN_CLOSE_DBG("page %p, net_priv %p, _count %d",
|
||||
cmnd->sg[i].page, cmnd->sg[i].page->net_priv,
|
||||
atomic_read(&cmnd->sg[i].page->_count));
|
||||
struct page *page = sg_page(&cmnd->sg[i]);
|
||||
TRACE_CONN_CLOSE_DBG("page %p, net_priv %p, "
|
||||
"_count %d", page, page->net_priv,
|
||||
atomic_read(&page->_count));
|
||||
|
||||
if (cmnd->sg[i].page->net_priv != NULL) {
|
||||
if (page->net_priv != NULL) {
|
||||
if (restart == 0) {
|
||||
spin_unlock_bh(&conn->cmd_list_lock);
|
||||
restart = 1;
|
||||
}
|
||||
while(cmnd->sg[i].page->net_priv != NULL)
|
||||
iscsi_put_page_callback(cmnd->sg[i].page);
|
||||
while(page->net_priv != NULL)
|
||||
iscsi_put_page_callback(page);
|
||||
}
|
||||
}
|
||||
cmnd_put(cmnd);
|
||||
@@ -131,19 +132,19 @@ again:
|
||||
if (cmnd_get_check(rsp))
|
||||
continue;
|
||||
for(i = 0; i < sg_cnt; i++) {
|
||||
struct page *page = sg_page(&rsp->sg[i]);
|
||||
TRACE_CONN_CLOSE_DBG(" page %p, net_priv %p, "
|
||||
"_count %d", rsp->sg[i].page,
|
||||
rsp->sg[i].page->net_priv,
|
||||
atomic_read(&rsp->sg[i].page->_count));
|
||||
"_count %d", page, page->net_priv,
|
||||
atomic_read(&page->_count));
|
||||
|
||||
if (rsp->sg[i].page->net_priv != NULL) {
|
||||
if (page->net_priv != NULL) {
|
||||
if (restart == 0) {
|
||||
spin_unlock_bh(&cmnd->rsp_cmd_lock);
|
||||
spin_unlock_bh(&conn->cmd_list_lock);
|
||||
restart = 1;
|
||||
}
|
||||
while(rsp->sg[i].page->net_priv != NULL)
|
||||
iscsi_put_page_callback(rsp->sg[i].page);
|
||||
while(page->net_priv != NULL)
|
||||
iscsi_put_page_callback(page);
|
||||
}
|
||||
}
|
||||
cmnd_put(rsp);
|
||||
@@ -336,9 +337,10 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
sg_cnt = get_pgcnt(cmnd->bufflen,
|
||||
cmnd->sg[0].offset);
|
||||
for(i = 0; i < sg_cnt; i++) {
|
||||
struct page *page = sg_page(&cmnd->sg[i]);
|
||||
TRACE_CONN_CLOSE_DBG("page %p, net_priv %p, _count %d",
|
||||
cmnd->sg[i].page, cmnd->sg[i].page->net_priv,
|
||||
atomic_read(&cmnd->sg[i].page->_count));
|
||||
page, page->net_priv,
|
||||
atomic_read(&page->_count));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,9 +358,9 @@ static void close_conn(struct iscsi_conn *conn)
|
||||
sBUG_ON(rsp->sg_cnt != sg_cnt);
|
||||
for(i = 0; i < sg_cnt; i++) {
|
||||
TRACE_CONN_CLOSE_DBG(" page %p, net_priv %p, "
|
||||
"_count %d", rsp->sg[i].page,
|
||||
rsp->sg[i].page->net_priv,
|
||||
atomic_read(&rsp->sg[i].page->_count));
|
||||
"_count %d", sg_page(&rsp->sg[i]),
|
||||
sg_page(&rsp->sg[i])->net_priv,
|
||||
atomic_read(&sg_page(&rsp->sg[i])->_count));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -809,8 +811,8 @@ void iscsi_put_page_callback(struct page *page)
|
||||
if (atomic_dec_and_test(&cmd->net_ref_cnt)) {
|
||||
int i, sg_cnt = get_pgcnt(cmd->bufflen, cmd->sg[0].offset);
|
||||
for(i = 0; i < sg_cnt; i++) {
|
||||
TRACE_NET_PAGE("Clearing page %p", cmd->sg[i].page);
|
||||
cmd->sg[i].page->net_priv = NULL;
|
||||
TRACE_NET_PAGE("Clearing page %p", sg_page(&cmd->sg[i]));
|
||||
sg_page(&cmd->sg[i])->net_priv = NULL;
|
||||
}
|
||||
cmnd_put(cmd);
|
||||
}
|
||||
@@ -923,31 +925,31 @@ retry:
|
||||
|
||||
while (1) {
|
||||
#ifdef NET_PAGE_CALLBACKS_DEFINED
|
||||
if (unlikely((sg[idx].page->net_priv != NULL) &&
|
||||
(sg[idx].page->net_priv != ref_cmd))) {
|
||||
if (unlikely((sg_page(&sg[idx])->net_priv != NULL) &&
|
||||
(sg_page(&sg[idx])->net_priv != ref_cmd))) {
|
||||
PRINT_ERROR("net_priv isn't NULL and != ref_cmd "
|
||||
"(write_cmnd %p, ref_cmd %p, sg %p, idx %d, "
|
||||
"net_priv %p)", write_cmnd, ref_cmd, sg, idx,
|
||||
sg[idx].page->net_priv);
|
||||
sg_page(&sg[idx])->net_priv);
|
||||
sBUG();
|
||||
}
|
||||
sg[idx].page->net_priv = ref_cmd;
|
||||
sg_page(&sg[idx])->net_priv = ref_cmd;
|
||||
#endif
|
||||
sendsize = PAGE_SIZE - offset;
|
||||
if (size <= sendsize) {
|
||||
retry2:
|
||||
res = sendpage(sock, sg[idx].page, offset, size, flags);
|
||||
res = sendpage(sock, sg_page(&sg[idx]), offset, size, flags);
|
||||
TRACE_WRITE("%s %#Lx:%u: %d(%lu,%u,%u)",
|
||||
sock->ops->sendpage ? "sendpage" : "sock_no_sendpage",
|
||||
(unsigned long long)conn->session->sid, conn->cid,
|
||||
res, sg[idx].page->index, offset, size);
|
||||
res, sg_page(&sg[idx])->index, offset, size);
|
||||
if (unlikely(res <= 0)) {
|
||||
if (res == -EINTR)
|
||||
goto retry2;
|
||||
else
|
||||
goto out_res;
|
||||
}
|
||||
check_net_priv(ref_cmd, sg[idx].page);
|
||||
check_net_priv(ref_cmd, sg_page(&sg[idx]));
|
||||
if (res == size) {
|
||||
conn->write_size = 0;
|
||||
return saved_size;
|
||||
@@ -958,19 +960,19 @@ retry2:
|
||||
}
|
||||
|
||||
retry1:
|
||||
res = sendpage(sock, sg[idx].page, offset, sendsize,
|
||||
res = sendpage(sock, sg_page(&sg[idx]), offset, sendsize,
|
||||
flags | MSG_MORE);
|
||||
TRACE_WRITE("%s %#Lx:%u: %d(%lu,%u,%u)",
|
||||
sock->ops->sendpage ? "sendpage" : "sock_no_sendpage",
|
||||
(unsigned long long ) conn->session->sid, conn->cid,
|
||||
res, sg[idx].page->index, offset, sendsize);
|
||||
res, sg_page(&sg[idx])->index, offset, sendsize);
|
||||
if (unlikely(res <= 0)) {
|
||||
if (res == -EINTR)
|
||||
goto retry1;
|
||||
else
|
||||
goto out_res;
|
||||
}
|
||||
check_net_priv(ref_cmd, sg[idx].page);
|
||||
check_net_priv(ref_cmd, sg_page(&sg[idx]));
|
||||
if (res == sendsize) {
|
||||
idx++;
|
||||
offset = 0;
|
||||
@@ -988,7 +990,7 @@ out_iov:
|
||||
return saved_size - size;
|
||||
|
||||
out_res:
|
||||
check_net_priv(ref_cmd, sg[idx].page);
|
||||
check_net_priv(ref_cmd, sg_page(&sg[idx]));
|
||||
if (res == -EAGAIN)
|
||||
goto out;
|
||||
/* else go through */
|
||||
|
||||
@@ -1016,8 +1016,8 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha,
|
||||
case CTIO_TIMEOUT:
|
||||
case CTIO_INVALID_RX_ID:
|
||||
/* they are OK */
|
||||
TRACE_MGMT_DBG("qla2x00tgt(%ld): CTIO with status %#x "
|
||||
"received (LIP_RESET=e, ABORTED=2, "
|
||||
TRACE(TRACE_MGMT_MINOR, "qla2x00tgt(%ld): CTIO with "
|
||||
"status %#x received (LIP_RESET=e, ABORTED=2, "
|
||||
"TARGET_RESET=17, TIMEOUT=b, "
|
||||
"INVALID_RX_ID=8)", ha->instance, status);
|
||||
break;
|
||||
@@ -1052,7 +1052,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha,
|
||||
goto out;
|
||||
}
|
||||
if (unlikely(err)) {
|
||||
PRINT_INFO("Found by handle failed CTIO scst_cmd "
|
||||
TRACE_MGMT_DBG("Found by handle failed CTIO scst_cmd "
|
||||
"%p (op %x)", scst_cmd, scst_cmd->cdb[0]);
|
||||
}
|
||||
} else if (ctio != NULL) {
|
||||
@@ -1075,7 +1075,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha,
|
||||
goto out;
|
||||
}
|
||||
if (unlikely(err)) {
|
||||
PRINT_INFO("Found by ctio failed CTIO scst_cmd %p "
|
||||
TRACE_MGMT_DBG("Found by ctio failed CTIO scst_cmd %p "
|
||||
"(op %x)", scst_cmd, scst_cmd->cdb[0]);
|
||||
}
|
||||
|
||||
@@ -1085,7 +1085,8 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha,
|
||||
|
||||
cmd = (struct q2t_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
|
||||
if (unlikely(err)) {
|
||||
PRINT_INFO("Failed CTIO state %d", cmd->state);
|
||||
TRACE(TRACE_MGMT_MINOR, "Failed CTIO state %d (err %x)",
|
||||
cmd->state, status);
|
||||
}
|
||||
|
||||
if (cmd->state == Q2T_STATE_PROCESSED) {
|
||||
@@ -1120,7 +1121,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha,
|
||||
|
||||
scst_rx_data(scst_cmd, rx_status, context);
|
||||
} else if (cmd->state == Q2T_STATE_ABORTED) {
|
||||
TRACE_DBG("Aborted command %p finished", cmd);
|
||||
TRACE_MGMT_DBG("Aborted command %p finished", cmd);
|
||||
goto out_free;
|
||||
} else {
|
||||
PRINT_ERROR("qla2x00tgt(%ld): A command in state (%d) should "
|
||||
|
||||
@@ -69,10 +69,10 @@
|
||||
#define NOTIFY_ACK_TM_RESP_CODE_VALID BIT_4
|
||||
|
||||
/* Command's states */
|
||||
#define Q2T_STATE_NEW 0 /* New command and SCST processes it */
|
||||
#define Q2T_STATE_NEW 0 /* New command and SCST processing it */
|
||||
#define Q2T_STATE_PROCESSED 1 /* SCST done processing */
|
||||
#define Q2T_STATE_NEED_DATA 2 /* SCST needs data to process */
|
||||
#define Q2T_STATE_DATA_IN 3 /* Data arrived and SCST processes it */
|
||||
#define Q2T_STATE_NEED_DATA 2 /* SCST needs data to continue */
|
||||
#define Q2T_STATE_DATA_IN 3 /* Data arrived and SCST processing them */
|
||||
#define Q2T_STATE_ABORTED 4 /* Command aborted */
|
||||
|
||||
/* Misc */
|
||||
|
||||
+2
-2
@@ -61,14 +61,14 @@ qla2x00_store_tgt_enabled(struct class_device *cdev,
|
||||
case '0' :
|
||||
if ((ha->flags.enable_target_mode) || force) {
|
||||
qla_target.tgt_host_action(ha, DISABLE_TARGET_MODE);
|
||||
msleep_interruptible(10*1000);
|
||||
}
|
||||
msleep_interruptible(3*1000);
|
||||
break;
|
||||
case '1' :
|
||||
if ((ha->flags.enable_target_mode == 0) || force) {
|
||||
qla_target.tgt_host_action(ha, ENABLE_TARGET_MODE);
|
||||
msleep_interruptible(10*1000);
|
||||
}
|
||||
msleep_interruptible(3*1000);
|
||||
break;
|
||||
default:
|
||||
printk("%s: Requested action not understood: %s\n",
|
||||
|
||||
+86
-2
@@ -36,6 +36,10 @@
|
||||
|
||||
#include <scst_const.h>
|
||||
|
||||
#ifndef DECLARE_MUTEX_LOCKED
|
||||
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
|
||||
typedef _Bool bool;
|
||||
#endif
|
||||
@@ -2235,6 +2239,52 @@ static inline int scst_mgmt_cmd_get_status(struct scst_mgmt_cmd *mcmd)
|
||||
return mcmd->status;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
|
||||
|
||||
static inline struct page *sg_page(struct scatterlist *sg)
|
||||
{
|
||||
return sg->page;
|
||||
}
|
||||
|
||||
static inline void *sg_virt(struct scatterlist *sg)
|
||||
{
|
||||
return page_address(sg_page(sg)) + sg->offset;
|
||||
}
|
||||
|
||||
static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
|
||||
{
|
||||
memset(sgl, 0, sizeof(*sgl) * nents);
|
||||
}
|
||||
|
||||
static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
|
||||
{
|
||||
sg->page = page;
|
||||
}
|
||||
|
||||
static inline void sg_set_page(struct scatterlist *sg, struct page *page,
|
||||
unsigned int len, unsigned int offset)
|
||||
{
|
||||
sg_assign_page(sg, page);
|
||||
sg->offset = offset;
|
||||
sg->length = len;
|
||||
}
|
||||
|
||||
static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
|
||||
unsigned int buflen)
|
||||
{
|
||||
sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
|
||||
}
|
||||
|
||||
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) */
|
||||
|
||||
static inline void sg_clear(struct scatterlist *sg)
|
||||
{
|
||||
memset(sg, 0, sizeof(*sg));
|
||||
#ifdef CONFIG_DEBUG_SG
|
||||
sg->sg_magic = SG_MAGIC;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions for access to the commands data (SG) buffer,
|
||||
* including HIGHMEM environment. Should be used instead of direct
|
||||
@@ -2245,7 +2295,41 @@ static inline int scst_mgmt_cmd_get_status(struct scst_mgmt_cmd *mcmd)
|
||||
*
|
||||
* The "put" function unmaps the buffer.
|
||||
*/
|
||||
int __scst_get_buf(struct scst_cmd *cmd, uint8_t **buf);
|
||||
static inline int __scst_get_buf(struct scst_cmd *cmd, uint8_t **buf)
|
||||
{
|
||||
int res = 0;
|
||||
struct scatterlist *sg = cmd->sg;
|
||||
int i = cmd->get_sg_buf_entry_num;
|
||||
|
||||
*buf = NULL;
|
||||
|
||||
if ((i >= cmd->sg_cnt) || unlikely(sg == NULL))
|
||||
goto out;
|
||||
#ifdef SCST_HIGHMEM /* HIGHMEM isn't currently supported */
|
||||
/*
|
||||
* HIGHMEM pages not merged (clustered), so if it's
|
||||
* not HIGHMEM page, kmap() is the same as page_address()
|
||||
*/
|
||||
if (scst_cmd_atomic(cmd)) {
|
||||
enum km_type km;
|
||||
if (in_softirq())
|
||||
km = KM_SOFTIRQ0;
|
||||
else
|
||||
km = KM_USER0;
|
||||
*buf = kmap_atomic(sg[i].page, km);
|
||||
} else
|
||||
*buf = kmap(sg[i].page);
|
||||
#else
|
||||
*buf = page_address(sg_page(&sg[i]));
|
||||
#endif
|
||||
*buf += sg[i].offset;
|
||||
res = sg[i].length;
|
||||
cmd->get_sg_buf_entry_num++;
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int scst_get_buf_first(struct scst_cmd *cmd, uint8_t **buf)
|
||||
{
|
||||
cmd->get_sg_buf_entry_num = 0;
|
||||
@@ -2260,7 +2344,7 @@ static inline int scst_get_buf_next(struct scst_cmd *cmd, uint8_t **buf)
|
||||
|
||||
static inline void scst_put_buf(struct scst_cmd *cmd, void *buf)
|
||||
{
|
||||
#ifdef SCST_HIGHMEM
|
||||
#ifdef SCST_HIGHMEM /* HIGHMEM isn't currently supported */
|
||||
if (cmd->sg_cnt) {
|
||||
if (scst_cmd_atomic(cmd)) {
|
||||
enum km_type km;
|
||||
|
||||
@@ -346,17 +346,16 @@ static struct page *dev_user_alloc_pages(struct scatterlist *sg,
|
||||
if (ucmd->cur_data_page >= ucmd->num_data_pages)
|
||||
goto out;
|
||||
|
||||
sg->page = ucmd->data_pages[ucmd->cur_data_page];
|
||||
sg->length = PAGE_SIZE - sg->offset;
|
||||
|
||||
sg_set_page(sg, ucmd->data_pages[ucmd->cur_data_page],
|
||||
PAGE_SIZE - sg->offset, 0);
|
||||
ucmd->cur_data_page++;
|
||||
|
||||
TRACE_MEM("page=%p, length=%d", sg->page, sg->length);
|
||||
TRACE_BUFFER("Page data", page_address(sg->page), sg->length);
|
||||
TRACE_MEM("page=%p, length=%d", sg_page(sg), sg->length);
|
||||
TRACE_BUFFER("Page data", sg_virt(sg), sg->length);
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return sg->page;
|
||||
return sg_page(sg);
|
||||
}
|
||||
|
||||
static void dev_user_on_cached_mem_free(struct scst_user_cmd *ucmd)
|
||||
|
||||
@@ -2196,12 +2196,18 @@ static inline void blockio_check_finish(struct blockio_work *blockio_work)
|
||||
}
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
|
||||
static int blockio_endio(struct bio *bio, unsigned int bytes_done, int error)
|
||||
#else
|
||||
static void blockio_endio(struct bio *bio, int error)
|
||||
#endif
|
||||
{
|
||||
struct blockio_work *blockio_work = bio->bi_private;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
|
||||
if (bio->bi_size)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? error : -EIO;
|
||||
|
||||
@@ -2224,7 +2230,11 @@ static int blockio_endio(struct bio *bio, unsigned int bytes_done, int error)
|
||||
blockio_check_finish(blockio_work);
|
||||
|
||||
bio_put(bio);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
|
||||
return 0;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
|
||||
@@ -2233,10 +2243,10 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
|
||||
struct scst_vdisk_dev *virt_dev = thr->virt_dev;
|
||||
struct block_device *bdev = thr->bdev;
|
||||
struct request_queue *q = bdev_get_queue(bdev);
|
||||
int j, max_nr_vecs = 0;
|
||||
int length, max_nr_vecs = 0;
|
||||
uint8_t *address;
|
||||
struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
|
||||
int need_new_bio;
|
||||
struct scatterlist *sgl = cmd->sg;
|
||||
struct blockio_work *blockio_work;
|
||||
int bios = 0;
|
||||
|
||||
@@ -2258,24 +2268,27 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
|
||||
max_nr_vecs = 1;
|
||||
|
||||
need_new_bio = 1;
|
||||
for (j = 0; j < cmd->sg_cnt; ++j) {
|
||||
int len, bytes, off, thislen;
|
||||
struct page *page;
|
||||
|
||||
page = sgl[j].page;
|
||||
off = sgl[j].offset;
|
||||
len = sgl[j].length;
|
||||
length = scst_get_buf_first(cmd, &address);
|
||||
while(length > 0) {
|
||||
int len, bytes, off, thislen;
|
||||
uint8_t *addr;
|
||||
|
||||
addr = address;
|
||||
off = offset_in_page(addr);
|
||||
len = length;
|
||||
thislen = 0;
|
||||
|
||||
while (len > 0) {
|
||||
int rc;
|
||||
struct page *page = virt_to_page(addr);
|
||||
|
||||
if (need_new_bio) {
|
||||
bio = bio_alloc(GFP_KERNEL, max_nr_vecs);
|
||||
if (!bio) {
|
||||
PRINT_ERROR("Failed to create bio "
|
||||
"for data segment= %d "
|
||||
"cmd %p", j, cmd);
|
||||
"for data segment= %d cmd %p",
|
||||
cmd->get_sg_buf_entry_num, cmd);
|
||||
goto out_no_bio;
|
||||
}
|
||||
|
||||
@@ -2306,13 +2319,16 @@ static void blockio_exec_rw(struct scst_cmd *cmd, struct scst_vdisk_thr *thr,
|
||||
continue;
|
||||
}
|
||||
|
||||
page++;
|
||||
addr += PAGE_SIZE;
|
||||
thislen += bytes;
|
||||
len -= bytes;
|
||||
off = 0;
|
||||
}
|
||||
|
||||
lba_start += sgl[j].length >> virt_dev->block_shift;
|
||||
lba_start += length >> virt_dev->block_shift;
|
||||
|
||||
scst_put_buf(cmd, address);
|
||||
length = scst_get_buf_next(cmd, &address);
|
||||
}
|
||||
|
||||
/* +1 to prevent erroneous too early command completion */
|
||||
|
||||
@@ -1567,44 +1567,6 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
int __scst_get_buf(struct scst_cmd *cmd, uint8_t **buf)
|
||||
{
|
||||
int res = 0;
|
||||
struct scatterlist *sg = cmd->sg;
|
||||
int i = cmd->get_sg_buf_entry_num;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
*buf = NULL;
|
||||
|
||||
if ((i >= cmd->sg_cnt) || unlikely(sg == NULL))
|
||||
goto out;
|
||||
#ifdef SCST_HIGHMEM
|
||||
/*
|
||||
* HIGHMEM pages not merged (clustered), so if it's
|
||||
* not HIGHMEM page, kmap() is the same as page_address()
|
||||
*/
|
||||
if (scst_cmd_atomic(cmd)) {
|
||||
enum km_type km;
|
||||
if (in_softirq())
|
||||
km = KM_SOFTIRQ0;
|
||||
else
|
||||
km = KM_USER0;
|
||||
*buf = kmap_atomic(sg[i].page, km);
|
||||
} else
|
||||
*buf = kmap(sg[i].page);
|
||||
#else
|
||||
*buf = page_address(sg[i].page);
|
||||
#endif
|
||||
*buf += sg[i].offset;
|
||||
res = sg[i].length;
|
||||
cmd->get_sg_buf_entry_num++;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static const int SCST_CDB_LENGTH[8] = { 6, 10, 10, -1, 16, 12, -1, -1 };
|
||||
|
||||
#define SCST_CDB_GROUP(opcode) ((opcode >> 5) & 0x7)
|
||||
|
||||
@@ -296,7 +296,7 @@ struct scst_tgt *scst_register(struct scst_tgt_template *vtt,
|
||||
|
||||
tgt = kzalloc(sizeof(*tgt), GFP_KERNEL);
|
||||
if (tgt == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s", "kzalloc() failed");
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of tgt failed");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
@@ -1736,7 +1736,6 @@ EXPORT_SYMBOL(scst_proc_log_entry_write);
|
||||
EXPORT_SYMBOL(scst_create_proc_entry);
|
||||
EXPORT_SYMBOL(scst_single_seq_open);
|
||||
|
||||
EXPORT_SYMBOL(__scst_get_buf);
|
||||
EXPORT_SYMBOL(scst_get);
|
||||
EXPORT_SYMBOL(scst_put);
|
||||
|
||||
|
||||
+33
-27
@@ -75,7 +75,7 @@ static int scst_check_clustering(struct scatterlist *sg, int cur, int hint)
|
||||
{
|
||||
int res = -1;
|
||||
int i = hint;
|
||||
unsigned long pfn_cur = page_to_pfn(sg[cur].page);
|
||||
unsigned long pfn_cur = page_to_pfn(sg_page(&sg[cur]));
|
||||
int len_cur = sg[cur].length;
|
||||
unsigned long pfn_cur_next = pfn_cur + (len_cur >> PAGE_SHIFT);
|
||||
int full_page_cur = (len_cur & (PAGE_SIZE - 1)) == 0;
|
||||
@@ -95,7 +95,7 @@ static int scst_check_clustering(struct scatterlist *sg, int cur, int hint)
|
||||
|
||||
/* check the hint first */
|
||||
if (i >= 0) {
|
||||
pfn = page_to_pfn(sg[i].page);
|
||||
pfn = page_to_pfn(sg_page(&sg[i]));
|
||||
pfn_next = pfn + (sg[i].length >> PAGE_SHIFT);
|
||||
full_page = (sg[i].length & (PAGE_SIZE - 1)) == 0;
|
||||
|
||||
@@ -108,7 +108,7 @@ static int scst_check_clustering(struct scatterlist *sg, int cur, int hint)
|
||||
|
||||
/* ToDo: implement more intelligent search */
|
||||
for(i = cur - 1; i >= 0; i--) {
|
||||
pfn = page_to_pfn(sg[i].page);
|
||||
pfn = page_to_pfn(sg_page(&sg[i]));
|
||||
pfn_next = pfn + (sg[i].length >> PAGE_SHIFT);
|
||||
full_page = (sg[i].length & (PAGE_SIZE - 1)) == 0;
|
||||
|
||||
@@ -125,15 +125,15 @@ out:
|
||||
out_tail:
|
||||
TRACE_MEM("SG segment %d will be tail merged with segment %d", cur, i);
|
||||
sg[i].length += len_cur;
|
||||
memset(&sg[cur], 0, sizeof(sg[cur]));
|
||||
sg_clear(&sg[cur]);
|
||||
res = i;
|
||||
goto out;
|
||||
|
||||
out_head:
|
||||
TRACE_MEM("SG segment %d will be head merged with segment %d", cur, i);
|
||||
sg[i].page = sg[cur].page;
|
||||
sg_assign_page(&sg[i], sg_page(&sg[cur]));
|
||||
sg[i].length += len_cur;
|
||||
memset(&sg[cur], 0, sizeof(sg[cur]));
|
||||
sg_clear(&sg[cur]);
|
||||
res = i;
|
||||
goto out;
|
||||
}
|
||||
@@ -146,7 +146,7 @@ static void scst_free_sys_sg_entries(struct scatterlist *sg, int sg_count,
|
||||
TRACE_MEM("sg=%p, sg_count=%d", sg, sg_count);
|
||||
|
||||
for(i = 0; i < sg_count; i++) {
|
||||
struct page *p = sg[i].page;
|
||||
struct page *p = sg_page(&sg[i]);
|
||||
int len = sg[i].length;
|
||||
int pages =
|
||||
(len >> PAGE_SHIFT) + ((len & ~PAGE_MASK) != 0);
|
||||
@@ -182,15 +182,15 @@ static void scst_free_sys_sg_entries(struct scatterlist *sg, int sg_count,
|
||||
static struct page *scst_alloc_sys_pages(struct scatterlist *sg,
|
||||
gfp_t gfp_mask, void *priv)
|
||||
{
|
||||
sg->page = alloc_pages(gfp_mask, 0);
|
||||
sg->offset = 0;
|
||||
sg->length = PAGE_SIZE;
|
||||
TRACE_MEM("page=%p, sg=%p, priv=%p", sg->page, sg, priv);
|
||||
if (sg->page == NULL) {
|
||||
struct page *page = alloc_pages(gfp_mask, 0);
|
||||
|
||||
sg_set_page(sg, page, PAGE_SIZE, 0);
|
||||
TRACE_MEM("page=%p, sg=%p, priv=%p", page, sg, priv);
|
||||
if (page == NULL) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of "
|
||||
"sg page failed");
|
||||
}
|
||||
return sg->page;
|
||||
return page;
|
||||
}
|
||||
|
||||
static int scst_alloc_sg_entries(struct scatterlist *sg, int pages,
|
||||
@@ -265,7 +265,7 @@ static int sgv_alloc_arrays(struct sgv_pool_obj *obj,
|
||||
|
||||
sz = pages_to_alloc * sizeof(obj->sg_entries[0]);
|
||||
|
||||
obj->sg_entries = (struct scatterlist*)kzalloc(sz, gfp_mask);
|
||||
obj->sg_entries = (struct scatterlist*)kmalloc(sz, gfp_mask);
|
||||
if (unlikely(obj->sg_entries == NULL)) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "Allocation of sgv_pool_obj "
|
||||
"SG vector failed (size %d)", sz);
|
||||
@@ -273,6 +273,8 @@ static int sgv_alloc_arrays(struct sgv_pool_obj *obj,
|
||||
goto out;
|
||||
}
|
||||
|
||||
sg_init_table(obj->sg_entries, pages_to_alloc);
|
||||
|
||||
if (obj->owner_pool->clustered) {
|
||||
if (order <= sgv_pools_mgr.sgv_max_trans_order) {
|
||||
obj->trans_tbl = (struct trans_tbl_ent*)obj->sg_entries_data;
|
||||
@@ -528,7 +530,6 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
|
||||
if (obj->sg_count != 0) {
|
||||
TRACE_MEM("Cached sgv_obj %p", obj);
|
||||
EXTRACHECKS_BUG_ON(obj->order != order);
|
||||
atomic_inc(&pool->acc.hit_alloc);
|
||||
atomic_inc(&pool->cache_acc[order].hit_alloc);
|
||||
goto success;
|
||||
}
|
||||
@@ -540,9 +541,8 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
|
||||
TRACE_MEM("Brand new sgv_obj %p", obj);
|
||||
if (order <= sgv_pools_mgr.sgv_max_local_order) {
|
||||
obj->sg_entries = obj->sg_entries_data;
|
||||
sg_init_table(obj->sg_entries, pages_to_alloc);
|
||||
TRACE_MEM("sg_entries %p", obj->sg_entries);
|
||||
memset(obj->sg_entries, 0,
|
||||
pages_to_alloc*sizeof(obj->sg_entries[0]));
|
||||
if (pool->clustered) {
|
||||
obj->trans_tbl = (struct trans_tbl_ent*)
|
||||
(obj->sg_entries + pages_to_alloc);
|
||||
@@ -572,16 +572,19 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
|
||||
goto out_return2;
|
||||
cache = NULL;
|
||||
sz = sizeof(*obj) + pages*sizeof(obj->sg_entries[0]);
|
||||
obj = kzalloc(sz, gfp_mask);
|
||||
obj = kmalloc(sz, gfp_mask);
|
||||
if (unlikely(obj == NULL)) {
|
||||
TRACE(TRACE_OUT_OF_MEM, "Allocation of "
|
||||
"sgv_pool_obj failed (size %d)", size);
|
||||
goto out_fail;
|
||||
}
|
||||
memset(obj, 0, sizeof(*obj));
|
||||
obj->owner_pool = pool;
|
||||
obj->order = -1 - order;
|
||||
obj->sg_entries = obj->sg_entries_data;
|
||||
obj->allocator_priv = priv;
|
||||
|
||||
obj->sg_entries = obj->sg_entries_data;
|
||||
sg_init_table(obj->sg_entries, pages);
|
||||
|
||||
if (sgv_pool_hiwmk_check(pages_to_alloc, no_fail) != 0)
|
||||
goto out_fail_free_sg_entries;
|
||||
@@ -600,7 +603,6 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
|
||||
}
|
||||
|
||||
success:
|
||||
atomic_inc(&pool->acc.total_alloc);
|
||||
spin_lock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
sgv_pools_mgr.mgr.thr.active_pages_total += 1 << order;
|
||||
spin_unlock_bh(&sgv_pools_mgr.mgr.pool_mgr_lock);
|
||||
@@ -728,10 +730,12 @@ struct scatterlist *scst_alloc(int size, unsigned long gfp_mask, int *count)
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = kzalloc(pages*sizeof(*res), gfp_mask);
|
||||
res = kmalloc(pages*sizeof(*res), gfp_mask);
|
||||
if (res == NULL)
|
||||
goto out;
|
||||
|
||||
sg_init_table(res, pages);
|
||||
|
||||
/*
|
||||
* If we allow use clustering here, we will have troubles in
|
||||
* scst_free() to figure out how many pages are in the SG vector.
|
||||
@@ -791,8 +795,6 @@ int sgv_pool_init(struct sgv_pool *pool, const char *name, int clustered)
|
||||
|
||||
atomic_set(&pool->acc.other_alloc, 0);
|
||||
atomic_set(&pool->acc.big_alloc, 0);
|
||||
atomic_set(&pool->acc.total_alloc, 0);
|
||||
atomic_set(&pool->acc.hit_alloc, 0);
|
||||
|
||||
pool->clustered = clustered;
|
||||
pool->alloc_fns.alloc_pages_fn = scst_alloc_sys_pages;
|
||||
@@ -1058,8 +1060,8 @@ int scst_sgv_pools_init(unsigned long mem_hwmark, unsigned long mem_lwmark)
|
||||
int res;
|
||||
struct scst_sgv_pools_manager *pools = &sgv_pools_mgr;
|
||||
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
memset(pools, 0, sizeof(*pools));
|
||||
|
||||
sgv_pools_mgr.mgr.thr.hi_wmk = mem_hwmark >> PAGE_SHIFT;
|
||||
@@ -1154,11 +1156,15 @@ void scst_sgv_pools_deinit(void)
|
||||
|
||||
static void scst_do_sgv_read(struct seq_file *seq, const struct sgv_pool *pool)
|
||||
{
|
||||
int i;
|
||||
int i, total = 0, hit = 0;
|
||||
|
||||
for(i = 0; i < SGV_POOL_ELEMENTS; i++) {
|
||||
hit += atomic_read(&pool->cache_acc[i].hit_alloc);
|
||||
total += atomic_read(&pool->cache_acc[i].total_alloc);
|
||||
}
|
||||
|
||||
seq_printf(seq, "\n%-30s %-11d %-11d %d/%d (P/O)\n", pool->name,
|
||||
atomic_read(&pool->acc.hit_alloc),
|
||||
atomic_read(&pool->acc.total_alloc),
|
||||
hit, total,
|
||||
pool->acc.cached_pages,
|
||||
pool->acc.cached_entries);
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ struct sgv_pool_obj
|
||||
|
||||
struct sgv_pool_acc
|
||||
{
|
||||
atomic_t total_alloc, hit_alloc;
|
||||
u32 cached_pages, cached_entries;
|
||||
atomic_t big_alloc, other_alloc;
|
||||
};
|
||||
|
||||
@@ -1211,10 +1211,10 @@ static void scst_cmd_done_local(struct scst_cmd *cmd, int next_state)
|
||||
int i;
|
||||
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[0].page);
|
||||
"%p", cmd->sg_cnt, sg, (void*)sg_page(&sg[0]));
|
||||
for(i = 0; i < cmd->sg_cnt; ++i) {
|
||||
TRACE_BUFF_FLAG(TRACE_RCV_TOP,
|
||||
"Exec'd sg", page_address(sg[i].page),
|
||||
"Exec'd sg", sg_virt(&sg[i]),
|
||||
sg[i].length);
|
||||
}
|
||||
}
|
||||
@@ -2553,10 +2553,10 @@ static int scst_xmit_response(struct scst_cmd *cmd)
|
||||
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[0].page);
|
||||
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", page_address(sg[i].page),
|
||||
"Xmitting sg", sg_virt(&sg[i]),
|
||||
sg[i].length);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user