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

Reply via email to