1 /* $NetBSD: ld.c,v 1.106 2019/03/19 07:01:14 mlelstv 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.106 2019/03/19 07:01:14 mlelstv 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 #include <sys/reboot.h> 59 60 #include <dev/ldvar.h> 61 62 #include "ioconf.h" 63 64 static void ldminphys(struct buf *bp); 65 static bool ld_suspend(device_t, const pmf_qual_t *); 66 static bool ld_shutdown(device_t, int); 67 static int ld_diskstart(device_t, struct buf *bp); 68 static void ld_iosize(device_t, int *); 69 static int ld_dumpblocks(device_t, void *, daddr_t, int); 70 static void ld_fake_geometry(struct ld_softc *); 71 static void ld_set_geometry(struct ld_softc *); 72 static void ld_config_interrupts (device_t); 73 static int ld_lastclose(device_t); 74 static int ld_discard(device_t, off_t, off_t); 75 static int ld_flush(device_t, bool); 76 77 static dev_type_open(ldopen); 78 static dev_type_close(ldclose); 79 static dev_type_read(ldread); 80 static dev_type_write(ldwrite); 81 static dev_type_ioctl(ldioctl); 82 static dev_type_strategy(ldstrategy); 83 static dev_type_dump(lddump); 84 static dev_type_size(ldsize); 85 static dev_type_discard(lddiscard); 86 87 const struct bdevsw ld_bdevsw = { 88 .d_open = ldopen, 89 .d_close = ldclose, 90 .d_strategy = ldstrategy, 91 .d_ioctl = ldioctl, 92 .d_dump = lddump, 93 .d_psize = ldsize, 94 .d_discard = lddiscard, 95 .d_flag = D_DISK | D_MPSAFE 96 }; 97 98 const struct cdevsw ld_cdevsw = { 99 .d_open = ldopen, 100 .d_close = ldclose, 101 .d_read = ldread, 102 .d_write = ldwrite, 103 .d_ioctl = ldioctl, 104 .d_stop = nostop, 105 .d_tty = notty, 106 .d_poll = nopoll, 107 .d_mmap = nommap, 108 .d_kqfilter = nokqfilter, 109 .d_discard = lddiscard, 110 .d_flag = D_DISK | D_MPSAFE 111 }; 112 113 static struct dkdriver lddkdriver = { 114 .d_open = ldopen, 115 .d_close = ldclose, 116 .d_strategy = ldstrategy, 117 .d_iosize = ld_iosize, 118 .d_minphys = ldminphys, 119 .d_diskstart = ld_diskstart, 120 .d_dumpblocks = ld_dumpblocks, 121 .d_lastclose = ld_lastclose, 122 .d_discard = ld_discard 123 }; 124 125 void 126 ldattach(struct ld_softc *sc, const char *default_strategy) 127 { 128 device_t self = sc->sc_dv; 129 struct dk_softc *dksc = &sc->sc_dksc; 130 131 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM); 132 cv_init(&sc->sc_drain, "lddrain"); 133 134 if ((sc->sc_flags & LDF_ENABLED) == 0) { 135 return; 136 } 137 138 /* Initialise dk and disk structure. */ 139 dk_init(dksc, self, DKTYPE_LD); 140 disk_init(&dksc->sc_dkdev, dksc->sc_xname, &lddkdriver); 141 142 if (sc->sc_maxxfer > MAXPHYS) 143 sc->sc_maxxfer = MAXPHYS; 144 145 /* Build synthetic geometry if necessary. */ 146 if (sc->sc_nheads == 0 || sc->sc_nsectors == 0 || 147 sc->sc_ncylinders == 0) 148 ld_fake_geometry(sc); 149 150 sc->sc_disksize512 = sc->sc_secperunit * sc->sc_secsize / DEV_BSIZE; 151 152 if (sc->sc_flags & LDF_NO_RND) 153 dksc->sc_flags |= DKF_NO_RND; 154 155 /* Attach dk and disk subsystems */ 156 dk_attach(dksc); 157 disk_attach(&dksc->sc_dkdev); 158 ld_set_geometry(sc); 159 160 bufq_alloc(&dksc->sc_bufq, default_strategy, BUFQ_SORT_RAWBLOCK); 161 162 /* Register with PMF */ 163 if (!pmf_device_register1(dksc->sc_dev, ld_suspend, NULL, ld_shutdown)) 164 aprint_error_dev(dksc->sc_dev, 165 "couldn't establish power handler\n"); 166 167 /* Discover wedges on this disk. */ 168 config_interrupts(sc->sc_dv, ld_config_interrupts); 169 } 170 171 int 172 ldadjqparam(struct ld_softc *sc, int xmax) 173 { 174 175 mutex_enter(&sc->sc_mutex); 176 sc->sc_maxqueuecnt = xmax; 177 mutex_exit(&sc->sc_mutex); 178 179 return (0); 180 } 181 182 int 183 ldbegindetach(struct ld_softc *sc, int flags) 184 { 185 struct dk_softc *dksc = &sc->sc_dksc; 186 int rv = 0; 187 188 if ((sc->sc_flags & LDF_ENABLED) == 0) 189 return (0); 190 191 rv = disk_begindetach(&dksc->sc_dkdev, ld_lastclose, dksc->sc_dev, flags); 192 193 if (rv != 0) 194 return rv; 195 196 mutex_enter(&sc->sc_mutex); 197 sc->sc_maxqueuecnt = 0; 198 199 while (sc->sc_queuecnt > 0) { 200 sc->sc_flags |= LDF_DRAIN; 201 cv_wait(&sc->sc_drain, &sc->sc_mutex); 202 } 203 mutex_exit(&sc->sc_mutex); 204 205 return (rv); 206 } 207 208 void 209 ldenddetach(struct ld_softc *sc) 210 { 211 struct dk_softc *dksc = &sc->sc_dksc; 212 int bmaj, cmaj, i, mn; 213 214 if ((sc->sc_flags & LDF_ENABLED) == 0) 215 return; 216 217 mutex_enter(&sc->sc_mutex); 218 219 /* Wait for commands queued with the hardware to complete. */ 220 if (sc->sc_queuecnt != 0) { 221 if (cv_timedwait(&sc->sc_drain, &sc->sc_mutex, 30 * hz)) 222 printf("%s: not drained\n", dksc->sc_xname); 223 } 224 mutex_exit(&sc->sc_mutex); 225 226 /* Kill off any queued buffers. */ 227 dk_drain(dksc); 228 bufq_free(dksc->sc_bufq); 229 230 /* Locate the major numbers. */ 231 bmaj = bdevsw_lookup_major(&ld_bdevsw); 232 cmaj = cdevsw_lookup_major(&ld_cdevsw); 233 234 /* Nuke the vnodes for any open instances. */ 235 for (i = 0; i < MAXPARTITIONS; i++) { 236 mn = DISKMINOR(device_unit(dksc->sc_dev), i); 237 vdevgone(bmaj, mn, mn, VBLK); 238 vdevgone(cmaj, mn, mn, VCHR); 239 } 240 241 /* Delete all of our wedges. */ 242 dkwedge_delall(&dksc->sc_dkdev); 243 244 /* Detach from the disk list. */ 245 disk_detach(&dksc->sc_dkdev); 246 disk_destroy(&dksc->sc_dkdev); 247 248 dk_detach(dksc); 249 250 /* Deregister with PMF */ 251 pmf_device_deregister(dksc->sc_dev); 252 253 /* 254 * XXX We can't really flush the cache here, because the 255 * XXX device may already be non-existent from the controller's 256 * XXX perspective. 257 */ 258 #if 0 259 ld_flush(dksc->sc_dev, false); 260 #endif 261 cv_destroy(&sc->sc_drain); 262 mutex_destroy(&sc->sc_mutex); 263 } 264 265 /* ARGSUSED */ 266 static bool 267 ld_suspend(device_t dev, const pmf_qual_t *qual) 268 { 269 return ld_shutdown(dev, 0); 270 } 271 272 /* ARGSUSED */ 273 static bool 274 ld_shutdown(device_t dev, int flags) 275 { 276 if ((flags & RB_NOSYNC) == 0 && ld_flush(dev, true) != 0) 277 return false; 278 279 return true; 280 } 281 282 /* ARGSUSED */ 283 static int 284 ldopen(dev_t dev, int flags, int fmt, struct lwp *l) 285 { 286 struct ld_softc *sc; 287 struct dk_softc *dksc; 288 int unit; 289 290 unit = DISKUNIT(dev); 291 if ((sc = device_lookup_private(&ld_cd, unit)) == NULL) 292 return (ENXIO); 293 dksc = &sc->sc_dksc; 294 295 return dk_open(dksc, dev, flags, fmt, l); 296 } 297 298 static int 299 ld_lastclose(device_t self) 300 { 301 ld_flush(self, false); 302 303 return 0; 304 } 305 306 /* ARGSUSED */ 307 static int 308 ldclose(dev_t dev, int flags, int fmt, struct lwp *l) 309 { 310 struct ld_softc *sc; 311 struct dk_softc *dksc; 312 int unit; 313 314 unit = DISKUNIT(dev); 315 sc = device_lookup_private(&ld_cd, unit); 316 dksc = &sc->sc_dksc; 317 318 return dk_close(dksc, dev, flags, fmt, l); 319 } 320 321 /* ARGSUSED */ 322 static int 323 ldread(dev_t dev, struct uio *uio, int ioflag) 324 { 325 326 return (physio(ldstrategy, NULL, dev, B_READ, ldminphys, uio)); 327 } 328 329 /* ARGSUSED */ 330 static int 331 ldwrite(dev_t dev, struct uio *uio, int ioflag) 332 { 333 334 return (physio(ldstrategy, NULL, dev, B_WRITE, ldminphys, uio)); 335 } 336 337 /* ARGSUSED */ 338 static int 339 ldioctl(dev_t dev, u_long cmd, void *addr, int32_t flag, struct lwp *l) 340 { 341 struct ld_softc *sc; 342 struct dk_softc *dksc; 343 int unit, error; 344 345 unit = DISKUNIT(dev); 346 sc = device_lookup_private(&ld_cd, unit); 347 dksc = &sc->sc_dksc; 348 349 error = 0; 350 351 /* 352 * Some common checks so that individual attachments wouldn't need 353 * to duplicate them. 354 */ 355 switch (cmd) { 356 case DIOCCACHESYNC: 357 /* 358 * XXX Do we really need to care about having a writable 359 * file descriptor here? 360 */ 361 if ((flag & FWRITE) == 0) 362 error = EBADF; 363 else 364 error = 0; 365 break; 366 } 367 368 if (error != 0) 369 return (error); 370 371 if (sc->sc_ioctl) { 372 if ((sc->sc_flags & LDF_MPSAFE) == 0) 373 KERNEL_LOCK(1, curlwp); 374 error = (*sc->sc_ioctl)(sc, cmd, addr, flag, 0); 375 if ((sc->sc_flags & LDF_MPSAFE) == 0) 376 KERNEL_UNLOCK_ONE(curlwp); 377 if (error != EPASSTHROUGH) 378 return (error); 379 } 380 381 /* something not handled by the attachment */ 382 return dk_ioctl(dksc, dev, cmd, addr, flag, l); 383 } 384 385 /* 386 * Flush the device's cache. 387 */ 388 static int 389 ld_flush(device_t self, bool poll) 390 { 391 int error = 0; 392 struct ld_softc *sc = device_private(self); 393 394 if (sc->sc_ioctl) { 395 if ((sc->sc_flags & LDF_MPSAFE) == 0) 396 KERNEL_LOCK(1, curlwp); 397 error = (*sc->sc_ioctl)(sc, DIOCCACHESYNC, NULL, 0, poll); 398 if ((sc->sc_flags & LDF_MPSAFE) == 0) 399 KERNEL_UNLOCK_ONE(curlwp); 400 if (error != 0) 401 device_printf(self, "unable to flush cache\n"); 402 } 403 404 return error; 405 } 406 407 static void 408 ldstrategy(struct buf *bp) 409 { 410 struct ld_softc *sc; 411 struct dk_softc *dksc; 412 int unit; 413 414 unit = DISKUNIT(bp->b_dev); 415 sc = device_lookup_private(&ld_cd, unit); 416 dksc = &sc->sc_dksc; 417 418 dk_strategy(dksc, bp); 419 } 420 421 static int 422 ld_diskstart(device_t dev, struct buf *bp) 423 { 424 struct ld_softc *sc = device_private(dev); 425 int error; 426 427 if (sc->sc_queuecnt >= sc->sc_maxqueuecnt) 428 return EAGAIN; 429 430 if ((sc->sc_flags & LDF_MPSAFE) == 0) 431 KERNEL_LOCK(1, curlwp); 432 433 mutex_enter(&sc->sc_mutex); 434 435 if (sc->sc_queuecnt >= sc->sc_maxqueuecnt) 436 error = EAGAIN; 437 else { 438 error = (*sc->sc_start)(sc, bp); 439 if (error == 0) 440 sc->sc_queuecnt++; 441 } 442 443 mutex_exit(&sc->sc_mutex); 444 445 if ((sc->sc_flags & LDF_MPSAFE) == 0) 446 KERNEL_UNLOCK_ONE(curlwp); 447 448 return error; 449 } 450 451 void 452 lddone(struct ld_softc *sc, struct buf *bp) 453 { 454 struct dk_softc *dksc = &sc->sc_dksc; 455 456 dk_done(dksc, bp); 457 458 mutex_enter(&sc->sc_mutex); 459 if (--sc->sc_queuecnt <= sc->sc_maxqueuecnt) { 460 if ((sc->sc_flags & LDF_DRAIN) != 0) { 461 sc->sc_flags &= ~LDF_DRAIN; 462 cv_broadcast(&sc->sc_drain); 463 } 464 mutex_exit(&sc->sc_mutex); 465 dk_start(dksc, NULL); 466 } else 467 mutex_exit(&sc->sc_mutex); 468 } 469 470 static int 471 ldsize(dev_t dev) 472 { 473 struct ld_softc *sc; 474 struct dk_softc *dksc; 475 int unit; 476 477 unit = DISKUNIT(dev); 478 if ((sc = device_lookup_private(&ld_cd, unit)) == NULL) 479 return (-1); 480 dksc = &sc->sc_dksc; 481 482 if ((sc->sc_flags & LDF_ENABLED) == 0) 483 return (-1); 484 485 return dk_size(dksc, dev); 486 } 487 488 /* 489 * Take a dump. 490 */ 491 static int 492 lddump(dev_t dev, daddr_t blkno, void *va, size_t size) 493 { 494 struct ld_softc *sc; 495 struct dk_softc *dksc; 496 int unit; 497 498 unit = DISKUNIT(dev); 499 if ((sc = device_lookup_private(&ld_cd, unit)) == NULL) 500 return (ENXIO); 501 dksc = &sc->sc_dksc; 502 503 if ((sc->sc_flags & LDF_ENABLED) == 0) 504 return (ENODEV); 505 506 return dk_dump(dksc, dev, blkno, va, size); 507 } 508 509 static int 510 ld_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk) 511 { 512 struct ld_softc *sc = device_private(dev); 513 514 if (sc->sc_dump == NULL) 515 return (ENODEV); 516 517 return (*sc->sc_dump)(sc, va, blkno, nblk); 518 } 519 520 /* 521 * Adjust the size of a transfer. 522 */ 523 static void 524 ldminphys(struct buf *bp) 525 { 526 int unit; 527 struct ld_softc *sc; 528 529 unit = DISKUNIT(bp->b_dev); 530 sc = device_lookup_private(&ld_cd, unit); 531 532 ld_iosize(sc->sc_dv, &bp->b_bcount); 533 minphys(bp); 534 } 535 536 static void 537 ld_iosize(device_t d, int *countp) 538 { 539 struct ld_softc *sc = device_private(d); 540 541 if (*countp > sc->sc_maxxfer) 542 *countp = sc->sc_maxxfer; 543 } 544 545 static void 546 ld_fake_geometry(struct ld_softc *sc) 547 { 548 uint64_t ncyl; 549 550 if (sc->sc_secperunit <= 528 * 2048) /* 528MB */ 551 sc->sc_nheads = 16; 552 else if (sc->sc_secperunit <= 1024 * 2048) /* 1GB */ 553 sc->sc_nheads = 32; 554 else if (sc->sc_secperunit <= 21504 * 2048) /* 21GB */ 555 sc->sc_nheads = 64; 556 else if (sc->sc_secperunit <= 43008 * 2048) /* 42GB */ 557 sc->sc_nheads = 128; 558 else 559 sc->sc_nheads = 255; 560 561 sc->sc_nsectors = 63; 562 sc->sc_ncylinders = INT_MAX; 563 ncyl = sc->sc_secperunit / 564 (sc->sc_nheads * sc->sc_nsectors); 565 if (ncyl < INT_MAX) 566 sc->sc_ncylinders = (int)ncyl; 567 } 568 569 static void 570 ld_set_geometry(struct ld_softc *sc) 571 { 572 struct dk_softc *dksc = &sc->sc_dksc; 573 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 574 char tbuf[9]; 575 576 format_bytes(tbuf, sizeof(tbuf), sc->sc_secperunit * 577 sc->sc_secsize); 578 aprint_normal_dev(dksc->sc_dev, "%s, %d cyl, %d head, %d sec, " 579 "%d bytes/sect x %"PRIu64" sectors\n", 580 tbuf, sc->sc_ncylinders, sc->sc_nheads, 581 sc->sc_nsectors, sc->sc_secsize, sc->sc_secperunit); 582 583 memset(dg, 0, sizeof(*dg)); 584 dg->dg_secperunit = sc->sc_secperunit; 585 dg->dg_secsize = sc->sc_secsize; 586 dg->dg_nsectors = sc->sc_nsectors; 587 dg->dg_ntracks = sc->sc_nheads; 588 dg->dg_ncylinders = sc->sc_ncylinders; 589 590 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, sc->sc_typename); 591 } 592 593 static void 594 ld_config_interrupts(device_t d) 595 { 596 struct ld_softc *sc = device_private(d); 597 struct dk_softc *dksc = &sc->sc_dksc; 598 599 dkwedge_discover(&dksc->sc_dkdev); 600 } 601 602 static int 603 ld_discard(device_t dev, off_t pos, off_t len) 604 { 605 struct ld_softc *sc = device_private(dev); 606 struct buf dbuf, *bp = &dbuf; 607 int error = 0; 608 609 KASSERT(len <= INT_MAX); 610 611 if (sc->sc_discard == NULL) 612 return (ENODEV); 613 614 if ((sc->sc_flags & LDF_MPSAFE) == 0) 615 KERNEL_LOCK(1, curlwp); 616 617 buf_init(bp); 618 bp->b_vp = NULL; 619 bp->b_data = NULL; 620 bp->b_bufsize = 0; 621 bp->b_rawblkno = pos / sc->sc_secsize; 622 bp->b_bcount = len; 623 bp->b_flags = B_WRITE; 624 bp->b_cflags = BC_BUSY; 625 626 error = (*sc->sc_discard)(sc, bp); 627 if (error == 0) 628 error = biowait(bp); 629 630 buf_destroy(bp); 631 632 if ((sc->sc_flags & LDF_MPSAFE) == 0) 633 KERNEL_UNLOCK_ONE(curlwp); 634 635 return error; 636 } 637 638 void 639 lddiscardend(struct ld_softc *sc, struct buf *bp) 640 { 641 642 if (bp->b_error) 643 bp->b_resid = bp->b_bcount; 644 biodone(bp); 645 } 646 647 static int 648 lddiscard(dev_t dev, off_t pos, off_t len) 649 { 650 struct ld_softc *sc; 651 struct dk_softc *dksc; 652 int unit; 653 654 unit = DISKUNIT(dev); 655 sc = device_lookup_private(&ld_cd, unit); 656 dksc = &sc->sc_dksc; 657 658 return dk_discard(dksc, dev, pos, len); 659 } 660 661 MODULE(MODULE_CLASS_DRIVER, ld, "dk_subr"); 662 663 #ifdef _MODULE 664 CFDRIVER_DECL(ld, DV_DISK, NULL); 665 #endif 666 667 static int 668 ld_modcmd(modcmd_t cmd, void *opaque) 669 { 670 #ifdef _MODULE 671 devmajor_t bmajor, cmajor; 672 #endif 673 int error = 0; 674 675 #ifdef _MODULE 676 switch (cmd) { 677 case MODULE_CMD_INIT: 678 bmajor = cmajor = -1; 679 error = devsw_attach(ld_cd.cd_name, &ld_bdevsw, &bmajor, 680 &ld_cdevsw, &cmajor); 681 if (error) 682 break; 683 error = config_cfdriver_attach(&ld_cd); 684 break; 685 case MODULE_CMD_FINI: 686 error = config_cfdriver_detach(&ld_cd); 687 if (error) 688 break; 689 devsw_detach(&ld_bdevsw, &ld_cdevsw); 690 break; 691 default: 692 error = ENOTTY; 693 break; 694 } 695 #endif 696 697 return error; 698 } 699