diff options
Diffstat (limited to 'drivers/net/xen-netback')
-rw-r--r-- | drivers/net/xen-netback/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/xen-netback/common.h | 18 | ||||
-rw-r--r-- | drivers/net/xen-netback/interface.c | 123 | ||||
-rw-r--r-- | drivers/net/xen-netback/netback.c | 15 | ||||
-rw-r--r-- | drivers/net/xen-netback/xenbus.c | 77 |
5 files changed, 97 insertions, 137 deletions
diff --git a/drivers/net/xen-netback/Makefile b/drivers/net/xen-netback/Makefile index d49798a46b51..84e9cbc36359 100644 --- a/drivers/net/xen-netback/Makefile +++ b/drivers/net/xen-netback/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_XEN_NETDEV_BACKEND) := xen-netback.o xen-netback-y := netback.o xenbus.o interface.o hash.o rx.o diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 936c0b3e0ba2..05847eb91a1b 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -248,6 +248,22 @@ struct xenvif_hash { struct xenvif_hash_cache cache; }; +struct backend_info { + struct xenbus_device *dev; + struct xenvif *vif; + + /* This is the state that will be reflected in xenstore when any + * active hotplug script completes. + */ + enum xenbus_state state; + + enum xenbus_state frontend_state; + struct xenbus_watch hotplug_status_watch; + u8 have_hotplug_status_watch:1; + + const char *hotplug_script; +}; + struct xenvif { /* Unique identifier for this interface. */ domid_t domid; @@ -283,6 +299,8 @@ struct xenvif { struct xenbus_watch credit_watch; struct xenbus_watch mcast_ctrl_watch; + struct backend_info *be; + spinlock_t lock; #ifdef CONFIG_DEBUG_FS diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 6da12518e693..68dd7bb07ca6 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -148,8 +148,7 @@ void xenvif_wake_queue(struct xenvif_queue *queue) } static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb, - struct net_device *sb_dev, - select_queue_fallback_t fallback) + struct net_device *sb_dev) { struct xenvif *vif = netdev_priv(dev); unsigned int size = vif->hash.size; @@ -162,7 +161,8 @@ static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb, return 0; if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE) - return fallback(dev, skb, NULL) % dev->real_num_tx_queues; + return netdev_pick_tx(dev, skb, NULL) % + dev->real_num_tx_queues; xenvif_set_skb_hash(vif, skb); @@ -626,6 +626,38 @@ err: return err; } +static void xenvif_disconnect_queue(struct xenvif_queue *queue) +{ + if (queue->tx_irq) { + unbind_from_irqhandler(queue->tx_irq, queue); + if (queue->tx_irq == queue->rx_irq) + queue->rx_irq = 0; + queue->tx_irq = 0; + } + + if (queue->rx_irq) { + unbind_from_irqhandler(queue->rx_irq, queue); + queue->rx_irq = 0; + } + + if (queue->task) { + kthread_stop(queue->task); + queue->task = NULL; + } + + if (queue->dealloc_task) { + kthread_stop(queue->dealloc_task); + queue->dealloc_task = NULL; + } + + if (queue->napi.poll) { + netif_napi_del(&queue->napi); + queue->napi.poll = NULL; + } + + xenvif_unmap_frontend_data_rings(queue); +} + int xenvif_connect_data(struct xenvif_queue *queue, unsigned long tx_ring_ref, unsigned long rx_ring_ref, @@ -633,7 +665,7 @@ int xenvif_connect_data(struct xenvif_queue *queue, unsigned int rx_evtchn) { struct task_struct *task; - int err = -ENOMEM; + int err; BUG_ON(queue->tx_irq); BUG_ON(queue->task); @@ -651,13 +683,27 @@ int xenvif_connect_data(struct xenvif_queue *queue, netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll, XENVIF_NAPI_WEIGHT); + queue->stalled = true; + + task = kthread_run(xenvif_kthread_guest_rx, queue, + "%s-guest-rx", queue->name); + if (IS_ERR(task)) + goto kthread_err; + queue->task = task; + + task = kthread_run(xenvif_dealloc_kthread, queue, + "%s-dealloc", queue->name); + if (IS_ERR(task)) + goto kthread_err; + queue->dealloc_task = task; + if (tx_evtchn == rx_evtchn) { /* feature-split-event-channels == 0 */ err = bind_interdomain_evtchn_to_irqhandler( queue->vif->domid, tx_evtchn, xenvif_interrupt, 0, queue->name, queue); if (err < 0) - goto err_unmap; + goto err; queue->tx_irq = queue->rx_irq = err; disable_irq(queue->tx_irq); } else { @@ -668,7 +714,7 @@ int xenvif_connect_data(struct xenvif_queue *queue, queue->vif->domid, tx_evtchn, xenvif_tx_interrupt, 0, queue->tx_irq_name, queue); if (err < 0) - goto err_unmap; + goto err; queue->tx_irq = err; disable_irq(queue->tx_irq); @@ -678,48 +724,18 @@ int xenvif_connect_data(struct xenvif_queue *queue, queue->vif->domid, rx_evtchn, xenvif_rx_interrupt, 0, queue->rx_irq_name, queue); if (err < 0) - goto err_tx_unbind; + goto err; queue->rx_irq = err; disable_irq(queue->rx_irq); } - queue->stalled = true; - - task = kthread_create(xenvif_kthread_guest_rx, - (void *)queue, "%s-guest-rx", queue->name); - if (IS_ERR(task)) { - pr_warn("Could not allocate kthread for %s\n", queue->name); - err = PTR_ERR(task); - goto err_rx_unbind; - } - queue->task = task; - get_task_struct(task); - - task = kthread_create(xenvif_dealloc_kthread, - (void *)queue, "%s-dealloc", queue->name); - if (IS_ERR(task)) { - pr_warn("Could not allocate kthread for %s\n", queue->name); - err = PTR_ERR(task); - goto err_rx_unbind; - } - queue->dealloc_task = task; - - wake_up_process(queue->task); - wake_up_process(queue->dealloc_task); - return 0; -err_rx_unbind: - unbind_from_irqhandler(queue->rx_irq, queue); - queue->rx_irq = 0; -err_tx_unbind: - unbind_from_irqhandler(queue->tx_irq, queue); - queue->tx_irq = 0; -err_unmap: - xenvif_unmap_frontend_data_rings(queue); - netif_napi_del(&queue->napi); +kthread_err: + pr_warn("Could not allocate kthread for %s\n", queue->name); + err = PTR_ERR(task); err: - module_put(THIS_MODULE); + xenvif_disconnect_queue(queue); return err; } @@ -747,30 +763,7 @@ void xenvif_disconnect_data(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) { - kthread_stop(queue->task); - put_task_struct(queue->task); - queue->task = NULL; - } - - if (queue->dealloc_task) { - kthread_stop(queue->dealloc_task); - queue->dealloc_task = NULL; - } - - if (queue->tx_irq) { - if (queue->tx_irq == queue->rx_irq) - unbind_from_irqhandler(queue->tx_irq, queue); - else { - unbind_from_irqhandler(queue->tx_irq, queue); - unbind_from_irqhandler(queue->rx_irq, queue); - } - queue->tx_irq = 0; - } - - xenvif_unmap_frontend_data_rings(queue); + xenvif_disconnect_queue(queue); } xenvif_mcast_addr_list_free(vif); diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 1d9940d4e8c7..0020b2e8c279 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -136,12 +136,12 @@ static inline struct xenvif_queue *ubuf_to_queue(const struct ubuf_info *ubuf) static u16 frag_get_pending_idx(skb_frag_t *frag) { - return (u16)frag->page_offset; + return (u16)skb_frag_off(frag); } static void frag_set_pending_idx(skb_frag_t *frag, u16 pending_idx) { - frag->page_offset = pending_idx; + skb_frag_off_set(frag, pending_idx); } static inline pending_ring_idx_t pending_index(unsigned i) @@ -925,6 +925,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, skb_shinfo(skb)->nr_frags = MAX_SKB_FRAGS; nskb = xenvif_alloc_skb(0); if (unlikely(nskb == NULL)) { + skb_shinfo(skb)->nr_frags = 0; kfree_skb(skb); xenvif_tx_err(queue, &txreq, extra_count, idx); if (net_ratelimit()) @@ -940,6 +941,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, if (xenvif_set_skb_gso(queue->vif, skb, gso)) { /* Failure in xenvif_set_skb_gso is fatal. */ + skb_shinfo(skb)->nr_frags = 0; kfree_skb(skb); kfree_skb(nskb); break; @@ -1055,7 +1057,7 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s int j; skb->truesize += skb->data_len; for (j = 0; j < i; j++) - put_page(frags[j].page.p); + put_page(skb_frag_page(&frags[j])); return -ENOMEM; } @@ -1067,8 +1069,8 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s BUG(); offset += len; - frags[i].page.p = page; - frags[i].page_offset = 0; + __skb_frag_set_page(&frags[i], page); + skb_frag_off_set(&frags[i], 0); skb_frag_size_set(&frags[i], len); } @@ -1653,9 +1655,6 @@ static int __init netback_init(void) #ifdef CONFIG_DEBUG_FS xen_netback_dbg_root = debugfs_create_dir("xen-netback", NULL); - if (IS_ERR_OR_NULL(xen_netback_dbg_root)) - pr_warn("Init of debugfs returned %ld!\n", - PTR_ERR(xen_netback_dbg_root)); #endif /* CONFIG_DEBUG_FS */ return 0; diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 330ddb64930f..f533b7372d59 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -1,43 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Xenbus code for netif backend * * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au> * Copyright (C) 2005 XenSource Ltd - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. */ #include "common.h" #include <linux/vmalloc.h> #include <linux/rtnetlink.h> -struct backend_info { - struct xenbus_device *dev; - struct xenvif *vif; - - /* This is the state that will be reflected in xenstore when any - * active hotplug script completes. - */ - enum xenbus_state state; - - enum xenbus_state frontend_state; - struct xenbus_watch hotplug_status_watch; - u8 have_hotplug_status_watch:1; - - const char *hotplug_script; -}; - static int connect_data_rings(struct backend_info *be, struct xenvif_queue *queue); static void connect(struct backend_info *be); @@ -198,50 +170,26 @@ DEFINE_SHOW_ATTRIBUTE(xenvif_ctrl); static void xenvif_debugfs_addif(struct xenvif *vif) { - struct dentry *pfile; int i; - if (IS_ERR_OR_NULL(xen_netback_dbg_root)) - return; - vif->xenvif_dbg_root = debugfs_create_dir(vif->dev->name, xen_netback_dbg_root); - if (!IS_ERR_OR_NULL(vif->xenvif_dbg_root)) { - for (i = 0; i < vif->num_queues; ++i) { - char filename[sizeof("io_ring_q") + 4]; - - snprintf(filename, sizeof(filename), "io_ring_q%d", i); - pfile = debugfs_create_file(filename, - 0600, - vif->xenvif_dbg_root, - &vif->queues[i], - &xenvif_dbg_io_ring_ops_fops); - if (IS_ERR_OR_NULL(pfile)) - pr_warn("Creation of io_ring file returned %ld!\n", - PTR_ERR(pfile)); - } + for (i = 0; i < vif->num_queues; ++i) { + char filename[sizeof("io_ring_q") + 4]; - if (vif->ctrl_irq) { - pfile = debugfs_create_file("ctrl", - 0400, - vif->xenvif_dbg_root, - vif, - &xenvif_ctrl_fops); - if (IS_ERR_OR_NULL(pfile)) - pr_warn("Creation of ctrl file returned %ld!\n", - PTR_ERR(pfile)); - } - } else - netdev_warn(vif->dev, - "Creation of vif debugfs dir returned %ld!\n", - PTR_ERR(vif->xenvif_dbg_root)); + snprintf(filename, sizeof(filename), "io_ring_q%d", i); + debugfs_create_file(filename, 0600, vif->xenvif_dbg_root, + &vif->queues[i], + &xenvif_dbg_io_ring_ops_fops); + } + + if (vif->ctrl_irq) + debugfs_create_file("ctrl", 0400, vif->xenvif_dbg_root, vif, + &xenvif_ctrl_fops); } static void xenvif_debugfs_delif(struct xenvif *vif) { - if (IS_ERR_OR_NULL(xen_netback_dbg_root)) - return; - debugfs_remove_recursive(vif->xenvif_dbg_root); vif->xenvif_dbg_root = NULL; } @@ -472,6 +420,7 @@ static int backend_create_xenvif(struct backend_info *be) return err; } be->vif = vif; + vif->be = be; kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE); return 0; |