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.
Fix: Enhance function (ft_queue_data_in) which sends data back to initiator
to make use of
LSO feature of underlying HW.
Technical Details: Enhancement benefits in all threee cases , use_sg, mem, and
task_buf. This changes
are applicable only for SG_DATA_IO_CDB because most likely for other
CDB's, response data may
may not cross max_frame_size (2112).
Dependencies: This depends on TCM and Joe's FC4 patches for TCM
Signed-off-by: Kiran Patil <[email protected]>
---
drivers/target/tcm_fc/tfc_io.c | 39 ++++++++++++++++++++++++++++++++++++---
1 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index e77a45a..c64313d 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -111,7 +111,12 @@ 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 */
+ /*
+ * Change it to not used 'scatterlist' only if se_cmd_flags doesn't
+ * indicate it as DATA_SG_IO_CDB
+ */
+ if (!(se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))
+ use_sg = 0; /* XXX to test the non-sg path */
while (remaining) {
if (!mem_len) {
@@ -123,7 +128,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,6 +142,13 @@ 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_SIZE".
+ */
+ fr_max_payload(fp) = cmd->sess->max_frame;
}
tlen = min(mem_len, frame_len);
@@ -167,7 +185,17 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
frame_len -= tlen;
remaining -= tlen;
- if (frame_len)
+ if (use_sg) {
+ /*
+ * If using scatterlist, then allow (continue) building
+ * 'skb' as long as 'nr_frags' is less than
+ * FC_FRAME_SG_LEN and frame_len is valid, otherwise
+ * send the frame.
+ */
+ if (frame_len &&
+ (skb_shinfo(fp_skb(fp))->nr_frags < FC_FRAME_SG_LEN))
+ continue;
+ } else if (frame_len)
continue;
if (!remaining)
f_ctl |= FC_FC_END_SEQ;
@@ -177,6 +205,11 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
if (error) {
WARN_ON(1);
/* XXX For now, initiator will retry */
+ 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