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 2006 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 * Logical domain channel devices are devices implemented entirely 30 * in software; cnex is the nexus for channel-devices. They use 31 * the HV channel interfaces via the LDC transport module to send 32 * and receive data and to register callbacks. 33 */ 34 35 #include <sys/types.h> 36 #include <sys/cmn_err.h> 37 #include <sys/conf.h> 38 #include <sys/ddi.h> 39 #include <sys/ddi_impldefs.h> 40 #include <sys/devops.h> 41 #include <sys/instance.h> 42 #include <sys/modctl.h> 43 #include <sys/open.h> 44 #include <sys/stat.h> 45 #include <sys/sunddi.h> 46 #include <sys/sunndi.h> 47 #include <sys/systm.h> 48 #include <sys/mkdev.h> 49 #include <sys/machsystm.h> 50 #include <sys/intr.h> 51 #include <sys/ddi_intr_impl.h> 52 #include <sys/ivintr.h> 53 #include <sys/hypervisor_api.h> 54 #include <sys/ldc.h> 55 #include <sys/cnex.h> 56 #include <sys/mach_descrip.h> 57 58 /* 59 * Internal functions/information 60 */ 61 static struct cnex_pil_map cnex_class_to_pil[] = { 62 {LDC_DEV_GENERIC, PIL_3}, 63 {LDC_DEV_BLK, PIL_4}, 64 {LDC_DEV_BLK_SVC, PIL_3}, 65 {LDC_DEV_NT, PIL_6}, 66 {LDC_DEV_NT_SVC, PIL_4}, 67 {LDC_DEV_SERIAL, PIL_6} 68 }; 69 #define CNEX_MAX_DEVS (sizeof (cnex_class_to_pil) / \ 70 sizeof (cnex_class_to_pil[0])) 71 72 #define SUN4V_REG_SPEC2CFG_HDL(x) ((x >> 32) & ~(0xfull << 28)) 73 74 static hrtime_t cnex_pending_tmout = 2ull * NANOSEC; /* 2 secs in nsecs */ 75 static void *cnex_state; 76 77 static void cnex_intr_redist(void *arg); 78 static uint_t cnex_intr_wrapper(caddr_t arg); 79 80 /* 81 * Debug info 82 */ 83 #ifdef DEBUG 84 85 /* 86 * Print debug messages 87 * 88 * set cnexdbg to 0xf for enabling all msgs 89 * 0x8 - Errors 90 * 0x4 - Warnings 91 * 0x2 - All debug messages 92 * 0x1 - Minimal debug messages 93 */ 94 95 int cnexdbg = 0x8; 96 97 static void 98 cnexdebug(const char *fmt, ...) 99 { 100 char buf[512]; 101 va_list ap; 102 103 va_start(ap, fmt); 104 (void) vsprintf(buf, fmt, ap); 105 va_end(ap); 106 107 cmn_err(CE_CONT, "%s\n", buf); 108 } 109 110 #define D1 \ 111 if (cnexdbg & 0x01) \ 112 cnexdebug 113 114 #define D2 \ 115 if (cnexdbg & 0x02) \ 116 cnexdebug 117 118 #define DWARN \ 119 if (cnexdbg & 0x04) \ 120 cnexdebug 121 122 #define DERR \ 123 if (cnexdbg & 0x08) \ 124 cnexdebug 125 126 #else 127 128 #define D1 129 #define D2 130 #define DWARN 131 #define DERR 132 133 #endif 134 135 /* 136 * Config information 137 */ 138 static int cnex_attach(dev_info_t *, ddi_attach_cmd_t); 139 static int cnex_detach(dev_info_t *, ddi_detach_cmd_t); 140 static int cnex_open(dev_t *, int, int, cred_t *); 141 static int cnex_close(dev_t, int, int, cred_t *); 142 static int cnex_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 143 static int cnex_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, 144 void *); 145 146 static struct bus_ops cnex_bus_ops = { 147 BUSO_REV, 148 nullbusmap, /* bus_map */ 149 NULL, /* bus_get_intrspec */ 150 NULL, /* bus_add_intrspec */ 151 NULL, /* bus_remove_intrspec */ 152 i_ddi_map_fault, /* bus_map_fault */ 153 ddi_no_dma_map, /* bus_dma_map */ 154 ddi_no_dma_allochdl, /* bus_dma_allochdl */ 155 NULL, /* bus_dma_freehdl */ 156 NULL, /* bus_dma_bindhdl */ 157 NULL, /* bus_dma_unbindhdl */ 158 NULL, /* bus_dma_flush */ 159 NULL, /* bus_dma_win */ 160 NULL, /* bus_dma_ctl */ 161 cnex_ctl, /* bus_ctl */ 162 ddi_bus_prop_op, /* bus_prop_op */ 163 0, /* bus_get_eventcookie */ 164 0, /* bus_add_eventcall */ 165 0, /* bus_remove_eventcall */ 166 0, /* bus_post_event */ 167 NULL, /* bus_intr_ctl */ 168 NULL, /* bus_config */ 169 NULL, /* bus_unconfig */ 170 NULL, /* bus_fm_init */ 171 NULL, /* bus_fm_fini */ 172 NULL, /* bus_fm_access_enter */ 173 NULL, /* bus_fm_access_exit */ 174 NULL, /* bus_power */ 175 NULL /* bus_intr_op */ 176 }; 177 178 static struct cb_ops cnex_cb_ops = { 179 cnex_open, /* open */ 180 cnex_close, /* close */ 181 nodev, /* strategy */ 182 nodev, /* print */ 183 nodev, /* dump */ 184 nodev, /* read */ 185 nodev, /* write */ 186 cnex_ioctl, /* ioctl */ 187 nodev, /* devmap */ 188 nodev, /* mmap */ 189 nodev, /* segmap */ 190 nochpoll, /* poll */ 191 ddi_prop_op, /* cb_prop_op */ 192 0, /* streamtab */ 193 D_MP | D_NEW | D_HOTPLUG /* Driver compatibility flag */ 194 }; 195 196 static struct dev_ops cnex_ops = { 197 DEVO_REV, /* devo_rev, */ 198 0, /* refcnt */ 199 ddi_getinfo_1to1, /* info */ 200 nulldev, /* identify */ 201 nulldev, /* probe */ 202 cnex_attach, /* attach */ 203 cnex_detach, /* detach */ 204 nodev, /* reset */ 205 &cnex_cb_ops, /* driver operations */ 206 &cnex_bus_ops, /* bus operations */ 207 nulldev /* power */ 208 }; 209 210 /* 211 * Module linkage information for the kernel. 212 */ 213 static struct modldrv modldrv = { 214 &mod_driverops, 215 "sun4v channel-devices nexus driver v%I%", 216 &cnex_ops, 217 }; 218 219 static struct modlinkage modlinkage = { 220 MODREV_1, (void *)&modldrv, NULL 221 }; 222 223 int 224 _init(void) 225 { 226 int err; 227 228 if ((err = ddi_soft_state_init(&cnex_state, 229 sizeof (cnex_soft_state_t), 0)) != 0) { 230 return (err); 231 } 232 if ((err = mod_install(&modlinkage)) != 0) { 233 ddi_soft_state_fini(&cnex_state); 234 return (err); 235 } 236 return (0); 237 } 238 239 int 240 _fini(void) 241 { 242 int err; 243 244 if ((err = mod_remove(&modlinkage)) != 0) 245 return (err); 246 ddi_soft_state_fini(&cnex_state); 247 return (0); 248 } 249 250 int 251 _info(struct modinfo *modinfop) 252 { 253 return (mod_info(&modlinkage, modinfop)); 254 } 255 256 /* 257 * Callback function invoked by the interrupt redistribution 258 * framework. This will redirect interrupts at CPUs that are 259 * currently available in the system. 260 */ 261 static void 262 cnex_intr_redist(void *arg) 263 { 264 cnex_ldc_t *cldcp; 265 cnex_soft_state_t *cnex_ssp = arg; 266 int intr_state; 267 hrtime_t start; 268 uint64_t cpuid; 269 int rv; 270 271 ASSERT(cnex_ssp != NULL); 272 mutex_enter(&cnex_ssp->clist_lock); 273 274 cldcp = cnex_ssp->clist; 275 while (cldcp != NULL) { 276 277 mutex_enter(&cldcp->lock); 278 279 if (cldcp->tx.hdlr) { 280 /* 281 * Don't do anything for disabled interrupts. 282 */ 283 rv = hvldc_intr_getvalid(cnex_ssp->cfghdl, 284 cldcp->tx.ino, &intr_state); 285 if (rv) { 286 DWARN("cnex_intr_redist: tx ino=0x%llx, " 287 "can't get valid\n", cldcp->tx.ino); 288 mutex_exit(&cldcp->lock); 289 mutex_exit(&cnex_ssp->clist_lock); 290 return; 291 } 292 if (intr_state == HV_INTR_NOTVALID) { 293 cldcp = cldcp->next; 294 continue; 295 } 296 297 cpuid = intr_dist_cpuid(); 298 299 /* disable interrupts */ 300 rv = hvldc_intr_setvalid(cnex_ssp->cfghdl, 301 cldcp->tx.ino, HV_INTR_NOTVALID); 302 if (rv) { 303 DWARN("cnex_intr_redist: tx ino=0x%llx, " 304 "can't set valid\n", cldcp->tx.ino); 305 mutex_exit(&cldcp->lock); 306 mutex_exit(&cnex_ssp->clist_lock); 307 return; 308 } 309 310 /* 311 * Make a best effort to wait for pending interrupts 312 * to finish. There is not much we can do if we timeout. 313 */ 314 start = gethrtime(); 315 316 do { 317 rv = hvldc_intr_getstate(cnex_ssp->cfghdl, 318 cldcp->tx.ino, &intr_state); 319 if (rv) { 320 DWARN("cnex_intr_redist: tx ino=0x%llx," 321 "can't get state\n", cldcp->tx.ino); 322 mutex_exit(&cldcp->lock); 323 mutex_exit(&cnex_ssp->clist_lock); 324 return; 325 } 326 327 if ((gethrtime() - start) > cnex_pending_tmout) 328 break; 329 330 } while (!panicstr && 331 intr_state == HV_INTR_DELIVERED_STATE); 332 333 (void) hvldc_intr_settarget(cnex_ssp->cfghdl, 334 cldcp->tx.ino, cpuid); 335 (void) hvldc_intr_setvalid(cnex_ssp->cfghdl, 336 cldcp->tx.ino, HV_INTR_VALID); 337 } 338 339 if (cldcp->rx.hdlr) { 340 /* 341 * Don't do anything for disabled interrupts. 342 */ 343 rv = hvldc_intr_getvalid(cnex_ssp->cfghdl, 344 cldcp->rx.ino, &intr_state); 345 if (rv) { 346 DWARN("cnex_intr_redist: rx ino=0x%llx, " 347 "can't get valid\n", cldcp->rx.ino); 348 mutex_exit(&cldcp->lock); 349 mutex_exit(&cnex_ssp->clist_lock); 350 return; 351 } 352 if (intr_state == HV_INTR_NOTVALID) { 353 cldcp = cldcp->next; 354 continue; 355 } 356 357 cpuid = intr_dist_cpuid(); 358 359 /* disable interrupts */ 360 rv = hvldc_intr_setvalid(cnex_ssp->cfghdl, 361 cldcp->rx.ino, HV_INTR_NOTVALID); 362 if (rv) { 363 DWARN("cnex_intr_redist: rx ino=0x%llx, " 364 "can't set valid\n", cldcp->rx.ino); 365 mutex_exit(&cldcp->lock); 366 mutex_exit(&cnex_ssp->clist_lock); 367 return; 368 } 369 370 /* 371 * Make a best effort to wait for pending interrupts 372 * to finish. There is not much we can do if we timeout. 373 */ 374 start = gethrtime(); 375 376 do { 377 rv = hvldc_intr_getstate(cnex_ssp->cfghdl, 378 cldcp->rx.ino, &intr_state); 379 if (rv) { 380 DWARN("cnex_intr_redist: rx ino=0x%llx," 381 "can't set state\n", cldcp->rx.ino); 382 mutex_exit(&cldcp->lock); 383 mutex_exit(&cnex_ssp->clist_lock); 384 return; 385 } 386 387 if ((gethrtime() - start) > cnex_pending_tmout) 388 break; 389 390 } while (!panicstr && 391 intr_state == HV_INTR_DELIVERED_STATE); 392 393 (void) hvldc_intr_settarget(cnex_ssp->cfghdl, 394 cldcp->rx.ino, cpuid); 395 (void) hvldc_intr_setvalid(cnex_ssp->cfghdl, 396 cldcp->rx.ino, HV_INTR_VALID); 397 } 398 399 mutex_exit(&cldcp->lock); 400 401 /* next channel */ 402 cldcp = cldcp->next; 403 } 404 405 mutex_exit(&cnex_ssp->clist_lock); 406 } 407 408 /* 409 * Exported interface to register a LDC endpoint with 410 * the channel nexus 411 */ 412 static int 413 cnex_reg_chan(dev_info_t *dip, uint64_t id, ldc_dev_t devclass) 414 { 415 int idx; 416 cnex_ldc_t *cldcp; 417 int listsz, num_nodes, num_channels; 418 md_t *mdp = NULL; 419 mde_cookie_t rootnode, *listp = NULL; 420 uint64_t tmp_id, rxino, txino; 421 cnex_soft_state_t *cnex_ssp; 422 int status, instance; 423 424 /* Get device instance and structure */ 425 instance = ddi_get_instance(dip); 426 cnex_ssp = ddi_get_soft_state(cnex_state, instance); 427 428 /* Check to see if channel is already registered */ 429 mutex_enter(&cnex_ssp->clist_lock); 430 cldcp = cnex_ssp->clist; 431 while (cldcp) { 432 if (cldcp->id == id) { 433 DWARN("cnex_reg_chan: channel 0x%llx exists\n", id); 434 mutex_exit(&cnex_ssp->clist_lock); 435 return (EINVAL); 436 } 437 cldcp = cldcp->next; 438 } 439 440 /* Get the Tx/Rx inos from the MD */ 441 if ((mdp = md_get_handle()) == NULL) { 442 DWARN("cnex_reg_chan: cannot init MD\n"); 443 mutex_exit(&cnex_ssp->clist_lock); 444 return (ENXIO); 445 } 446 num_nodes = md_node_count(mdp); 447 ASSERT(num_nodes > 0); 448 449 listsz = num_nodes * sizeof (mde_cookie_t); 450 listp = (mde_cookie_t *)kmem_zalloc(listsz, KM_SLEEP); 451 452 rootnode = md_root_node(mdp); 453 454 /* search for all channel_endpoint nodes */ 455 num_channels = md_scan_dag(mdp, rootnode, 456 md_find_name(mdp, "channel-endpoint"), 457 md_find_name(mdp, "fwd"), listp); 458 if (num_channels <= 0) { 459 DWARN("cnex_reg_chan: invalid channel id\n"); 460 kmem_free(listp, listsz); 461 (void) md_fini_handle(mdp); 462 mutex_exit(&cnex_ssp->clist_lock); 463 return (EINVAL); 464 } 465 466 for (idx = 0; idx < num_channels; idx++) { 467 468 /* Get the channel ID */ 469 status = md_get_prop_val(mdp, listp[idx], "id", &tmp_id); 470 if (status) { 471 DWARN("cnex_reg_chan: cannot read LDC ID\n"); 472 kmem_free(listp, listsz); 473 (void) md_fini_handle(mdp); 474 mutex_exit(&cnex_ssp->clist_lock); 475 return (ENXIO); 476 } 477 if (tmp_id != id) 478 continue; 479 480 /* Get the Tx and Rx ino */ 481 status = md_get_prop_val(mdp, listp[idx], "tx-ino", &txino); 482 if (status) { 483 DWARN("cnex_reg_chan: cannot read Tx ino\n"); 484 kmem_free(listp, listsz); 485 (void) md_fini_handle(mdp); 486 mutex_exit(&cnex_ssp->clist_lock); 487 return (ENXIO); 488 } 489 status = md_get_prop_val(mdp, listp[idx], "rx-ino", &rxino); 490 if (status) { 491 DWARN("cnex_reg_chan: cannot read Rx ino\n"); 492 kmem_free(listp, listsz); 493 (void) md_fini_handle(mdp); 494 mutex_exit(&cnex_ssp->clist_lock); 495 return (ENXIO); 496 } 497 } 498 kmem_free(listp, listsz); 499 (void) md_fini_handle(mdp); 500 501 /* Allocate a new channel structure */ 502 cldcp = kmem_zalloc(sizeof (*cldcp), KM_SLEEP); 503 504 /* Initialize the channel */ 505 mutex_init(&cldcp->lock, NULL, MUTEX_DRIVER, NULL); 506 507 cldcp->id = id; 508 cldcp->tx.ino = txino; 509 cldcp->rx.ino = rxino; 510 cldcp->devclass = devclass; 511 512 /* add channel to nexus channel list */ 513 cldcp->next = cnex_ssp->clist; 514 cnex_ssp->clist = cldcp; 515 516 mutex_exit(&cnex_ssp->clist_lock); 517 518 return (0); 519 } 520 521 /* 522 * Add Tx/Rx interrupt handler for the channel 523 */ 524 static int 525 cnex_add_intr(dev_info_t *dip, uint64_t id, cnex_intrtype_t itype, 526 uint_t (*hdlr)(), caddr_t arg1, caddr_t arg2) 527 { 528 int rv, idx, pil; 529 cnex_ldc_t *cldcp; 530 cnex_intr_t *iinfo; 531 uint64_t cpuid; 532 cnex_soft_state_t *cnex_ssp; 533 int instance; 534 535 /* Get device instance and structure */ 536 instance = ddi_get_instance(dip); 537 cnex_ssp = ddi_get_soft_state(cnex_state, instance); 538 539 /* get channel info */ 540 mutex_enter(&cnex_ssp->clist_lock); 541 cldcp = cnex_ssp->clist; 542 while (cldcp) { 543 if (cldcp->id == id) 544 break; 545 cldcp = cldcp->next; 546 } 547 if (cldcp == NULL) { 548 DWARN("cnex_add_intr: channel 0x%llx does not exist\n", id); 549 mutex_exit(&cnex_ssp->clist_lock); 550 return (EINVAL); 551 } 552 mutex_exit(&cnex_ssp->clist_lock); 553 554 /* get channel lock */ 555 mutex_enter(&cldcp->lock); 556 557 /* get interrupt type */ 558 if (itype == CNEX_TX_INTR) { 559 iinfo = &(cldcp->tx); 560 } else if (itype == CNEX_RX_INTR) { 561 iinfo = &(cldcp->rx); 562 } else { 563 DWARN("cnex_add_intr: invalid interrupt type\n", id); 564 mutex_exit(&cldcp->lock); 565 return (EINVAL); 566 } 567 568 /* check if a handler is already added */ 569 if (iinfo->hdlr != 0) { 570 DWARN("cnex_add_intr: interrupt handler exists\n"); 571 mutex_exit(&cldcp->lock); 572 return (EINVAL); 573 } 574 575 /* save interrupt handler info */ 576 iinfo->hdlr = hdlr; 577 iinfo->arg1 = arg1; 578 iinfo->arg2 = arg2; 579 580 iinfo->ssp = cnex_ssp; 581 582 /* 583 * FIXME - generate the interrupt cookie 584 * using the interrupt registry 585 */ 586 iinfo->icookie = cnex_ssp->cfghdl | iinfo->ino; 587 588 D1("cnex_add_intr: add hdlr, cfghdl=0x%llx, ino=0x%llx, " 589 "cookie=0x%llx\n", cnex_ssp->cfghdl, iinfo->ino, iinfo->icookie); 590 591 /* Pick a PIL on the basis of the channel's devclass */ 592 for (idx = 0, pil = PIL_3; idx < CNEX_MAX_DEVS; idx++) { 593 if (cldcp->devclass == cnex_class_to_pil[idx].devclass) { 594 pil = cnex_class_to_pil[idx].pil; 595 break; 596 } 597 } 598 599 /* add interrupt to solaris ivec table */ 600 VERIFY(add_ivintr(iinfo->icookie, pil, cnex_intr_wrapper, 601 (caddr_t)iinfo, NULL) == 0); 602 603 /* set the cookie in the HV */ 604 rv = hvldc_intr_setcookie(cnex_ssp->cfghdl, iinfo->ino, iinfo->icookie); 605 606 /* pick next CPU in the domain for this channel */ 607 cpuid = intr_dist_cpuid(); 608 609 /* set the target CPU and then enable interrupts */ 610 rv = hvldc_intr_settarget(cnex_ssp->cfghdl, iinfo->ino, cpuid); 611 if (rv) { 612 DWARN("cnex_add_intr: ino=0x%llx, cannot set target cpu\n", 613 iinfo->ino); 614 goto hv_error; 615 } 616 rv = hvldc_intr_setstate(cnex_ssp->cfghdl, iinfo->ino, 617 HV_INTR_IDLE_STATE); 618 if (rv) { 619 DWARN("cnex_add_intr: ino=0x%llx, cannot set state\n", 620 iinfo->ino); 621 goto hv_error; 622 } 623 rv = hvldc_intr_setvalid(cnex_ssp->cfghdl, iinfo->ino, HV_INTR_VALID); 624 if (rv) { 625 DWARN("cnex_add_intr: ino=0x%llx, cannot set valid\n", 626 iinfo->ino); 627 goto hv_error; 628 } 629 630 mutex_exit(&cldcp->lock); 631 return (0); 632 633 hv_error: 634 (void) rem_ivintr(iinfo->icookie, NULL); 635 mutex_exit(&cldcp->lock); 636 return (ENXIO); 637 } 638 639 640 /* 641 * Exported interface to unregister a LDC endpoint with 642 * the channel nexus 643 */ 644 static int 645 cnex_unreg_chan(dev_info_t *dip, uint64_t id) 646 { 647 cnex_ldc_t *cldcp, *prev_cldcp; 648 cnex_soft_state_t *cnex_ssp; 649 int instance; 650 651 /* Get device instance and structure */ 652 instance = ddi_get_instance(dip); 653 cnex_ssp = ddi_get_soft_state(cnex_state, instance); 654 655 /* find and remove channel from list */ 656 mutex_enter(&cnex_ssp->clist_lock); 657 prev_cldcp = NULL; 658 cldcp = cnex_ssp->clist; 659 while (cldcp) { 660 if (cldcp->id == id) 661 break; 662 prev_cldcp = cldcp; 663 cldcp = cldcp->next; 664 } 665 666 if (cldcp == 0) { 667 DWARN("cnex_unreg_chan: invalid channel %d\n", id); 668 mutex_exit(&cnex_ssp->clist_lock); 669 return (EINVAL); 670 } 671 672 if (cldcp->tx.hdlr || cldcp->rx.hdlr) { 673 DWARN("cnex_unreg_chan: handlers still exist\n"); 674 mutex_exit(&cnex_ssp->clist_lock); 675 return (ENXIO); 676 } 677 678 if (prev_cldcp) 679 prev_cldcp->next = cldcp->next; 680 else 681 cnex_ssp->clist = cldcp->next; 682 683 mutex_exit(&cnex_ssp->clist_lock); 684 685 /* destroy mutex */ 686 mutex_destroy(&cldcp->lock); 687 688 /* free channel */ 689 kmem_free(cldcp, sizeof (*cldcp)); 690 691 return (0); 692 } 693 694 /* 695 * Remove Tx/Rx interrupt handler for the channel 696 */ 697 static int 698 cnex_rem_intr(dev_info_t *dip, uint64_t id, cnex_intrtype_t itype) 699 { 700 int rv; 701 cnex_ldc_t *cldcp; 702 cnex_intr_t *iinfo; 703 cnex_soft_state_t *cnex_ssp; 704 hrtime_t start; 705 int instance, istate; 706 707 /* Get device instance and structure */ 708 instance = ddi_get_instance(dip); 709 cnex_ssp = ddi_get_soft_state(cnex_state, instance); 710 711 /* get channel info */ 712 mutex_enter(&cnex_ssp->clist_lock); 713 cldcp = cnex_ssp->clist; 714 while (cldcp) { 715 if (cldcp->id == id) 716 break; 717 cldcp = cldcp->next; 718 } 719 if (cldcp == NULL) { 720 DWARN("cnex_rem_intr: channel 0x%llx does not exist\n", id); 721 mutex_exit(&cnex_ssp->clist_lock); 722 return (EINVAL); 723 } 724 mutex_exit(&cnex_ssp->clist_lock); 725 726 /* get rid of the channel intr handler */ 727 mutex_enter(&cldcp->lock); 728 729 /* get interrupt type */ 730 if (itype == CNEX_TX_INTR) { 731 iinfo = &(cldcp->tx); 732 } else if (itype == CNEX_RX_INTR) { 733 iinfo = &(cldcp->rx); 734 } else { 735 DWARN("cnex_rem_intr: invalid interrupt type\n"); 736 mutex_exit(&cldcp->lock); 737 return (EINVAL); 738 } 739 740 D1("cnex_rem_intr: interrupt ino=0x%x\n", iinfo->ino); 741 742 /* check if a handler is already added */ 743 if (iinfo->hdlr == 0) { 744 DWARN("cnex_rem_intr: interrupt handler does not exist\n"); 745 mutex_exit(&cldcp->lock); 746 return (EINVAL); 747 } 748 749 D1("cnex_rem_intr: set intr to invalid ino=0x%x\n", iinfo->ino); 750 rv = hvldc_intr_setvalid(cnex_ssp->cfghdl, 751 iinfo->ino, HV_INTR_NOTVALID); 752 if (rv) { 753 DWARN("cnex_rem_intr: cannot set valid ino=%x\n", iinfo->ino); 754 mutex_exit(&cldcp->lock); 755 return (ENXIO); 756 } 757 758 /* 759 * Make a best effort to wait for pending interrupts 760 * to finish. There is not much we can do if we timeout. 761 */ 762 start = gethrtime(); 763 do { 764 rv = hvldc_intr_getstate(cnex_ssp->cfghdl, iinfo->ino, &istate); 765 if (rv) { 766 DWARN("cnex_rem_intr: ino=0x%llx, cannot get state\n", 767 iinfo->ino); 768 } 769 770 if (rv || ((gethrtime() - start) > cnex_pending_tmout)) 771 break; 772 773 } while (!panicstr && istate == HV_INTR_DELIVERED_STATE); 774 775 /* if interrupts are still pending print warning */ 776 if (istate != HV_INTR_IDLE_STATE) { 777 DWARN("cnex_rem_intr: cannot remove intr busy ino=%x\n", 778 iinfo->ino); 779 /* clear interrupt state */ 780 (void) hvldc_intr_setstate(cnex_ssp->cfghdl, iinfo->ino, 781 HV_INTR_IDLE_STATE); 782 } 783 784 /* remove interrupt */ 785 rem_ivintr(iinfo->icookie, NULL); 786 787 /* clear interrupt info */ 788 bzero(iinfo, sizeof (*iinfo)); 789 790 mutex_exit(&cldcp->lock); 791 792 return (0); 793 } 794 795 796 /* 797 * Clear pending Tx/Rx interrupt 798 */ 799 static int 800 cnex_clr_intr(dev_info_t *dip, uint64_t id, cnex_intrtype_t itype) 801 { 802 int rv; 803 cnex_ldc_t *cldcp; 804 cnex_intr_t *iinfo; 805 cnex_soft_state_t *cnex_ssp; 806 int instance; 807 808 /* Get device instance and structure */ 809 instance = ddi_get_instance(dip); 810 cnex_ssp = ddi_get_soft_state(cnex_state, instance); 811 812 /* get channel info */ 813 mutex_enter(&cnex_ssp->clist_lock); 814 cldcp = cnex_ssp->clist; 815 while (cldcp) { 816 if (cldcp->id == id) 817 break; 818 cldcp = cldcp->next; 819 } 820 if (cldcp == NULL) { 821 DWARN("cnex_clr_intr: channel 0x%llx does not exist\n", id); 822 mutex_exit(&cnex_ssp->clist_lock); 823 return (EINVAL); 824 } 825 mutex_exit(&cnex_ssp->clist_lock); 826 827 mutex_enter(&cldcp->lock); 828 829 /* get interrupt type */ 830 if (itype == CNEX_TX_INTR) { 831 iinfo = &(cldcp->tx); 832 } else if (itype == CNEX_RX_INTR) { 833 iinfo = &(cldcp->rx); 834 } else { 835 DWARN("cnex_rem_intr: invalid interrupt type\n"); 836 mutex_exit(&cldcp->lock); 837 return (EINVAL); 838 } 839 840 D1("cnex_rem_intr: interrupt ino=0x%x\n", iinfo->ino); 841 842 /* check if a handler is already added */ 843 if (iinfo->hdlr == 0) { 844 DWARN("cnex_clr_intr: interrupt handler does not exist\n"); 845 mutex_exit(&cldcp->lock); 846 return (EINVAL); 847 } 848 849 rv = hvldc_intr_setstate(cnex_ssp->cfghdl, iinfo->ino, 850 HV_INTR_IDLE_STATE); 851 if (rv) { 852 DWARN("cnex_intr_wrapper: cannot clear interrupt state\n"); 853 } 854 855 mutex_exit(&cldcp->lock); 856 857 return (0); 858 } 859 860 /* 861 * Channel nexus interrupt handler wrapper 862 */ 863 static uint_t 864 cnex_intr_wrapper(caddr_t arg) 865 { 866 int res; 867 uint_t (*handler)(); 868 caddr_t handler_arg1; 869 caddr_t handler_arg2; 870 cnex_intr_t *iinfo = (cnex_intr_t *)arg; 871 872 ASSERT(iinfo != NULL); 873 874 handler = iinfo->hdlr; 875 handler_arg1 = iinfo->arg1; 876 handler_arg2 = iinfo->arg2; 877 878 D1("cnex_intr_wrapper: ino=0x%llx invoke client handler\n", iinfo->ino); 879 res = (*handler)(handler_arg1, handler_arg2); 880 881 return (res); 882 } 883 884 /*ARGSUSED*/ 885 static int 886 cnex_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 887 { 888 int rv, instance, reglen; 889 cnex_regspec_t *reg_p; 890 ldc_cnex_t cinfo; 891 cnex_soft_state_t *cnex_ssp; 892 893 switch (cmd) { 894 case DDI_ATTACH: 895 break; 896 case DDI_RESUME: 897 return (DDI_SUCCESS); 898 default: 899 return (DDI_FAILURE); 900 } 901 902 /* 903 * Get the instance specific soft state structure. 904 * Save the devi for this instance in the soft_state data. 905 */ 906 instance = ddi_get_instance(devi); 907 if (ddi_soft_state_zalloc(cnex_state, instance) != DDI_SUCCESS) 908 return (DDI_FAILURE); 909 cnex_ssp = ddi_get_soft_state(cnex_state, instance); 910 911 cnex_ssp->devi = devi; 912 cnex_ssp->clist = NULL; 913 914 if (ddi_getlongprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 915 "reg", (caddr_t)®_p, ®len) != DDI_SUCCESS) { 916 return (DDI_FAILURE); 917 } 918 919 /* get the sun4v config handle for this device */ 920 cnex_ssp->cfghdl = SUN4V_REG_SPEC2CFG_HDL(reg_p->physaddr); 921 kmem_free(reg_p, reglen); 922 923 D1("cnex_attach: cfghdl=0x%llx\n", cnex_ssp->cfghdl); 924 925 /* init channel list mutex */ 926 mutex_init(&cnex_ssp->clist_lock, NULL, MUTEX_DRIVER, NULL); 927 928 /* Register with LDC module */ 929 cinfo.dip = devi; 930 cinfo.reg_chan = cnex_reg_chan; 931 cinfo.unreg_chan = cnex_unreg_chan; 932 cinfo.add_intr = cnex_add_intr; 933 cinfo.rem_intr = cnex_rem_intr; 934 cinfo.clr_intr = cnex_clr_intr; 935 936 /* 937 * LDC register will fail if an nexus instance had already 938 * registered with the LDC framework 939 */ 940 rv = ldc_register(&cinfo); 941 if (rv) { 942 DWARN("cnex_attach: unable to register with LDC\n"); 943 ddi_soft_state_free(cnex_state, instance); 944 mutex_destroy(&cnex_ssp->clist_lock); 945 return (DDI_FAILURE); 946 } 947 948 if (ddi_create_minor_node(devi, "devctl", S_IFCHR, instance, 949 DDI_NT_NEXUS, 0) != DDI_SUCCESS) { 950 ddi_remove_minor_node(devi, NULL); 951 ddi_soft_state_free(cnex_state, instance); 952 mutex_destroy(&cnex_ssp->clist_lock); 953 return (DDI_FAILURE); 954 } 955 956 /* Add interrupt redistribution callback. */ 957 intr_dist_add(cnex_intr_redist, cnex_ssp); 958 959 ddi_report_dev(devi); 960 return (DDI_SUCCESS); 961 } 962 963 /*ARGSUSED*/ 964 static int 965 cnex_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 966 { 967 int instance; 968 ldc_cnex_t cinfo; 969 cnex_soft_state_t *cnex_ssp; 970 971 switch (cmd) { 972 case DDI_DETACH: 973 break; 974 case DDI_SUSPEND: 975 return (DDI_SUCCESS); 976 default: 977 return (DDI_FAILURE); 978 } 979 980 instance = ddi_get_instance(devi); 981 cnex_ssp = ddi_get_soft_state(cnex_state, instance); 982 983 /* check if there are any channels still registered */ 984 if (cnex_ssp->clist) { 985 cmn_err(CE_WARN, "?cnex_dettach: channels registered %d\n", 986 ddi_get_instance(devi)); 987 return (DDI_FAILURE); 988 } 989 990 /* Unregister with LDC module */ 991 cinfo.dip = devi; 992 (void) ldc_unregister(&cinfo); 993 994 /* Remove interrupt redistribution callback. */ 995 intr_dist_rem(cnex_intr_redist, cnex_ssp); 996 997 /* destroy mutex */ 998 mutex_destroy(&cnex_ssp->clist_lock); 999 1000 /* free soft state structure */ 1001 ddi_soft_state_free(cnex_state, instance); 1002 1003 return (DDI_SUCCESS); 1004 } 1005 1006 /*ARGSUSED*/ 1007 static int 1008 cnex_open(dev_t *devp, int flags, int otyp, cred_t *credp) 1009 { 1010 int instance; 1011 1012 if (otyp != OTYP_CHR) 1013 return (EINVAL); 1014 1015 instance = getminor(*devp); 1016 if (ddi_get_soft_state(cnex_state, instance) == NULL) 1017 return (ENXIO); 1018 1019 return (0); 1020 } 1021 1022 /*ARGSUSED*/ 1023 static int 1024 cnex_close(dev_t dev, int flags, int otyp, cred_t *credp) 1025 { 1026 int instance; 1027 1028 if (otyp != OTYP_CHR) 1029 return (EINVAL); 1030 1031 instance = getminor(dev); 1032 if (ddi_get_soft_state(cnex_state, instance) == NULL) 1033 return (ENXIO); 1034 1035 return (0); 1036 } 1037 1038 /*ARGSUSED*/ 1039 static int 1040 cnex_ioctl(dev_t dev, 1041 int cmd, intptr_t arg, int mode, cred_t *cred_p, int *rval_p) 1042 { 1043 int instance; 1044 cnex_soft_state_t *cnex_ssp; 1045 1046 instance = getminor(dev); 1047 if ((cnex_ssp = ddi_get_soft_state(cnex_state, instance)) == NULL) 1048 return (ENXIO); 1049 ASSERT(cnex_ssp->devi); 1050 return (ndi_devctl_ioctl(cnex_ssp->devi, cmd, arg, mode, 0)); 1051 } 1052 1053 static int 1054 cnex_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop, 1055 void *arg, void *result) 1056 { 1057 char name[MAXNAMELEN]; 1058 uint32_t reglen; 1059 int *cnex_regspec; 1060 1061 switch (ctlop) { 1062 case DDI_CTLOPS_REPORTDEV: 1063 if (rdip == NULL) 1064 return (DDI_FAILURE); 1065 cmn_err(CE_CONT, "?channel-device: %s%d\n", 1066 ddi_driver_name(rdip), ddi_get_instance(rdip)); 1067 return (DDI_SUCCESS); 1068 1069 case DDI_CTLOPS_INITCHILD: 1070 { 1071 dev_info_t *child = (dev_info_t *)arg; 1072 1073 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, 1074 DDI_PROP_DONTPASS, "reg", 1075 &cnex_regspec, ®len) != DDI_SUCCESS) { 1076 return (DDI_FAILURE); 1077 } 1078 1079 (void) snprintf(name, sizeof (name), "%x", *cnex_regspec); 1080 ddi_set_name_addr(child, name); 1081 ddi_set_parent_data(child, NULL); 1082 ddi_prop_free(cnex_regspec); 1083 return (DDI_SUCCESS); 1084 } 1085 1086 case DDI_CTLOPS_UNINITCHILD: 1087 { 1088 dev_info_t *child = (dev_info_t *)arg; 1089 1090 NDI_CONFIG_DEBUG((CE_NOTE, 1091 "DDI_CTLOPS_UNINITCHILD(%s, instance=%d)", 1092 ddi_driver_name(child), DEVI(child)->devi_instance)); 1093 1094 ddi_set_name_addr(child, NULL); 1095 1096 return (DDI_SUCCESS); 1097 } 1098 1099 case DDI_CTLOPS_DMAPMAPC: 1100 case DDI_CTLOPS_REPORTINT: 1101 case DDI_CTLOPS_REGSIZE: 1102 case DDI_CTLOPS_NREGS: 1103 case DDI_CTLOPS_SIDDEV: 1104 case DDI_CTLOPS_SLAVEONLY: 1105 case DDI_CTLOPS_AFFINITY: 1106 case DDI_CTLOPS_POKE: 1107 case DDI_CTLOPS_PEEK: 1108 /* 1109 * These ops correspond to functions that "shouldn't" be called 1110 * by a channel-device driver. So we whine when we're called. 1111 */ 1112 cmn_err(CE_WARN, "%s%d: invalid op (%d) from %s%d\n", 1113 ddi_driver_name(dip), ddi_get_instance(dip), ctlop, 1114 ddi_driver_name(rdip), ddi_get_instance(rdip)); 1115 return (DDI_FAILURE); 1116 1117 case DDI_CTLOPS_ATTACH: 1118 case DDI_CTLOPS_BTOP: 1119 case DDI_CTLOPS_BTOPR: 1120 case DDI_CTLOPS_DETACH: 1121 case DDI_CTLOPS_DVMAPAGESIZE: 1122 case DDI_CTLOPS_IOMIN: 1123 case DDI_CTLOPS_POWER: 1124 case DDI_CTLOPS_PTOB: 1125 default: 1126 /* 1127 * Everything else (e.g. PTOB/BTOP/BTOPR requests) we pass up 1128 */ 1129 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 1130 } 1131 } 1132 1133 /* -------------------------------------------------------------------------- */ 1134