From: Kiran Patil <[email protected]>
Problem: Existing implementation of TCM/LIO target isn't taking advantage of
underlying HW (NIC)
Large Send Offload (LSO) feature. Unable to use non-linear SKBs for
CONTROL_NONSG CDBs
such as INQUIRY, etc...
Fix: Enhance function (ft_queue_data_in) which sends data back to initiator
to make use of
LSO feature of underlying HW and fix the issues related to
CONTROL_NONSG, where code
was unable to map TCM provided buffer (t_task_buf) as non-linear SKB.
Technical Details: Enhancement benefits in all threee cases , use_sg, mem, and
task_buf. This changes
are applicable only for all CDBs (DATA/CONTROL SG/NONSG).
- Addressed comments from Joe w.r.t checking and making use_sg = 0 only
for DATA_SG whereas it is applicale for CONTROL_SG/CONTROL_NONSG.
- Made the prink rate limited (in case where "unable to send frame")
- Fixed 2 issues/bugs related to CONTROL_NONSG and non-linear SKB.
- Added a BUG_ON(!page)
Dependencies: This depends on TCM and Joe's FC4 patches for TCM
Signed-off-by: Kiran Patil <[email protected]>
Signed-off-by: Yi Zou <[email protected]>
---
drivers/target/tcm_fc/tfc_io.c | 44 ++++++++++++++++++++++++++++++++++------
1 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index e77a45a..4c3c0ef 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -78,6 +78,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
size_t frame_len = 0;
size_t mem_len;
size_t tlen;
+ size_t off_in_page;
struct page *page;
int use_sg;
int error;
@@ -111,7 +112,6 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
/* no scatter/gather in skb for odd word length due to fc_seq_send() */
use_sg = !(remaining % 4);
- use_sg = 0; /* XXX to test the non-sg path */
while (remaining) {
if (!mem_len) {
@@ -123,7 +123,13 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
page = mem->se_page;
}
if (!frame_len) {
- frame_len = cmd->sess->max_frame;
+ /*
+ * If lport's has capability of Large Send Offload LSO)
+ * , then allow 'frame_len' to be as big as 'lso_max'
+ * if indicated transfer length is >= lport->lso_max
+ */
+ frame_len = (lport->seq_offload) ? lport->lso_max :
+ cmd->sess->max_frame;
frame_len = min(frame_len, remaining);
fp = fc_frame_alloc(lport, use_sg ? 0 : frame_len);
if (!fp)
@@ -131,16 +137,34 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
to = fc_frame_payload_get(fp, 0);
fh_off = frame_off;
frame_off += frame_len;
+ /*
+ * Setup the frame's max payload which is used by base
+ * driver to indicate HW about max frame size, so that
+ * HW can do fragmentation appropriately based on
+ * "gso_max_size" of underline netdev.
+ */
+ fr_max_payload(fp) = cmd->sess->max_frame;
}
tlen = min(mem_len, frame_len);
if (use_sg) {
- if (!mem)
- page = virt_to_page(task->t_task_buf + mem_off);
+ if (!mem) {
+ BUG_ON(!task->t_task_buf);
+ page_addr = task->t_task_buf + mem_off;
+ /*
+ * In this case, offset is 'offset_in_page' of
+ * (t_task_buf + mem_off) instead of 'mem_off'.
+ */
+ off_in_page = offset_in_page(page_addr);
+ page = virt_to_page(page_addr);
+ tlen = min(tlen, PAGE_SIZE - off_in_page);
+ } else
+ off_in_page = mem_off;
+ BUG_ON(!page);
get_page(page);
skb_fill_page_desc(fp_skb(fp),
skb_shinfo(fp_skb(fp))->nr_frags,
- page, mem_off, tlen);
+ page, off_in_page, tlen);
fr_len(fp) += tlen;
fp_skb(fp)->data_len += tlen;
fp_skb(fp)->truesize +=
@@ -167,7 +191,8 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
frame_len -= tlen;
remaining -= tlen;
- if (frame_len)
+ if (frame_len &&
+ (skb_shinfo(fp_skb(fp))->nr_frags < FC_FRAME_SG_LEN))
continue;
if (!remaining)
f_ctl |= FC_FC_END_SEQ;
@@ -175,8 +200,13 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
FC_TYPE_FCP, f_ctl, fh_off);
error = lport->tt.seq_send(lport, cmd->seq, fp);
if (error) {
- WARN_ON(1);
/* XXX For now, initiator will retry */
+ if (printk_ratelimit())
+ printk(KERN_ERR "%s: Failed to send frame %p, "
+ "xid <0x%x>, remaining <0x%x>, "
+ "lso_max <0x%x>\n",
+ __func__, fp, ep->xid,
+ remaining, lport->lso_max);
}
}
return ft_queue_status(se_cmd);
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel