Commit 60b86665 authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller

netvsc: optimize calculation of number of slots

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: default avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e073782a
...@@ -345,34 +345,14 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, ...@@ -345,34 +345,14 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb,
return slots_used; return slots_used;
} }
static int count_skb_frag_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.
int i, frags = skb_shinfo(skb)->nr_frags; */
int pages = 0; static unsigned int netvsc_get_slots(const struct sk_buff *skb)
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)
{ {
char *data = skb->data; return PFN_UP(offset_in_page(skb->data) + skb_headlen(skb))
unsigned int offset = offset_in_page(data); + skb_shinfo(skb)->nr_frags
unsigned int len = skb_headlen(skb); + 2;
int slots;
int frag_slots;
slots = DIV_ROUND_UP(offset + len, PAGE_SIZE);
frag_slots = count_skb_frag_slots(skb);
return slots + frag_slots;
} }
static u32 net_checksum_info(struct sk_buff *skb) 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) ...@@ -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 page_buf[MAX_PAGE_BUFFER_COUNT];
struct hv_page_buffer *pb = page_buf; struct hv_page_buffer *pb = page_buf;
/* We will atmost need two pages to describe the rndis /* We can only transmit MAX_PAGE_BUFFER_COUNT number
* header. We can only transmit MAX_PAGE_BUFFER_COUNT number
* of pages in a single packet. If skb is scattered around * of pages in a single packet. If skb is scattered around
* more pages we try linearizing it. * more pages we try linearizing it.
*/ */
num_data_pgs = netvsc_get_slots(skb);
num_data_pgs = netvsc_get_slots(skb) + 2;
if (unlikely(num_data_pgs > MAX_PAGE_BUFFER_COUNT)) { if (unlikely(num_data_pgs > MAX_PAGE_BUFFER_COUNT)) {
++net_device_ctx->eth_stats.tx_scattered; ++net_device_ctx->eth_stats.tx_scattered;
if (skb_linearize(skb)) if (skb_linearize(skb))
goto no_memory; 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) { if (num_data_pgs > MAX_PAGE_BUFFER_COUNT) {
++net_device_ctx->eth_stats.tx_too_big; ++net_device_ctx->eth_stats.tx_too_big;
goto drop; goto drop;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment