This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / xen / xenbus / xenbus_client.c
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  */
32
33 #include <xen/evtchn.h>
34 #include <xen/gnttab.h>
35 #include <xen/xenbus.h>
36 #include <xen/driver_util.h>
37
38 /* xenbus_probe.c */
39 extern char *kasprintf(const char *fmt, ...);
40
41 #define DPRINTK(fmt, args...) \
42     pr_debug("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
43
44 int xenbus_watch_path(struct xenbus_device *dev, const char *path,
45                       struct xenbus_watch *watch,
46                       void (*callback)(struct xenbus_watch *,
47                                        const char **, unsigned int))
48 {
49         int err;
50
51         watch->node = path;
52         watch->callback = callback;
53
54         err = register_xenbus_watch(watch);
55
56         if (err) {
57                 watch->node = NULL;
58                 watch->callback = NULL;
59                 xenbus_dev_fatal(dev, err, "adding watch on %s", path);
60         }
61
62         return err;
63 }
64 EXPORT_SYMBOL_GPL(xenbus_watch_path);
65
66
67 int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
68                        const char *path2, struct xenbus_watch *watch,
69                        void (*callback)(struct xenbus_watch *,
70                                         const char **, unsigned int))
71 {
72         int err;
73         char *state = kasprintf("%s/%s", path, path2);
74         if (!state) {
75                 xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
76                 return -ENOMEM;
77         }
78         err = xenbus_watch_path(dev, state, watch, callback);
79
80         if (err)
81                 kfree(state);
82         return err;
83 }
84 EXPORT_SYMBOL_GPL(xenbus_watch_path2);
85
86
87 int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state)
88 {
89         /* We check whether the state is currently set to the given value, and
90            if not, then the state is set.  We don't want to unconditionally
91            write the given state, because we don't want to fire watches
92            unnecessarily.  Furthermore, if the node has gone, we don't write
93            to it, as the device will be tearing down, and we don't want to
94            resurrect that directory.
95
96            Note that, because of this cached value of our state, this function
97            will not work inside a Xenstore transaction (something it was
98            trying to in the past) because dev->state would not get reset if
99            the transaction was aborted.
100
101          */
102
103         int current_state;
104         int err;
105
106         if (state == dev->state)
107                 return 0;
108
109         err = xenbus_scanf(XBT_NIL, dev->nodename, "state", "%d",
110                            &current_state);
111         if (err != 1)
112                 return 0;
113
114         err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%d", state);
115         if (err) {
116                 if (state != XenbusStateClosing) /* Avoid looping */
117                         xenbus_dev_fatal(dev, err, "writing new state");
118                 return err;
119         }
120
121         dev->state = state;
122
123         return 0;
124 }
125 EXPORT_SYMBOL_GPL(xenbus_switch_state);
126
127
128 /**
129  * Return the path to the error node for the given device, or NULL on failure.
130  * If the value returned is non-NULL, then it is the caller's to kfree.
131  */
132 static char *error_path(struct xenbus_device *dev)
133 {
134         return kasprintf("error/%s", dev->nodename);
135 }
136
137
138 void _dev_error(struct xenbus_device *dev, int err, const char *fmt,
139                 va_list ap)
140 {
141         int ret;
142         unsigned int len;
143         char *printf_buffer = NULL, *path_buffer = NULL;
144
145 #define PRINTF_BUFFER_SIZE 4096
146         printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
147         if (printf_buffer == NULL)
148                 goto fail;
149
150         len = sprintf(printf_buffer, "%i ", -err);
151         ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
152
153         BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
154
155         dev_err(&dev->dev, "%s\n", printf_buffer);
156
157         path_buffer = error_path(dev);
158
159         if (path_buffer == NULL) {
160                 printk("xenbus: failed to write error node for %s (%s)\n",
161                        dev->nodename, printf_buffer);
162                 goto fail;
163         }
164
165         if (xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer) != 0) {
166                 printk("xenbus: failed to write error node for %s (%s)\n",
167                        dev->nodename, printf_buffer);
168                 goto fail;
169         }
170
171 fail:
172         if (printf_buffer)
173                 kfree(printf_buffer);
174         if (path_buffer)
175                 kfree(path_buffer);
176 }
177
178
179 void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
180                       ...)
181 {
182         va_list ap;
183
184         va_start(ap, fmt);
185         _dev_error(dev, err, fmt, ap);
186         va_end(ap);
187 }
188 EXPORT_SYMBOL_GPL(xenbus_dev_error);
189
190
191 void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
192                       ...)
193 {
194         va_list ap;
195
196         va_start(ap, fmt);
197         _dev_error(dev, err, fmt, ap);
198         va_end(ap);
199
200         xenbus_switch_state(dev, XenbusStateClosing);
201 }
202 EXPORT_SYMBOL_GPL(xenbus_dev_fatal);
203
204
205 int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn)
206 {
207         int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0);
208         if (err < 0)
209                 xenbus_dev_fatal(dev, err, "granting access to ring page");
210         return err;
211 }
212 EXPORT_SYMBOL_GPL(xenbus_grant_ring);
213
214
215 int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
216 {
217         struct evtchn_alloc_unbound alloc_unbound;
218         int err;
219
220         alloc_unbound.dom        = DOMID_SELF;
221         alloc_unbound.remote_dom = dev->otherend_id;
222
223         err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
224                                           &alloc_unbound);
225         if (err)
226                 xenbus_dev_fatal(dev, err, "allocating event channel");
227         else
228                 *port = alloc_unbound.port;
229
230         return err;
231 }
232 EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn);
233
234
235 int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port)
236 {
237         struct evtchn_bind_interdomain bind_interdomain;
238         int err;
239
240         bind_interdomain.remote_dom  = dev->otherend_id;
241         bind_interdomain.remote_port = remote_port,
242
243         err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
244                                           &bind_interdomain);
245         if (err)
246                 xenbus_dev_fatal(dev, err,
247                                  "binding to event channel %d from domain %d",
248                                  remote_port, dev->otherend_id);
249         else
250                 *port = bind_interdomain.local_port;
251
252         return err;
253 }
254 EXPORT_SYMBOL_GPL(xenbus_bind_evtchn);
255
256
257 int xenbus_free_evtchn(struct xenbus_device *dev, int port)
258 {
259         struct evtchn_close close;
260         int err;
261
262         close.port = port;
263
264         err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
265         if (err)
266                 xenbus_dev_error(dev, err, "freeing event channel %d", port);
267
268         return err;
269 }
270
271
272 enum xenbus_state xenbus_read_driver_state(const char *path)
273 {
274         enum xenbus_state result;
275         int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
276         if (err)
277                 result = XenbusStateClosed;
278
279         return result;
280 }
281 EXPORT_SYMBOL_GPL(xenbus_read_driver_state);