xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Paul Durrant <paul.durrant@citrix.com>
To: xen-devel@lists.xensource.com, jeremy@goop.org
Cc: Paul Durrant <paul.durrant@citrix.com>,
	Ian Campbell <ian.campbell@citrix.com>
Subject: [PATCH] Register watches for frontend features.
Date: Mon, 5 Jul 2010 12:39:33 +0100	[thread overview]
Message-ID: <1278329973-12414-1-git-send-email-paul.durrant@citrix.com> (raw)

Frontend features are currently only sampled at ring connection time.
Some frontends can change these features dynamically so watches should
be used to update the corresponding netback flags as and when they
change.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Cc: Ian Campbell <ian.campbell@citrix.com>
---
 drivers/xen/netback/common.h |    8 +
 drivers/xen/netback/xenbus.c |  293 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 274 insertions(+), 27 deletions(-)

diff --git a/drivers/xen/netback/common.h b/drivers/xen/netback/common.h
index a673331..3a0abf6 100644
--- a/drivers/xen/netback/common.h
+++ b/drivers/xen/netback/common.h
@@ -154,6 +154,14 @@ struct netback_accelerator {
 struct backend_info {
 	struct xenbus_device *dev;
 	struct xen_netif *netif;
+
+	/* Frontend feature watches. */
+    struct xenbus_watch can_sg_watch;
+    struct xenbus_watch gso_watch;
+    struct xenbus_watch gso_prefix_watch;
+    struct xenbus_watch csum_watch;
+    struct xenbus_watch smart_poll_watch;
+
 	enum xenbus_state frontend_state;
 	struct xenbus_watch hotplug_status_watch;
 	int have_hotplug_status_watch:1;
diff --git a/drivers/xen/netback/xenbus.c b/drivers/xen/netback/xenbus.c
index 99831c7..d08463c 100644
--- a/drivers/xen/netback/xenbus.c
+++ b/drivers/xen/netback/xenbus.c
@@ -33,6 +33,7 @@ static int connect_rings(struct backend_info *);
 static void connect(struct backend_info *);
 static void backend_create_netif(struct backend_info *be);
 static void unregister_hotplug_status_watch(struct backend_info *be);
+static void unregister_frontend_watches(struct backend_info *be);
 
 static int netback_remove(struct xenbus_device *dev)
 {
@@ -44,6 +45,7 @@ static int netback_remove(struct xenbus_device *dev)
 	if (be->netif) {
 		kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
 		xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
+		unregister_frontend_watches(be);
 		netif_disconnect(be->netif);
 		be->netif = NULL;
 	}
@@ -227,6 +229,7 @@ static void disconnect_backend(struct xenbus_device *dev)
 
 	if (be->netif) {
 		xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
+		unregister_frontend_watches(be);
 		netif_disconnect(be->netif);
 		be->netif = NULL;
 	}
@@ -409,6 +412,268 @@ static void connect(struct backend_info *be)
 	netif_wake_queue(be->netif->dev);
 }
 
+static void feature_can_sg_watch(struct xenbus_watch *watch,
+			         const char **vec,
+			         unsigned int vec_size)
+{
+	struct backend_info *be = container_of(watch,
+					       struct backend_info,
+					       can_sg_watch);
+	struct xen_netif *netif = be->netif;
+	struct xenbus_device *dev = be->dev;
+	int val;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg",
+			 "%d", &val) < 0)
+		val = 0;
+	netif->can_sg = !!val;
+	DPRINTK("can_sg -> %d\n", netif->can_sg);
+
+	netif_set_features(netif);
+}
+
+static int register_can_sg_watch(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	int err;
+
+	if (be->can_sg_watch.node)
+		return -EEXIST;
+
+	err = xenbus_watch_pathfmt(dev, &be->can_sg_watch,
+				   feature_can_sg_watch, "%s/%s",
+				   dev->otherend, "feature-sg");
+	if (err) {
+		xenbus_dev_fatal(dev, err, "watching %s/feature-sg",
+				 dev->otherend);
+		return err;
+	}
+	return 0;
+}
+
+static void unregister_can_sg_watch(struct backend_info *be)
+{
+	if (!be->can_sg_watch.node)
+		return;
+
+	unregister_xenbus_watch(&be->can_sg_watch);
+	kfree(be->can_sg_watch.node);
+	be->can_sg_watch.node = NULL;
+}
+
+static void feature_gso_watch(struct xenbus_watch *watch,
+			      const char **vec,
+			      unsigned int vec_size)
+{
+	struct backend_info *be = container_of(watch,
+					       struct backend_info,
+					       gso_watch);
+	struct xen_netif *netif = be->netif;
+	struct xenbus_device *dev = be->dev;
+	int val;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4",
+			 "%d", &val) < 0)
+		val = 0;
+	netif->gso = !!val;
+	DPRINTK("gso -> %d\n", netif->gso);
+
+	netif_set_features(netif);
+}
+
+static int register_gso_watch(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	int err;
+
+	if (be->gso_watch.node)
+		return -EEXIST;
+
+	err = xenbus_watch_pathfmt(dev, &be->gso_watch,
+				   feature_gso_watch, "%s/%s",
+				   dev->otherend, "feature-gso-tcpv4");
+	if (err) {
+		xenbus_dev_fatal(dev, err, "watching %s/feature-gso-tcpv4",
+				 dev->otherend);
+		return err;
+	}
+	return 0;
+}
+
+static void unregister_gso_watch(struct backend_info *be)
+{
+	if (!be->gso_watch.node)
+		return;
+
+	unregister_xenbus_watch(&be->gso_watch);
+	kfree(be->gso_watch.node);
+	be->gso_watch.node = NULL;
+}
+
+static void feature_gso_prefix_watch(struct xenbus_watch *watch,
+				     const char **vec,
+				     unsigned int vec_size)
+{
+	struct backend_info *be = container_of(watch,
+					       struct backend_info,
+					       gso_prefix_watch);
+	struct xen_netif *netif = be->netif;
+	struct xenbus_device *dev = be->dev;
+	int val;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4-prefix",
+			 "%d", &val) < 0)
+		val = 0;
+	netif->gso_prefix = !!val;
+	DPRINTK("gso_prefix -> %d\n", netif->gso_prefix);
+
+	netif_set_features(netif);
+}
+
+static int register_gso_prefix_watch(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	int err;
+
+	if (be->gso_prefix_watch.node)
+		return -EEXIST;
+
+	err = xenbus_watch_pathfmt(dev, &be->gso_prefix_watch,
+				   feature_gso_prefix_watch, "%s/%s",
+				   dev->otherend, "feature-gso-tcpv4-prefix");
+	if (err) {
+		xenbus_dev_fatal(dev, err, "watching %s/feature-gso-tcpv4-prefix",
+				 dev->otherend);
+		return err;
+	}
+	return 0;
+}
+
+static void unregister_gso_prefix_watch(struct backend_info *be)
+{
+	if (!be->gso_prefix_watch.node)
+		return;
+
+	unregister_xenbus_watch(&be->gso_prefix_watch);
+	kfree(be->gso_prefix_watch.node);
+	be->gso_prefix_watch.node = NULL;
+}
+
+static void feature_csum_watch(struct xenbus_watch *watch,
+			       const char **vec,
+			       unsigned int vec_size)
+{
+	struct backend_info *be = container_of(watch,
+					       struct backend_info,
+					       csum_watch);
+	struct xen_netif *netif = be->netif;
+	struct xenbus_device *dev = be->dev;
+	int val;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum",
+			 "%d", &val) < 0)
+		val = 0;
+	netif->csum = !val;
+	DPRINTK("csum -> %d\n", netif->csum);
+
+	netif_set_features(netif);
+}
+
+static int register_csum_watch(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	int err;
+
+	if (be->csum_watch.node)
+		return -EEXIST;
+
+	err = xenbus_watch_pathfmt(dev, &be->csum_watch,
+				   feature_csum_watch, "%s/%s",
+				   dev->otherend, "feature-no-csum");
+	if (err) {
+		xenbus_dev_fatal(dev, err, "watching %s/feature-no-csum",
+				 dev->otherend);
+		return err;
+	}
+	return 0;
+}
+
+static void unregister_csum_watch(struct backend_info *be)
+{
+	if (!be->csum_watch.node)
+		return;
+
+	unregister_xenbus_watch(&be->csum_watch);
+	kfree(be->csum_watch.node);
+	be->csum_watch.node = NULL;
+}
+
+static void feature_smart_poll_watch(struct xenbus_watch *watch,
+				     const char **vec,
+				     unsigned int vec_size)
+{
+	struct backend_info *be = container_of(watch,
+					       struct backend_info,
+					       smart_poll_watch);
+	struct xen_netif *netif = be->netif;
+	struct xenbus_device *dev = be->dev;
+	int val;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-smart-poll",
+			 "%d", &val) < 0)
+		val = 0;
+	netif->smart_poll = !!val;
+	DPRINTK("smart_poll -> %d\n", netif->smart_poll);
+
+	netif_set_features(netif);
+}
+
+static int register_smart_poll_watch(struct backend_info *be)
+{
+	struct xenbus_device *dev = be->dev;
+	int err;
+
+	if (be->smart_poll_watch.node)
+		return -EEXIST;
+
+	err = xenbus_watch_pathfmt(dev, &be->smart_poll_watch,
+				   feature_smart_poll_watch, "%s/%s",
+				   dev->otherend, "feature-smart-poll");
+	if (err) {
+		xenbus_dev_fatal(dev, err, "watching %s/feature-smart-poll",
+				 dev->otherend);
+		return err;
+	}
+	return 0;
+}
+
+static void unregister_smart_poll_watch(struct backend_info *be)
+{
+	if (!be->smart_poll_watch.node)
+		return;
+
+	unregister_xenbus_watch(&be->smart_poll_watch);
+	kfree(be->smart_poll_watch.node);
+	be->smart_poll_watch.node = NULL;
+}
+
+static void register_frontend_watches(struct backend_info *be)
+{
+	register_can_sg_watch(be);
+	register_gso_watch(be);
+	register_gso_prefix_watch(be);
+	register_csum_watch(be);
+	register_smart_poll_watch(be);
+}
+
+static void unregister_frontend_watches(struct backend_info *be)
+{
+	unregister_can_sg_watch(be);
+	unregister_gso_watch(be);
+	unregister_gso_prefix_watch(be);
+	unregister_csum_watch(be);
+	unregister_smart_poll_watch(be);
+}
 
 static int connect_rings(struct backend_info *be)
 {
@@ -457,33 +722,7 @@ static int connect_rings(struct backend_info *be)
 			netif->dev->tx_queue_len = 1;
 	}
 
