xref: /OK3568_Linux_fs/kernel/drivers/xen/xenbus/xenbus_comms.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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