ia64/xen-unstable
changeset 11976:47cc7392741a
[LINUX] Move xenbus backend probing into a separate source file and
only build it when CONFIG_XEN_BACKEND is set.
This removes unused code from frontend only configurations and also
makes PV-on-HVM drivers on older kernels simpler by removing code
which would otherwise require extra code in the compatability shim.
Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
only build it when CONFIG_XEN_BACKEND is set.
This removes unused code from frontend only configurations and also
makes PV-on-HVM drivers on older kernels simpler by removing code
which would otherwise require extra code in the compatability shim.
Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
author | Ian Campbell <ian.campbell@xensource.com> |
---|---|
date | Wed Oct 25 13:58:30 2006 +0100 (2006-10-25) |
parents | 266aef9b0386 |
children | bd643d9db838 |
files | linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c |
line diff
1.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile Wed Oct 25 13:58:30 2006 +0100 1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile Wed Oct 25 13:58:30 2006 +0100 1.3 @@ -9,4 +9,5 @@ xenbus-objs += xenbus_client.o 1.4 xenbus-objs += xenbus_comms.o 1.5 xenbus-objs += xenbus_xs.o 1.6 xenbus-objs += xenbus_probe.o 1.7 +obj-$(CONFIG_XEN_BACKEND) += xenbus_probe_backend.o 1.8 obj-$(CONFIG_XEN_XENBUS_DEV) += xenbus_dev.o
2.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Wed Oct 25 13:58:30 2006 +0100 2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Wed Oct 25 13:58:30 2006 +0100 2.3 @@ -56,6 +56,7 @@ 2.4 #include <xen/hvm.h> 2.5 2.6 #include "xenbus_comms.h" 2.7 +#include "xenbus_probe.h" 2.8 2.9 int xen_store_evtchn; 2.10 struct xenstore_domain_interface *xen_store_interface; 2.11 @@ -68,12 +69,7 @@ static struct notifier_block *xenstore_c 2.12 static void wait_for_devices(struct xenbus_driver *xendrv); 2.13 2.14 static int xenbus_probe_frontend(const char *type, const char *name); 2.15 -static int xenbus_uevent_backend(struct device *dev, char **envp, 2.16 - int num_envp, char *buffer, int buffer_size); 2.17 -static int xenbus_probe_backend(const char *type, const char *domid); 2.18 2.19 -static int xenbus_dev_probe(struct device *_dev); 2.20 -static int xenbus_dev_remove(struct device *_dev); 2.21 static void xenbus_dev_shutdown(struct device *_dev); 2.22 2.23 /* If something in array of ids matches this device, return it. */ 2.24 @@ -87,7 +83,7 @@ match_device(const struct xenbus_device_ 2.25 return NULL; 2.26 } 2.27 2.28 -static int xenbus_match(struct device *_dev, struct device_driver *_drv) 2.29 +int xenbus_match(struct device *_dev, struct device_driver *_drv) 2.30 { 2.31 struct xenbus_driver *drv = to_xenbus_driver(_drv); 2.32 2.33 @@ -97,17 +93,6 @@ static int xenbus_match(struct device *_ 2.34 return match_device(drv->ids, to_xenbus_device(_dev)) != NULL; 2.35 } 2.36 2.37 -struct xen_bus_type 2.38 -{ 2.39 - char *root; 2.40 - unsigned int levels; 2.41 - int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename); 2.42 - int (*probe)(const char *type, const char *dir); 2.43 - struct bus_type bus; 2.44 - struct device dev; 2.45 -}; 2.46 - 2.47 - 2.48 /* device/<type>/<id> => <type>-<id> */ 2.49 static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename) 2.50 { 2.51 @@ -144,7 +129,7 @@ static void free_otherend_watch(struct x 2.52 } 2.53 2.54 2.55 -static int read_otherend_details(struct xenbus_device *xendev, 2.56 +int read_otherend_details(struct xenbus_device *xendev, 2.57 char *id_node, char *path_node) 2.58 { 2.59 int err = xenbus_gather(XBT_NIL, xendev->nodename, 2.60 @@ -177,12 +162,6 @@ static int read_backend_details(struct x 2.61 } 2.62 2.63 2.64 -static int read_frontend_details(struct xenbus_device *xendev) 2.65 -{ 2.66 - return read_otherend_details(xendev, "frontend-id", "frontend"); 2.67 -} 2.68 - 2.69 - 2.70 /* Bus type for frontend drivers. */ 2.71 static struct xen_bus_type xenbus_frontend = { 2.72 .root = "device", 2.73 @@ -201,106 +180,6 @@ static struct xen_bus_type xenbus_fronte 2.74 }, 2.75 }; 2.76 2.77 -/* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */ 2.78 -static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename) 2.79 -{ 2.80 - int domid, err; 2.81 - const char *devid, *type, *frontend; 2.82 - unsigned int typelen; 2.83 - 2.84 - type = strchr(nodename, '/'); 2.85 - if (!type) 2.86 - return -EINVAL; 2.87 - type++; 2.88 - typelen = strcspn(type, "/"); 2.89 - if (!typelen || type[typelen] != '/') 2.90 - return -EINVAL; 2.91 - 2.92 - devid = strrchr(nodename, '/') + 1; 2.93 - 2.94 - err = xenbus_gather(XBT_NIL, nodename, "frontend-id", "%i", &domid, 2.95 - "frontend", NULL, &frontend, 2.96 - NULL); 2.97 - if (err) 2.98 - return err; 2.99 - if (strlen(frontend) == 0) 2.100 - err = -ERANGE; 2.101 - if (!err && !xenbus_exists(XBT_NIL, frontend, "")) 2.102 - err = -ENOENT; 2.103 - 2.104 - kfree(frontend); 2.105 - 2.106 - if (err) 2.107 - return err; 2.108 - 2.109 - if (snprintf(bus_id, BUS_ID_SIZE, 2.110 - "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE) 2.111 - return -ENOSPC; 2.112 - return 0; 2.113 -} 2.114 - 2.115 -static struct xen_bus_type xenbus_backend = { 2.116 - .root = "backend", 2.117 - .levels = 3, /* backend/type/<frontend>/<id> */ 2.118 - .get_bus_id = backend_bus_id, 2.119 - .probe = xenbus_probe_backend, 2.120 - .bus = { 2.121 - .name = "xen-backend", 2.122 - .match = xenbus_match, 2.123 - .probe = xenbus_dev_probe, 2.124 - .remove = xenbus_dev_remove, 2.125 -// .shutdown = xenbus_dev_shutdown, 2.126 - .uevent = xenbus_uevent_backend, 2.127 - }, 2.128 - .dev = { 2.129 - .bus_id = "xen-backend", 2.130 - }, 2.131 -}; 2.132 - 2.133 -static int xenbus_uevent_backend(struct device *dev, char **envp, 2.134 - int num_envp, char *buffer, int buffer_size) 2.135 -{ 2.136 - struct xenbus_device *xdev; 2.137 - struct xenbus_driver *drv; 2.138 - int i = 0; 2.139 - int length = 0; 2.140 - 2.141 - DPRINTK(""); 2.142 - 2.143 - if (dev == NULL) 2.144 - return -ENODEV; 2.145 - 2.146 - xdev = to_xenbus_device(dev); 2.147 - if (xdev == NULL) 2.148 - return -ENODEV; 2.149 - 2.150 - /* stuff we want to pass to /sbin/hotplug */ 2.151 - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 2.152 - "XENBUS_TYPE=%s", xdev->devicetype); 2.153 - 2.154 - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 2.155 - "XENBUS_PATH=%s", xdev->nodename); 2.156 - 2.157 - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 2.158 - "XENBUS_BASE_PATH=%s", xenbus_backend.root); 2.159 - 2.160 - /* terminate, set to next free slot, shrink available space */ 2.161 - envp[i] = NULL; 2.162 - envp = &envp[i]; 2.163 - num_envp -= i; 2.164 - buffer = &buffer[length]; 2.165 - buffer_size -= length; 2.166 - 2.167 - if (dev->driver) { 2.168 - drv = to_xenbus_driver(dev->driver); 2.169 - if (drv && drv->uevent) 2.170 - return drv->uevent(xdev, envp, num_envp, buffer, 2.171 - buffer_size); 2.172 - } 2.173 - 2.174 - return 0; 2.175 -} 2.176 - 2.177 static void otherend_changed(struct xenbus_watch *watch, 2.178 const char **vec, unsigned int len) 2.179 { 2.180 @@ -360,7 +239,7 @@ static int watch_otherend(struct xenbus_ 2.181 } 2.182 2.183 2.184 -static int xenbus_dev_probe(struct device *_dev) 2.185 +int xenbus_dev_probe(struct device *_dev) 2.186 { 2.187 struct xenbus_device *dev = to_xenbus_device(_dev); 2.188 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); 2.189 @@ -407,7 +286,7 @@ fail: 2.190 return -ENODEV; 2.191 } 2.192 2.193 -static int xenbus_dev_remove(struct device *_dev) 2.194 +int xenbus_dev_remove(struct device *_dev) 2.195 { 2.196 struct xenbus_device *dev = to_xenbus_device(_dev); 2.197 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); 2.198 @@ -445,8 +324,8 @@ static void xenbus_dev_shutdown(struct d 2.199 put_device(&dev->dev); 2.200 } 2.201 2.202 -static int xenbus_register_driver_common(struct xenbus_driver *drv, 2.203 - struct xen_bus_type *bus) 2.204 +int xenbus_register_driver_common(struct xenbus_driver *drv, 2.205 + struct xen_bus_type *bus) 2.206 { 2.207 int ret; 2.208 2.209 @@ -477,14 +356,6 @@ int xenbus_register_frontend(struct xenb 2.210 } 2.211 EXPORT_SYMBOL_GPL(xenbus_register_frontend); 2.212 2.213 -int xenbus_register_backend(struct xenbus_driver *drv) 2.214 -{ 2.215 - drv->read_otherend_details = read_frontend_details; 2.216 - 2.217 - return xenbus_register_driver_common(drv, &xenbus_backend); 2.218 -} 2.219 -EXPORT_SYMBOL_GPL(xenbus_register_backend); 2.220 - 2.221 void xenbus_unregister_driver(struct xenbus_driver *drv) 2.222 { 2.223 driver_unregister(&drv->driver); 2.224 @@ -596,9 +467,9 @@ static ssize_t xendev_show_devtype(struc 2.225 DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); 2.226 2.227 2.228 -static int xenbus_probe_node(struct xen_bus_type *bus, 2.229 - const char *type, 2.230 - const char *nodename) 2.231 +int xenbus_probe_node(struct xen_bus_type *bus, 2.232 + const char *type, 2.233 + const char *nodename) 2.234 { 2.235 int err; 2.236 struct xenbus_device *xendev; 2.237 @@ -668,55 +539,6 @@ static int xenbus_probe_frontend(const c 2.238 return err; 2.239 } 2.240 2.241 -/* backend/<typename>/<frontend-uuid>/<name> */ 2.242 -static int xenbus_probe_backend_unit(const char *dir, 2.243 - const char *type, 2.244 - const char *name) 2.245 -{ 2.246 - char *nodename; 2.247 - int err; 2.248 - 2.249 - nodename = kasprintf("%s/%s", dir, name); 2.250 - if (!nodename) 2.251 - return -ENOMEM; 2.252 - 2.253 - DPRINTK("%s\n", nodename); 2.254 - 2.255 - err = xenbus_probe_node(&xenbus_backend, type, nodename); 2.256 - kfree(nodename); 2.257 - return err; 2.258 -} 2.259 - 2.260 -/* backend/<typename>/<frontend-domid> */ 2.261 -static int xenbus_probe_backend(const char *type, const char *domid) 2.262 -{ 2.263 - char *nodename; 2.264 - int err = 0; 2.265 - char **dir; 2.266 - unsigned int i, dir_n = 0; 2.267 - 2.268 - DPRINTK(""); 2.269 - 2.270 - nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid); 2.271 - if (!nodename) 2.272 - return -ENOMEM; 2.273 - 2.274 - dir = xenbus_directory(XBT_NIL, nodename, "", &dir_n); 2.275 - if (IS_ERR(dir)) { 2.276 - kfree(nodename); 2.277 - return PTR_ERR(dir); 2.278 - } 2.279 - 2.280 - for (i = 0; i < dir_n; i++) { 2.281 - err = xenbus_probe_backend_unit(nodename, type, dir[i]); 2.282 - if (err) 2.283 - break; 2.284 - } 2.285 - kfree(dir); 2.286 - kfree(nodename); 2.287 - return err; 2.288 -} 2.289 - 2.290 static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type) 2.291 { 2.292 int err = 0; 2.293 @@ -737,7 +559,7 @@ static int xenbus_probe_device_type(stru 2.294 return err; 2.295 } 2.296 2.297 -static int xenbus_probe_devices(struct xen_bus_type *bus) 2.298 +int xenbus_probe_devices(struct xen_bus_type *bus) 2.299 { 2.300 int err = 0; 2.301 char **dir; 2.302 @@ -779,7 +601,7 @@ static int strsep_len(const char *str, c 2.303 return (len == 0) ? i : -ERANGE; 2.304 } 2.305 2.306 -static void dev_changed(const char *node, struct xen_bus_type *bus) 2.307 +void dev_changed(const char *node, struct xen_bus_type *bus) 2.308 { 2.309 int exists, rootlen; 2.310 struct xenbus_device *dev; 2.311 @@ -824,25 +646,12 @@ static void frontend_changed(struct xenb 2.312 dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend); 2.313 } 2.314 2.315 -static void backend_changed(struct xenbus_watch *watch, 2.316 - const char **vec, unsigned int len) 2.317 -{ 2.318 - DPRINTK(""); 2.319 - 2.320 - dev_changed(vec[XS_WATCH_PATH], &xenbus_backend); 2.321 -} 2.322 - 2.323 /* We watch for devices appearing and vanishing. */ 2.324 static struct xenbus_watch fe_watch = { 2.325 .node = "device", 2.326 .callback = frontend_changed, 2.327 }; 2.328 2.329 -static struct xenbus_watch be_watch = { 2.330 - .node = "backend", 2.331 - .callback = backend_changed, 2.332 -}; 2.333 - 2.334 static int suspend_dev(struct device *dev, void *data) 2.335 { 2.336 int err = 0; 2.337 @@ -913,7 +722,7 @@ void xenbus_suspend(void) 2.338 DPRINTK(""); 2.339 2.340 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); 2.341 - bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev); 2.342 + xenbus_backend_suspend(suspend_dev); 2.343 xs_suspend(); 2.344 } 2.345 EXPORT_SYMBOL_GPL(xenbus_suspend); 2.346 @@ -923,7 +732,7 @@ void xenbus_resume(void) 2.347 xb_init_comms(); 2.348 xs_resume(); 2.349 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev); 2.350 - bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev); 2.351 + xenbus_backend_resume(resume_dev); 2.352 } 2.353 EXPORT_SYMBOL_GPL(xenbus_resume); 2.354 2.355 @@ -956,13 +765,10 @@ void xenbus_probe(void *unused) 2.356 { 2.357 BUG_ON((xenstored_ready <= 0)); 2.358 2.359 - /* Enumerate devices in xenstore. */ 2.360 + /* Enumerate devices in xenstore and watch for changes. */ 2.361 xenbus_probe_devices(&xenbus_frontend); 2.362 - xenbus_probe_devices(&xenbus_backend); 2.363 - 2.364 - /* Watch for changes. */ 2.365 register_xenbus_watch(&fe_watch); 2.366 - register_xenbus_watch(&be_watch); 2.367 + xenbus_backend_probe_and_watch(); 2.368 2.369 /* Notify others that xenstore is up */ 2.370 notifier_call_chain(&xenstore_chain, 0, NULL); 2.371 @@ -1021,7 +827,7 @@ static int __init xenbus_probe_init(void 2.372 2.373 /* Register ourselves with the kernel bus subsystem */ 2.374 bus_register(&xenbus_frontend.bus); 2.375 - bus_register(&xenbus_backend.bus); 2.376 + xenbus_backend_bus_register(); 2.377 2.378 /* 2.379 * Domain0 doesn't have a store_evtchn or store_mfn yet. 2.380 @@ -1092,7 +898,7 @@ static int __init xenbus_probe_init(void 2.381 2.382 /* Register ourselves with the kernel device subsystem */ 2.383 device_register(&xenbus_frontend.dev); 2.384 - device_register(&xenbus_backend.dev); 2.385 + xenbus_backend_device_register(); 2.386 2.387 if (!is_initial_xendomain()) 2.388 xenbus_probe(NULL);
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h Wed Oct 25 13:58:30 2006 +0100 3.3 @@ -0,0 +1,77 @@ 3.4 +/****************************************************************************** 3.5 + * xenbus_probe.h 3.6 + * 3.7 + * Talks to Xen Store to figure out what devices we have. 3.8 + * 3.9 + * Copyright (C) 2005 Rusty Russell, IBM Corporation 3.10 + * Copyright (C) 2005 XenSource Ltd. 3.11 + * 3.12 + * This program is free software; you can redistribute it and/or 3.13 + * modify it under the terms of the GNU General Public License version 2 3.14 + * as published by the Free Software Foundation; or, when distributed 3.15 + * separately from the Linux kernel or incorporated into other 3.16 + * software packages, subject to the following license: 3.17 + * 3.18 + * Permission is hereby granted, free of charge, to any person obtaining a copy 3.19 + * of this source file (the "Software"), to deal in the Software without 3.20 + * restriction, including without limitation the rights to use, copy, modify, 3.21 + * merge, publish, distribute, sublicense, and/or sell copies of the Software, 3.22 + * and to permit persons to whom the Software is furnished to do so, subject to 3.23 + * the following conditions: 3.24 + * 3.25 + * The above copyright notice and this permission notice shall be included in 3.26 + * all copies or substantial portions of the Software. 3.27 + * 3.28 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 3.29 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 3.30 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 3.31 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 3.32 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 3.33 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 3.34 + * IN THE SOFTWARE. 3.35 + */ 3.36 + 3.37 +#ifndef _XENBUS_PROBE_H 3.38 +#define _XENBUS_PROBE_H 3.39 + 3.40 +#ifdef CONFIG_XEN_BACKEND 3.41 +extern void xenbus_backend_suspend(int (*fn)(struct device *, void *)); 3.42 +extern void xenbus_backend_resume(int (*fn)(struct device *, void *)); 3.43 +extern void xenbus_backend_probe_and_watch(void); 3.44 +extern void xenbus_backend_bus_register(void); 3.45 +extern void xenbus_backend_device_register(void); 3.46 +#else 3.47 +static inline void xenbus_backend_suspend(int (*fn)(struct device *, void *)) {} 3.48 +static inline void xenbus_backend_resume(int (*fn)(struct device *, void *)) {} 3.49 +static inline void xenbus_backend_probe_and_watch(void) {} 3.50 +static inline void xenbus_backend_bus_register(void) {} 3.51 +static inline void xenbus_backend_device_register(void) {} 3.52 +#endif 3.53 + 3.54 +struct xen_bus_type 3.55 +{ 3.56 + char *root; 3.57 + unsigned int levels; 3.58 + int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename); 3.59 + int (*probe)(const char *type, const char *dir); 3.60 + struct bus_type bus; 3.61 + struct device dev; 3.62 +}; 3.63 + 3.64 +extern int xenbus_match(struct device *_dev, struct device_driver *_drv); 3.65 +extern int xenbus_dev_probe(struct device *_dev); 3.66 +extern int xenbus_dev_remove(struct device *_dev); 3.67 +extern int xenbus_register_driver_common(struct xenbus_driver *drv, 3.68 + struct xen_bus_type *bus); 3.69 +extern int xenbus_probe_node(struct xen_bus_type *bus, 3.70 + const char *type, 3.71 + const char *nodename); 3.72 +extern int xenbus_probe_devices(struct xen_bus_type *bus); 3.73 + 3.74 +extern void dev_changed(const char *node, struct xen_bus_type *bus); 3.75 + 3.76 +/* Simplified asprintf. Probably belongs in lib */ 3.77 +extern char *kasprintf(const char *fmt, ...); 3.78 + 3.79 +#endif 3.80 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c Wed Oct 25 13:58:30 2006 +0100 4.3 @@ -0,0 +1,271 @@ 4.4 +/****************************************************************************** 4.5 + * Talks to Xen Store to figure out what devices we have (backend half). 4.6 + * 4.7 + * Copyright (C) 2005 Rusty Russell, IBM Corporation 4.8 + * Copyright (C) 2005 Mike Wray, Hewlett-Packard 4.9 + * Copyright (C) 2005, 2006 XenSource Ltd 4.10 + * 4.11 + * This program is free software; you can redistribute it and/or 4.12 + * modify it under the terms of the GNU General Public License version 2 4.13 + * as published by the Free Software Foundation; or, when distributed 4.14 + * separately from the Linux kernel or incorporated into other 4.15 + * software packages, subject to the following license: 4.16 + * 4.17 + * Permission is hereby granted, free of charge, to any person obtaining a copy 4.18 + * of this source file (the "Software"), to deal in the Software without 4.19 + * restriction, including without limitation the rights to use, copy, modify, 4.20 + * merge, publish, distribute, sublicense, and/or sell copies of the Software, 4.21 + * and to permit persons to whom the Software is furnished to do so, subject to 4.22 + * the following conditions: 4.23 + * 4.24 + * The above copyright notice and this permission notice shall be included in 4.25 + * all copies or substantial portions of the Software. 4.26 + * 4.27 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 4.28 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 4.29 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4.30 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 4.31 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 4.32 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 4.33 + * IN THE SOFTWARE. 4.34 + */ 4.35 + 4.36 +#define DPRINTK(fmt, args...) \ 4.37 + pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \ 4.38 + __FUNCTION__, __LINE__, ##args) 4.39 + 4.40 +#include <linux/kernel.h> 4.41 +#include <linux/err.h> 4.42 +#include <linux/string.h> 4.43 +#include <linux/ctype.h> 4.44 +#include <linux/fcntl.h> 4.45 +#include <linux/mm.h> 4.46 +#include <linux/notifier.h> 4.47 +#include <linux/kthread.h> 4.48 + 4.49 +#include <asm/io.h> 4.50 +#include <asm/page.h> 4.51 +#include <asm/maddr.h> 4.52 +#include <asm/pgtable.h> 4.53 +#include <asm/hypervisor.h> 4.54 +#include <xen/xenbus.h> 4.55 +#include <xen/xen_proc.h> 4.56 +#include <xen/evtchn.h> 4.57 +#include <xen/features.h> 4.58 +#include <xen/hvm.h> 4.59 + 4.60 +#include "xenbus_comms.h" 4.61 +#include "xenbus_probe.h" 4.62 + 4.63 +#ifdef HAVE_XEN_PLATFORM_COMPAT_H 4.64 +#include <xen/platform-compat.h> 4.65 +#endif 4.66 + 4.67 +static int xenbus_uevent_backend(struct device *dev, char **envp, 4.68 + int num_envp, char *buffer, int buffer_size); 4.69 +static int xenbus_probe_backend(const char *type, const char *domid); 4.70 + 4.71 +extern int read_otherend_details(struct xenbus_device *xendev, 4.72 + char *id_node, char *path_node); 4.73 + 4.74 +static int read_frontend_details(struct xenbus_device *xendev) 4.75 +{ 4.76 + return read_otherend_details(xendev, "frontend-id", "frontend"); 4.77 +} 4.78 + 4.79 +/* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */ 4.80 +static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename) 4.81 +{ 4.82 + int domid, err; 4.83 + const char *devid, *type, *frontend; 4.84 + unsigned int typelen; 4.85 + 4.86 + type = strchr(nodename, '/'); 4.87 + if (!type) 4.88 + return -EINVAL; 4.89 + type++; 4.90 + typelen = strcspn(type, "/"); 4.91 + if (!typelen || type[typelen] != '/') 4.92 + return -EINVAL; 4.93 + 4.94 + devid = strrchr(nodename, '/') + 1; 4.95 + 4.96 + err = xenbus_gather(XBT_NIL, nodename, "frontend-id", "%i", &domid, 4.97 + "frontend", NULL, &frontend, 4.98 + NULL); 4.99 + if (err) 4.100 + return err; 4.101 + if (strlen(frontend) == 0) 4.102 + err = -ERANGE; 4.103 + if (!err && !xenbus_exists(XBT_NIL, frontend, "")) 4.104 + err = -ENOENT; 4.105 + kfree(frontend); 4.106 + 4.107 + if (err) 4.108 + return err; 4.109 + 4.110 + if (snprintf(bus_id, BUS_ID_SIZE, 4.111 + "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE) 4.112 + return -ENOSPC; 4.113 + return 0; 4.114 +} 4.115 + 4.116 +static struct xen_bus_type xenbus_backend = { 4.117 + .root = "backend", 4.118 + .levels = 3, /* backend/type/<frontend>/<id> */ 4.119 + .get_bus_id = backend_bus_id, 4.120 + .probe = xenbus_probe_backend, 4.121 + .bus = { 4.122 + .name = "xen-backend", 4.123 + .match = xenbus_match, 4.124 + .probe = xenbus_dev_probe, 4.125 + .remove = xenbus_dev_remove, 4.126 +// .shutdown = xenbus_dev_shutdown, 4.127 + .uevent = xenbus_uevent_backend, 4.128 + }, 4.129 + .dev = { 4.130 + .bus_id = "xen-backend", 4.131 + }, 4.132 +}; 4.133 + 4.134 +static int xenbus_uevent_backend(struct device *dev, char **envp, 4.135 + int num_envp, char *buffer, int buffer_size) 4.136 +{ 4.137 + struct xenbus_device *xdev; 4.138 + struct xenbus_driver *drv; 4.139 + int i = 0; 4.140 + int length = 0; 4.141 + 4.142 + DPRINTK(""); 4.143 + 4.144 + if (dev == NULL) 4.145 + return -ENODEV; 4.146 + 4.147 + xdev = to_xenbus_device(dev); 4.148 + if (xdev == NULL) 4.149 + return -ENODEV; 4.150 + 4.151 + /* stuff we want to pass to /sbin/hotplug */ 4.152 + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 4.153 + "XENBUS_TYPE=%s", xdev->devicetype); 4.154 + 4.155 + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 4.156 + "XENBUS_PATH=%s", xdev->nodename); 4.157 + 4.158 + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, 4.159 + "XENBUS_BASE_PATH=%s", xenbus_backend.root); 4.160 + 4.161 + /* terminate, set to next free slot, shrink available space */ 4.162 + envp[i] = NULL; 4.163 + envp = &envp[i]; 4.164 + num_envp -= i; 4.165 + buffer = &buffer[length]; 4.166 + buffer_size -= length; 4.167 + 4.168 + if (dev->driver) { 4.169 + drv = to_xenbus_driver(dev->driver); 4.170 + if (drv && drv->uevent) 4.171 + return drv->uevent(xdev, envp, num_envp, buffer, 4.172 + buffer_size); 4.173 + } 4.174 + 4.175 + return 0; 4.176 +} 4.177 + 4.178 +int xenbus_register_backend(struct xenbus_driver *drv) 4.179 +{ 4.180 + drv->read_otherend_details = read_frontend_details; 4.181 + 4.182 + return xenbus_register_driver_common(drv, &xenbus_backend); 4.183 +} 4.184 +EXPORT_SYMBOL_GPL(xenbus_register_backend); 4.185 + 4.186 +/* backend/<typename>/<frontend-uuid>/<name> */ 4.187 +static int xenbus_probe_backend_unit(const char *dir, 4.188 + const char *type, 4.189 + const char *name) 4.190 +{ 4.191 + char *nodename; 4.192 + int err; 4.193 + 4.194 + nodename = kasprintf("%s/%s", dir, name); 4.195 + if (!nodename) 4.196 + return -ENOMEM; 4.197 + 4.198 + DPRINTK("%s\n", nodename); 4.199 + 4.200 + err = xenbus_probe_node(&xenbus_backend, type, nodename); 4.201 + kfree(nodename); 4.202 + return err; 4.203 +} 4.204 + 4.205 +/* backend/<typename>/<frontend-domid> */ 4.206 +static int xenbus_probe_backend(const char *type, const char *domid) 4.207 +{ 4.208 + char *nodename; 4.209 + int err = 0; 4.210 + char **dir; 4.211 + unsigned int i, dir_n = 0; 4.212 + 4.213 + DPRINTK(""); 4.214 + 4.215 + nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid); 4.216 + if (!nodename) 4.217 + return -ENOMEM; 4.218 + 4.219 + dir = xenbus_directory(XBT_NIL, nodename, "", &dir_n); 4.220 + if (IS_ERR(dir)) { 4.221 + kfree(nodename); 4.222 + return PTR_ERR(dir); 4.223 + } 4.224 + 4.225 + for (i = 0; i < dir_n; i++) { 4.226 + err = xenbus_probe_backend_unit(nodename, type, dir[i]); 4.227 + if (err) 4.228 + break; 4.229 + } 4.230 + kfree(dir); 4.231 + kfree(nodename); 4.232 + return err; 4.233 +} 4.234 + 4.235 +static void backend_changed(struct xenbus_watch *watch, 4.236 + const char **vec, unsigned int len) 4.237 +{ 4.238 + DPRINTK(""); 4.239 + 4.240 + dev_changed(vec[XS_WATCH_PATH], &xenbus_backend); 4.241 +} 4.242 + 4.243 +static struct xenbus_watch be_watch = { 4.244 + .node = "backend", 4.245 + .callback = backend_changed, 4.246 +}; 4.247 + 4.248 +void xenbus_backend_suspend(int (*fn)(struct device *, void *)) 4.249 +{ 4.250 + DPRINTK(""); 4.251 + bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); 4.252 +} 4.253 + 4.254 +void xenbus_backend_resume(int (*fn)(struct device *, void *)) 4.255 +{ 4.256 + DPRINTK(""); 4.257 + bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); 4.258 +} 4.259 + 4.260 +void xenbus_backend_probe_and_watch(void) 4.261 +{ 4.262 + xenbus_probe_devices(&xenbus_backend); 4.263 + register_xenbus_watch(&be_watch); 4.264 +} 4.265 + 4.266 +void xenbus_backend_bus_register(void) 4.267 +{ 4.268 + bus_register(&xenbus_backend.bus); 4.269 +} 4.270 + 4.271 +void xenbus_backend_device_register(void) 4.272 +{ 4.273 + device_register(&xenbus_backend.dev); 4.274 +}