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