1 1.45 isaki /* $NetBSD: ld_virtio.c,v 1.45 2025/08/27 04:41:24 isaki Exp $ */ 2 1.1 hannken 3 1.1 hannken /* 4 1.1 hannken * Copyright (c) 2010 Minoura Makoto. 5 1.1 hannken * All rights reserved. 6 1.1 hannken * 7 1.1 hannken * Redistribution and use in source and binary forms, with or without 8 1.1 hannken * modification, are permitted provided that the following conditions 9 1.1 hannken * are met: 10 1.1 hannken * 1. Redistributions of source code must retain the above copyright 11 1.1 hannken * notice, this list of conditions and the following disclaimer. 12 1.1 hannken * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 hannken * notice, this list of conditions and the following disclaimer in the 14 1.1 hannken * documentation and/or other materials provided with the distribution. 15 1.1 hannken * 16 1.1 hannken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 hannken * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 hannken * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 hannken * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 hannken * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.1 hannken * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.1 hannken * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.1 hannken * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.1 hannken * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.1 hannken * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.1 hannken */ 27 1.1 hannken 28 1.1 hannken #include <sys/cdefs.h> 29 1.45 isaki __KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.45 2025/08/27 04:41:24 isaki Exp $"); 30 1.1 hannken 31 1.1 hannken #include <sys/param.h> 32 1.1 hannken #include <sys/systm.h> 33 1.1 hannken #include <sys/kernel.h> 34 1.1 hannken #include <sys/buf.h> 35 1.11 jdolecek #include <sys/bufq.h> 36 1.1 hannken #include <sys/bus.h> 37 1.1 hannken #include <sys/device.h> 38 1.1 hannken #include <sys/disk.h> 39 1.1 hannken #include <sys/mutex.h> 40 1.12 pgoyette #include <sys/module.h> 41 1.36 jakllsch #include <sys/kmem.h> 42 1.1 hannken 43 1.1 hannken #include <dev/ldvar.h> 44 1.1 hannken #include <dev/pci/virtioreg.h> 45 1.1 hannken #include <dev/pci/virtiovar.h> 46 1.1 hannken 47 1.12 pgoyette #include "ioconf.h" 48 1.12 pgoyette 49 1.1 hannken /* 50 1.1 hannken * ld_virtioreg: 51 1.1 hannken */ 52 1.1 hannken /* Configuration registers */ 53 1.1 hannken #define VIRTIO_BLK_CONFIG_CAPACITY 0 /* 64bit */ 54 1.1 hannken #define VIRTIO_BLK_CONFIG_SIZE_MAX 8 /* 32bit */ 55 1.1 hannken #define VIRTIO_BLK_CONFIG_SEG_MAX 12 /* 32bit */ 56 1.1 hannken #define VIRTIO_BLK_CONFIG_GEOMETRY_C 16 /* 16bit */ 57 1.1 hannken #define VIRTIO_BLK_CONFIG_GEOMETRY_H 18 /* 8bit */ 58 1.1 hannken #define VIRTIO_BLK_CONFIG_GEOMETRY_S 19 /* 8bit */ 59 1.1 hannken #define VIRTIO_BLK_CONFIG_BLK_SIZE 20 /* 32bit */ 60 1.42 jakllsch #define VIRTIO_BLK_CONFIG_PHYSICAL_BLOCK_EXP 24 /* 8bit */ 61 1.42 jakllsch #define VIRTIO_BLK_CONFIG_ALIGNMENT_OFFSET 25 /* 8bit */ 62 1.42 jakllsch #define VIRTIO_BLK_CONFIG_MIN_IO_SIZE 26 /* 16bit */ 63 1.42 jakllsch #define VIRTIO_BLK_CONFIG_OPT_IO_SIZE 28 /* 32bit */ 64 1.18 jakllsch #define VIRTIO_BLK_CONFIG_WRITEBACK 32 /* 8bit */ 65 1.36 jakllsch #define VIRTIO_BLK_CONFIG_NUM_QUEUES 34 /* 16bit */ 66 1.36 jakllsch #define VIRTIO_BLK_CONFIG_MAX_DISCARD_SECTORS 36 /* 32bit */ 67 1.36 jakllsch #define VIRTIO_BLK_CONFIG_MAX_DISCARD_SEG 40 /* 32bit */ 68 1.36 jakllsch #define VIRTIO_BLK_CONFIG_DISCARD_SECTOR_ALIGNMENT 44 /* 32bit */ 69 1.1 hannken 70 1.1 hannken /* Feature bits */ 71 1.1 hannken #define VIRTIO_BLK_F_BARRIER (1<<0) 72 1.1 hannken #define VIRTIO_BLK_F_SIZE_MAX (1<<1) 73 1.1 hannken #define VIRTIO_BLK_F_SEG_MAX (1<<2) 74 1.1 hannken #define VIRTIO_BLK_F_GEOMETRY (1<<4) 75 1.1 hannken #define VIRTIO_BLK_F_RO (1<<5) 76 1.1 hannken #define VIRTIO_BLK_F_BLK_SIZE (1<<6) 77 1.1 hannken #define VIRTIO_BLK_F_SCSI (1<<7) 78 1.1 hannken #define VIRTIO_BLK_F_FLUSH (1<<9) 79 1.18 jakllsch #define VIRTIO_BLK_F_TOPOLOGY (1<<10) 80 1.18 jakllsch #define VIRTIO_BLK_F_CONFIG_WCE (1<<11) 81 1.36 jakllsch #define VIRTIO_BLK_F_MQ (1<<12) 82 1.36 jakllsch #define VIRTIO_BLK_F_DISCARD (1<<13) 83 1.36 jakllsch #define VIRTIO_BLK_F_WRITE_ZEROES (1<<14) 84 1.36 jakllsch #define VIRTIO_BLK_F_LIFETIME (1<<15) 85 1.36 jakllsch #define VIRTIO_BLK_F_SECURE_ERASE (1<<16) 86 1.1 hannken 87 1.17 jakllsch /* 88 1.9 christos * Each block request uses at least two segments - one for the header 89 1.9 christos * and one for the status. 90 1.17 jakllsch */ 91 1.34 isaki #define VIRTIO_BLK_CTRL_SEGMENTS 2 92 1.9 christos 93 1.30 uwe #define VIRTIO_BLK_FLAG_BITS \ 94 1.30 uwe VIRTIO_COMMON_FLAG_BITS \ 95 1.36 jakllsch "b\x10" "SECURE_ERASE\0" \ 96 1.36 jakllsch "b\x0f" "LIFETIME\0" \ 97 1.36 jakllsch "b\x0e" "WRITE_ZEROES\0" \ 98 1.36 jakllsch "b\x0d" "DISCARD\0" \ 99 1.36 jakllsch "b\x0c" "MQ\0" \ 100 1.30 uwe "b\x0b" "CONFIG_WCE\0" \ 101 1.30 uwe "b\x0a" "TOPOLOGY\0" \ 102 1.30 uwe "b\x09" "FLUSH\0" \ 103 1.30 uwe "b\x07" "SCSI\0" \ 104 1.30 uwe "b\x06" "BLK_SIZE\0" \ 105 1.30 uwe "b\x05" "RO\0" \ 106 1.30 uwe "b\x04" "GEOMETRY\0" \ 107 1.30 uwe "b\x02" "SEG_MAX\0" \ 108 1.30 uwe "b\x01" "SIZE_MAX\0" \ 109 1.30 uwe "b\x00" "BARRIER\0" 110 1.9 christos 111 1.1 hannken /* Command */ 112 1.1 hannken #define VIRTIO_BLK_T_IN 0 113 1.1 hannken #define VIRTIO_BLK_T_OUT 1 114 1.18 jakllsch #define VIRTIO_BLK_T_FLUSH 4 115 1.36 jakllsch #define VIRTIO_BLK_T_GET_ID 8 116 1.36 jakllsch #define VIRTIO_BLK_T_GET_LIFETIME 10 117 1.36 jakllsch #define VIRTIO_BLK_T_DISCARD 11 118 1.36 jakllsch #define VIRTIO_BLK_T_WRITE_ZEROES 13 119 1.36 jakllsch #define VIRTIO_BLK_T_SECURE_ERASE 14 120 1.1 hannken #define VIRTIO_BLK_T_BARRIER 0x80000000 121 1.1 hannken 122 1.21 jakllsch /* Sector */ 123 1.21 jakllsch #define VIRTIO_BLK_BSIZE 512 124 1.21 jakllsch 125 1.1 hannken /* Status */ 126 1.1 hannken #define VIRTIO_BLK_S_OK 0 127 1.1 hannken #define VIRTIO_BLK_S_IOERR 1 128 1.18 jakllsch #define VIRTIO_BLK_S_UNSUPP 2 129 1.1 hannken 130 1.1 hannken /* Request header structure */ 131 1.1 hannken struct virtio_blk_req_hdr { 132 1.1 hannken uint32_t type; /* VIRTIO_BLK_T_* */ 133 1.1 hannken uint32_t ioprio; 134 1.1 hannken uint64_t sector; 135 1.1 hannken } __packed; 136 1.21 jakllsch /* payload and 1 byte status follows */ 137 1.1 hannken 138 1.36 jakllsch struct virtio_blk_discard_write_zeroes { 139 1.36 jakllsch uint64_t sector; 140 1.36 jakllsch uint32_t num_sectors; 141 1.36 jakllsch union { 142 1.36 jakllsch uint32_t flags; 143 1.36 jakllsch struct { 144 1.36 jakllsch uint32_t unmap:1; 145 1.36 jakllsch uint32_t reserved:31; 146 1.36 jakllsch }; 147 1.36 jakllsch }; 148 1.36 jakllsch } __packed; 149 1.1 hannken 150 1.1 hannken /* 151 1.1 hannken * ld_virtiovar: 152 1.1 hannken */ 153 1.1 hannken struct virtio_blk_req { 154 1.1 hannken struct virtio_blk_req_hdr vr_hdr; 155 1.1 hannken uint8_t vr_status; 156 1.1 hannken struct buf *vr_bp; 157 1.20 jakllsch #define DUMMY_VR_BP ((void *)1) 158 1.1 hannken bus_dmamap_t vr_cmdsts; 159 1.1 hannken bus_dmamap_t vr_payload; 160 1.36 jakllsch void * vr_datap; 161 1.36 jakllsch size_t vr_datas; 162 1.1 hannken }; 163 1.1 hannken 164 1.1 hannken struct ld_virtio_softc { 165 1.1 hannken struct ld_softc sc_ld; 166 1.1 hannken device_t sc_dev; 167 1.1 hannken 168 1.35 riastrad uint32_t sc_seg_max; /* max number of segs in xfer */ 169 1.35 riastrad uint32_t sc_size_max; /* max size of single seg */ 170 1.35 riastrad 171 1.1 hannken struct virtio_softc *sc_virtio; 172 1.9 christos struct virtqueue sc_vq; 173 1.1 hannken 174 1.1 hannken struct virtio_blk_req *sc_reqs; 175 1.9 christos bus_dma_segment_t sc_reqs_seg; 176 1.1 hannken 177 1.1 hannken int sc_readonly; 178 1.20 jakllsch 179 1.20 jakllsch enum { 180 1.20 jakllsch SYNC_FREE, SYNC_BUSY, SYNC_DONE 181 1.20 jakllsch } sc_sync_use; 182 1.20 jakllsch kcondvar_t sc_sync_wait; 183 1.20 jakllsch kmutex_t sc_sync_wait_lock; 184 1.20 jakllsch uint8_t sc_sync_status; 185 1.39 mlelstv uint8_t *sc_typename; 186 1.36 jakllsch 187 1.36 jakllsch uint32_t sc_max_discard_sectors; 188 1.36 jakllsch uint32_t sc_max_discard_seg; 189 1.36 jakllsch #if 0 190 1.36 jakllsch uint32_t sc_discard_sector_alignment; 191 1.36 jakllsch #endif 192 1.1 hannken }; 193 1.1 hannken 194 1.1 hannken static int ld_virtio_match(device_t, cfdata_t, void *); 195 1.1 hannken static void ld_virtio_attach(device_t, device_t, void *); 196 1.1 hannken static int ld_virtio_detach(device_t, int); 197 1.1 hannken 198 1.1 hannken CFATTACH_DECL_NEW(ld_virtio, sizeof(struct ld_virtio_softc), 199 1.1 hannken ld_virtio_match, ld_virtio_attach, ld_virtio_detach, NULL); 200 1.1 hannken 201 1.1 hannken static int 202 1.1 hannken ld_virtio_match(device_t parent, cfdata_t match, void *aux) 203 1.1 hannken { 204 1.15 jdolecek struct virtio_attach_args *va = aux; 205 1.1 hannken 206 1.29 reinoud if (va->sc_childdevid == VIRTIO_DEVICE_ID_BLOCK) 207 1.1 hannken return 1; 208 1.1 hannken 209 1.1 hannken return 0; 210 1.1 hannken } 211 1.1 hannken 212 1.1 hannken static int ld_virtio_vq_done(struct virtqueue *); 213 1.43 rin static int ld_virtio_dump(struct ld_softc *, void *, daddr_t, int); 214 1.1 hannken static int ld_virtio_start(struct ld_softc *, struct buf *); 215 1.20 jakllsch static int ld_virtio_ioctl(struct ld_softc *, u_long, void *, int32_t, bool); 216 1.40 mlelstv static int ld_virtio_info(struct ld_softc *, bool); 217 1.36 jakllsch static int ld_virtio_discard(struct ld_softc *, struct buf *); 218 1.1 hannken 219 1.1 hannken static int 220 1.1 hannken ld_virtio_alloc_reqs(struct ld_virtio_softc *sc, int qsize) 221 1.1 hannken { 222 1.1 hannken int allocsize, r, rsegs, i; 223 1.1 hannken struct ld_softc *ld = &sc->sc_ld; 224 1.1 hannken void *vaddr; 225 1.1 hannken 226 1.1 hannken allocsize = sizeof(struct virtio_blk_req) * qsize; 227 1.15 jdolecek r = bus_dmamem_alloc(virtio_dmat(sc->sc_virtio), allocsize, 0, 0, 228 1.28 skrll &sc->sc_reqs_seg, 1, &rsegs, BUS_DMA_WAITOK); 229 1.1 hannken if (r != 0) { 230 1.1 hannken aprint_error_dev(sc->sc_dev, 231 1.1 hannken "DMA memory allocation failed, size %d, " 232 1.1 hannken "error code %d\n", allocsize, r); 233 1.1 hannken goto err_none; 234 1.1 hannken } 235 1.15 jdolecek r = bus_dmamem_map(virtio_dmat(sc->sc_virtio), 236 1.9 christos &sc->sc_reqs_seg, 1, allocsize, 237 1.28 skrll &vaddr, BUS_DMA_WAITOK); 238 1.1 hannken if (r != 0) { 239 1.1 hannken aprint_error_dev(sc->sc_dev, 240 1.1 hannken "DMA memory map failed, " 241 1.1 hannken "error code %d\n", r); 242 1.1 hannken goto err_dmamem_alloc; 243 1.1 hannken } 244 1.1 hannken sc->sc_reqs = vaddr; 245 1.1 hannken memset(vaddr, 0, allocsize); 246 1.1 hannken for (i = 0; i < qsize; i++) { 247 1.1 hannken struct virtio_blk_req *vr = &sc->sc_reqs[i]; 248 1.15 jdolecek r = bus_dmamap_create(virtio_dmat(sc->sc_virtio), 249 1.1 hannken offsetof(struct virtio_blk_req, vr_bp), 250 1.1 hannken 1, 251 1.1 hannken offsetof(struct virtio_blk_req, vr_bp), 252 1.1 hannken 0, 253 1.28 skrll BUS_DMA_WAITOK|BUS_DMA_ALLOCNOW, 254 1.1 hannken &vr->vr_cmdsts); 255 1.1 hannken if (r != 0) { 256 1.1 hannken aprint_error_dev(sc->sc_dev, 257 1.1 hannken "command dmamap creation failed, " 258 1.1 hannken "error code %d\n", r); 259 1.1 hannken goto err_reqs; 260 1.1 hannken } 261 1.15 jdolecek r = bus_dmamap_load(virtio_dmat(sc->sc_virtio), vr->vr_cmdsts, 262 1.1 hannken &vr->vr_hdr, 263 1.1 hannken offsetof(struct virtio_blk_req, vr_bp), 264 1.28 skrll NULL, BUS_DMA_WAITOK); 265 1.1 hannken if (r != 0) { 266 1.1 hannken aprint_error_dev(sc->sc_dev, 267 1.1 hannken "command dmamap load failed, " 268 1.1 hannken "error code %d\n", r); 269 1.1 hannken goto err_reqs; 270 1.1 hannken } 271 1.15 jdolecek r = bus_dmamap_create(virtio_dmat(sc->sc_virtio), 272 1.35 riastrad /*size*/ld->sc_maxxfer, 273 1.35 riastrad /*nseg*/sc->sc_seg_max, 274 1.35 riastrad /*maxsegsz*/sc->sc_size_max, 275 1.35 riastrad /*boundary*/0, 276 1.28 skrll BUS_DMA_WAITOK|BUS_DMA_ALLOCNOW, 277 1.1 hannken &vr->vr_payload); 278 1.1 hannken if (r != 0) { 279 1.1 hannken aprint_error_dev(sc->sc_dev, 280 1.1 hannken "payload dmamap creation failed, " 281 1.1 hannken "error code %d\n", r); 282 1.1 hannken goto err_reqs; 283 1.1 hannken } 284 1.36 jakllsch vr->vr_datap = NULL; 285 1.36 jakllsch vr->vr_datas = 0; 286 1.1 hannken } 287 1.1 hannken return 0; 288 1.1 hannken 289 1.1 hannken err_reqs: 290 1.1 hannken for (i = 0; i < qsize; i++) { 291 1.1 hannken struct virtio_blk_req *vr = &sc->sc_reqs[i]; 292 1.1 hannken if (vr->vr_cmdsts) { 293 1.15 jdolecek bus_dmamap_destroy(virtio_dmat(sc->sc_virtio), 294 1.1 hannken vr->vr_cmdsts); 295 1.1 hannken vr->vr_cmdsts = 0; 296 1.1 hannken } 297 1.1 hannken if (vr->vr_payload) { 298 1.15 jdolecek bus_dmamap_destroy(virtio_dmat(sc->sc_virtio), 299 1.1 hannken vr->vr_payload); 300 1.1 hannken vr->vr_payload = 0; 301 1.1 hannken } 302 1.1 hannken } 303 1.15 jdolecek bus_dmamem_unmap(virtio_dmat(sc->sc_virtio), sc->sc_reqs, allocsize); 304 1.1 hannken err_dmamem_alloc: 305 1.15 jdolecek bus_dmamem_free(virtio_dmat(sc->sc_virtio), &sc->sc_reqs_seg, 1); 306 1.1 hannken err_none: 307 1.1 hannken return -1; 308 1.1 hannken } 309 1.1 hannken 310 1.1 hannken static void 311 1.1 hannken ld_virtio_attach(device_t parent, device_t self, void *aux) 312 1.1 hannken { 313 1.1 hannken struct ld_virtio_softc *sc = device_private(self); 314 1.1 hannken struct ld_softc *ld = &sc->sc_ld; 315 1.1 hannken struct virtio_softc *vsc = device_private(parent); 316 1.29 reinoud uint64_t features; 317 1.35 riastrad int qsize; 318 1.1 hannken 319 1.15 jdolecek if (virtio_child(vsc) != NULL) { 320 1.1 hannken aprint_normal(": child already attached for %s; " 321 1.10 msaitoh "something wrong...\n", device_xname(parent)); 322 1.1 hannken return; 323 1.1 hannken } 324 1.1 hannken 325 1.1 hannken sc->sc_dev = self; 326 1.1 hannken sc->sc_virtio = vsc; 327 1.1 hannken 328 1.31 yamaguch virtio_child_attach_start(vsc, self, IPL_BIO, 329 1.15 jdolecek (VIRTIO_BLK_F_SIZE_MAX | VIRTIO_BLK_F_SEG_MAX | 330 1.20 jakllsch VIRTIO_BLK_F_GEOMETRY | VIRTIO_BLK_F_RO | VIRTIO_BLK_F_BLK_SIZE | 331 1.42 jakllsch VIRTIO_BLK_F_FLUSH | VIRTIO_BLK_F_TOPOLOGY | 332 1.42 jakllsch VIRTIO_BLK_F_CONFIG_WCE | VIRTIO_BLK_F_DISCARD), 333 1.15 jdolecek VIRTIO_BLK_FLAG_BITS); 334 1.15 jdolecek 335 1.15 jdolecek features = virtio_features(vsc); 336 1.29 reinoud if (features == 0) 337 1.29 reinoud goto err; 338 1.15 jdolecek 339 1.1 hannken if (features & VIRTIO_BLK_F_RO) 340 1.1 hannken sc->sc_readonly = 1; 341 1.1 hannken else 342 1.1 hannken sc->sc_readonly = 0; 343 1.1 hannken 344 1.3 hannken if (features & VIRTIO_BLK_F_BLK_SIZE) { 345 1.3 hannken ld->sc_secsize = virtio_read_device_config_4(vsc, 346 1.3 hannken VIRTIO_BLK_CONFIG_BLK_SIZE); 347 1.9 christos } else 348 1.21 jakllsch ld->sc_secsize = VIRTIO_BLK_BSIZE; 349 1.9 christos 350 1.35 riastrad if (features & VIRTIO_BLK_F_SEG_MAX) { 351 1.35 riastrad sc->sc_seg_max = virtio_read_device_config_4(vsc, 352 1.35 riastrad VIRTIO_BLK_CONFIG_SEG_MAX); 353 1.35 riastrad if (sc->sc_seg_max == 0) { 354 1.35 riastrad aprint_error_dev(sc->sc_dev, 355 1.35 riastrad "Invalid SEG_MAX %d\n", sc->sc_seg_max); 356 1.35 riastrad goto err; 357 1.35 riastrad } 358 1.35 riastrad } else { 359 1.35 riastrad sc->sc_seg_max = 1; 360 1.35 riastrad aprint_verbose_dev(sc->sc_dev, 361 1.35 riastrad "Unknown SEG_MAX, assuming %"PRIu32"\n", sc->sc_seg_max); 362 1.35 riastrad } 363 1.35 riastrad 364 1.35 riastrad /* At least genfs_io assumes size_max*seg_max >= MAXPHYS. */ 365 1.9 christos if (features & VIRTIO_BLK_F_SIZE_MAX) { 366 1.35 riastrad sc->sc_size_max = virtio_read_device_config_4(vsc, 367 1.9 christos VIRTIO_BLK_CONFIG_SIZE_MAX); 368 1.35 riastrad if (sc->sc_size_max < MAXPHYS/sc->sc_seg_max) { 369 1.9 christos aprint_error_dev(sc->sc_dev, 370 1.35 riastrad "Too small SIZE_MAX %d minimum is %d\n", 371 1.35 riastrad sc->sc_size_max, MAXPHYS/sc->sc_seg_max); 372 1.9 christos // goto err; 373 1.35 riastrad sc->sc_size_max = MAXPHYS/sc->sc_seg_max; 374 1.35 riastrad } else if (sc->sc_size_max > MAXPHYS) { 375 1.35 riastrad aprint_verbose_dev(sc->sc_dev, 376 1.35 riastrad "Clip SIZE_MAX from %d to %d\n", 377 1.35 riastrad sc->sc_size_max, MAXPHYS); 378 1.35 riastrad sc->sc_size_max = MAXPHYS; 379 1.9 christos } 380 1.35 riastrad } else { 381 1.35 riastrad sc->sc_size_max = MAXPHYS; 382 1.35 riastrad aprint_verbose_dev(sc->sc_dev, 383 1.35 riastrad "Unknown SIZE_MAX, assuming %"PRIu32"\n", 384 1.35 riastrad sc->sc_size_max); 385 1.35 riastrad } 386 1.9 christos 387 1.35 riastrad aprint_normal_dev(sc->sc_dev, "max %"PRIu32" segs" 388 1.35 riastrad " of max %"PRIu32" bytes\n", 389 1.35 riastrad sc->sc_seg_max, sc->sc_size_max); 390 1.1 hannken 391 1.32 yamaguch virtio_init_vq_vqdone(vsc, &sc->sc_vq, 0, 392 1.32 yamaguch ld_virtio_vq_done); 393 1.32 yamaguch 394 1.35 riastrad if (virtio_alloc_vq(vsc, &sc->sc_vq, sc->sc_size_max, 395 1.35 riastrad sc->sc_seg_max + VIRTIO_BLK_CTRL_SEGMENTS, "I/O request") != 0) 396 1.1 hannken goto err; 397 1.9 christos qsize = sc->sc_vq.vq_num; 398 1.1 hannken 399 1.31 yamaguch if (virtio_child_attach_finish(vsc, &sc->sc_vq, 1, 400 1.32 yamaguch NULL, VIRTIO_F_INTR_MSIX) != 0) 401 1.15 jdolecek goto err; 402 1.15 jdolecek 403 1.1 hannken ld->sc_dv = self; 404 1.1 hannken ld->sc_secperunit = virtio_read_device_config_8(vsc, 405 1.21 jakllsch VIRTIO_BLK_CONFIG_CAPACITY) / (ld->sc_secsize / VIRTIO_BLK_BSIZE); 406 1.35 riastrad 407 1.35 riastrad /* 408 1.35 riastrad * Clamp ld->sc_maxxfer to MAXPHYS before ld_virtio_alloc_reqs 409 1.35 riastrad * allocates DMA maps of at most ld->sc_maxxfer bytes. 410 1.35 riastrad * ldattach will also clamp to MAXPHYS, but not until after 411 1.35 riastrad * ld_virtio_alloc_reqs is done, so that doesn't help. 412 1.35 riastrad */ 413 1.35 riastrad ld->sc_maxxfer = MIN(MAXPHYS, sc->sc_size_max * sc->sc_seg_max); 414 1.35 riastrad 415 1.1 hannken if (features & VIRTIO_BLK_F_GEOMETRY) { 416 1.1 hannken ld->sc_ncylinders = virtio_read_device_config_2(vsc, 417 1.1 hannken VIRTIO_BLK_CONFIG_GEOMETRY_C); 418 1.1 hannken ld->sc_nheads = virtio_read_device_config_1(vsc, 419 1.1 hannken VIRTIO_BLK_CONFIG_GEOMETRY_H); 420 1.1 hannken ld->sc_nsectors = virtio_read_device_config_1(vsc, 421 1.1 hannken VIRTIO_BLK_CONFIG_GEOMETRY_S); 422 1.1 hannken } 423 1.42 jakllsch if (features & VIRTIO_BLK_F_TOPOLOGY) { 424 1.42 jakllsch ld->sc_alignedsec = virtio_read_device_config_1(vsc, 425 1.42 jakllsch VIRTIO_BLK_CONFIG_ALIGNMENT_OFFSET); 426 1.42 jakllsch ld->sc_physsecsize = ld->sc_secsize << 427 1.42 jakllsch virtio_read_device_config_1(vsc, 428 1.42 jakllsch VIRTIO_BLK_CONFIG_PHYSICAL_BLOCK_EXP); 429 1.42 jakllsch } 430 1.20 jakllsch ld->sc_maxqueuecnt = qsize - 1; /* reserve slot for dumps, flushes */ 431 1.1 hannken 432 1.1 hannken if (ld_virtio_alloc_reqs(sc, qsize) < 0) 433 1.1 hannken goto err; 434 1.1 hannken 435 1.20 jakllsch cv_init(&sc->sc_sync_wait, "vblksync"); 436 1.20 jakllsch mutex_init(&sc->sc_sync_wait_lock, MUTEX_DEFAULT, IPL_BIO); 437 1.20 jakllsch sc->sc_sync_use = SYNC_FREE; 438 1.20 jakllsch 439 1.1 hannken ld->sc_dump = ld_virtio_dump; 440 1.1 hannken ld->sc_start = ld_virtio_start; 441 1.20 jakllsch ld->sc_ioctl = ld_virtio_ioctl; 442 1.1 hannken 443 1.40 mlelstv if (ld_virtio_info(ld, true) == 0) 444 1.39 mlelstv ld->sc_typename = sc->sc_typename; 445 1.39 mlelstv else 446 1.39 mlelstv ld->sc_typename = __UNCONST("Virtio Block Device"); 447 1.39 mlelstv 448 1.36 jakllsch if (features & VIRTIO_BLK_F_DISCARD) { 449 1.36 jakllsch ld->sc_discard = ld_virtio_discard; 450 1.36 jakllsch sc->sc_max_discard_sectors = virtio_read_device_config_4(vsc, 451 1.36 jakllsch VIRTIO_BLK_CONFIG_MAX_DISCARD_SECTORS); 452 1.36 jakllsch sc->sc_max_discard_seg = virtio_read_device_config_4(vsc, 453 1.36 jakllsch VIRTIO_BLK_CONFIG_MAX_DISCARD_SEG); 454 1.36 jakllsch #if 0 455 1.36 jakllsch sc->sc_discard_sector_alignment = 456 1.36 jakllsch virtio_read_device_config_4(vsc, 457 1.36 jakllsch VIRTIO_BLK_CONFIG_DISCARD_SECTOR_ALIGNMENT); 458 1.36 jakllsch #endif 459 1.36 jakllsch } 460 1.36 jakllsch 461 1.16 mlelstv ld->sc_flags = LDF_ENABLED | LDF_MPSAFE; 462 1.11 jdolecek ldattach(ld, BUFQ_DISK_DEFAULT_STRAT); 463 1.1 hannken 464 1.1 hannken return; 465 1.1 hannken 466 1.1 hannken err: 467 1.15 jdolecek virtio_child_attach_failed(vsc); 468 1.1 hannken return; 469 1.1 hannken } 470 1.1 hannken 471 1.40 mlelstv static int __used 472 1.40 mlelstv ld_virtio_info(struct ld_softc *ld, bool poll) 473 1.39 mlelstv { 474 1.39 mlelstv struct ld_virtio_softc *sc = device_private(ld->sc_dv); 475 1.39 mlelstv struct virtio_softc *vsc = sc->sc_virtio; 476 1.39 mlelstv struct virtqueue *vq = &sc->sc_vq; 477 1.39 mlelstv struct virtio_blk_req *vr; 478 1.39 mlelstv int r; 479 1.39 mlelstv int slot; 480 1.41 mlelstv uint8_t *id_data; /* virtio v1.2 5.2.6 */ 481 1.41 mlelstv size_t id_len = 20; 482 1.40 mlelstv bool unload = false; 483 1.39 mlelstv 484 1.39 mlelstv if (sc->sc_typename != NULL) { 485 1.39 mlelstv kmem_strfree(sc->sc_typename); 486 1.39 mlelstv sc->sc_typename = NULL; 487 1.39 mlelstv } 488 1.39 mlelstv 489 1.41 mlelstv id_data = kmem_alloc(id_len, KM_SLEEP); 490 1.41 mlelstv 491 1.40 mlelstv mutex_enter(&sc->sc_sync_wait_lock); 492 1.40 mlelstv while (sc->sc_sync_use != SYNC_FREE) { 493 1.40 mlelstv if (poll) { 494 1.40 mlelstv mutex_exit(&sc->sc_sync_wait_lock); 495 1.40 mlelstv ld_virtio_vq_done(vq); 496 1.40 mlelstv mutex_enter(&sc->sc_sync_wait_lock); 497 1.40 mlelstv continue; 498 1.40 mlelstv } 499 1.40 mlelstv cv_wait(&sc->sc_sync_wait, &sc->sc_sync_wait_lock); 500 1.40 mlelstv } 501 1.40 mlelstv sc->sc_sync_use = SYNC_BUSY; 502 1.40 mlelstv mutex_exit(&sc->sc_sync_wait_lock); 503 1.40 mlelstv 504 1.39 mlelstv r = virtio_enqueue_prep(vsc, vq, &slot); 505 1.39 mlelstv if (r != 0) 506 1.40 mlelstv goto done; 507 1.39 mlelstv 508 1.39 mlelstv vr = &sc->sc_reqs[slot]; 509 1.39 mlelstv KASSERT(vr->vr_bp == NULL); 510 1.39 mlelstv 511 1.39 mlelstv r = bus_dmamap_load(virtio_dmat(vsc), vr->vr_payload, 512 1.41 mlelstv id_data, id_len, NULL, 513 1.39 mlelstv BUS_DMA_READ|BUS_DMA_NOWAIT); 514 1.39 mlelstv if (r != 0) { 515 1.39 mlelstv aprint_error_dev(sc->sc_dev, 516 1.39 mlelstv "payload dmamap failed, error code %d\n", r); 517 1.39 mlelstv virtio_enqueue_abort(vsc, vq, slot); 518 1.40 mlelstv goto done; 519 1.39 mlelstv } 520 1.40 mlelstv unload = true; 521 1.39 mlelstv 522 1.39 mlelstv KASSERT(vr->vr_payload->dm_nsegs <= sc->sc_seg_max); 523 1.39 mlelstv r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs + 524 1.39 mlelstv VIRTIO_BLK_CTRL_SEGMENTS); 525 1.39 mlelstv if (r != 0) { 526 1.39 mlelstv bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload); 527 1.40 mlelstv goto done; 528 1.39 mlelstv } 529 1.39 mlelstv 530 1.39 mlelstv vr->vr_bp = DUMMY_VR_BP; 531 1.39 mlelstv vr->vr_hdr.type = virtio_rw32(vsc, VIRTIO_BLK_T_GET_ID); 532 1.39 mlelstv vr->vr_hdr.ioprio = virtio_rw32(vsc, 0); 533 1.39 mlelstv vr->vr_hdr.sector = virtio_rw64(vsc, 0); 534 1.39 mlelstv 535 1.39 mlelstv bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 536 1.39 mlelstv 0, sizeof(struct virtio_blk_req_hdr), 537 1.39 mlelstv BUS_DMASYNC_PREWRITE); 538 1.39 mlelstv bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 539 1.41 mlelstv 0, id_len, 540 1.39 mlelstv BUS_DMASYNC_PREREAD); 541 1.39 mlelstv bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 542 1.39 mlelstv offsetof(struct virtio_blk_req, vr_status), 543 1.39 mlelstv sizeof(uint8_t), 544 1.39 mlelstv BUS_DMASYNC_PREREAD); 545 1.39 mlelstv 546 1.39 mlelstv virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 547 1.39 mlelstv 0, sizeof(struct virtio_blk_req_hdr), 548 1.39 mlelstv true); 549 1.39 mlelstv virtio_enqueue(vsc, vq, slot, vr->vr_payload, false); 550 1.39 mlelstv virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 551 1.39 mlelstv offsetof(struct virtio_blk_req, vr_status), 552 1.39 mlelstv sizeof(uint8_t), 553 1.39 mlelstv false); 554 1.39 mlelstv virtio_enqueue_commit(vsc, vq, slot, true); 555 1.39 mlelstv 556 1.40 mlelstv done: 557 1.39 mlelstv mutex_enter(&sc->sc_sync_wait_lock); 558 1.40 mlelstv while (sc->sc_sync_use != SYNC_DONE) { 559 1.40 mlelstv if (poll) { 560 1.40 mlelstv mutex_exit(&sc->sc_sync_wait_lock); 561 1.40 mlelstv ld_virtio_vq_done(vq); 562 1.40 mlelstv mutex_enter(&sc->sc_sync_wait_lock); 563 1.40 mlelstv continue; 564 1.40 mlelstv } 565 1.39 mlelstv cv_wait(&sc->sc_sync_wait, &sc->sc_sync_wait_lock); 566 1.40 mlelstv } 567 1.39 mlelstv 568 1.39 mlelstv if (sc->sc_sync_status == VIRTIO_BLK_S_OK) 569 1.39 mlelstv r = 0; 570 1.39 mlelstv else 571 1.39 mlelstv r = EIO; 572 1.39 mlelstv 573 1.39 mlelstv sc->sc_sync_use = SYNC_FREE; 574 1.39 mlelstv cv_broadcast(&sc->sc_sync_wait); 575 1.39 mlelstv mutex_exit(&sc->sc_sync_wait_lock); 576 1.39 mlelstv 577 1.40 mlelstv if (unload) { 578 1.40 mlelstv bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 579 1.41 mlelstv 0, id_len, BUS_DMASYNC_POSTREAD); 580 1.40 mlelstv bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload); 581 1.40 mlelstv } 582 1.39 mlelstv 583 1.44 mlelstv if (r == 0) { 584 1.44 mlelstv if (id_data[0] == '\0') 585 1.44 mlelstv r = ENOENT; 586 1.44 mlelstv else 587 1.45 isaki sc->sc_typename = kmem_strndup(id_data, id_len, KM_NOSLEEP); 588 1.44 mlelstv } 589 1.39 mlelstv 590 1.41 mlelstv kmem_free(id_data, id_len); 591 1.41 mlelstv 592 1.40 mlelstv return r; 593 1.39 mlelstv } 594 1.39 mlelstv 595 1.39 mlelstv static int 596 1.1 hannken ld_virtio_start(struct ld_softc *ld, struct buf *bp) 597 1.1 hannken { 598 1.1 hannken /* splbio */ 599 1.1 hannken struct ld_virtio_softc *sc = device_private(ld->sc_dv); 600 1.1 hannken struct virtio_softc *vsc = sc->sc_virtio; 601 1.9 christos struct virtqueue *vq = &sc->sc_vq; 602 1.1 hannken struct virtio_blk_req *vr; 603 1.1 hannken int r; 604 1.1 hannken int isread = (bp->b_flags & B_READ); 605 1.1 hannken int slot; 606 1.1 hannken 607 1.1 hannken if (sc->sc_readonly && !isread) 608 1.1 hannken return EIO; 609 1.1 hannken 610 1.1 hannken r = virtio_enqueue_prep(vsc, vq, &slot); 611 1.1 hannken if (r != 0) 612 1.1 hannken return r; 613 1.9 christos 614 1.1 hannken vr = &sc->sc_reqs[slot]; 615 1.9 christos KASSERT(vr->vr_bp == NULL); 616 1.9 christos 617 1.15 jdolecek r = bus_dmamap_load(virtio_dmat(vsc), vr->vr_payload, 618 1.1 hannken bp->b_data, bp->b_bcount, NULL, 619 1.1 hannken ((isread?BUS_DMA_READ:BUS_DMA_WRITE) 620 1.1 hannken |BUS_DMA_NOWAIT)); 621 1.9 christos if (r != 0) { 622 1.9 christos aprint_error_dev(sc->sc_dev, 623 1.9 christos "payload dmamap failed, error code %d\n", r); 624 1.9 christos virtio_enqueue_abort(vsc, vq, slot); 625 1.1 hannken return r; 626 1.9 christos } 627 1.1 hannken 628 1.35 riastrad KASSERT(vr->vr_payload->dm_nsegs <= sc->sc_seg_max); 629 1.9 christos r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs + 630 1.34 isaki VIRTIO_BLK_CTRL_SEGMENTS); 631 1.1 hannken if (r != 0) { 632 1.15 jdolecek bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload); 633 1.1 hannken return r; 634 1.1 hannken } 635 1.1 hannken 636 1.1 hannken vr->vr_bp = bp; 637 1.37 jakllsch vr->vr_hdr.type = virtio_rw32(vsc, 638 1.29 reinoud isread ? VIRTIO_BLK_T_IN : VIRTIO_BLK_T_OUT); 639 1.29 reinoud vr->vr_hdr.ioprio = virtio_rw32(vsc, 0); 640 1.29 reinoud vr->vr_hdr.sector = virtio_rw64(vsc, 641 1.29 reinoud bp->b_rawblkno * sc->sc_ld.sc_secsize / 642 1.29 reinoud VIRTIO_BLK_BSIZE); 643 1.1 hannken 644 1.15 jdolecek bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 645 1.1 hannken 0, sizeof(struct virtio_blk_req_hdr), 646 1.1 hannken BUS_DMASYNC_PREWRITE); 647 1.15 jdolecek bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 648 1.1 hannken 0, bp->b_bcount, 649 1.1 hannken isread?BUS_DMASYNC_PREREAD:BUS_DMASYNC_PREWRITE); 650 1.15 jdolecek bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 651 1.1 hannken offsetof(struct virtio_blk_req, vr_status), 652 1.1 hannken sizeof(uint8_t), 653 1.1 hannken BUS_DMASYNC_PREREAD); 654 1.1 hannken 655 1.1 hannken virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 656 1.1 hannken 0, sizeof(struct virtio_blk_req_hdr), 657 1.1 hannken true); 658 1.1 hannken virtio_enqueue(vsc, vq, slot, vr->vr_payload, !isread); 659 1.1 hannken virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 660 1.1 hannken offsetof(struct virtio_blk_req, vr_status), 661 1.1 hannken sizeof(uint8_t), 662 1.1 hannken false); 663 1.25 jakllsch virtio_enqueue_commit(vsc, vq, slot, true); 664 1.1 hannken 665 1.1 hannken return 0; 666 1.1 hannken } 667 1.1 hannken 668 1.1 hannken static void 669 1.1 hannken ld_virtio_vq_done1(struct ld_virtio_softc *sc, struct virtio_softc *vsc, 670 1.1 hannken struct virtqueue *vq, int slot) 671 1.1 hannken { 672 1.1 hannken struct virtio_blk_req *vr = &sc->sc_reqs[slot]; 673 1.1 hannken struct buf *bp = vr->vr_bp; 674 1.36 jakllsch const uint32_t rt = virtio_rw32(vsc, vr->vr_hdr.type); 675 1.1 hannken 676 1.9 christos vr->vr_bp = NULL; 677 1.9 christos 678 1.15 jdolecek bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 679 1.1 hannken 0, sizeof(struct virtio_blk_req_hdr), 680 1.1 hannken BUS_DMASYNC_POSTWRITE); 681 1.20 jakllsch bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 682 1.20 jakllsch sizeof(struct virtio_blk_req_hdr), sizeof(uint8_t), 683 1.20 jakllsch BUS_DMASYNC_POSTREAD); 684 1.20 jakllsch if (bp == DUMMY_VR_BP) { 685 1.20 jakllsch mutex_enter(&sc->sc_sync_wait_lock); 686 1.20 jakllsch sc->sc_sync_status = vr->vr_status; 687 1.20 jakllsch sc->sc_sync_use = SYNC_DONE; 688 1.27 hannken cv_broadcast(&sc->sc_sync_wait); 689 1.20 jakllsch mutex_exit(&sc->sc_sync_wait_lock); 690 1.20 jakllsch virtio_dequeue_commit(vsc, vq, slot); 691 1.20 jakllsch return; 692 1.20 jakllsch } 693 1.36 jakllsch switch (rt) { 694 1.36 jakllsch case VIRTIO_BLK_T_OUT: 695 1.36 jakllsch case VIRTIO_BLK_T_IN: 696 1.36 jakllsch bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 697 1.36 jakllsch 0, bp->b_bcount, 698 1.36 jakllsch (bp->b_flags & B_READ)?BUS_DMASYNC_POSTREAD 699 1.36 jakllsch :BUS_DMASYNC_POSTWRITE); 700 1.36 jakllsch break; 701 1.36 jakllsch default: 702 1.36 jakllsch if (vr->vr_datap == NULL) 703 1.36 jakllsch break; 704 1.36 jakllsch bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 705 1.36 jakllsch 0, vr->vr_datas, BUS_DMASYNC_POSTREAD | 706 1.36 jakllsch BUS_DMASYNC_POSTWRITE); 707 1.36 jakllsch break; 708 1.36 jakllsch } 709 1.19 jakllsch bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload); 710 1.1 hannken 711 1.1 hannken if (vr->vr_status != VIRTIO_BLK_S_OK) { 712 1.1 hannken bp->b_error = EIO; 713 1.1 hannken bp->b_resid = bp->b_bcount; 714 1.1 hannken } else { 715 1.1 hannken bp->b_error = 0; 716 1.1 hannken bp->b_resid = 0; 717 1.1 hannken } 718 1.1 hannken 719 1.36 jakllsch if (vr->vr_datap != NULL) { 720 1.36 jakllsch kmem_free(vr->vr_datap, vr->vr_datas); 721 1.36 jakllsch vr->vr_datap = NULL; 722 1.36 jakllsch vr->vr_datas = 0; 723 1.36 jakllsch } 724 1.36 jakllsch 725 1.1 hannken virtio_dequeue_commit(vsc, vq, slot); 726 1.1 hannken 727 1.36 jakllsch switch (rt) { 728 1.36 jakllsch case VIRTIO_BLK_T_OUT: 729 1.36 jakllsch case VIRTIO_BLK_T_IN: 730 1.36 jakllsch lddone(&sc->sc_ld, bp); 731 1.36 jakllsch break; 732 1.36 jakllsch case VIRTIO_BLK_T_DISCARD: 733 1.36 jakllsch lddiscardend(&sc->sc_ld, bp); 734 1.36 jakllsch break; 735 1.36 jakllsch } 736 1.1 hannken } 737 1.1 hannken 738 1.1 hannken static int 739 1.1 hannken ld_virtio_vq_done(struct virtqueue *vq) 740 1.1 hannken { 741 1.1 hannken struct virtio_softc *vsc = vq->vq_owner; 742 1.15 jdolecek struct ld_virtio_softc *sc = device_private(virtio_child(vsc)); 743 1.1 hannken int r = 0; 744 1.1 hannken int slot; 745 1.1 hannken 746 1.1 hannken again: 747 1.1 hannken if (virtio_dequeue(vsc, vq, &slot, NULL)) 748 1.1 hannken return r; 749 1.1 hannken r = 1; 750 1.1 hannken 751 1.1 hannken ld_virtio_vq_done1(sc, vsc, vq, slot); 752 1.1 hannken goto again; 753 1.1 hannken } 754 1.1 hannken 755 1.1 hannken static int 756 1.43 rin ld_virtio_dump(struct ld_softc *ld, void *data, daddr_t blkno, int blkcnt) 757 1.1 hannken { 758 1.1 hannken struct ld_virtio_softc *sc = device_private(ld->sc_dv); 759 1.1 hannken struct virtio_softc *vsc = sc->sc_virtio; 760 1.9 christos struct virtqueue *vq = &sc->sc_vq; 761 1.1 hannken struct virtio_blk_req *vr; 762 1.1 hannken int slot, r; 763 1.1 hannken 764 1.1 hannken if (sc->sc_readonly) 765 1.1 hannken return EIO; 766 1.1 hannken 767 1.1 hannken r = virtio_enqueue_prep(vsc, vq, &slot); 768 1.1 hannken if (r != 0) { 769 1.1 hannken if (r == EAGAIN) { /* no free slot; dequeue first */ 770 1.1 hannken delay(100); 771 1.1 hannken ld_virtio_vq_done(vq); 772 1.1 hannken r = virtio_enqueue_prep(vsc, vq, &slot); 773 1.1 hannken if (r != 0) 774 1.1 hannken return r; 775 1.1 hannken } 776 1.1 hannken return r; 777 1.1 hannken } 778 1.1 hannken vr = &sc->sc_reqs[slot]; 779 1.15 jdolecek r = bus_dmamap_load(virtio_dmat(vsc), vr->vr_payload, 780 1.1 hannken data, blkcnt*ld->sc_secsize, NULL, 781 1.1 hannken BUS_DMA_WRITE|BUS_DMA_NOWAIT); 782 1.1 hannken if (r != 0) 783 1.1 hannken return r; 784 1.1 hannken 785 1.17 jakllsch r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs + 786 1.34 isaki VIRTIO_BLK_CTRL_SEGMENTS); 787 1.1 hannken if (r != 0) { 788 1.15 jdolecek bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload); 789 1.1 hannken return r; 790 1.1 hannken } 791 1.1 hannken 792 1.1 hannken vr->vr_bp = (void*)0xdeadbeef; 793 1.29 reinoud vr->vr_hdr.type = virtio_rw32(vsc, VIRTIO_BLK_T_OUT); 794 1.29 reinoud vr->vr_hdr.ioprio = virtio_rw32(vsc, 0); 795 1.29 reinoud vr->vr_hdr.sector = virtio_rw64(vsc, 796 1.43 rin blkno * ld->sc_secsize / 797 1.29 reinoud VIRTIO_BLK_BSIZE); 798 1.1 hannken 799 1.15 jdolecek bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 800 1.1 hannken 0, sizeof(struct virtio_blk_req_hdr), 801 1.1 hannken BUS_DMASYNC_PREWRITE); 802 1.15 jdolecek bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 803 1.1 hannken 0, blkcnt*ld->sc_secsize, 804 1.1 hannken BUS_DMASYNC_PREWRITE); 805 1.15 jdolecek bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 806 1.1 hannken offsetof(struct virtio_blk_req, vr_status), 807 1.1 hannken sizeof(uint8_t), 808 1.1 hannken BUS_DMASYNC_PREREAD); 809 1.1 hannken 810 1.1 hannken virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 811 1.1 hannken 0, sizeof(struct virtio_blk_req_hdr), 812 1.1 hannken true); 813 1.1 hannken virtio_enqueue(vsc, vq, slot, vr->vr_payload, true); 814 1.1 hannken virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 815 1.1 hannken offsetof(struct virtio_blk_req, vr_status), 816 1.1 hannken sizeof(uint8_t), 817 1.1 hannken false); 818 1.1 hannken virtio_enqueue_commit(vsc, vq, slot, true); 819 1.1 hannken 820 1.1 hannken for ( ; ; ) { 821 1.1 hannken int dslot; 822 1.1 hannken 823 1.1 hannken r = virtio_dequeue(vsc, vq, &dslot, NULL); 824 1.1 hannken if (r != 0) 825 1.1 hannken continue; 826 1.1 hannken if (dslot != slot) { 827 1.1 hannken ld_virtio_vq_done1(sc, vsc, vq, dslot); 828 1.1 hannken continue; 829 1.1 hannken } else 830 1.1 hannken break; 831 1.1 hannken } 832 1.17 jakllsch 833 1.15 jdolecek bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 834 1.1 hannken 0, sizeof(struct virtio_blk_req_hdr), 835 1.1 hannken BUS_DMASYNC_POSTWRITE); 836 1.15 jdolecek bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 837 1.1 hannken 0, blkcnt*ld->sc_secsize, 838 1.1 hannken BUS_DMASYNC_POSTWRITE); 839 1.15 jdolecek bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 840 1.1 hannken offsetof(struct virtio_blk_req, vr_status), 841 1.1 hannken sizeof(uint8_t), 842 1.1 hannken BUS_DMASYNC_POSTREAD); 843 1.1 hannken if (vr->vr_status == VIRTIO_BLK_S_OK) 844 1.1 hannken r = 0; 845 1.1 hannken else 846 1.1 hannken r = EIO; 847 1.1 hannken virtio_dequeue_commit(vsc, vq, slot); 848 1.1 hannken 849 1.1 hannken return r; 850 1.1 hannken } 851 1.1 hannken 852 1.1 hannken static int 853 1.1 hannken ld_virtio_detach(device_t self, int flags) 854 1.1 hannken { 855 1.1 hannken struct ld_virtio_softc *sc = device_private(self); 856 1.1 hannken struct ld_softc *ld = &sc->sc_ld; 857 1.15 jdolecek bus_dma_tag_t dmat = virtio_dmat(sc->sc_virtio); 858 1.1 hannken int r, i, qsize; 859 1.1 hannken 860 1.9 christos qsize = sc->sc_vq.vq_num; 861 1.1 hannken r = ldbegindetach(ld, flags); 862 1.1 hannken if (r != 0) 863 1.1 hannken return r; 864 1.1 hannken virtio_reset(sc->sc_virtio); 865 1.9 christos virtio_free_vq(sc->sc_virtio, &sc->sc_vq); 866 1.1 hannken 867 1.1 hannken for (i = 0; i < qsize; i++) { 868 1.1 hannken bus_dmamap_destroy(dmat, 869 1.1 hannken sc->sc_reqs[i].vr_cmdsts); 870 1.1 hannken bus_dmamap_destroy(dmat, 871 1.1 hannken sc->sc_reqs[i].vr_payload); 872 1.1 hannken } 873 1.1 hannken bus_dmamem_unmap(dmat, sc->sc_reqs, 874 1.1 hannken sizeof(struct virtio_blk_req) * qsize); 875 1.9 christos bus_dmamem_free(dmat, &sc->sc_reqs_seg, 1); 876 1.1 hannken 877 1.1 hannken ldenddetach(ld); 878 1.1 hannken 879 1.39 mlelstv if (sc->sc_typename != NULL) 880 1.39 mlelstv kmem_strfree(sc->sc_typename); 881 1.39 mlelstv 882 1.23 jakllsch cv_destroy(&sc->sc_sync_wait); 883 1.23 jakllsch mutex_destroy(&sc->sc_sync_wait_lock); 884 1.23 jakllsch 885 1.15 jdolecek virtio_child_detach(sc->sc_virtio); 886 1.15 jdolecek 887 1.1 hannken return 0; 888 1.1 hannken } 889 1.12 pgoyette 890 1.20 jakllsch static int 891 1.20 jakllsch ld_virtio_flush(struct ld_softc *ld, bool poll) 892 1.20 jakllsch { 893 1.20 jakllsch struct ld_virtio_softc * const sc = device_private(ld->sc_dv); 894 1.20 jakllsch struct virtio_softc * const vsc = sc->sc_virtio; 895 1.29 reinoud const uint64_t features = virtio_features(vsc); 896 1.20 jakllsch struct virtqueue *vq = &sc->sc_vq; 897 1.20 jakllsch struct virtio_blk_req *vr; 898 1.20 jakllsch int slot; 899 1.20 jakllsch int r; 900 1.20 jakllsch 901 1.20 jakllsch if ((features & VIRTIO_BLK_F_FLUSH) == 0) 902 1.20 jakllsch return 0; 903 1.20 jakllsch 904 1.20 jakllsch mutex_enter(&sc->sc_sync_wait_lock); 905 1.20 jakllsch while (sc->sc_sync_use != SYNC_FREE) { 906 1.20 jakllsch if (poll) { 907 1.20 jakllsch mutex_exit(&sc->sc_sync_wait_lock); 908 1.20 jakllsch ld_virtio_vq_done(vq); 909 1.20 jakllsch mutex_enter(&sc->sc_sync_wait_lock); 910 1.20 jakllsch continue; 911 1.20 jakllsch } 912 1.20 jakllsch cv_wait(&sc->sc_sync_wait, &sc->sc_sync_wait_lock); 913 1.20 jakllsch } 914 1.20 jakllsch sc->sc_sync_use = SYNC_BUSY; 915 1.20 jakllsch mutex_exit(&sc->sc_sync_wait_lock); 916 1.20 jakllsch 917 1.20 jakllsch r = virtio_enqueue_prep(vsc, vq, &slot); 918 1.20 jakllsch if (r != 0) { 919 1.20 jakllsch return r; 920 1.20 jakllsch } 921 1.20 jakllsch 922 1.20 jakllsch vr = &sc->sc_reqs[slot]; 923 1.20 jakllsch KASSERT(vr->vr_bp == NULL); 924 1.20 jakllsch 925 1.34 isaki r = virtio_enqueue_reserve(vsc, vq, slot, VIRTIO_BLK_CTRL_SEGMENTS); 926 1.20 jakllsch if (r != 0) { 927 1.20 jakllsch return r; 928 1.20 jakllsch } 929 1.20 jakllsch 930 1.20 jakllsch vr->vr_bp = DUMMY_VR_BP; 931 1.29 reinoud vr->vr_hdr.type = virtio_rw32(vsc, VIRTIO_BLK_T_FLUSH); 932 1.29 reinoud vr->vr_hdr.ioprio = virtio_rw32(vsc, 0); 933 1.29 reinoud vr->vr_hdr.sector = virtio_rw64(vsc, 0); 934 1.20 jakllsch 935 1.20 jakllsch bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 936 1.20 jakllsch 0, sizeof(struct virtio_blk_req_hdr), 937 1.20 jakllsch BUS_DMASYNC_PREWRITE); 938 1.20 jakllsch bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 939 1.20 jakllsch offsetof(struct virtio_blk_req, vr_status), 940 1.20 jakllsch sizeof(uint8_t), 941 1.20 jakllsch BUS_DMASYNC_PREREAD); 942 1.20 jakllsch 943 1.20 jakllsch virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 944 1.20 jakllsch 0, sizeof(struct virtio_blk_req_hdr), 945 1.20 jakllsch true); 946 1.20 jakllsch virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 947 1.20 jakllsch offsetof(struct virtio_blk_req, vr_status), 948 1.20 jakllsch sizeof(uint8_t), 949 1.20 jakllsch false); 950 1.20 jakllsch virtio_enqueue_commit(vsc, vq, slot, true); 951 1.20 jakllsch 952 1.20 jakllsch mutex_enter(&sc->sc_sync_wait_lock); 953 1.20 jakllsch while (sc->sc_sync_use != SYNC_DONE) { 954 1.20 jakllsch if (poll) { 955 1.20 jakllsch mutex_exit(&sc->sc_sync_wait_lock); 956 1.20 jakllsch ld_virtio_vq_done(vq); 957 1.20 jakllsch mutex_enter(&sc->sc_sync_wait_lock); 958 1.20 jakllsch continue; 959 1.20 jakllsch } 960 1.20 jakllsch cv_wait(&sc->sc_sync_wait, &sc->sc_sync_wait_lock); 961 1.20 jakllsch } 962 1.20 jakllsch 963 1.20 jakllsch if (sc->sc_sync_status == VIRTIO_BLK_S_OK) 964 1.20 jakllsch r = 0; 965 1.20 jakllsch else 966 1.20 jakllsch r = EIO; 967 1.20 jakllsch 968 1.20 jakllsch sc->sc_sync_use = SYNC_FREE; 969 1.27 hannken cv_broadcast(&sc->sc_sync_wait); 970 1.20 jakllsch mutex_exit(&sc->sc_sync_wait_lock); 971 1.20 jakllsch 972 1.20 jakllsch return r; 973 1.20 jakllsch } 974 1.20 jakllsch 975 1.20 jakllsch static int 976 1.20 jakllsch ld_virtio_getcache(struct ld_softc *ld, int *bitsp) 977 1.20 jakllsch { 978 1.20 jakllsch struct ld_virtio_softc * const sc = device_private(ld->sc_dv); 979 1.20 jakllsch struct virtio_softc * const vsc = sc->sc_virtio; 980 1.29 reinoud const uint64_t features = virtio_features(vsc); 981 1.20 jakllsch 982 1.20 jakllsch *bitsp = DKCACHE_READ; 983 1.20 jakllsch if ((features & VIRTIO_BLK_F_CONFIG_WCE) != 0) 984 1.20 jakllsch *bitsp |= DKCACHE_WCHANGE; 985 1.20 jakllsch if (virtio_read_device_config_1(vsc, 986 1.20 jakllsch VIRTIO_BLK_CONFIG_WRITEBACK) != 0x00) 987 1.20 jakllsch *bitsp |= DKCACHE_WRITE; 988 1.20 jakllsch 989 1.20 jakllsch return 0; 990 1.20 jakllsch } 991 1.20 jakllsch 992 1.20 jakllsch static int 993 1.20 jakllsch ld_virtio_setcache(struct ld_softc *ld, int bits) 994 1.20 jakllsch { 995 1.20 jakllsch struct ld_virtio_softc * const sc = device_private(ld->sc_dv); 996 1.20 jakllsch struct virtio_softc * const vsc = sc->sc_virtio; 997 1.20 jakllsch const uint8_t wce = (bits & DKCACHE_WRITE) ? 0x01 : 0x00; 998 1.20 jakllsch 999 1.20 jakllsch virtio_write_device_config_1(vsc, 1000 1.20 jakllsch VIRTIO_BLK_CONFIG_WRITEBACK, wce); 1001 1.20 jakllsch if (virtio_read_device_config_1(vsc, 1002 1.20 jakllsch VIRTIO_BLK_CONFIG_WRITEBACK) != wce) 1003 1.20 jakllsch return EIO; 1004 1.20 jakllsch 1005 1.20 jakllsch return 0; 1006 1.20 jakllsch } 1007 1.20 jakllsch 1008 1.20 jakllsch static int 1009 1.20 jakllsch ld_virtio_ioctl(struct ld_softc *ld, u_long cmd, void *addr, int32_t flag, bool poll) 1010 1.20 jakllsch { 1011 1.20 jakllsch int error; 1012 1.20 jakllsch 1013 1.20 jakllsch switch (cmd) { 1014 1.20 jakllsch case DIOCCACHESYNC: 1015 1.20 jakllsch error = ld_virtio_flush(ld, poll); 1016 1.20 jakllsch break; 1017 1.20 jakllsch 1018 1.20 jakllsch case DIOCGCACHE: 1019 1.20 jakllsch error = ld_virtio_getcache(ld, (int *)addr); 1020 1.20 jakllsch break; 1021 1.20 jakllsch 1022 1.20 jakllsch case DIOCSCACHE: 1023 1.20 jakllsch error = ld_virtio_setcache(ld, *(int *)addr); 1024 1.20 jakllsch break; 1025 1.20 jakllsch 1026 1.20 jakllsch default: 1027 1.20 jakllsch error = EPASSTHROUGH; 1028 1.20 jakllsch break; 1029 1.20 jakllsch } 1030 1.20 jakllsch 1031 1.20 jakllsch return error; 1032 1.20 jakllsch } 1033 1.20 jakllsch 1034 1.36 jakllsch static int 1035 1.36 jakllsch ld_virtio_discard(struct ld_softc *ld, struct buf *bp) 1036 1.36 jakllsch { 1037 1.36 jakllsch struct ld_virtio_softc * const sc = device_private(ld->sc_dv); 1038 1.36 jakllsch struct virtio_softc * const vsc = sc->sc_virtio; 1039 1.36 jakllsch struct virtqueue * const vq = &sc->sc_vq; 1040 1.36 jakllsch struct virtio_blk_req *vr; 1041 1.36 jakllsch const uint64_t features = virtio_features(vsc); 1042 1.36 jakllsch int r; 1043 1.36 jakllsch int slot; 1044 1.36 jakllsch uint64_t blkno; 1045 1.36 jakllsch uint32_t nblks; 1046 1.36 jakllsch struct virtio_blk_discard_write_zeroes * dwz; 1047 1.36 jakllsch 1048 1.36 jakllsch if ((features & VIRTIO_BLK_F_DISCARD) == 0 || 1049 1.36 jakllsch sc->sc_max_discard_seg < 1) 1050 1.36 jakllsch return EINVAL; 1051 1.36 jakllsch 1052 1.36 jakllsch if (sc->sc_readonly) 1053 1.36 jakllsch return EIO; 1054 1.36 jakllsch 1055 1.36 jakllsch blkno = bp->b_rawblkno * sc->sc_ld.sc_secsize / VIRTIO_BLK_BSIZE; 1056 1.36 jakllsch nblks = bp->b_bcount / VIRTIO_BLK_BSIZE; 1057 1.36 jakllsch 1058 1.36 jakllsch if (nblks > sc->sc_max_discard_sectors) 1059 1.36 jakllsch return ERANGE; 1060 1.36 jakllsch 1061 1.36 jakllsch r = virtio_enqueue_prep(vsc, vq, &slot); 1062 1.36 jakllsch if (r != 0) { 1063 1.36 jakllsch return r; 1064 1.36 jakllsch } 1065 1.36 jakllsch 1066 1.36 jakllsch vr = &sc->sc_reqs[slot]; 1067 1.36 jakllsch KASSERT(vr->vr_bp == NULL); 1068 1.36 jakllsch 1069 1.36 jakllsch dwz = kmem_alloc(sizeof(*dwz), KM_SLEEP); 1070 1.36 jakllsch 1071 1.36 jakllsch r = bus_dmamap_load(virtio_dmat(vsc), vr->vr_payload, 1072 1.36 jakllsch dwz, sizeof(*dwz), NULL, BUS_DMA_WRITE | BUS_DMA_NOWAIT); 1073 1.36 jakllsch if (r != 0) { 1074 1.36 jakllsch device_printf(sc->sc_dev, 1075 1.36 jakllsch "discard payload dmamap failed, error code %d\n", r); 1076 1.36 jakllsch virtio_enqueue_abort(vsc, vq, slot); 1077 1.36 jakllsch kmem_free(dwz, sizeof(*dwz)); 1078 1.36 jakllsch return r; 1079 1.36 jakllsch } 1080 1.36 jakllsch 1081 1.36 jakllsch KASSERT(vr->vr_payload->dm_nsegs <= sc->sc_seg_max); 1082 1.36 jakllsch r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs + 1083 1.36 jakllsch VIRTIO_BLK_CTRL_SEGMENTS); 1084 1.36 jakllsch if (r != 0) { 1085 1.36 jakllsch bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload); 1086 1.36 jakllsch kmem_free(dwz, sizeof(*dwz)); 1087 1.36 jakllsch return r; 1088 1.36 jakllsch } 1089 1.36 jakllsch 1090 1.36 jakllsch vr->vr_hdr.type = virtio_rw32(vsc, VIRTIO_BLK_T_DISCARD); 1091 1.36 jakllsch vr->vr_hdr.ioprio = virtio_rw32(vsc, 0); 1092 1.36 jakllsch vr->vr_hdr.sector = virtio_rw64(vsc, 0); 1093 1.36 jakllsch vr->vr_bp = bp; 1094 1.36 jakllsch 1095 1.36 jakllsch KASSERT(vr->vr_datap == NULL); 1096 1.36 jakllsch vr->vr_datap = dwz; 1097 1.36 jakllsch vr->vr_datas = sizeof(*dwz); 1098 1.36 jakllsch 1099 1.36 jakllsch dwz->sector = virtio_rw64(vsc, blkno); 1100 1.36 jakllsch dwz->num_sectors = virtio_rw32(vsc, nblks); 1101 1.36 jakllsch dwz->flags = virtio_rw32(vsc, 0); 1102 1.36 jakllsch 1103 1.36 jakllsch bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 1104 1.36 jakllsch 0, sizeof(struct virtio_blk_req_hdr), 1105 1.36 jakllsch BUS_DMASYNC_PREWRITE); 1106 1.36 jakllsch bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 1107 1.36 jakllsch 0, vr->vr_datas, BUS_DMASYNC_PREWRITE); 1108 1.36 jakllsch bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 1109 1.36 jakllsch offsetof(struct virtio_blk_req, vr_status), 1110 1.36 jakllsch sizeof(uint8_t), 1111 1.36 jakllsch BUS_DMASYNC_PREREAD); 1112 1.36 jakllsch 1113 1.36 jakllsch virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 1114 1.36 jakllsch 0, sizeof(struct virtio_blk_req_hdr), 1115 1.36 jakllsch true); 1116 1.36 jakllsch virtio_enqueue(vsc, vq, slot, vr->vr_payload, true); 1117 1.36 jakllsch virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 1118 1.36 jakllsch offsetof(struct virtio_blk_req, vr_status), 1119 1.36 jakllsch sizeof(uint8_t), 1120 1.36 jakllsch false); 1121 1.36 jakllsch virtio_enqueue_commit(vsc, vq, slot, true); 1122 1.36 jakllsch 1123 1.36 jakllsch return 0; 1124 1.36 jakllsch } 1125 1.36 jakllsch 1126 1.12 pgoyette MODULE(MODULE_CLASS_DRIVER, ld_virtio, "ld,virtio"); 1127 1.12 pgoyette 1128 1.12 pgoyette static int 1129 1.12 pgoyette ld_virtio_modcmd(modcmd_t cmd, void *opaque) 1130 1.12 pgoyette { 1131 1.12 pgoyette int error = 0; 1132 1.17 jakllsch 1133 1.12 pgoyette switch (cmd) { 1134 1.12 pgoyette case MODULE_CMD_INIT: 1135 1.38 mlelstv #ifdef _MODULE 1136 1.38 mlelstv error = config_init_component(cfdriver_ioconf_ld_virtio, 1137 1.12 pgoyette cfattach_ioconf_ld_virtio, cfdata_ioconf_ld_virtio); 1138 1.38 mlelstv #endif 1139 1.12 pgoyette break; 1140 1.12 pgoyette case MODULE_CMD_FINI: 1141 1.38 mlelstv #ifdef _MODULE 1142 1.38 mlelstv error = config_fini_component(cfdriver_ioconf_ld_virtio, 1143 1.12 pgoyette cfattach_ioconf_ld_virtio, cfdata_ioconf_ld_virtio); 1144 1.38 mlelstv #endif 1145 1.12 pgoyette break; 1146 1.12 pgoyette default: 1147 1.12 pgoyette error = ENOTTY; 1148 1.12 pgoyette break; 1149 1.12 pgoyette } 1150 1.12 pgoyette 1151 1.12 pgoyette return error; 1152 1.12 pgoyette } 1153