ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c @ 7800:5aad7e145e50

If /sbin/ isn't in the path, udev rules will erroneously not get
installed.

Signed-off-by: Nivedita Singhvi <niv@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Mon Nov 14 11:05:34 2005 +0100 (2005-11-14)
parents 0915074c356e
children 8ee7df2c18d1
line source
1 /******************************************************************************
2 * xenbus_comms.c
3 *
4 * Low level code to talks to Xen Store: ringbuffer and event channel.
5 *
6 * Copyright (C) 2005 Rusty Russell, IBM Corporation
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 */
30 #include <asm/hypervisor.h>
31 #include <asm-xen/evtchn.h>
32 #include <linux/wait.h>
33 #include <linux/interrupt.h>
34 #include <linux/sched.h>
35 #include <linux/err.h>
36 #include <asm-xen/xenbus.h>
37 #include "xenbus_comms.h"
39 static int xenbus_irq;
41 extern void xenbus_probe(void *);
42 extern int xenstored_ready;
43 static DECLARE_WORK(probe_work, xenbus_probe, NULL);
45 DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
47 static inline struct xenstore_domain_interface *xenstore_domain_interface(void)
48 {
49 return mfn_to_virt(xen_start_info->store_mfn);
50 }
52 static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
53 {
54 if (unlikely(xenstored_ready == 0)) {
55 xenstored_ready = 1;
56 schedule_work(&probe_work);
57 }
59 wake_up(&xb_waitq);
60 return IRQ_HANDLED;
61 }
63 static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
64 {
65 return ((prod - cons) <= XENSTORE_RING_SIZE);
66 }
68 static void *get_output_chunk(XENSTORE_RING_IDX cons,
69 XENSTORE_RING_IDX prod,
70 char *buf, uint32_t *len)
71 {
72 *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
73 if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
74 *len = XENSTORE_RING_SIZE - (prod - cons);
75 return buf + MASK_XENSTORE_IDX(prod);
76 }
78 static const void *get_input_chunk(XENSTORE_RING_IDX cons,
79 XENSTORE_RING_IDX prod,
80 const char *buf, uint32_t *len)
81 {
82 *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
83 if ((prod - cons) < *len)
84 *len = prod - cons;
85 return buf + MASK_XENSTORE_IDX(cons);
86 }
88 int xb_write(const void *data, unsigned len)
89 {
90 struct xenstore_domain_interface *intf = xenstore_domain_interface();
91 XENSTORE_RING_IDX cons, prod;
93 while (len != 0) {
94 void *dst;
95 unsigned int avail;
97 wait_event_interruptible(xb_waitq,
98 (intf->req_prod - intf->req_cons) !=
99 XENSTORE_RING_SIZE);
101 /* Read indexes, then verify. */
102 cons = intf->req_cons;
103 prod = intf->req_prod;
104 mb();
105 if (!check_indexes(cons, prod))
106 return -EIO;
108 dst = get_output_chunk(cons, prod, intf->req, &avail);
109 if (avail == 0)
110 continue;
111 if (avail > len)
112 avail = len;
114 memcpy(dst, data, avail);
115 data += avail;
116 len -= avail;
118 /* Other side must not see new header until data is there. */
119 wmb();
120 intf->req_prod += avail;
122 /* This implies mb() before other side sees interrupt. */
123 notify_remote_via_evtchn(xen_start_info->store_evtchn);
124 }
126 return 0;
127 }
129 int xb_read(void *data, unsigned len)
130 {
131 struct xenstore_domain_interface *intf = xenstore_domain_interface();
132 XENSTORE_RING_IDX cons, prod;
134 while (len != 0) {
135 unsigned int avail;
136 const char *src;
138 wait_event_interruptible(xb_waitq,
139 intf->rsp_cons != intf->rsp_prod);
141 /* Read indexes, then verify. */
142 cons = intf->rsp_cons;
143 prod = intf->rsp_prod;
144 mb();
145 if (!check_indexes(cons, prod))
146 return -EIO;
148 src = get_input_chunk(cons, prod, intf->rsp, &avail);
149 if (avail == 0)
150 continue;
151 if (avail > len)
152 avail = len;
154 /* We must read header before we read data. */
155 rmb();
157 memcpy(data, src, avail);
158 data += avail;
159 len -= avail;
161 /* Other side must not see free space until we've copied out */
162 mb();
163 intf->rsp_cons += avail;
165 pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
167 /* Implies mb(): they will see new header. */
168 notify_remote_via_evtchn(xen_start_info->store_evtchn);
169 }
171 return 0;
172 }
174 /* Set up interrupt handler off store event channel. */
175 int xb_init_comms(void)
176 {
177 int err;
179 if (xenbus_irq)
180 unbind_from_irqhandler(xenbus_irq, &xb_waitq);
182 err = bind_evtchn_to_irqhandler(
183 xen_start_info->store_evtchn, wake_waiting,
184 0, "xenbus", &xb_waitq);
185 if (err <= 0) {
186 printk(KERN_ERR "XENBUS request irq failed %i\n", err);
187 return err;
188 }
190 xenbus_irq = err;
192 return 0;
193 }
195 /*
196 * Local variables:
197 * c-file-style: "linux"
198 * indent-tabs-mode: t
199 * c-indent-level: 8
200 * c-basic-offset: 8
201 * tab-width: 8
202 * End:
203 */