xref: /freebsd/sys/dev/xen/blkfront/block.h (revision 443cc4d407dcc04239701b7a418ea5bfd007e0ba)
189e0f4d2SKip Macy /*
29999d2cbSKip Macy  * XenBSD block device driver
39999d2cbSKip Macy  *
4e4808c4bSKip Macy  * Copyright (c) 2009 Scott Long, Yahoo!
59999d2cbSKip Macy  * Copyright (c) 2009 Frank Suchomel, Citrix
69999d2cbSKip Macy  * Copyright (c) 2009 Doug F. Rabson, Citrix
79999d2cbSKip Macy  * Copyright (c) 2005 Kip Macy
89999d2cbSKip Macy  * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
99999d2cbSKip Macy  * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
109999d2cbSKip Macy  *
119999d2cbSKip Macy  *
129999d2cbSKip Macy  * Permission is hereby granted, free of charge, to any person obtaining a copy
139999d2cbSKip Macy  * of this software and associated documentation files (the "Software"), to
149999d2cbSKip Macy  * deal in the Software without restriction, including without limitation the
159999d2cbSKip Macy  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
169999d2cbSKip Macy  * sell copies of the Software, and to permit persons to whom the Software is
179999d2cbSKip Macy  * furnished to do so, subject to the following conditions:
189999d2cbSKip Macy  *
199999d2cbSKip Macy  * The above copyright notice and this permission notice shall be included in
209999d2cbSKip Macy  * all copies or substantial portions of the Software.
2189e0f4d2SKip Macy  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2289e0f4d2SKip Macy  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2389e0f4d2SKip Macy  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2489e0f4d2SKip Macy  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2589e0f4d2SKip Macy  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26e4808c4bSKip Macy  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27e4808c4bSKip Macy  * DEALINGS IN THE SOFTWARE.
2889e0f4d2SKip Macy  *
2989e0f4d2SKip Macy  * $FreeBSD$
3089e0f4d2SKip Macy  */
3189e0f4d2SKip Macy 
3289e0f4d2SKip Macy 
3389e0f4d2SKip Macy #ifndef __XEN_DRIVERS_BLOCK_H__
3489e0f4d2SKip Macy #define __XEN_DRIVERS_BLOCK_H__
35ff662b5cSJustin T. Gibbs #include <xen/blkif.h>
36ff662b5cSJustin T. Gibbs 
37ff662b5cSJustin T. Gibbs /**
38*443cc4d4SJustin T. Gibbs  * Given a number of blkif segments, compute the maximum I/O size supported.
39*443cc4d4SJustin T. Gibbs  *
40*443cc4d4SJustin T. Gibbs  * \note This calculation assumes that all but the first and last segments
41*443cc4d4SJustin T. Gibbs  *       of the I/O are fully utilized.
42*443cc4d4SJustin T. Gibbs  *
43*443cc4d4SJustin T. Gibbs  * \note We reserve a segement from the maximum supported by the transport to
44*443cc4d4SJustin T. Gibbs  *       guarantee we can handle an unaligned transfer without the need to
45*443cc4d4SJustin T. Gibbs  *       use a bounce buffer.
46*443cc4d4SJustin T. Gibbs  */
47*443cc4d4SJustin T. Gibbs #define	XBF_SEGS_TO_SIZE(segs)						\
48*443cc4d4SJustin T. Gibbs 	(((segs) - 1) * PAGE_SIZE)
49*443cc4d4SJustin T. Gibbs 
50*443cc4d4SJustin T. Gibbs /**
51*443cc4d4SJustin T. Gibbs  * Compute the maximum number of blkif segments requried to represent
52*443cc4d4SJustin T. Gibbs  * an I/O of the given size.
53*443cc4d4SJustin T. Gibbs  *
54*443cc4d4SJustin T. Gibbs  * \note This calculation assumes that all but the first and last segments
55*443cc4d4SJustin T. Gibbs  *       of the I/O are fully utilized.
56*443cc4d4SJustin T. Gibbs  *
57*443cc4d4SJustin T. Gibbs  * \note We reserve a segement to guarantee we can handle an unaligned
58*443cc4d4SJustin T. Gibbs  *       transfer without the need to use a bounce buffer.
59*443cc4d4SJustin T. Gibbs  */
60*443cc4d4SJustin T. Gibbs #define	XBF_SIZE_TO_SEGS(size)						\
61*443cc4d4SJustin T. Gibbs 	((size / PAGE_SIZE) + 1)
62*443cc4d4SJustin T. Gibbs 
63*443cc4d4SJustin T. Gibbs /**
64ff662b5cSJustin T. Gibbs  * The maximum number of outstanding requests blocks (request headers plus
65ff662b5cSJustin T. Gibbs  * additional segment blocks) we will allow in a negotiated block-front/back
66ff662b5cSJustin T. Gibbs  * communication channel.
67ff662b5cSJustin T. Gibbs  */
68ff662b5cSJustin T. Gibbs #define XBF_MAX_REQUESTS		256
69ff662b5cSJustin T. Gibbs 
70ff662b5cSJustin T. Gibbs /**
71ff662b5cSJustin T. Gibbs  * The maximum mapped region size per request we will allow in a negotiated
72ff662b5cSJustin T. Gibbs  * block-front/back communication channel.
73ff662b5cSJustin T. Gibbs  */
74ff662b5cSJustin T. Gibbs #define	XBF_MAX_REQUEST_SIZE						\
75*443cc4d4SJustin T. Gibbs 	MIN(MAXPHYS, XBF_SEGS_TO_SIZE(BLKIF_MAX_SEGMENTS_PER_REQUEST))
76ff662b5cSJustin T. Gibbs 
77ff662b5cSJustin T. Gibbs /**
78ff662b5cSJustin T. Gibbs  * The maximum number of segments (within a request header and accompanying
79ff662b5cSJustin T. Gibbs  * segment blocks) per request we will allow in a negotiated block-front/back
80ff662b5cSJustin T. Gibbs  * communication channel.
81ff662b5cSJustin T. Gibbs  */
82ff662b5cSJustin T. Gibbs #define	XBF_MAX_SEGMENTS_PER_REQUEST					\
83ff662b5cSJustin T. Gibbs 	(MIN(BLKIF_MAX_SEGMENTS_PER_REQUEST,				\
84*443cc4d4SJustin T. Gibbs 	     XBF_SIZE_TO_SEGS(XBF_MAX_REQUEST_SIZE)))
85ff662b5cSJustin T. Gibbs 
86ff662b5cSJustin T. Gibbs /**
87ff662b5cSJustin T. Gibbs  * The maximum number of shared memory ring pages we will allow in a
88ff662b5cSJustin T. Gibbs  * negotiated block-front/back communication channel.  Allow enough
89ff662b5cSJustin T. Gibbs  * ring space for all requests to be  XBF_MAX_REQUEST_SIZE'd.
90ff662b5cSJustin T. Gibbs  */
91ff662b5cSJustin T. Gibbs #define XBF_MAX_RING_PAGES						    \
92ff662b5cSJustin T. Gibbs 	BLKIF_RING_PAGES(BLKIF_SEGS_TO_BLOCKS(XBF_MAX_SEGMENTS_PER_REQUEST) \
93ff662b5cSJustin T. Gibbs 		       * XBF_MAX_REQUESTS)
9489e0f4d2SKip Macy 
9589e0f4d2SKip Macy struct xlbd_type_info
9689e0f4d2SKip Macy {
9789e0f4d2SKip Macy 	int partn_shift;
9889e0f4d2SKip Macy 	int disks_per_major;
9989e0f4d2SKip Macy 	char *devname;
10089e0f4d2SKip Macy 	char *diskname;
10189e0f4d2SKip Macy };
10289e0f4d2SKip Macy 
10389e0f4d2SKip Macy struct xlbd_major_info
10489e0f4d2SKip Macy {
10589e0f4d2SKip Macy 	int major;
10689e0f4d2SKip Macy 	int index;
10789e0f4d2SKip Macy 	int usage;
10889e0f4d2SKip Macy 	struct xlbd_type_info *type;
10989e0f4d2SKip Macy };
11089e0f4d2SKip Macy 
111e4808c4bSKip Macy struct xb_command {
112e4808c4bSKip Macy 	TAILQ_ENTRY(xb_command)	cm_link;
113e4808c4bSKip Macy 	struct xb_softc		*cm_sc;
114e4808c4bSKip Macy 	u_int			cm_flags;
115e4808c4bSKip Macy #define XB_CMD_FROZEN		(1<<0)
116e4808c4bSKip Macy #define XB_CMD_POLLED		(1<<1)
117e4808c4bSKip Macy #define XB_ON_XBQ_FREE		(1<<2)
118e4808c4bSKip Macy #define XB_ON_XBQ_READY		(1<<3)
119e4808c4bSKip Macy #define XB_ON_XBQ_BUSY		(1<<4)
120e4808c4bSKip Macy #define XB_ON_XBQ_COMPLETE	(1<<5)
121e4808c4bSKip Macy #define XB_ON_XBQ_MASK		((1<<2)|(1<<3)|(1<<4)|(1<<5))
122e4808c4bSKip Macy 	bus_dmamap_t		map;
123ff662b5cSJustin T. Gibbs 	uint64_t		id;
124ff662b5cSJustin T. Gibbs 	grant_ref_t		*sg_refs;
125e4808c4bSKip Macy 	struct bio		*bp;
126e4808c4bSKip Macy 	grant_ref_t		gref_head;
127e4808c4bSKip Macy 	void			*data;
128e4808c4bSKip Macy 	size_t			datalen;
129ff662b5cSJustin T. Gibbs 	u_int			nseg;
130e4808c4bSKip Macy 	int			operation;
131e4808c4bSKip Macy 	blkif_sector_t		sector_number;
132e4808c4bSKip Macy 	int			status;
133e4808c4bSKip Macy 	void			(* cm_complete)(struct xb_command *);
13489e0f4d2SKip Macy };
13589e0f4d2SKip Macy 
136e4808c4bSKip Macy #define XBQ_FREE	0
137e4808c4bSKip Macy #define XBQ_BIO		1
138e4808c4bSKip Macy #define XBQ_READY	2
139e4808c4bSKip Macy #define XBQ_BUSY	3
140e4808c4bSKip Macy #define XBQ_COMPLETE	4
141e4808c4bSKip Macy #define XBQ_COUNT	5
14289e0f4d2SKip Macy 
143e4808c4bSKip Macy struct xb_qstat {
144e4808c4bSKip Macy 	uint32_t	q_length;
145e4808c4bSKip Macy 	uint32_t	q_max;
146e4808c4bSKip Macy };
147e4808c4bSKip Macy 
148e4808c4bSKip Macy union xb_statrequest {
149e4808c4bSKip Macy 	uint32_t		ms_item;
150e4808c4bSKip Macy 	struct xb_qstat		ms_qstat;
151e4808c4bSKip Macy };
152e4808c4bSKip Macy 
153e4808c4bSKip Macy /*
154e4808c4bSKip Macy  * We have one of these per vbd, whether ide, scsi or 'other'.
155e4808c4bSKip Macy  */
15689e0f4d2SKip Macy struct xb_softc {
15789e0f4d2SKip Macy 	device_t		xb_dev;
15889e0f4d2SKip Macy 	struct disk		*xb_disk;		/* disk params */
15989e0f4d2SKip Macy 	struct bio_queue_head   xb_bioq;		/* sort queue */
16089e0f4d2SKip Macy 	int			xb_unit;
16189e0f4d2SKip Macy 	int			xb_flags;
16289e0f4d2SKip Macy #define XB_OPEN		(1<<0)		/* drive is open (can't shut down) */
163e4808c4bSKip Macy #define XB_BARRIER	(1 << 1)	/* backend supports barriers */
164e4808c4bSKip Macy #define XB_READY	(1 << 2)	/* Is ready */
165e4808c4bSKip Macy #define XB_FROZEN	(1 << 3)	/* Waiting for resources */
16689e0f4d2SKip Macy 	int			vdevice;
16789e0f4d2SKip Macy 	int			connected;
168ff662b5cSJustin T. Gibbs 	u_int			ring_pages;
169ff662b5cSJustin T. Gibbs 	uint32_t		max_requests;
170ff662b5cSJustin T. Gibbs 	uint32_t		max_request_segments;
171ff662b5cSJustin T. Gibbs 	uint32_t		max_request_blocks;
172ff662b5cSJustin T. Gibbs 	uint32_t		max_request_size;
173ff662b5cSJustin T. Gibbs 	grant_ref_t		ring_ref[XBF_MAX_RING_PAGES];
17489e0f4d2SKip Macy 	blkif_front_ring_t	ring;
17589e0f4d2SKip Macy 	unsigned int		irq;
17689e0f4d2SKip Macy 	struct gnttab_free_callback	callback;
177e4808c4bSKip Macy 	TAILQ_HEAD(,xb_command)	cm_free;
178e4808c4bSKip Macy 	TAILQ_HEAD(,xb_command)	cm_ready;
179e4808c4bSKip Macy 	TAILQ_HEAD(,xb_command)	cm_busy;
180e4808c4bSKip Macy 	TAILQ_HEAD(,xb_command)	cm_complete;
181e4808c4bSKip Macy 	struct xb_qstat		xb_qstat[XBQ_COUNT];
182e4808c4bSKip Macy 	bus_dma_tag_t		xb_io_dmat;
183e4808c4bSKip Macy 
18489e0f4d2SKip Macy 	/**
18589e0f4d2SKip Macy 	 * The number of people holding this device open.  We won't allow a
18689e0f4d2SKip Macy 	 * hot-unplug unless this is 0.
18789e0f4d2SKip Macy 	 */
18889e0f4d2SKip Macy 	int			users;
189e4808c4bSKip Macy 	struct mtx		xb_io_lock;
190ff662b5cSJustin T. Gibbs 
191ff662b5cSJustin T. Gibbs 	struct xb_command      *shadow;
19289e0f4d2SKip Macy };
193e4808c4bSKip Macy 
194ff662b5cSJustin T. Gibbs int xlvbd_add(struct xb_softc *, blkif_sector_t sectors, int device,
195ff662b5cSJustin T. Gibbs 	      uint16_t vdisk_info, unsigned long sector_size);
196e4808c4bSKip Macy void xlvbd_del(struct xb_softc *);
197e4808c4bSKip Macy 
198e4808c4bSKip Macy #define XBQ_ADD(sc, qname)					\
199e4808c4bSKip Macy 	do {							\
200e4808c4bSKip Macy 		struct xb_qstat *qs;				\
201e4808c4bSKip Macy 								\
202e4808c4bSKip Macy 		qs = &(sc)->xb_qstat[qname];			\
203e4808c4bSKip Macy 		qs->q_length++;					\
204e4808c4bSKip Macy 		if (qs->q_length > qs->q_max)			\
205e4808c4bSKip Macy 			qs->q_max = qs->q_length;		\
206e4808c4bSKip Macy 	} while (0)
207e4808c4bSKip Macy 
208e4808c4bSKip Macy #define XBQ_REMOVE(sc, qname)	(sc)->xb_qstat[qname].q_length--
209e4808c4bSKip Macy 
210e4808c4bSKip Macy #define XBQ_INIT(sc, qname)					\
211e4808c4bSKip Macy 	do {							\
212e4808c4bSKip Macy 		sc->xb_qstat[qname].q_length = 0;		\
213e4808c4bSKip Macy 		sc->xb_qstat[qname].q_max = 0;			\
214e4808c4bSKip Macy 	} while (0)
215e4808c4bSKip Macy 
216e4808c4bSKip Macy #define XBQ_COMMAND_QUEUE(name, index)					\
217e4808c4bSKip Macy 	static __inline void						\
218e4808c4bSKip Macy 	xb_initq_ ## name (struct xb_softc *sc)				\
219e4808c4bSKip Macy 	{								\
220e4808c4bSKip Macy 		TAILQ_INIT(&sc->cm_ ## name);				\
221e4808c4bSKip Macy 		XBQ_INIT(sc, index);					\
222e4808c4bSKip Macy 	}								\
223e4808c4bSKip Macy 	static __inline void						\
224e4808c4bSKip Macy 	xb_enqueue_ ## name (struct xb_command *cm)			\
225e4808c4bSKip Macy 	{								\
226e4808c4bSKip Macy 		if ((cm->cm_flags & XB_ON_XBQ_MASK) != 0) {		\
227e4808c4bSKip Macy 			printf("command %p is on another queue, "	\
228e4808c4bSKip Macy 			    "flags = %#x\n", cm, cm->cm_flags);		\
229e4808c4bSKip Macy 			panic("command is on another queue");		\
230e4808c4bSKip Macy 		}							\
231e4808c4bSKip Macy 		TAILQ_INSERT_TAIL(&cm->cm_sc->cm_ ## name, cm, cm_link); \
232e4808c4bSKip Macy 		cm->cm_flags |= XB_ON_ ## index;			\
233e4808c4bSKip Macy 		XBQ_ADD(cm->cm_sc, index);				\
234e4808c4bSKip Macy 	}								\
235e4808c4bSKip Macy 	static __inline void						\
236e4808c4bSKip Macy 	xb_requeue_ ## name (struct xb_command *cm)			\
237e4808c4bSKip Macy 	{								\
238e4808c4bSKip Macy 		if ((cm->cm_flags & XB_ON_XBQ_MASK) != 0) {		\
239e4808c4bSKip Macy 			printf("command %p is on another queue, "	\
240e4808c4bSKip Macy 			    "flags = %#x\n", cm, cm->cm_flags);		\
241e4808c4bSKip Macy 			panic("command is on another queue");		\
242e4808c4bSKip Macy 		}							\
243e4808c4bSKip Macy 		TAILQ_INSERT_HEAD(&cm->cm_sc->cm_ ## name, cm, cm_link); \
244e4808c4bSKip Macy 		cm->cm_flags |= XB_ON_ ## index;			\
245e4808c4bSKip Macy 		XBQ_ADD(cm->cm_sc, index);				\
246e4808c4bSKip Macy 	}								\
247e4808c4bSKip Macy 	static __inline struct xb_command *				\
248e4808c4bSKip Macy 	xb_dequeue_ ## name (struct xb_softc *sc)			\
249e4808c4bSKip Macy 	{								\
250e4808c4bSKip Macy 		struct xb_command *cm;					\
251e4808c4bSKip Macy 									\
252e4808c4bSKip Macy 		if ((cm = TAILQ_FIRST(&sc->cm_ ## name)) != NULL) {	\
253ff662b5cSJustin T. Gibbs 			if ((cm->cm_flags & XB_ON_XBQ_MASK) !=		\
254ff662b5cSJustin T. Gibbs 			     XB_ON_ ## index) {				\
255e4808c4bSKip Macy 				printf("command %p not in queue, "	\
256e4808c4bSKip Macy 				    "flags = %#x, bit = %#x\n", cm,	\
257e4808c4bSKip Macy 				    cm->cm_flags, XB_ON_ ## index);	\
258e4808c4bSKip Macy 				panic("command not in queue");		\
259e4808c4bSKip Macy 			}						\
260e4808c4bSKip Macy 			TAILQ_REMOVE(&sc->cm_ ## name, cm, cm_link);	\
261e4808c4bSKip Macy 			cm->cm_flags &= ~XB_ON_ ## index;		\
262e4808c4bSKip Macy 			XBQ_REMOVE(sc, index);				\
263e4808c4bSKip Macy 		}							\
264e4808c4bSKip Macy 		return (cm);						\
265e4808c4bSKip Macy 	}								\
266e4808c4bSKip Macy 	static __inline void						\
267e4808c4bSKip Macy 	xb_remove_ ## name (struct xb_command *cm)			\
268e4808c4bSKip Macy 	{								\
269ff662b5cSJustin T. Gibbs 		if ((cm->cm_flags & XB_ON_XBQ_MASK) != XB_ON_ ## index){\
270e4808c4bSKip Macy 			printf("command %p not in queue, flags = %#x, " \
271e4808c4bSKip Macy 			    "bit = %#x\n", cm, cm->cm_flags,		\
272e4808c4bSKip Macy 			    XB_ON_ ## index);				\
273e4808c4bSKip Macy 			panic("command not in queue");			\
274e4808c4bSKip Macy 		}							\
275e4808c4bSKip Macy 		TAILQ_REMOVE(&cm->cm_sc->cm_ ## name, cm, cm_link);	\
276e4808c4bSKip Macy 		cm->cm_flags &= ~XB_ON_ ## index;			\
277e4808c4bSKip Macy 		XBQ_REMOVE(cm->cm_sc, index);				\
278e4808c4bSKip Macy 	}								\
279e4808c4bSKip Macy struct hack
280e4808c4bSKip Macy 
281e4808c4bSKip Macy XBQ_COMMAND_QUEUE(free, XBQ_FREE);
282e4808c4bSKip Macy XBQ_COMMAND_QUEUE(ready, XBQ_READY);
283e4808c4bSKip Macy XBQ_COMMAND_QUEUE(busy, XBQ_BUSY);
284e4808c4bSKip Macy XBQ_COMMAND_QUEUE(complete, XBQ_COMPLETE);
285e4808c4bSKip Macy 
286e4808c4bSKip Macy static __inline void
287e4808c4bSKip Macy xb_initq_bio(struct xb_softc *sc)
288e4808c4bSKip Macy {
289e4808c4bSKip Macy 	bioq_init(&sc->xb_bioq);
290e4808c4bSKip Macy 	XBQ_INIT(sc, XBQ_BIO);
291e4808c4bSKip Macy }
292e4808c4bSKip Macy 
293e4808c4bSKip Macy static __inline void
294e4808c4bSKip Macy xb_enqueue_bio(struct xb_softc *sc, struct bio *bp)
295e4808c4bSKip Macy {
296e4808c4bSKip Macy 	bioq_insert_tail(&sc->xb_bioq, bp);
297e4808c4bSKip Macy 	XBQ_ADD(sc, XBQ_BIO);
298e4808c4bSKip Macy }
299e4808c4bSKip Macy 
300e4808c4bSKip Macy static __inline void
301e4808c4bSKip Macy xb_requeue_bio(struct xb_softc *sc, struct bio *bp)
302e4808c4bSKip Macy {
303e4808c4bSKip Macy 	bioq_insert_head(&sc->xb_bioq, bp);
304e4808c4bSKip Macy 	XBQ_ADD(sc, XBQ_BIO);
305e4808c4bSKip Macy }
306e4808c4bSKip Macy 
307e4808c4bSKip Macy static __inline struct bio *
308e4808c4bSKip Macy xb_dequeue_bio(struct xb_softc *sc)
309e4808c4bSKip Macy {
310e4808c4bSKip Macy 	struct bio *bp;
311e4808c4bSKip Macy 
312e4808c4bSKip Macy 	if ((bp = bioq_first(&sc->xb_bioq)) != NULL) {
313e4808c4bSKip Macy 		bioq_remove(&sc->xb_bioq, bp);
314e4808c4bSKip Macy 		XBQ_REMOVE(sc, XBQ_BIO);
315e4808c4bSKip Macy 	}
316e4808c4bSKip Macy 	return (bp);
317e4808c4bSKip Macy }
31889e0f4d2SKip Macy 
31989e0f4d2SKip Macy #endif /* __XEN_DRIVERS_BLOCK_H__ */
32089e0f4d2SKip Macy 
321