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