1 /* $NetBSD: ld.c,v 1.97 2016/09/27 03:33:32 pgoyette Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran and Charles M. Hannum. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Disk driver for use by RAID controllers. 34 */ 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: ld.c,v 1.97 2016/09/27 03:33:32 pgoyette Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/device.h> 43 #include <sys/queue.h> 44 #include <sys/proc.h> 45 #include <sys/buf.h> 46 #include <sys/bufq.h> 47 #include <sys/endian.h> 48 #include <sys/disklabel.h> 49 #include <sys/disk.h> 50 #include <sys/dkio.h> 51 #include <sys/stat.h> 52 #include <sys/conf.h> 53 #include <sys/fcntl.h> 54 #include <sys/vnode.h> 55 #include <sys/syslog.h> 56 #include <sys/mutex.h> 57 #include <sys/module.h> 58 59 #include <dev/ldvar.h> 60 61 static void ldminphys(struct buf *bp); 62 static bool ld_suspend(device_t, const pmf_qual_t *); 63 static bool ld_shutdown(device_t, int); 64 static int ld_diskstart(device_t, struct buf *bp); 65 static void ld_iosize(device_t, int *); 66 static int ld_dumpblocks(device_t, void *, daddr_t, int); 67 static void ld_fake_geometry(struct ld_softc *); 68 static void ld_set_geometry(struct ld_softc *); 69 static void ld_config_interrupts (device_t); 70 static int ld_lastclose(device_t); 71 static int ld_discard(device_t, off_t, off_t); 72 73 extern struct cfdriver ld_cd; 74 75 static dev_type_open(ldopen); 76 static dev_type_close(ldclose); 77 static dev_type_read(ldread); 78 static dev_type_write(ldwrite); 79 static dev_type_ioctl(ldioctl); 80 static dev_type_strategy(ldstrategy); 81 static dev_type_dump(lddump); 82 static dev_type_size(ldsize); 83 static dev_type_discard(lddiscard); 84 85 const struct bdevsw ld_bdevsw = { 86 .d_open = ldopen, 87 .d_close = ldclose, 88 .d_strategy = ldstrategy, 89 .d_ioctl = ldioctl, 90 .d_dump = lddump, 91 .d_psize = ldsize, 92 .d_discard = lddiscard, 93 .d_flag = D_DISK | D_MPSAFE 94 }; 95 96 const struct cdevsw ld_cdevsw = { 97 .d_open = ldopen, 98 .d_close = ldclose, 99 .d_read = ldread, 100 .d_write = ldwrite, 101 .d_ioctl = ldioctl, 102 .d_stop = nostop, 103 .d_tty = notty, 104 .d_poll = nopoll, 105 .d_mmap = nommap, 106 .d_kqfilter = nokqfilter, 107 .d_discard = lddiscard, 108 .d_flag = D_DISK | D_MPSAFE 109 }; 110 111 static struct dkdriver lddkdriver = { 112 .d_open = ldopen, 113 .d_close = ldclose, 114 .d_strategy = ldstrategy, 115 .d_iosize = ld_iosize, 116 .d_minphys = ldminphys, 117 .d_diskstart = ld_diskstart, 118 .d_dumpblocks = ld_dumpblocks, 119 .d_lastclose = ld_lastclose, 120 .d_discard = ld_discard 121 }; 122 123 void 124 ldattach(struct ld_softc *sc, const char *default_strategy) 125 { 126 device_t self = sc->sc_dv; 127 struct dk_softc *dksc = &sc->sc_dksc; 128 129 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM); 130 cv_init(&sc->sc_drain, "lddrain"); 131 132 if ((sc->sc_flags & LDF_ENABLED) == 0) { 133 return; 134 } 135 136 /* Initialise dk and disk structure. */ 137 dk_init(dksc, self, DKTYPE_LD); 138 disk_init(&dksc->sc_dkdev, dksc->sc_xname, &lddkdriver); 139 140 if (sc->sc_maxxfer > MAXPHYS) 141 sc->sc_maxxfer = MAXPHYS; 142 143 /* Build synthetic geometry if necessary. */ 144 if (sc->sc_nheads == 0 || sc->sc_nsectors == 0 || 145 sc->sc_ncylinders == 0) 146 ld_fake_geometry(sc); 147 148 sc->sc_disksize512 = sc->sc_secperunit * sc->sc_secsize / DEV_BSIZE; 149 150 /* Attach dk and disk subsystems */ 151 dk_attach(dksc); 152 disk_attach(&dksc->sc_dkdev); 153 ld_set_geometry(sc); 154 155 bufq_alloc(&dksc->sc_bufq, default_strategy, BUFQ_SORT_RAWBLOCK); 156 157 /* Register with PMF */ 158 if (!pmf_device_register1(dksc->sc_dev, ld_suspend, NULL, ld_shutdown)) 159 aprint_error_dev(dksc->sc_dev, 160 "couldn't establish power handler\n"); 161 162 /* Discover wedges on this disk. */ 163 config_interrupts(sc->sc_dv, ld_config_interrupts); 164 } 165 166 int 167 ldadjqparam(struct ld_softc *sc, int xmax) 168 { 169 170 mutex_enter(&sc->sc_mutex); 171 sc->sc_maxqueuecnt = xmax; 172 mutex_exit(&sc->sc_mutex); 173 174 return (0); 175 } 176 177 int 178 ldbegindetach(struct ld_softc *sc, int flags) 179 { 180 struct dk_softc *dksc = &sc->sc_dksc; 181 int rv = 0; 182 183 if ((sc->sc_flags & LDF_ENABLED) == 0) 184 return (0); 185 186 rv = disk_begindetach(&dksc->sc_dkdev, ld_lastclose, dksc->sc_dev, flags); 187 188 if (rv != 0) 189 return rv; 190 191 mutex_enter(&sc->sc_mutex); 192 sc->sc_maxqueuecnt = 0; 193 194 while (sc->sc_queuecnt > 0) { 195 sc->sc_flags |= LDF_DRAIN; 196 cv_wait(&sc->sc_drain, &sc->sc_mutex); 197 } 198 mutex_exit(&sc->sc_mutex); 199 200 return (rv); 201 } 202 203 void 204 ldenddetach(struct ld_softc *sc) 205 { 206 struct dk_softc *dksc = &sc->sc_dksc; 207 int bmaj, cmaj, i, mn; 208 209 if ((sc->sc_flags & LDF_ENABLED) == 0) 210 return; 211 212 mutex_enter(&sc->sc_mutex); 213 214 /* Wait for commands queued with the hardware to complete. */ 215 if (sc->sc_queuecnt != 0) { 216 if (cv_timedwait(&sc->sc_drain, &sc->sc_mutex, 30 * hz)) 217 printf("%s: not drained\n", dksc->sc_xname); 218 } 219 mutex_exit(&sc->sc_mutex); 220 221 /* Kill off any queued buffers. */ 222 dk_drain(dksc); 223 bufq_free(dksc->sc_bufq); 224 225 /* Locate the major numbers. */ 226 bmaj = bdevsw_lookup_major(&ld_bdevsw); 227 cmaj = cdevsw_lookup_major(&ld_cdevsw); 228 229 /* Nuke the vnodes for any open instances. */ 230 for (i = 0; i < MAXPARTITIONS; i++) { 231 mn = DISKMINOR(device_unit(dksc->sc_dev), i); 232 vdevgone(bmaj, mn, mn, VBLK); 233 vdevgone(cmaj, mn, mn, VCHR); 234 } 235 236 /* Delete all of our wedges. */ 237 dkwedge_delall(&dksc->sc_dkdev); 238 239 /* Detach from the disk list. */ 240 disk_detach(&dksc->sc_dkdev); 241 disk_destroy(&dksc->sc_dkdev); 242 243 dk_detach(dksc); 244 245 /* Deregister with PMF */ 246 pmf_device_deregister(dksc->sc_dev); 247 248 /* 249 * XXX We can't really flush the cache here, beceause the 250 * XXX device may already be non-existent from the controller's 251 * XXX perspective. 252 */ 253 #if 0 254 /* Flush the device's cache. */ 255 if (sc->sc_flush != NULL) 256 if ((*sc->sc_flush)(sc, 0) != 0) 257 device_printf(dksc->sc_dev, "unable to flush cache\n"); 258 #endif 259 cv_destroy(&sc->sc_drain); 260 mutex_destroy(&sc->sc_mutex); 261 } 262 263 /* ARGSUSED */ 264 static bool 265 ld_suspend(device_t dev, const pmf_qual_t *qual) 266 { 267 return ld_shutdown(dev, 0); 268 } 269 270 /* ARGSUSED */ 271 static bool 272 ld_shutdown(device_t dev, int flags) 273 { 274 struct ld_softc *sc = device_private(dev); 275 struct dk_softc *dksc = &sc->sc_dksc; 276 277 if (sc->sc_flush != NULL && (*sc->sc_flush)(sc, LDFL_POLL) != 0) { 278 device_printf(dksc->sc_dev, "unable to flush cache\n"); 279 return false; 280 } 281 282 return true; 283 } 284 285 /* ARGSUSED */ 286 static int 287 ldopen(dev_t dev, int flags, int fmt, struct lwp *l) 288 { 289 struct ld_softc *sc; 290 struct dk_softc *dksc; 291 int unit; 292 293 unit = DISKUNIT(dev); 294 if ((sc = device_lookup_private(&ld_cd, unit)) == NULL) 295 return (ENXIO); 296 dksc = &sc->sc_dksc; 297 298 return dk_open(dksc, dev, flags, fmt, l); 299 } 300 301 static int 302 ld_lastclose(device_t self) 303 { 304 struct ld_softc *sc = device_private(self); 305 306 if (sc->sc_flush != NULL && (*sc->sc_flush)(sc, 0) != 0) 307 device_printf(self, "unable to flush cache\n"); 308 309 return 0; 310 } 311 312 /* ARGSUSED */ 313 static int 314 ldclose(dev_t dev, int flags, int fmt, struct lwp *l) 315 { 316 struct ld_softc *sc; 317 struct dk_softc *dksc; 318 int unit; 319 320 unit = DISKUNIT(dev); 321 sc = device_lookup_private(&ld_cd, unit); 322 dksc = &sc->sc_dksc; 323 324 return dk_close(dksc, dev, flags, fmt, l); 325 } 326 327 /* ARGSUSED */ 328 static int 329 ldread(dev_t dev, struct uio *uio, int ioflag) 330 { 331 332 return (physio(ldstrategy, NULL, dev, B_READ, ldminphys, uio)); 333 } 334 335 /* ARGSUSED */ 336 static int 337 ldwrite(dev_t dev, struct uio *uio, int ioflag) 338 { 339 340 return (physio(ldstrategy, NULL, dev, B_WRITE, ldminphys, uio)); 341 } 342 343 /* ARGSUSED */ 344 static int 345 ldioctl(dev_t dev, u_long cmd, void *addr, int32_t flag, struct lwp *l) 346 { 347 struct ld_softc *sc; 348 struct dk_softc *dksc; 349 int unit, error; 350 351 unit = DISKUNIT(dev); 352 sc = device_lookup_private(&ld_cd, unit); 353 dksc = &sc->sc_dksc; 354 355 error = 0; 356 357 switch (cmd) { 358 case DIOCCACHESYNC: 359 /* 360 * XXX Do we really need to care about having a writable 361 * file descriptor here? 362 */ 363 if ((flag & FWRITE) == 0) 364 error = EBADF; 365 else if (sc->sc_flush) 366 error = (*sc->sc_flush)(sc, 0); 367 else 368 error = 0; /* XXX Error out instead? */ 369 break; 370 371 default: 372 error = dk_ioctl(dksc, dev, cmd, addr, flag, l); 373 break; 374 } 375 376 return (error); 377 } 378 379 static void 380 ldstrategy(struct buf *bp) 381 { 382 struct ld_softc *sc; 383 struct dk_softc *dksc; 384 int unit; 385 386 unit = DISKUNIT(bp->b_dev); 387 sc = device_lookup_private(&ld_cd, unit); 388 dksc = &sc->sc_dksc; 389 390 dk_strategy(dksc, bp); 391 } 392 393 static int 394 ld_diskstart(device_t dev, struct buf *bp) 395 { 396 struct ld_softc *sc = device_private(dev); 397 int error; 398 399 if (sc->sc_queuecnt >= sc->sc_maxqueuecnt) 400 return EAGAIN; 401 402 mutex_enter(&sc->sc_mutex); 403 404 if (sc->sc_queuecnt >= sc->sc_maxqueuecnt) 405 error = EAGAIN; 406 else { 407 error = (*sc->sc_start)(sc, bp); 408 if (error == 0) 409 sc->sc_queuecnt++; 410 } 411 412 mutex_exit(&sc->sc_mutex); 413 414 return error; 415 } 416 417 void 418 lddone(struct ld_softc *sc, struct buf *bp) 419 { 420 struct dk_softc *dksc = &sc->sc_dksc; 421 422 dk_done(dksc, bp); 423 424 mutex_enter(&sc->sc_mutex); 425 if (--sc->sc_queuecnt <= sc->sc_maxqueuecnt) { 426 if ((sc->sc_flags & LDF_DRAIN) != 0) { 427 sc->sc_flags &= ~LDF_DRAIN; 428 cv_broadcast(&sc->sc_drain); 429 } 430 mutex_exit(&sc->sc_mutex); 431 dk_start(dksc, NULL); 432 } else 433 mutex_exit(&sc->sc_mutex); 434 } 435 436 static int 437 ldsize(dev_t dev) 438 { 439 struct ld_softc *sc; 440 struct dk_softc *dksc; 441 int unit; 442 443 unit = DISKUNIT(dev); 444 if ((sc = device_lookup_private(&ld_cd, unit)) == NULL) 445 return (ENODEV); 446 dksc = &sc->sc_dksc; 447 448 if ((sc->sc_flags & LDF_ENABLED) == 0) 449 return (ENODEV); 450 451 return dk_size(dksc, dev); 452 } 453 454 /* 455 * Take a dump. 456 */ 457 static int 458 lddump(dev_t dev, daddr_t blkno, void *va, size_t size) 459 { 460 struct ld_softc *sc; 461 struct dk_softc *dksc; 462 int unit; 463 464 unit = DISKUNIT(dev); 465 if ((sc = device_lookup_private(&ld_cd, unit)) == NULL) 466 return (ENXIO); 467 dksc = &sc->sc_dksc; 468 469 if ((sc->sc_flags & LDF_ENABLED) == 0) 470 return (ENODEV); 471 472 return dk_dump(dksc, dev, blkno, va, size); 473 } 474 475 static int 476 ld_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk) 477 { 478 struct ld_softc *sc = device_private(dev); 479 480 if (sc->sc_dump == NULL) 481 return (ENODEV); 482 483 return (*sc->sc_dump)(sc, va, blkno, nblk); 484 } 485 486 /* 487 * Adjust the size of a transfer. 488 */ 489 static void 490 ldminphys(struct buf *bp) 491 { 492 int unit; 493 struct ld_softc *sc; 494 495 unit = DISKUNIT(bp->b_dev); 496 sc = device_lookup_private(&ld_cd, unit); 497 498 ld_iosize(sc->sc_dv, &bp->b_bcount); 499 minphys(bp); 500 } 501 502 static void 503 ld_iosize(device_t d, int *countp) 504 { 505 struct ld_softc *sc = device_private(d); 506 507 if (*countp > sc->sc_maxxfer) 508 *countp = sc->sc_maxxfer; 509 } 510 511 static void 512 ld_fake_geometry(struct ld_softc *sc) 513 { 514 uint64_t ncyl; 515 516 if (sc->sc_secperunit <= 528 * 2048) /* 528MB */ 517 sc->sc_nheads = 16; 518 else if (sc->sc_secperunit <= 1024 * 2048) /* 1GB */ 519 sc->sc_nheads = 32; 520 else if (sc->sc_secperunit <= 21504 * 2048) /* 21GB */ 521 sc->sc_nheads = 64; 522 else if (sc->sc_secperunit <= 43008 * 2048) /* 42GB */ 523 sc->sc_nheads = 128; 524 else 525 sc->sc_nheads = 255; 526 527 sc->sc_nsectors = 63; 528 sc->sc_ncylinders = INT_MAX; 529 ncyl = sc->sc_secperunit / 530 (sc->sc_nheads * sc->sc_nsectors); 531 if (ncyl < INT_MAX) 532 sc->sc_ncylinders = (int)ncyl; 533 } 534 535 static void 536 ld_set_geometry(struct ld_softc *sc) 537 { 538 struct dk_softc *dksc = &sc->sc_dksc; 539 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 540 char tbuf[9]; 541 542 format_bytes(tbuf, sizeof(tbuf), sc->sc_secperunit * 543 sc->sc_secsize); 544 aprint_normal_dev(dksc->sc_dev, "%s, %d cyl, %d head, %d sec, " 545 "%d bytes/sect x %"PRIu64" sectors\n", 546 tbuf, sc->sc_ncylinders, sc->sc_nheads, 547 sc->sc_nsectors, sc->sc_secsize, sc->sc_secperunit); 548 549 memset(dg, 0, sizeof(*dg)); 550 dg->dg_secperunit = sc->sc_secperunit; 551 dg->dg_secsize = sc->sc_secsize; 552 dg->dg_nsectors = sc->sc_nsectors; 553 dg->dg_ntracks = sc->sc_nheads; 554 dg->dg_ncylinders = sc->sc_ncylinders; 555 556 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL); 557 } 558 559 static void 560 ld_config_interrupts(device_t d) 561 { 562 struct ld_softc *sc = device_private(d); 563 struct dk_softc *dksc = &sc->sc_dksc; 564 565 dkwedge_discover(&dksc->sc_dkdev); 566 } 567 568 static int 569 ld_discard(device_t dev, off_t pos, off_t len) 570 { 571 struct ld_softc *sc = device_private(dev); 572 573 if (sc->sc_discard == NULL) 574 return (ENODEV); 575 576 return (*sc->sc_discard)(sc, pos, len); 577 } 578 579 static int 580 lddiscard(dev_t dev, off_t pos, off_t len) 581 { 582 struct ld_softc *sc; 583 struct dk_softc *dksc; 584 int unit; 585 586 unit = DISKUNIT(dev); 587 sc = device_lookup_private(&ld_cd, unit); 588 dksc = &sc->sc_dksc; 589 590 return dk_discard(dksc, dev, pos, len); 591 } 592 593 MODULE(MODULE_CLASS_DRIVER, ld, "dk_subr"); 594 595 #ifdef _MODULE 596 CFDRIVER_DECL(ld, DV_DISK, NULL); 597 #endif 598 599 static int 600 ld_modcmd(modcmd_t cmd, void *opaque) 601 { 602 #ifdef _MODULE 603 devmajor_t bmajor, cmajor; 604 #endif 605 int error = 0; 606 607 #ifdef _MODULE 608 switch (cmd) { 609 case MODULE_CMD_INIT: 610 bmajor = cmajor = -1; 611 error = devsw_attach(ld_cd.cd_name, &ld_bdevsw, &bmajor, 612 &ld_cdevsw, &cmajor); 613 if (error) 614 break; 615 error = config_cfdriver_attach(&ld_cd); 616 break; 617 case MODULE_CMD_FINI: 618 error = config_cfdriver_detach(&ld_cd); 619 if (error) 620 break; 621 devsw_detach(&ld_bdevsw, &ld_cdevsw); 622 break; 623 default: 624 error = ENOTTY; 625 break; 626 } 627 #endif 628 629 return error; 630 } 631