direct-io.hg

view linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c @ 12798:70a7a4c953b4

[LINUX] Make CONFIG_XEN_FRAMEBUFFER=m build properly.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Dec 08 09:34:24 2006 +0000 (2006-12-08)
parents c242b6d6a64a
children d275951acf10
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_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port)
258 {
259 struct evtchn_bind_interdomain bind_interdomain;
260 int err;
262 bind_interdomain.remote_dom = dev->otherend_id;
263 bind_interdomain.remote_port = remote_port,
265 err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
266 &bind_interdomain);
267 if (err)
268 xenbus_dev_fatal(dev, err,
269 "binding to event channel %d from domain %d",
270 remote_port, dev->otherend_id);
271 else
272 *port = bind_interdomain.local_port;
274 return err;
275 }
276 EXPORT_SYMBOL_GPL(xenbus_bind_evtchn);
279 int xenbus_free_evtchn(struct xenbus_device *dev, int port)
280 {
281 struct evtchn_close close;
282 int err;
284 close.port = port;
286 err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
287 if (err)
288 xenbus_dev_error(dev, err, "freeing event channel %d", port);
290 return err;
291 }
292 EXPORT_SYMBOL_GPL(xenbus_free_evtchn);
295 enum xenbus_state xenbus_read_driver_state(const char *path)
296 {
297 enum xenbus_state result;
298 int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
299 if (err)
300 result = XenbusStateUnknown;
302 return result;
303 }
304 EXPORT_SYMBOL_GPL(xenbus_read_driver_state);