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>
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 +}