netvsc: optimize calculation of number of slots
authorstephen hemminger <stephen@networkplumber.org>
Thu, 8 Jun 2017 23:21:18 +0000 (16:21 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 9 Jun 2017 16:15:02 +0000 (12:15 -0400)
Speed up transmit check for fragmented packets by using existing
macros to compute number of pages, and eliminate loop since
skb fragments each take a page. Number of slots is also unsigned.

Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/hyperv/netvsc_drv.c

index 2564ac83eb64f70f6d7da6c8d666ea8cb3cbed2b..df6d8e28949e2c20b0a6292eba511c3dd0875084 100644 (file)
@@ -345,34 +345,14 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb,
        return slots_used;
 }
 
-static int count_skb_frag_slots(struct sk_buff *skb)
-{
-       int i, frags = skb_shinfo(skb)->nr_frags;
-       int pages = 0;
-
-       for (i = 0; i < frags; i++) {
-               skb_frag_t *frag = skb_shinfo(skb)->frags + i;
-               unsigned long size = skb_frag_size(frag);
-               unsigned long offset = frag->page_offset;
-
-               /* Skip unused frames from start of page */
-               offset &= ~PAGE_MASK;
-               pages += PFN_UP(offset + size);
-       }
-       return pages;
-}
-
-static int netvsc_get_slots(struct sk_buff *skb)
+/* Estimate number of page buffers neede to transmit
+ * Need at most 2 for RNDIS header plus skb body and fragments.
+ */
+static unsigned int netvsc_get_slots(const struct sk_buff *skb)
 {
-       char *data = skb->data;
-       unsigned int offset = offset_in_page(data);
-       unsigned int len = skb_headlen(skb);
-       int slots;
-       int frag_slots;
-
-       slots = DIV_ROUND_UP(offset + len, PAGE_SIZE);
-       frag_slots = count_skb_frag_slots(skb);
-       return slots + frag_slots;
+       return PFN_UP(offset_in_page(skb->data) + skb_headlen(skb))
+               + skb_shinfo(skb)->nr_frags
+               + 2;
 }
 
 static u32 net_checksum_info(struct sk_buff *skb)
@@ -410,21 +390,18 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
        struct hv_page_buffer page_buf[MAX_PAGE_BUFFER_COUNT];
        struct hv_page_buffer *pb = page_buf;
 
-       /* We will atmost need two pages to describe the rndis
-        * header. We can only transmit MAX_PAGE_BUFFER_COUNT number
+       /* We can only transmit MAX_PAGE_BUFFER_COUNT number
         * of pages in a single packet. If skb is scattered around
         * more pages we try linearizing it.
         */
-
-       num_data_pgs = netvsc_get_slots(skb) + 2;
-
+       num_data_pgs = netvsc_get_slots(skb);
        if (unlikely(num_data_pgs > MAX_PAGE_BUFFER_COUNT)) {
                ++net_device_ctx->eth_stats.tx_scattered;
 
                if (skb_linearize(skb))
                        goto no_memory;
 
-               num_data_pgs = netvsc_get_slots(skb) + 2;
+               num_data_pgs = netvsc_get_slots(skb);
                if (num_data_pgs > MAX_PAGE_BUFFER_COUNT) {
                        ++net_device_ctx->eth_stats.tx_too_big;
                        goto drop;