From f51de24356e49e4dcb5095e87717065580912120 Mon Sep 17 00:00:00 2001 From: Zoltan Kiss Date: Tue, 8 Jul 2014 19:49:14 +0100 Subject: xen-netback: Adding debugfs "io_ring_qX" files This patch adds debugfs capabilities to netback. There used to be a similar patch floating around for classic kernel, but it used procfs. It is based on a very similar blkback patch. It creates xen-netback/[vifname]/io_ring_q[queueno] files, reading them output various ring variables etc. Writing "kick" into it imitates an interrupt happened, it can be useful to check whether the ring is just stalled due to a missed interrupt. Signed-off-by: Zoltan Kiss Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: xen-devel@lists.xenproject.org Signed-off-by: David S. Miller --- drivers/net/xen-netback/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/xen-netback/interface.c') diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 9e97c7ca0ddd..ef75b45e5085 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -102,7 +102,7 @@ static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t xenvif_interrupt(int irq, void *dev_id) +irqreturn_t xenvif_interrupt(int irq, void *dev_id) { xenvif_tx_interrupt(irq, dev_id); xenvif_rx_interrupt(irq, dev_id); -- cgit From c835a677331495cf137a7f8a023463afd9f032f8 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Mon, 14 Jul 2014 16:37:24 +0200 Subject: net: set name_assign_type in alloc_netdev() Extend alloc_netdev{,_mq{,s}}() to take name_assign_type as argument, and convert all users to pass NET_NAME_UNKNOWN. Coccinelle patch: @@ expression sizeof_priv, name, setup, txqs, rxqs, count; @@ ( -alloc_netdev_mqs(sizeof_priv, name, setup, txqs, rxqs) +alloc_netdev_mqs(sizeof_priv, name, NET_NAME_UNKNOWN, setup, txqs, rxqs) | -alloc_netdev_mq(sizeof_priv, name, setup, count) +alloc_netdev_mq(sizeof_priv, name, NET_NAME_UNKNOWN, setup, count) | -alloc_netdev(sizeof_priv, name, setup) +alloc_netdev(sizeof_priv, name, NET_NAME_UNKNOWN, setup) ) v9: move comments here from the wrong commit Signed-off-by: Tom Gundersen Reviewed-by: David Herrmann Signed-off-by: David S. Miller --- drivers/net/xen-netback/interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/xen-netback/interface.c') diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index ef75b45e5085..bd59d9dbf27b 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -418,8 +418,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, * When the guest selects the desired number, it will be updated * via netif_set_real_num_*_queues(). */ - dev = alloc_netdev_mq(sizeof(struct xenvif), name, ether_setup, - xenvif_max_queues); + dev = alloc_netdev_mq(sizeof(struct xenvif), name, NET_NAME_UNKNOWN, + ether_setup, xenvif_max_queues); if (dev == NULL) { pr_warn("Could not allocate netdev for %s\n", name); return ERR_PTR(-ENOMEM); -- cgit From 3d1af1df9762e56e563e8fd088a1b4ce2bcfaf8b Mon Sep 17 00:00:00 2001 From: Zoltan Kiss Date: Mon, 4 Aug 2014 16:20:57 +0100 Subject: xen-netback: Using a new state bit instead of carrier This patch introduces a new state bit VIF_STATUS_CONNECTED to track whether the vif is in a connected state. Using carrier will not work with the next patch in this series, which aims to turn the carrier temporarily off if the guest doesn't seem to be able to receive packets. Signed-off-by: Zoltan Kiss Signed-off-by: David Vrabel Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: xen-devel@lists.xenproject.org v2: - rename the bitshift type to "enum state_bit_shift" here, not in the next patch Signed-off-by: David S. Miller --- drivers/net/xen-netback/interface.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/net/xen-netback/interface.c') diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index bd59d9dbf27b..fbdadb3d8220 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -55,7 +55,8 @@ static inline void xenvif_stop_queue(struct xenvif_queue *queue) int xenvif_schedulable(struct xenvif *vif) { - return netif_running(vif->dev) && netif_carrier_ok(vif->dev); + return netif_running(vif->dev) && + test_bit(VIF_STATUS_CONNECTED, &vif->status); } static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id) @@ -267,7 +268,7 @@ static void xenvif_down(struct xenvif *vif) static int xenvif_open(struct net_device *dev) { struct xenvif *vif = netdev_priv(dev); - if (netif_carrier_ok(dev)) + if (test_bit(VIF_STATUS_CONNECTED, &vif->status)) xenvif_up(vif); netif_tx_start_all_queues(dev); return 0; @@ -276,7 +277,7 @@ static int xenvif_open(struct net_device *dev) static int xenvif_close(struct net_device *dev) { struct xenvif *vif = netdev_priv(dev); - if (netif_carrier_ok(dev)) + if (test_bit(VIF_STATUS_CONNECTED, &vif->status)) xenvif_down(vif); netif_tx_stop_all_queues(dev); return 0; @@ -528,6 +529,7 @@ void xenvif_carrier_on(struct xenvif *vif) if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN) dev_set_mtu(vif->dev, ETH_DATA_LEN); netdev_update_features(vif->dev); + set_bit(VIF_STATUS_CONNECTED, &vif->status); netif_carrier_on(vif->dev); if (netif_running(vif->dev)) xenvif_up(vif); @@ -625,9 +627,11 @@ void xenvif_carrier_off(struct xenvif *vif) struct net_device *dev = vif->dev; rtnl_lock(); - netif_carrier_off(dev); /* discard queued packets */ - if (netif_running(dev)) - xenvif_down(vif); + if (test_and_clear_bit(VIF_STATUS_CONNECTED, &vif->status)) { + netif_carrier_off(dev); /* discard queued packets */ + if (netif_running(dev)) + xenvif_down(vif); + } rtnl_unlock(); } @@ -656,8 +660,7 @@ void xenvif_disconnect(struct xenvif *vif) unsigned int num_queues = vif->num_queues; unsigned int queue_index; - if (netif_carrier_ok(vif->dev)) - xenvif_carrier_off(vif); + xenvif_carrier_off(vif); for (queue_index = 0; queue_index < num_queues; ++queue_index) { queue = &vif->queues[queue_index]; -- cgit From f34a4cf9c9b4fd35ba7f9a596cedb011879a1a4d Mon Sep 17 00:00:00 2001 From: Zoltan Kiss Date: Mon, 4 Aug 2014 16:20:58 +0100 Subject: xen-netback: Turn off the carrier if the guest is not able to receive Currently when the guest is not able to receive more packets, qdisc layer starts a timer, and when it goes off, qdisc is started again to deliver a packet again. This is a very slow way to drain the queues, consumes unnecessary resources and slows down other guests shutdown. This patch change the behaviour by turning the carrier off when that timer fires, so all the packets are freed up which were stucked waiting for that vif. Instead of the rx_queue_purge bool it uses the VIF_STATUS_RX_PURGE_EVENT bit to signal the thread that either the timeout happened or an RX interrupt arrived, so the thread can check what it should do. It also disables NAPI, so the guest can't transmit, but leaves the interrupts on, so it can resurrect. Only the queues which brought down the interface can enable it again, the bit QUEUE_STATUS_RX_STALLED makes sure of that. Signed-off-by: Zoltan Kiss Signed-off-by: David Vrabel Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: xen-devel@lists.xenproject.org Signed-off-by: David S. Miller --- drivers/net/xen-netback/interface.c | 49 +++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 21 deletions(-) (limited to 'drivers/net/xen-netback/interface.c') diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index fbdadb3d8220..48a55cda979b 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -78,8 +78,12 @@ int xenvif_poll(struct napi_struct *napi, int budget) /* This vif is rogue, we pretend we've there is nothing to do * for this vif to deschedule it from NAPI. But this interface * will be turned off in thread context later. + * Also, if a guest doesn't post enough slots to receive data on one of + * its queues, the carrier goes down and NAPI is descheduled here so + * the guest can't send more packets until it's ready to receive. */ - if (unlikely(queue->vif->disabled)) { + if (unlikely(queue->vif->disabled || + !netif_carrier_ok(queue->vif->dev))) { napi_complete(napi); return 0; } @@ -97,7 +101,16 @@ int xenvif_poll(struct napi_struct *napi, int budget) static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id) { struct xenvif_queue *queue = dev_id; + struct netdev_queue *net_queue = + netdev_get_tx_queue(queue->vif->dev, queue->id); + /* QUEUE_STATUS_RX_PURGE_EVENT is only set if either QDisc was off OR + * the carrier went down and this queue was previously blocked + */ + if (unlikely(netif_tx_queue_stopped(net_queue) || + (!netif_carrier_ok(queue->vif->dev) && + test_bit(QUEUE_STATUS_RX_STALLED, &queue->status)))) + set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status); xenvif_kick_thread(queue); return IRQ_HANDLED; @@ -125,16 +138,14 @@ void xenvif_wake_queue(struct xenvif_queue *queue) netif_tx_wake_queue(netdev_get_tx_queue(dev, id)); } -/* Callback to wake the queue and drain it on timeout */ -static void xenvif_wake_queue_callback(unsigned long data) +/* Callback to wake the queue's thread and turn the carrier off on timeout */ +static void xenvif_rx_stalled(unsigned long data) { struct xenvif_queue *queue = (struct xenvif_queue *)data; if (xenvif_queue_stopped(queue)) { - netdev_err(queue->vif->dev, "draining TX queue\n"); - queue->rx_queue_purge = true; + set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status); xenvif_kick_thread(queue); - xenvif_wake_queue(queue); } } @@ -183,11 +194,11 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev) * drain. */ if (!xenvif_rx_ring_slots_available(queue, min_slots_needed)) { - queue->wake_queue.function = xenvif_wake_queue_callback; - queue->wake_queue.data = (unsigned long)queue; + queue->rx_stalled.function = xenvif_rx_stalled; + queue->rx_stalled.data = (unsigned long)queue; xenvif_stop_queue(queue); - mod_timer(&queue->wake_queue, - jiffies + rx_drain_timeout_jiffies); + mod_timer(&queue->rx_stalled, + jiffies + rx_drain_timeout_jiffies); } skb_queue_tail(&queue->rx_queue, skb); @@ -515,7 +526,7 @@ int xenvif_init_queue(struct xenvif_queue *queue) queue->grant_tx_handle[i] = NETBACK_INVALID_HANDLE; } - init_timer(&queue->wake_queue); + init_timer(&queue->rx_stalled); netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll, XENVIF_NAPI_WEIGHT); @@ -666,7 +677,7 @@ void xenvif_disconnect(struct xenvif *vif) queue = &vif->queues[queue_index]; if (queue->task) { - del_timer_sync(&queue->wake_queue); + del_timer_sync(&queue->rx_stalled); kthread_stop(queue->task); queue->task = NULL; } @@ -708,16 +719,12 @@ void xenvif_free(struct xenvif *vif) /* Here we want to avoid timeout messages if an skb can be legitimately * stuck somewhere else. Realistically this could be an another vif's * internal or QDisc queue. That another vif also has this - * rx_drain_timeout_msecs timeout, but the timer only ditches the - * internal queue. After that, the QDisc queue can put in worst case - * XEN_NETIF_RX_RING_SIZE / MAX_SKB_FRAGS skbs into that another vif's - * internal queue, so we need several rounds of such timeouts until we - * can be sure that no another vif should have skb's from us. We are - * not sending more skb's, so newly stuck packets are not interesting - * for us here. + * rx_drain_timeout_msecs timeout, so give it time to drain out. + * Although if that other guest wakes up just before its timeout happens + * and takes only one skb from QDisc, it can hold onto other skbs for a + * longer period. */ - unsigned int worst_case_skb_lifetime = (rx_drain_timeout_msecs/1000) * - DIV_ROUND_UP(XENVIF_QUEUE_LENGTH, (XEN_NETIF_RX_RING_SIZE / MAX_SKB_FRAGS)); + unsigned int worst_case_skb_lifetime = (rx_drain_timeout_msecs/1000); unregister_netdev(vif->dev); -- cgit From 2561cc15e3816e4323f9e79a6890bff94c0bbec2 Mon Sep 17 00:00:00 2001 From: Zoltan Kiss Date: Mon, 11 Aug 2014 13:01:44 +0100 Subject: xen-netback: Don't deschedule NAPI when carrier off In the patch called "xen-netback: Turn off the carrier if the guest is not able to receive" NAPI was descheduled when the carrier was set off. That's not what most of the drivers do, and we don't have any specific reason to do so as well, so revert that change. Signed-off-by: Zoltan Kiss Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: xen-devel@lists.xenproject.org Acked-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/xen-netback/interface.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/net/xen-netback/interface.c') diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 48a55cda979b..bfd10cb9c8de 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -78,12 +78,8 @@ int xenvif_poll(struct napi_struct *napi, int budget) /* This vif is rogue, we pretend we've there is nothing to do * for this vif to deschedule it from NAPI. But this interface * will be turned off in thread context later. - * Also, if a guest doesn't post enough slots to receive data on one of - * its queues, the carrier goes down and NAPI is descheduled here so - * the guest can't send more packets until it's ready to receive. */ - if (unlikely(queue->vif->disabled || - !netif_carrier_ok(queue->vif->dev))) { + if (unlikely(queue->vif->disabled)) { napi_complete(napi); return 0; } -- cgit From ea2c5e134237eadc9924ce821ded678750024549 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Tue, 12 Aug 2014 11:48:06 +0100 Subject: xen-netback: move NAPI add/remove calls Originally netif_napi_add was in xenvif_init_queue and netif_napi_del was in xenvif_deinit_queue, while kthreads were handled in xenvif_connect and xenvif_disconnect. Move netif_napi_add and netif_napi_del to xenvif_connect and xenvif_disconnect so that they reside together with kthread operations. Signed-off-by: Wei Liu Cc: Ian Campbell Cc: Zoltan Kiss Signed-off-by: David S. Miller --- drivers/net/xen-netback/interface.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net/xen-netback/interface.c') diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index bfd10cb9c8de..5f3d6c06fcf7 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -524,9 +524,6 @@ int xenvif_init_queue(struct xenvif_queue *queue) init_timer(&queue->rx_stalled); - netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll, - XENVIF_NAPI_WEIGHT); - return 0; } @@ -614,6 +611,9 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref, wake_up_process(queue->task); wake_up_process(queue->dealloc_task); + netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll, + XENVIF_NAPI_WEIGHT); + return 0; err_rx_unbind: @@ -672,6 +672,8 @@ void xenvif_disconnect(struct xenvif *vif) for (queue_index = 0; queue_index < num_queues; ++queue_index) { queue = &vif->queues[queue_index]; + netif_napi_del(&queue->napi); + if (queue->task) { del_timer_sync(&queue->rx_stalled); kthread_stop(queue->task); @@ -704,7 +706,6 @@ void xenvif_disconnect(struct xenvif *vif) void xenvif_deinit_queue(struct xenvif_queue *queue) { free_xenballooned_pages(MAX_PENDING_REQS, queue->mmap_pages); - netif_napi_del(&queue->napi); } void xenvif_free(struct xenvif *vif) -- cgit From a64bd934528e26e8956112e43a279fba2ee0634e Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Tue, 12 Aug 2014 11:48:07 +0100 Subject: xen-netback: don't stop dealloc kthread too early Reference count the number of packets in host stack, so that we don't stop the deallocation thread too early. If not, we can end up with xenvif_free permanently waiting for deallocation thread to unmap grefs. Reported-by: Thomas Leonard Signed-off-by: Wei Liu Cc: Ian Campbell Cc: Zoltan Kiss Signed-off-by: David S. Miller --- drivers/net/xen-netback/interface.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/net/xen-netback/interface.c') diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 5f3d6c06fcf7..0aaca902699a 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -43,6 +43,23 @@ #define XENVIF_QUEUE_LENGTH 32 #define XENVIF_NAPI_WEIGHT 64 +/* This function is used to set SKBTX_DEV_ZEROCOPY as well as + * increasing the inflight counter. We need to increase the inflight + * counter because core driver calls into xenvif_zerocopy_callback + * which calls xenvif_skb_zerocopy_complete. + */ +void xenvif_skb_zerocopy_prepare(struct xenvif_queue *queue, + struct sk_buff *skb) +{ + skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + atomic_inc(&queue->inflight_packets); +} + +void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue) +{ + atomic_dec(&queue->inflight_packets); +} + static inline void xenvif_stop_queue(struct xenvif_queue *queue) { struct net_device *dev = queue->vif->dev; @@ -557,6 +574,7 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref, init_waitqueue_head(&queue->wq); init_waitqueue_head(&queue->dealloc_wq); + atomic_set(&queue->inflight_packets, 0); if (tx_evtchn == rx_evtchn) { /* feature-split-event-channels == 0 */ -- cgit From b1252858213f39700dac1bc3295b6e88f6cce24b Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Tue, 12 Aug 2014 11:48:08 +0100 Subject: xen-netback: remove loop waiting function The original implementation relies on a loop to check if all inflight packets are freed. Now we have proper reference counting, there's no need to use loop anymore. Signed-off-by: Wei Liu Cc: Ian Campbell Cc: Zoltan Kiss Signed-off-by: David S. Miller --- drivers/net/xen-netback/interface.c | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'drivers/net/xen-netback/interface.c') diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 0aaca902699a..e29e15dca86e 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -660,25 +660,6 @@ void xenvif_carrier_off(struct xenvif *vif) rtnl_unlock(); } -static void xenvif_wait_unmap_timeout(struct xenvif_queue *queue, - unsigned int worst_case_skb_lifetime) -{ - int i, unmap_timeout = 0; - - for (i = 0; i < MAX_PENDING_REQS; ++i) { - if (queue->grant_tx_handle[i] != NETBACK_INVALID_HANDLE) { - unmap_timeout++; - schedule_timeout(msecs_to_jiffies(1000)); - if (unmap_timeout > worst_case_skb_lifetime && - net_ratelimit()) - netdev_err(queue->vif->dev, - "Page still granted! Index: %x\n", - i); - i = -1; - } - } -} - void xenvif_disconnect(struct xenvif *vif) { struct xenvif_queue *queue = NULL; @@ -731,21 +712,11 @@ void xenvif_free(struct xenvif *vif) struct xenvif_queue *queue = NULL; unsigned int num_queues = vif->num_queues; unsigned int queue_index; - /* Here we want to avoid timeout messages if an skb can be legitimately - * stuck somewhere else. Realistically this could be an another vif's - * internal or QDisc queue. That another vif also has this - * rx_drain_timeout_msecs timeout, so give it time to drain out. - * Although if that other guest wakes up just before its timeout happens - * and takes only one skb from QDisc, it can hold onto other skbs for a - * longer period. - */ - unsigned int worst_case_skb_lifetime = (rx_drain_timeout_msecs/1000); unregister_netdev(vif->dev); for (queue_index = 0; queue_index < num_queues; ++queue_index) { queue = &vif->queues[queue_index]; - xenvif_wait_unmap_timeout(queue, worst_case_skb_lifetime); xenvif_deinit_queue(queue); } -- cgit