1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * sun4v domain services PRI driver 30 */ 31 32 #include <sys/types.h> 33 #include <sys/file.h> 34 #include <sys/errno.h> 35 #include <sys/open.h> 36 #include <sys/cred.h> 37 #include <sys/uio.h> 38 #include <sys/stat.h> 39 #include <sys/ksynch.h> 40 #include <sys/modctl.h> 41 #include <sys/conf.h> 42 #include <sys/devops.h> 43 #include <sys/debug.h> 44 #include <sys/cmn_err.h> 45 #include <sys/ddi.h> 46 #include <sys/sunddi.h> 47 #include <sys/ds.h> 48 49 #include <sys/ds_pri.h> 50 51 static uint_t ds_pri_debug = 0; 52 #define DS_PRI_DBG if (ds_pri_debug) printf 53 54 #define DS_PRI_NAME "ds_pri" 55 56 #define TEST_HARNESS 57 #ifdef TEST_HARNESS 58 #define DS_PRI_MAX_PRI_SIZE (64 * 1024) 59 60 #define DSIOC_TEST_REG 97 61 #define DSIOC_TEST_UNREG 98 62 #define DSIOC_TEST_DATA 99 63 64 struct ds_pri_test_data { 65 size_t size; 66 void *data; 67 }; 68 69 struct ds_pri_test_data32 { 70 size32_t size; 71 caddr32_t data; 72 }; 73 #endif /* TEST_HARNESS */ 74 75 typedef enum { 76 DS_PRI_REQUEST = 0, 77 DS_PRI_DATA = 1, 78 DS_PRI_UPDATE = 2 79 } ds_pri_msg_type_t; 80 81 typedef struct { 82 struct { 83 uint64_t seq_num; 84 uint64_t type; 85 } hdr; 86 uint8_t data[1]; 87 } ds_pri_msg_t; 88 89 /* The following are bit field flags */ 90 /* No service implies no PRI and no outstanding request */ 91 typedef enum { 92 DS_PRI_NO_SERVICE = 0x0, 93 DS_PRI_HAS_SERVICE = 0x1, 94 DS_PRI_REQUESTED = 0x2, 95 DS_PRI_HAS_PRI = 0x4 96 } ds_pri_flags_t; 97 98 struct ds_pri_state { 99 dev_info_t *dip; 100 int instance; 101 102 kmutex_t lock; 103 kcondvar_t cv; 104 105 /* PRI/DS */ 106 ds_pri_flags_t state; 107 uint64_t gencount; 108 ds_svc_hdl_t ds_pri_handle; 109 void *ds_pri; 110 size_t ds_pri_len; 111 uint64_t req_id; 112 uint64_t last_req_id; 113 }; 114 115 typedef struct ds_pri_state ds_pri_state_t; 116 117 static void *ds_pri_statep; 118 119 static void request_pri(ds_pri_state_t *sp); 120 121 static int ds_pri_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 122 static int ds_pri_attach(dev_info_t *, ddi_attach_cmd_t); 123 static int ds_pri_detach(dev_info_t *, ddi_detach_cmd_t); 124 static int ds_pri_open(dev_t *, int, int, cred_t *); 125 static int ds_pri_close(dev_t, int, int, cred_t *); 126 static int ds_pri_read(dev_t, struct uio *, cred_t *); 127 static int ds_pri_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 128 129 /* 130 * DS Callbacks 131 */ 132 static void ds_pri_reg_handler(ds_cb_arg_t, ds_ver_t *, ds_svc_hdl_t); 133 static void ds_pri_unreg_handler(ds_cb_arg_t arg); 134 static void ds_pri_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen); 135 136 /* 137 * PRI DS capability registration 138 */ 139 140 static ds_ver_t ds_pri_ver_1_0 = { 1, 0 }; 141 142 static ds_capability_t ds_pri_cap = { 143 "pri", 144 &ds_pri_ver_1_0, 145 1 146 }; 147 148 /* 149 * PRI DS Client callback vector 150 */ 151 static ds_clnt_ops_t ds_pri_ops = { 152 ds_pri_reg_handler, /* ds_reg_cb */ 153 ds_pri_unreg_handler, /* ds_unreg_cb */ 154 ds_pri_data_handler, /* ds_data_cb */ 155 NULL /* cb_arg */ 156 }; 157 158 /* 159 * DS PRI driver Ops Vector 160 */ 161 static struct cb_ops ds_pri_cb_ops = { 162 ds_pri_open, /* cb_open */ 163 ds_pri_close, /* cb_close */ 164 nodev, /* cb_strategy */ 165 nodev, /* cb_print */ 166 nodev, /* cb_dump */ 167 ds_pri_read, /* cb_read */ 168 nodev, /* cb_write */ 169 ds_pri_ioctl, /* cb_ioctl */ 170 nodev, /* cb_devmap */ 171 nodev, /* cb_mmap */ 172 nodev, /* cb_segmap */ 173 nochpoll, /* cb_chpoll */ 174 ddi_prop_op, /* cb_prop_op */ 175 (struct streamtab *)NULL, /* cb_str */ 176 D_MP | D_64BIT, /* cb_flag */ 177 CB_REV, /* cb_rev */ 178 nodev, /* cb_aread */ 179 nodev /* cb_awrite */ 180 }; 181 182 static struct dev_ops ds_pri_dev_ops = { 183 DEVO_REV, /* devo_rev */ 184 0, /* devo_refcnt */ 185 ds_pri_getinfo, /* devo_getinfo */ 186 nulldev, /* devo_identify */ 187 nulldev, /* devo_probe */ 188 ds_pri_attach, /* devo_attach */ 189 ds_pri_detach, /* devo_detach */ 190 nodev, /* devo_reset */ 191 &ds_pri_cb_ops, /* devo_cb_ops */ 192 (struct bus_ops *)NULL, /* devo_bus_ops */ 193 nulldev /* devo_power */ 194 }; 195 196 static struct modldrv modldrv = { 197 &mod_driverops, 198 "Domain Services PRI Driver 1.0", 199 &ds_pri_dev_ops 200 }; 201 202 static struct modlinkage modlinkage = { 203 MODREV_1, 204 (void *)&modldrv, 205 NULL 206 }; 207 208 209 int 210 _init(void) 211 { 212 int retval; 213 214 retval = ddi_soft_state_init(&ds_pri_statep, 215 sizeof (ds_pri_state_t), 0); 216 if (retval != 0) 217 return (retval); 218 219 retval = mod_install(&modlinkage); 220 if (retval != 0) { 221 ddi_soft_state_fini(&ds_pri_statep); 222 return (retval); 223 } 224 225 return (retval); 226 } 227 228 229 int 230 _info(struct modinfo *modinfop) 231 { 232 return (mod_info(&modlinkage, modinfop)); 233 } 234 235 236 int 237 _fini(void) 238 { 239 int retval; 240 241 if ((retval = mod_remove(&modlinkage)) != 0) 242 return (retval); 243 244 ddi_soft_state_fini(&ds_pri_statep); 245 246 return (retval); 247 } 248 249 250 /*ARGSUSED*/ 251 static int 252 ds_pri_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp) 253 { 254 ds_pri_state_t *sp; 255 int retval = DDI_FAILURE; 256 257 ASSERT(resultp != NULL); 258 259 switch (cmd) { 260 case DDI_INFO_DEVT2DEVINFO: 261 sp = ddi_get_soft_state(ds_pri_statep, getminor((dev_t)arg)); 262 if (sp != NULL) { 263 *resultp = sp->dip; 264 retval = DDI_SUCCESS; 265 } else 266 *resultp = NULL; 267 break; 268 269 case DDI_INFO_DEVT2INSTANCE: 270 *resultp = (void *)(uintptr_t)getminor((dev_t)arg); 271 retval = DDI_SUCCESS; 272 break; 273 274 default: 275 break; 276 } 277 278 return (retval); 279 } 280 281 282 static int 283 ds_pri_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 284 { 285 int instance; 286 ds_pri_state_t *sp; 287 int rv; 288 289 switch (cmd) { 290 case DDI_ATTACH: 291 break; 292 293 case DDI_RESUME: 294 return (DDI_SUCCESS); 295 296 default: 297 return (DDI_FAILURE); 298 } 299 300 instance = ddi_get_instance(dip); 301 302 if (ddi_soft_state_zalloc(ds_pri_statep, instance) != 303 DDI_SUCCESS) { 304 cmn_err(CE_WARN, "%s@%d: Unable to allocate state", 305 DS_PRI_NAME, instance); 306 return (DDI_FAILURE); 307 } 308 sp = ddi_get_soft_state(ds_pri_statep, instance); 309 310 mutex_init(&sp->lock, NULL, MUTEX_DEFAULT, NULL); 311 cv_init(&sp->cv, NULL, CV_DEFAULT, NULL); 312 313 if (ddi_create_minor_node(dip, DS_PRI_NAME, S_IFCHR, instance, 314 DDI_PSEUDO, 0) != DDI_SUCCESS) { 315 cmn_err(CE_WARN, "%s@%d: Unable to create minor node", 316 DS_PRI_NAME, instance); 317 goto fail; 318 } 319 320 if (ds_pri_ops.cb_arg != NULL) 321 goto fail; 322 ds_pri_ops.cb_arg = dip; 323 324 sp->state = DS_PRI_NO_SERVICE; 325 326 /* Until the service registers the handle is invalid */ 327 sp->ds_pri_handle = DS_INVALID_HDL; 328 329 sp->ds_pri = NULL; 330 sp->ds_pri_len = 0; 331 sp->req_id = 0; 332 333 if ((rv = ds_cap_init(&ds_pri_cap, &ds_pri_ops)) != 0) { 334 cmn_err(CE_NOTE, "ds_cap_init failed: %d", rv); 335 goto fail; 336 } 337 338 ddi_report_dev(dip); 339 340 return (DDI_SUCCESS); 341 342 fail: 343 ddi_remove_minor_node(dip, NULL); 344 cv_destroy(&sp->cv); 345 mutex_destroy(&sp->lock); 346 ddi_soft_state_free(ds_pri_statep, instance); 347 return (DDI_FAILURE); 348 349 } 350 351 352 /*ARGSUSED*/ 353 static int 354 ds_pri_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 355 { 356 ds_pri_state_t *sp; 357 int instance; 358 int rv; 359 360 instance = ddi_get_instance(dip); 361 sp = ddi_get_soft_state(ds_pri_statep, instance); 362 363 switch (cmd) { 364 case DDI_DETACH: 365 break; 366 367 case DDI_SUSPEND: 368 return (DDI_SUCCESS); 369 370 default: 371 return (DDI_FAILURE); 372 } 373 374 /* This really shouldn't fail - but check anyway */ 375 if ((rv = ds_cap_fini(&ds_pri_cap)) != 0) { 376 cmn_err(CE_WARN, "ds_cap_fini failed: %d", rv); 377 } 378 379 if (sp != NULL && sp->ds_pri_len != 0) 380 kmem_free(sp->ds_pri, sp->ds_pri_len); 381 382 ddi_remove_minor_node(dip, NULL); 383 cv_destroy(&sp->cv); 384 mutex_destroy(&sp->lock); 385 ddi_soft_state_free(ds_pri_statep, instance); 386 387 return (DDI_SUCCESS); 388 } 389 390 391 /*ARGSUSED*/ 392 static int 393 ds_pri_open(dev_t *devp, int flag, int otyp, cred_t *credp) 394 { 395 ds_pri_state_t *sp; 396 int instance; 397 398 if (otyp != OTYP_CHR) 399 return (EINVAL); 400 401 instance = getminor(*devp); 402 sp = ddi_get_soft_state(ds_pri_statep, instance); 403 if (sp == NULL) 404 return (ENXIO); 405 406 /* 407 * On open we dont fetch the PRI even if we have a valid service 408 * handle. PRI fetch is essentially lazy and on-demand. 409 */ 410 411 DS_PRI_DBG("ds_pri_open: state = 0x%x\n", sp->state); 412 413 return (0); 414 } 415 416 417 /*ARGSUSED*/ 418 static int 419 ds_pri_close(dev_t dev, int flag, int otyp, cred_t *credp) 420 { 421 int instance; 422 423 if (otyp != OTYP_CHR) 424 return (EINVAL); 425 426 DS_PRI_DBG("ds_pri_close\n"); 427 428 instance = getminor(dev); 429 if (ddi_get_soft_state(ds_pri_statep, instance) == NULL) 430 return (ENXIO); 431 432 return (0); 433 } 434 435 436 /*ARGSUSED*/ 437 static int 438 ds_pri_read(dev_t dev, struct uio *uiop, cred_t *credp) 439 { 440 ds_pri_state_t *sp; 441 int instance; 442 size_t len; 443 int retval; 444 caddr_t tmpbufp; 445 446 instance = getminor(dev); 447 if ((sp = ddi_get_soft_state(ds_pri_statep, instance)) == NULL) 448 return (ENXIO); 449 450 len = uiop->uio_resid; 451 452 if (len == 0) 453 return (0); 454 455 mutex_enter(&sp->lock); 456 457 DS_PRI_DBG("ds_pri_read: state = 0x%x\n", sp->state); 458 459 /* block or bail if there is no current PRI */ 460 if (!(sp->state & DS_PRI_HAS_PRI)) { 461 DS_PRI_DBG("ds_pri_read: no PRI held\n"); 462 463 if (uiop->uio_fmode & (FNDELAY | FNONBLOCK)) { 464 mutex_exit(&sp->lock); 465 return (EAGAIN); 466 } 467 468 while (!(sp->state & DS_PRI_HAS_PRI)) { 469 DS_PRI_DBG("ds_pri_read: state = 0x%x\n", sp->state); 470 request_pri(sp); 471 if (cv_wait_sig(&sp->cv, &sp->lock) == 0) { 472 mutex_exit(&sp->lock); 473 return (EINTR); 474 } 475 } 476 } 477 478 if (uiop->uio_offset < 0 || uiop->uio_offset > sp->ds_pri_len) { 479 mutex_exit(&sp->lock); 480 return (EINVAL); 481 } 482 483 if (len > (sp->ds_pri_len - uiop->uio_offset)) 484 len = sp->ds_pri_len - uiop->uio_offset; 485 486 /* already checked that offset < ds_pri_len above */ 487 if (len == 0) { 488 mutex_exit(&sp->lock); 489 return (0); 490 } 491 492 /* 493 * We're supposed to move the data out to userland, but 494 * that can suspend because of page faults etc., and meanwhile 495 * other parts of this driver want to update the PRI buffer ... 496 * we could hold the data buffer locked with a flag etc., 497 * but that's still a lock ... a simpler mechanism - if not quite 498 * as performance efficient is to simply clone here the part of 499 * the buffer we care about and then the original can be released 500 * for further updates while the uiomove continues. 501 */ 502 503 tmpbufp = kmem_alloc(len, KM_SLEEP); 504 bcopy(((caddr_t)sp->ds_pri) + uiop->uio_offset, tmpbufp, len); 505 mutex_exit(&sp->lock); 506 507 retval = uiomove(tmpbufp, len, UIO_READ, uiop); 508 509 kmem_free(tmpbufp, len); 510 511 return (retval); 512 } 513 514 515 /*ARGSUSED*/ 516 static int 517 ds_pri_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 518 int *rvalp) 519 { 520 ds_pri_state_t *sp; 521 int instance; 522 523 instance = getminor(dev); 524 if ((sp = ddi_get_soft_state(ds_pri_statep, instance)) == NULL) 525 return (ENXIO); 526 527 switch (cmd) { 528 case DSPRI_GETINFO: { 529 struct dspri_info info; 530 531 if (!(mode & FREAD)) 532 return (EACCES); 533 534 /* 535 * We are not guaranteed that ddi_copyout(9F) will read 536 * atomically anything larger than a byte. Therefore we 537 * must duplicate the size before copying it out to the user. 538 */ 539 mutex_enter(&sp->lock); 540 541 loop:; 542 if (sp->state & DS_PRI_HAS_PRI) { 543 /* If we have a PRI simply return the info */ 544 info.size = sp->ds_pri_len; 545 info.token = sp->gencount; 546 } else 547 if (!(sp->state & DS_PRI_HAS_SERVICE)) { 548 /* If we have no service return a nil response */ 549 info.size = 0; 550 info.token = 0; 551 } else { 552 request_pri(sp); 553 /* wait for something & check again */ 554 if (cv_wait_sig(&sp->cv, &sp->lock) == 0) { 555 mutex_exit(&sp->lock); 556 return (EINTR); 557 } 558 goto loop; 559 } 560 DS_PRI_DBG("ds_pri_ioctl: DSPRI_GETINFO sz=0x%lx tok=0x%lx\n", 561 info.size, info.token); 562 mutex_exit(&sp->lock); 563 564 if (ddi_copyout(&info, (void *)arg, sizeof (info), mode) != 0) 565 return (EFAULT); 566 break; 567 } 568 569 case DSPRI_WAIT: { 570 uint64_t gencount; 571 572 if (ddi_copyin((void *)arg, &gencount, sizeof (gencount), 573 mode) != 0) 574 return (EFAULT); 575 576 mutex_enter(&sp->lock); 577 578 DS_PRI_DBG("ds_pri_ioctl: DSPRI_WAIT gen=0x%lx sp->gen=0x%lx\n", 579 gencount, sp->gencount); 580 581 while ((sp->state & DS_PRI_HAS_PRI) == 0 || 582 gencount == sp->gencount) { 583 if (cv_wait_sig(&sp->cv, &sp->lock) == 0) { 584 mutex_exit(&sp->lock); 585 return (EINTR); 586 } 587 } 588 mutex_exit(&sp->lock); 589 break; 590 } 591 592 default: 593 return (ENOTTY); 594 } 595 return (0); 596 } 597 598 599 /* assumes sp->lock is held when called */ 600 static void 601 request_pri(ds_pri_state_t *sp) 602 { 603 ds_pri_msg_t reqmsg; 604 605 ASSERT(MUTEX_HELD(&sp->lock)); 606 607 /* If a request is already pending we're done */ 608 if (!(sp->state & DS_PRI_HAS_SERVICE)) 609 return; 610 if (sp->state & DS_PRI_REQUESTED) 611 return; 612 613 /* If we have an old PRI - remove it */ 614 if (sp->state & DS_PRI_HAS_PRI) { 615 ASSERT(sp->ds_pri_len != 0); 616 ASSERT(sp->ds_pri != NULL); 617 618 /* remove the old data if we have an outstanding request */ 619 kmem_free(sp->ds_pri, sp->ds_pri_len); 620 sp->ds_pri_len = 0; 621 sp->ds_pri = NULL; 622 sp->state &= ~DS_PRI_HAS_PRI; 623 } else { 624 ASSERT(sp->ds_pri == NULL); 625 ASSERT(sp->ds_pri_len == 0); 626 } 627 628 reqmsg.hdr.seq_num = ++(sp->req_id); 629 reqmsg.hdr.type = DS_PRI_REQUEST; 630 631 DS_PRI_DBG("request_pri: request id 0x%lx\n", sp->req_id); 632 633 /* 634 * Request consists of header only. 635 * We don't care about fail status for ds_send; 636 * if it does fail we will get an unregister callback 637 * from the DS framework and we handle the state change 638 * there. 639 */ 640 (void) ds_cap_send(sp->ds_pri_handle, &reqmsg, sizeof (reqmsg.hdr)); 641 642 sp->state |= DS_PRI_REQUESTED; 643 sp->last_req_id = sp->req_id; 644 } 645 646 /* 647 * DS Callbacks 648 */ 649 /*ARGSUSED*/ 650 static void 651 ds_pri_reg_handler(ds_cb_arg_t arg, ds_ver_t *ver, ds_svc_hdl_t hdl) 652 { 653 dev_info_t *dip = arg; 654 ds_pri_state_t *sp; 655 int instance; 656 657 instance = ddi_get_instance(dip); 658 if ((sp = ddi_get_soft_state(ds_pri_statep, instance)) == NULL) 659 return; 660 661 DS_PRI_DBG("ds_pri_reg_handler: registering handle 0x%lx for version " 662 "0x%x:0x%x\n", (uint64_t)hdl, ver->major, ver->minor); 663 664 /* When the domain service comes up automatically req the pri */ 665 mutex_enter(&sp->lock); 666 667 ASSERT(sp->ds_pri_handle == DS_INVALID_HDL); 668 sp->ds_pri_handle = hdl; 669 670 ASSERT(sp->state == DS_PRI_NO_SERVICE); 671 ASSERT(sp->ds_pri == NULL); 672 ASSERT(sp->ds_pri_len == 0); 673 674 /* have service, but no PRI */ 675 sp->state |= DS_PRI_HAS_SERVICE; 676 677 /* 678 * Cannot request a PRI here, because the reg handler cannot 679 * do a DS send operation - we take care of this later. 680 */ 681 mutex_exit(&sp->lock); 682 } 683 684 685 static void 686 ds_pri_unreg_handler(ds_cb_arg_t arg) 687 { 688 dev_info_t *dip = arg; 689 ds_pri_state_t *sp; 690 int instance; 691 692 instance = ddi_get_instance(dip); 693 if ((sp = ddi_get_soft_state(ds_pri_statep, instance)) == NULL) 694 return; 695 696 DS_PRI_DBG("ds_pri_unreg_handler: un-registering ds_pri service\n"); 697 698 mutex_enter(&sp->lock); 699 700 /* Once the service goes - if we have a PRI at hand free it up */ 701 if (sp->ds_pri_len != 0) { 702 kmem_free(sp->ds_pri, sp->ds_pri_len); 703 sp->ds_pri_len = 0; 704 sp->ds_pri = NULL; 705 } 706 sp->ds_pri_handle = DS_INVALID_HDL; 707 sp->state = DS_PRI_NO_SERVICE; 708 709 mutex_exit(&sp->lock); 710 } 711 712 713 static void 714 ds_pri_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen) 715 { 716 dev_info_t *dip = arg; 717 ds_pri_state_t *sp; 718 int instance; 719 void *data; 720 ds_pri_msg_t *msgp; 721 size_t pri_size; 722 723 msgp = (ds_pri_msg_t *)buf; 724 725 /* make sure the header is at least valid */ 726 if (buflen < sizeof (msgp->hdr)) 727 return; 728 729 DS_PRI_DBG("ds_pri_data_handler: msg buf len 0x%lx : type 0x%lx, " 730 "seqn 0x%lx\n", buflen, msgp->hdr.type, msgp->hdr.seq_num); 731 732 instance = ddi_get_instance(dip); 733 if ((sp = ddi_get_soft_state(ds_pri_statep, instance)) == NULL) 734 return; 735 736 mutex_enter(&sp->lock); 737 738 ASSERT(sp->state & DS_PRI_HAS_SERVICE); 739 740 switch (msgp->hdr.type) { 741 case DS_PRI_DATA: /* in response to a request from us */ 742 break; 743 case DS_PRI_UPDATE: /* aynch notification */ 744 /* our default response to this is to request the PRI */ 745 /* simply issue a request for the new PRI */ 746 request_pri(sp); 747 goto done; 748 default: /* ignore garbage or unknown message types */ 749 goto done; 750 } 751 752 /* 753 * If there is no pending PRI request, then we've received a 754 * bogus data message ... so ignore it. 755 */ 756 757 if (!(sp->state & DS_PRI_REQUESTED)) { 758 cmn_err(CE_WARN, "Received DS pri data without request"); 759 goto done; 760 } 761 762 /* response to a request therefore old PRI must be gone */ 763 ASSERT(!(sp->state & DS_PRI_HAS_PRI)); 764 ASSERT(sp->ds_pri_len == 0); 765 ASSERT(sp->ds_pri == NULL); 766 767 /* response seq_num should match our request seq_num */ 768 if (msgp->hdr.seq_num != sp->last_req_id) { 769 cmn_err(CE_WARN, "Received DS pri data out of sequence with " 770 "request"); 771 goto done; 772 } 773 774 pri_size = buflen - sizeof (msgp->hdr); 775 data = kmem_alloc(pri_size, KM_SLEEP); 776 sp->ds_pri = data; 777 sp->ds_pri_len = pri_size; 778 bcopy(msgp->data, data, sp->ds_pri_len); 779 sp->state &= ~DS_PRI_REQUESTED; 780 sp->state |= DS_PRI_HAS_PRI; 781 782 sp->gencount++; 783 cv_broadcast(&sp->cv); 784 785 done:; 786 mutex_exit(&sp->lock); 787 } 788