~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/xen/xenbus/xenbus_comms.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 program is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU General Public License version 2
 
10
 * as published by the Free Software Foundation; or, when distributed
 
11
 * separately from the Linux kernel or incorporated into other
 
12
 * software packages, subject to the following license:
 
13
 *
 
14
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 
15
 * of this source file (the "Software"), to deal in the Software without
 
16
 * restriction, including without limitation the rights to use, copy, modify,
 
17
 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
 
18
 * and to permit persons to whom the Software is furnished to do so, subject to
 
19
 * the following conditions:
 
20
 *
 
21
 * The above copyright notice and this permission notice shall be included in
 
22
 * all copies or substantial portions of the Software.
 
23
 *
 
24
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
25
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
26
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
27
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
28
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
29
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 
30
 * IN THE SOFTWARE.
 
31
 */
 
32
 
 
33
#include <linux/wait.h>
 
34
#include <linux/interrupt.h>
 
35
#include <linux/sched.h>
 
36
#include <linux/err.h>
 
37
#include <xen/xenbus.h>
 
38
#include <asm/xen/hypervisor.h>
 
39
#include <xen/events.h>
 
40
#include <xen/page.h>
 
41
#include "xenbus_comms.h"
 
42
 
 
43
static int xenbus_irq;
 
44
 
 
45
static DECLARE_WORK(probe_work, xenbus_probe);
 
46
 
 
47
static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
 
48
 
 
49
static irqreturn_t wake_waiting(int irq, void *unused)
 
50
{
 
51
        if (unlikely(xenstored_ready == 0)) {
 
52
                xenstored_ready = 1;
 
53
                schedule_work(&probe_work);
 
54
        }
 
55
 
 
56
        wake_up(&xb_waitq);
 
57
        return IRQ_HANDLED;
 
58
}
 
59
 
 
60
static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
 
61
{
 
62
        return ((prod - cons) <= XENSTORE_RING_SIZE);
 
63
}
 
64
 
 
65
static void *get_output_chunk(XENSTORE_RING_IDX cons,
 
66
                              XENSTORE_RING_IDX prod,
 
67
                              char *buf, uint32_t *len)
 
68
{
 
69
        *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
 
70
        if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
 
71
                *len = XENSTORE_RING_SIZE - (prod - cons);
 
72
        return buf + MASK_XENSTORE_IDX(prod);
 
73
}
 
74
 
 
75
static const void *get_input_chunk(XENSTORE_RING_IDX cons,
 
76
                                   XENSTORE_RING_IDX prod,
 
77
                                   const char *buf, uint32_t *len)
 
78
{
 
79
        *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
 
80
        if ((prod - cons) < *len)
 
81
                *len = prod - cons;
 
82
        return buf + MASK_XENSTORE_IDX(cons);
 
83
}
 
84
 
 
85
/**
 
86
 * xb_write - low level write
 
87
 * @data: buffer to send
 
88
 * @len: length of buffer
 
89
 *
 
90
 * Returns 0 on success, error otherwise.
 
91
 */
 
92
int xb_write(const void *data, unsigned len)
 
93
{
 
94
        struct xenstore_domain_interface *intf = xen_store_interface;
 
95
        XENSTORE_RING_IDX cons, prod;
 
96
        int rc;
 
97
 
 
98
        while (len != 0) {
 
99
                void *dst;
 
100
                unsigned int avail;
 
101
 
 
102
                rc = wait_event_interruptible(
 
103
                        xb_waitq,
 
104
                        (intf->req_prod - intf->req_cons) !=
 
105
                        XENSTORE_RING_SIZE);
 
106
                if (rc < 0)
 
107
                        return rc;
 
108
 
 
109
                /* Read indexes, then verify. */
 
110
                cons = intf->req_cons;
 
111
                prod = intf->req_prod;
 
112
                if (!check_indexes(cons, prod)) {
 
113
                        intf->req_cons = intf->req_prod = 0;
 
114
                        return -EIO;
 
115
                }
 
116
 
 
117
                dst = get_output_chunk(cons, prod, intf->req, &avail);
 
118
                if (avail == 0)
 
119
                        continue;
 
120
                if (avail > len)
 
121
                        avail = len;
 
122
 
 
123
                /* Must write data /after/ reading the consumer index. */
 
124
                mb();
 
125
 
 
126
                memcpy(dst, data, avail);
 
127
                data += avail;
 
128
                len -= avail;
 
129
 
 
130
                /* Other side must not see new producer until data is there. */
 
131
                wmb();
 
132
                intf->req_prod += avail;
 
133
 
 
134
                /* Implies mb(): other side will see the updated producer. */
 
135
                notify_remote_via_evtchn(xen_store_evtchn);
 
136
        }
 
137
 
 
138
        return 0;
 
139
}
 
