diff options
Diffstat (limited to 'drivers/net/xen-netback/interface.c')
| -rw-r--r-- | drivers/net/xen-netback/interface.c | 56 |
1 files changed, 23 insertions, 33 deletions
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index bfd10cb9c8de..e29e15dca86e 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c | |||
| @@ -43,6 +43,23 @@ | |||
| 43 | #define XENVIF_QUEUE_LENGTH 32 | 43 | #define XENVIF_QUEUE_LENGTH 32 |
| 44 | #define XENVIF_NAPI_WEIGHT 64 | 44 | #define XENVIF_NAPI_WEIGHT 64 |
| 45 | 45 | ||
| 46 | /* This function is used to set SKBTX_DEV_ZEROCOPY as well as | ||
| 47 | * increasing the inflight counter. We need to increase the inflight | ||
| 48 | * counter because core driver calls into xenvif_zerocopy_callback | ||
| 49 | * which calls xenvif_skb_zerocopy_complete. | ||
| 50 | */ | ||
| 51 | void xenvif_skb_zerocopy_prepare(struct xenvif_queue *queue, | ||
| 52 | struct sk_buff *skb) | ||
| 53 | { | ||
| 54 | skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; | ||
| 55 | atomic_inc(&queue->inflight_packets); | ||
| 56 | } | ||
| 57 | |||
| 58 | void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue) | ||
| 59 | { | ||
| 60 | atomic_dec(&queue->inflight_packets); | ||
| 61 | } | ||
| 62 | |||
| 46 | static inline void xenvif_stop_queue(struct xenvif_queue *queue) | 63 | static inline void xenvif_stop_queue(struct xenvif_queue *queue) |
| 47 | { | 64 | { |
| 48 | struct net_device *dev = queue->vif->dev; | 65 | struct net_device *dev = queue->vif->dev; |
| @@ -524,9 +541,6 @@ int xenvif_init_queue(struct xenvif_queue *queue) | |||
| 524 | 541 | ||
| 525 | init_timer(&queue->rx_stalled); | 542 | init_timer(&queue->rx_stalled); |
| 526 | 543 | ||
| 527 | netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll, | ||
| 528 | XENVIF_NAPI_WEIGHT); | ||
| 529 | |||
| 530 | return 0; | 544 | return 0; |
| 531 | } | 545 | } |
| 532 | 546 | ||
| @@ -560,6 +574,7 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref, | |||
| 560 | 574 | ||
| 561 | init_waitqueue_head(&queue->wq); | 575 | init_waitqueue_head(&queue->wq); |
| 562 | init_waitqueue_head(&queue->dealloc_wq); | 576 | init_waitqueue_head(&queue->dealloc_wq); |
| 577 | atomic_set(&queue->inflight_packets, 0); | ||
| 563 | 578 | ||
| 564 | if (tx_evtchn == rx_evtchn) { | 579 | if (tx_evtchn == rx_evtchn) { |
| 565 | /* feature-split-event-channels == 0 */ | 580 | /* feature-split-event-channels == 0 */ |
| @@ -614,6 +629,9 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref, | |||
| 614 | wake_up_process(queue->task); | 629 | wake_up_process(queue->task); |
| 615 | wake_up_process(queue->dealloc_task); | 630 | wake_up_process(queue->dealloc_task); |
| 616 | 631 | ||
| 632 | netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll, | ||
| 633 | XENVIF_NAPI_WEIGHT); | ||
| 634 | |||
| 617 | return 0; | 635 | return 0; |
| 618 | 636 | ||
| 619 | err_rx_unbind: | 637 | err_rx_unbind: |
| @@ -642,25 +660,6 @@ void xenvif_carrier_off(struct xenvif *vif) | |||
| 642 | rtnl_unlock(); | 660 | rtnl_unlock(); |
| 643 | } | 661 | } |
| 644 | 662 | ||
| 645 | static void xenvif_wait_unmap_timeout(struct xenvif_queue *queue, | ||
| 646 | unsigned int worst_case_skb_lifetime) | ||
| 647 | { | ||
| 648 | int i, unmap_timeout = 0; | ||
| 649 | |||
| 650 | for (i = 0; i < MAX_PENDING_REQS; ++i) { | ||
| 651 | if (queue->grant_tx_handle[i] != NETBACK_INVALID_HANDLE) { | ||
| 652 | unmap_timeout++; | ||
| 653 | schedule_timeout(msecs_to_jiffies(1000)); | ||
| 654 | if (unmap_timeout > worst_case_skb_lifetime && | ||
| 655 | net_ratelimit()) | ||
| 656 | netdev_err(queue->vif->dev, | ||
| 657 | "Page still granted! Index: %x\n", | ||
| 658 | i); | ||
| 659 | i = -1; | ||
| 660 | } | ||
| 661 | } | ||
| 662 | } | ||
| 663 | |||
| 664 | void xenvif_disconnect(struct xenvif *vif) | 663 | void xenvif_disconnect(struct xenvif *vif) |
| 665 | { | 664 | { |
| 666 | struct xenvif_queue *queue = NULL; | 665 | struct xenvif_queue *queue = NULL; |
| @@ -672,6 +671,8 @@ void xenvif_disconnect(struct xenvif *vif) | |||
| 672 | for (queue_index = 0; queue_index < num_queues; ++queue_index) { | 671 | for (queue_index = 0; queue_index < num_queues; ++queue_index) { |
| 673 | queue = &vif->queues[queue_index]; | 672 | queue = &vif->queues[queue_index]; |
| 674 | 673 | ||
| 674 | netif_napi_del(&queue->napi); | ||
| 675 | |||
| 675 | if (queue->task) { | 676 | if (queue->task) { |
| 676 | del_timer_sync(&queue->rx_stalled); | 677 | del_timer_sync(&queue->rx_stalled); |
| 677 | kthread_stop(queue->task); | 678 | kthread_stop(queue->task); |
| @@ -704,7 +705,6 @@ void xenvif_disconnect(struct xenvif *vif) | |||
| 704 | void xenvif_deinit_queue(struct xenvif_queue *queue) | 705 | void xenvif_deinit_queue(struct xenvif_queue *queue) |
| 705 | { | 706 | { |
| 706 | free_xenballooned_pages(MAX_PENDING_REQS, queue->mmap_pages); | 707 | free_xenballooned_pages(MAX_PENDING_REQS, queue->mmap_pages); |
| 707 | netif_napi_del(&queue->napi); | ||
| 708 | } | 708 | } |
| 709 | 709 | ||
| 710 | void xenvif_free(struct xenvif *vif) | 710 | void xenvif_free(struct xenvif *vif) |
| @@ -712,21 +712,11 @@ void xenvif_free(struct xenvif *vif) | |||
| 712 | struct xenvif_queue *queue = NULL; | 712 | struct xenvif_queue *queue = NULL; |
| 713 | unsigned int num_queues = vif->num_queues; | 713 | unsigned int num_queues = vif->num_queues; |
| 714 | unsigned int queue_index; | 714 | unsigned int queue_index; |
| 715 | /* Here we want to avoid timeout messages if an skb can be legitimately | ||
| 716 | * stuck somewhere else. Realistically this could be an another vif's | ||
| 717 | * internal or QDisc queue. That another vif also has this | ||
| 718 | * rx_drain_timeout_msecs timeout, so give it time to drain out. | ||
| 719 | * Although if that other guest wakes up just before its timeout happens | ||
| 720 | * and takes only one skb from QDisc, it can hold onto other skbs for a | ||
| 721 | * longer period. | ||
| 722 | */ | ||
| 723 | unsigned int worst_case_skb_lifetime = (rx_drain_timeout_msecs/1000); | ||
| 724 | 715 | ||
| 725 | unregister_netdev(vif->dev); | 716 | unregister_netdev(vif->dev); |
| 726 | 717 | ||
| 727 | for (queue_index = 0; queue_index < num_queues; ++queue_index) { | 718 | for (queue_index = 0; queue_index < num_queues; ++queue_index) { |
| 728 | queue = &vif->queues[queue_index]; | 719 | queue = &vif->queues[queue_index]; |
| 729 | xenvif_wait_unmap_timeout(queue, worst_case_skb_lifetime); | ||
| 730 | xenvif_deinit_queue(queue); | 720 | xenvif_deinit_queue(queue); |
| 731 | } | 721 | } |
| 732 | 722 | ||
