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