1 /* $NetBSD: ld.c,v 1.104 2017/10/28 03:47:24 riastradh 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.104 2017/10/28 03:47:24 riastradh 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 error = (*sc->sc_ioctl)(sc, cmd, addr, flag, 0); 373 if (error != EPASSTHROUGH) 374 return (error); 375 } 376 377 /* something not handled by the attachment */ 378 return dk_ioctl(dksc, dev, cmd, addr, flag, l); 379 } 380 381 /* 382 * Flush the device's cache. 383 */ 384 static int 385 ld_flush(device_t self, bool poll) 386 { 387 int error = 0; 388 struct ld_softc *sc = device_private(self); 389 390 if (sc->sc_ioctl) { 391 error = (*sc->sc_ioctl)(sc, DIOCCACHESYNC, NULL, 0, poll); 392 if (error != 0) 393 device_printf(self, "unable to flush cache\n"); 394 } 395 396 return error; 397 } 398 399 static void 400 ldstrategy(struct buf *bp) 401 { 402 struct ld_softc *sc; 403 struct dk_softc *dksc; 404 int unit; 405 406 unit = DISKUNIT(bp->b_dev); 407 sc = device_lookup_private(&ld_cd, unit); 408 dksc = &sc->sc_dksc; 409 410 dk_strategy(dksc, bp); 411 } 412 413 static int 414 ld_diskstart(device_t dev, struct buf *bp) 415 { 416 struct ld_softc *sc = device_private(dev); 417 int error; 418 419 if (sc->sc_queuecnt >= sc->sc_maxqueuecnt) 420 return EAGAIN; 421 422 if ((sc->sc_flags & LDF_MPSAFE) == 0) 423 KERNEL_LOCK(1, curlwp); 424 425 mutex_enter(&sc->sc_mutex); 426 427 if (sc->sc_queuecnt >= sc->sc_maxqueuecnt) 428 error = EAGAIN; 429 else { 430 error = (*sc->sc_start)(sc, bp); 431 if (error == 0) 432 sc->sc_queuecnt++; 433 } 434 435 mutex_exit(&sc->sc_mutex); 436 437 if ((sc->sc_flags & LDF_MPSAFE) == 0) 438 KERNEL_UNLOCK_ONE(curlwp); 439 440 return error; 441 } 442 443 void 444 lddone(struct ld_softc *sc, struct buf *bp) 445 { 446 struct dk_softc *dksc = &sc->sc_dksc; 447 448 dk_done(dksc, bp); 449 450 mutex_enter(&sc->sc_mutex); 451 if (--sc->sc_queuecnt <= sc->sc_maxqueuecnt) { 452 if ((sc->sc_flags & LDF_DRAIN) != 0) { 453 sc->sc_flags &= ~LDF_DRAIN; 454 cv_broadcast(&sc->sc_drain); 455 } 456 mutex_exit(&sc->sc_mutex); 457 dk_start(dksc, NULL); 458 } else 459 mutex_exit(&sc->sc_mutex); 460 } 461 462 static int 463 ldsize(dev_t dev) 464 { 465 struct ld_softc *sc; 466 struct dk_softc *dksc; 467 int unit; 468 469 unit = DISKUNIT(dev); 470 if ((sc = device_lookup_private(&ld_cd, unit)) == NULL) 471 return (-1); 472 dksc = &sc->sc_dksc; 473 474 if ((sc->sc_flags & LDF_ENABLED) == 0) 475 return (-1); 476 477 return dk_size(dksc, dev); 478 } 479 480 /* 481 * Take a dump. 482 */ 483 static int 484 lddump(dev_t dev, daddr_t blkno, void *va, size_t size) 485 { 486 struct ld_softc *sc; 487 struct dk_softc *dksc; 488 int unit; 489 490 unit = DISKUNIT(dev); 491 if ((sc = device_lookup_private(&ld_cd, unit)) == NULL) 492 return (ENXIO); 493 dksc = &sc->sc_dksc; 494 495 if ((sc->sc_flags & LDF_ENABLED) == 0) 496 return (ENODEV); 497 498 return dk_dump(dksc, dev, blkno, va, size); 499 } 500 501 static int 502 ld_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk) 503 { 504 struct ld_softc *sc = device_private(dev); 505 506 if (sc->sc_dump == NULL) 507 return (ENODEV); 508 509 return (*sc->sc_dump)(sc, va, blkno, nblk); 510 } 511 512 /* 513 * Adjust the size of a transfer. 514 */ 515 static void 516 ldminphys(struct buf *bp) 517 { 518 int unit; 519 struct ld_softc *sc; 520 521 unit = DISKUNIT(bp->b_dev); 522 sc = device_lookup_private(&ld_cd, unit); 523 524 ld_iosize(sc->sc_dv, &bp->b_bcount); 525 minphys(bp); 526 } 527 528 static void 529 ld_iosize(device_t d, int *countp) 530 { 531 struct ld_softc *sc = device_private(d); 532 533 if (*countp > sc->sc_maxxfer) 534 *countp = sc->sc_maxxfer; 535 } 536 537 static void 538 ld_fake_geometry(struct ld_softc *sc) 539 { 540 uint64_t ncyl; 541 542 if (sc->sc_secperunit <= 528 * 2048) /* 528MB */ 543 sc->sc_nheads = 16; 544 else if (sc->sc_secperunit <= 1024 * 2048) /* 1GB */ 545 sc->sc_nheads = 32; 546 else if (sc->sc_secperunit <= 21504 * 2048) /* 21GB */ 547 sc->sc_nheads = 64; 548 else if (sc->sc_secperunit <= 43008 * 2048) /* 42GB */ 549 sc->sc_nheads = 128; 550 else 551 sc->sc_nheads = 255; 552 553 sc->sc_nsectors = 63; 554 sc->sc_ncylinders = INT_MAX; 555 ncyl = sc->sc_secperunit / 556 (sc->sc_nheads * sc->sc_nsectors); 557 if (ncyl < INT_MAX) 558 sc->sc_ncylinders = (int)ncyl; 559 } 560 561 static void 562 ld_set_geometry(struct ld_softc *sc) 563 { 564 struct dk_softc *dksc = &sc->sc_dksc; 565 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 566 char tbuf[9]; 567 568 format_bytes(tbuf, sizeof(tbuf), sc->sc_secperunit * 569 sc->sc_secsize); 570 aprint_normal_dev(dksc->sc_dev, "%s, %d cyl, %d head, %d sec, " 571 "%d bytes/sect x %"PRIu64" sectors\n", 572 tbuf, sc->sc_ncylinders, sc->sc_nheads, 573 sc->sc_nsectors, sc->sc_secsize, sc->sc_secperunit); 574 575 memset(dg, 0, sizeof(*dg)); 576 dg->dg_secperunit = sc->sc_secperunit; 577 dg->dg_secsize = sc->sc_secsize; 578 dg->dg_nsectors = sc->sc_nsectors; 579 dg->dg_ntracks = sc->sc_nheads; 580 dg->dg_ncylinders = sc->sc_ncylinders; 581 582 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL); 583 } 584 585 static void 586 ld_config_interrupts(device_t d) 587 { 588 struct ld_softc *sc = device_private(d); 589 struct dk_softc *dksc = &sc->sc_dksc; 590 591 dkwedge_discover(&dksc->sc_dkdev); 592 } 593 594 static int 595 ld_discard(device_t dev, off_t pos, off_t len) 596 { 597 struct ld_softc *sc = device_private(dev); 598 struct buf dbuf, *bp = &dbuf; 599 int error = 0; 600 601 KASSERT(len <= INT_MAX); 602 603 if (sc->sc_discard == NULL) 604 return (ENODEV); 605 606 if ((sc->sc_flags & LDF_MPSAFE) == 0) 607 KERNEL_LOCK(1, curlwp); 608 609 buf_init(bp); 610 bp->b_vp = NULL; 611 bp->b_data = NULL; 612 bp->b_bufsize = 0; 613 bp->b_rawblkno = pos / sc->sc_secsize; 614 bp->b_bcount = len; 615 bp->b_flags = B_WRITE; 616 bp->b_cflags = BC_BUSY; 617 618 error = (*sc->sc_discard)(sc, bp); 619 if (error == 0) 620 error = biowait(bp); 621 622 buf_destroy(bp); 623 624 if ((sc->sc_flags & LDF_MPSAFE) == 0) 625 KERNEL_UNLOCK_ONE(curlwp); 626 627 return error; 628 } 629 630 void 631 lddiscardend(struct ld_softc *sc, struct buf *bp) 632 { 633 634 if (bp->b_error) 635 bp->b_resid = bp->b_bcount; 636 biodone(bp); 637 } 638 639 static int 640 lddiscard(dev_t dev, off_t pos, off_t len) 641 { 642 struct ld_softc *sc; 643 struct dk_softc *dksc; 644 int unit; 645 646 unit = DISKUNIT(dev); 647 sc = device_lookup_private(&ld_cd, unit); 648 dksc = &sc->sc_dksc; 649 650 return dk_discard(dksc, dev, pos, len); 651 } 652 653 MODULE(MODULE_CLASS_DRIVER, ld, "dk_subr"); 654 655 #ifdef _MODULE 656 CFDRIVER_DECL(ld, DV_DISK, NULL); 657 #endif 658 659 static int 660 ld_modcmd(modcmd_t cmd, void *opaque) 661 { 662 #ifdef _MODULE 663 devmajor_t bmajor, cmajor; 664 #endif 665 int error = 0; 666 667 #ifdef _MODULE 668 switch (cmd) { 669 case MODULE_CMD_INIT: 670 bmajor = cmajor = -1; 671 error = devsw_attach(ld_cd.cd_name, &ld_bdevsw, &bmajor, 672 &ld_cdevsw, &cmajor); 673 if (error) 674 break; 675 error = config_cfdriver_attach(&ld_cd); 676 break; 677 case MODULE_CMD_FINI: 678 error = config_cfdriver_detach(&ld_cd); 679 if (error) 680 break; 681 devsw_detach(&ld_bdevsw, &ld_cdevsw); 682 break; 683 default: 684 error = ENOTTY; 685 break; 686 } 687 #endif 688 689 return error; 690 } 691