| .. | .. |
|---|
| 70 | 70 | wake_up(&queue->dealloc_wq); |
|---|
| 71 | 71 | } |
|---|
| 72 | 72 | |
|---|
| 73 | | -int xenvif_schedulable(struct xenvif *vif) |
|---|
| 73 | +static int xenvif_schedulable(struct xenvif *vif) |
|---|
| 74 | 74 | { |
|---|
| 75 | 75 | return netif_running(vif->dev) && |
|---|
| 76 | 76 | test_bit(VIF_STATUS_CONNECTED, &vif->status) && |
|---|
| .. | .. |
|---|
| 178 | 178 | return IRQ_HANDLED; |
|---|
| 179 | 179 | } |
|---|
| 180 | 180 | |
|---|
| 181 | | -int xenvif_queue_stopped(struct xenvif_queue *queue) |
|---|
| 182 | | -{ |
|---|
| 183 | | - struct net_device *dev = queue->vif->dev; |
|---|
| 184 | | - unsigned int id = queue->id; |
|---|
| 185 | | - return netif_tx_queue_stopped(netdev_get_tx_queue(dev, id)); |
|---|
| 186 | | -} |
|---|
| 187 | | - |
|---|
| 188 | | -void xenvif_wake_queue(struct xenvif_queue *queue) |
|---|
| 189 | | -{ |
|---|
| 190 | | - struct net_device *dev = queue->vif->dev; |
|---|
| 191 | | - unsigned int id = queue->id; |
|---|
| 192 | | - netif_tx_wake_queue(netdev_get_tx_queue(dev, id)); |
|---|
| 193 | | -} |
|---|
| 194 | | - |
|---|
| 195 | 181 | static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb, |
|---|
| 196 | | - struct net_device *sb_dev, |
|---|
| 197 | | - select_queue_fallback_t fallback) |
|---|
| 182 | + struct net_device *sb_dev) |
|---|
| 198 | 183 | { |
|---|
| 199 | 184 | struct xenvif *vif = netdev_priv(dev); |
|---|
| 200 | 185 | unsigned int size = vif->hash.size; |
|---|
| .. | .. |
|---|
| 207 | 192 | return 0; |
|---|
| 208 | 193 | |
|---|
| 209 | 194 | if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE) |
|---|
| 210 | | - return fallback(dev, skb, NULL) % dev->real_num_tx_queues; |
|---|
| 195 | + return netdev_pick_tx(dev, skb, NULL) % |
|---|
| 196 | + dev->real_num_tx_queues; |
|---|
| 211 | 197 | |
|---|
| 212 | 198 | xenvif_set_skb_hash(vif, skb); |
|---|
| 213 | 199 | |
|---|
| .. | .. |
|---|
| 269 | 255 | if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE) |
|---|
| 270 | 256 | skb_clear_hash(skb); |
|---|
| 271 | 257 | |
|---|
| 272 | | - xenvif_rx_queue_tail(queue, skb); |
|---|
| 258 | + if (!xenvif_rx_queue_tail(queue, skb)) |
|---|
| 259 | + goto drop; |
|---|
| 260 | + |
|---|
| 273 | 261 | xenvif_kick_thread(queue); |
|---|
| 274 | 262 | |
|---|
| 275 | 263 | return NETDEV_TX_OK; |
|---|
| 276 | 264 | |
|---|
| 277 | 265 | drop: |
|---|
| 278 | 266 | vif->dev->stats.tx_dropped++; |
|---|
| 279 | | - dev_kfree_skb(skb); |
|---|
| 267 | + dev_kfree_skb_any(skb); |
|---|
| 280 | 268 | return NETDEV_TX_OK; |
|---|
| 281 | 269 | } |
|---|
| 282 | 270 | |
|---|
| .. | .. |
|---|
| 528 | 516 | vif->queues = NULL; |
|---|
| 529 | 517 | vif->num_queues = 0; |
|---|
| 530 | 518 | |
|---|
| 519 | + vif->xdp_headroom = 0; |
|---|
| 520 | + |
|---|
| 531 | 521 | spin_lock_init(&vif->lock); |
|---|
| 532 | 522 | INIT_LIST_HEAD(&vif->fe_mcast_addr); |
|---|
| 533 | 523 | |
|---|
| .. | .. |
|---|
| 630 | 620 | struct net_device *dev = vif->dev; |
|---|
| 631 | 621 | void *addr; |
|---|
| 632 | 622 | struct xen_netif_ctrl_sring *shared; |
|---|
| 623 | + RING_IDX rsp_prod, req_prod; |
|---|
| 633 | 624 | int err; |
|---|
| 634 | 625 | |
|---|
| 635 | 626 | err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif), |
|---|
| .. | .. |
|---|
| 638 | 629 | goto err; |
|---|
| 639 | 630 | |
|---|
| 640 | 631 | shared = (struct xen_netif_ctrl_sring *)addr; |
|---|
| 641 | | - BACK_RING_INIT(&vif->ctrl, shared, XEN_PAGE_SIZE); |
|---|
| 632 | + rsp_prod = READ_ONCE(shared->rsp_prod); |
|---|
| 633 | + req_prod = READ_ONCE(shared->req_prod); |
|---|
| 634 | + |
|---|
| 635 | + BACK_RING_ATTACH(&vif->ctrl, shared, rsp_prod, XEN_PAGE_SIZE); |
|---|
| 636 | + |
|---|
| 637 | + err = -EIO; |
|---|
| 638 | + if (req_prod - rsp_prod > RING_SIZE(&vif->ctrl)) |
|---|
| 639 | + goto err_unmap; |
|---|
| 642 | 640 | |
|---|
| 643 | 641 | err = bind_interdomain_evtchn_to_irq_lateeoi(vif->domid, evtchn); |
|---|
| 644 | 642 | if (err < 0) |
|---|
| .. | .. |
|---|
| 671 | 669 | return err; |
|---|
| 672 | 670 | } |
|---|
| 673 | 671 | |
|---|
| 672 | +static void xenvif_disconnect_queue(struct xenvif_queue *queue) |
|---|
| 673 | +{ |
|---|
| 674 | + if (queue->task) { |
|---|
| 675 | + kthread_stop(queue->task); |
|---|
| 676 | + put_task_struct(queue->task); |
|---|
| 677 | + queue->task = NULL; |
|---|
| 678 | + } |
|---|
| 679 | + |
|---|
| 680 | + if (queue->dealloc_task) { |
|---|
| 681 | + kthread_stop(queue->dealloc_task); |
|---|
| 682 | + queue->dealloc_task = NULL; |
|---|
| 683 | + } |
|---|
| 684 | + |
|---|
| 685 | + if (queue->napi.poll) { |
|---|
| 686 | + netif_napi_del(&queue->napi); |
|---|
| 687 | + queue->napi.poll = NULL; |
|---|
| 688 | + } |
|---|
| 689 | + |
|---|
| 690 | + if (queue->tx_irq) { |
|---|
| 691 | + unbind_from_irqhandler(queue->tx_irq, queue); |
|---|
| 692 | + if (queue->tx_irq == queue->rx_irq) |
|---|
| 693 | + queue->rx_irq = 0; |
|---|
| 694 | + queue->tx_irq = 0; |
|---|
| 695 | + } |
|---|
| 696 | + |
|---|
| 697 | + if (queue->rx_irq) { |
|---|
| 698 | + unbind_from_irqhandler(queue->rx_irq, queue); |
|---|
| 699 | + queue->rx_irq = 0; |
|---|
| 700 | + } |
|---|
| 701 | + |
|---|
| 702 | + xenvif_unmap_frontend_data_rings(queue); |
|---|
| 703 | +} |
|---|
| 704 | + |
|---|
| 674 | 705 | int xenvif_connect_data(struct xenvif_queue *queue, |
|---|
| 675 | 706 | unsigned long tx_ring_ref, |
|---|
| 676 | 707 | unsigned long rx_ring_ref, |
|---|
| .. | .. |
|---|
| 678 | 709 | unsigned int rx_evtchn) |
|---|
| 679 | 710 | { |
|---|
| 680 | 711 | struct task_struct *task; |
|---|
| 681 | | - int err = -ENOMEM; |
|---|
| 712 | + int err; |
|---|
| 682 | 713 | |
|---|
| 683 | 714 | BUG_ON(queue->tx_irq); |
|---|
| 684 | 715 | BUG_ON(queue->task); |
|---|
| .. | .. |
|---|
| 696 | 727 | netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll, |
|---|
| 697 | 728 | XENVIF_NAPI_WEIGHT); |
|---|
| 698 | 729 | |
|---|
| 730 | + queue->stalled = true; |
|---|
| 731 | + |
|---|
| 732 | + task = kthread_run(xenvif_kthread_guest_rx, queue, |
|---|
| 733 | + "%s-guest-rx", queue->name); |
|---|
| 734 | + if (IS_ERR(task)) |
|---|
| 735 | + goto kthread_err; |
|---|
| 736 | + queue->task = task; |
|---|
| 737 | + /* |
|---|
| 738 | + * Take a reference to the task in order to prevent it from being freed |
|---|
| 739 | + * if the thread function returns before kthread_stop is called. |
|---|
| 740 | + */ |
|---|
| 741 | + get_task_struct(task); |
|---|
| 742 | + |
|---|
| 743 | + task = kthread_run(xenvif_dealloc_kthread, queue, |
|---|
| 744 | + "%s-dealloc", queue->name); |
|---|
| 745 | + if (IS_ERR(task)) |
|---|
| 746 | + goto kthread_err; |
|---|
| 747 | + queue->dealloc_task = task; |
|---|
| 748 | + |
|---|
| 699 | 749 | if (tx_evtchn == rx_evtchn) { |
|---|
| 700 | 750 | /* feature-split-event-channels == 0 */ |
|---|
| 701 | 751 | err = bind_interdomain_evtchn_to_irqhandler_lateeoi( |
|---|
| 702 | 752 | queue->vif->domid, tx_evtchn, xenvif_interrupt, 0, |
|---|
| 703 | 753 | queue->name, queue); |
|---|
| 704 | 754 | if (err < 0) |
|---|
| 705 | | - goto err_unmap; |
|---|
| 755 | + goto err; |
|---|
| 706 | 756 | queue->tx_irq = queue->rx_irq = err; |
|---|
| 707 | 757 | disable_irq(queue->tx_irq); |
|---|
| 708 | 758 | } else { |
|---|
| .. | .. |
|---|
| 713 | 763 | queue->vif->domid, tx_evtchn, xenvif_tx_interrupt, 0, |
|---|
| 714 | 764 | queue->tx_irq_name, queue); |
|---|
| 715 | 765 | if (err < 0) |
|---|
| 716 | | - goto err_unmap; |
|---|
| 766 | + goto err; |
|---|
| 717 | 767 | queue->tx_irq = err; |
|---|
| 718 | 768 | disable_irq(queue->tx_irq); |
|---|
| 719 | 769 | |
|---|
| .. | .. |
|---|
| 723 | 773 | queue->vif->domid, rx_evtchn, xenvif_rx_interrupt, 0, |
|---|
| 724 | 774 | queue->rx_irq_name, queue); |
|---|
| 725 | 775 | if (err < 0) |
|---|
| 726 | | - goto err_tx_unbind; |
|---|
| 776 | + goto err; |
|---|
| 727 | 777 | queue->rx_irq = err; |
|---|
| 728 | 778 | disable_irq(queue->rx_irq); |
|---|
| 729 | 779 | } |
|---|
| 730 | 780 | |
|---|
| 731 | | - queue->stalled = true; |
|---|
| 732 | | - |
|---|
| 733 | | - task = kthread_create(xenvif_kthread_guest_rx, |
|---|
| 734 | | - (void *)queue, "%s-guest-rx", queue->name); |
|---|
| 735 | | - if (IS_ERR(task)) { |
|---|
| 736 | | - pr_warn("Could not allocate kthread for %s\n", queue->name); |
|---|
| 737 | | - err = PTR_ERR(task); |
|---|
| 738 | | - goto err_rx_unbind; |
|---|
| 739 | | - } |
|---|
| 740 | | - queue->task = task; |
|---|
| 741 | | - get_task_struct(task); |
|---|
| 742 | | - |
|---|
| 743 | | - task = kthread_create(xenvif_dealloc_kthread, |
|---|
| 744 | | - (void *)queue, "%s-dealloc", queue->name); |
|---|
| 745 | | - if (IS_ERR(task)) { |
|---|
| 746 | | - pr_warn("Could not allocate kthread for %s\n", queue->name); |
|---|
| 747 | | - err = PTR_ERR(task); |
|---|
| 748 | | - goto err_rx_unbind; |
|---|
| 749 | | - } |
|---|
| 750 | | - queue->dealloc_task = task; |
|---|
| 751 | | - |
|---|
| 752 | | - wake_up_process(queue->task); |
|---|
| 753 | | - wake_up_process(queue->dealloc_task); |
|---|
| 754 | | - |
|---|
| 755 | 781 | return 0; |
|---|
| 756 | 782 | |
|---|
| 757 | | -err_rx_unbind: |
|---|
| 758 | | - unbind_from_irqhandler(queue->rx_irq, queue); |
|---|
| 759 | | - queue->rx_irq = 0; |
|---|
| 760 | | -err_tx_unbind: |
|---|
| 761 | | - unbind_from_irqhandler(queue->tx_irq, queue); |
|---|
| 762 | | - queue->tx_irq = 0; |
|---|
| 763 | | -err_unmap: |
|---|
| 764 | | - xenvif_unmap_frontend_data_rings(queue); |
|---|
| 765 | | - netif_napi_del(&queue->napi); |
|---|
| 783 | +kthread_err: |
|---|
| 784 | + pr_warn("Could not allocate kthread for %s\n", queue->name); |
|---|
| 785 | + err = PTR_ERR(task); |
|---|
| 766 | 786 | err: |
|---|
| 787 | + xenvif_disconnect_queue(queue); |
|---|
| 767 | 788 | return err; |
|---|
| 768 | 789 | } |
|---|
| 769 | 790 | |
|---|
| .. | .. |
|---|
| 791 | 812 | for (queue_index = 0; queue_index < num_queues; ++queue_index) { |
|---|
| 792 | 813 | queue = &vif->queues[queue_index]; |
|---|
| 793 | 814 | |
|---|
| 794 | | - netif_napi_del(&queue->napi); |
|---|
| 795 | | - |
|---|
| 796 | | - if (queue->task) { |
|---|
| 797 | | - kthread_stop(queue->task); |
|---|
| 798 | | - put_task_struct(queue->task); |
|---|
| 799 | | - queue->task = NULL; |
|---|
| 800 | | - } |
|---|
| 801 | | - |
|---|
| 802 | | - if (queue->dealloc_task) { |
|---|
| 803 | | - kthread_stop(queue->dealloc_task); |
|---|
| 804 | | - queue->dealloc_task = NULL; |
|---|
| 805 | | - } |
|---|
| 806 | | - |
|---|
| 807 | | - if (queue->tx_irq) { |
|---|
| 808 | | - if (queue->tx_irq == queue->rx_irq) |
|---|
| 809 | | - unbind_from_irqhandler(queue->tx_irq, queue); |
|---|
| 810 | | - else { |
|---|
| 811 | | - unbind_from_irqhandler(queue->tx_irq, queue); |
|---|
| 812 | | - unbind_from_irqhandler(queue->rx_irq, queue); |
|---|
| 813 | | - } |
|---|
| 814 | | - queue->tx_irq = 0; |
|---|
| 815 | | - } |
|---|
| 816 | | - |
|---|
| 817 | | - xenvif_unmap_frontend_data_rings(queue); |
|---|
| 815 | + xenvif_disconnect_queue(queue); |
|---|
| 818 | 816 | } |
|---|
| 819 | 817 | |
|---|
| 820 | 818 | xenvif_mcast_addr_list_free(vif); |
|---|