On 11/3/10 4:15 PM, Kiran Patil wrote:
> 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
s/used/use/
> + * indicate it as DATA_SG_IO_CDB
> + */
> + if (!(se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))
Does that flag indicate the back-end's capability for SG's or libfc's capability
for SG's? It seems like any buffer that TCM gives us can be represented by
an SG list to hand to the libfc LLD.
> + 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;
Why not set this up in the session instead of testing seq_offload for each
frame?
Basically add lso_max to the session as a separate field. But ... that's OK
to do in a later enhancement.
> 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);
WARN_ON could be removed. Maybe printk should be rate-limited or deleted.
> }
> }
> return ft_queue_status(se_cmd);
>
> _______________________________________________
> devel mailing list
> [email protected]
> http://www.open-fcoe.org/mailman/listinfo/devel
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel