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

Reply via email to