From patchwork Thu Mar 19 10:05:42 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Imre Palik X-Patchwork-Id: 451821 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 114FF1400D5 for ; Thu, 19 Mar 2015 21:06:30 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="verification failed; unprotected key" header.d=gmail.com header.i=@gmail.com header.b=HKlosIOA; dkim-adsp=none (unprotected policy); dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754268AbbCSKGZ (ORCPT ); Thu, 19 Mar 2015 06:06:25 -0400 Received: from mail-wi0-f175.google.com ([209.85.212.175]:34083 "EHLO mail-wi0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750928AbbCSKGW (ORCPT ); Thu, 19 Mar 2015 06:06:22 -0400 Received: by wibg7 with SMTP id g7so6819292wib.1; Thu, 19 Mar 2015 03:06:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=h6M7VVLY8Bk6S498GDLVhmy12Vh6KkWngkMGULTkscM=; b=HKlosIOACmYOeUlvVXKsicFufMqCoLBVGSJJWEgMv/9afoMS/Hu/h5+AiBfEKy+BW5 kR2AD27St3R9wq60cLfl2pFFv5A6tPQgb6qe6wfYA333OwkcGu19SDEqffF4xTjh5tfm ICE/b3SEx7xf0wUQDVNKkwwbn7o1GPROkRx6o27WCy4q6L4hPPc7nIXZ/8vNbW6ricXO GKhQSVYpBvkgOiTovFcEKcfxy8YmgmJsIF6M7LYn2FkztjWELTnRNQEwe4+EJvmg3dUM BV23r5fAkWPeCU9fw4np9hohicC8N/WwvnFYNbbNVwRwvs3mjDMzGraO9fc8A5fMeMJu 37ow== X-Received: by 10.194.208.229 with SMTP id mh5mr130088439wjc.108.1426759581225; Thu, 19 Mar 2015 03:06:21 -0700 (PDT) Received: from uf01faf317492524e7af8.ant.amazon.com (54-240-197-225.amazon.com. [54.240.197.225]) by mx.google.com with ESMTPSA id cf12sm1296352wjb.10.2015.03.19.03.06.19 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 19 Mar 2015 03:06:20 -0700 (PDT) From: Imre Palik To: xen-devel@lists.xenproject.org, Ian Campbell , Wei Liu Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, "Palik, Imre" , Anthony Liguori Subject: [PATCH v2] xen-netback: making the bandwidth limiter runtime settable Date: Thu, 19 Mar 2015 11:05:42 +0100 Message-Id: <1426759542-15948-1-git-send-email-imrep.amz@gmail.com> X-Mailer: git-send-email 1.7.9.5 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: "Palik, Imre" With the current netback, the bandwidth limiter's parameters are only settable during vif setup time. This patch register a watch on them, and thus makes them runtime changeable. When the watch fires, the timer is reset. The timer's mutex is used for fencing the change. Cc: Anthony Liguori Signed-off-by: Imre Palik Acked-by: Wei Liu --- drivers/net/xen-netback/common.h | 4 +++ drivers/net/xen-netback/interface.c | 1 + drivers/net/xen-netback/netback.c | 4 +-- drivers/net/xen-netback/xenbus.c | 57 +++++++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 589fa25..8a495b3 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -238,6 +238,8 @@ struct xenvif { unsigned int num_queues; /* active queues, resource allocated */ unsigned int stalled_queues; + struct xenbus_watch credit_watch; + spinlock_t lock; #ifdef CONFIG_DEBUG_FS @@ -260,6 +262,8 @@ static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif) return to_xenbus_device(vif->dev->dev.parent); } +void xenvif_tx_credit_callback(unsigned long data); + struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, unsigned int handle); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 3aa8648..34d8038 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -463,6 +463,7 @@ int xenvif_init_queue(struct xenvif_queue *queue) queue->credit_bytes = queue->remaining_credit = ~0UL; queue->credit_usec = 0UL; init_timer(&queue->credit_timeout); + queue->credit_timeout.function = xenvif_tx_credit_callback; queue->credit_window_start = get_jiffies_64(); queue->rx_queue_max = XENVIF_RX_QUEUE_BYTES; diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index cab9f52..2c25e8e 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -641,7 +641,7 @@ static void tx_add_credit(struct xenvif_queue *queue) queue->remaining_credit = min(max_credit, max_burst); } -static void tx_credit_callback(unsigned long data) +void xenvif_tx_credit_callback(unsigned long data) { struct xenvif_queue *queue = (struct xenvif_queue *)data; tx_add_credit(queue); @@ -1169,8 +1169,6 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size) if (size > queue->remaining_credit) { queue->credit_timeout.data = (unsigned long)queue; - queue->credit_timeout.function = - tx_credit_callback; mod_timer(&queue->credit_timeout, next_credit); queue->credit_window_start = next_credit; diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 794204e..3d8dbf5 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -41,6 +41,7 @@ static void connect(struct backend_info *be); static int read_xenbus_vif_flags(struct backend_info *be); static int backend_create_xenvif(struct backend_info *be); static void unregister_hotplug_status_watch(struct backend_info *be); +static void xen_unregister_watchers(struct xenvif *vif); static void set_backend_state(struct backend_info *be, enum xenbus_state state); @@ -232,6 +233,7 @@ static int netback_remove(struct xenbus_device *dev) unregister_hotplug_status_watch(be); if (be->vif) { kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); + xen_unregister_watchers(be->vif); xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); xenvif_free(be->vif); be->vif = NULL; @@ -430,6 +432,7 @@ static int backend_create_xenvif(struct backend_info *be) static void backend_disconnect(struct backend_info *be) { if (be->vif) { + xen_unregister_watchers(be->vif); #ifdef CONFIG_DEBUG_FS xenvif_debugfs_delif(be->vif); #endif /* CONFIG_DEBUG_FS */ @@ -645,6 +648,59 @@ static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[]) return 0; } +static void xen_net_rate_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + struct xenvif *vif = container_of(watch, struct xenvif, credit_watch); + struct xenbus_device *dev = xenvif_to_xenbus_device(vif); + unsigned long credit_bytes; + unsigned long credit_usec; + unsigned int queue_index; + + xen_net_read_rate(dev, &credit_bytes, &credit_usec); + for (queue_index = 0; queue_index < vif->num_queues; queue_index++) { + struct xenvif_queue *queue = &vif->queues[queue_index]; + + queue->credit_bytes = credit_bytes; + queue->credit_usec = credit_usec; + if (!mod_timer_pending(&queue->credit_timeout, jiffies) && + queue->remaining_credit > queue->credit_bytes) { + queue->remaining_credit = queue->credit_bytes; + } + } +} + +static int xen_register_watchers(struct xenbus_device *dev, struct xenvif *vif) +{ + int err = 0; + char *node; + unsigned maxlen = strlen(dev->nodename) + sizeof("/rate"); + + node = kmalloc(maxlen, GFP_KERNEL); + if (!node) + return -ENOMEM; + snprintf(node, maxlen, "%s/rate", dev->nodename); + vif->credit_watch.node = node; + vif->credit_watch.callback = xen_net_rate_changed; + err = register_xenbus_watch(&vif->credit_watch); + if (err) { + pr_err("Failed to set watcher %s\n", vif->credit_watch.node); + kfree(node); + vif->credit_watch.node = NULL; + vif->credit_watch.callback = NULL; + } + return err; +} + +static void xen_unregister_watchers(struct xenvif *vif) +{ + if (vif->credit_watch.node) { + unregister_xenbus_watch(&vif->credit_watch); + kfree(vif->credit_watch.node); + vif->credit_watch.node = NULL; + } +} + static void unregister_hotplug_status_watch(struct backend_info *be) { if (be->have_hotplug_status_watch) { @@ -709,6 +765,7 @@ static void connect(struct backend_info *be) } xen_net_read_rate(dev, &credit_bytes, &credit_usec); + xen_register_watchers(dev, be->vif); read_xenbus_vif_flags(be); /* Use the number of queues requested by the frontend */