1*4882a593Smuzhiyun /******************************************************************************
2*4882a593Smuzhiyun * xenbus_comms.c
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Low level code to talks to Xen Store: ringbuffer and event channel.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 2005 Rusty Russell, IBM Corporation
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or
9*4882a593Smuzhiyun * modify it under the terms of the GNU General Public License version 2
10*4882a593Smuzhiyun * as published by the Free Software Foundation; or, when distributed
11*4882a593Smuzhiyun * separately from the Linux kernel or incorporated into other
12*4882a593Smuzhiyun * software packages, subject to the following license:
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a copy
15*4882a593Smuzhiyun * of this source file (the "Software"), to deal in the Software without
16*4882a593Smuzhiyun * restriction, including without limitation the rights to use, copy, modify,
17*4882a593Smuzhiyun * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18*4882a593Smuzhiyun * and to permit persons to whom the Software is furnished to do so, subject to
19*4882a593Smuzhiyun * the following conditions:
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun * The above copyright notice and this permission notice shall be included in
22*4882a593Smuzhiyun * all copies or substantial portions of the Software.
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27*4882a593Smuzhiyun * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28*4882a593Smuzhiyun * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29*4882a593Smuzhiyun * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30*4882a593Smuzhiyun * IN THE SOFTWARE.
31*4882a593Smuzhiyun */
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #include <linux/wait.h>
36*4882a593Smuzhiyun #include <linux/interrupt.h>
37*4882a593Smuzhiyun #include <linux/kthread.h>
38*4882a593Smuzhiyun #include <linux/sched.h>
39*4882a593Smuzhiyun #include <linux/err.h>
40*4882a593Smuzhiyun #include <xen/xenbus.h>
41*4882a593Smuzhiyun #include <asm/xen/hypervisor.h>
42*4882a593Smuzhiyun #include <xen/events.h>
43*4882a593Smuzhiyun #include <xen/page.h>
44*4882a593Smuzhiyun #include "xenbus.h"
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* A list of replies. Currently only one will ever be outstanding. */
47*4882a593Smuzhiyun LIST_HEAD(xs_reply_list);
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /* A list of write requests. */
50*4882a593Smuzhiyun LIST_HEAD(xb_write_list);
51*4882a593Smuzhiyun DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
52*4882a593Smuzhiyun DEFINE_MUTEX(xb_write_mutex);
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /* Protect xenbus reader thread against save/restore. */
55*4882a593Smuzhiyun DEFINE_MUTEX(xs_response_mutex);
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun static int xenbus_irq;
58*4882a593Smuzhiyun static struct task_struct *xenbus_task;
59*4882a593Smuzhiyun
wake_waiting(int irq,void * unused)60*4882a593Smuzhiyun static irqreturn_t wake_waiting(int irq, void *unused)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun wake_up(&xb_waitq);
63*4882a593Smuzhiyun return IRQ_HANDLED;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
check_indexes(XENSTORE_RING_IDX cons,XENSTORE_RING_IDX prod)66*4882a593Smuzhiyun static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun return ((prod - cons) <= XENSTORE_RING_SIZE);
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
get_output_chunk(XENSTORE_RING_IDX cons,XENSTORE_RING_IDX prod,char * buf,uint32_t * len)71*4882a593Smuzhiyun static void *get_output_chunk(XENSTORE_RING_IDX cons,
72*4882a593Smuzhiyun XENSTORE_RING_IDX prod,
73*4882a593Smuzhiyun char *buf, uint32_t *len)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
76*4882a593Smuzhiyun if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
77*4882a593Smuzhiyun *len = XENSTORE_RING_SIZE - (prod - cons);
78*4882a593Smuzhiyun return buf + MASK_XENSTORE_IDX(prod);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
get_input_chunk(XENSTORE_RING_IDX cons,XENSTORE_RING_IDX prod,const char * buf,uint32_t * len)81*4882a593Smuzhiyun static const void *get_input_chunk(XENSTORE_RING_IDX cons,
82*4882a593Smuzhiyun XENSTORE_RING_IDX prod,
83*4882a593Smuzhiyun const char *buf, uint32_t *len)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
86*4882a593Smuzhiyun if ((prod - cons) < *len)
87*4882a593Smuzhiyun *len = prod - cons;
88*4882a593Smuzhiyun return buf + MASK_XENSTORE_IDX(cons);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
xb_data_to_write(void)91*4882a593Smuzhiyun static int xb_data_to_write(void)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun struct xenstore_domain_interface *intf = xen_store_interface;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun return (intf->req_prod - intf->req_cons) != XENSTORE_RING_SIZE &&
96*4882a593Smuzhiyun !list_empty(&xb_write_list);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /**
100*4882a593Smuzhiyun * xb_write - low level write
101*4882a593Smuzhiyun * @data: buffer to send
102*4882a593Smuzhiyun * @len: length of buffer
103*4882a593Smuzhiyun *
104*4882a593Smuzhiyun * Returns number of bytes written or -err.
105*4882a593Smuzhiyun */
xb_write(const void * data,unsigned int len)106*4882a593Smuzhiyun static int xb_write(const void *data, unsigned int len)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun struct xenstore_domain_interface *intf = xen_store_interface;
109*4882a593Smuzhiyun XENSTORE_RING_IDX cons, prod;
110*4882a593Smuzhiyun unsigned int bytes = 0;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun while (len != 0) {
113*4882a593Smuzhiyun void *dst;
114*4882a593Smuzhiyun unsigned int avail;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun /* Read indexes, then verify. */
117*4882a593Smuzhiyun cons = intf->req_cons;
118*4882a593Smuzhiyun prod = intf->req_prod;
119*4882a593Smuzhiyun if (!check_indexes(cons, prod)) {
120*4882a593Smuzhiyun intf->req_cons = intf->req_prod = 0;
121*4882a593Smuzhiyun return -EIO;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun if (!xb_data_to_write())
124*4882a593Smuzhiyun return bytes;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun /* Must write data /after/ reading the consumer index. */
127*4882a593Smuzhiyun virt_mb();
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun dst = get_output_chunk(cons, prod, intf->req, &avail);
130*4882a593Smuzhiyun if (avail == 0)
131*4882a593Smuzhiyun continue;
132*4882a593Smuzhiyun if (avail > len)
133*4882a593Smuzhiyun avail = len;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun memcpy(dst, data, avail);
136*4882a593Smuzhiyun data += avail;
137*4882a593Smuzhiyun len -= avail;
138*4882a593Smuzhiyun bytes += avail;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /* Other side must not see new producer until data is there. */
141*4882a593Smuzhiyun virt_wmb();
142*4882a593Smuzhiyun intf->req_prod += avail;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun /* Implies mb(): other side will see the updated producer. */
145*4882a593Smuzhiyun if (prod <= intf->req_cons)
146*4882a593Smuzhiyun notify_remote_via_evtchn(xen_store_evtchn);
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun return bytes;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
xb_data_to_read(void)152*4882a593Smuzhiyun static int xb_data_to_read(void)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun struct xenstore_domain_interface *intf = xen_store_interface;
155*4882a593Smuzhiyun return (intf->rsp_cons != intf->rsp_prod);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
xb_read(void * data,unsigned int len)158*4882a593Smuzhiyun static int xb_read(void *data, unsigned int len)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun struct xenstore_domain_interface *intf = xen_store_interface;
161*4882a593Smuzhiyun XENSTORE_RING_IDX cons, prod;
162*4882a593Smuzhiyun unsigned int bytes = 0;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun while (len != 0) {
165*4882a593Smuzhiyun unsigned int avail;
166*4882a593Smuzhiyun const char *src;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun /* Read indexes, then verify. */
169*4882a593Smuzhiyun cons = intf->rsp_cons;
170*4882a593Smuzhiyun prod = intf->rsp_prod;
171*4882a593Smuzhiyun if (cons == prod)
172*4882a593Smuzhiyun return bytes;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun if (!check_indexes(cons, prod)) {
175*4882a593Smuzhiyun intf->rsp_cons = intf->rsp_prod = 0;
176*4882a593Smuzhiyun return -EIO;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun src = get_input_chunk(cons, prod, intf->rsp, &avail);
180*4882a593Smuzhiyun if (avail == 0)
181*4882a593Smuzhiyun continue;
182*4882a593Smuzhiyun if (avail > len)
183*4882a593Smuzhiyun avail = len;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /* Must read data /after/ reading the producer index. */
186*4882a593Smuzhiyun virt_rmb();
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun memcpy(data, src, avail);
189*4882a593Smuzhiyun data += avail;
190*4882a593Smuzhiyun len -= avail;
191*4882a593Smuzhiyun bytes += avail;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /* Other side must not see free space until we've copied out */
194*4882a593Smuzhiyun virt_mb();
195*4882a593Smuzhiyun intf->rsp_cons += avail;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /* Implies mb(): other side will see the updated consumer. */
198*4882a593Smuzhiyun if (intf->rsp_prod - cons >= XENSTORE_RING_SIZE)
199*4882a593Smuzhiyun notify_remote_via_evtchn(xen_store_evtchn);
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun return bytes;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
process_msg(void)205*4882a593Smuzhiyun static int process_msg(void)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun static struct {
208*4882a593Smuzhiyun struct xsd_sockmsg msg;
209*4882a593Smuzhiyun char *body;
210*4882a593Smuzhiyun union {
211*4882a593Smuzhiyun void *alloc;
212*4882a593Smuzhiyun struct xs_watch_event *watch;
213*4882a593Smuzhiyun };
214*4882a593Smuzhiyun bool in_msg;
215*4882a593Smuzhiyun bool in_hdr;
216*4882a593Smuzhiyun unsigned int read;
217*4882a593Smuzhiyun } state;
218*4882a593Smuzhiyun struct xb_req_data *req;
219*4882a593Smuzhiyun int err;
220*4882a593Smuzhiyun unsigned int len;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun if (!state.in_msg) {
223*4882a593Smuzhiyun state.in_msg = true;
224*4882a593Smuzhiyun state.in_hdr = true;
225*4882a593Smuzhiyun state.read = 0;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun /*
228*4882a593Smuzhiyun * We must disallow save/restore while reading a message.
229*4882a593Smuzhiyun * A partial read across s/r leaves us out of sync with
230*4882a593Smuzhiyun * xenstored.
231*4882a593Smuzhiyun * xs_response_mutex is locked as long as we are processing one
232*4882a593Smuzhiyun * message. state.in_msg will be true as long as we are holding
233*4882a593Smuzhiyun * the lock here.
234*4882a593Smuzhiyun */
235*4882a593Smuzhiyun mutex_lock(&xs_response_mutex);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun if (!xb_data_to_read()) {
238*4882a593Smuzhiyun /* We raced with save/restore: pending data 'gone'. */
239*4882a593Smuzhiyun mutex_unlock(&xs_response_mutex);
240*4882a593Smuzhiyun state.in_msg = false;
241*4882a593Smuzhiyun return 0;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun if (state.in_hdr) {
246*4882a593Smuzhiyun if (state.read != sizeof(state.msg)) {
247*4882a593Smuzhiyun err = xb_read((void *)&state.msg + state.read,
248*4882a593Smuzhiyun sizeof(state.msg) - state.read);
249*4882a593Smuzhiyun if (err < 0)
250*4882a593Smuzhiyun goto out;
251*4882a593Smuzhiyun state.read += err;
252*4882a593Smuzhiyun if (state.read != sizeof(state.msg))
253*4882a593Smuzhiyun return 0;
254*4882a593Smuzhiyun if (state.msg.len > XENSTORE_PAYLOAD_MAX) {
255*4882a593Smuzhiyun err = -EINVAL;
256*4882a593Smuzhiyun goto out;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun len = state.msg.len + 1;
261*4882a593Smuzhiyun if (state.msg.type == XS_WATCH_EVENT)
262*4882a593Smuzhiyun len += sizeof(*state.watch);
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun state.alloc = kmalloc(len, GFP_NOIO | __GFP_HIGH);
265*4882a593Smuzhiyun if (!state.alloc)
266*4882a593Smuzhiyun return -ENOMEM;
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun if (state.msg.type == XS_WATCH_EVENT)
269*4882a593Smuzhiyun state.body = state.watch->body;
270*4882a593Smuzhiyun else
271*4882a593Smuzhiyun state.body = state.alloc;
272*4882a593Smuzhiyun state.in_hdr = false;
273*4882a593Smuzhiyun state.read = 0;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun err = xb_read(state.body + state.read, state.msg.len - state.read);
277*4882a593Smuzhiyun if (err < 0)
278*4882a593Smuzhiyun goto out;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun state.read += err;
281*4882a593Smuzhiyun if (state.read != state.msg.len)
282*4882a593Smuzhiyun return 0;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun state.body[state.msg.len] = '\0';
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (state.msg.type == XS_WATCH_EVENT) {
287*4882a593Smuzhiyun state.watch->len = state.msg.len;
288*4882a593Smuzhiyun err = xs_watch_msg(state.watch);
289*4882a593Smuzhiyun } else {
290*4882a593Smuzhiyun err = -ENOENT;
291*4882a593Smuzhiyun mutex_lock(&xb_write_mutex);
292*4882a593Smuzhiyun list_for_each_entry(req, &xs_reply_list, list) {
293*4882a593Smuzhiyun if (req->msg.req_id == state.msg.req_id) {
294*4882a593Smuzhiyun list_del(&req->list);
295*4882a593Smuzhiyun err = 0;
296*4882a593Smuzhiyun break;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun mutex_unlock(&xb_write_mutex);
300*4882a593Smuzhiyun if (err)
301*4882a593Smuzhiyun goto out;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun if (req->state == xb_req_state_wait_reply) {
304*4882a593Smuzhiyun req->msg.req_id = req->caller_req_id;
305*4882a593Smuzhiyun req->msg.type = state.msg.type;
306*4882a593Smuzhiyun req->msg.len = state.msg.len;
307*4882a593Smuzhiyun req->body = state.body;
308*4882a593Smuzhiyun /* write body, then update state */
309*4882a593Smuzhiyun virt_wmb();
310*4882a593Smuzhiyun req->state = xb_req_state_got_reply;
311*4882a593Smuzhiyun req->cb(req);
312*4882a593Smuzhiyun } else
313*4882a593Smuzhiyun kfree(req);
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun mutex_unlock(&xs_response_mutex);
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun state.in_msg = false;
319*4882a593Smuzhiyun state.alloc = NULL;
320*4882a593Smuzhiyun return err;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun out:
323*4882a593Smuzhiyun mutex_unlock(&xs_response_mutex);
324*4882a593Smuzhiyun state.in_msg = false;
325*4882a593Smuzhiyun kfree(state.alloc);
326*4882a593Smuzhiyun state.alloc = NULL;
327*4882a593Smuzhiyun return err;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
process_writes(void)330*4882a593Smuzhiyun static int process_writes(void)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun static struct {
333*4882a593Smuzhiyun struct xb_req_data *req;
334*4882a593Smuzhiyun int idx;
335*4882a593Smuzhiyun unsigned int written;
336*4882a593Smuzhiyun } state;
337*4882a593Smuzhiyun void *base;
338*4882a593Smuzhiyun unsigned int len;
339*4882a593Smuzhiyun int err = 0;
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun if (!xb_data_to_write())
342*4882a593Smuzhiyun return 0;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun mutex_lock(&xb_write_mutex);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun if (!state.req) {
347*4882a593Smuzhiyun state.req = list_first_entry(&xb_write_list,
348*4882a593Smuzhiyun struct xb_req_data, list);
349*4882a593Smuzhiyun state.idx = -1;
350*4882a593Smuzhiyun state.written = 0;
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun if (state.req->state == xb_req_state_aborted)
354*4882a593Smuzhiyun goto out_err;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun while (state.idx < state.req->num_vecs) {
357*4882a593Smuzhiyun if (state.idx < 0) {
358*4882a593Smuzhiyun base = &state.req->msg;
359*4882a593Smuzhiyun len = sizeof(state.req->msg);
360*4882a593Smuzhiyun } else {
361*4882a593Smuzhiyun base = state.req->vec[state.idx].iov_base;
362*4882a593Smuzhiyun len = state.req->vec[state.idx].iov_len;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun err = xb_write(base + state.written, len - state.written);
365*4882a593Smuzhiyun if (err < 0)
366*4882a593Smuzhiyun goto out_err;
367*4882a593Smuzhiyun state.written += err;
368*4882a593Smuzhiyun if (state.written != len)
369*4882a593Smuzhiyun goto out;
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun state.idx++;
372*4882a593Smuzhiyun state.written = 0;
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun list_del(&state.req->list);
376*4882a593Smuzhiyun state.req->state = xb_req_state_wait_reply;
377*4882a593Smuzhiyun list_add_tail(&state.req->list, &xs_reply_list);
378*4882a593Smuzhiyun state.req = NULL;
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun out:
381*4882a593Smuzhiyun mutex_unlock(&xb_write_mutex);
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun return 0;
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun out_err:
386*4882a593Smuzhiyun state.req->msg.type = XS_ERROR;
387*4882a593Smuzhiyun state.req->err = err;
388*4882a593Smuzhiyun list_del(&state.req->list);
389*4882a593Smuzhiyun if (state.req->state == xb_req_state_aborted)
390*4882a593Smuzhiyun kfree(state.req);
391*4882a593Smuzhiyun else {
392*4882a593Smuzhiyun /* write err, then update state */
393*4882a593Smuzhiyun virt_wmb();
394*4882a593Smuzhiyun state.req->state = xb_req_state_got_reply;
395*4882a593Smuzhiyun wake_up(&state.req->wq);
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun mutex_unlock(&xb_write_mutex);
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun state.req = NULL;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun return err;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
xb_thread_work(void)405*4882a593Smuzhiyun static int xb_thread_work(void)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun return xb_data_to_read() || xb_data_to_write();
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
xenbus_thread(void * unused)410*4882a593Smuzhiyun static int xenbus_thread(void *unused)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun int err;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun while (!kthread_should_stop()) {
415*4882a593Smuzhiyun if (wait_event_interruptible(xb_waitq, xb_thread_work()))
416*4882a593Smuzhiyun continue;
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun err = process_msg();
419*4882a593Smuzhiyun if (err == -ENOMEM)
420*4882a593Smuzhiyun schedule();
421*4882a593Smuzhiyun else if (err)
422*4882a593Smuzhiyun pr_warn_ratelimited("error %d while reading message\n",
423*4882a593Smuzhiyun err);
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun err = process_writes();
426*4882a593Smuzhiyun if (err)
427*4882a593Smuzhiyun pr_warn_ratelimited("error %d while writing message\n",
428*4882a593Smuzhiyun err);
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun xenbus_task = NULL;
432*4882a593Smuzhiyun return 0;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun /**
436*4882a593Smuzhiyun * xb_init_comms - Set up interrupt handler off store event channel.
437*4882a593Smuzhiyun */
xb_init_comms(void)438*4882a593Smuzhiyun int xb_init_comms(void)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun struct xenstore_domain_interface *intf = xen_store_interface;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun if (intf->req_prod != intf->req_cons)
443*4882a593Smuzhiyun pr_err("request ring is not quiescent (%08x:%08x)!\n",
444*4882a593Smuzhiyun intf->req_cons, intf->req_prod);
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun if (intf->rsp_prod != intf->rsp_cons) {
447*4882a593Smuzhiyun pr_warn("response ring is not quiescent (%08x:%08x): fixing up\n",
448*4882a593Smuzhiyun intf->rsp_cons, intf->rsp_prod);
449*4882a593Smuzhiyun /* breaks kdump */
450*4882a593Smuzhiyun if (!reset_devices)
451*4882a593Smuzhiyun intf->rsp_cons = intf->rsp_prod;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun if (xenbus_irq) {
455*4882a593Smuzhiyun /* Already have an irq; assume we're resuming */
456*4882a593Smuzhiyun rebind_evtchn_irq(xen_store_evtchn, xenbus_irq);
457*4882a593Smuzhiyun } else {
458*4882a593Smuzhiyun int err;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun err = bind_evtchn_to_irqhandler(xen_store_evtchn, wake_waiting,
461*4882a593Smuzhiyun 0, "xenbus", &xb_waitq);
462*4882a593Smuzhiyun if (err < 0) {
463*4882a593Smuzhiyun pr_err("request irq failed %i\n", err);
464*4882a593Smuzhiyun return err;
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun xenbus_irq = err;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun if (!xenbus_task) {
470*4882a593Smuzhiyun xenbus_task = kthread_run(xenbus_thread, NULL,
471*4882a593Smuzhiyun "xenbus");
472*4882a593Smuzhiyun if (IS_ERR(xenbus_task))
473*4882a593Smuzhiyun return PTR_ERR(xenbus_task);
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun return 0;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun
xb_deinit_comms(void)480*4882a593Smuzhiyun void xb_deinit_comms(void)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun unbind_from_irqhandler(xenbus_irq, &xb_waitq);
483*4882a593Smuzhiyun xenbus_irq = 0;
484*4882a593Smuzhiyun }
485