summaryrefslogtreecommitdiffstats
path: root/sys/xen
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2008-12-04 07:59:05 +0000
committerkmacy <kmacy@FreeBSD.org>2008-12-04 07:59:05 +0000
commit77ba713706a3fffb53f651616e1a3d43caffe7ac (patch)
treeff76f522d9d91397c9adee09cba8d5e6b0f32df5 /sys/xen
parent0db39db0278da23ed458007116b629ab4a578a3e (diff)
downloadFreeBSD-src-77ba713706a3fffb53f651616e1a3d43caffe7ac.zip
FreeBSD-src-77ba713706a3fffb53f651616e1a3d43caffe7ac.tar.gz
Integrate 185578 from dfr
Use newbus to managed devices
Diffstat (limited to 'sys/xen')
-rw-r--r--sys/xen/gnttab.c6
-rw-r--r--sys/xen/gnttab.h2
-rw-r--r--sys/xen/xenbus/xenbus_client.c80
-rw-r--r--sys/xen/xenbus/xenbus_comms.c8
-rw-r--r--sys/xen/xenbus/xenbus_comms.h9
-rw-r--r--sys/xen/xenbus/xenbus_dev.c7
-rw-r--r--sys/xen/xenbus/xenbus_if.m37
-rw-r--r--sys/xen/xenbus/xenbus_probe.c1245
-rw-r--r--sys/xen/xenbus/xenbus_probe_backend.c1
-rw-r--r--sys/xen/xenbus/xenbus_xs.c4
-rw-r--r--sys/xen/xenbus/xenbusvar.h248
11 files changed, 640 insertions, 1007 deletions
diff --git a/sys/xen/gnttab.c b/sys/xen/gnttab.c
index 896af7b..fdd3d1b 100644
--- a/sys/xen/gnttab.c
+++ b/sys/xen/gnttab.c
@@ -537,8 +537,8 @@ gnttab_expand(unsigned int req_entries)
return rc;
}
-static int
-gnttab_init(void *unused)
+int
+gnttab_init()
{
int i;
unsigned int max_nr_glist_frames;
@@ -593,4 +593,4 @@ ini_nomem:
}
MTX_SYSINIT(gnttab, &gnttab_list_lock, "GNTTAB LOCK", MTX_DEF);
-SYSINIT(gnttab, SI_SUB_PSEUDO, SI_ORDER_FIRST, gnttab_init, NULL);
+//SYSINIT(gnttab, SI_SUB_PSEUDO, SI_ORDER_FIRST, gnttab_init, NULL);
diff --git a/sys/xen/gnttab.h b/sys/xen/gnttab.h
index 6a24dd2..d1abe14 100644
--- a/sys/xen/gnttab.h
+++ b/sys/xen/gnttab.h
@@ -49,6 +49,8 @@ struct gnttab_free_callback {
uint16_t count;
};
+int gnttab_init(void);
+
int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
int flags);
diff --git a/sys/xen/xenbus/xenbus_client.c b/sys/xen/xenbus/xenbus_client.c
index a6f9e6b..d8a1a3f 100644
--- a/sys/xen/xenbus/xenbus_client.c
+++ b/sys/xen/xenbus/xenbus_client.c
@@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$");
#include <machine/xen/xen-os.h>
#include <machine/xen/evtchn.h>
#include <xen/gnttab.h>
-#include <machine/xen/xenbus.h>
+#include <xen/xenbus/xenbusvar.h>
#include <machine/stdarg.h>
@@ -71,7 +71,7 @@ const char *xenbus_strstate(XenbusState state)
}
int
-xenbus_watch_path(struct xenbus_device *dev, char *path,
+xenbus_watch_path(device_t dev, char *path,
struct xenbus_watch *watch,
void (*callback)(struct xenbus_watch *,
const char **, unsigned int))
@@ -94,7 +94,7 @@ xenbus_watch_path(struct xenbus_device *dev, char *path,
EXPORT_SYMBOL(xenbus_watch_path);
-int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
+int xenbus_watch_path2(device_t dev, const char *path,
const char *path2, struct xenbus_watch *watch,
void (*callback)(struct xenbus_watch *,
const char **, unsigned int))
@@ -119,70 +119,27 @@ int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
}
EXPORT_SYMBOL(xenbus_watch_path2);
-
-int xenbus_switch_state(struct xenbus_device *dev,
- XenbusState state)
-{
- /* We check whether the state is currently set to the given value, and
- if not, then the state is set. We don't want to unconditionally
- write the given state, because we don't want to fire watches
- unnecessarily. Furthermore, if the node has gone, we don't write
- to it, as the device will be tearing down, and we don't want to
- resurrect that directory.
- */
-
- int current_state;
- int err;
-
- if (state == dev->state)
- return (0);
-
- err = xenbus_scanf(XBT_NIL, dev->nodename, "state", "%d",
- &current_state);
- if (err != 1)
- return 0;
-
- err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%d", state);
- if (err) {
- if (state != XenbusStateClosing) /* Avoid looping */
- xenbus_dev_fatal(dev, err, "writing new state");
- return err;
- }
-
- dev->state = state;
- return 0;
-
-}
-
-int xenbus_frontend_closed(struct xenbus_device *dev)
-{
- xenbus_switch_state(dev, XenbusStateClosed);
-#if 0
- complete(&dev->down);
-#endif
- return 0;
-}
-
/**
* Return the path to the error node for the given device, or NULL on failure.
* If the value returned is non-NULL, then it is the caller's to kfree.
*/
-static char *error_path(struct xenbus_device *dev)
+static char *error_path(device_t dev)
{
- char *path_buffer = kmalloc(strlen("error/") + strlen(dev->nodename) +
+ char *path_buffer = kmalloc(strlen("error/")
+ + strlen(xenbus_get_node(dev)) +
1, GFP_KERNEL);
if (path_buffer == NULL) {
return NULL;
}
strcpy(path_buffer, "error/");
- strcpy(path_buffer + strlen("error/"), dev->nodename);
+ strcpy(path_buffer + strlen("error/"), xenbus_get_node(dev));
return path_buffer;
}
-static void _dev_error(struct xenbus_device *dev, int err, const char *fmt,
+static void _dev_error(device_t dev, int err, const char *fmt,
va_list ap)
{
int ret;
@@ -205,13 +162,13 @@ static void _dev_error(struct xenbus_device *dev, int err, const char *fmt,
if (path_buffer == NULL) {
printk("xenbus: failed to write error node for %s (%s)\n",
- dev->nodename, printf_buffer);
+ xenbus_get_node(dev), printf_buffer);
goto fail;
}
if (xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer) != 0) {
printk("xenbus: failed to write error node for %s (%s)\n",
- dev->nodename, printf_buffer);
+ xenbus_get_node(dev), printf_buffer);
goto fail;
}
@@ -223,7 +180,7 @@ static void _dev_error(struct xenbus_device *dev, int err, const char *fmt,
}
-void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
+void xenbus_dev_error(device_t dev, int err, const char *fmt,
...)
{
va_list ap;
@@ -235,7 +192,7 @@ void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
EXPORT_SYMBOL(xenbus_dev_error);
-void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
+void xenbus_dev_fatal(device_t dev, int err, const char *fmt,
...)
{
va_list ap;
@@ -244,14 +201,15 @@ void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
_dev_error(dev, err, fmt, ap);
va_end(ap);
- xenbus_switch_state(dev, XenbusStateClosing);
+ xenbus_set_state(dev, XenbusStateClosing);
}
EXPORT_SYMBOL(xenbus_dev_fatal);
-int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn)
+int xenbus_grant_ring(device_t dev, unsigned long ring_mfn)
{
- int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0);
+ int err = gnttab_grant_foreign_access(
+ xenbus_get_otherend_id(dev), ring_mfn, 0);
if (err < 0)
xenbus_dev_fatal(dev, err, "granting access to ring page");
return err;
@@ -259,13 +217,13 @@ int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn)
EXPORT_SYMBOL(xenbus_grant_ring);
-int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
+int xenbus_alloc_evtchn(device_t dev, int *port)
{
struct evtchn_alloc_unbound alloc_unbound;
int err;
alloc_unbound.dom = DOMID_SELF;
- alloc_unbound.remote_dom = dev->otherend_id;
+ alloc_unbound.remote_dom = xenbus_get_otherend_id(dev);
err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
&alloc_unbound);
@@ -279,7 +237,7 @@ int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
EXPORT_SYMBOL(xenbus_alloc_evtchn);
-int xenbus_free_evtchn(struct xenbus_device *dev, int port)
+int xenbus_free_evtchn(device_t dev, int port)
{
struct evtchn_close close;
int err;
diff --git a/sys/xen/xenbus/xenbus_comms.c b/sys/xen/xenbus/xenbus_comms.c
index 8f0f171..90f0ea9 100644
--- a/sys/xen/xenbus/xenbus_comms.c
+++ b/sys/xen/xenbus/xenbus_comms.c
@@ -31,8 +31,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
-#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/bus.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <sys/param.h>
@@ -41,14 +41,12 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/kernel.h>
-
-
#include <machine/xen/xen-os.h>
#include <machine/xen/hypervisor.h>
#include <machine/xen/evtchn.h>
-#include <machine/xen/xenbus.h>
#include <machine/xen/xen_intr.h>
#include <xen/xenbus/xenbus_comms.h>
+#include <xen/interface/io/xs_wire.h>
static int xenbus_irq;
diff --git a/sys/xen/xenbus/xenbus_comms.h b/sys/xen/xenbus/xenbus_comms.h
index 871afd5..94a57dc 100644
--- a/sys/xen/xenbus/xenbus_comms.h
+++ b/sys/xen/xenbus/xenbus_comms.h
@@ -125,19 +125,14 @@ struct xen_bus_type
};
-extern void xenbus_backend_probe_and_watch(void);
-int xenbus_probe_node(struct xen_bus_type *bus, const char *type,
- const char *nodename);
-int xenbus_probe_devices(struct xen_bus_type *bus);
-
-int xenbus_register_driver_common(struct xenbus_driver *drv,
- struct xen_bus_type *bus);
+#if 0
void dev_changed(const char *node, struct xen_bus_type *bus);
int
read_otherend_details(struct xenbus_device *xendev, char *id_node,
char *path_node);
+#endif
char *kasprintf(const char *fmt, ...);
diff --git a/sys/xen/xenbus/xenbus_dev.c b/sys/xen/xenbus/xenbus_dev.c
index 8a13322..52e0b67 100644
--- a/sys/xen/xenbus/xenbus_dev.c
+++ b/sys/xen/xenbus/xenbus_dev.c
@@ -44,16 +44,11 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/conf.h>
-
#include <machine/xen/xen-os.h>
#include <machine/xen/hypervisor.h>
-#include <machine/xen/xenbus.h>
-#include <machine/xen/hypervisor.h>
+#include <xen/xenbus/xenbusvar.h>
#include <xen/xenbus/xenbus_comms.h>
-
-
-
#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK)
#define BUG_ON PANIC_IF
#define semaphore sema
diff --git a/sys/xen/xenbus/xenbus_if.m b/sys/xen/xenbus/xenbus_if.m
new file mode 100644
index 0000000..018a2bb
--- /dev/null
+++ b/sys/xen/xenbus/xenbus_if.m
@@ -0,0 +1,37 @@
+#-
+# Copyright (c) 2008 Doug Rabson
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+#include <sys/bus.h>
+#include <xen/interface/io/xenbus.h>
+
+INTERFACE xenbus;
+
+METHOD int backend_changed {
+ device_t dev;
+ enum xenbus_state newstate;
+};
diff --git a/sys/xen/xenbus/xenbus_probe.c b/sys/xen/xenbus/xenbus_probe.c
index c45a375..e57e6e3 100644
--- a/sys/xen/xenbus/xenbus_probe.c
+++ b/sys/xen/xenbus/xenbus_probe.c
@@ -1,6 +1,7 @@
/******************************************************************************
* Talks to Xen Store to figure out what devices we have.
*
+ * Copyright (C) 2008 Doug Rabson
* Copyright (C) 2005 Rusty Russell, IBM Corporation
* Copyright (C) 2005 Mike Wray, Hewlett-Packard
* Copyright (C) 2005 XenSource Ltd
@@ -38,838 +39,355 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/cdefs.h>
-#include <sys/time.h>
-#include <sys/sema.h>
-#include <sys/eventhandler.h>
-#include <sys/errno.h>
+#include <sys/bus.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
-#include <sys/conf.h>
-#include <sys/systm.h>
+#include <sys/sysctl.h>
#include <sys/syslog.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
+#include <sys/systm.h>
#include <sys/sx.h>
+#include <sys/taskqueue.h>
#include <machine/xen/xen-os.h>
-#include <machine/xen/hypervisor.h>
-#include <machine/xen/xenbus.h>
-#include <machine/xen/evtchn.h>
#include <machine/stdarg.h>
+#include <xen/gnttab.h>
+#include <xen/xenbus/xenbusvar.h>
#include <xen/xenbus/xenbus_comms.h>
-struct xendev_list_head xenbus_device_frontend_list;
-struct xendev_list_head xenbus_device_backend_list;
-static LIST_HEAD(, xenbus_driver) xendrv_list;
-
-extern struct sx xenwatch_mutex;
-
-EVENTHANDLER_DECLARE(xenstore_event, xenstore_event_handler_t);
-static struct eventhandler_list *xenstore_chain;
-device_t xenbus_dev;
-device_t xenbus_backend_dev;
-static MALLOC_DEFINE(M_XENDEV, "xenintrdrv", "xen system device");
-
-#define streq(a, b) (strcmp((a), (b)) == 0)
-
-static int watch_otherend(struct xenbus_device *dev);
-
-
-/* If something in array of ids matches this device, return it. */
-static const struct xenbus_device_id *
-match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
-{
- for (; !streq(arr->devicetype, ""); arr++) {
- if (streq(arr->devicetype, dev->devicetype))
- return arr;
- }
- return NULL;
-}
-
-#if 0
-static int xenbus_match(device_t _dev)
-{
- struct xenbus_driver *drv;
- struct xenbus_device *dev;
-
- dev = device_get_softc(_dev);
- drv = dev->driver;
-
- if (!drv->ids)
- return 0;
-
- return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
-}
-#endif
-
-
-/* device/<type>/<id> => <type>-<id> */
-static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
-{
- nodename = strchr(nodename, '/');
- if (!nodename || strlen(nodename + 1) >= BUS_ID_SIZE) {
- log(LOG_WARNING, "XENBUS: bad frontend %s\n", nodename);
- return -EINVAL;
- }
-
- strlcpy(bus_id, nodename + 1, BUS_ID_SIZE);
- if (!strchr(bus_id, '/')) {
- log(LOG_WARNING, "XENBUS: bus_id %s no slash\n", bus_id);
- return -EINVAL;
- }
- *strchr(bus_id, '/') = '-';
- return 0;
-}
-
-
-static void free_otherend_details(struct xenbus_device *dev)
-{
- kfree((void*)(uintptr_t)dev->otherend);
- dev->otherend = NULL;
-}
-
-
-static void free_otherend_watch(struct xenbus_device *dev)
-{
- if (dev->otherend_watch.node) {
- unregister_xenbus_watch(&dev->otherend_watch);
- kfree(dev->otherend_watch.node);
- dev->otherend_watch.node = NULL;
- }
-}
-
-int
-read_otherend_details(struct xenbus_device *xendev, char *id_node,
- char *path_node)
-{
- int err = xenbus_gather(XBT_NIL, xendev->nodename,
- id_node, "%i", &xendev->otherend_id,
- path_node, NULL, &xendev->otherend,
- NULL);
- if (err) {
- xenbus_dev_fatal(xendev, err,
- "reading other end details from %s",
- xendev->nodename);
- return err;
- }
- if (strlen(xendev->otherend) == 0 ||
- !xenbus_exists(XBT_NIL, xendev->otherend, "")) {
- xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s",
- xendev->nodename);
- kfree((void *)(uintptr_t)xendev->otherend);
- xendev->otherend = NULL;
- return -ENOENT;
- }
-
- return 0;
-}
-
-
-static int read_backend_details(struct xenbus_device *xendev)
-{
- return read_otherend_details(xendev, "backend-id", "backend");
-}
-
-#ifdef notyet
-/* XXX - move to probe backend */
-static int read_frontend_details(struct xenbus_device *xendev)
-{
- if (strncmp(xendev->nodename, "backend", 7))
- return -ENOENT;
- return read_otherend_details(xendev, "frontend-id", "frontend");
-}
-#endif
-
-/* Bus type for frontend drivers. */
-static int xenbus_probe_frontend(const char *type, const char *name);
-static struct xen_bus_type xenbus_frontend = {
- .root = "device",
- .levels = 2, /* device/type/<id> */
- .get_bus_id = frontend_bus_id,
- .probe = xenbus_probe_frontend,
- .bus = &xenbus_device_frontend_list,
-#if 0
- /* this initialization needs to happen dynamically */
- .bus = {
- .name = "xen",
- .match = xenbus_match,
- },
- .dev = {
- .bus_id = "xen",
- },
-#endif
+struct xenbus_softc {
+ struct xenbus_watch xs_devicewatch;
+ struct task xs_probechildren;
+ struct intr_config_hook xs_attachcb;
+ device_t xs_dev;
};
-#if 0
-static int xenbus_hotplug_backend(device_t dev, char **envp,
- int num_envp, char *buffer, int buffer_size)
-{
- panic("implement me");
-#if 0
- struct xenbus_device *xdev;
- struct xenbus_driver *drv = NULL;
- int i = 0;
- int length = 0;
- char *basepath_end;
- char *frontend_id;
-
- DPRINTK("");
-
- if (dev == NULL)
- return -ENODEV;
-
- xdev = to_xenbus_device(dev);
- if (xdev == NULL)
- return -ENODEV;
-
- if (dev->driver)
- drv = to_xenbus_driver(dev->driver);
-
- /* stuff we want to pass to /sbin/hotplug */
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "XENBUS_TYPE=%s", xdev->devicetype);
-
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "XENBUS_PATH=%s", xdev->nodename);
-
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "XENBUS_BASE_PATH=%s", xdev->nodename);
-
- basepath_end = strrchr(envp[i - 1], '/');
- length -= strlen(basepath_end);
- *basepath_end = '\0';
- basepath_end = strrchr(envp[i - 1], '/');
- length -= strlen(basepath_end);
- *basepath_end = '\0';
-
- basepath_end++;
- frontend_id = kmalloc(strlen(basepath_end) + 1, GFP_KERNEL);
- strcpy(frontend_id, basepath_end);
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "XENBUS_FRONTEND_ID=%s", frontend_id);
- kfree(frontend_id);
-
- /* terminate, set to next free slot, shrink available space */
- envp[i] = NULL;
- envp = &envp[i];
- num_envp -= i;
- buffer = &buffer[length];
- buffer_size -= length;
-
- if (drv && drv->hotplug)
- return drv->hotplug(xdev, envp, num_envp, buffer, buffer_size);
-
-#endif
- return 0;
-}
-#endif
-
-#if 0
-static int xenbus_probe_backend(const char *type, const char *domid, int unit);
-static struct xen_bus_type xenbus_backend = {
- .root = "backend",
- .levels = 3, /* backend/type/<frontend>/<id> */
- .get_bus_id = backend_bus_id,
- .probe = xenbus_probe_backend,
- /* at init time */
- .bus = &xenbus_device_backend_list,
-#if 0
- .bus = {
- .name = "xen-backend",
- .match = xenbus_match,
- .hotplug = xenbus_hotplug_backend,
- },
- .dev = {
- .bus_id = "xen-backend",
- },
-#endif
+struct xenbus_device_ivars {
+ struct xenbus_watch xd_otherend_watch; /* must be first */
+ struct sx xd_lock;
+ device_t xd_dev;
+ char *xd_node; /* node name in xenstore */
+ char *xd_type; /* xen device type */
+ enum xenbus_state xd_state;
+ int xd_otherend_id;
+ char *xd_otherend_path;
};
-#endif
-static void otherend_changed(struct xenbus_watch *watch,
- const char **vec, unsigned int len)
+/* Simplified asprintf. */
+char *
+kasprintf(const char *fmt, ...)
{
+ va_list ap;
+ unsigned int len;
+ char *p, dummy[1];
- struct xenbus_device *dev = (struct xenbus_device *)watch;
- struct xenbus_driver *drv = dev->driver;
- XenbusState state;
-
- /* Protect us against watches firing on old details when the otherend
- details change, say immediately after a resume. */
- if (!dev->otherend || strncmp(dev->otherend, vec[XS_WATCH_PATH],
- strlen(dev->otherend))) {
- DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]);
- return;
- }
-
- state = xenbus_read_driver_state(dev->otherend);
-
- DPRINTK("state is %d, %s, %s", state, dev->otherend_watch.node,
- vec[XS_WATCH_PATH]);
-
- /*
- * Ignore xenbus transitions during shutdown. This prevents us doing
- * work that can fail e.g., when the rootfs is gone.
- */
-#if 0
- if (system_state > SYSTEM_RUNNING) {
- struct xen_bus_type *bus = bus;
- bus = container_of(dev->dev.bus, struct xen_bus_type, bus);
- /* If we're frontend, drive the state machine to Closed. */
- /* This should cause the backend to release our resources. */
- if ((bus == &xenbus_frontend) && (state == XenbusStateClosing))
- xenbus_frontend_closed(dev);
- return;
- }
-#endif
- if (drv->otherend_changed)
- drv->otherend_changed(dev, state);
+ va_start(ap, fmt);
+ /* FIXME: vsnprintf has a bug, NULL should work */
+ len = vsnprintf(dummy, 0, fmt, ap);
+ va_end(ap);
+ p = kmalloc(len + 1, GFP_KERNEL);
+ if (!p)
+ return NULL;
+ va_start(ap, fmt);
+ vsprintf(p, fmt, ap);
+ va_end(ap);
+ return p;
}
-
-static int talk_to_otherend(struct xenbus_device *dev)
+static void
+xenbus_identify(driver_t *driver, device_t parent)
{
- struct xenbus_driver *drv;
-
- drv = dev->driver;
-
- free_otherend_watch(dev);
- free_otherend_details(dev);
-
- return drv->read_otherend_details(dev);
-}
-static int watch_otherend(struct xenbus_device *dev)
-{
- return xenbus_watch_path2(dev, dev->otherend, "state",
- &dev->otherend_watch, otherend_changed);
+ BUS_ADD_CHILD(parent, 0, "xenbus", 0);
}
static int
-xenbus_dev_probe(struct xenbus_device *dev)
+xenbus_probe(device_t dev)
{
- struct xenbus_driver *drv = dev->driver;
- const struct xenbus_device_id *id;
- int err;
-
+ int err = 0;
+
DPRINTK("");
-
- if (!drv->probe) {
- err = -ENODEV;
- goto fail;
- }
-
- id = match_device(drv->ids, dev);
- if (!id) {
- err = -ENODEV;
- goto fail;
- }
-
- err = talk_to_otherend(dev);
+
+ /* Initialize the interface to xenstore. */
+ err = xs_init();
if (err) {
- log(LOG_WARNING,
- "xenbus_probe: talk_to_otherend on %s failed.\n",
- dev->nodename);
- return err;
+ log(LOG_WARNING,
+ "XENBUS: Error initializing xenstore comms: %i\n", err);
+ return (ENXIO);
}
-
- err = drv->probe(dev, id);
- if (err)
- goto fail;
-
- err = watch_otherend(dev);
+ err = gnttab_init();
if (err) {
- log(LOG_WARNING,
- "xenbus_probe: watch_otherend on %s failed.\n",
- dev->nodename);
- return err;
+ log(LOG_WARNING,
+ "XENBUS: Error initializing grant table: %i\n", err);
+ return (ENXIO);
}
-
- return 0;
- fail:
- xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename);
- xenbus_switch_state(dev, XenbusStateClosed);
- return -ENODEV;
-}
+ device_set_desc(dev, "Xen Devices");
-static void xenbus_dev_free(struct xenbus_device *xendev)
-{
- LIST_REMOVE(xendev, list);
- kfree(xendev);
+ return (0);
}
-int
-xenbus_remove_device(struct xenbus_device *dev)
+static enum xenbus_state
+xenbus_otherend_state(struct xenbus_device_ivars *ivars)
{
- struct xenbus_driver *drv = dev->driver;
-
- DPRINTK("");
-
- free_otherend_watch(dev);
- free_otherend_details(dev);
- if (drv->remove)
- drv->remove(dev);
-
- xenbus_switch_state(dev, XenbusStateClosed);
-
- if (drv->cleanup_device)
- return drv->cleanup_device(dev);
-
- xenbus_dev_free(dev);
-
- return 0;
-}
-
-#if 0
-static int
-xenbus_dev_remove(device_t _dev)
-{
- return xenbus_remove_device(to_xenbus_device(_dev));
+ return (xenbus_read_driver_state(ivars->xd_otherend_path));
}
-#endif
-int xenbus_register_driver_common(struct xenbus_driver *drv,
- struct xen_bus_type *bus)
+static void
+xenbus_backend_changed(struct xenbus_watch *watch, const char **vec,
+ unsigned int len)
{
- struct xenbus_device *xdev;
-
-#if 0
- int ret;
- /* this all happens in the driver itself
- * doing this here simple serves to obfuscate
- */
+ struct xenbus_device_ivars *ivars;
+ device_t dev;
+ enum xenbus_state newstate;
- drv->driver.name = drv->name;
- drv->driver.bus = &bus->bus;
- drv->driver.owner = drv->owner;
- drv->driver.probe = xenbus_dev_probe;
- drv->driver.remove = xenbus_dev_remove;
+ ivars = (struct xenbus_device_ivars *) watch;
+ dev = ivars->xd_dev;
- return ret;
-#endif
- sx_xlock(&xenwatch_mutex);
- LIST_INSERT_HEAD(&xendrv_list, drv, list);
- sx_xunlock(&xenwatch_mutex);
- LIST_FOREACH(xdev, bus->bus, list) {
- if (match_device(drv->ids, xdev)) {
- xdev->driver = drv;
- xenbus_dev_probe(xdev);
- }
- }
- return 0;
-}
-
-int xenbus_register_frontend(struct xenbus_driver *drv)
-{
- drv->read_otherend_details = read_backend_details;
+ if (!ivars->xd_otherend_path
+ || strncmp(ivars->xd_otherend_path, vec[XS_WATCH_PATH],
+ strlen(ivars->xd_otherend_path)))
+ return;
- return xenbus_register_driver_common(drv, &xenbus_frontend);
+ newstate = xenbus_otherend_state(ivars);
+ XENBUS_BACKEND_CHANGED(dev, newstate);
}
-EXPORT_SYMBOL(xenbus_register_frontend);
-
-void xenbus_unregister_driver(struct xenbus_driver *drv)
+static int
+xenbus_device_exists(device_t dev, const char *node)
{
-#if 0
- driver_unregister(&drv->driver);
-#endif
-}
-EXPORT_SYMBOL(xenbus_unregister_driver);
+ device_t *kids;
+ struct xenbus_device_ivars *ivars;
+ int i, count, result;
-struct xb_find_info
-{
- struct xenbus_device *dev;
- const char *nodename;
-};
+ if (device_get_children(dev, &kids, &count))
+ return (FALSE);
-static struct xenbus_device *
-xenbus_device_find(const char *nodename, struct xendev_list_head *bus)
-{
- struct xenbus_device *xdev;
- LIST_FOREACH(xdev, bus, list) {
- if (streq(xdev->nodename, nodename)) {
- return xdev;
-#if 0
- get_device(dev);
-#endif
+ result = FALSE;
+ for (i = 0; i < count; i++) {
+ ivars = device_get_ivars(kids[i]);
+ if (!strcmp(ivars->xd_node, node)) {
+ result = TRUE;
+ break;
}
}
- return NULL;
-}
-#if 0
-static int cleanup_dev(device_t dev, void *data)
-{
- struct xenbus_device *xendev = device_get_softc(dev);
- struct xb_find_info *info = data;
- int len = strlen(info->nodename);
+ free(kids, M_TEMP);
- DPRINTK("%s", info->nodename);
-
- if (!strncmp(xendev->nodename, info->nodename, len)) {
- info->dev = xendev;
-#if 0
- get_device(dev);
-#endif
- return 1;
- }
- return 0;
+ return (result);
}
-#endif
-static void xenbus_cleanup_devices(const char *path, struct xendev_list_head * bus)
+static int
+xenbus_add_device(device_t dev, const char *bus,
+ const char *type, const char *id)
{
-#if 0
- struct xb_find_info info = { .nodename = path };
-
- do {
- info.dev = NULL;
- bus_for_each_dev(bus, NULL, &info, cleanup_dev);
- if (info.dev) {
- device_unregister(&info.dev->dev);
- put_device(&info.dev->dev);
- }
- } while (info.dev);
-#endif
-}
+ device_t child;
+ struct xenbus_device_ivars *ivars;
+ enum xenbus_state state;
+ char *statepath;
-#if 0
-void xenbus_dev_release(device_t dev)
-{
- /*
- * nothing to do softc gets freed with the device
- */
-
-}
-#endif
-/* Simplified asprintf. */
-char *kasprintf(const char *fmt, ...)
-{
- va_list ap;
- unsigned int len;
- char *p, dummy[1];
+ ivars = malloc(sizeof(struct xenbus_device_ivars),
+ M_DEVBUF, M_ZERO|M_WAITOK);
+ ivars->xd_node = kasprintf("%s/%s/%s", bus, type, id);
- va_start(ap, fmt);
- /* FIXME: vsnprintf has a bug, NULL should work */
- len = vsnprintf(dummy, 0, fmt, ap);
- va_end(ap);
-
- p = kmalloc(len + 1, GFP_KERNEL);
- if (!p)
- return NULL;
- va_start(ap, fmt);
- vsprintf(p, fmt, ap);
- va_end(ap);
- return p;
-}
-
-#if 0
-static ssize_t xendev_show_nodename(struct device *dev, char *buf)
-{
- return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
-}
-DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
-
-static ssize_t xendev_show_devtype(struct device *dev, char *buf)
-{
- return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
-}
-DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
-#endif
-
-int xenbus_probe_node(struct xen_bus_type *bus, const char *type,
- const char *nodename)
-{
-#define CHECK_FAIL \
- do { \
- if (err) \
- goto fail; \
- } while (0) \
-
-
-
- int err;
- struct xenbus_device *xendev;
- struct xenbus_driver *xdrv;
- size_t stringlen;
- char *tmpstring;
+ if (xenbus_device_exists(dev, ivars->xd_node)) {
+ /*
+ * We are already tracking this node
+ */
+ free(ivars->xd_node, M_DEVBUF);
+ free(ivars, M_DEVBUF);
+ return (0);
+ }
- XenbusState state = xenbus_read_driver_state(nodename);
+ state = xenbus_read_driver_state(ivars->xd_node);
- if (bus->error)
- return (bus->error);
-
-
if (state != XenbusStateInitialising) {
- /* Device is not new, so ignore it. This can happen if a
- device is going away after switching to Closed. */
- return 0;
+ /*
+ * Device is not new, so ignore it. This can
+ * happen if a device is going away after
+ * switching to Closed.
+ */
+ free(ivars->xd_node, M_DEVBUF);
+ free(ivars, M_DEVBUF);
+ return (0);
}
-
- stringlen = strlen(nodename) + 1 + strlen(type) + 1;
- xendev = kmalloc(sizeof(*xendev) + stringlen, GFP_KERNEL);
- if (!xendev)
- return -ENOMEM;
- memset(xendev, 0, sizeof(*xendev));
- xendev->state = XenbusStateInitialising;
-
- /* Copy the strings into the extra space. */
-
- tmpstring = (char *)(xendev + 1);
- strcpy(tmpstring, nodename);
- xendev->nodename = tmpstring;
-
- tmpstring += strlen(tmpstring) + 1;
- strcpy(tmpstring, type);
- xendev->devicetype = tmpstring;
+
/*
- * equivalent to device registration
- * events
+ * Find the backend details
*/
- LIST_INSERT_HEAD(bus->bus, xendev, list);
- LIST_FOREACH(xdrv, &xendrv_list, list) {
- if (match_device(xdrv->ids, xendev)) {
- xendev->driver = xdrv;
- if (!xenbus_dev_probe(xendev))
- break;
- }
- }
+ xenbus_gather(XBT_NIL, ivars->xd_node,
+ "backend-id", "%i", &ivars->xd_otherend_id,
+ "backend", NULL, &ivars->xd_otherend_path,
+ NULL);
-#if 0
- xendev->dev.parent = &bus->dev;
- xendev->dev.bus = &bus->bus;
- xendev->dev.release = xenbus_dev_release;
-
- err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
- CHECK_FAIL;
-
- /* Register with generic device framework. */
- err = device_register(&xendev->dev);
- CHECK_FAIL;
-
- device_create_file(&xendev->dev, &dev_attr_nodename);
- device_create_file(&xendev->dev, &dev_attr_devtype);
-#endif
- return 0;
-
-#undef CHECK_FAIL
-#if 0
- fail:
- xenbus_dev_free(xendev);
-#endif
- return err;
-}
+ sx_init(&ivars->xd_lock, "xdlock");
+ ivars->xd_type = strdup(type, M_DEVBUF);
+ ivars->xd_state = XenbusStateInitialising;
-/* device/<typename>/<name> */
-static int xenbus_probe_frontend(const char *type, const char *name)
-{
- char *nodename;
- int err;
+ statepath = malloc(strlen(ivars->xd_otherend_path)
+ + strlen("/state") + 1, M_DEVBUF, M_NOWAIT);
+ sprintf(statepath, "%s/state", ivars->xd_otherend_path);
- nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name);
- if (!nodename)
- return -ENOMEM;
+ ivars->xd_otherend_watch.node = statepath;
+ ivars->xd_otherend_watch.callback = xenbus_backend_changed;
- DPRINTK("%s", nodename);
+ child = device_add_child(dev, NULL, -1);
+ ivars->xd_dev = child;
+ device_set_ivars(child, ivars);
- err = xenbus_probe_node(&xenbus_frontend, type, nodename);
- kfree(nodename);
- return err;
+ return (0);
}
-static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type)
+static int
+xenbus_enumerate_type(device_t dev, const char *bus, const char *type)
{
- int err = 0;
char **dir;
- unsigned int dir_n = 0;
- int i;
+ unsigned int i, count;
- dir = xenbus_directory(XBT_NIL, bus->root, type, &dir_n);
+ dir = xenbus_directory(XBT_NIL, bus, type, &count);
if (IS_ERR(dir))
- return PTR_ERR(dir);
+ return (EINVAL);
+ for (i = 0; i < count; i++)
+ xenbus_add_device(dev, bus, type, dir[i]);
- for (i = 0; i < dir_n; i++) {
- err = bus->probe(type, dir[i]);
- if (err)
- break;
- }
- kfree(dir);
- return err;
+ free(dir, M_DEVBUF);
+
+ return (0);
}
-int xenbus_probe_devices(struct xen_bus_type *bus)
+static int
+xenbus_enumerate_bus(device_t dev, const char *bus)
{
- int err = 0;
char **dir;
- unsigned int i, dir_n;
+ unsigned int i, count;
- dir = xenbus_directory(XBT_NIL, bus->root, "", &dir_n);
+ dir = xenbus_directory(XBT_NIL, bus, "", &count);
if (IS_ERR(dir))
- return PTR_ERR(dir);
-
- for (i = 0; i < dir_n; i++) {
- err = xenbus_probe_device_type(bus, dir[i]);
- if (err)
- break;
+ return (EINVAL);
+ for (i = 0; i < count; i++) {
+ xenbus_enumerate_type(dev, bus, dir[i]);
}
- kfree(dir);
+ free(dir, M_DEVBUF);
- return err;
+ return (0);
}
-static unsigned int char_count(const char *str, char c)
+static int
+xenbus_probe_children(device_t dev)
{
- unsigned int i, ret = 0;
+ device_t *kids;
+ struct xenbus_device_ivars *ivars;
+ int i, count;
+
+ /*
+ * Probe any new devices and register watches for any that
+ * attach successfully. Since part of the protocol which
+ * establishes a connection with the other end is interrupt
+ * driven, we sleep until the device reaches a stable state
+ * (closed or connected).
+ */
+ if (device_get_children(dev, &kids, &count) == 0) {
+ for (i = 0; i < count; i++) {
+ if (device_get_state(kids[i]) != DS_NOTPRESENT)
+ continue;
+
+ if (device_probe_and_attach(kids[i]))
+ continue;
+ ivars = device_get_ivars(kids[i]);
+ register_xenbus_watch(
+ &ivars->xd_otherend_watch);
+ sx_xlock(&ivars->xd_lock);
+ while (ivars->xd_state != XenbusStateClosed
+ && ivars->xd_state != XenbusStateConnected)
+ sx_sleep(&ivars->xd_state, &ivars->xd_lock,
+ 0, "xdattach", 0);
+ sx_xunlock(&ivars->xd_lock);
+ }
+ free(kids, M_TEMP);
+ }
- for (i = 0; str[i]; i++)
- if (str[i] == c)
- ret++;
- return ret;
+ return (0);
}
-static int strsep_len(const char *str, char c, unsigned int len)
+static void
+xenbus_probe_children_cb(void *arg, int pending)
{
- unsigned int i;
+ device_t dev = (device_t) arg;
- for (i = 0; str[i]; i++)
- if (str[i] == c) {
- if (len == 0)
- return i;
- len--;
- }
- return (len == 0) ? i : -ERANGE;
+ xenbus_probe_children(dev);
}
-void dev_changed(const char *node, struct xen_bus_type *bus)
+static void
+xenbus_devices_changed(struct xenbus_watch *watch,
+ const char **vec, unsigned int len)
{
- int exists, rootlen;
- struct xenbus_device *dev;
- char type[BUS_ID_SIZE];
- const char *p;
- char *root;
-
- DPRINTK("");
- if (char_count(node, '/') < 2)
- return;
-
- exists = xenbus_exists(XBT_NIL, node, "");
- if (!exists) {
- xenbus_cleanup_devices(node, bus->bus);
- return;
- }
-
- /* backend/<type>/... or device/<type>/... */
- p = strchr(node, '/') + 1;
- snprintf(type, BUS_ID_SIZE, "%.*s", (int)strcspn(p, "/"), p);
- type[BUS_ID_SIZE-1] = '\0';
+ struct xenbus_softc *sc = (struct xenbus_softc *) watch;
+ device_t dev = sc->xs_dev;
+ char *node, *bus, *type, *id, *p;
- rootlen = strsep_len(node, '/', bus->levels);
- if (rootlen < 0)
- return;
- root = kasprintf("%.*s", rootlen, node);
- if (!root)
- return;
+ node = strdup(vec[XS_WATCH_PATH], M_DEVBUF);;
+ p = strchr(node, '/');
+ if (!p)
+ goto out;
+ bus = node;
+ *p = 0;
+ type = p + 1;
- dev = xenbus_device_find(root, bus->bus);
- if (!dev)
- xenbus_probe_node(bus, type, root);
-#if 0
- else
- put_device(&dev->dev);
-#endif
- kfree(root);
-}
+ p = strchr(type, '/');
+ if (!p)
+ goto out;
+ *p = 0;
+ id = p + 1;
-static void frontend_changed(struct xenbus_watch *watch,
- const char **vec, unsigned int len)
-{
- DPRINTK("");
+ p = strchr(id, '/');
+ if (p)
+ *p = 0;
- dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend);
+ xenbus_add_device(dev, bus, type, id);
+ taskqueue_enqueue(taskqueue_thread, &sc->xs_probechildren);
+out:
+ free(node, M_DEVBUF);
}
-/* We watch for devices appearing and vanishing. */
-static struct xenbus_watch fe_watch = {
- .node = "device",
- .callback = frontend_changed,
-};
-
-#ifdef notyet
-
-static int suspend_dev(device_t dev, void *data)
+static void
+xenbus_attach_deferred(void *arg)
{
- int err = 0;
- struct xenbus_driver *drv;
- struct xenbus_device *xdev;
-
- DPRINTK("");
+ device_t dev = (device_t) arg;
+ struct xenbus_softc *sc = device_get_softc(dev);
+ int error;
+
+ error = xenbus_enumerate_bus(dev, "device");
+ if (error)
+ return;
+ xenbus_probe_children(dev);
- xdev = device_get_softc(dev);
+ sc->xs_dev = dev;
+ sc->xs_devicewatch.node = "device";
+ sc->xs_devicewatch.callback = xenbus_devices_changed;
- drv = xdev->driver;
+ TASK_INIT(&sc->xs_probechildren, 0, xenbus_probe_children_cb, dev);
- if (device_get_driver(dev) == NULL)
- return 0;
+ register_xenbus_watch(&sc->xs_devicewatch);
- if (drv->suspend)
- err = drv->suspend(xdev);
-#if 0
- /* bus_id ? */
- if (err)
- log(LOG_WARNING, "xenbus: suspend %s failed: %i\n",
- dev->bus_id, err);
-#endif
- return 0;
+ config_intrhook_disestablish(&sc->xs_attachcb);
}
-
-
-static int resume_dev(device_t dev, void *data)
+static int
+xenbus_attach(device_t dev)
{
- int err;
- struct xenbus_driver *drv;
- struct xenbus_device *xdev;
+ struct xenbus_softc *sc = device_get_softc(dev);
- DPRINTK("");
+ sc->xs_attachcb.ich_func = xenbus_attach_deferred;
+ sc->xs_attachcb.ich_arg = dev;
+ config_intrhook_establish(&sc->xs_attachcb);
- if (device_get_driver(dev) == NULL)
- return 0;
- xdev = device_get_softc(dev);
- drv = xdev->driver;
-
- err = talk_to_otherend(xdev);
-#if 0
- if (err) {
- log(LOG_WARNING,
- "xenbus: resume (talk_to_otherend) %s failed: %i\n",
- dev->bus_id, err);
- return err;
- }
-#endif
- if (drv->resume)
- err = drv->resume(xdev);
-
- err = watch_otherend(xdev);
-#if 0
- /* bus_id? */
- if (err)
- log(LOG_WARNING,
- "xenbus: resume %s failed: %i\n", dev->bus_id, err);
-#endif
- return err;
+ return (0);
}
-#endif
-void xenbus_suspend(void)
+static void
+xenbus_suspend(device_t dev)
{
DPRINTK("");
panic("implement me");
@@ -879,9 +397,9 @@ void xenbus_suspend(void)
#endif
xs_suspend();
}
-EXPORT_SYMBOL(xenbus_suspend);
-void xenbus_resume(void)
+static void
+xenbus_resume(device_t dev)
{
xb_init_comms();
xs_resume();
@@ -891,218 +409,115 @@ void xenbus_resume(void)
bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
#endif
}
-EXPORT_SYMBOL(xenbus_resume);
-
-#if 0
-static device_t
-xenbus_add_child(device_t bus, int order, const char *name, int unit)
-{
- device_t child;
-
- child = device_add_child_ordered(bus, order, name, unit);
-
- return(child);
-}
-#endif
-
-/* A flag to determine if xenstored is 'ready' (i.e. has started) */
-int xenstored_ready = 0;
-
-int register_xenstore_notifier(xenstore_event_handler_t func, void *arg, int priority)
+static int
+xenbus_print_child(device_t dev, device_t child)
{
- int ret = 0;
+ struct xenbus_device_ivars *ivars = device_get_ivars(child);
+ int retval = 0;
- if (xenstored_ready > 0)
- ret = func(NULL);
- else
- eventhandler_register(xenstore_chain, "xenstore", func, arg, priority);
+ retval += bus_print_child_header(dev, child);
+ retval += printf(" at %s", ivars->xd_node);
+ retval += bus_print_child_footer(dev, child);
- return ret;
+ return (retval);
}
-EXPORT_SYMBOL(register_xenstore_notifier);
-#if 0
-void unregister_xenstore_notifier(struct notifier_block *nb)
-{
- notifier_chain_unregister(&xenstore_chain, nb);
-}
-EXPORT_SYMBOL(unregister_xenstore_notifier);
-#endif
-
-
-#ifdef DOM0
-static struct proc_dir_entry *xsd_mfn_intf;
-static struct proc_dir_entry *xsd_port_intf;
-
-
-static int xsd_mfn_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static int
+xenbus_read_ivar(device_t dev, device_t child, int index,
+ uintptr_t * result)
{
- int len;
- len = sprintf(page, "%ld", xen_start_info->store_mfn);
- *eof = 1;
- return len;
-}
+ struct xenbus_device_ivars *ivars = device_get_ivars(child);
-static int xsd_port_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len;
+ switch (index) {
+ case XENBUS_IVAR_NODE:
+ *result = (uintptr_t) ivars->xd_node;
+ return (0);
+ case XENBUS_IVAR_TYPE:
+ *result = (uintptr_t) ivars->xd_type;
+ return (0);
+ case XENBUS_IVAR_STATE:
+ *result = (uintptr_t) ivars->xd_state;
+ return (0);
- len = sprintf(page, "%d", xen_start_info->store_evtchn);
- *eof = 1;
- return len;
-}
+ case XENBUS_IVAR_OTHEREND_ID:
+ *result = (uintptr_t) ivars->xd_otherend_id;
+ return (0);
-#endif
-
-static int dom0 = 0;
-
-static int
-xenbus_probe_sysinit(void *unused)
-{
- int err = 0;
-
- DPRINTK("");
-
- LIST_INIT(&xenbus_device_frontend_list);
- LIST_INIT(&xenbus_device_backend_list);
- LIST_INIT(&xendrv_list);
-#if 0
- if (xen_init() < 0) {
- DPRINTK("failed");
- return -ENODEV;
+ case XENBUS_IVAR_OTHEREND_PATH:
+ *result = (uintptr_t) ivars->xd_otherend_path;
+ return (0);
}
+ return (ENOENT);
+}
- /* Register ourselves with the kernel bus & device subsystems */
- bus_register(&xenbus_frontend.bus);
- bus_register(&xenbus_backend.bus);
- device_register(&xenbus_frontend.dev);
- device_register(&xenbus_backend.dev);
-#endif
-
- /*
- ** Domain0 doesn't have a store_evtchn or store_mfn yet.
- */
- dom0 = (xen_start_info->store_evtchn == 0);
-
-
-#ifdef DOM0
- if (dom0) {
-
- unsigned long page;
- evtchn_op_t op = { 0 };
- int ret;
-
+static int
+xenbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
+{
+ struct xenbus_device_ivars *ivars = device_get_ivars(child);
+ enum xenbus_state newstate;
+ int currstate;
+ int error;
- /* Allocate page. */
- page = get_zeroed_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
+ switch (index) {
+ case XENBUS_IVAR_STATE:
+ newstate = (enum xenbus_state) value;
+ sx_xlock(&ivars->xd_lock);
+ if (ivars->xd_state == newstate)
+ goto out;
- /* We don't refcnt properly, so set reserved on page.
- * (this allocation is permanent) */
- SetPageReserved(virt_to_page(page));
+ error = xenbus_scanf(XBT_NIL, ivars->xd_node, "state",
+ "%d", &currstate);
+ if (error < 0)
+ goto out;
- xen_start_info->store_mfn =
- pfn_to_mfn(virt_to_phys((void *)page) >>
- PAGE_SHIFT);
-
- /* Next allocate a local port which xenstored can bind to */
- op.cmd = EVTCHNOP_alloc_unbound;
- op.u.alloc_unbound.dom = DOMID_SELF;
- op.u.alloc_unbound.remote_dom = 0;
-
- ret = HYPERVISOR_event_channel_op(&op);
- BUG_ON(ret);
- xen_start_info->store_evtchn = op.u.alloc_unbound.port;
-
- /* And finally publish the above info in /proc/xen */
- if((xsd_mfn_intf = create_xen_proc_entry("xsd_mfn", 0400)))
- xsd_mfn_intf->read_proc = xsd_mfn_read;
- if((xsd_port_intf = create_xen_proc_entry("xsd_port", 0400)))
- xsd_port_intf->read_proc = xsd_port_read;
- }
-#endif
- /* Initialize the interface to xenstore. */
- err = xs_init();
- if (err) {
- log(LOG_WARNING,
- "XENBUS: Error initializing xenstore comms: %i\n", err);
- return err;
+ error = xenbus_printf(XBT_NIL, ivars->xd_node, "state",
+ "%d", newstate);
+ if (error) {
+ if (newstate != XenbusStateClosing) /* Avoid looping */
+ xenbus_dev_fatal(dev, error, "writing new state");
+ goto out;
+ }
+ ivars->xd_state = newstate;
+ wakeup(&ivars->xd_state);
+ out:
+ sx_xunlock(&ivars->xd_lock);
+ return (0);
+
+ case XENBUS_IVAR_NODE:
+ case XENBUS_IVAR_TYPE:
+ case XENBUS_IVAR_OTHEREND_ID:
+ case XENBUS_IVAR_OTHEREND_PATH:
+ /*
+ * These variables are read-only.
+ */
+ return (EINVAL);
}
-
- return 0;
+ return (ENOENT);
}
-
-static int
-xenbus_probe_sysinit2(void *unused)
-{
- if (!dom0) {
- xenstored_ready = 1;
+SYSCTL_DECL(_dev);
+SYSCTL_NODE(_dev, OID_AUTO, xen, CTLFLAG_RD, NULL, "Xen");
#if 0
- xenbus_dev = BUS_ADD_CHILD(parent, 0, "xenbus", 0);
- if (xenbus_dev == NULL)
- panic("xenbus: could not attach");
- xenbus_backend_dev = BUS_ADD_CHILD(parent, 0, "xb_be", 0);
- if (xenbus_backend_dev == NULL)
- panic("xenbus: could not attach");
+SYSCTL_INT(_dev_xen, OID_AUTO, xsd_port, CTLFLAG_RD, &xen_store_evtchn, 0, "");
+SYSCTL_ULONG(_dev_xen, OID_AUTO, xsd_kva, CTLFLAG_RD, (u_long *) &xen_store, 0, "");
#endif
- BUG_ON((xenstored_ready <= 0));
-
-
- /* Enumerate devices in xenstore. */
- xenbus_probe_devices(&xenbus_frontend);
- register_xenbus_watch(&fe_watch);
- xenbus_backend_probe_and_watch();
-
- /* Notify others that xenstore is up */
- EVENTHANDLER_INVOKE(xenstore_event);
- }
- return (0);
-}
-
-
-SYSINIT(xenbus_probe_sysinit, SI_SUB_PSEUDO, SI_ORDER_FIRST, xenbus_probe_sysinit, NULL);
-SYSINIT(xenbus_probe_sysinit2, SI_SUB_PSEUDO, SI_ORDER_ANY,
- xenbus_probe_sysinit2, NULL);
-
-#if 0
static device_method_t xenbus_methods[] = {
/* Device interface */
-#if 0
- DEVMETHOD(device_identify, xenbus_identify),
+ DEVMETHOD(device_identify, xenbus_identify),
DEVMETHOD(device_probe, xenbus_probe),
DEVMETHOD(device_attach, xenbus_attach),
-
DEVMETHOD(device_detach, bus_generic_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
-#endif
DEVMETHOD(device_suspend, xenbus_suspend),
DEVMETHOD(device_resume, xenbus_resume),
/* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_add_child, xenbus_add_child),
- DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
- DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
-#if 0
- DEVMETHOD(bus_set_resource, bus_generic_set_resource),
- DEVMETHOD(bus_get_resource, bus_generic_get_resource),
-#endif
- DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
- DEVMETHOD(bus_release_resource, bus_generic_release_resource),
-#if 0
- DEVMETHOD(bus_delete_resource, bus_generic_delete_resource),
-#endif
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_print_child, xenbus_print_child),
+ DEVMETHOD(bus_read_ivar, xenbus_read_ivar),
+ DEVMETHOD(bus_write_ivar, xenbus_write_ivar),
{ 0, 0 }
};
@@ -1111,24 +526,12 @@ static char driver_name[] = "xenbus";
static driver_t xenbus_driver = {
driver_name,
xenbus_methods,
- sizeof(struct xenbus_device),
+ sizeof(struct xenbus_softc),
};
devclass_t xenbus_devclass;
-DRIVER_MODULE(xenbus, nexus, xenbus_driver, xenbus_devclass, 0, 0);
-
+#ifdef XENHVM
+DRIVER_MODULE(xenbus, xenpci, xenbus_driver, xenbus_devclass, 0, 0);
+#else
+DRIVER_MODULE(xenbus, nexus, xenbus_driver, xenbus_devclass, 0, 0);
#endif
-
-
-
-
-
-/*
- * Local variables:
- * c-file-style: "bsd"
- * indent-tabs-mode: t
- * c-indent-level: 4
- * c-basic-offset: 8
- * tab-width: 4
- * End:
- */
diff --git a/sys/xen/xenbus/xenbus_probe_backend.c b/sys/xen/xenbus/xenbus_probe_backend.c
index 3cb8e67..af83fe6 100644
--- a/sys/xen/xenbus/xenbus_probe_backend.c
+++ b/sys/xen/xenbus/xenbus_probe_backend.c
@@ -58,7 +58,6 @@ __FBSDID("$FreeBSD$");
#include <machine/xen/xen-os.h>
#include <machine/xen/hypervisor.h>
-#include <machine/xen/xenbus.h>
#include <machine/xen/evtchn.h>
#include <machine/stdarg.h>
diff --git a/sys/xen/xenbus/xenbus_xs.c b/sys/xen/xenbus/xenbus_xs.c
index a5d8a34..332a509 100644
--- a/sys/xen/xenbus/xenbus_xs.c
+++ b/sys/xen/xenbus/xenbus_xs.c
@@ -53,9 +53,9 @@ __FBSDID("$FreeBSD$");
#include <machine/xen/xen-os.h>
#include <machine/xen/hypervisor.h>
-#include <machine/xen/xenbus.h>
#include <machine/stdarg.h>
+#include <xen/xenbus/xenbusvar.h>
#include <xen/xenbus/xenbus_comms.h>
static int xs_process_msg(enum xsd_sockmsg_type *type);
@@ -788,8 +788,6 @@ static void xenwatch_thread(void *unused)
{
struct xs_stored_msg *msg;
- xenwatch_running = 1;
-
DELAY(100000);
while (xenwatch_inline) {
printf("xenwatch inline still running\n");
diff --git a/sys/xen/xenbus/xenbusvar.h b/sys/xen/xenbus/xenbusvar.h
new file mode 100644
index 0000000..1331c43
--- /dev/null
+++ b/sys/xen/xenbus/xenbusvar.h
@@ -0,0 +1,248 @@
+/******************************************************************************
+ * xenbus.h
+ *
+ * Talks to Xen Store to figure out what devices we have.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ * Copyright (C) 2005 XenSource Ltd.
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _XEN_XENBUS_XENBUSVAR_H
+#define _XEN_XENBUS_XENBUSVAR_H
+
+#include <sys/queue.h>
+#include <sys/bus.h>
+#include <sys/eventhandler.h>
+#include <machine/xen/xen-os.h>
+#include <xen/interface/io/xenbus.h>
+#include <xen/interface/io/xs_wire.h>
+
+#include "xenbus_if.h"
+
+enum {
+ /*
+ * Path of this device node.
+ */
+ XENBUS_IVAR_NODE,
+
+ /*
+ * The device type (e.g. vif, vbd).
+ */
+ XENBUS_IVAR_TYPE,
+
+ /*
+ * The state of this device (not the otherend's state).
+ */
+ XENBUS_IVAR_STATE,
+
+ /*
+ * Domain ID of the other end device.
+ */
+ XENBUS_IVAR_OTHEREND_ID,
+
+ /*
+ * Path of the other end device.
+ */
+ XENBUS_IVAR_OTHEREND_PATH
+};
+
+/*
+ * Simplified accessors for xenbus devices
+ */
+#define XENBUS_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(xenbus, var, XENBUS, ivar, type)
+
+XENBUS_ACCESSOR(node, NODE, const char *)
+XENBUS_ACCESSOR(type, TYPE, const char *)
+XENBUS_ACCESSOR(state, STATE, enum xenbus_state)
+XENBUS_ACCESSOR(otherend_id, OTHEREND_ID, int)
+XENBUS_ACCESSOR(otherend_path, OTHEREND_PATH, const char *)
+
+/* Register callback to watch this node. */
+struct xenbus_watch
+{
+ LIST_ENTRY(xenbus_watch) list;
+
+ /* Path being watched. */
+ char *node;
+
+ /* Callback (executed in a process context with no locks held). */
+ void (*callback)(struct xenbus_watch *,
+ const char **vec, unsigned int len);
+};
+
+typedef int (*xenstore_event_handler_t)(void *);
+
+struct xenbus_transaction
+{
+ uint32_t id;
+};
+
+#define XBT_NIL ((struct xenbus_transaction) { 0 })
+
+char **xenbus_directory(struct xenbus_transaction t,
+ const char *dir, const char *node, unsigned int *num);
+void *xenbus_read(struct xenbus_transaction t,
+ const char *dir, const char *node, unsigned int *len);
+int xenbus_write(struct xenbus_transaction t,
+ const char *dir, const char *node, const char *string);
+int xenbus_mkdir(struct xenbus_transaction t,
+ const char *dir, const char *node);
+int xenbus_exists(struct xenbus_transaction t,
+ const char *dir, const char *node);
+int xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node);
+int xenbus_transaction_start(struct xenbus_transaction *t);
+int xenbus_transaction_end(struct xenbus_transaction t, int abort);
+
+/* Single read and scanf: returns -errno or num scanned if > 0. */
+int xenbus_scanf(struct xenbus_transaction t,
+ const char *dir, const char *node, const char *fmt, ...)
+ __attribute__((format(scanf, 4, 5)));
+
+/* Single printf and write: returns -errno or 0. */
+int xenbus_printf(struct xenbus_transaction t,
+ const char *dir, const char *node, const char *fmt, ...)
+ __attribute__((format(printf, 4, 5)));
+
+/* Generic read function: NULL-terminated triples of name,
+ * sprintf-style type string, and pointer. Returns 0 or errno.*/
+int xenbus_gather(struct xenbus_transaction t, const char *dir, ...);
+
+/* notifer routines for when the xenstore comes up */
+int register_xenstore_notifier(xenstore_event_handler_t func, void *arg, int priority);
+#if 0
+void unregister_xenstore_notifier();
+#endif
+int register_xenbus_watch(struct xenbus_watch *watch);
+void unregister_xenbus_watch(struct xenbus_watch *watch);
+void xs_suspend(void);
+void xs_resume(void);
+
+/* Used by xenbus_dev to borrow kernel's store connection. */
+void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
+
+#define XENBUS_IS_ERR_READ(str) ({ \
+ if (!IS_ERR(str) && strlen(str) == 0) { \
+ free(str, M_DEVBUF); \
+ str = ERR_PTR(-ERANGE); \
+ } \
+ IS_ERR(str); \
+})
+
+#define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE)
+
+/**
+ * Register a watch on the given path, using the given xenbus_watch structure
+ * for storage, and the given callback function as the callback. Return 0 on
+ * success, or -errno on error. On success, the given path will be saved as
+ * watch->node, and remains the caller's to free. On error, watch->node will
+ * be NULL, the device will switch to XenbusStateClosing, and the error will
+ * be saved in the store.
+ */
+int xenbus_watch_path(device_t dev, char *path,
+ struct xenbus_watch *watch,
+ void (*callback)(struct xenbus_watch *,
+ const char **, unsigned int));
+
+
+/**
+ * Register a watch on the given path/path2, using the given xenbus_watch
+ * structure for storage, and the given callback function as the callback.
+ * Return 0 on success, or -errno on error. On success, the watched path
+ * (path/path2) will be saved as watch->node, and becomes the caller's to
+ * kfree(). On error, watch->node will be NULL, so the caller has nothing to
+ * free, the device will switch to XenbusStateClosing, and the error will be
+ * saved in the store.
+ */
+int xenbus_watch_path2(device_t dev, const char *path,
+ const char *path2, struct xenbus_watch *watch,
+ void (*callback)(struct xenbus_watch *,
+ const char **, unsigned int));
+
+
+/**
+ * Advertise in the store a change of the given driver to the given new_state.
+ * which case this is performed inside its own transaction. Return 0 on
+ * success, or -errno on error. On error, the device will switch to
+ * XenbusStateClosing, and the error will be saved in the store.
+ */
+int xenbus_switch_state(device_t dev,
+ XenbusState new_state);
+
+
+/**
+ * Grant access to the given ring_mfn to the peer of the given device. Return
+ * 0 on success, or -errno on error. On error, the device will switch to
+ * XenbusStateClosing, and the error will be saved in the store.
+ */
+int xenbus_grant_ring(device_t dev, unsigned long ring_mfn);
+
+
+/**
+ * Allocate an event channel for the given xenbus_device, assigning the newly
+ * created local port to *port. Return 0 on success, or -errno on error. On
+ * error, the device will switch to XenbusStateClosing, and the error will be
+ * saved in the store.
+ */
+int xenbus_alloc_evtchn(device_t dev, int *port);
+
+
+/**
+ * Free an existing event channel. Returns 0 on success or -errno on error.
+ */
+int xenbus_free_evtchn(device_t dev, int port);
+
+
+/**
+ * Return the state of the driver rooted at the given store path, or
+ * XenbusStateClosed if no state can be read.
+ */
+XenbusState xenbus_read_driver_state(const char *path);
+
+
+/***
+ * Report the given negative errno into the store, along with the given
+ * formatted message.
+ */
+void xenbus_dev_error(device_t dev, int err, const char *fmt,
+ ...);
+
+
+/***
+ * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by
+ * xenbus_switch_state(dev, NULL, XenbusStateClosing) to schedule an orderly
+ * closedown of this driver and its peer.
+ */
+void xenbus_dev_fatal(device_t dev, int err, const char *fmt,
+ ...);
+
+int xenbus_dev_init(void);
+
+const char *xenbus_strstate(enum xenbus_state state);
+int xenbus_dev_is_online(device_t dev);
+int xenbus_frontend_closed(device_t dev);
+
+#endif /* _XEN_XENBUS_XENBUSVAR_H */
OpenPOWER on IntegriCloud