ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c @ 13665:140afd7a5462

merge with xen-unstable.hg
author awilliam@xenbuild2.aw
date Sat Jan 27 14:07:19 2007 -0700 (2007-01-27)
parents d275951acf10
children 1e56ac73b9b9
line source
1 /******************************************************************************
2 * Client-facing interface for the Xenbus driver. In other words, the
3 * interface between the Xenbus and the device-specific code, be it the
4 * frontend or the backend of that driver.
5 *
6 * Copyright (C) 2005 XenSource Ltd
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation; or, when distributed
11 * separately from the Linux kernel or incorporated into other
12 * software packages, subject to the following license:
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this source file (the "Software"), to deal in the Software without
16 * restriction, including without limitation the rights to use, copy, modify,
17 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18 * and to permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30 * IN THE SOFTWARE.
31 */
33 #include <xen/evtchn.h>
34 #include <xen/gnttab.h>
35 #include <xen/xenbus.h>
36 #include <xen/driver_util.h>
38 #ifdef HAVE_XEN_PLATFORM_COMPAT_H
39 #include <xen/platform-compat.h>
40 #endif
42 #define DPRINTK(fmt, args...) \
43 pr_debug("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
45 char *xenbus_strstate(enum xenbus_state state)
46 {
47 static char *name[] = {
48 [ XenbusStateUnknown ] = "Unknown",
49 [ XenbusStateInitialising ] = "Initialising",
50 [ XenbusStateInitWait ] = "InitWait",
51 [ XenbusStateInitialised ] = "Initialised",
52 [ XenbusStateConnected ] = "Connected",
53 [ XenbusStateClosing ] = "Closing",
54 [ XenbusStateClosed ] = "Closed",
55 };
56 return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
57 }
59 int xenbus_watch_path(struct xenbus_device *dev, const char *path,
60 struct xenbus_watch *watch,
61 void (*callback)(struct xenbus_watch *,
62 const char **, unsigned int))
63 {
64 int err;
66 watch->node = path;
67 watch->callback = callback;
69 err = register_xenbus_watch(watch);
71 if (err) {
72 watch->node = NULL;
73 watch->callback = NULL;
74 xenbus_dev_fatal(dev, err, "adding watch on %s", path);
75 }
77 return err;
78 }
79 EXPORT_SYMBOL_GPL(xenbus_watch_path);
82 int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
83 const char *path2, struct xenbus_watch *watch,
84 void (*callback)(struct xenbus_watch *,
85 const char **, unsigned int))
86 {
87 int err;
88 char *state = kasprintf(GFP_KERNEL, "%s/%s", path, path2);
89 if (!state) {
90 xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
91 return -ENOMEM;
92 }
93 err = xenbus_watch_path(dev, state, watch, callback);
95 if (err)
96 kfree(state);
97 return err;
98 }
99 EXPORT_SYMBOL_GPL(xenbus_watch_path2);
102 int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state)
103 {
104 /* We check whether the state is currently set to the given value, and
105 if not, then the state is set. We don't want to unconditionally
106 write the given state, because we don't want to fire watches
107 unnecessarily. Furthermore, if the node has gone, we don't write
108 to it, as the device will be tearing down, and we don't want to
109 resurrect that directory.
111 Note that, because of this cached value of our state, this function
112 will not work inside a Xenstore transaction (something it was
113 trying to in the past) because dev->state would not get reset if
114 the transaction was aborted.
116 */
118 int current_state;
119 int err;
121 if (state == dev->state)
122 return 0;
124 err = xenbus_scanf(XBT_NIL, dev->nodename, "state", "%d",
125 &current_state);
126 if (err != 1)
127 return 0;
129 err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%d", state);
130 if (err) {
131 if (state != XenbusStateClosing) /* Avoid looping */
132 xenbus_dev_fatal(dev, err, "writing new state");
133 return err;
134 }
136 dev->state = state;
138 return 0;
139 }
140 EXPORT_SYMBOL_GPL(xenbus_switch_state);
142 int xenbus_frontend_closed(struct xenbus_device *dev)
143 {
144 xenbus_switch_state(dev, XenbusStateClosed);
145 complete(&dev->down);
146 return 0;
147 }
148 EXPORT_SYMBOL_GPL(xenbus_frontend_closed);
150 /**
151 * Return the path to the error node for the given device, or NULL on failure.
152 * If the value returned is non-NULL, then it is the caller's to kfree.
153 */
154 static char *error_path(struct xenbus_device *dev)
155 {
156 return kasprintf(GFP_KERNEL, "error/%s", dev->nodename);
157 }
160 void _dev_error(struct xenbus_device *dev, int err, const char *fmt,
161 va_list ap)
162 {
163 int ret;
164 unsigned int len;
165 char *printf_buffer = NULL, *path_buffer = NULL;
167 #define PRINTF_BUFFER_SIZE 4096
168 printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
169 if (printf_buffer == NULL)
170 goto fail;
172 len = sprintf(printf_buffer, "%i ", -err);
173 ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
175 BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
177 dev_err(&dev->dev, "%s\n", printf_buffer);
179 path_buffer = error_path(dev);
181 if (path_buffer == NULL) {
182 printk("xenbus: failed to write error node for %s (%s)\n",
183 dev->nodename, printf_buffer);
184 goto fail;
185 }
187 if (xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer) != 0) {
188 printk("xenbus: failed to write error node for %s (%s)\n",
189 dev->nodename, printf_buffer);
190 goto fail;
191 }
193 fail:
194 if (printf_buffer)
195 kfree(printf_buffer);
196 if (path_buffer)
197 kfree(path_buffer);
198 }
201 void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
202 ...)
203 {
204 va_list ap;
206 va_start(ap, fmt);
207 _dev_error(dev, err, fmt, ap);
208 va_end(ap);
209 }
210 EXPORT_SYMBOL_GPL(xenbus_dev_error);
213 void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
214 ...)
215 {
216 va_list ap;
218 va_start(ap, fmt);
219 _dev_error(dev, err, fmt, ap);
220 va_end(ap);
222 xenbus_switch_state(dev, XenbusStateClosing);
223 }
224 EXPORT_SYMBOL_GPL(xenbus_dev_fatal);
227 int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn)
228 {
229 int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0);
230 if (err < 0)
231 xenbus_dev_fatal(dev, err, "granting access to ring page");
232 return err;
233 }
234 EXPORT_SYMBOL_GPL(xenbus_grant_ring);
237 int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
238 {
239 struct evtchn_alloc_unbound alloc_unbound;
240 int err;
242 alloc_unbound.dom = DOMID_SELF;
243 alloc_unbound.remote_dom = dev->otherend_id;
245 err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
246 &alloc_unbound);
247 if (err)
248 xenbus_dev_fatal(dev, err, "allocating event channel");
249 else
250 *port = alloc_unbound.port;
252 return err;
253 }
254 EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn);
257 int xenbus_free_evtchn(struct xenbus_device *dev, int port)
258 {
259 struct evtchn_close close;
260 int err;
262 close.port = port;
264 err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
265 if (err)
266 xenbus_dev_error(dev, err, "freeing event channel %d", port);
268 return err;
269 }
270 EXPORT_SYMBOL_GPL(xenbus_free_evtchn);
273 enum xenbus_state xenbus_read_driver_state(const char *path)
274 {
275 enum xenbus_state result;
276 int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
277 if (err)
278 result = XenbusStateUnknown;
280 return result;
281 }
282 EXPORT_SYMBOL_GPL(xenbus_read_driver_state);