History

vmxnet3: must split too big fragments

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.

Eric Dumazet committed 14 years ago

Commit a4d7e481 parent 78933631 file · +45 −20Browse files

Unified · Split

drivers/net/vmxnet3/vmxnet3_drv.c+45−20
@@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, · 743 unmodified lines
744 744
745 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {745 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
746 const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];746 const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
747 u32 buf_size;
747 748
748 tbi = tq->buf_info + tq->tx_ring.next2fill;749 buf_offset = 0;
749 tbi->map_type = VMXNET3_MAP_PAGE;750 len = skb_frag_size(frag);
750 tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,751 while (len) {
751 0, skb_frag_size(frag),752 tbi = tq->buf_info + tq->tx_ring.next2fill;
752 DMA_TO_DEVICE);753 if (len < VMXNET3_MAX_TX_BUF_SIZE) {
754 buf_size = len;
755 dw2 |= len;
756 } else {
757 buf_size = VMXNET3_MAX_TX_BUF_SIZE;
758 /* spec says that for TxDesc.len, 0 == 2^14 */
759 }
760 tbi->map_type = VMXNET3_MAP_PAGE;
761 tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
762 buf_offset, buf_size,
763 DMA_TO_DEVICE);
753 764
754 tbi->len = skb_frag_size(frag);765 tbi->len = buf_size;
755 766
756 gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;767 gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
757 BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);768 BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
758 769
759 gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);770 gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
760 gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));771 gdesc->dword[2] = cpu_to_le32(dw2);
761 gdesc->dword[3] = 0;772 gdesc->dword[3] = 0;
762 773
763 dev_dbg(&adapter->netdev->dev,774 dev_dbg(&adapter->netdev->dev,
764 "txd[%u]: 0x%llu %u %u\n",775 "txd[%u]: 0x%llu %u %u\n",
765 tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),776 tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
766 le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);777 le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
767 vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);778 vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
768 dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;779 dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
780
781 len -= buf_size;
782 buf_offset += buf_size;
783 }
769 }784 }
770 785
771 ctx->eop_txd = gdesc;786 ctx->eop_txd = gdesc;
@@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb, · 114 unmodified lines
886 }901 }
887}902}
888 903
904static int txd_estimate(const struct sk_buff *skb)
905{
906 int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
907 int i;
908
909 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
910 const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
911
912 count += VMXNET3_TXD_NEEDED(skb_frag_size(frag));
913 }
914 return count;
915}
889 916
890/*917/*
891 * Transmits a pkt thru a given tq918 * Transmits a pkt thru a given tq
@@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, · 22 unmodified lines
914 union Vmxnet3_GenericDesc tempTxDesc;941 union Vmxnet3_GenericDesc tempTxDesc;
915#endif942#endif
916 943
917 /* conservatively estimate # of descriptors to use */944 count = txd_estimate(skb);
918 count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
919 skb_shinfo(skb)->nr_frags + 1;
920 945
921 ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));946 ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
922 947