-	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg",
-			 "%d", &val) < 0)
-		val = 0;
-	netif->can_sg = !!val;
-
-	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4",
-			 "%d", &val) < 0)
-		val = 0;
-	netif->gso = !!val;
-
-	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4-prefix",
-			 "%d", &val) < 0)
-		val = 0;
-	netif->gso_prefix = !!val;
-
-	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
-			 "%d", &val) < 0)
-		val = 0;
-	netif->csum = !val;
-
-	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-smart-poll",
-			 "%d", &val) < 0)
-		val = 0;
-	netif->smart_poll = !!val;
-
-	/* Set dev->features */
-	netif_set_features(netif);
+	register_frontend_watches(be);
 
 	/* Map the shared frame, irq etc. */
 	err = netif_map(netif, tx_ring_ref, rx_ring_ref, evtchn);
-- 
1.5.6.5

             reply	other threads:[~2010-07-05 11:39 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-07-05 11:39 Paul Durrant [this message]
2010-07-07 18:10 ` [PATCH] Register watches for frontend features Jeremy Fitzhardinge
2010-07-09 12:53   ` Paul Durrant
2010-07-10 17:30     ` Jeremy Fitzhardinge

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1278329973-12414-1-git-send-email-paul.durrant@citrix.com \
    --to=paul.durrant@citrix.com \
    --cc=ian.campbell@citrix.com \
    --cc=jeremy@goop.org \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).