LGTM. Thanks for doing this! Did you do any performance testing with this patch?

Reviewed-by: Bhavesh Davda <bhav...@vmware.com>

--
Bhavesh Davda

----- Original Message -----
> From: "Eric Dumazet" <eric.duma...@gmail.com>
> To: "Shreyas Bhatewara" <sbhatew...@vmware.com>, "David Miller" 
> <da...@davemloft.net>
> Cc: "VMware, Inc." <pv-driv...@vmware.com>, net...@vger.kernel.org, 
> linux-kernel@vger.kernel.org, "jongman heo"
> <jongman....@samsung.com>
> Sent: Monday, October 29, 2012 10:30:49 AM
> Subject: [Pv-drivers] [PATCH] vmxnet3: must split too big fragments
> 
> From: Eric Dumazet <eduma...@google.com>
> 
> vmxnet3 has a 16Kbytes limit per tx descriptor, that happened to work
> as long as we provided PAGE_SIZE fragments.
> 
> Our stack can now build larger fragments, so we need to split them to
> the 16kbytes boundary.
> 
> Signed-off-by: Eric Dumazet <eduma...@google.com>
> Reported-by: jongman heo <jongman....@samsung.com>
> Tested-by: jongman heo <jongman....@samsung.com>
> Cc: Shreyas Bhatewara <sbhatew...@vmware.com>
> ---
>  drivers/net/vmxnet3/vmxnet3_drv.c |   65
>  +++++++++++++++++++---------
>  1 file changed, 45 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c
> b/drivers/net/vmxnet3/vmxnet3_drv.c
> index ce9d4f2..0ae1bcc 100644
> --- a/drivers/net/vmxnet3/vmxnet3_drv.c
> +++ b/drivers/net/vmxnet3/vmxnet3_drv.c
> @@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct
> vmxnet3_tx_ctx *ctx,
>  
>       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
>               const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
> +             u32 buf_size;
>  
> -             tbi = tq->buf_info + tq->tx_ring.next2fill;
> -             tbi->map_type = VMXNET3_MAP_PAGE;
> -             tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
> -                                              0, skb_frag_size(frag),
> -                                              DMA_TO_DEVICE);
> +             buf_offset = 0;
> +             len = skb_frag_size(frag);
> +             while (len) {
> +                     tbi = tq->buf_info + tq->tx_ring.next2fill;
> +                     if (len < VMXNET3_MAX_TX_BUF_SIZE) {
> +                             buf_size = len;
> +                             dw2 |= len;
> +                     } else {
> +                             buf_size = VMXNET3_MAX_TX_BUF_SIZE;
> +                             /* spec says that for TxDesc.len, 0 == 2^14 */
> +                     }
> +                     tbi->map_type = VMXNET3_MAP_PAGE;
> +                     tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, 
> frag,
> +                                                      buf_offset, buf_size,
> +                                                      DMA_TO_DEVICE);
>  
> -             tbi->len = skb_frag_size(frag);
> +                     tbi->len = buf_size;
>  
> -             gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
> -             BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
> +                     gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
> +                     BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
>  
> -             gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
> -             gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));
> -             gdesc->dword[3] = 0;
> +                     gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
> +                     gdesc->dword[2] = cpu_to_le32(dw2);
> +                     gdesc->dword[3] = 0;
>  
> -             dev_dbg(&adapter->netdev->dev,
> -                     "txd[%u]: 0x%llu %u %u\n",
> -                     tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
> -                     le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
> -             vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
> -             dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
> +                     dev_dbg(&adapter->netdev->dev,
> +                             "txd[%u]: 0x%llu %u %u\n",
> +                             tq->tx_ring.next2fill, 
> le64_to_cpu(gdesc->txd.addr),
> +                             le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
> +                     vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
> +                     dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
> +
> +                     len -= buf_size;
> +                     buf_offset += buf_size;
> +             }
>       }
>  
>       ctx->eop_txd = gdesc;
> @@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb,
>       }
>  }
>  
> +static int txd_estimate(const struct sk_buff *skb)
> +{
> +     int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
> +     int i;
> +
> +     for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
> +             const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
> +
> +             count += VMXNET3_TXD_NEEDED(skb_frag_size(frag));
> +     }
> +     return count;
> +}
>  
>  /*
>   * Transmits a pkt thru a given tq
> @@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct
> vmxnet3_tx_queue *tq,
>       union Vmxnet3_GenericDesc tempTxDesc;
>  #endif
>  
> -     /* conservatively estimate # of descriptors to use */
> -     count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
> -             skb_shinfo(skb)->nr_frags + 1;
> +     count = txd_estimate(skb);
>  
>       ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
>  
> 
> 
> _______________________________________________
> Pv-drivers mailing list
> pv-driv...@vmware.com
> http://mailman2.vmware.com/mailman/listinfo/pv-drivers
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to