1181643Skmacy/* 2199959Skmacy * XenBSD block device driver 3199959Skmacy * 4251195Sgibbs * Copyright (c) 2010-2013 Spectra Logic Corporation 5199960Skmacy * Copyright (c) 2009 Scott Long, Yahoo! 6199959Skmacy * Copyright (c) 2009 Frank Suchomel, Citrix 7199959Skmacy * Copyright (c) 2009 Doug F. Rabson, Citrix 8199959Skmacy * Copyright (c) 2005 Kip Macy 9199959Skmacy * Copyright (c) 2003-2004, Keir Fraser & Steve Hand 10199959Skmacy * Modifications by Mark A. Williamson are (c) Intel Research Cambridge 11199959Skmacy * 12199959Skmacy * 13199959Skmacy * Permission is hereby granted, free of charge, to any person obtaining a copy 14199959Skmacy * of this software and associated documentation files (the "Software"), to 15199959Skmacy * deal in the Software without restriction, including without limitation the 16199959Skmacy * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 17199959Skmacy * sell copies of the Software, and to permit persons to whom the Software is 18199959Skmacy * furnished to do so, subject to the following conditions: 19199959Skmacy * 20199959Skmacy * The above copyright notice and this permission notice shall be included in 21199959Skmacy * all copies or substantial portions of the Software. 22181643Skmacy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23181643Skmacy * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24181643Skmacy * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25181643Skmacy * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26181643Skmacy * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27199960Skmacy * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28199960Skmacy * DEALINGS IN THE SOFTWARE. 29181643Skmacy * 30181643Skmacy * $FreeBSD$ 31181643Skmacy */ 32181643Skmacy 33251195Sgibbs#ifndef __XEN_BLKFRONT_BLOCK_H__ 34251195Sgibbs#define __XEN_BLKFRONT_BLOCK_H__ 35214077Sgibbs#include <xen/blkif.h> 36181643Skmacy 37214077Sgibbs/** 38231839Sgibbs * Given a number of blkif segments, compute the maximum I/O size supported. 39231839Sgibbs * 40231839Sgibbs * \note This calculation assumes that all but the first and last segments 41231839Sgibbs * of the I/O are fully utilized. 42231839Sgibbs * 43231839Sgibbs * \note We reserve a segement from the maximum supported by the transport to 44231839Sgibbs * guarantee we can handle an unaligned transfer without the need to 45231839Sgibbs * use a bounce buffer. 46231839Sgibbs */ 47251195Sgibbs#define XBD_SEGS_TO_SIZE(segs) \ 48231839Sgibbs (((segs) - 1) * PAGE_SIZE) 49231839Sgibbs 50231839Sgibbs/** 51231839Sgibbs * Compute the maximum number of blkif segments requried to represent 52231839Sgibbs * an I/O of the given size. 53231839Sgibbs * 54231839Sgibbs * \note This calculation assumes that all but the first and last segments 55231839Sgibbs * of the I/O are fully utilized. 56231839Sgibbs * 57231839Sgibbs * \note We reserve a segement to guarantee we can handle an unaligned 58231839Sgibbs * transfer without the need to use a bounce buffer. 59231839Sgibbs */ 60251195Sgibbs#define XBD_SIZE_TO_SEGS(size) \ 61231839Sgibbs ((size / PAGE_SIZE) + 1) 62231839Sgibbs 63231839Sgibbs/** 64285738Sroyger * The maximum number of shared memory ring pages we will allow in a 65285738Sroyger * negotiated block-front/back communication channel. Allow enough 66285738Sroyger * ring space for all requests to be XBD_MAX_REQUEST_SIZE'd. 67285738Sroyger */ 68285738Sroyger#define XBD_MAX_RING_PAGES 32 69285738Sroyger 70285738Sroyger/** 71287801Scperciva * The maximum number of outstanding requests we will allow in a negotiated 72287801Scperciva * block-front/back communication channel. 73214077Sgibbs */ 74285738Sroyger#define XBD_MAX_REQUESTS \ 75285738Sroyger __CONST_RING_SIZE(blkif, PAGE_SIZE * XBD_MAX_RING_PAGES) 76214077Sgibbs 77214077Sgibbs/** 78287802Scperciva * The maximum number of blkif segments which can be provided per indirect 79287802Scperciva * page in an indirect request. 80214077Sgibbs */ 81287802Scperciva#define XBD_MAX_SEGMENTS_PER_PAGE \ 82287802Scperciva (PAGE_SIZE / sizeof(struct blkif_request_segment)) 83214077Sgibbs 84287802Scperciva/** 85287802Scperciva * The maximum number of blkif segments which can be provided in an indirect 86287802Scperciva * request. 87287802Scperciva */ 88287802Scperciva#define XBD_MAX_INDIRECT_SEGMENTS \ 89287802Scperciva (BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST * XBD_MAX_SEGMENTS_PER_PAGE) 90287802Scperciva 91287802Scperciva/** 92287802Scperciva * Compute the number of indirect segment pages required for an I/O with the 93287802Scperciva * specified number of indirect segments. 94287802Scperciva */ 95287802Scperciva#define XBD_INDIRECT_SEGS_TO_PAGES(segs) \ 96287802Scperciva ((segs + XBD_MAX_SEGMENTS_PER_PAGE - 1) / XBD_MAX_SEGMENTS_PER_PAGE) 97287802Scperciva 98251751Sgibbstypedef enum { 99251751Sgibbs XBDCF_Q_MASK = 0xFF, 100252260Sgibbs /* This command has contributed to xbd_qfrozen_cnt. */ 101251751Sgibbs XBDCF_FROZEN = 1<<8, 102252260Sgibbs /* Freeze the command queue on dispatch (i.e. single step command). */ 103252260Sgibbs XBDCF_Q_FREEZE = 1<<9, 104252260Sgibbs /* Bus DMA returned EINPROGRESS for this command. */ 105251772Sgibbs XBDCF_ASYNC_MAPPING = 1<<10, 106251751Sgibbs XBDCF_INITIALIZER = XBDCF_Q_MASK 107251751Sgibbs} xbdc_flag_t; 108251751Sgibbs 109251195Sgibbsstruct xbd_command; 110251195Sgibbstypedef void xbd_cbcf_t(struct xbd_command *); 111181643Skmacy 112251195Sgibbsstruct xbd_command { 113251195Sgibbs TAILQ_ENTRY(xbd_command) cm_link; 114251195Sgibbs struct xbd_softc *cm_sc; 115251751Sgibbs xbdc_flag_t cm_flags; 116251195Sgibbs bus_dmamap_t cm_map; 117251195Sgibbs uint64_t cm_id; 118251195Sgibbs grant_ref_t *cm_sg_refs; 119251195Sgibbs struct bio *cm_bp; 120251195Sgibbs grant_ref_t cm_gref_head; 121251195Sgibbs void *cm_data; 122251195Sgibbs size_t cm_datalen; 123251195Sgibbs u_int cm_nseg; 124251195Sgibbs int cm_operation; 125251195Sgibbs blkif_sector_t cm_sector_number; 126251195Sgibbs int cm_status; 127251195Sgibbs xbd_cbcf_t *cm_complete; 128287802Scperciva void *cm_indirectionpages; 129287802Scperciva grant_ref_t cm_indirectionrefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST]; 130181643Skmacy}; 131181643Skmacy 132251751Sgibbstypedef enum { 133251751Sgibbs XBD_Q_FREE, 134251751Sgibbs XBD_Q_READY, 135251751Sgibbs XBD_Q_BUSY, 136251751Sgibbs XBD_Q_COMPLETE, 137251751Sgibbs XBD_Q_BIO, 138251751Sgibbs XBD_Q_COUNT, 139251751Sgibbs XBD_Q_NONE = XBDCF_Q_MASK 140251751Sgibbs} xbd_q_index_t; 141181643Skmacy 142251751Sgibbstypedef struct xbd_cm_q { 143251751Sgibbs TAILQ_HEAD(, xbd_command) q_tailq; 144251751Sgibbs uint32_t q_length; 145251751Sgibbs uint32_t q_max; 146251751Sgibbs} xbd_cm_q_t; 147181643Skmacy 148251751Sgibbstypedef enum { 149251751Sgibbs XBD_STATE_DISCONNECTED, 150251751Sgibbs XBD_STATE_CONNECTED, 151251751Sgibbs XBD_STATE_SUSPENDED 152251751Sgibbs} xbd_state_t; 153181643Skmacy 154251751Sgibbstypedef enum { 155251772Sgibbs XBDF_NONE = 0, 156251772Sgibbs XBDF_OPEN = 1 << 0, /* drive is open (can't shut down) */ 157251772Sgibbs XBDF_BARRIER = 1 << 1, /* backend supports barriers */ 158252260Sgibbs XBDF_FLUSH = 1 << 2, /* backend supports flush */ 159252260Sgibbs XBDF_READY = 1 << 3, /* Is ready */ 160252260Sgibbs XBDF_CM_SHORTAGE = 1 << 4, /* Free cm resource shortage active. */ 161252260Sgibbs XBDF_GNT_SHORTAGE = 1 << 5, /* Grant ref resource shortage active */ 162298960Smav XBDF_WAIT_IDLE = 1 << 6, /* 163252260Sgibbs * No new work until oustanding work 164252260Sgibbs * completes. 165252260Sgibbs */ 166298960Smav XBDF_DISCARD = 1 << 7, /* backend supports discard */ 167298960Smav XBDF_PERSISTENT = 1 << 8 /* backend supports persistent grants */ 168251751Sgibbs} xbd_flag_t; 169251751Sgibbs 170181643Skmacy/* 171199960Skmacy * We have one of these per vbd, whether ide, scsi or 'other'. 172181643Skmacy */ 173251195Sgibbsstruct xbd_softc { 174251195Sgibbs device_t xbd_dev; 175251195Sgibbs struct disk *xbd_disk; /* disk params */ 176251195Sgibbs struct bio_queue_head xbd_bioq; /* sort queue */ 177251195Sgibbs int xbd_unit; 178251751Sgibbs xbd_flag_t xbd_flags; 179251772Sgibbs int xbd_qfrozen_cnt; 180251195Sgibbs int xbd_vdevice; 181251751Sgibbs xbd_state_t xbd_state; 182251195Sgibbs u_int xbd_ring_pages; 183251195Sgibbs uint32_t xbd_max_requests; 184251195Sgibbs uint32_t xbd_max_request_segments; 185251195Sgibbs uint32_t xbd_max_request_size; 186287802Scperciva uint32_t xbd_max_request_indirectpages; 187251195Sgibbs grant_ref_t xbd_ring_ref[XBD_MAX_RING_PAGES]; 188251195Sgibbs blkif_front_ring_t xbd_ring; 189255040Sgibbs xen_intr_handle_t xen_intr_handle; 190251195Sgibbs struct gnttab_free_callback xbd_callback; 191251751Sgibbs xbd_cm_q_t xbd_cm_q[XBD_Q_COUNT]; 192251195Sgibbs bus_dma_tag_t xbd_io_dmat; 193199960Skmacy 194181643Skmacy /** 195181643Skmacy * The number of people holding this device open. We won't allow a 196181643Skmacy * hot-unplug unless this is 0. 197181643Skmacy */ 198251195Sgibbs int xbd_users; 199251195Sgibbs struct mtx xbd_io_lock; 200214077Sgibbs 201251195Sgibbs struct xbd_command *xbd_shadow; 202181643Skmacy}; 203181643Skmacy 204251195Sgibbsint xbd_instance_create(struct xbd_softc *, blkif_sector_t sectors, int device, 205298960Smav uint16_t vdisk_info, unsigned long sector_size, 206298960Smav unsigned long phys_sector_size); 207199960Skmacy 208251751Sgibbsstatic inline void 209251751Sgibbsxbd_added_qentry(struct xbd_softc *sc, xbd_q_index_t index) 210251751Sgibbs{ 211251751Sgibbs struct xbd_cm_q *cmq; 212199960Skmacy 213251751Sgibbs cmq = &sc->xbd_cm_q[index]; 214251751Sgibbs cmq->q_length++; 215251751Sgibbs if (cmq->q_length > cmq->q_max) 216251751Sgibbs cmq->q_max = cmq->q_length; 217251751Sgibbs} 218199960Skmacy 219251751Sgibbsstatic inline void 220251751Sgibbsxbd_removed_qentry(struct xbd_softc *sc, xbd_q_index_t index) 221251751Sgibbs{ 222251751Sgibbs sc->xbd_cm_q[index].q_length--; 223251751Sgibbs} 224199960Skmacy 225252260Sgibbsstatic inline uint32_t 226252260Sgibbsxbd_queue_length(struct xbd_softc *sc, xbd_q_index_t index) 227252260Sgibbs{ 228252260Sgibbs return (sc->xbd_cm_q[index].q_length); 229252260Sgibbs} 230252260Sgibbs 231251751Sgibbsstatic inline void 232251751Sgibbsxbd_initq_cm(struct xbd_softc *sc, xbd_q_index_t index) 233251751Sgibbs{ 234251751Sgibbs struct xbd_cm_q *cmq; 235199960Skmacy 236251751Sgibbs cmq = &sc->xbd_cm_q[index]; 237251751Sgibbs TAILQ_INIT(&cmq->q_tailq); 238251751Sgibbs cmq->q_length = 0; 239251751Sgibbs cmq->q_max = 0; 240251751Sgibbs} 241199960Skmacy 242251751Sgibbsstatic inline void 243251751Sgibbsxbd_enqueue_cm(struct xbd_command *cm, xbd_q_index_t index) 244251751Sgibbs{ 245251751Sgibbs KASSERT(index != XBD_Q_BIO, 246251751Sgibbs ("%s: Commands cannot access the bio queue.", __func__)); 247251751Sgibbs if ((cm->cm_flags & XBDCF_Q_MASK) != XBD_Q_NONE) 248251751Sgibbs panic("%s: command %p is already on queue %d.", 249251751Sgibbs __func__, cm, cm->cm_flags & XBDCF_Q_MASK); 250251751Sgibbs TAILQ_INSERT_TAIL(&cm->cm_sc->xbd_cm_q[index].q_tailq, cm, cm_link); 251251751Sgibbs cm->cm_flags &= ~XBDCF_Q_MASK; 252251751Sgibbs cm->cm_flags |= index; 253251751Sgibbs xbd_added_qentry(cm->cm_sc, index); 254251751Sgibbs} 255251751Sgibbs 256251751Sgibbsstatic inline void 257251751Sgibbsxbd_requeue_cm(struct xbd_command *cm, xbd_q_index_t index) 258251751Sgibbs{ 259251751Sgibbs KASSERT(index != XBD_Q_BIO, 260251751Sgibbs ("%s: Commands cannot access the bio queue.", __func__)); 261251751Sgibbs if ((cm->cm_flags & XBDCF_Q_MASK) != XBD_Q_NONE) 262251751Sgibbs panic("%s: command %p is already on queue %d.", 263251751Sgibbs __func__, cm, cm->cm_flags & XBDCF_Q_MASK); 264251751Sgibbs TAILQ_INSERT_HEAD(&cm->cm_sc->xbd_cm_q[index].q_tailq, cm, cm_link); 265251751Sgibbs cm->cm_flags &= ~XBDCF_Q_MASK; 266251751Sgibbs cm->cm_flags |= index; 267251751Sgibbs xbd_added_qentry(cm->cm_sc, index); 268251751Sgibbs} 269251751Sgibbs 270251751Sgibbsstatic inline struct xbd_command * 271251751Sgibbsxbd_dequeue_cm(struct xbd_softc *sc, xbd_q_index_t index) 272251751Sgibbs{ 273251751Sgibbs struct xbd_command *cm; 274251751Sgibbs 275251751Sgibbs KASSERT(index != XBD_Q_BIO, 276251751Sgibbs ("%s: Commands cannot access the bio queue.", __func__)); 277251751Sgibbs 278251751Sgibbs if ((cm = TAILQ_FIRST(&sc->xbd_cm_q[index].q_tailq)) != NULL) { 279251751Sgibbs if ((cm->cm_flags & XBDCF_Q_MASK) != index) { 280251751Sgibbs panic("%s: command %p is on queue %d, " 281251751Sgibbs "not specified queue %d", 282251751Sgibbs __func__, cm, 283251751Sgibbs cm->cm_flags & XBDCF_Q_MASK, 284251751Sgibbs index); 285251751Sgibbs } 286251751Sgibbs TAILQ_REMOVE(&sc->xbd_cm_q[index].q_tailq, cm, cm_link); 287251751Sgibbs cm->cm_flags &= ~XBDCF_Q_MASK; 288251751Sgibbs cm->cm_flags |= XBD_Q_NONE; 289251751Sgibbs xbd_removed_qentry(cm->cm_sc, index); 290251751Sgibbs } 291251751Sgibbs return (cm); 292251751Sgibbs} 293251751Sgibbs 294251751Sgibbsstatic inline void 295251751Sgibbsxbd_remove_cm(struct xbd_command *cm, xbd_q_index_t expected_index) 296251751Sgibbs{ 297251751Sgibbs xbd_q_index_t index; 298251751Sgibbs 299251751Sgibbs index = cm->cm_flags & XBDCF_Q_MASK; 300251751Sgibbs 301251751Sgibbs KASSERT(index != XBD_Q_BIO, 302251751Sgibbs ("%s: Commands cannot access the bio queue.", __func__)); 303251751Sgibbs 304251751Sgibbs if (index != expected_index) { 305251751Sgibbs panic("%s: command %p is on queue %d, not specified queue %d", 306251751Sgibbs __func__, cm, index, expected_index); 307251751Sgibbs } 308251751Sgibbs TAILQ_REMOVE(&cm->cm_sc->xbd_cm_q[index].q_tailq, cm, cm_link); 309251751Sgibbs cm->cm_flags &= ~XBDCF_Q_MASK; 310251751Sgibbs cm->cm_flags |= XBD_Q_NONE; 311251751Sgibbs xbd_removed_qentry(cm->cm_sc, index); 312251751Sgibbs} 313251751Sgibbs 314252260Sgibbsstatic inline void 315251195Sgibbsxbd_initq_bio(struct xbd_softc *sc) 316199960Skmacy{ 317251195Sgibbs bioq_init(&sc->xbd_bioq); 318199960Skmacy} 319199960Skmacy 320252260Sgibbsstatic inline void 321251195Sgibbsxbd_enqueue_bio(struct xbd_softc *sc, struct bio *bp) 322199960Skmacy{ 323251195Sgibbs bioq_insert_tail(&sc->xbd_bioq, bp); 324251751Sgibbs xbd_added_qentry(sc, XBD_Q_BIO); 325199960Skmacy} 326199960Skmacy 327252260Sgibbsstatic inline void 328251195Sgibbsxbd_requeue_bio(struct xbd_softc *sc, struct bio *bp) 329199960Skmacy{ 330251195Sgibbs bioq_insert_head(&sc->xbd_bioq, bp); 331251751Sgibbs xbd_added_qentry(sc, XBD_Q_BIO); 332199960Skmacy} 333199960Skmacy 334252260Sgibbsstatic inline struct bio * 335251195Sgibbsxbd_dequeue_bio(struct xbd_softc *sc) 336199960Skmacy{ 337199960Skmacy struct bio *bp; 338199960Skmacy 339251195Sgibbs if ((bp = bioq_first(&sc->xbd_bioq)) != NULL) { 340251195Sgibbs bioq_remove(&sc->xbd_bioq, bp); 341251751Sgibbs xbd_removed_qentry(sc, XBD_Q_BIO); 342199960Skmacy } 343199960Skmacy return (bp); 344199960Skmacy} 345199960Skmacy 346251751Sgibbsstatic inline void 347251751Sgibbsxbd_initqs(struct xbd_softc *sc) 348251751Sgibbs{ 349251751Sgibbs u_int index; 350251751Sgibbs 351251751Sgibbs for (index = 0; index < XBD_Q_COUNT; index++) 352251751Sgibbs xbd_initq_cm(sc, index); 353251751Sgibbs 354251751Sgibbs xbd_initq_bio(sc); 355251751Sgibbs} 356251751Sgibbs 357251195Sgibbs#endif /* __XEN_BLKFRONT_BLOCK_H__ */ 358