xenbus_client.c revision 1.1 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 file may be distributed separately from the Linux kernel, or
9 * incorporated into other software packages, subject to the following license:
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this source file (the "Software"), to deal in the Software without
13 * restriction, including without limitation the rights to use, copy, modify,
14 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
15 * and to permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 * IN THE SOFTWARE.
28 */
29
30
31 #if 0
32 #define DPRINTK(fmt, args...) \
33 printk("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
34 #else
35 #define DPRINTK(fmt, args...) ((void)0)
36 #endif
37
38
39 #include <asm-xen/evtchn.h>
40 #include <asm-xen/gnttab.h>
41 #include <asm-xen/xenbus.h>
42
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(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 =
74 kmalloc(strlen(path) + 1 + strlen(path2) + 1, GFP_KERNEL);
75 if (!state) {
76 xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
77 return -ENOMEM;
78 }
79 strcpy(state, path);
80 strcat(state, "/");
81 strcat(state, path2);
82
83 err = xenbus_watch_path(dev, state, watch, callback);
84
85 if (err) {
86 kfree(state);
87 }
88 return err;
89 }
90 EXPORT_SYMBOL(xenbus_watch_path2);
91
92
93 int xenbus_switch_state(struct xenbus_device *dev,
94 struct xenbus_transaction *xbt,
95 XenbusState state)
96 {
97 /* We check whether the state is currently set to the given value, and
98 if not, then the state is set. We don't want to unconditionally
99 write the given state, because we don't want to fire watches
100 unnecessarily. Furthermore, if the node has gone, we don't write
101 to it, as the device will be tearing down, and we don't want to
102 resurrect that directory.
103 */
104
105 int current_state;
106
107 int err = xenbus_scanf(xbt, dev->nodename, "state", "%d",
108 ¤t_state);
109 if ((err == 1 && (XenbusState)current_state == state) ||
110 err == -ENOENT)
111 return 0;
112
113 err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
114 if (err) {
115 xenbus_dev_fatal(dev, err, "writing new state");
116 return err;
117 }
118 return 0;
119 }
120 EXPORT_SYMBOL(xenbus_switch_state);
121
122
123 /**
124 * Return the path to the error node for the given device, or NULL on failure.
125 * If the value returned is non-NULL, then it is the caller's to kfree.
126 */
127 static char *error_path(struct xenbus_device *dev)
128 {
129 char *path_buffer = kmalloc(strlen("error/") + strlen(dev->nodename) +
130 1, GFP_KERNEL);
131 if (path_buffer == NULL) {
132 return NULL;
133 }
134
135 strcpy(path_buffer, "error/");
136 strcpy(path_buffer + strlen("error/"), dev->nodename);
137
138 return path_buffer;
139 }
140
141
142 void _dev_error(struct xenbus_device *dev, int err, const char *fmt,
143 va_list ap)
144 {
145 int ret;
146 unsigned int len;
147 char *printf_buffer = NULL, *path_buffer = NULL;
148
149 #define PRINTF_BUFFER_SIZE 4096
150 printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
151 if (printf_buffer == NULL)
152 goto fail;
153
154 len = sprintf(printf_buffer, "%i ", -err);
155 ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
156
157 BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
158 dev->has_error = 1;
159
160 path_buffer = error_path(dev);
161
162 if (path_buffer == NULL) {
163 printk("xenbus: failed to write error node for %s (%s)\n",
164 dev->nodename, printf_buffer);
165 goto fail;
166 }
167
168 if (xenbus_write(NULL, path_buffer, "error", printf_buffer) != 0) {
169 printk("xenbus: failed to write error node for %s (%s)\n",
170 dev->nodename, printf_buffer);
171 goto fail;
172 }
173
174 fail:
175 if (printf_buffer)
176 kfree(printf_buffer);
177 if (path_buffer)
178 kfree(path_buffer);
179 }
180
181
182 void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
183 ...)
184 {
185 va_list ap;
186
187 va_start(ap, fmt);
188 _dev_error(dev, err, fmt, ap);
189 va_end(ap);
190 }
191 EXPORT_SYMBOL(xenbus_dev_error);
192
193
194 void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
195 ...)
196 {
197 va_list ap;
198
199 va_start(ap, fmt);
200 _dev_error(dev, err, fmt, ap);
201 va_end(ap);
202
203 xenbus_switch_state(dev, NULL, XenbusStateClosing);
204 }
205 EXPORT_SYMBOL(xenbus_dev_fatal);
206
207
208 int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn)
209 {
210 int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0);
211 if (err < 0)
212 xenbus_dev_fatal(dev, err, "granting access to ring page");
213 return err;
214 }
215 EXPORT_SYMBOL(xenbus_grant_ring);
216
217
218 int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
219 {
220 evtchn_op_t op = {
221 .cmd = EVTCHNOP_alloc_unbound,
222 .u.alloc_unbound.dom = DOMID_SELF,
223 .u.alloc_unbound.remote_dom = dev->otherend_id };
224
225 int err = HYPERVISOR_event_channel_op(&op);
226 if (err)
227 xenbus_dev_fatal(dev, err, "allocating event channel");
228 else
229 *port = op.u.alloc_unbound.port;
230 return err;
231 }
232 EXPORT_SYMBOL(xenbus_alloc_evtchn);
233
234
235 XenbusState xenbus_read_driver_state(const char *path)
236 {
237 XenbusState result;
238
239 int err = xenbus_gather(NULL, path, "state", "%d", &result, NULL);
240 if (err)
241 result = XenbusStateClosed;
242
243 return result;
244 }
245 EXPORT_SYMBOL(xenbus_read_driver_state);
246
247
248 /*
249 * Local variables:
250 * c-file-style: "linux"
251 * indent-tabs-mode: t
252 * c-indent-level: 8
253 * c-basic-offset: 8
254 * tab-width: 8
255 * End:
256 */
257