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: Stephen Hemminger <sthemmin@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
e073782a41
Коммит
60b86665af
|
@ -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.
|
||||||
|
*/
|
||||||
|
static unsigned int netvsc_get_slots(const struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int i, frags = skb_shinfo(skb)->nr_frags;
|
return PFN_UP(offset_in_page(skb->data) + skb_headlen(skb))
|
||||||
int pages = 0;
|
+ skb_shinfo(skb)->nr_frags
|
||||||
|
+ 2;
|
||||||
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;
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче