- 2.6.17 port work build breaks, but the patch set is relativly stable
[linux-flexiantxendom0-3.2.10.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, XenbusState 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_NULL, dev->nodename, "state", "%d",
110                            &current_state);
111         if (err != 1)
112                 return 0;
113
114         err = xenbus_printf(XBT_NULL, 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_NULL, 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         evtchn_op_t op = {
218                 .cmd = EVTCHNOP_alloc_unbound,
219                 .u.alloc_unbound.dom = DOMID_SELF,
220                 .u.alloc_unbound.remote_dom = dev->otherend_id
221         };
222         int err = HYPERVISOR_event_channel_op(&op);
223         if (err)
224                 xenbus_dev_fatal(dev, err, "allocating event channel");
225         else
226                 *port = op.u.alloc_unbound.port;
227         return err;
228 }
229 EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn);
230
231
232 int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port)
233 {
234         evtchn_op_t op = {
235                 .cmd = EVTCHNOP_bind_interdomain,
236                 .u.bind_interdomain.remote_dom = dev->otherend_id,
237                 .u.bind_interdomain.remote_port = remote_port,
238         };
239         int err = HYPERVISOR_event_channel_op(&op);
240         if (err)
241                 xenbus_dev_fatal(dev, err,
242                                  "binding to event channel %d from domain %d",
243                                  remote_port, dev->otherend_id);
244         else
245                 *port = op.u.bind_interdomain.local_port;
246         return err;
247 }
248 EXPORT_SYMBOL_GPL(xenbus_bind_evtchn);
249
250
251 int xenbus_free_evtchn(struct xenbus_device *dev, int port)
252 {
253         evtchn_op_t op = {
254                 .cmd = EVTCHNOP_close,
255                 .u.close.port = port,
256         };
257         int err = HYPERVISOR_event_channel_op(&op);
258         if (err)
259                 xenbus_dev_error(dev, err, "freeing event channel %d", port);
260         return err;
261 }
262
263
264 XenbusState xenbus_read_driver_state(const char *path)
265 {
266         XenbusState result;
267         int err = xenbus_gather(XBT_NULL, path, "state", "%d", &result, NULL);
268         if (err)
269                 result = XenbusStateClosed;
270
271         return result;
272 }
273 EXPORT_SYMBOL_GPL(xenbus_read_driver_state);
274
275
276 /*
277  * Local variables:
278  *  c-file-style: "linux"
279  *  indent-tabs-mode: t
280  *  c-indent-level: 8
281  *  c-basic-offset: 8
282  *  tab-width: 8
283  * End:
284  */