140
 
 
141
int xb_data_to_read(void)
 
142
{
 
143
        struct xenstore_domain_interface *intf = xen_store_interface;
 
144
        return (intf->rsp_cons != intf->rsp_prod);
 
145
}
 
146
 
 
147
int xb_wait_for_data_to_read(void)
 
148
{
 
149
        return wait_event_interruptible(xb_waitq, xb_data_to_read());
 
150
}
 
151
 
 
152
int xb_read(void *data, unsigned len)
 
153
{
 
154
        struct xenstore_domain_interface *intf = xen_store_interface;
 
155
        XENSTORE_RING_IDX cons, prod;
 
156
        int rc;
 
157
 
 
158
        while (len != 0) {
 
159
                unsigned int avail;
 
160
                const char *src;
 
161
 
 
162
                rc = xb_wait_for_data_to_read();
 
163
                if (rc < 0)
 
164
                        return rc;
 
165
 
 
166
                /* Read indexes, then verify. */
 
167
                cons = intf->rsp_cons;
 
168
                prod = intf->rsp_prod;
 
169
                if (!check_indexes(cons, prod)) {
 
170
                        intf->rsp_cons = intf->rsp_prod = 0;
 
171
                        return -EIO;
 
172
                }
 
173
 
 
174
                src = get_input_chunk(cons, prod, intf->rsp, &avail);
 
175
                if (avail == 0)
 
176
                        continue;
 
177
                if (avail > len)
 
178
                        avail = len;
 
179
 
 
180
                /* Must read data /after/ reading the producer index. */
 
181
                rmb();
 
182
 
 
183
                memcpy(data, src, avail);
 
184
                data += avail;
 
185
                len -= avail;
 
186
 
 
187
                /* Other side must not see free space until we've copied out */
 
188
                mb();
 
189
                intf->rsp_cons += avail;
 
190
 
 
191
                pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
 
192
 
 
193
                /* Implies mb(): other side will see the updated consumer. */
 
194
                notify_remote_via_evtchn(xen_store_evtchn);
 
195
        }
 
196
 
 
197
        return 0;
 
198
}
 
199
 
 
200
/**
 
201
 * xb_init_comms - Set up interrupt handler off store event channel.
 
202
 */
 
203
int xb_init_comms(void)
 
204
{
 
205
        struct xenstore_domain_interface *intf = xen_store_interface;
 
206
 
 
207
        if (intf->req_prod != intf->req_cons)
 
208
                printk(KERN_ERR "XENBUS request ring is not quiescent "
 
209
                       "(%08x:%08x)!\n", intf->req_cons, intf->req_prod);
 
210
 
 
211
        if (intf->rsp_prod != intf->rsp_cons) {
 
212
                printk(KERN_WARNING "XENBUS response ring is not quiescent "
 
213
                       "(%08x:%08x): fixing up\n",
 
214
                       intf->rsp_cons, intf->rsp_prod);
 
215
                /* breaks kdump */
 
216
                if (!reset_devices)
 
217
                        intf->rsp_cons = intf->rsp_prod;
 
218
        }
 
219
 
 
220
        if (xenbus_irq) {
 
221
                /* Already have an irq; assume we're resuming */
 
222
                rebind_evtchn_irq(xen_store_evtchn, xenbus_irq);
 
223
        } else {
 
224
                int err;
 
225
                err = bind_evtchn_to_irqhandler(xen_store_evtchn, wake_waiting,
 
226
                                                0, "xenbus", &xb_waitq);
 
227
                if (err <= 0) {
 
228
                        printk(KERN_ERR "XENBUS request irq failed %i\n", err);
 
229
                        return err;
 
230
                }
 
231
 
 
232
                xenbus_irq = err;
 
233
        }
 
234
 
 
235
        return 0;
 
236
}