Tue Aug 21 18:45:16 2018 UTC ()


(jdolecek)
diff -r1.84 -r1.85 src/sys/arch/xen/xen/xbd_xenbus.c

cvs diff -r1.84 -r1.85 src/sys/arch/xen/xen/xbd_xenbus.c (switch to unified diff)

--- src/sys/arch/xen/xen/xbd_xenbus.c 2018/08/21 18:31:55 1.84
+++ src/sys/arch/xen/xen/xbd_xenbus.c 2018/08/21 18:45:16 1.85
@@ -1,1023 +1,1029 @@ @@ -1,1023 +1,1029 @@
1/* $NetBSD: xbd_xenbus.c,v 1.84 2018/08/21 18:31:55 jdolecek Exp $ */ 1/* $NetBSD: xbd_xenbus.c,v 1.85 2018/08/21 18:45:16 jdolecek Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Manuel Bouyer. 4 * Copyright (c) 2006 Manuel Bouyer.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 * 25 *
26 */ 26 */
27 27
28/* 28/*
29 * The file contains the xbd frontend code required for block-level 29 * The file contains the xbd frontend code required for block-level
30 * communications (similar to hard disks) between two Xen domains. 30 * communications (similar to hard disks) between two Xen domains.
31 * 31 *
32 * We are not supposed to receive solicitations spontaneously from backend. The 32 * We are not supposed to receive solicitations spontaneously from backend. The
33 * protocol is therefore fairly simple and uses only one ring to communicate 33 * protocol is therefore fairly simple and uses only one ring to communicate
34 * with backend: frontend posts requests to the ring then wait for their 34 * with backend: frontend posts requests to the ring then wait for their
35 * replies asynchronously. 35 * replies asynchronously.
36 * 36 *
37 * xbd follows NetBSD's disk(9) convention. At any time, a LWP can schedule 37 * xbd follows NetBSD's disk(9) convention. At any time, a LWP can schedule
38 * an operation request for the device (be it open(), read(), write(), ...). 38 * an operation request for the device (be it open(), read(), write(), ...).
39 * Calls are typically processed that way: 39 * Calls are typically processed that way:
40 * - initiate request: xbdread/write/open/ioctl/.. 40 * - initiate request: xbdread/write/open/ioctl/..
41 * - depending on operation, it is handled directly by disk(9) subsystem or 41 * - depending on operation, it is handled directly by disk(9) subsystem or
42 * goes through physio(9) first. 42 * goes through physio(9) first.
43 * - the request is ultimately processed by xbd_diskstart() that prepares the 43 * - the request is ultimately processed by xbd_diskstart() that prepares the
44 * xbd requests, post them in the ring I/O queue, then signal the backend. 44 * xbd requests, post them in the ring I/O queue, then signal the backend.
45 * 45 *
46 * When a response is available in the queue, the backend signals the frontend 46 * When a response is available in the queue, the backend signals the frontend
47 * via its event channel. This triggers xbd_handler(), which will link back 47 * via its event channel. This triggers xbd_handler(), which will link back
48 * the response to its request through the request ID, and mark the I/O as 48 * the response to its request through the request ID, and mark the I/O as
49 * completed. 49 * completed.
50 */ 50 */
51 51
52#include <sys/cdefs.h> 52#include <sys/cdefs.h>
53__KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c,v 1.84 2018/08/21 18:31:55 jdolecek Exp $"); 53__KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c,v 1.85 2018/08/21 18:45:16 jdolecek Exp $");
54 54
55#include "opt_xen.h" 55#include "opt_xen.h"
56 56
57 57
58#include <sys/param.h> 58#include <sys/param.h>
59#include <sys/buf.h> 59#include <sys/buf.h>
60#include <sys/bufq.h> 60#include <sys/bufq.h>
61#include <sys/device.h> 61#include <sys/device.h>
62#include <sys/disk.h> 62#include <sys/disk.h>
63#include <sys/disklabel.h> 63#include <sys/disklabel.h>
64#include <sys/conf.h> 64#include <sys/conf.h>
65#include <sys/fcntl.h> 65#include <sys/fcntl.h>
66#include <sys/kernel.h> 66#include <sys/kernel.h>
67#include <sys/proc.h> 67#include <sys/proc.h>
68#include <sys/systm.h> 68#include <sys/systm.h>
69#include <sys/stat.h> 69#include <sys/stat.h>
70#include <sys/vnode.h> 70#include <sys/vnode.h>
71 71
72#include <dev/dkvar.h> 72#include <dev/dkvar.h>
73 73
74#include <uvm/uvm.h> 74#include <uvm/uvm.h>
75 75
76#include <xen/hypervisor.h> 76#include <xen/hypervisor.h>
77#include <xen/evtchn.h> 77#include <xen/evtchn.h>
78#include <xen/granttables.h> 78#include <xen/granttables.h>
79#include <xen/xen-public/io/blkif.h> 79#include <xen/xen-public/io/blkif.h>
80#include <xen/xen-public/io/protocols.h> 80#include <xen/xen-public/io/protocols.h>
81 81
82#include <xen/xenbus.h> 82#include <xen/xenbus.h>
83#include "locators.h" 83#include "locators.h"
84 84
85#undef XBD_DEBUG 85#undef XBD_DEBUG
86#ifdef XBD_DEBUG 86#ifdef XBD_DEBUG
87#define DPRINTF(x) printf x; 87#define DPRINTF(x) printf x;
88#else 88#else
89#define DPRINTF(x) 89#define DPRINTF(x)
90#endif 90#endif
91 91
92#define GRANT_INVALID_REF -1 92#define GRANT_INVALID_REF -1
93 93
94#define XBD_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE) 94#define XBD_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE)
95#define XBD_MAX_XFER (PAGE_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST) 95#define XBD_MAX_XFER (PAGE_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST)
96 96
97#define XEN_BSHIFT 9 /* log2(XEN_BSIZE) */ 97#define XEN_BSHIFT 9 /* log2(XEN_BSIZE) */
98#define XEN_BSIZE (1 << XEN_BSHIFT)  98#define XEN_BSIZE (1 << XEN_BSHIFT)
99 99
100struct xbd_req { 100struct xbd_req {
101 SLIST_ENTRY(xbd_req) req_next; 101 SLIST_ENTRY(xbd_req) req_next;
102 uint16_t req_id; /* ID passed to backend */ 102 uint16_t req_id; /* ID passed to backend */
103 union { 103 union {
104 struct { 104 struct {
105 grant_ref_t req_gntref[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 105 grant_ref_t req_gntref[BLKIF_MAX_SEGMENTS_PER_REQUEST];
106 int req_nr_segments; /* number of segments in this request */ 106 int req_nr_segments; /* number of segments in this request */
107 struct buf *req_bp; /* buffer associated with this request */ 107 struct buf *req_bp; /* buffer associated with this request */
108 } req_rw; 108 } req_rw;
109 struct { 109 struct {
110 int s_error; 110 int s_error;
111 volatile int s_done; 111 volatile int s_done;
112 } req_sync; 112 } req_sync;
113 } u; 113 } u;
114}; 114};
115#define req_gntref u.req_rw.req_gntref 115#define req_gntref u.req_rw.req_gntref
116#define req_nr_segments u.req_rw.req_nr_segments 116#define req_nr_segments u.req_rw.req_nr_segments
117#define req_bp u.req_rw.req_bp 117#define req_bp u.req_rw.req_bp
118#define req_sync u.req_sync 118#define req_sync u.req_sync
119 119
120struct xbd_xenbus_softc { 120struct xbd_xenbus_softc {
121 struct dk_softc sc_dksc; /* Must be first in this struct */ 121 struct dk_softc sc_dksc; /* Must be first in this struct */
122 struct xenbus_device *sc_xbusd; 122 struct xenbus_device *sc_xbusd;
123 123
124 struct intrhand *sc_ih; /* Interrupt handler for this instance. */ 124 struct intrhand *sc_ih; /* Interrupt handler for this instance. */
125  125
126 blkif_front_ring_t sc_ring; 126 blkif_front_ring_t sc_ring;
127 127
128 unsigned int sc_evtchn; 128 unsigned int sc_evtchn;
129 129
130 grant_ref_t sc_ring_gntref; 130 grant_ref_t sc_ring_gntref;
131 131
132 struct xbd_req sc_reqs[XBD_RING_SIZE]; 132 struct xbd_req sc_reqs[XBD_RING_SIZE];
133 SLIST_HEAD(,xbd_req) sc_xbdreq_head; /* list of free requests */ 133 SLIST_HEAD(,xbd_req) sc_xbdreq_head; /* list of free requests */
134 bool sc_xbdreq_wait; /* special waiting on xbd_req */ 134 bool sc_xbdreq_wait; /* special waiting on xbd_req */
135 135
136 int sc_backend_status; /* our status with backend */ 136 int sc_backend_status; /* our status with backend */
137#define BLKIF_STATE_DISCONNECTED 0 137#define BLKIF_STATE_DISCONNECTED 0
138#define BLKIF_STATE_CONNECTED 1 138#define BLKIF_STATE_CONNECTED 1
139#define BLKIF_STATE_SUSPENDED 2 139#define BLKIF_STATE_SUSPENDED 2
140 140
141 int sc_shutdown; 141 int sc_shutdown;
142#define BLKIF_SHUTDOWN_RUN 0 /* no shutdown */ 142#define BLKIF_SHUTDOWN_RUN 0 /* no shutdown */
143#define BLKIF_SHUTDOWN_REMOTE 1 /* backend-initiated shutdown in progress */ 143#define BLKIF_SHUTDOWN_REMOTE 1 /* backend-initiated shutdown in progress */
144#define BLKIF_SHUTDOWN_LOCAL 2 /* locally-initiated shutdown in progress */ 144#define BLKIF_SHUTDOWN_LOCAL 2 /* locally-initiated shutdown in progress */
145 145
146 uint64_t sc_sectors; /* number of sectors for this device */ 146 uint64_t sc_sectors; /* number of sectors for this device */
147 u_long sc_secsize; /* sector size */ 147 u_long sc_secsize; /* sector size */
148 uint64_t sc_xbdsize; /* size of disk in DEV_BSIZE */ 148 uint64_t sc_xbdsize; /* size of disk in DEV_BSIZE */
149 u_long sc_info; /* VDISK_* */ 149 u_long sc_info; /* VDISK_* */
150 u_long sc_handle; /* from backend */ 150 u_long sc_handle; /* from backend */
151 int sc_cache_flush; /* backend supports BLKIF_OP_FLUSH_DISKCACHE */ 151 int sc_cache_flush; /* backend supports BLKIF_OP_FLUSH_DISKCACHE */
152}; 152};
153 153
154#if 0 154#if 0
155/* too big to be on stack */ 155/* too big to be on stack */
156static multicall_entry_t rq_mcl[XBD_RING_SIZE+1]; 156static multicall_entry_t rq_mcl[XBD_RING_SIZE+1];
157static paddr_t rq_pages[XBD_RING_SIZE]; 157static paddr_t rq_pages[XBD_RING_SIZE];
158#endif 158#endif
159 159
160static int xbd_xenbus_match(device_t, cfdata_t, void *); 160static int xbd_xenbus_match(device_t, cfdata_t, void *);
161static void xbd_xenbus_attach(device_t, device_t, void *); 161static void xbd_xenbus_attach(device_t, device_t, void *);
162static int xbd_xenbus_detach(device_t, int); 162static int xbd_xenbus_detach(device_t, int);
163 163
164static bool xbd_xenbus_suspend(device_t, const pmf_qual_t *); 164static bool xbd_xenbus_suspend(device_t, const pmf_qual_t *);
165static bool xbd_xenbus_resume(device_t, const pmf_qual_t *); 165static bool xbd_xenbus_resume(device_t, const pmf_qual_t *);
166 166
167static int xbd_handler(void *); 167static int xbd_handler(void *);
168static int xbd_diskstart(device_t, struct buf *); 168static int xbd_diskstart(device_t, struct buf *);
169static void xbd_backend_changed(void *, XenbusState); 169static void xbd_backend_changed(void *, XenbusState);
170static void xbd_connect(struct xbd_xenbus_softc *); 170static void xbd_connect(struct xbd_xenbus_softc *);
171 171
172static void xbdminphys(struct buf *); 172static void xbdminphys(struct buf *);
173 173
174CFATTACH_DECL3_NEW(xbd, sizeof(struct xbd_xenbus_softc), 174CFATTACH_DECL3_NEW(xbd, sizeof(struct xbd_xenbus_softc),
175 xbd_xenbus_match, xbd_xenbus_attach, xbd_xenbus_detach, NULL, NULL, NULL, 175 xbd_xenbus_match, xbd_xenbus_attach, xbd_xenbus_detach, NULL, NULL, NULL,
176 DVF_DETACH_SHUTDOWN); 176 DVF_DETACH_SHUTDOWN);
177 177
178dev_type_open(xbdopen); 178dev_type_open(xbdopen);
179dev_type_close(xbdclose); 179dev_type_close(xbdclose);
180dev_type_read(xbdread); 180dev_type_read(xbdread);
181dev_type_write(xbdwrite); 181dev_type_write(xbdwrite);
182dev_type_ioctl(xbdioctl); 182dev_type_ioctl(xbdioctl);
183dev_type_strategy(xbdstrategy); 183dev_type_strategy(xbdstrategy);
184dev_type_dump(xbddump); 184dev_type_dump(xbddump);
185dev_type_size(xbdsize); 185dev_type_size(xbdsize);
186 186
187const struct bdevsw xbd_bdevsw = { 187const struct bdevsw xbd_bdevsw = {
188 .d_open = xbdopen, 188 .d_open = xbdopen,
189 .d_close = xbdclose, 189 .d_close = xbdclose,
190 .d_strategy = xbdstrategy, 190 .d_strategy = xbdstrategy,
191 .d_ioctl = xbdioctl, 191 .d_ioctl = xbdioctl,
192 .d_dump = xbddump, 192 .d_dump = xbddump,
193 .d_psize = xbdsize, 193 .d_psize = xbdsize,
194 .d_discard = nodiscard, 194 .d_discard = nodiscard,
195 .d_flag = D_DISK 195 .d_flag = D_DISK
196}; 196};
197 197
198const struct cdevsw xbd_cdevsw = { 198const struct cdevsw xbd_cdevsw = {
199 .d_open = xbdopen, 199 .d_open = xbdopen,
200 .d_close = xbdclose, 200 .d_close = xbdclose,
201 .d_read = xbdread, 201 .d_read = xbdread,
202 .d_write = xbdwrite, 202 .d_write = xbdwrite,
203 .d_ioctl = xbdioctl, 203 .d_ioctl = xbdioctl,
204 .d_stop = nostop, 204 .d_stop = nostop,
205 .d_tty = notty, 205 .d_tty = notty,
206 .d_poll = nopoll, 206 .d_poll = nopoll,
207 .d_mmap = nommap, 207 .d_mmap = nommap,
208 .d_kqfilter = nokqfilter, 208 .d_kqfilter = nokqfilter,
209 .d_discard = nodiscard, 209 .d_discard = nodiscard,
210 .d_flag = D_DISK 210 .d_flag = D_DISK
211}; 211};
212 212
213extern struct cfdriver xbd_cd; 213extern struct cfdriver xbd_cd;
214 214
215static struct dkdriver xbddkdriver = { 215static struct dkdriver xbddkdriver = {
216 .d_strategy = xbdstrategy, 216 .d_strategy = xbdstrategy,
217 .d_minphys = xbdminphys, 217 .d_minphys = xbdminphys,
218 .d_open = xbdopen, 218 .d_open = xbdopen,
219 .d_close = xbdclose, 219 .d_close = xbdclose,
220 .d_diskstart = xbd_diskstart, 220 .d_diskstart = xbd_diskstart,
221}; 221};
222 222
223static int 223static int
224xbd_xenbus_match(device_t parent, cfdata_t match, void *aux) 224xbd_xenbus_match(device_t parent, cfdata_t match, void *aux)
225{ 225{
226 struct xenbusdev_attach_args *xa = aux; 226 struct xenbusdev_attach_args *xa = aux;
227 227
228 if (strcmp(xa->xa_type, "vbd") != 0) 228 if (strcmp(xa->xa_type, "vbd") != 0)
229 return 0; 229 return 0;
230 230
231 if (match->cf_loc[XENBUSCF_ID] != XENBUSCF_ID_DEFAULT && 231 if (match->cf_loc[XENBUSCF_ID] != XENBUSCF_ID_DEFAULT &&
232 match->cf_loc[XENBUSCF_ID] != xa->xa_id) 232 match->cf_loc[XENBUSCF_ID] != xa->xa_id)
233 return 0; 233 return 0;
234 234
235 return 1; 235 return 1;
236} 236}
237 237
238static void 238static void
239xbd_xenbus_attach(device_t parent, device_t self, void *aux) 239xbd_xenbus_attach(device_t parent, device_t self, void *aux)
240{ 240{
241 struct xbd_xenbus_softc *sc = device_private(self); 241 struct xbd_xenbus_softc *sc = device_private(self);
242 struct xenbusdev_attach_args *xa = aux; 242 struct xenbusdev_attach_args *xa = aux;
243 blkif_sring_t *ring; 243 blkif_sring_t *ring;
244 RING_IDX i; 244 RING_IDX i;
245#ifdef XBD_DEBUG 245#ifdef XBD_DEBUG
246 char **dir, *val; 246 char **dir, *val;
247 int dir_n = 0; 247 int dir_n = 0;
248 char id_str[20]; 248 char id_str[20];
249 int err; 249 int err;
250#endif 250#endif
251 251
252 config_pending_incr(self); 252 config_pending_incr(self);
253 aprint_normal(": Xen Virtual Block Device Interface\n"); 253 aprint_normal(": Xen Virtual Block Device Interface\n");
254 254
255 dk_init(&sc->sc_dksc, self, DKTYPE_ESDI); 255 dk_init(&sc->sc_dksc, self, DKTYPE_ESDI);
256 disk_init(&sc->sc_dksc.sc_dkdev, device_xname(self), &xbddkdriver); 256 disk_init(&sc->sc_dksc.sc_dkdev, device_xname(self), &xbddkdriver);
257 257
258#ifdef XBD_DEBUG 258#ifdef XBD_DEBUG
259 printf("path: %s\n", xa->xa_xbusd->xbusd_path); 259 printf("path: %s\n", xa->xa_xbusd->xbusd_path);
260 snprintf(id_str, sizeof(id_str), "%d", xa->xa_id); 260 snprintf(id_str, sizeof(id_str), "%d", xa->xa_id);
261 err = xenbus_directory(NULL, "device/vbd", id_str, &dir_n, &dir); 261 err = xenbus_directory(NULL, "device/vbd", id_str, &dir_n, &dir);
262 if (err) { 262 if (err) {
263 aprint_error_dev(self, "xenbus_directory err %d\n", err); 263 aprint_error_dev(self, "xenbus_directory err %d\n", err);
264 } else { 264 } else {
265 printf("%s/\n", xa->xa_xbusd->xbusd_path); 265 printf("%s/\n", xa->xa_xbusd->xbusd_path);
266 for (i = 0; i < dir_n; i++) { 266 for (i = 0; i < dir_n; i++) {
267 printf("\t/%s", dir[i]); 267 printf("\t/%s", dir[i]);
268 err = xenbus_read(NULL, xa->xa_xbusd->xbusd_path, 268 err = xenbus_read(NULL, xa->xa_xbusd->xbusd_path,
269 dir[i], NULL, &val); 269 dir[i], NULL, &val);
270 if (err) { 270 if (err) {
271 aprint_error_dev(self, "xenbus_read err %d\n", 271 aprint_error_dev(self, "xenbus_read err %d\n",
272 err); 272 err);
273 } else { 273 } else {
274 printf(" = %s\n", val); 274 printf(" = %s\n", val);
275 free(val, M_DEVBUF); 275 free(val, M_DEVBUF);
276 } 276 }
277 } 277 }
278 } 278 }
279#endif /* XBD_DEBUG */ 279#endif /* XBD_DEBUG */
280 sc->sc_xbusd = xa->xa_xbusd; 280 sc->sc_xbusd = xa->xa_xbusd;
281 sc->sc_xbusd->xbusd_otherend_changed = xbd_backend_changed; 281 sc->sc_xbusd->xbusd_otherend_changed = xbd_backend_changed;
282 282
283 /* initialize free requests list */ 283 /* initialize free requests list */
284 SLIST_INIT(&sc->sc_xbdreq_head); 284 SLIST_INIT(&sc->sc_xbdreq_head);
285 for (i = 0; i < XBD_RING_SIZE; i++) { 285 for (i = 0; i < XBD_RING_SIZE; i++) {
286 sc->sc_reqs[i].req_id = i; 286 sc->sc_reqs[i].req_id = i;
287 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, &sc->sc_reqs[i], 287 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, &sc->sc_reqs[i],
288 req_next); 288 req_next);
289 } 289 }
290 290
291 sc->sc_backend_status = BLKIF_STATE_DISCONNECTED; 291 sc->sc_backend_status = BLKIF_STATE_DISCONNECTED;
292 sc->sc_shutdown = BLKIF_SHUTDOWN_REMOTE; 292 sc->sc_shutdown = BLKIF_SHUTDOWN_REMOTE;
293 293
294 ring = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED); 294 ring = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED);
295 if (ring == NULL) 295 if (ring == NULL)
296 panic("%s: can't alloc ring", device_xname(self)); 296 panic("%s: can't alloc ring", device_xname(self));
297 sc->sc_ring.sring = ring; 297 sc->sc_ring.sring = ring;
298 298
299 /* resume shared structures and tell backend that we are ready */ 299 /* resume shared structures and tell backend that we are ready */
300 if (xbd_xenbus_resume(self, PMF_Q_NONE) == false) { 300 if (xbd_xenbus_resume(self, PMF_Q_NONE) == false) {
301 uvm_km_free(kernel_map, (vaddr_t)ring, PAGE_SIZE, 301 uvm_km_free(kernel_map, (vaddr_t)ring, PAGE_SIZE,
302 UVM_KMF_WIRED); 302 UVM_KMF_WIRED);
303 return; 303 return;
304 } 304 }
305 305
306 if (!pmf_device_register(self, xbd_xenbus_suspend, xbd_xenbus_resume)) 306 if (!pmf_device_register(self, xbd_xenbus_suspend, xbd_xenbus_resume))
307 aprint_error_dev(self, "couldn't establish power handler\n"); 307 aprint_error_dev(self, "couldn't establish power handler\n");
308 308
309} 309}
310 310
311static int 311static int
312xbd_xenbus_detach(device_t dev, int flags) 312xbd_xenbus_detach(device_t dev, int flags)
313{ 313{
314 struct xbd_xenbus_softc *sc = device_private(dev); 314 struct xbd_xenbus_softc *sc = device_private(dev);
315 int bmaj, cmaj, i, mn, rc, s; 315 int bmaj, cmaj, i, mn, rc, s;
316 316
317 rc = disk_begindetach(&sc->sc_dksc.sc_dkdev, NULL, dev, flags); 317 rc = disk_begindetach(&sc->sc_dksc.sc_dkdev, NULL, dev, flags);
318 if (rc != 0) 318 if (rc != 0)
319 return rc; 319 return rc;
320 320
321 s = splbio(); /* XXXSMP */ 321 s = splbio(); /* XXXSMP */
322 DPRINTF(("%s: xbd_detach\n", device_xname(dev))); 322 DPRINTF(("%s: xbd_detach\n", device_xname(dev)));
323 if (sc->sc_shutdown == BLKIF_SHUTDOWN_RUN) { 323 if (sc->sc_shutdown == BLKIF_SHUTDOWN_RUN) {
324 sc->sc_shutdown = BLKIF_SHUTDOWN_LOCAL; 324 sc->sc_shutdown = BLKIF_SHUTDOWN_LOCAL;
325 /* wait for requests to complete */ 325 /* wait for requests to complete */
326 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED && 326 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED &&
327 disk_isbusy(&sc->sc_dksc.sc_dkdev)) { 327 disk_isbusy(&sc->sc_dksc.sc_dkdev)) {
328 /* XXXSMP */ 328 /* XXXSMP */
329 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach", hz/2); 329 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach", hz/2);
330 } 330 }
331 331
332 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosing); 332 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosing);
333 } 333 }
334 if ((flags & DETACH_FORCE) == 0) { 334 if ((flags & DETACH_FORCE) == 0) {
335 /* xbd_xenbus_detach already in progress */ 335 /* xbd_xenbus_detach already in progress */
336 wakeup(xbd_xenbus_detach); /* XXXSMP */ 336 wakeup(xbd_xenbus_detach); /* XXXSMP */
337 splx(s); 337 splx(s);
338 return EALREADY; 338 return EALREADY;
339 } 339 }
340 while (xenbus_read_driver_state(sc->sc_xbusd->xbusd_otherend) 340 while (xenbus_read_driver_state(sc->sc_xbusd->xbusd_otherend)
341 != XenbusStateClosed) { 341 != XenbusStateClosed) {
342 /* XXXSMP */ 342 /* XXXSMP */
343 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach2", hz/2); 343 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach2", hz/2);
344 } 344 }
345 splx(s); 345 splx(s);
346 346
347 /* locate the major number */ 347 /* locate the major number */
348 bmaj = bdevsw_lookup_major(&xbd_bdevsw); 348 bmaj = bdevsw_lookup_major(&xbd_bdevsw);
349 cmaj = cdevsw_lookup_major(&xbd_cdevsw); 349 cmaj = cdevsw_lookup_major(&xbd_cdevsw);
350 350
351 /* Nuke the vnodes for any open instances. */ 351 /* Nuke the vnodes for any open instances. */
352 for (i = 0; i < MAXPARTITIONS; i++) { 352 for (i = 0; i < MAXPARTITIONS; i++) {
353 mn = DISKMINOR(device_unit(dev), i); 353 mn = DISKMINOR(device_unit(dev), i);
354 vdevgone(bmaj, mn, mn, VBLK); 354 vdevgone(bmaj, mn, mn, VBLK);
355 vdevgone(cmaj, mn, mn, VCHR); 355 vdevgone(cmaj, mn, mn, VCHR);
356 } 356 }
357 if (sc->sc_backend_status == BLKIF_STATE_CONNECTED) { 357 if (sc->sc_backend_status == BLKIF_STATE_CONNECTED) {
358 /* Delete all of our wedges. */ 358 /* Delete all of our wedges. */
359 dkwedge_delall(&sc->sc_dksc.sc_dkdev); 359 dkwedge_delall(&sc->sc_dksc.sc_dkdev);
360 360
361 /* Kill off any queued buffers. */ 361 /* Kill off any queued buffers. */
362 dk_drain(&sc->sc_dksc); 362 dk_drain(&sc->sc_dksc);
363 bufq_free(sc->sc_dksc.sc_bufq); 363 bufq_free(sc->sc_dksc.sc_bufq);
364 364
365 /* detach disk */ 365 /* detach disk */
366 disk_detach(&sc->sc_dksc.sc_dkdev); 366 disk_detach(&sc->sc_dksc.sc_dkdev);
367 disk_destroy(&sc->sc_dksc.sc_dkdev); 367 disk_destroy(&sc->sc_dksc.sc_dkdev);
368 dk_detach(&sc->sc_dksc); 368 dk_detach(&sc->sc_dksc);
369 } 369 }
370 370
371 hypervisor_mask_event(sc->sc_evtchn); 371 hypervisor_mask_event(sc->sc_evtchn);
372 intr_disestablish(sc->sc_ih); 372 intr_disestablish(sc->sc_ih);
373 373
374 while (xengnt_status(sc->sc_ring_gntref)) { 374 while (xengnt_status(sc->sc_ring_gntref)) {
375 /* XXXSMP */ 375 /* XXXSMP */
376 tsleep(xbd_xenbus_detach, PRIBIO, "xbd_ref", hz/2); 376 tsleep(xbd_xenbus_detach, PRIBIO, "xbd_ref", hz/2);
377 } 377 }
378 xengnt_revoke_access(sc->sc_ring_gntref); 378 xengnt_revoke_access(sc->sc_ring_gntref);
379 uvm_km_free(kernel_map, (vaddr_t)sc->sc_ring.sring, 379 uvm_km_free(kernel_map, (vaddr_t)sc->sc_ring.sring,
380 PAGE_SIZE, UVM_KMF_WIRED); 380 PAGE_SIZE, UVM_KMF_WIRED);
381 381
382 pmf_device_deregister(dev); 382 pmf_device_deregister(dev);
383 383
384 return 0; 384 return 0;
385} 385}
386 386
387static bool 387static bool
388xbd_xenbus_suspend(device_t dev, const pmf_qual_t *qual) { 388xbd_xenbus_suspend(device_t dev, const pmf_qual_t *qual) {
389 389
390 int s; 390 int s;
391 struct xbd_xenbus_softc *sc; 391 struct xbd_xenbus_softc *sc;
392 392
393 sc = device_private(dev); 393 sc = device_private(dev);
394 394
395 s = splbio(); /* XXXSMP */ 395 s = splbio(); /* XXXSMP */
396 /* wait for requests to complete, then suspend device */ 396 /* wait for requests to complete, then suspend device */
397 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED && 397 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED &&
398 disk_isbusy(&sc->sc_dksc.sc_dkdev)) { 398 disk_isbusy(&sc->sc_dksc.sc_dkdev)) {
399 /* XXXSMP */ 399 /* XXXSMP */
400 tsleep(xbd_xenbus_suspend, PRIBIO, "xbdsuspend", hz/2); 400 tsleep(xbd_xenbus_suspend, PRIBIO, "xbdsuspend", hz/2);
401 } 401 }
402 402
403 hypervisor_mask_event(sc->sc_evtchn); 403 hypervisor_mask_event(sc->sc_evtchn);
404 sc->sc_backend_status = BLKIF_STATE_SUSPENDED; 404 sc->sc_backend_status = BLKIF_STATE_SUSPENDED;
405 intr_disestablish(sc->sc_ih); 405 intr_disestablish(sc->sc_ih);
406 406
407 splx(s); 407 splx(s);
408 408
409 xenbus_device_suspend(sc->sc_xbusd); 409 xenbus_device_suspend(sc->sc_xbusd);
410 aprint_verbose_dev(dev, "removed event channel %d\n", sc->sc_evtchn); 410 aprint_verbose_dev(dev, "removed event channel %d\n", sc->sc_evtchn);
411 411
412 return true; 412 return true;
413} 413}
414 414
415static bool 415static bool
416xbd_xenbus_resume(device_t dev, const pmf_qual_t *qual) 416xbd_xenbus_resume(device_t dev, const pmf_qual_t *qual)
417{ 417{
418 struct xbd_xenbus_softc *sc; 418 struct xbd_xenbus_softc *sc;
419 struct xenbus_transaction *xbt; 419 struct xenbus_transaction *xbt;
420 int error; 420 int error;
421 blkif_sring_t *ring; 421 blkif_sring_t *ring;
422 paddr_t ma; 422 paddr_t ma;
423 const char *errmsg; 423 const char *errmsg;
424 424
425 sc = device_private(dev); 425 sc = device_private(dev);
426 426
427 if (sc->sc_backend_status == BLKIF_STATE_SUSPENDED) { 427 if (sc->sc_backend_status == BLKIF_STATE_SUSPENDED) {
428 /* 428 /*
429 * Device was suspended, so ensure that access associated to 429 * Device was suspended, so ensure that access associated to
430 * the block I/O ring is revoked. 430 * the block I/O ring is revoked.
431 */ 431 */
432 xengnt_revoke_access(sc->sc_ring_gntref); 432 xengnt_revoke_access(sc->sc_ring_gntref);
433 } 433 }
434 sc->sc_ring_gntref = GRANT_INVALID_REF; 434 sc->sc_ring_gntref = GRANT_INVALID_REF;
435 435
436 /* Initialize ring */ 436 /* Initialize ring */
437 ring = sc->sc_ring.sring; 437 ring = sc->sc_ring.sring;
438 memset(ring, 0, PAGE_SIZE); 438 memset(ring, 0, PAGE_SIZE);
439 SHARED_RING_INIT(ring); 439 SHARED_RING_INIT(ring);
440 FRONT_RING_INIT(&sc->sc_ring, ring, PAGE_SIZE); 440 FRONT_RING_INIT(&sc->sc_ring, ring, PAGE_SIZE);
441 441
442 /* 442 /*
443 * get MA address of the ring, and use it to set up the grant entry 443 * get MA address of the ring, and use it to set up the grant entry
444 * for the block device 444 * for the block device
445 */ 445 */
446 (void)pmap_extract_ma(pmap_kernel(), (vaddr_t)ring, &ma); 446 (void)pmap_extract_ma(pmap_kernel(), (vaddr_t)ring, &ma);
447 error = xenbus_grant_ring(sc->sc_xbusd, ma, &sc->sc_ring_gntref); 447 error = xenbus_grant_ring(sc->sc_xbusd, ma, &sc->sc_ring_gntref);
448 if (error) 448 if (error)
449 goto abort_resume; 449 goto abort_resume;
450 450
451 error = xenbus_alloc_evtchn(sc->sc_xbusd, &sc->sc_evtchn); 451 error = xenbus_alloc_evtchn(sc->sc_xbusd, &sc->sc_evtchn);
452 if (error) 452 if (error)
453 goto abort_resume; 453 goto abort_resume;
454 454
455 aprint_verbose_dev(dev, "using event channel %d\n", 455 aprint_verbose_dev(dev, "using event channel %d\n",
456 sc->sc_evtchn); 456 sc->sc_evtchn);
457 sc->sc_ih = intr_establish_xname(0, &xen_pic, sc->sc_evtchn, IST_LEVEL, 457 sc->sc_ih = intr_establish_xname(0, &xen_pic, sc->sc_evtchn, IST_LEVEL,
458 IPL_BIO, &xbd_handler, sc, false, device_xname(dev)); 458 IPL_BIO, &xbd_handler, sc, false, device_xname(dev));
459 KASSERT(sc->sc_ih != NULL); 459 KASSERT(sc->sc_ih != NULL);
460 460
461again: 461again:
462 xbt = xenbus_transaction_start(); 462 xbt = xenbus_transaction_start();
463 if (xbt == NULL) 463 if (xbt == NULL)
464 return false; 464 return false;
465 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path, 465 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
466 "ring-ref","%u", sc->sc_ring_gntref); 466 "ring-ref","%u", sc->sc_ring_gntref);
467 if (error) { 467 if (error) {
468 errmsg = "writing ring-ref"; 468 errmsg = "writing ring-ref";
469 goto abort_transaction; 469 goto abort_transaction;
470 } 470 }
471 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path, 471 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
472 "event-channel", "%u", sc->sc_evtchn); 472 "event-channel", "%u", sc->sc_evtchn);
473 if (error) { 473 if (error) {
474 errmsg = "writing event channel"; 474 errmsg = "writing event channel";
475 goto abort_transaction; 475 goto abort_transaction;
476 } 476 }
477 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path, 477 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
478 "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE); 478 "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE);
479 if (error) { 479 if (error) {
480 errmsg = "writing protocol"; 480 errmsg = "writing protocol";
481 goto abort_transaction; 481 goto abort_transaction;
482 } 482 }
483 error = xenbus_transaction_end(xbt, 0); 483 error = xenbus_transaction_end(xbt, 0);
484 if (error == EAGAIN) 484 if (error == EAGAIN)
485 goto again; 485 goto again;
486 if (error != 0) { 486 if (error != 0) {
487 xenbus_dev_fatal(sc->sc_xbusd, error, 487 xenbus_dev_fatal(sc->sc_xbusd, error,
488 "completing transaction"); 488 "completing transaction");
489 return false; 489 return false;
490 } 490 }
491 491
492 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateInitialised); 492 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateInitialised);
493 493
494 if (sc->sc_backend_status == BLKIF_STATE_SUSPENDED) { 494 if (sc->sc_backend_status == BLKIF_STATE_SUSPENDED) {
495 /* 495 /*
496 * device was suspended, softc structures are 496 * device was suspended, softc structures are
497 * already initialized - we use a shortcut 497 * already initialized - we use a shortcut
498 */ 498 */
499 sc->sc_backend_status = BLKIF_STATE_CONNECTED; 499 sc->sc_backend_status = BLKIF_STATE_CONNECTED;
500 xenbus_device_resume(sc->sc_xbusd); 500 xenbus_device_resume(sc->sc_xbusd);
501 hypervisor_enable_event(sc->sc_evtchn); 501 hypervisor_enable_event(sc->sc_evtchn);
502 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateConnected); 502 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateConnected);
503 } 503 }
504 504
505 return true; 505 return true;
506 506
507abort_resume: 507abort_resume:
508 xenbus_dev_fatal(sc->sc_xbusd, error, "resuming device"); 508 xenbus_dev_fatal(sc->sc_xbusd, error, "resuming device");
509 return false; 509 return false;
510 510
511abort_transaction: 511abort_transaction:
512 xenbus_transaction_end(xbt, 1); 512 xenbus_transaction_end(xbt, 1);
513 xenbus_dev_fatal(sc->sc_xbusd, error, "%s", errmsg); 513 xenbus_dev_fatal(sc->sc_xbusd, error, "%s", errmsg);
514 return false; 514 return false;
515} 515}
516 516
517static void 517static void
518xbd_backend_changed(void *arg, XenbusState new_state) 518xbd_backend_changed(void *arg, XenbusState new_state)
519{ 519{
520 struct xbd_xenbus_softc *sc = device_private((device_t)arg); 520 struct xbd_xenbus_softc *sc = device_private((device_t)arg);
521 struct disk_geom *dg; 521 struct disk_geom *dg;
522 522
523 char buf[9]; 523 char buf[9];
524 int s; 524 int s;
525 DPRINTF(("%s: new backend state %d\n", 525 DPRINTF(("%s: new backend state %d\n",
526 device_xname(sc->sc_dksc.sc_dev), new_state)); 526 device_xname(sc->sc_dksc.sc_dev), new_state));
527 527
528 switch (new_state) { 528 switch (new_state) {
529 case XenbusStateUnknown: 529 case XenbusStateUnknown:
530 case XenbusStateInitialising: 530 case XenbusStateInitialising:
531 case XenbusStateInitWait: 531 case XenbusStateInitWait:
532 case XenbusStateInitialised: 532 case XenbusStateInitialised:
533 break; 533 break;
534 case XenbusStateClosing: 534 case XenbusStateClosing:
535 s = splbio(); /* XXXSMP */ 535 s = splbio(); /* XXXSMP */
536 if (sc->sc_shutdown == BLKIF_SHUTDOWN_RUN) 536 if (sc->sc_shutdown == BLKIF_SHUTDOWN_RUN)
537 sc->sc_shutdown = BLKIF_SHUTDOWN_REMOTE; 537 sc->sc_shutdown = BLKIF_SHUTDOWN_REMOTE;
538 /* wait for requests to complete */ 538 /* wait for requests to complete */
539 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED && 539 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED &&
540 disk_isbusy(&sc->sc_dksc.sc_dkdev)) { 540 disk_isbusy(&sc->sc_dksc.sc_dkdev)) {
541 /* XXXSMP */ 541 /* XXXSMP */
542 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach", hz/2); 542 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach", hz/2);
543 } 543 }
544 splx(s); 544 splx(s);
545 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosed); 545 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosed);
546 break; 546 break;
547 case XenbusStateConnected: 547 case XenbusStateConnected:
548 /* 548 /*
549 * note that xbd_backend_changed() can only be called by 549 * note that xbd_backend_changed() can only be called by
550 * the xenbus thread. 550 * the xenbus thread.
551 */ 551 */
552 552
553 if (sc->sc_backend_status == BLKIF_STATE_CONNECTED || 553 if (sc->sc_backend_status == BLKIF_STATE_CONNECTED ||
554 sc->sc_backend_status == BLKIF_STATE_SUSPENDED) 554 sc->sc_backend_status == BLKIF_STATE_SUSPENDED)
555 /* already connected */ 555 /* already connected */
556 return; 556 return;
557 557
558 xbd_connect(sc); 558 xbd_connect(sc);
559 sc->sc_shutdown = BLKIF_SHUTDOWN_RUN; 559 sc->sc_shutdown = BLKIF_SHUTDOWN_RUN;
560 hypervisor_enable_event(sc->sc_evtchn); 560 hypervisor_enable_event(sc->sc_evtchn);
561 561
562 sc->sc_xbdsize = 562 sc->sc_xbdsize =
563 sc->sc_sectors * (uint64_t)sc->sc_secsize / DEV_BSIZE; 563 sc->sc_sectors * (uint64_t)sc->sc_secsize / DEV_BSIZE;
564 dg = &sc->sc_dksc.sc_dkdev.dk_geom; 564 dg = &sc->sc_dksc.sc_dkdev.dk_geom;
565 memset(dg, 0, sizeof(*dg));  565 memset(dg, 0, sizeof(*dg));
566 566
567 dg->dg_secperunit = sc->sc_xbdsize; 567 dg->dg_secperunit = sc->sc_xbdsize;
568 dg->dg_secsize = DEV_BSIZE; 568 dg->dg_secsize = DEV_BSIZE;
569 dg->dg_ntracks = 1; 569 dg->dg_ntracks = 1;
570 // XXX: Ok to hard-code DEV_BSIZE? 570 // XXX: Ok to hard-code DEV_BSIZE?
571 dg->dg_nsectors = 1024 * (1024 / dg->dg_secsize); 571 dg->dg_nsectors = 1024 * (1024 / dg->dg_secsize);
572 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors; 572 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors;
573 573
574 bufq_alloc(&sc->sc_dksc.sc_bufq, "fcfs", 0); 574 bufq_alloc(&sc->sc_dksc.sc_bufq, "fcfs", 0);
575 dk_attach(&sc->sc_dksc); 575 dk_attach(&sc->sc_dksc);
576 disk_attach(&sc->sc_dksc.sc_dkdev); 576 disk_attach(&sc->sc_dksc.sc_dkdev);
577 577
578 sc->sc_backend_status = BLKIF_STATE_CONNECTED; 578 sc->sc_backend_status = BLKIF_STATE_CONNECTED;
579 579
580 /* try to read the disklabel */ 580 /* try to read the disklabel */
581 dk_getdisklabel(&sc->sc_dksc, 0 /* XXX ? */); 581 dk_getdisklabel(&sc->sc_dksc, 0 /* XXX ? */);
582 format_bytes(buf, sizeof(buf), sc->sc_sectors * sc->sc_secsize); 582 format_bytes(buf, sizeof(buf), sc->sc_sectors * sc->sc_secsize);
583 aprint_verbose_dev(sc->sc_dksc.sc_dev, 583 aprint_verbose_dev(sc->sc_dksc.sc_dev,
584 "%s, %d bytes/sect x %" PRIu64 " sectors\n", 584 "%s, %d bytes/sect x %" PRIu64 " sectors\n",
585 buf, (int)dg->dg_secsize, sc->sc_xbdsize); 585 buf, (int)dg->dg_secsize, sc->sc_xbdsize);
586 /* Discover wedges on this disk. */ 586 /* Discover wedges on this disk. */
587 dkwedge_discover(&sc->sc_dksc.sc_dkdev); 587 dkwedge_discover(&sc->sc_dksc.sc_dkdev);
588 588
589 disk_set_info(sc->sc_dksc.sc_dev, &sc->sc_dksc.sc_dkdev, NULL); 589 disk_set_info(sc->sc_dksc.sc_dev, &sc->sc_dksc.sc_dkdev, NULL);
590 590
591 /* the disk should be working now */ 591 /* the disk should be working now */
592 config_pending_decr(sc->sc_dksc.sc_dev); 592 config_pending_decr(sc->sc_dksc.sc_dev);
593 break; 593 break;
594 default: 594 default:
595 panic("bad backend state %d", new_state); 595 panic("bad backend state %d", new_state);
596 } 596 }
597} 597}
598 598
599static void 599static void
600xbd_connect(struct xbd_xenbus_softc *sc) 600xbd_connect(struct xbd_xenbus_softc *sc)
601{ 601{
602 int err; 602 int err;
603 unsigned long long sectors; 603 unsigned long long sectors;
604 u_long cache_flush; 604 u_long cache_flush;
605 605
606 err = xenbus_read_ul(NULL, 606 err = xenbus_read_ul(NULL,
607 sc->sc_xbusd->xbusd_path, "virtual-device", &sc->sc_handle, 10); 607 sc->sc_xbusd->xbusd_path, "virtual-device", &sc->sc_handle, 10);
608 if (err) 608 if (err)
609 panic("%s: can't read number from %s/virtual-device\n",  609 panic("%s: can't read number from %s/virtual-device\n",
610 device_xname(sc->sc_dksc.sc_dev), 610 device_xname(sc->sc_dksc.sc_dev),
611 sc->sc_xbusd->xbusd_otherend); 611 sc->sc_xbusd->xbusd_otherend);
612 err = xenbus_read_ull(NULL, 612 err = xenbus_read_ull(NULL,
613 sc->sc_xbusd->xbusd_otherend, "sectors", &sectors, 10); 613 sc->sc_xbusd->xbusd_otherend, "sectors", &sectors, 10);
614 if (err) 614 if (err)
615 panic("%s: can't read number from %s/sectors\n",  615 panic("%s: can't read number from %s/sectors\n",
616 device_xname(sc->sc_dksc.sc_dev), 616 device_xname(sc->sc_dksc.sc_dev),
617 sc->sc_xbusd->xbusd_otherend); 617 sc->sc_xbusd->xbusd_otherend);
618 sc->sc_sectors = sectors; 618 sc->sc_sectors = sectors;
619 619
620 err = xenbus_read_ul(NULL, 620 err = xenbus_read_ul(NULL,
621 sc->sc_xbusd->xbusd_otherend, "info", &sc->sc_info, 10); 621 sc->sc_xbusd->xbusd_otherend, "info", &sc->sc_info, 10);
622 if (err) 622 if (err)
623 panic("%s: can't read number from %s/info\n",  623 panic("%s: can't read number from %s/info\n",
624 device_xname(sc->sc_dksc.sc_dev), 624 device_xname(sc->sc_dksc.sc_dev),
625 sc->sc_xbusd->xbusd_otherend); 625 sc->sc_xbusd->xbusd_otherend);
626 err = xenbus_read_ul(NULL, 626 err = xenbus_read_ul(NULL,
627 sc->sc_xbusd->xbusd_otherend, "sector-size", &sc->sc_secsize, 10); 627 sc->sc_xbusd->xbusd_otherend, "sector-size", &sc->sc_secsize, 10);
628 if (err) 628 if (err)
629 panic("%s: can't read number from %s/sector-size\n",  629 panic("%s: can't read number from %s/sector-size\n",
630 device_xname(sc->sc_dksc.sc_dev), 630 device_xname(sc->sc_dksc.sc_dev),
631 sc->sc_xbusd->xbusd_otherend); 631 sc->sc_xbusd->xbusd_otherend);
632 632
633 err = xenbus_read_ul(NULL, sc->sc_xbusd->xbusd_otherend, 633 err = xenbus_read_ul(NULL, sc->sc_xbusd->xbusd_otherend,
634 "feature-flush-cache", &cache_flush, 10); 634 "feature-flush-cache", &cache_flush, 10);
635 if (err) 635 if (err)
636 cache_flush = 0; 636 cache_flush = 0;
637 if (cache_flush > 0) 637 if (cache_flush > 0)
638 sc->sc_cache_flush = 1; 638 sc->sc_cache_flush = 1;
639 else 639 else
640 sc->sc_cache_flush = 0; 640 sc->sc_cache_flush = 0;
641 641
642 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateConnected); 642 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateConnected);
643} 643}
644 644
645static int 645static int
646xbd_handler(void *arg) 646xbd_handler(void *arg)
647{ 647{
648 struct xbd_xenbus_softc *sc = arg; 648 struct xbd_xenbus_softc *sc = arg;
649 struct buf *bp; 649 struct buf *bp;
650 RING_IDX resp_prod, i; 650 RING_IDX resp_prod, i;
651 int more_to_do; 651 int more_to_do;
652 int seg; 652 int seg;
653 653
654 DPRINTF(("xbd_handler(%s)\n", device_xname(sc->sc_dksc.sc_dev))); 654 DPRINTF(("xbd_handler(%s)\n", device_xname(sc->sc_dksc.sc_dev)));
655 655
656 if (__predict_false(sc->sc_backend_status != BLKIF_STATE_CONNECTED)) 656 if (__predict_false(sc->sc_backend_status != BLKIF_STATE_CONNECTED))
657 return 0; 657 return 0;
658again: 658again:
659 resp_prod = sc->sc_ring.sring->rsp_prod; 659 resp_prod = sc->sc_ring.sring->rsp_prod;
660 xen_rmb(); /* ensure we see replies up to resp_prod */ 660 xen_rmb(); /* ensure we see replies up to resp_prod */
661 for (i = sc->sc_ring.rsp_cons; i != resp_prod; i++) { 661 for (i = sc->sc_ring.rsp_cons; i != resp_prod; i++) {
662 blkif_response_t *rep = RING_GET_RESPONSE(&sc->sc_ring, i); 662 blkif_response_t *rep = RING_GET_RESPONSE(&sc->sc_ring, i);
663 struct xbd_req *xbdreq = &sc->sc_reqs[rep->id]; 663 struct xbd_req *xbdreq = &sc->sc_reqs[rep->id];
664 bp = xbdreq->req_bp; 664
665 DPRINTF(("xbd_handler(%p): b_bcount = %ld\n", 
666 xbdreq->req_bp, (long)bp->b_bcount)); 
667 if (rep->operation == BLKIF_OP_FLUSH_DISKCACHE) { 665 if (rep->operation == BLKIF_OP_FLUSH_DISKCACHE) {
 666 KASSERT(xbdreq->req_bp == NULL);
668 xbdreq->req_sync.s_error = rep->status; 667 xbdreq->req_sync.s_error = rep->status;
669 xbdreq->req_sync.s_done = 1; 668 xbdreq->req_sync.s_done = 1;
670 wakeup(xbdreq); /* XXXSMP */ 669 wakeup(xbdreq); /* XXXSMP */
671 /* caller will free the req */ 670 /* caller will free the req */
672 continue; 671 continue;
673 } 672 }
 673
 674 if (rep->operation != BLKIF_OP_READ &&
 675 rep->operation != BLKIF_OP_WRITE) {
 676 aprint_error_dev(sc->sc_dksc.sc_dev,
 677 "bad operation %d from backend\n", rep->operation);
 678 continue;
 679 }
 680
674 for (seg = xbdreq->req_nr_segments - 1; seg >= 0; seg--) { 681 for (seg = xbdreq->req_nr_segments - 1; seg >= 0; seg--) {
675 if (__predict_false( 682 if (__predict_false(
676 xengnt_status(xbdreq->req_gntref[seg]))) { 683 xengnt_status(xbdreq->req_gntref[seg]))) {
677 aprint_verbose_dev(sc->sc_dksc.sc_dev, 684 aprint_verbose_dev(sc->sc_dksc.sc_dev,
678 "grant still used by backend\n"); 685 "grant still used by backend\n");
679 sc->sc_ring.rsp_cons = i; 686 sc->sc_ring.rsp_cons = i;
680 xbdreq->req_nr_segments = seg + 1; 687 xbdreq->req_nr_segments = seg + 1;
681 goto done; 688 goto done;
682 } 689 }
683 xengnt_revoke_access(xbdreq->req_gntref[seg]); 690 xengnt_revoke_access(xbdreq->req_gntref[seg]);
684 xbdreq->req_nr_segments--; 691 xbdreq->req_nr_segments--;
685 } 692 }
686 if (rep->operation != BLKIF_OP_READ && 693 KASSERT(xbdreq->req_nr_segments == 0);
687 rep->operation != BLKIF_OP_WRITE) { 694
688 aprint_error_dev(sc->sc_dksc.sc_dev, 695 bp = xbdreq->req_bp;
689 "bad operation %d from backend\n", rep->operation); 696 xbdreq->req_bp = NULL;
690 bp->b_error = EIO; 697 DPRINTF(("%s(%p): b_bcount = %ld\n", __func__,
691 bp->b_resid = bp->b_bcount; 698 bp, (long)bp->b_bcount));
692 goto next; 699
693 } 
694 if (rep->status != BLKIF_RSP_OKAY) { 700 if (rep->status != BLKIF_RSP_OKAY) {
695 bp->b_error = EIO; 701 bp->b_error = EIO;
696 bp->b_resid = bp->b_bcount; 702 bp->b_resid = bp->b_bcount;
697 goto next; 703 goto next;
698 } 704 }
699 /* b_resid was set in dk_start */ 705 /* b_resid was set in dk_start */
700next: 706next:
701 dk_done(&sc->sc_dksc, bp); 707 dk_done(&sc->sc_dksc, bp);
702 708
703 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq, req_next); 709 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq, req_next);
704 } 710 }
705done: 711done:
706 xen_rmb(); 712 xen_rmb();
707 sc->sc_ring.rsp_cons = i; 713 sc->sc_ring.rsp_cons = i;
708 714
709 RING_FINAL_CHECK_FOR_RESPONSES(&sc->sc_ring, more_to_do); 715 RING_FINAL_CHECK_FOR_RESPONSES(&sc->sc_ring, more_to_do);
710 if (more_to_do) 716 if (more_to_do)
711 goto again; 717 goto again;
712 718
713 if (sc->sc_xbdreq_wait) 719 if (sc->sc_xbdreq_wait)
714 wakeup(&sc->sc_xbdreq_wait); /* XXXSMP */ 720 wakeup(&sc->sc_xbdreq_wait); /* XXXSMP */
715 else 721 else
716 dk_start(&sc->sc_dksc, NULL); 722 dk_start(&sc->sc_dksc, NULL);
717 return 1; 723 return 1;
718} 724}
719 725
720static void 726static void
721xbdminphys(struct buf *bp) 727xbdminphys(struct buf *bp)
722{ 728{
723 if (bp->b_bcount > XBD_MAX_XFER) { 729 if (bp->b_bcount > XBD_MAX_XFER) {
724 bp->b_bcount = XBD_MAX_XFER; 730 bp->b_bcount = XBD_MAX_XFER;
725 } 731 }
726 minphys(bp); 732 minphys(bp);
727} 733}
728 734
729int 735int
730xbdopen(dev_t dev, int flags, int fmt, struct lwp *l) 736xbdopen(dev_t dev, int flags, int fmt, struct lwp *l)
731{ 737{
732 struct xbd_xenbus_softc *sc; 738 struct xbd_xenbus_softc *sc;
733 739
734 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); 740 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev));
735 if (sc == NULL) 741 if (sc == NULL)
736 return (ENXIO); 742 return (ENXIO);
737 if ((flags & FWRITE) && (sc->sc_info & VDISK_READONLY)) 743 if ((flags & FWRITE) && (sc->sc_info & VDISK_READONLY))
738 return EROFS; 744 return EROFS;
739 745
740 DPRINTF(("xbdopen(0x%04x, %d)\n", dev, flags)); 746 DPRINTF(("xbdopen(0x%04x, %d)\n", dev, flags));
741 return dk_open(&sc->sc_dksc, dev, flags, fmt, l); 747 return dk_open(&sc->sc_dksc, dev, flags, fmt, l);
742} 748}
743 749
744int 750int
745xbdclose(dev_t dev, int flags, int fmt, struct lwp *l) 751xbdclose(dev_t dev, int flags, int fmt, struct lwp *l)
746{ 752{
747 struct xbd_xenbus_softc *sc; 753 struct xbd_xenbus_softc *sc;
748 754
749 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); 755 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev));
750 756
751 DPRINTF(("xbdclose(%d, %d)\n", dev, flags)); 757 DPRINTF(("xbdclose(%d, %d)\n", dev, flags));
752 return dk_close(&sc->sc_dksc, dev, flags, fmt, l); 758 return dk_close(&sc->sc_dksc, dev, flags, fmt, l);
753} 759}
754 760
755void 761void
756xbdstrategy(struct buf *bp) 762xbdstrategy(struct buf *bp)
757{ 763{
758 struct xbd_xenbus_softc *sc; 764 struct xbd_xenbus_softc *sc;
759 765
760 sc = device_lookup_private(&xbd_cd, DISKUNIT(bp->b_dev)); 766 sc = device_lookup_private(&xbd_cd, DISKUNIT(bp->b_dev));
761 767
762 DPRINTF(("xbdstrategy(%p): b_bcount = %ld\n", bp, 768 DPRINTF(("xbdstrategy(%p): b_bcount = %ld\n", bp,
763 (long)bp->b_bcount)); 769 (long)bp->b_bcount));
764 770
765 if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) { 771 if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) {
766 bp->b_error = EIO; 772 bp->b_error = EIO;
767 biodone(bp); 773 biodone(bp);
768 return; 774 return;
769 } 775 }
770 if (__predict_false((sc->sc_info & VDISK_READONLY) && 776 if (__predict_false((sc->sc_info & VDISK_READONLY) &&
771 (bp->b_flags & B_READ) == 0)) { 777 (bp->b_flags & B_READ) == 0)) {
772 bp->b_error = EROFS; 778 bp->b_error = EROFS;
773 biodone(bp); 779 biodone(bp);
774 return; 780 return;
775 } 781 }
776 782
777 dk_strategy(&sc->sc_dksc, bp); 783 dk_strategy(&sc->sc_dksc, bp);
778 return; 784 return;
779} 785}
780 786
781int 787int
782xbdsize(dev_t dev) 788xbdsize(dev_t dev)
783{ 789{
784 struct xbd_xenbus_softc *sc; 790 struct xbd_xenbus_softc *sc;
785 791
786 DPRINTF(("xbdsize(%d)\n", dev)); 792 DPRINTF(("xbdsize(%d)\n", dev));
787 793
788 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); 794 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev));
789 if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) 795 if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN)
790 return -1; 796 return -1;
791 return dk_size(&sc->sc_dksc, dev); 797 return dk_size(&sc->sc_dksc, dev);
792} 798}
793 799
794int 800int
795xbdread(dev_t dev, struct uio *uio, int flags) 801xbdread(dev_t dev, struct uio *uio, int flags)
796{ 802{
797 struct xbd_xenbus_softc *sc =  803 struct xbd_xenbus_softc *sc =
798 device_lookup_private(&xbd_cd, DISKUNIT(dev)); 804 device_lookup_private(&xbd_cd, DISKUNIT(dev));
799 struct dk_softc *dksc = &sc->sc_dksc; 805 struct dk_softc *dksc = &sc->sc_dksc;
800 806
801 if (!DK_ATTACHED(dksc)) 807 if (!DK_ATTACHED(dksc))
802 return ENXIO; 808 return ENXIO;
803 return physio(xbdstrategy, NULL, dev, B_READ, xbdminphys, uio); 809 return physio(xbdstrategy, NULL, dev, B_READ, xbdminphys, uio);
804} 810}
805 811
806int 812int
807xbdwrite(dev_t dev, struct uio *uio, int flags) 813xbdwrite(dev_t dev, struct uio *uio, int flags)
808{ 814{
809 struct xbd_xenbus_softc *sc = 815 struct xbd_xenbus_softc *sc =
810 device_lookup_private(&xbd_cd, DISKUNIT(dev)); 816 device_lookup_private(&xbd_cd, DISKUNIT(dev));
811 struct dk_softc *dksc = &sc->sc_dksc; 817 struct dk_softc *dksc = &sc->sc_dksc;
812 818
813 if (!DK_ATTACHED(dksc)) 819 if (!DK_ATTACHED(dksc))
814 return ENXIO; 820 return ENXIO;
815 if (__predict_false(sc->sc_info & VDISK_READONLY)) 821 if (__predict_false(sc->sc_info & VDISK_READONLY))
816 return EROFS; 822 return EROFS;
817 return physio(xbdstrategy, NULL, dev, B_WRITE, xbdminphys, uio); 823 return physio(xbdstrategy, NULL, dev, B_WRITE, xbdminphys, uio);
818} 824}
819 825
820int 826int
821xbdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 827xbdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
822{ 828{
823 struct xbd_xenbus_softc *sc = 829 struct xbd_xenbus_softc *sc =
824 device_lookup_private(&xbd_cd, DISKUNIT(dev)); 830 device_lookup_private(&xbd_cd, DISKUNIT(dev));
825 struct dk_softc *dksc; 831 struct dk_softc *dksc;
826 int error; 832 int error;
827 int s; 833 int s;
828 struct xbd_req *xbdreq; 834 struct xbd_req *xbdreq;
829 blkif_request_t *req; 835 blkif_request_t *req;
830 int notify; 836 int notify;
831 837
832 DPRINTF(("xbdioctl(%d, %08lx, %p, %d, %p)\n", 838 DPRINTF(("xbdioctl(%d, %08lx, %p, %d, %p)\n",
833 dev, cmd, data, flag, l)); 839 dev, cmd, data, flag, l));
834 dksc = &sc->sc_dksc; 840 dksc = &sc->sc_dksc;
835 841
836 switch (cmd) { 842 switch (cmd) {
837 case DIOCSSTRATEGY: 843 case DIOCSSTRATEGY:
838 error = EOPNOTSUPP; 844 error = EOPNOTSUPP;
839 break; 845 break;
840 case DIOCCACHESYNC: 846 case DIOCCACHESYNC:
841 if (sc->sc_cache_flush <= 0) { 847 if (sc->sc_cache_flush <= 0) {
842 if (sc->sc_cache_flush == 0) { 848 if (sc->sc_cache_flush == 0) {
843 aprint_error_dev(sc->sc_dksc.sc_dev, 849 aprint_error_dev(sc->sc_dksc.sc_dev,
844 "WARNING: cache flush not supported " 850 "WARNING: cache flush not supported "
845 "by backend\n"); 851 "by backend\n");
846 sc->sc_cache_flush = -1; 852 sc->sc_cache_flush = -1;
847 } 853 }
848 return EOPNOTSUPP; 854 return EOPNOTSUPP;
849 } 855 }
850 856
851 s = splbio(); /* XXXSMP */ 857 s = splbio(); /* XXXSMP */
852 858
853 while (RING_FULL(&sc->sc_ring)) { 859 while (RING_FULL(&sc->sc_ring)) {
854 sc->sc_xbdreq_wait = 1; 860 sc->sc_xbdreq_wait = 1;
855 /* XXXSMP */ 861 /* XXXSMP */
856 tsleep(&sc->sc_xbdreq_wait, PRIBIO, "xbdreq", 0); 862 tsleep(&sc->sc_xbdreq_wait, PRIBIO, "xbdreq", 0);
857 } 863 }
858 sc->sc_xbdreq_wait = 0; 864 sc->sc_xbdreq_wait = 0;
859 865
860 xbdreq = SLIST_FIRST(&sc->sc_xbdreq_head); 866 xbdreq = SLIST_FIRST(&sc->sc_xbdreq_head);
861 if (__predict_false(xbdreq == NULL)) { 867 if (__predict_false(xbdreq == NULL)) {
862 DPRINTF(("xbdioctl: no req\n")); 868 DPRINTF(("xbdioctl: no req\n"));
863 error = ENOMEM; 869 error = ENOMEM;
864 } else { 870 } else {
865 SLIST_REMOVE_HEAD(&sc->sc_xbdreq_head, req_next); 871 SLIST_REMOVE_HEAD(&sc->sc_xbdreq_head, req_next);
866 req = RING_GET_REQUEST(&sc->sc_ring, 872 req = RING_GET_REQUEST(&sc->sc_ring,
867 sc->sc_ring.req_prod_pvt); 873 sc->sc_ring.req_prod_pvt);
868 req->id = xbdreq->req_id; 874 req->id = xbdreq->req_id;
869 req->operation = BLKIF_OP_FLUSH_DISKCACHE; 875 req->operation = BLKIF_OP_FLUSH_DISKCACHE;
870 req->handle = sc->sc_handle; 876 req->handle = sc->sc_handle;
871 xbdreq->req_sync.s_done = 0; 877 xbdreq->req_sync.s_done = 0;
872 sc->sc_ring.req_prod_pvt++; 878 sc->sc_ring.req_prod_pvt++;
873 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->sc_ring, 879 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->sc_ring,
874 notify); 880 notify);
875 if (notify) 881 if (notify)
876 hypervisor_notify_via_evtchn(sc->sc_evtchn); 882 hypervisor_notify_via_evtchn(sc->sc_evtchn);
877 /* request sent, now wait for completion */ 883 /* request sent, now wait for completion */
878 while (xbdreq->req_sync.s_done == 0) { 884 while (xbdreq->req_sync.s_done == 0) {
879 /* XXXSMP */ 885 /* XXXSMP */
880 tsleep(xbdreq, PRIBIO, "xbdsync", 0); 886 tsleep(xbdreq, PRIBIO, "xbdsync", 0);
881 } 887 }
882 if (xbdreq->req_sync.s_error == BLKIF_RSP_EOPNOTSUPP) 888 if (xbdreq->req_sync.s_error == BLKIF_RSP_EOPNOTSUPP)
883 error = EOPNOTSUPP; 889 error = EOPNOTSUPP;
884 else if (xbdreq->req_sync.s_error == BLKIF_RSP_OKAY) 890 else if (xbdreq->req_sync.s_error == BLKIF_RSP_OKAY)
885 error = 0; 891 error = 0;
886 else 892 else
887 error = EIO; 893 error = EIO;
888 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq, 894 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq,
889 req_next); 895 req_next);
890 } 896 }
891 splx(s); 897 splx(s);
892 break; 898 break;
893 899
894 default: 900 default:
895 error = dk_ioctl(dksc, dev, cmd, data, flag, l); 901 error = dk_ioctl(dksc, dev, cmd, data, flag, l);
896 break; 902 break;
897 } 903 }
898 904
899 return error; 905 return error;
900} 906}
901 907
902int 908int
903xbddump(dev_t dev, daddr_t blkno, void *va, size_t size) 909xbddump(dev_t dev, daddr_t blkno, void *va, size_t size)
904{ 910{
905 struct xbd_xenbus_softc *sc; 911 struct xbd_xenbus_softc *sc;
906 912
907 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); 913 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev));
908 if (sc == NULL) 914 if (sc == NULL)
909 return (ENXIO); 915 return (ENXIO);
910 916
911 DPRINTF(("xbddump(%d, %" PRId64 ", %p, %lu)\n", dev, blkno, va, 917 DPRINTF(("xbddump(%d, %" PRId64 ", %p, %lu)\n", dev, blkno, va,
912 (unsigned long)size)); 918 (unsigned long)size));
913 return dk_dump(&sc->sc_dksc, dev, blkno, va, size); 919 return dk_dump(&sc->sc_dksc, dev, blkno, va, size);
914} 920}
915 921
916static int 922static int
917xbd_diskstart(device_t self, struct buf *bp) 923xbd_diskstart(device_t self, struct buf *bp)
918{ 924{
919 struct xbd_xenbus_softc *sc = device_private(self); 925 struct xbd_xenbus_softc *sc = device_private(self);
920 struct xbd_req *xbdreq; 926 struct xbd_req *xbdreq;
921 blkif_request_t *req; 927 blkif_request_t *req;
922 size_t bcount, off; 928 size_t bcount, off;
923 paddr_t ma; 929 paddr_t ma;
924 vaddr_t va; 930 vaddr_t va;
925 int nsects, nbytes, seg; 931 int nsects, nbytes, seg;
926 int notify, error = 0; 932 int notify, error = 0;
927 int s; 933 int s;
928 934
929 DPRINTF(("xbd_diskstart(%p): b_bcount = %ld\n", 935 DPRINTF(("xbd_diskstart(%p): b_bcount = %ld\n",
930 bp, (long)bp->b_bcount)); 936 bp, (long)bp->b_bcount));
931 937
932 if (sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) { 938 if (sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) {
933 error = EIO; 939 error = EIO;
934 goto err; 940 goto err;
935 } 941 }
936 942
937 if (bp->b_rawblkno < 0 || bp->b_rawblkno > sc->sc_xbdsize) { 943 if (bp->b_rawblkno < 0 || bp->b_rawblkno > sc->sc_xbdsize) {
938 /* invalid block number */ 944 /* invalid block number */
939 error = EINVAL; 945 error = EINVAL;
940 goto err; 946 goto err;
941 } 947 }
942 948
943 s = splbio(); /* XXX SMP */ 949 s = splbio(); /* XXX SMP */
944 950
945 if (__predict_false( 951 if (__predict_false(
946 sc->sc_backend_status == BLKIF_STATE_SUSPENDED)) { 952 sc->sc_backend_status == BLKIF_STATE_SUSPENDED)) {
947 /* device is suspended, do not consume buffer */ 953 /* device is suspended, do not consume buffer */
948 DPRINTF(("%s: (xbd_diskstart) device suspended\n", 954 DPRINTF(("%s: (xbd_diskstart) device suspended\n",
949 sc->sc_dksc.sc_xname)); 955 sc->sc_dksc.sc_xname));
950 error = EAGAIN; 956 error = EAGAIN;
951 goto out; 957 goto out;
952 } 958 }
953 959
954 if (RING_FULL(&sc->sc_ring) || sc->sc_xbdreq_wait) { 960 if (RING_FULL(&sc->sc_ring) || sc->sc_xbdreq_wait) {
955 DPRINTF(("xbd_diskstart: ring_full\n")); 961 DPRINTF(("xbd_diskstart: ring_full\n"));
956 error = EAGAIN; 962 error = EAGAIN;
957 goto out; 963 goto out;
958 } 964 }
959 965
960 xbdreq = SLIST_FIRST(&sc->sc_xbdreq_head); 966 xbdreq = SLIST_FIRST(&sc->sc_xbdreq_head);
961 if (__predict_false(xbdreq == NULL)) { 967 if (__predict_false(xbdreq == NULL)) {
962 DPRINTF(("xbd_diskstart: no req\n")); 968 DPRINTF(("xbd_diskstart: no req\n"));
963 error = EAGAIN; 969 error = EAGAIN;
964 goto out; 970 goto out;
965 } 971 }
966 972
967 if ((vaddr_t)bp->b_data & (XEN_BSIZE - 1)) { 973 if ((vaddr_t)bp->b_data & (XEN_BSIZE - 1)) {
968 DPRINTF(("xbd_diskstart: no align\n")); 974 DPRINTF(("xbd_diskstart: no align\n"));
969 error = EINVAL; 975 error = EINVAL;
970 goto out; 976 goto out;
971 } 977 }
972 978
973 xbdreq->req_bp = bp; 979 xbdreq->req_bp = bp;
974 980
975 SLIST_REMOVE_HEAD(&sc->sc_xbdreq_head, req_next); 981 SLIST_REMOVE_HEAD(&sc->sc_xbdreq_head, req_next);
976 req = RING_GET_REQUEST(&sc->sc_ring, sc->sc_ring.req_prod_pvt); 982 req = RING_GET_REQUEST(&sc->sc_ring, sc->sc_ring.req_prod_pvt);
977 req->id = xbdreq->req_id; 983 req->id = xbdreq->req_id;
978 req->operation = 984 req->operation =
979 bp->b_flags & B_READ ? BLKIF_OP_READ : BLKIF_OP_WRITE; 985 bp->b_flags & B_READ ? BLKIF_OP_READ : BLKIF_OP_WRITE;
980 req->sector_number = bp->b_rawblkno; 986 req->sector_number = bp->b_rawblkno;
981 req->handle = sc->sc_handle; 987 req->handle = sc->sc_handle;
982 988
983 va = (vaddr_t)bp->b_data & ~PAGE_MASK; 989 va = (vaddr_t)bp->b_data & ~PAGE_MASK;
984 off = (vaddr_t)bp->b_data & PAGE_MASK; 990 off = (vaddr_t)bp->b_data & PAGE_MASK;
985 bcount = bp->b_bcount; 991 bcount = bp->b_bcount;
986 bp->b_resid = 0; 992 bp->b_resid = 0;
987 for (seg = 0; bcount > 0;) { 993 for (seg = 0; bcount > 0;) {
988 pmap_extract_ma(pmap_kernel(), va, &ma); 994 pmap_extract_ma(pmap_kernel(), va, &ma);
989 KASSERT((ma & (XEN_BSIZE - 1)) == 0); 995 KASSERT((ma & (XEN_BSIZE - 1)) == 0);
990 if (bcount > PAGE_SIZE - off) 996 if (bcount > PAGE_SIZE - off)
991 nbytes = PAGE_SIZE - off; 997 nbytes = PAGE_SIZE - off;
992 else 998 else
993 nbytes = bcount; 999 nbytes = bcount;
994 nsects = nbytes >> XEN_BSHIFT; 1000 nsects = nbytes >> XEN_BSHIFT;
995 req->seg[seg].first_sect = off >> XEN_BSHIFT; 1001 req->seg[seg].first_sect = off >> XEN_BSHIFT;
996 req->seg[seg].last_sect = 1002 req->seg[seg].last_sect =
997 (off >> XEN_BSHIFT) + nsects - 1; 1003 (off >> XEN_BSHIFT) + nsects - 1;
998 KASSERT(req->seg[seg].first_sect <= 1004 KASSERT(req->seg[seg].first_sect <=
999 req->seg[seg].last_sect); 1005 req->seg[seg].last_sect);
1000 KASSERT(req->seg[seg].last_sect < 8); 1006 KASSERT(req->seg[seg].last_sect < 8);
1001 if (__predict_false(xengnt_grant_access( 1007 if (__predict_false(xengnt_grant_access(
1002 sc->sc_xbusd->xbusd_otherend_id, ma, 1008 sc->sc_xbusd->xbusd_otherend_id, ma,
1003 (bp->b_flags & B_READ) == 0, 1009 (bp->b_flags & B_READ) == 0,
1004 &xbdreq->req_gntref[seg]))) 1010 &xbdreq->req_gntref[seg])))
1005 panic("xbd_diskstart: xengnt_grant_access"); /* XXX XXX !!! */ 1011 panic("xbd_diskstart: xengnt_grant_access"); /* XXX XXX !!! */
1006 req->seg[seg].gref = xbdreq->req_gntref[seg]; 1012 req->seg[seg].gref = xbdreq->req_gntref[seg];
1007 seg++; 1013 seg++;
1008 KASSERT(seg <= BLKIF_MAX_SEGMENTS_PER_REQUEST); 1014 KASSERT(seg <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
1009 va += PAGE_SIZE; 1015 va += PAGE_SIZE;
1010 off = 0; 1016 off = 0;
1011 bcount -= nbytes; 1017 bcount -= nbytes;
1012 } 1018 }
1013 xbdreq->req_nr_segments = req->nr_segments = seg; 1019 xbdreq->req_nr_segments = req->nr_segments = seg;
1014 sc->sc_ring.req_prod_pvt++; 1020 sc->sc_ring.req_prod_pvt++;
1015 1021
1016out: 1022out:
1017 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->sc_ring, notify); 1023 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->sc_ring, notify);
1018 if (notify) 1024 if (notify)
1019 hypervisor_notify_via_evtchn(sc->sc_evtchn); 1025 hypervisor_notify_via_evtchn(sc->sc_evtchn);
1020 splx(s); /* XXXSMP */ 1026 splx(s); /* XXXSMP */
1021err: 1027err:
1022 return error; 1028 return error;
1023} 1029}