On Thu, 2010-11-11 at 17:07 -0800, Joe Eykholt wrote: > > On 11/11/10 5:00 PM, Nicholas A. Bellinger wrote: > > On Wed, 2010-11-10 at 17:44 -0800, 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. 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]> > > > > Btw, I think this patch looks good guys.. > > > > Joe, can I get your ACK and get this merged into lio-core-2.6.git for > > testing..? > > I reviewed it but didn't test it. Based on that, I'll give my ack. > > Acked-by: Joe Eykholt <[email protected]> >
Thanks Joe! Commited as: [tcm_fc_ddp_offload b035e31] TCM/OpenFCoE : Added Large Send Offload Author: Kiran Patil <[email protected]> 1 files changed, 37 insertions(+), 7 deletions(-) and pushed into lio-core-2.6.git/tcm_fc_ddp_offload for testing along with the latest lio-4.0 changes from hch. Thanks Kiran and Yi! --nab > > > > > Thanks! > > > > --nab > > > >> --- > >> > >> 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 > > _______________________________________________ devel mailing list [email protected] http://www.open-fcoe.org/mailman/listinfo/devel
