diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 136 |
1 files changed, 88 insertions, 48 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 7bab4de658a9..916241d16c67 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -299,35 +299,76 @@ static struct sk_buff *page_to_skb(struct receive_queue *rq, | |||
299 | return skb; | 299 | return skb; |
300 | } | 300 | } |
301 | 301 | ||
302 | static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb) | 302 | static struct sk_buff *receive_small(void *buf, unsigned int len) |
303 | { | 303 | { |
304 | struct skb_vnet_hdr *hdr = skb_vnet_hdr(head_skb); | 304 | struct sk_buff * skb = buf; |
305 | |||
306 | len -= sizeof(struct virtio_net_hdr); | ||
307 | skb_trim(skb, len); | ||
308 | |||
309 | return skb; | ||
310 | } | ||
311 | |||
312 | static struct sk_buff *receive_big(struct net_device *dev, | ||
313 | struct receive_queue *rq, | ||
314 | void *buf, | ||
315 | unsigned int len) | ||
316 | { | ||
317 | struct page *page = buf; | ||
318 | struct sk_buff *skb = page_to_skb(rq, page, 0, len, PAGE_SIZE); | ||
319 | |||
320 | if (unlikely(!skb)) | ||
321 | goto err; | ||
322 | |||
323 | return skb; | ||
324 | |||
325 | err: | ||
326 | dev->stats.rx_dropped++; | ||
327 | give_pages(rq, page); | ||
328 | return NULL; | ||
329 | } | ||
330 | |||
331 | static struct sk_buff *receive_mergeable(struct net_device *dev, | ||
332 | struct receive_queue *rq, | ||
333 | void *buf, | ||
334 | unsigned int len) | ||
335 | { | ||
336 | struct skb_vnet_hdr *hdr = buf; | ||
337 | int num_buf = hdr->mhdr.num_buffers; | ||
338 | struct page *page = virt_to_head_page(buf); | ||
339 | int offset = buf - page_address(page); | ||
340 | struct sk_buff *head_skb = page_to_skb(rq, page, offset, len, | ||
341 | MERGE_BUFFER_LEN); | ||
305 | struct sk_buff *curr_skb = head_skb; | 342 | struct sk_buff *curr_skb = head_skb; |
306 | char *buf; | ||
307 | struct page *page; | ||
308 | int num_buf, len, offset; | ||
309 | 343 | ||
310 | num_buf = hdr->mhdr.num_buffers; | 344 | if (unlikely(!curr_skb)) |
345 | goto err_skb; | ||
346 | |||
311 | while (--num_buf) { | 347 | while (--num_buf) { |
312 | int num_skb_frags = skb_shinfo(curr_skb)->nr_frags; | 348 | int num_skb_frags; |
349 | |||
313 | buf = virtqueue_get_buf(rq->vq, &len); | 350 | buf = virtqueue_get_buf(rq->vq, &len); |
314 | if (unlikely(!buf)) { | 351 | if (unlikely(!buf)) { |
315 | pr_debug("%s: rx error: %d buffers missing\n", | 352 | pr_debug("%s: rx error: %d buffers out of %d missing\n", |
316 | head_skb->dev->name, hdr->mhdr.num_buffers); | 353 | dev->name, num_buf, hdr->mhdr.num_buffers); |
317 | head_skb->dev->stats.rx_length_errors++; | 354 | dev->stats.rx_length_errors++; |
318 | return -EINVAL; | 355 | goto err_buf; |
319 | } | 356 | } |
320 | if (unlikely(len > MERGE_BUFFER_LEN)) { | 357 | if (unlikely(len > MERGE_BUFFER_LEN)) { |
321 | pr_debug("%s: rx error: merge buffer too long\n", | 358 | pr_debug("%s: rx error: merge buffer too long\n", |
322 | head_skb->dev->name); | 359 | dev->name); |
323 | len = MERGE_BUFFER_LEN; | 360 | len = MERGE_BUFFER_LEN; |
324 | } | 361 | } |
362 | |||
363 | page = virt_to_head_page(buf); | ||
364 | --rq->num; | ||
365 | |||
366 | num_skb_frags = skb_shinfo(curr_skb)->nr_frags; | ||
325 | if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) { | 367 | if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) { |
326 | struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC); | 368 | struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC); |
327 | if (unlikely(!nskb)) { | 369 | |
328 | head_skb->dev->stats.rx_dropped++; | 370 | if (unlikely(!nskb)) |
329 | return -ENOMEM; | 371 | goto err_skb; |
330 | } | ||
331 | if (curr_skb == head_skb) | 372 | if (curr_skb == head_skb) |
332 | skb_shinfo(curr_skb)->frag_list = nskb; | 373 | skb_shinfo(curr_skb)->frag_list = nskb; |
333 | else | 374 | else |
@@ -341,8 +382,7 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb) | |||
341 | head_skb->len += len; | 382 | head_skb->len += len; |
342 | head_skb->truesize += MERGE_BUFFER_LEN; | 383 | head_skb->truesize += MERGE_BUFFER_LEN; |
343 | } | 384 | } |
344 | page = virt_to_head_page(buf); | 385 | offset = buf - page_address(page); |
345 | offset = buf - (char *)page_address(page); | ||
346 | if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) { | 386 | if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) { |
347 | put_page(page); | 387 | put_page(page); |
348 | skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1, | 388 | skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1, |
@@ -351,9 +391,28 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb) | |||
351 | skb_add_rx_frag(curr_skb, num_skb_frags, page, | 391 | skb_add_rx_frag(curr_skb, num_skb_frags, page, |
352 | offset, len, MERGE_BUFFER_LEN); | 392 | offset, len, MERGE_BUFFER_LEN); |
353 | } | 393 | } |
394 | } | ||
395 | |||
396 | return head_skb; | ||
397 | |||
398 | err_skb: | ||
399 | put_page(page); | ||
400 | while (--num_buf) { | ||
401 | buf = virtqueue_get_buf(rq->vq, &len); | ||
402 | if (unlikely(!buf)) { | ||
403 | pr_debug("%s: rx error: %d buffers missing\n", | ||
404 | dev->name, num_buf); | ||
405 | dev->stats.rx_length_errors++; | ||
406 | break; | ||
407 | } | ||
408 | page = virt_to_head_page(buf); | ||
409 | put_page(page); | ||
354 | --rq->num; | 410 | --rq->num; |
355 | } | 411 | } |
356 | return 0; | 412 | err_buf: |
413 | dev->stats.rx_dropped++; | ||
414 | dev_kfree_skb(head_skb); | ||
415 | return NULL; | ||
357 | } | 416 | } |
358 | 417 | ||
359 | static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) | 418 | static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) |
@@ -362,7 +421,6 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) | |||
362 | struct net_device *dev = vi->dev; | 421 | struct net_device *dev = vi->dev; |
363 | struct virtnet_stats *stats = this_cpu_ptr(vi->stats); | 422 | struct virtnet_stats *stats = this_cpu_ptr(vi->stats); |
364 | struct sk_buff *skb; | 423 | struct sk_buff *skb; |
365 | struct page *page; | ||
366 | struct skb_vnet_hdr *hdr; | 424 | struct skb_vnet_hdr *hdr; |
367 | 425 | ||
368 | if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { | 426 | if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { |
@@ -377,33 +435,15 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) | |||
377 | return; | 435 | return; |
378 | } | 436 | } |
379 | 437 | ||
380 | if (!vi->mergeable_rx_bufs && !vi->big_packets) { | 438 | if (vi->mergeable_rx_bufs) |
381 | skb = buf; | 439 | skb = receive_mergeable(dev, rq, buf, len); |
382 | len -= sizeof(struct virtio_net_hdr); | 440 | else if (vi->big_packets) |
383 | skb_trim(skb, len); | 441 | skb = receive_big(dev, rq, buf, len); |
384 | } else if (vi->mergeable_rx_bufs) { | 442 | else |
385 | struct page *page = virt_to_head_page(buf); | 443 | skb = receive_small(buf, len); |
386 | skb = page_to_skb(rq, page, | 444 | |
387 | (char *)buf - (char *)page_address(page), | 445 | if (unlikely(!skb)) |
388 | len, MERGE_BUFFER_LEN); | 446 | return; |
389 | if (unlikely(!skb)) { | ||
390 | dev->stats.rx_dropped++; | ||
391 | put_page(page); | ||
392 | return; | ||
393 | } | ||
394 | if (receive_mergeable(rq, skb)) { | ||
395 | dev_kfree_skb(skb); | ||
396 | return; | ||
397 | } | ||
398 | } else { | ||
399 | page = buf; | ||
400 | skb = page_to_skb(rq, page, 0, len, PAGE_SIZE); | ||
401 | if (unlikely(!skb)) { | ||
402 | dev->stats.rx_dropped++; | ||
403 | give_pages(rq, page); | ||
404 | return; | ||
405 | } | ||
406 | } | ||
407 | 447 | ||
408 | hdr = skb_vnet_hdr(skb); | 448 | hdr = skb_vnet_hdr(skb); |
409 | 449 | ||
@@ -1084,7 +1124,7 @@ static void virtnet_set_rx_mode(struct net_device *dev) | |||
1084 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, | 1124 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, |
1085 | VIRTIO_NET_CTRL_MAC_TABLE_SET, | 1125 | VIRTIO_NET_CTRL_MAC_TABLE_SET, |
1086 | sg, NULL)) | 1126 | sg, NULL)) |
1087 | dev_warn(&dev->dev, "Failed to set MAC fitler table.\n"); | 1127 | dev_warn(&dev->dev, "Failed to set MAC filter table.\n"); |
1088 | 1128 | ||
1089 | kfree(buf); | 1129 | kfree(buf); |
1090 | } | 1130 | } |