Merge tag '9p-6.3-for-linus-part1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / net / 9p / trans_xen.c
index 82c7005ede65679bd528637ff029573a03e7776e..c64050e839ac6faccd7f9741654cfa74bf661836 100644 (file)
@@ -372,19 +372,24 @@ out:
        return ret;
 }
 
-static int xen_9pfs_front_probe(struct xenbus_device *dev,
-                               const struct xenbus_device_id *id)
+static int xen_9pfs_front_init(struct xenbus_device *dev)
 {
        int ret, i;
        struct xenbus_transaction xbt;
-       struct xen_9pfs_front_priv *priv = NULL;
-       char *versions;
+       struct xen_9pfs_front_priv *priv = dev_get_drvdata(&dev->dev);
+       char *versions, *v;
        unsigned int max_rings, max_ring_order, len = 0;
 
        versions = xenbus_read(XBT_NIL, dev->otherend, "versions", &len);
        if (IS_ERR(versions))
                return PTR_ERR(versions);
-       if (strcmp(versions, "1")) {
+       for (v = versions; *v; v++) {
+               if (simple_strtoul(v, &v, 10) == 1) {
+                       v = NULL;
+                       break;
+               }
+       }
+       if (v) {
                kfree(versions);
                return -EINVAL;
        }
@@ -399,11 +404,6 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev,
        if (p9_xen_trans.maxsize > XEN_FLEX_RING_SIZE(max_ring_order))
                p9_xen_trans.maxsize = XEN_FLEX_RING_SIZE(max_ring_order) / 2;
 
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       priv->dev = dev;
        priv->num_rings = XEN_9PFS_NUM_RINGS;
        priv->rings = kcalloc(priv->num_rings, sizeof(*priv->rings),
                              GFP_KERNEL);
@@ -462,23 +462,35 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev,
                goto error;
        }
 
-       write_lock(&xen_9pfs_lock);
-       list_add_tail(&priv->list, &xen_9pfs_devs);
-       write_unlock(&xen_9pfs_lock);
-       dev_set_drvdata(&dev->dev, priv);
-       xenbus_switch_state(dev, XenbusStateInitialised);
-
        return 0;
 
  error_xenbus:
        xenbus_transaction_end(xbt, 1);
        xenbus_dev_fatal(dev, ret, "writing xenstore");
  error:
-       dev_set_drvdata(&dev->dev, NULL);
        xen_9pfs_front_free(priv);
        return ret;
 }
 
+static int xen_9pfs_front_probe(struct xenbus_device *dev,
+                               const struct xenbus_device_id *id)
+{
+       struct xen_9pfs_front_priv *priv = NULL;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->dev = dev;
+       dev_set_drvdata(&dev->dev, priv);
+
+       write_lock(&xen_9pfs_lock);
+       list_add_tail(&priv->list, &xen_9pfs_devs);
+       write_unlock(&xen_9pfs_lock);
+
+       return 0;
+}
+
 static int xen_9pfs_front_resume(struct xenbus_device *dev)
 {
        dev_warn(&dev->dev, "suspend/resume unsupported\n");
@@ -497,6 +509,8 @@ static void xen_9pfs_front_changed(struct xenbus_device *dev,
                break;
 
        case XenbusStateInitWait:
+               if (!xen_9pfs_front_init(dev))
+                       xenbus_switch_state(dev, XenbusStateInitialised);
                break;
 
        case XenbusStateConnected: