[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] Register watches for frontend features.



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@xxxxxxxxxx>
Cc: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
 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


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.