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! > > --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
