xref: /freebsd/sys/dev/xen/blkfront/block.h (revision 33eebb6a7591245d4d8c729c1d8a01c01d6c0f3a)
189e0f4d2SKip Macy /*
29999d2cbSKip Macy  * XenBSD block device driver
39999d2cbSKip Macy  *
4*33eebb6aSJustin T. Gibbs  * Copyright (c) 2010-2013 Spectra Logic Corporation
5e4808c4bSKip Macy  * Copyright (c) 2009 Scott Long, Yahoo!
69999d2cbSKip Macy  * Copyright (c) 2009 Frank Suchomel, Citrix
79999d2cbSKip Macy  * Copyright (c) 2009 Doug F. Rabson, Citrix
89999d2cbSKip Macy  * Copyright (c) 2005 Kip Macy
99999d2cbSKip Macy  * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
109999d2cbSKip Macy  * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
119999d2cbSKip Macy  *
129999d2cbSKip Macy  *
139999d2cbSKip Macy  * Permission is hereby granted, free of charge, to any person obtaining a copy
149999d2cbSKip Macy  * of this software and associated documentation files (the "Software"), to
159999d2cbSKip Macy  * deal in the Software without restriction, including without limitation the
169999d2cbSKip Macy  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
179999d2cbSKip Macy  * sell copies of the Software, and to permit persons to whom the Software is
189999d2cbSKip Macy  * furnished to do so, subject to the following conditions:
199999d2cbSKip Macy  *
209999d2cbSKip Macy  * The above copyright notice and this permission notice shall be included in
219999d2cbSKip Macy  * all copies or substantial portions of the Software.
2289e0f4d2SKip Macy  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2389e0f4d2SKip Macy  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2489e0f4d2SKip Macy  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2589e0f4d2SKip Macy  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2689e0f4d2SKip Macy  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27e4808c4bSKip Macy  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28e4808c4bSKip Macy  * DEALINGS IN THE SOFTWARE.
2989e0f4d2SKip Macy  *
3089e0f4d2SKip Macy  * $FreeBSD$
3189e0f4d2SKip Macy  */
3289e0f4d2SKip Macy 
3389e0f4d2SKip Macy 
34*33eebb6aSJustin T. Gibbs #ifndef __XEN_BLKFRONT_BLOCK_H__
35*33eebb6aSJustin T. Gibbs #define __XEN_BLKFRONT_BLOCK_H__
36ff662b5cSJustin T. Gibbs #include <xen/blkif.h>
37ff662b5cSJustin T. Gibbs 
38ff662b5cSJustin T. Gibbs /**
39443cc4d4SJustin T. Gibbs  * Given a number of blkif segments, compute the maximum I/O size supported.
40443cc4d4SJustin T. Gibbs  *
41443cc4d4SJustin T. Gibbs  * \note This calculation assumes that all but the first and last segments
42443cc4d4SJustin T. Gibbs  *       of the I/O are fully utilized.
43443cc4d4SJustin T. Gibbs  *
44443cc4d4SJustin T. Gibbs  * \note We reserve a segement from the maximum supported by the transport to
45443cc4d4SJustin T. Gibbs  *       guarantee we can handle an unaligned transfer without the need to
46443cc4d4SJustin T. Gibbs  *       use a bounce buffer.
47443cc4d4SJustin T. Gibbs  */
48*33eebb6aSJustin T. Gibbs #define	XBD_SEGS_TO_SIZE(segs)						\
49443cc4d4SJustin T. Gibbs 	(((segs) - 1) * PAGE_SIZE)
50443cc4d4SJustin T. Gibbs 
51443cc4d4SJustin T. Gibbs /**
52443cc4d4SJustin T. Gibbs  * Compute the maximum number of blkif segments requried to represent
53443cc4d4SJustin T. Gibbs  * an I/O of the given size.
54443cc4d4SJustin T. Gibbs  *
55443cc4d4SJustin T. Gibbs  * \note This calculation assumes that all but the first and last segments
56443cc4d4SJustin T. Gibbs  *       of the I/O are fully utilized.
57443cc4d4SJustin T. Gibbs  *
58443cc4d4SJustin T. Gibbs  * \note We reserve a segement to guarantee we can handle an unaligned
59443cc4d4SJustin T. Gibbs  *       transfer without the need to use a bounce buffer.
60443cc4d4SJustin T. Gibbs  */
61*33eebb6aSJustin T. Gibbs #define	XBD_SIZE_TO_SEGS(size)						\
62443cc4d4SJustin T. Gibbs 	((size / PAGE_SIZE) + 1)
63443cc4d4SJustin T. Gibbs 
64443cc4d4SJustin T. Gibbs /**
65ff662b5cSJustin T. Gibbs  * The maximum number of outstanding requests blocks (request headers plus
66ff662b5cSJustin T. Gibbs  * additional segment blocks) we will allow in a negotiated block-front/back
67ff662b5cSJustin T. Gibbs  * communication channel.
68ff662b5cSJustin T. Gibbs  */
69*33eebb6aSJustin T. Gibbs #define XBD_MAX_REQUESTS		256
70ff662b5cSJustin T. Gibbs 
71ff662b5cSJustin T. Gibbs /**
72ff662b5cSJustin T. Gibbs  * The maximum mapped region size per request we will allow in a negotiated
73ff662b5cSJustin T. Gibbs  * block-front/back communication channel.
74ff662b5cSJustin T. Gibbs  */
75*33eebb6aSJustin T. Gibbs #define	XBD_MAX_REQUEST_SIZE						\
76*33eebb6aSJustin T. Gibbs 	MIN(MAXPHYS, XBD_SEGS_TO_SIZE(BLKIF_MAX_SEGMENTS_PER_REQUEST))
77ff662b5cSJustin T. Gibbs 
78ff662b5cSJustin T. Gibbs /**
79ff662b5cSJustin T. Gibbs  * The maximum number of segments (within a request header and accompanying
80ff662b5cSJustin T. Gibbs  * segment blocks) per request we will allow in a negotiated block-front/back
81ff662b5cSJustin T. Gibbs  * communication channel.
82ff662b5cSJustin T. Gibbs  */
83*33eebb6aSJustin T. Gibbs #define	XBD_MAX_SEGMENTS_PER_REQUEST					\
84ff662b5cSJustin T. Gibbs 	(MIN(BLKIF_MAX_SEGMENTS_PER_REQUEST,				\
85*33eebb6aSJustin T. Gibbs 	     XBD_SIZE_TO_SEGS(XBD_MAX_REQUEST_SIZE)))
86ff662b5cSJustin T. Gibbs 
87ff662b5cSJustin T. Gibbs /**
88ff662b5cSJustin T. Gibbs  * The maximum number of shared memory ring pages we will allow in a
89ff662b5cSJustin T. Gibbs  * negotiated block-front/back communication channel.  Allow enough
90*33eebb6aSJustin T. Gibbs  * ring space for all requests to be  XBD_MAX_REQUEST_SIZE'd.
91ff662b5cSJustin T. Gibbs  */
92*33eebb6aSJustin T. Gibbs #define XBD_MAX_RING_PAGES						    \
93*33eebb6aSJustin T. Gibbs 	BLKIF_RING_PAGES(BLKIF_SEGS_TO_BLOCKS(XBD_MAX_SEGMENTS_PER_REQUEST) \
94*33eebb6aSJustin T. Gibbs 		       * XBD_MAX_REQUESTS)
9589e0f4d2SKip Macy 
96*33eebb6aSJustin T. Gibbs struct xbd_command;
97*33eebb6aSJustin T. Gibbs typedef void xbd_cbcf_t(struct xbd_command *);
9889e0f4d2SKip Macy 
99*33eebb6aSJustin T. Gibbs struct xbd_command {
100*33eebb6aSJustin T. Gibbs 	TAILQ_ENTRY(xbd_command) cm_link;
101*33eebb6aSJustin T. Gibbs 	struct xbd_softc	*cm_sc;
102e4808c4bSKip Macy 	u_int			 cm_flags;
103*33eebb6aSJustin T. Gibbs #define XBD_CMD_FROZEN		(1<<0)
104*33eebb6aSJustin T. Gibbs #define XBD_CMD_POLLED		(1<<1)
105*33eebb6aSJustin T. Gibbs #define XBD_ON_XBDQ_FREE	(1<<2)
106*33eebb6aSJustin T. Gibbs #define XBD_ON_XBDQ_READY	(1<<3)
107*33eebb6aSJustin T. Gibbs #define XBD_ON_XBDQ_BUSY	(1<<4)
108*33eebb6aSJustin T. Gibbs #define XBD_ON_XBDQ_COMPLETE	(1<<5)
109*33eebb6aSJustin T. Gibbs #define XBD_ON_XBDQ_MASK	((1<<2)|(1<<3)|(1<<4)|(1<<5))
110*33eebb6aSJustin T. Gibbs 	bus_dmamap_t		 cm_map;
111*33eebb6aSJustin T. Gibbs 	uint64_t		 cm_id;
112*33eebb6aSJustin T. Gibbs 	grant_ref_t		*cm_sg_refs;
113*33eebb6aSJustin T. Gibbs 	struct bio		*cm_bp;
114*33eebb6aSJustin T. Gibbs 	grant_ref_t		 cm_gref_head;
115*33eebb6aSJustin T. Gibbs 	void			*cm_data;
116*33eebb6aSJustin T. Gibbs 	size_t			 cm_datalen;
117*33eebb6aSJustin T. Gibbs 	u_int			 cm_nseg;
118*33eebb6aSJustin T. Gibbs 	int			 cm_operation;
119*33eebb6aSJustin T. Gibbs 	blkif_sector_t		 cm_sector_number;
120*33eebb6aSJustin T. Gibbs 	int			 cm_status;
121*33eebb6aSJustin T. Gibbs 	xbd_cbcf_t		*cm_complete;
12289e0f4d2SKip Macy };
12389e0f4d2SKip Macy 
124*33eebb6aSJustin T. Gibbs #define XBDQ_FREE	0
125*33eebb6aSJustin T. Gibbs #define XBDQ_BIO	1
126*33eebb6aSJustin T. Gibbs #define XBDQ_READY	2
127*33eebb6aSJustin T. Gibbs #define XBDQ_BUSY	3
128*33eebb6aSJustin T. Gibbs #define XBDQ_COMPLETE	4
129*33eebb6aSJustin T. Gibbs #define XBDQ_COUNT	5
13089e0f4d2SKip Macy 
131*33eebb6aSJustin T. Gibbs struct xbd_qstat {
132e4808c4bSKip Macy 	uint32_t	q_length;
133e4808c4bSKip Macy 	uint32_t	q_max;
134e4808c4bSKip Macy };
135e4808c4bSKip Macy 
136*33eebb6aSJustin T. Gibbs union xbd_statrequest {
137e4808c4bSKip Macy 	uint32_t		ms_item;
138*33eebb6aSJustin T. Gibbs 	struct xbd_qstat	ms_qstat;
139e4808c4bSKip Macy };
140e4808c4bSKip Macy 
141e4808c4bSKip Macy /*
142e4808c4bSKip Macy  * We have one of these per vbd, whether ide, scsi or 'other'.
143e4808c4bSKip Macy  */
144*33eebb6aSJustin T. Gibbs struct xbd_softc {
145*33eebb6aSJustin T. Gibbs 	device_t			 xbd_dev;
146*33eebb6aSJustin T. Gibbs 	struct disk			*xbd_disk;	/* disk params */
147*33eebb6aSJustin T. Gibbs 	struct bio_queue_head 		 xbd_bioq;	/* sort queue */
148*33eebb6aSJustin T. Gibbs 	int				 xbd_unit;
149*33eebb6aSJustin T. Gibbs 	int				 xbd_flags;
150*33eebb6aSJustin T. Gibbs #define XBD_OPEN	(1<<0)		/* drive is open (can't shut down) */
151*33eebb6aSJustin T. Gibbs #define XBD_BARRIER	(1 << 1)	/* backend supports barriers */
152*33eebb6aSJustin T. Gibbs #define XBD_READY	(1 << 2)	/* Is ready */
153*33eebb6aSJustin T. Gibbs #define XBD_FROZEN	(1 << 3)	/* Waiting for resources */
154*33eebb6aSJustin T. Gibbs 	int				 xbd_vdevice;
155*33eebb6aSJustin T. Gibbs 	int				 xbd_connected;
156*33eebb6aSJustin T. Gibbs 	u_int				 xbd_ring_pages;
157*33eebb6aSJustin T. Gibbs 	uint32_t			 xbd_max_requests;
158*33eebb6aSJustin T. Gibbs 	uint32_t			 xbd_max_request_segments;
159*33eebb6aSJustin T. Gibbs 	uint32_t			 xbd_max_request_blocks;
160*33eebb6aSJustin T. Gibbs 	uint32_t			 xbd_max_request_size;
161*33eebb6aSJustin T. Gibbs 	grant_ref_t			 xbd_ring_ref[XBD_MAX_RING_PAGES];
162*33eebb6aSJustin T. Gibbs 	blkif_front_ring_t		 xbd_ring;
163*33eebb6aSJustin T. Gibbs 	unsigned int			 xbd_irq;
164*33eebb6aSJustin T. Gibbs 	struct gnttab_free_callback	 xbd_callback;
165*33eebb6aSJustin T. Gibbs 	TAILQ_HEAD(,xbd_command)	 xbd_cm_free;
166*33eebb6aSJustin T. Gibbs 	TAILQ_HEAD(,xbd_command)	 xbd_cm_ready;
167*33eebb6aSJustin T. Gibbs 	TAILQ_HEAD(,xbd_command)	 xbd_cm_busy;
168*33eebb6aSJustin T. Gibbs 	TAILQ_HEAD(,xbd_command)	 xbd_cm_complete;
169*33eebb6aSJustin T. Gibbs 	struct xbd_qstat		 xbd_qstat[XBDQ_COUNT];
170*33eebb6aSJustin T. Gibbs 	bus_dma_tag_t			 xbd_io_dmat;
171e4808c4bSKip Macy 
17289e0f4d2SKip Macy 	/**
17389e0f4d2SKip Macy 	 * The number of people holding this device open.  We won't allow a
17489e0f4d2SKip Macy 	 * hot-unplug unless this is 0.
17589e0f4d2SKip Macy 	 */
176*33eebb6aSJustin T. Gibbs 	int				 xbd_users;
177*33eebb6aSJustin T. Gibbs 	struct mtx			 xbd_io_lock;
178ff662b5cSJustin T. Gibbs 
179*33eebb6aSJustin T. Gibbs 	struct xbd_command		*xbd_shadow;
18089e0f4d2SKip Macy };
181e4808c4bSKip Macy 
182*33eebb6aSJustin T. Gibbs int xbd_instance_create(struct xbd_softc *, blkif_sector_t sectors, int device,
183ff662b5cSJustin T. Gibbs 			uint16_t vdisk_info, unsigned long sector_size);
184e4808c4bSKip Macy 
185*33eebb6aSJustin T. Gibbs #define XBDQ_ADD(sc, qname)					\
186e4808c4bSKip Macy 	do {							\
187*33eebb6aSJustin T. Gibbs 		struct xbd_qstat *qs;				\
188e4808c4bSKip Macy 								\
189*33eebb6aSJustin T. Gibbs 		qs = &(sc)->xbd_qstat[qname];			\
190e4808c4bSKip Macy 		qs->q_length++;					\
191e4808c4bSKip Macy 		if (qs->q_length > qs->q_max)			\
192e4808c4bSKip Macy 			qs->q_max = qs->q_length;		\
193e4808c4bSKip Macy 	} while (0)
194e4808c4bSKip Macy 
195*33eebb6aSJustin T. Gibbs #define XBDQ_REMOVE(sc, qname)	(sc)->xbd_qstat[qname].q_length--
196e4808c4bSKip Macy 
197*33eebb6aSJustin T. Gibbs #define XBDQ_INIT(sc, qname)					\
198e4808c4bSKip Macy 	do {							\
199*33eebb6aSJustin T. Gibbs 		sc->xbd_qstat[qname].q_length = 0;		\
200*33eebb6aSJustin T. Gibbs 		sc->xbd_qstat[qname].q_max = 0;			\
201e4808c4bSKip Macy 	} while (0)
202e4808c4bSKip Macy 
203*33eebb6aSJustin T. Gibbs #define XBDQ_COMMAND_QUEUE(name, index)					\
204e4808c4bSKip Macy 	static __inline void						\
205*33eebb6aSJustin T. Gibbs 	xbd_initq_ ## name (struct xbd_softc *sc)			\
206e4808c4bSKip Macy 	{								\
207*33eebb6aSJustin T. Gibbs 		TAILQ_INIT(&sc->xbd_cm_ ## name);			\
208*33eebb6aSJustin T. Gibbs 		XBDQ_INIT(sc, index);					\
209e4808c4bSKip Macy 	}								\
210e4808c4bSKip Macy 	static __inline void						\
211*33eebb6aSJustin T. Gibbs 	xbd_enqueue_ ## name (struct xbd_command *cm)			\
212e4808c4bSKip Macy 	{								\
213*33eebb6aSJustin T. Gibbs 		if ((cm->cm_flags & XBD_ON_XBDQ_MASK) != 0) {		\
214e4808c4bSKip Macy 			printf("command %p is on another queue, "	\
215e4808c4bSKip Macy 			    "flags = %#x\n", cm, cm->cm_flags);		\
216e4808c4bSKip Macy 			panic("command is on another queue");		\
217e4808c4bSKip Macy 		}							\
218*33eebb6aSJustin T. Gibbs 		TAILQ_INSERT_TAIL(&cm->cm_sc->xbd_cm_ ## name, cm, cm_link); \
219*33eebb6aSJustin T. Gibbs 		cm->cm_flags |= XBD_ON_ ## index;			\
220*33eebb6aSJustin T. Gibbs 		XBDQ_ADD(cm->cm_sc, index);				\
221e4808c4bSKip Macy 	}								\
222e4808c4bSKip Macy 	static __inline void						\
223*33eebb6aSJustin T. Gibbs 	xbd_requeue_ ## name (struct xbd_command *cm)			\
224e4808c4bSKip Macy 	{								\
225*33eebb6aSJustin T. Gibbs 		if ((cm->cm_flags & XBD_ON_XBDQ_MASK) != 0) {		\
226e4808c4bSKip Macy 			printf("command %p is on another queue, "	\
227e4808c4bSKip Macy 			    "flags = %#x\n", cm, cm->cm_flags);		\
228e4808c4bSKip Macy 			panic("command is on another queue");		\
229e4808c4bSKip Macy 		}							\
230*33eebb6aSJustin T. Gibbs 		TAILQ_INSERT_HEAD(&cm->cm_sc->xbd_cm_ ## name, cm, cm_link); \
231*33eebb6aSJustin T. Gibbs 		cm->cm_flags |= XBD_ON_ ## index;			\
232*33eebb6aSJustin T. Gibbs 		XBDQ_ADD(cm->cm_sc, index);				\
233e4808c4bSKip Macy 	}								\
234*33eebb6aSJustin T. Gibbs 	static __inline struct xbd_command *				\
235*33eebb6aSJustin T. Gibbs 	xbd_dequeue_ ## name (struct xbd_softc *sc)			\
236e4808c4bSKip Macy 	{								\
237*33eebb6aSJustin T. Gibbs 		struct xbd_command *cm;					\
238e4808c4bSKip Macy 									\
239*33eebb6aSJustin T. Gibbs 		if ((cm = TAILQ_FIRST(&sc->xbd_cm_ ## name)) != NULL) {	\
240*33eebb6aSJustin T. Gibbs 			if ((cm->cm_flags & XBD_ON_XBDQ_MASK) !=		\
241*33eebb6aSJustin T. Gibbs 			     XBD_ON_ ## index) {				\
242e4808c4bSKip Macy 				printf("command %p not in queue, "	\
243e4808c4bSKip Macy 				    "flags = %#x, bit = %#x\n", cm,	\
244*33eebb6aSJustin T. Gibbs 				    cm->cm_flags, XBD_ON_ ## index);	\
245e4808c4bSKip Macy 				panic("command not in queue");		\
246e4808c4bSKip Macy 			}						\
247*33eebb6aSJustin T. Gibbs 			TAILQ_REMOVE(&sc->xbd_cm_ ## name, cm, cm_link);\
248*33eebb6aSJustin T. Gibbs 			cm->cm_flags &= ~XBD_ON_ ## index;		\
249*33eebb6aSJustin T. Gibbs 			XBDQ_REMOVE(sc, index);				\
250e4808c4bSKip Macy 		}							\
251e4808c4bSKip Macy 		return (cm);						\
252e4808c4bSKip Macy 	}								\
253e4808c4bSKip Macy 	static __inline void						\
254*33eebb6aSJustin T. Gibbs 	xbd_remove_ ## name (struct xbd_command *cm)			\
255e4808c4bSKip Macy 	{								\
256*33eebb6aSJustin T. Gibbs 		if ((cm->cm_flags & XBD_ON_XBDQ_MASK) != XBD_ON_ ## index){\
257e4808c4bSKip Macy 			printf("command %p not in queue, flags = %#x, " \
258e4808c4bSKip Macy 			    "bit = %#x\n", cm, cm->cm_flags,		\
259*33eebb6aSJustin T. Gibbs 			    XBD_ON_ ## index);				\
260e4808c4bSKip Macy 			panic("command not in queue");			\
261e4808c4bSKip Macy 		}							\
262*33eebb6aSJustin T. Gibbs 		TAILQ_REMOVE(&cm->cm_sc->xbd_cm_ ## name, cm, cm_link);	\
263*33eebb6aSJustin T. Gibbs 		cm->cm_flags &= ~XBD_ON_ ## index;			\
264*33eebb6aSJustin T. Gibbs 		XBDQ_REMOVE(cm->cm_sc, index);				\
265e4808c4bSKip Macy 	}								\
266e4808c4bSKip Macy struct hack
267e4808c4bSKip Macy 
268*33eebb6aSJustin T. Gibbs XBDQ_COMMAND_QUEUE(free, XBDQ_FREE);
269*33eebb6aSJustin T. Gibbs XBDQ_COMMAND_QUEUE(ready, XBDQ_READY);
270*33eebb6aSJustin T. Gibbs XBDQ_COMMAND_QUEUE(busy, XBDQ_BUSY);
271*33eebb6aSJustin T. Gibbs XBDQ_COMMAND_QUEUE(complete, XBDQ_COMPLETE);
272e4808c4bSKip Macy 
273e4808c4bSKip Macy static __inline void
274*33eebb6aSJustin T. Gibbs xbd_initq_bio(struct xbd_softc *sc)
275e4808c4bSKip Macy {
276*33eebb6aSJustin T. Gibbs 	bioq_init(&sc->xbd_bioq);
277*33eebb6aSJustin T. Gibbs 	XBDQ_INIT(sc, XBDQ_BIO);
278e4808c4bSKip Macy }
279e4808c4bSKip Macy 
280e4808c4bSKip Macy static __inline void
281*33eebb6aSJustin T. Gibbs xbd_enqueue_bio(struct xbd_softc *sc, struct bio *bp)
282e4808c4bSKip Macy {
283*33eebb6aSJustin T. Gibbs 	bioq_insert_tail(&sc->xbd_bioq, bp);
284*33eebb6aSJustin T. Gibbs 	XBDQ_ADD(sc, XBDQ_BIO);
285e4808c4bSKip Macy }
286e4808c4bSKip Macy 
287e4808c4bSKip Macy static __inline void
288*33eebb6aSJustin T. Gibbs xbd_requeue_bio(struct xbd_softc *sc, struct bio *bp)
289e4808c4bSKip Macy {
290*33eebb6aSJustin T. Gibbs 	bioq_insert_head(&sc->xbd_bioq, bp);
291*33eebb6aSJustin T. Gibbs 	XBDQ_ADD(sc, XBDQ_BIO);
292e4808c4bSKip Macy }
293e4808c4bSKip Macy 
294e4808c4bSKip Macy static __inline struct bio *
295*33eebb6aSJustin T. Gibbs xbd_dequeue_bio(struct xbd_softc *sc)
296e4808c4bSKip Macy {
297e4808c4bSKip Macy 	struct bio *bp;
298e4808c4bSKip Macy 
299*33eebb6aSJustin T. Gibbs 	if ((bp = bioq_first(&sc->xbd_bioq)) != NULL) {
300*33eebb6aSJustin T. Gibbs 		bioq_remove(&sc->xbd_bioq, bp);
301*33eebb6aSJustin T. Gibbs 		XBDQ_REMOVE(sc, XBDQ_BIO);
302e4808c4bSKip Macy 	}
303e4808c4bSKip Macy 	return (bp);
304e4808c4bSKip Macy }
30589e0f4d2SKip Macy 
306*33eebb6aSJustin T. Gibbs #endif /* __XEN_BLKFRONT_BLOCK_H__ */
307