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 mutex_exit(&cldcp->lock); 769 return (ENXIO); 770 } 771 772 if ((gethrtime() - start) > cnex_pending_tmout) 773 break; 774 775 } while (!panicstr && istate == HV_INTR_DELIVERED_STATE); 776 777 /* if interrupts are still pending print warning */ 778 if (istate != HV_INTR_IDLE_STATE) { 779 DWARN("cnex_rem_intr: cannot remove intr busy ino=%x\n", 780 iinfo->ino); 781 mutex_exit(&cldcp->lock); 782 return (EAGAIN); 783 } 784 785 /* remove interrupt */ 786 rem_ivintr(iinfo->icookie, NULL); 787 788 /* clear interrupt info */ 789 bzero(iinfo, sizeof (*iinfo)); 790 791 mutex_exit(&cldcp->lock); 792 793 return (0); 794 } 795 796 797 /* 798 * Clear pending Tx/Rx interrupt 799 */ 800 static int 801 cnex_clr_intr(dev_info_t *dip, uint64_t id, cnex_intrtype_t itype) 802 { 803 int rv; 804 cnex_ldc_t *cldcp; 805 cnex_intr_t *iinfo; 806 cnex_soft_state_t *cnex_ssp; 807 int instance; 808 809 /* Get device instance and structure */ 810 instance = ddi_get_instance(dip); 811 cnex_ssp = ddi_get_soft_state(cnex_state, instance); 812 813 /* get channel info */ 814 mutex_enter(&cnex_ssp->clist_lock); 815 cldcp = cnex_ssp->clist; 816 while (cldcp) { 817 if (cldcp->id == id) 818 break; 819 cldcp = cldcp->next; 820 } 821 if (cldcp == NULL) { 822 DWARN("cnex_clr_intr: channel 0x%llx does not exist\n", id); 823 mutex_exit(&cnex_ssp->clist_lock); 824 return (EINVAL); 825 } 826 mutex_exit(&cnex_ssp->clist_lock); 827 828 mutex_enter(&cldcp->lock); 829 830 /* get interrupt type */ 831 if (itype == CNEX_TX_INTR) { 832 iinfo = &(cldcp->tx); 833 } else if (itype == CNEX_RX_INTR) { 834 iinfo = &(cldcp->rx); 835 } else { 836 DWARN("cnex_rem_intr: invalid interrupt type\n"); 837 mutex_exit(&cldcp->lock); 838 return (EINVAL); 839 } 840 841 D1("cnex_rem_intr: interrupt ino=0x%x\n", iinfo->ino); 842 843 /* check if a handler is already added */ 844 if (iinfo->hdlr == 0) { 845 DWARN("cnex_clr_intr: interrupt handler does not exist\n"); 846 mutex_exit(&cldcp->lock); 847 return (EINVAL); 848 } 849 850 rv = hvldc_intr_setstate(cnex_ssp->cfghdl, iinfo->ino, 851 HV_INTR_IDLE_STATE); 852 if (rv) { 853 DWARN("cnex_intr_wrapper: cannot clear interrupt state\n"); 854 mutex_exit(&cldcp->lock); 855 return (ENXIO); 856 } 857 858 mutex_exit(&cldcp->lock); 859 860 return (0); 861 } 862 863 /* 864 * Channel nexus interrupt handler wrapper 865 */ 866 static uint_t 867 cnex_intr_wrapper(caddr_t arg) 868 { 869 int res; 870 uint_t (*handler)(); 871 caddr_t handler_arg1; 872 caddr_t handler_arg2; 873 cnex_intr_t *iinfo = (cnex_intr_t *)arg; 874 875 ASSERT(iinfo != NULL); 876 877 handler = iinfo->hdlr; 878 handler_arg1 = iinfo->arg1; 879 handler_arg2 = iinfo->arg2; 880 881 D1("cnex_intr_wrapper: ino=0x%llx invoke client handler\n", iinfo->ino); 882 res = (*handler)(handler_arg1, handler_arg2); 883 884 return (res); 885 } 886 887 /*ARGSUSED*/ 888 static int 889 cnex_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 890 { 891 int rv, instance, reglen; 892 cnex_regspec_t *reg_p; 893 ldc_cnex_t cinfo; 894 cnex_soft_state_t *cnex_ssp; 895 896 switch (cmd) { 897 case DDI_ATTACH: 898 break; 899 case DDI_RESUME: 900 return (DDI_SUCCESS); 901 default: 902 return (DDI_FAILURE); 903 } 904 905 /* 906 * Get the instance specific soft state structure. 907 * Save the devi for this instance in the soft_state data. 908 */ 909 instance = ddi_get_instance(devi); 910 if (ddi_soft_state_zalloc(cnex_state, instance) != DDI_SUCCESS) 911 return (DDI_FAILURE); 912 cnex_ssp = ddi_get_soft_state(cnex_state, instance); 913 914 cnex_ssp->devi = devi; 915 cnex_ssp->clist = NULL; 916 917 if (ddi_getlongprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 918 "reg", (caddr_t)®_p, ®len) != DDI_SUCCESS) { 919 return (DDI_FAILURE); 920 } 921 922 /* get the sun4v config handle for this device */ 923 cnex_ssp->cfghdl = SUN4V_REG_SPEC2CFG_HDL(reg_p->physaddr); 924 kmem_free(reg_p, reglen); 925 926 D1("cnex_attach: cfghdl=0x%llx\n", cnex_ssp->cfghdl); 927 928 /* init channel list mutex */ 929 mutex_init(&cnex_ssp->clist_lock, NULL, MUTEX_DRIVER, NULL); 930 931 /* Register with LDC module */ 932 cinfo.dip = devi; 933 cinfo.reg_chan = cnex_reg_chan; 934 cinfo.unreg_chan = cnex_unreg_chan; 935 cinfo.add_intr = cnex_add_intr; 936 cinfo.rem_intr = cnex_rem_intr; 937 cinfo.clr_intr = cnex_clr_intr; 938 939 /* 940 * LDC register will fail if an nexus instance had already 941 * registered with the LDC framework 942 */ 943 rv = ldc_register(&cinfo); 944 if (rv) { 945 DWARN("cnex_attach: unable to register with LDC\n"); 946 ddi_soft_state_free(cnex_state, instance); 947 mutex_destroy(&cnex_ssp->clist_lock); 948 return (DDI_FAILURE); 949 } 950 951 if (ddi_create_minor_node(devi, "devctl", S_IFCHR, instance, 952 DDI_NT_NEXUS, 0) != DDI_SUCCESS) { 953 ddi_remove_minor_node(devi, NULL); 954 ddi_soft_state_free(cnex_state, instance); 955 mutex_destroy(&cnex_ssp->clist_lock); 956 return (DDI_FAILURE); 957 } 958 959 /* Add interrupt redistribution callback. */ 960 intr_dist_add(cnex_intr_redist, cnex_ssp); 961 962 ddi_report_dev(devi); 963 return (DDI_SUCCESS); 964 } 965 966 /*ARGSUSED*/ 967 static int 968 cnex_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 969 { 970 int instance; 971 ldc_cnex_t cinfo; 972 cnex_soft_state_t *cnex_ssp; 973 974 switch (cmd) { 975 case DDI_DETACH: 976 break; 977 case DDI_SUSPEND: 978 return (DDI_SUCCESS); 979 default: 980 return (DDI_FAILURE); 981 } 982 983 instance = ddi_get_instance(devi); 984 cnex_ssp = ddi_get_soft_state(cnex_state, instance); 985 986 /* check if there are any channels still registered */ 987 if (cnex_ssp->clist) { 988 cmn_err(CE_WARN, "?cnex_dettach: channels registered %d\n", 989 ddi_get_instance(devi)); 990 return (DDI_FAILURE); 991 } 992 993 /* Unregister with LDC module */ 994 cinfo.dip = devi; 995 (void) ldc_unregister(&cinfo); 996 997 /* Remove interrupt redistribution callback. */ 998 intr_dist_rem(cnex_intr_redist, cnex_ssp); 999 1000 /* destroy mutex */ 1001 mutex_destroy(&cnex_ssp->clist_lock); 1002 1003 /* free soft state structure */ 1004 ddi_soft_state_free(cnex_state, instance); 1005 1006 return (DDI_SUCCESS); 1007 } 1008 1009 /*ARGSUSED*/ 1010 static int 1011 cnex_open(dev_t *devp, int flags, int otyp, cred_t *credp) 1012 { 1013 int instance; 1014 1015 if (otyp != OTYP_CHR) 1016 return (EINVAL); 1017 1018 instance = getminor(*devp); 1019 if (ddi_get_soft_state(cnex_state, instance) == NULL) 1020 return (ENXIO); 1021 1022 return (0); 1023 } 1024 1025 /*ARGSUSED*/ 1026 static int 1027 cnex_close(dev_t dev, int flags, int otyp, cred_t *credp) 1028 { 1029 int instance; 1030 1031 if (otyp != OTYP_CHR) 1032 return (EINVAL); 1033 1034 instance = getminor(dev); 1035 if (ddi_get_soft_state(cnex_state, instance) == NULL) 1036 return (ENXIO); 1037 1038 return (0); 1039 } 1040 1041 /*ARGSUSED*/ 1042 static int 1043 cnex_ioctl(dev_t dev, 1044 int cmd, intptr_t arg, int mode, cred_t *cred_p, int *rval_p) 1045 { 1046 int instance; 1047 cnex_soft_state_t *cnex_ssp; 1048 1049 instance = getminor(dev); 1050 if ((cnex_ssp = ddi_get_soft_state(cnex_state, instance)) == NULL) 1051 return (ENXIO); 1052 ASSERT(cnex_ssp->devi); 1053 return (ndi_devctl_ioctl(cnex_ssp->devi, cmd, arg, mode, 0)); 1054 } 1055 1056 static int 1057 cnex_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop, 1058 void *arg, void *result) 1059 { 1060 char name[MAXNAMELEN]; 1061 uint32_t reglen; 1062 int *cnex_regspec; 1063 1064 switch (ctlop) { 1065 case DDI_CTLOPS_REPORTDEV: 1066 if (rdip == NULL) 1067 return (DDI_FAILURE); 1068 cmn_err(CE_CONT, "?channel-device: %s%d\n", 1069 ddi_driver_name(rdip), ddi_get_instance(rdip)); 1070 return (DDI_SUCCESS); 1071 1072 case DDI_CTLOPS_INITCHILD: 1073 { 1074 dev_info_t *child = (dev_info_t *)arg; 1075 1076 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, 1077 DDI_PROP_DONTPASS, "reg", 1078 &cnex_regspec, ®len) != DDI_SUCCESS) { 1079 return (DDI_FAILURE); 1080 } 1081 1082 (void) snprintf(name, sizeof (name), "%x", *cnex_regspec); 1083 ddi_set_name_addr(child, name); 1084 ddi_set_parent_data(child, NULL); 1085 ddi_prop_free(cnex_regspec); 1086 return (DDI_SUCCESS); 1087 } 1088 1089 case DDI_CTLOPS_UNINITCHILD: 1090 { 1091 dev_info_t *child = (dev_info_t *)arg; 1092 1093 NDI_CONFIG_DEBUG((CE_NOTE, 1094 "DDI_CTLOPS_UNINITCHILD(%s, instance=%d)", 1095 ddi_driver_name(child), DEVI(child)->devi_instance)); 1096 1097 ddi_set_name_addr(child, NULL); 1098 1099 return (DDI_SUCCESS); 1100 } 1101 1102 case DDI_CTLOPS_DMAPMAPC: 1103 case DDI_CTLOPS_REPORTINT: 1104 case DDI_CTLOPS_REGSIZE: 1105 case DDI_CTLOPS_NREGS: 1106 case DDI_CTLOPS_SIDDEV: 1107 case DDI_CTLOPS_SLAVEONLY: 1108 case DDI_CTLOPS_AFFINITY: 1109 case DDI_CTLOPS_POKE: 1110 case DDI_CTLOPS_PEEK: 1111 /* 1112 * These ops correspond to functions that "shouldn't" be called 1113 * by a channel-device driver. So we whine when we're called. 1114 */ 1115 cmn_err(CE_WARN, "%s%d: invalid op (%d) from %s%d\n", 1116 ddi_driver_name(dip), ddi_get_instance(dip), ctlop, 1117 ddi_driver_name(rdip), ddi_get_instance(rdip)); 1118 return (DDI_FAILURE); 1119 1120 case DDI_CTLOPS_ATTACH: 1121 case DDI_CTLOPS_BTOP: 1122 case DDI_CTLOPS_BTOPR: 1123 case DDI_CTLOPS_DETACH: 1124 case DDI_CTLOPS_DVMAPAGESIZE: 1125 case DDI_CTLOPS_IOMIN: 1126 case DDI_CTLOPS_POWER: 1127 case DDI_CTLOPS_PTOB: 1128 default: 1129 /* 1130 * Everything else (e.g. PTOB/BTOP/BTOPR requests) we pass up 1131 */ 1132 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 1133 } 1134 } 1135 1136 /* -------------------------------------------------------------------------- */ 1137