]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
ixgbevf: Cleanup accounting for space needed at start of xmit_frame
authorAlexander Duyck <alexander.h.duyck@intel.com>
Fri, 11 May 2012 08:32:40 +0000 (08:32 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 17 Jul 2012 09:47:41 +0000 (02:47 -0700)
This change cleans up the accounting needed at the start of xmit_frame so
that we can avoid doing too much work to determine how many descriptors we
will need.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c

index 75af1920b0f787cd6a9f3171b12b87c734c704ac..855bb21824fed63fc2279794dc32de1672791899 100644 (file)
@@ -175,10 +175,8 @@ static void ixgbevf_unmap_and_free_tx_resource(struct ixgbevf_adapter *adapter,
 #define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR)
 
 /* Tx Descriptors needed, worst case */
-#define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \
-                        (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
-#define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \
-       MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1)      /* for context */
+#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IXGBE_MAX_DATA_PER_TXD)
+#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
 
 static void ixgbevf_tx_timeout(struct net_device *netdev);
 
@@ -2932,33 +2930,37 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        unsigned int tx_flags = 0;
        u8 hdr_len = 0;
        int r_idx = 0, tso;
-       int count = 0;
-
-       unsigned int f;
+       u16 count = TXD_USE_COUNT(skb_headlen(skb));
+#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
+       unsigned short f;
+#endif
 
        tx_ring = &adapter->tx_ring[r_idx];
 
+       /*
+        * need: 1 descriptor per page * PAGE_SIZE/IXGBE_MAX_DATA_PER_TXD,
+        *       + 1 desc for skb_headlen/IXGBE_MAX_DATA_PER_TXD,
+        *       + 2 desc gap to keep tail from touching head,
+        *       + 1 desc for context descriptor,
+        * otherwise try next time
+        */
+#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
+       for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
+               count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
+#else
+       count += skb_shinfo(skb)->nr_frags;
+#endif
+       if (ixgbevf_maybe_stop_tx(netdev, tx_ring, count + 3)) {
+               adapter->tx_busy++;
+               return NETDEV_TX_BUSY;
+       }
+
        if (vlan_tx_tag_present(skb)) {
                tx_flags |= vlan_tx_tag_get(skb);
                tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
                tx_flags |= IXGBE_TX_FLAGS_VLAN;
        }
 
-       /* four things can cause us to need a context descriptor */
-       if (skb_is_gso(skb) ||
-           (skb->ip_summed == CHECKSUM_PARTIAL) ||
-           (tx_flags & IXGBE_TX_FLAGS_VLAN))
-               count++;
-
-       count += TXD_USE_COUNT(skb_headlen(skb));
-       for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
-               count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]));
-
-       if (ixgbevf_maybe_stop_tx(netdev, tx_ring, count)) {
-               adapter->tx_busy++;
-               return NETDEV_TX_BUSY;
-       }
-
        first = tx_ring->next_to_use;
 
        if (skb->protocol == htons(ETH_P_IP))