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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Xen virtual device driver interfaces 31 */ 32 33 /* 34 * todo: 35 * + name space clean up: 36 * xvdi_* - public xen interfaces, for use by all leaf drivers 37 * xd_* - public xen data structures 38 * i_xvdi_* - implementation private functions 39 * xendev_* - xendev driver interfaces, both internal and in cb_ops/bus_ops 40 * + add mdb dcmds to dump ring status 41 * + implement xvdi_xxx to wrap xenbus_xxx read/write function 42 * + convert (xendev_ring_t *) into xvdi_ring_handle_t 43 */ 44 #include <sys/conf.h> 45 #include <sys/param.h> 46 #include <sys/kmem.h> 47 #include <vm/seg_kmem.h> 48 #include <sys/debug.h> 49 #include <sys/modctl.h> 50 #include <sys/autoconf.h> 51 #include <sys/ddi_impldefs.h> 52 #include <sys/ddi_subrdefs.h> 53 #include <sys/ddi.h> 54 #include <sys/sunddi.h> 55 #include <sys/sunndi.h> 56 #include <sys/sunldi.h> 57 #include <sys/fs/dv_node.h> 58 #include <sys/avintr.h> 59 #include <sys/psm.h> 60 #include <sys/spl.h> 61 #include <sys/promif.h> 62 #include <sys/list.h> 63 #include <sys/bootconf.h> 64 #include <sys/bootsvcs.h> 65 #include <sys/bootinfo.h> 66 #include <sys/note.h> 67 #ifdef XPV_HVM_DRIVER 68 #include <sys/xpv_support.h> 69 #include <sys/hypervisor.h> 70 #include <public/grant_table.h> 71 #include <public/xen.h> 72 #include <public/io/xenbus.h> 73 #include <public/io/xs_wire.h> 74 #include <public/event_channel.h> 75 #include <public/io/xenbus.h> 76 #else /* XPV_HVM_DRIVER */ 77 #include <sys/hypervisor.h> 78 #include <sys/xen_mmu.h> 79 #include <xen/sys/xenbus_impl.h> 80 #include <sys/evtchn_impl.h> 81 #endif /* XPV_HVM_DRIVER */ 82 #include <sys/gnttab.h> 83 #include <xen/sys/xendev.h> 84 #include <vm/hat_i86.h> 85 #include <sys/scsi/generic/inquiry.h> 86 #include <util/sscanf.h> 87 #include <xen/public/io/xs_wire.h> 88 89 90 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9') 91 #define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \ 92 ((ch) >= 'A' && (ch) <= 'F')) 93 94 static void xvdi_ring_init_sring(xendev_ring_t *); 95 static void xvdi_ring_init_front_ring(xendev_ring_t *, size_t, size_t); 96 #ifndef XPV_HVM_DRIVER 97 static void xvdi_ring_init_back_ring(xendev_ring_t *, size_t, size_t); 98 #endif 99 static void xvdi_reinit_ring(dev_info_t *, grant_ref_t *, xendev_ring_t *); 100 101 static int i_xvdi_add_watches(dev_info_t *); 102 static void i_xvdi_rem_watches(dev_info_t *); 103 104 static int i_xvdi_add_watch_oestate(dev_info_t *); 105 static void i_xvdi_rem_watch_oestate(dev_info_t *); 106 static void i_xvdi_oestate_cb(struct xenbus_device *, XenbusState); 107 static void i_xvdi_oestate_handler(void *); 108 109 static int i_xvdi_add_watch_hpstate(dev_info_t *); 110 static void i_xvdi_rem_watch_hpstate(dev_info_t *); 111 static void i_xvdi_hpstate_cb(struct xenbus_watch *, const char **, 112 unsigned int); 113 static void i_xvdi_hpstate_handler(void *); 114 115 static int i_xvdi_add_watch_bepath(dev_info_t *); 116 static void i_xvdi_rem_watch_bepath(dev_info_t *); 117 static void i_xvdi_bepath_cb(struct xenbus_watch *, const char **, 118 unsigned in); 119 120 static void xendev_offline_device(void *); 121 122 static void i_xvdi_probe_path_cb(struct xenbus_watch *, const char **, 123 unsigned int); 124 static void i_xvdi_probe_path_handler(void *); 125 126 typedef struct xd_cfg { 127 xendev_devclass_t devclass; 128 char *xsdev; 129 char *xs_path_fe; 130 char *xs_path_be; 131 char *node_fe; 132 char *node_be; 133 char *device_type; 134 int xd_ipl; 135 int flags; 136 } i_xd_cfg_t; 137 138 #define XD_DOM_ZERO 0x01 /* dom0 only. */ 139 #define XD_DOM_GUEST 0x02 /* Guest domains (i.e. non-dom0). */ 140 #define XD_DOM_IO 0x04 /* IO domains. */ 141 142 #define XD_DOM_ALL (XD_DOM_ZERO | XD_DOM_GUEST) 143 144 static i_xd_cfg_t xdci[] = { 145 { XEN_CONSOLE, NULL, NULL, NULL, "xencons", NULL, 146 "console", IPL_CONS, XD_DOM_ALL, }, 147 148 { XEN_VNET, "vif", "device/vif", "backend/vif", "xnf", "xnb", 149 "network", IPL_VIF, XD_DOM_ALL, }, 150 151 { XEN_VBLK, "vbd", "device/vbd", "backend/vbd", "xdf", "xdb", 152 "block", IPL_VBD, XD_DOM_ALL, }, 153 154 { XEN_XENBUS, NULL, NULL, NULL, "xenbus", NULL, 155 NULL, 0, XD_DOM_ALL, }, 156 157 { XEN_DOMCAPS, NULL, NULL, NULL, "domcaps", NULL, 158 NULL, 0, XD_DOM_ALL, }, 159 160 { XEN_BALLOON, NULL, NULL, NULL, "balloon", NULL, 161 NULL, 0, XD_DOM_ALL, }, 162 163 { XEN_EVTCHN, NULL, NULL, NULL, "evtchn", NULL, 164 NULL, 0, XD_DOM_ZERO, }, 165 166 { XEN_PRIVCMD, NULL, NULL, NULL, "privcmd", NULL, 167 NULL, 0, XD_DOM_ZERO, }, 168 }; 169 #define NXDC (sizeof (xdci) / sizeof (xdci[0])) 170 171 static void i_xvdi_enum_fe(dev_info_t *, i_xd_cfg_t *); 172 static void i_xvdi_enum_be(dev_info_t *, i_xd_cfg_t *); 173 static void i_xvdi_enum_worker(dev_info_t *, i_xd_cfg_t *, char *); 174 175 /* 176 * Xen device channel device access and DMA attributes 177 */ 178 static ddi_device_acc_attr_t xendev_dc_accattr = { 179 DDI_DEVICE_ATTR_V0, DDI_NEVERSWAP_ACC, DDI_STRICTORDER_ACC 180 }; 181 182 static ddi_dma_attr_t xendev_dc_dmaattr = { 183 DMA_ATTR_V0, /* version of this structure */ 184 0, /* lowest usable address */ 185 0xffffffffffffffffULL, /* highest usable address */ 186 0x7fffffff, /* maximum DMAable byte count */ 187 MMU_PAGESIZE, /* alignment in bytes */ 188 0x7ff, /* bitmap of burst sizes */ 189 1, /* minimum transfer */ 190 0xffffffffU, /* maximum transfer */ 191 0xffffffffffffffffULL, /* maximum segment length */ 192 1, /* maximum number of segments */ 193 1, /* granularity */ 194 0, /* flags (reserved) */ 195 }; 196 197 static dev_info_t *xendev_dip = NULL; 198 199 #define XVDI_DBG_STATE 0x01 200 #define XVDI_DBG_PROBE 0x02 201 202 #ifdef DEBUG 203 int i_xvdi_debug = 0; 204 205 #define XVDI_DPRINTF(flag, format, ...) \ 206 { \ 207 if (i_xvdi_debug & (flag)) \ 208 prom_printf((format), __VA_ARGS__); \ 209 } 210 #else 211 #define XVDI_DPRINTF(flag, format, ...) 212 #endif /* DEBUG */ 213 214 static i_xd_cfg_t * 215 i_xvdi_devclass2cfg(xendev_devclass_t devclass) 216 { 217 i_xd_cfg_t *xdcp; 218 int i; 219 220 for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) 221 if (xdcp->devclass == devclass) 222 return (xdcp); 223 224 return (NULL); 225 } 226 227 int 228 xvdi_init_dev(dev_info_t *dip) 229 { 230 xendev_devclass_t devcls; 231 int vdevnum; 232 domid_t domid; 233 struct xendev_ppd *pdp; 234 i_xd_cfg_t *xdcp; 235 boolean_t backend; 236 char xsnamebuf[TYPICALMAXPATHLEN]; 237 char *xsname; 238 239 devcls = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 240 DDI_PROP_DONTPASS, "devclass", XEN_INVAL); 241 vdevnum = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 242 DDI_PROP_DONTPASS, "vdev", VDEV_NOXS); 243 domid = (domid_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip, 244 DDI_PROP_DONTPASS, "domain", DOMID_SELF); 245 246 backend = (domid != DOMID_SELF); 247 xdcp = i_xvdi_devclass2cfg(devcls); 248 if (xdcp->device_type != NULL) 249 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 250 "device_type", xdcp->device_type); 251 252 pdp = kmem_zalloc(sizeof (*pdp), KM_SLEEP); 253 pdp->xd_domain = domid; 254 pdp->xd_vdevnum = vdevnum; 255 pdp->xd_devclass = devcls; 256 pdp->xd_evtchn = INVALID_EVTCHN; 257 mutex_init(&pdp->xd_lk, NULL, MUTEX_DRIVER, NULL); 258 ddi_set_parent_data(dip, pdp); 259 260 /* 261 * devices that do not need to interact with xenstore 262 */ 263 if (vdevnum == VDEV_NOXS) { 264 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 265 "unit-address", "0"); 266 if (devcls == XEN_CONSOLE) 267 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 268 "pm-hardware-state", "needs-suspend-resume"); 269 return (DDI_SUCCESS); 270 } 271 272 /* 273 * PV devices that need to probe xenstore 274 */ 275 276 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 277 "pm-hardware-state", "needs-suspend-resume"); 278 279 xsname = xsnamebuf; 280 if (!backend) 281 (void) snprintf(xsnamebuf, sizeof (xsnamebuf), 282 "%s/%d", xdcp->xs_path_fe, vdevnum); 283 else 284 (void) snprintf(xsnamebuf, sizeof (xsnamebuf), 285 "%s/%d/%d", xdcp->xs_path_be, domid, vdevnum); 286 if ((xenbus_read_driver_state(xsname) >= XenbusStateClosing)) { 287 /* Don't try to init a dev that may be closing */ 288 mutex_destroy(&pdp->xd_lk); 289 kmem_free(pdp, sizeof (*pdp)); 290 ddi_set_parent_data(dip, NULL); 291 return (DDI_FAILURE); 292 } 293 294 pdp->xd_xsdev.nodename = i_ddi_strdup(xsname, KM_SLEEP); 295 pdp->xd_xsdev.devicetype = xdcp->xsdev; 296 pdp->xd_xsdev.frontend = (backend ? 0 : 1); 297 pdp->xd_xsdev.data = dip; 298 pdp->xd_xsdev.otherend_id = (backend ? domid : -1); 299 if (i_xvdi_add_watches(dip) != DDI_SUCCESS) { 300 cmn_err(CE_WARN, "xvdi_init_dev: " 301 "cannot add watches for %s", xsname); 302 xvdi_uninit_dev(dip); 303 return (DDI_FAILURE); 304 } 305 306 /* 307 * frontend device will use "unit-addr" as 308 * the bus address, which will be set here 309 */ 310 if (!backend) { 311 char *prop_str; 312 unsigned int prop_len, addr, i; 313 boolean_t use_vdev; 314 char addr_str[9]; /* hold 32-bit hex */ 315 316 switch (devcls) { 317 case XEN_VNET: 318 if (xenbus_read(XBT_NULL, xsname, 319 "mac", (void *)&prop_str, &prop_len) == 0) { 320 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 321 dip, "mac", prop_str); 322 kmem_free(prop_str, prop_len); 323 } 324 prop_str = NULL; 325 if (xenbus_scanf(XBT_NULL, xsname, "handle", "%u", 326 &addr) == 0) { 327 328 (void) snprintf(addr_str, sizeof (addr_str), 329 "%x", addr); 330 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 331 dip, "unit-address", addr_str); 332 } 333 break; 334 case XEN_VBLK: 335 if (xenbus_read(XBT_NULL, pdp->xd_xsdev.otherend, 336 "dev", (void *)&prop_str, &prop_len) != 0) 337 break; 338 339 /* 340 * Save a copy of the xenstore "dev" property 341 * on the device node. 342 */ 343 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 344 dip, "xenstore-dev", prop_str); 345 346 /* 347 * Verify that the "dev" property associated with the 348 * otherend device is a 32-bit hex value. Normally 349 * we use this value as the "unit-address" (which is 350 * the same as the solaris device bus address). If 351 * the "dev" property is not a32-bit hex value then 352 * that usually means we're in an HVM environment 353 * where the disk names have been specified via 354 * non-integer values. In this case we'll fall 355 * back to using the devices vdev value (which is 356 * really just its xenstore id) as its unit-address. 357 */ 358 i = 0; 359 use_vdev = B_FALSE; 360 while (prop_str[i] != '\0') { 361 if ((!isxdigit(prop_str[i++])) || 362 (prop_str[i++] >= 8)) { 363 use_vdev = B_TRUE; 364 break; 365 } 366 } 367 if (use_vdev) { 368 /* 369 * Use the xenstore device id as the 370 * devices "unit-address". 371 */ 372 addr = vdevnum; 373 } else { 374 /* 375 * Use the xenstore "dev" property as the 376 * devices "unit-address". 377 */ 378 (void) sscanf(prop_str, "%x", &addr); 379 } 380 kmem_free(prop_str, prop_len); 381 (void) snprintf(addr_str, sizeof (addr_str), 382 "%x", addr); 383 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 384 dip, "unit-address", addr_str); 385 break; 386 default: 387 break; 388 } 389 } 390 391 return (DDI_SUCCESS); 392 } 393 394 void 395 xvdi_uninit_dev(dev_info_t *dip) 396 { 397 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 398 399 if (pdp != NULL) { 400 /* Remove any registered callbacks. */ 401 xvdi_remove_event_handler(dip, NULL); 402 403 /* Remove any registered watches. */ 404 i_xvdi_rem_watches(dip); 405 406 /* tell other end to close */ 407 if (pdp->xd_xsdev.otherend_id != (domid_t)-1) 408 (void) xvdi_switch_state(dip, XBT_NULL, 409 XenbusStateClosed); 410 411 if (pdp->xd_xsdev.nodename != NULL) 412 kmem_free((char *)(pdp->xd_xsdev.nodename), 413 strlen(pdp->xd_xsdev.nodename) + 1); 414 415 ddi_set_parent_data(dip, NULL); 416 417 mutex_destroy(&pdp->xd_lk); 418 kmem_free(pdp, sizeof (*pdp)); 419 } 420 } 421 422 /* 423 * Bind the event channel for this device instance. 424 * Currently we only support one evtchn per device instance. 425 */ 426 int 427 xvdi_bind_evtchn(dev_info_t *dip, evtchn_port_t evtchn) 428 { 429 struct xendev_ppd *pdp; 430 domid_t oeid; 431 int r; 432 433 pdp = ddi_get_parent_data(dip); 434 ASSERT(pdp != NULL); 435 ASSERT(pdp->xd_evtchn == INVALID_EVTCHN); 436 437 mutex_enter(&pdp->xd_lk); 438 if (pdp->xd_devclass == XEN_CONSOLE) { 439 if (!DOMAIN_IS_INITDOMAIN(xen_info)) { 440 pdp->xd_evtchn = xen_info->console.domU.evtchn; 441 } else { 442 pdp->xd_evtchn = INVALID_EVTCHN; 443 mutex_exit(&pdp->xd_lk); 444 return (DDI_SUCCESS); 445 } 446 } else { 447 oeid = pdp->xd_xsdev.otherend_id; 448 if (oeid == (domid_t)-1) { 449 mutex_exit(&pdp->xd_lk); 450 return (DDI_FAILURE); 451 } 452 453 if ((r = xen_bind_interdomain(oeid, evtchn, &pdp->xd_evtchn))) { 454 xvdi_dev_error(dip, r, "bind event channel"); 455 mutex_exit(&pdp->xd_lk); 456 return (DDI_FAILURE); 457 } 458 } 459 #ifndef XPV_HVM_DRIVER 460 pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn); 461 #endif 462 mutex_exit(&pdp->xd_lk); 463 464 return (DDI_SUCCESS); 465 } 466 467 /* 468 * Allocate an event channel for this device instance. 469 * Currently we only support one evtchn per device instance. 470 */ 471 int 472 xvdi_alloc_evtchn(dev_info_t *dip) 473 { 474 struct xendev_ppd *pdp; 475 domid_t oeid; 476 int rv; 477 478 pdp = ddi_get_parent_data(dip); 479 ASSERT(pdp != NULL); 480 ASSERT(pdp->xd_evtchn == INVALID_EVTCHN); 481 482 mutex_enter(&pdp->xd_lk); 483 if (pdp->xd_devclass == XEN_CONSOLE) { 484 if (!DOMAIN_IS_INITDOMAIN(xen_info)) { 485 pdp->xd_evtchn = xen_info->console.domU.evtchn; 486 } else { 487 pdp->xd_evtchn = INVALID_EVTCHN; 488 mutex_exit(&pdp->xd_lk); 489 return (DDI_SUCCESS); 490 } 491 } else { 492 oeid = pdp->xd_xsdev.otherend_id; 493 if (oeid == (domid_t)-1) { 494 mutex_exit(&pdp->xd_lk); 495 return (DDI_FAILURE); 496 } 497 498 if ((rv = xen_alloc_unbound_evtchn(oeid, &pdp->xd_evtchn))) { 499 xvdi_dev_error(dip, rv, "bind event channel"); 500 mutex_exit(&pdp->xd_lk); 501 return (DDI_FAILURE); 502 } 503 } 504 #ifndef XPV_HVM_DRIVER 505 pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn); 506 #endif 507 mutex_exit(&pdp->xd_lk); 508 509 return (DDI_SUCCESS); 510 } 511 512 /* 513 * Unbind the event channel for this device instance. 514 * Currently we only support one evtchn per device instance. 515 */ 516 void 517 xvdi_free_evtchn(dev_info_t *dip) 518 { 519 struct xendev_ppd *pdp; 520 521 pdp = ddi_get_parent_data(dip); 522 ASSERT(pdp != NULL); 523 524 mutex_enter(&pdp->xd_lk); 525 if (pdp->xd_evtchn != INVALID_EVTCHN) { 526 #ifndef XPV_HVM_DRIVER 527 ec_unbind_irq(pdp->xd_ispec.intrspec_vec); 528 pdp->xd_ispec.intrspec_vec = 0; 529 #endif 530 pdp->xd_evtchn = INVALID_EVTCHN; 531 } 532 mutex_exit(&pdp->xd_lk); 533 } 534 535 #ifndef XPV_HVM_DRIVER 536 /* 537 * Map an inter-domain communication ring for a virtual device. 538 * This is used by backend drivers. 539 */ 540 int 541 xvdi_map_ring(dev_info_t *dip, size_t nentry, size_t entrysize, 542 grant_ref_t gref, xendev_ring_t **ringpp) 543 { 544 domid_t oeid; 545 gnttab_map_grant_ref_t mapop; 546 gnttab_unmap_grant_ref_t unmapop; 547 caddr_t ringva; 548 ddi_acc_hdl_t *ap; 549 ddi_acc_impl_t *iap; 550 xendev_ring_t *ring; 551 int err; 552 char errstr[] = "mapping in ring buffer"; 553 554 ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP); 555 oeid = xvdi_get_oeid(dip); 556 557 /* alloc va in backend dom for ring buffer */ 558 ringva = vmem_xalloc(heap_arena, PAGESIZE, PAGESIZE, 559 0, 0, 0, 0, VM_SLEEP); 560 561 /* map in ring page */ 562 hat_prepare_mapping(kas.a_hat, ringva); 563 mapop.host_addr = (uint64_t)(uintptr_t)ringva; 564 mapop.flags = GNTMAP_host_map; 565 mapop.ref = gref; 566 mapop.dom = oeid; 567 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &mapop, 1); 568 if (err) { 569 xvdi_fatal_error(dip, err, errstr); 570 goto errout1; 571 } 572 573 if (mapop.status != 0) { 574 xvdi_fatal_error(dip, err, errstr); 575 goto errout2; 576 } 577 ring->xr_vaddr = ringva; 578 ring->xr_grant_hdl = mapop.handle; 579 ring->xr_gref = gref; 580 581 /* 582 * init an acc handle and associate it w/ this ring 583 * this is only for backend drivers. we get the memory by calling 584 * vmem_xalloc(), instead of calling any ddi function, so we have 585 * to init an acc handle by ourselves 586 */ 587 ring->xr_acc_hdl = impl_acc_hdl_alloc(KM_SLEEP, NULL); 588 ap = impl_acc_hdl_get(ring->xr_acc_hdl); 589 ap->ah_vers = VERS_ACCHDL; 590 ap->ah_dip = dip; 591 ap->ah_xfermodes = DDI_DMA_CONSISTENT; 592 ap->ah_acc = xendev_dc_accattr; 593 iap = (ddi_acc_impl_t *)ap->ah_platform_private; 594 iap->ahi_acc_attr |= DDI_ACCATTR_CPU_VADDR; 595 impl_acc_hdl_init(ap); 596 ap->ah_offset = 0; 597 ap->ah_len = (off_t)PAGESIZE; 598 ap->ah_addr = ring->xr_vaddr; 599 600 /* init backend ring */ 601 xvdi_ring_init_back_ring(ring, nentry, entrysize); 602 603 *ringpp = ring; 604 605 return (DDI_SUCCESS); 606 607 errout2: 608 /* unmap ring page */ 609 unmapop.host_addr = (uint64_t)(uintptr_t)ringva; 610 unmapop.handle = ring->xr_grant_hdl; 611 unmapop.dev_bus_addr = NULL; 612 (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1); 613 hat_release_mapping(kas.a_hat, ringva); 614 errout1: 615 vmem_xfree(heap_arena, ringva, PAGESIZE); 616 kmem_free(ring, sizeof (xendev_ring_t)); 617 return (DDI_FAILURE); 618 } 619 620 /* 621 * Unmap a ring for a virtual device. 622 * This is used by backend drivers. 623 */ 624 void 625 xvdi_unmap_ring(xendev_ring_t *ring) 626 { 627 gnttab_unmap_grant_ref_t unmapop; 628 629 ASSERT((ring != NULL) && (ring->xr_vaddr != NULL)); 630 631 impl_acc_hdl_free(ring->xr_acc_hdl); 632 unmapop.host_addr = (uint64_t)(uintptr_t)ring->xr_vaddr; 633 unmapop.handle = ring->xr_grant_hdl; 634 unmapop.dev_bus_addr = NULL; 635 (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1); 636 hat_release_mapping(kas.a_hat, ring->xr_vaddr); 637 vmem_xfree(heap_arena, ring->xr_vaddr, PAGESIZE); 638 kmem_free(ring, sizeof (xendev_ring_t)); 639 } 640 #endif /* XPV_HVM_DRIVER */ 641 642 /* 643 * Re-initialise an inter-domain communications ring for the backend domain. 644 * ring will be re-initialized after re-grant succeed 645 * ring will be freed if fails to re-grant access to backend domain 646 * so, don't keep useful data in the ring 647 * used only in frontend driver 648 */ 649 static void 650 xvdi_reinit_ring(dev_info_t *dip, grant_ref_t *gref, xendev_ring_t *ringp) 651 { 652 paddr_t rpaddr; 653 maddr_t rmaddr; 654 655 ASSERT((ringp != NULL) && (ringp->xr_paddr != 0)); 656 rpaddr = ringp->xr_paddr; 657 658 rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? rpaddr : pa_to_ma(rpaddr); 659 gnttab_grant_foreign_access_ref(ringp->xr_gref, xvdi_get_oeid(dip), 660 rmaddr >> PAGESHIFT, 0); 661 *gref = ringp->xr_gref; 662 663 /* init frontend ring */ 664 xvdi_ring_init_sring(ringp); 665 xvdi_ring_init_front_ring(ringp, ringp->xr_sring.fr.nr_ents, 666 ringp->xr_entry_size); 667 } 668 669 /* 670 * allocate Xen inter-domain communications ring for Xen virtual devices 671 * used only in frontend driver 672 * if *ringpp is not NULL, we'll simply re-init it 673 */ 674 int 675 xvdi_alloc_ring(dev_info_t *dip, size_t nentry, size_t entrysize, 676 grant_ref_t *gref, xendev_ring_t **ringpp) 677 { 678 size_t len; 679 xendev_ring_t *ring; 680 ddi_dma_cookie_t dma_cookie; 681 uint_t ncookies; 682 grant_ref_t ring_gref; 683 domid_t oeid; 684 maddr_t rmaddr; 685 686 if (*ringpp) { 687 xvdi_reinit_ring(dip, gref, *ringpp); 688 return (DDI_SUCCESS); 689 } 690 691 *ringpp = ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP); 692 oeid = xvdi_get_oeid(dip); 693 694 /* 695 * Allocate page for this ring buffer 696 */ 697 if (ddi_dma_alloc_handle(dip, &xendev_dc_dmaattr, DDI_DMA_SLEEP, 698 0, &ring->xr_dma_hdl) != DDI_SUCCESS) 699 goto err; 700 701 if (ddi_dma_mem_alloc(ring->xr_dma_hdl, PAGESIZE, 702 &xendev_dc_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0, 703 &ring->xr_vaddr, &len, &ring->xr_acc_hdl) != DDI_SUCCESS) { 704 ddi_dma_free_handle(&ring->xr_dma_hdl); 705 goto err; 706 } 707 708 if (ddi_dma_addr_bind_handle(ring->xr_dma_hdl, NULL, 709 ring->xr_vaddr, len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 710 DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies) != DDI_DMA_MAPPED) { 711 ddi_dma_mem_free(&ring->xr_acc_hdl); 712 ring->xr_vaddr = NULL; 713 ddi_dma_free_handle(&ring->xr_dma_hdl); 714 goto err; 715 } 716 ASSERT(ncookies == 1); 717 ring->xr_paddr = dma_cookie.dmac_laddress; 718 rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? ring->xr_paddr : 719 pa_to_ma(ring->xr_paddr); 720 721 if ((ring_gref = gnttab_grant_foreign_access(oeid, 722 rmaddr >> PAGESHIFT, 0)) == (grant_ref_t)-1) { 723 (void) ddi_dma_unbind_handle(ring->xr_dma_hdl); 724 ddi_dma_mem_free(&ring->xr_acc_hdl); 725 ring->xr_vaddr = NULL; 726 ddi_dma_free_handle(&ring->xr_dma_hdl); 727 goto err; 728 } 729 *gref = ring->xr_gref = ring_gref; 730 731 /* init frontend ring */ 732 xvdi_ring_init_sring(ring); 733 xvdi_ring_init_front_ring(ring, nentry, entrysize); 734 735 return (DDI_SUCCESS); 736 737 err: 738 kmem_free(ring, sizeof (xendev_ring_t)); 739 return (DDI_FAILURE); 740 } 741 742 /* 743 * Release ring buffers allocated for Xen devices 744 * used for frontend driver 745 */ 746 void 747 xvdi_free_ring(xendev_ring_t *ring) 748 { 749 ASSERT((ring != NULL) && (ring->xr_vaddr != NULL)); 750 751 (void) gnttab_end_foreign_access_ref(ring->xr_gref, 0); 752 (void) ddi_dma_unbind_handle(ring->xr_dma_hdl); 753 ddi_dma_mem_free(&ring->xr_acc_hdl); 754 ddi_dma_free_handle(&ring->xr_dma_hdl); 755 kmem_free(ring, sizeof (xendev_ring_t)); 756 } 757 758 dev_info_t * 759 xvdi_create_dev(dev_info_t *parent, xendev_devclass_t devclass, 760 domid_t dom, int vdev) 761 { 762 dev_info_t *dip; 763 boolean_t backend; 764 i_xd_cfg_t *xdcp; 765 char xsnamebuf[TYPICALMAXPATHLEN]; 766 char *type, *node = NULL, *xsname = NULL; 767 unsigned int tlen; 768 int ret; 769 770 ASSERT(DEVI_BUSY_OWNED(parent)); 771 772 backend = (dom != DOMID_SELF); 773 xdcp = i_xvdi_devclass2cfg(devclass); 774 ASSERT(xdcp != NULL); 775 776 if (vdev != VDEV_NOXS) { 777 if (!backend) { 778 (void) snprintf(xsnamebuf, sizeof (xsnamebuf), 779 "%s/%d", xdcp->xs_path_fe, vdev); 780 xsname = xsnamebuf; 781 node = xdcp->node_fe; 782 } else { 783 (void) snprintf(xsnamebuf, sizeof (xsnamebuf), 784 "%s/%d/%d", xdcp->xs_path_be, dom, vdev); 785 xsname = xsnamebuf; 786 node = xdcp->node_be; 787 } 788 } else { 789 node = xdcp->node_fe; 790 } 791 792 /* Must have a driver to use. */ 793 if (node == NULL) 794 return (NULL); 795 796 /* 797 * We need to check the state of this device before we go 798 * further, otherwise we'll end up with a dead loop if 799 * anything goes wrong. 800 */ 801 if ((xsname != NULL) && 802 (xenbus_read_driver_state(xsname) >= XenbusStateClosing)) 803 return (NULL); 804 805 ndi_devi_alloc_sleep(parent, node, DEVI_SID_NODEID, &dip); 806 807 /* 808 * Driver binding uses the compatible property _before_ the 809 * node name, so we set the node name to the 'model' of the 810 * device (i.e. 'xnb' or 'xdb') and, if 'type' is present, 811 * encode both the model and the type in a compatible property 812 * (i.e. 'xnb,netfront' or 'xnb,SUNW_mac'). This allows a 813 * driver binding based on the <model,type> pair _before_ a 814 * binding based on the node name. 815 */ 816 if ((xsname != NULL) && 817 (xenbus_read(XBT_NULL, xsname, "type", (void *)&type, &tlen) 818 == 0)) { 819 size_t clen; 820 char *c[1]; 821 822 clen = strlen(node) + strlen(type) + 2; 823 c[0] = kmem_alloc(clen, KM_SLEEP); 824 (void) snprintf(c[0], clen, "%s,%s", node, type); 825 826 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, 827 dip, "compatible", (char **)c, 1); 828 829 kmem_free(c[0], clen); 830 kmem_free(type, tlen); 831 } 832 833 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "devclass", devclass); 834 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "domain", dom); 835 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "vdev", vdev); 836 837 if (i_ddi_devi_attached(parent)) 838 ret = ndi_devi_online(dip, 0); 839 else 840 ret = ndi_devi_bind_driver(dip, 0); 841 if (ret != NDI_SUCCESS) 842 (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE); 843 844 return (dip); 845 } 846 847 /* 848 * xendev_enum_class() 849 */ 850 void 851 xendev_enum_class(dev_info_t *parent, xendev_devclass_t devclass) 852 { 853 boolean_t dom0 = DOMAIN_IS_INITDOMAIN(xen_info); 854 boolean_t domU = !dom0; 855 i_xd_cfg_t *xdcp; 856 857 xdcp = i_xvdi_devclass2cfg(devclass); 858 ASSERT(xdcp != NULL); 859 860 if (dom0 && !(xdcp->flags & XD_DOM_ZERO)) 861 return; 862 863 if (domU && !(xdcp->flags & XD_DOM_GUEST)) 864 return; 865 866 if (xdcp->xsdev == NULL) { 867 int circ; 868 869 /* 870 * Don't need to probe this kind of device from the 871 * store, just create one if it doesn't exist. 872 */ 873 874 ndi_devi_enter(parent, &circ); 875 if (xvdi_find_dev(parent, devclass, DOMID_SELF, VDEV_NOXS) 876 == NULL) 877 (void) xvdi_create_dev(parent, devclass, 878 DOMID_SELF, VDEV_NOXS); 879 ndi_devi_exit(parent, circ); 880 } else { 881 /* 882 * Probe this kind of device from the store, both 883 * frontend and backend. 884 */ 885 886 i_xvdi_enum_fe(parent, xdcp); 887 i_xvdi_enum_be(parent, xdcp); 888 } 889 } 890 891 /* 892 * xendev_enum_all() 893 */ 894 void 895 xendev_enum_all(dev_info_t *parent, boolean_t store_unavailable) 896 { 897 int i; 898 i_xd_cfg_t *xdcp; 899 boolean_t dom0 = DOMAIN_IS_INITDOMAIN(xen_info); 900 901 for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) { 902 /* 903 * Dom0 relies on watchpoints to create non-soft 904 * devices - don't attempt to iterate over the store. 905 */ 906 if (dom0 && (xdcp->xsdev != NULL)) 907 continue; 908 909 /* 910 * If the store is not yet available, don't attempt to 911 * iterate. 912 */ 913 if (store_unavailable && (xdcp->xsdev != NULL)) 914 continue; 915 916 xendev_enum_class(parent, xdcp->devclass); 917 } 918 } 919 920 xendev_devclass_t 921 xendev_nodename_to_devclass(char *nodename) 922 { 923 int i; 924 i_xd_cfg_t *xdcp; 925 926 /* 927 * This relies on the convention that variants of a base 928 * driver share the same prefix and that there are no drivers 929 * which share a common prefix with the name of any other base 930 * drivers. 931 * 932 * So for a base driver 'xnb' (which is the name listed in 933 * xdci) the variants all begin with the string 'xnb' (in fact 934 * they are 'xnbe', 'xnbo' and 'xnbu') and there are no other 935 * base drivers which have the prefix 'xnb'. 936 */ 937 ASSERT(nodename != NULL); 938 for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) { 939 if (((xdcp->node_fe != NULL) && 940 (strncmp(nodename, xdcp->node_fe, 941 strlen(xdcp->node_fe)) == 0)) || 942 ((xdcp->node_be != NULL) && 943 (strncmp(nodename, xdcp->node_be, 944 strlen(xdcp->node_be)) == 0))) 945 946 return (xdcp->devclass); 947 } 948 return (XEN_INVAL); 949 } 950 951 int 952 xendev_devclass_ipl(xendev_devclass_t devclass) 953 { 954 i_xd_cfg_t *xdcp; 955 956 xdcp = i_xvdi_devclass2cfg(devclass); 957 ASSERT(xdcp != NULL); 958 959 return (xdcp->xd_ipl); 960 } 961 962 /* 963 * Determine if a devinfo instance exists of a particular device 964 * class, domain and xenstore virtual device number. 965 */ 966 dev_info_t * 967 xvdi_find_dev(dev_info_t *parent, xendev_devclass_t devclass, 968 domid_t dom, int vdev) 969 { 970 dev_info_t *dip; 971 972 ASSERT(DEVI_BUSY_OWNED(parent)); 973 974 switch (devclass) { 975 case XEN_CONSOLE: 976 case XEN_XENBUS: 977 case XEN_DOMCAPS: 978 case XEN_BALLOON: 979 case XEN_EVTCHN: 980 case XEN_PRIVCMD: 981 /* Console and soft devices have no vdev. */ 982 vdev = VDEV_NOXS; 983 break; 984 default: 985 break; 986 } 987 988 for (dip = ddi_get_child(parent); dip != NULL; 989 dip = ddi_get_next_sibling(dip)) { 990 int *vdevnump, *domidp, *devclsp, vdevnum; 991 uint_t ndomid, nvdevnum, ndevcls; 992 xendev_devclass_t devcls; 993 domid_t domid; 994 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 995 996 if (pdp == NULL) { 997 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 998 DDI_PROP_DONTPASS, "domain", &domidp, &ndomid) != 999 DDI_PROP_SUCCESS) 1000 continue; 1001 ASSERT(ndomid == 1); 1002 domid = (domid_t)*domidp; 1003 ddi_prop_free(domidp); 1004 1005 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 1006 DDI_PROP_DONTPASS, "vdev", &vdevnump, &nvdevnum) != 1007 DDI_PROP_SUCCESS) 1008 continue; 1009 ASSERT(nvdevnum == 1); 1010 vdevnum = *vdevnump; 1011 ddi_prop_free(vdevnump); 1012 1013 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 1014 DDI_PROP_DONTPASS, "devclass", &devclsp, 1015 &ndevcls) != DDI_PROP_SUCCESS) 1016 continue; 1017 ASSERT(ndevcls == 1); 1018 devcls = (xendev_devclass_t)*devclsp; 1019 ddi_prop_free(devclsp); 1020 } else { 1021 domid = pdp->xd_domain; 1022 vdevnum = pdp->xd_vdevnum; 1023 devcls = pdp->xd_devclass; 1024 } 1025 1026 if ((domid == dom) && (vdevnum == vdev) && (devcls == devclass)) 1027 return (dip); 1028 } 1029 return (NULL); 1030 } 1031 1032 int 1033 xvdi_get_evtchn(dev_info_t *xdip) 1034 { 1035 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 1036 1037 ASSERT(pdp != NULL); 1038 return (pdp->xd_evtchn); 1039 } 1040 1041 int 1042 xvdi_get_vdevnum(dev_info_t *xdip) 1043 { 1044 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 1045 1046 ASSERT(pdp != NULL); 1047 return (pdp->xd_vdevnum); 1048 } 1049 1050 char * 1051 xvdi_get_xsname(dev_info_t *xdip) 1052 { 1053 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 1054 1055 ASSERT(pdp != NULL); 1056 return ((char *)(pdp->xd_xsdev.nodename)); 1057 } 1058 1059 char * 1060 xvdi_get_oename(dev_info_t *xdip) 1061 { 1062 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 1063 1064 ASSERT(pdp != NULL); 1065 if (pdp->xd_devclass == XEN_CONSOLE) 1066 return (NULL); 1067 return ((char *)(pdp->xd_xsdev.otherend)); 1068 } 1069 1070 struct xenbus_device * 1071 xvdi_get_xsd(dev_info_t *xdip) 1072 { 1073 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 1074 1075 ASSERT(pdp != NULL); 1076 return (&pdp->xd_xsdev); 1077 } 1078 1079 domid_t 1080 xvdi_get_oeid(dev_info_t *xdip) 1081 { 1082 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 1083 1084 ASSERT(pdp != NULL); 1085 if (pdp->xd_devclass == XEN_CONSOLE) 1086 return ((domid_t)-1); 1087 return ((domid_t)(pdp->xd_xsdev.otherend_id)); 1088 } 1089 1090 void 1091 xvdi_dev_error(dev_info_t *dip, int errno, char *errstr) 1092 { 1093 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1094 1095 ASSERT(pdp != NULL); 1096 xenbus_dev_error(&pdp->xd_xsdev, errno, errstr); 1097 } 1098 1099 void 1100 xvdi_fatal_error(dev_info_t *dip, int errno, char *errstr) 1101 { 1102 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1103 1104 ASSERT(pdp != NULL); 1105 xenbus_dev_fatal(&pdp->xd_xsdev, errno, errstr); 1106 } 1107 1108 static void 1109 i_xvdi_oestate_handler(void *arg) 1110 { 1111 dev_info_t *dip = arg; 1112 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1113 XenbusState oestate = pdp->xd_xsdev.otherend_state; 1114 ddi_eventcookie_t evc; 1115 1116 mutex_enter(&pdp->xd_lk); 1117 1118 if (pdp->xd_oe_ehid != NULL) { 1119 /* send notification to driver */ 1120 if (ddi_get_eventcookie(dip, XS_OE_STATE, 1121 &evc) == DDI_SUCCESS) { 1122 mutex_exit(&pdp->xd_lk); 1123 (void) ndi_post_event(dip, dip, evc, &oestate); 1124 mutex_enter(&pdp->xd_lk); 1125 } 1126 } else { 1127 /* 1128 * take default action, if driver hasn't registered its 1129 * event handler yet 1130 */ 1131 if (oestate == XenbusStateClosing) { 1132 (void) xvdi_switch_state(dip, XBT_NULL, 1133 XenbusStateClosed); 1134 } else if (oestate == XenbusStateClosed) { 1135 (void) xvdi_switch_state(dip, XBT_NULL, 1136 XenbusStateClosed); 1137 (void) xvdi_post_event(dip, XEN_HP_REMOVE); 1138 } 1139 } 1140 1141 mutex_exit(&pdp->xd_lk); 1142 1143 /* 1144 * We'll try to remove the devinfo node of this device if the 1145 * other end has closed. 1146 */ 1147 if (oestate == XenbusStateClosed) 1148 (void) ddi_taskq_dispatch(DEVI(ddi_get_parent(dip))->devi_taskq, 1149 xendev_offline_device, dip, DDI_SLEEP); 1150 } 1151 1152 static void 1153 i_xvdi_hpstate_handler(void *arg) 1154 { 1155 dev_info_t *dip = (dev_info_t *)arg; 1156 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1157 ddi_eventcookie_t evc; 1158 char *hp_status; 1159 unsigned int hpl; 1160 1161 mutex_enter(&pdp->xd_lk); 1162 if ((ddi_get_eventcookie(dip, XS_HP_STATE, &evc) == DDI_SUCCESS) && 1163 (xenbus_read(XBT_NULL, pdp->xd_hp_watch.node, "", 1164 (void *)&hp_status, &hpl) == 0)) { 1165 1166 xendev_hotplug_state_t new_state = Unrecognized; 1167 1168 if (strcmp(hp_status, "connected") == 0) 1169 new_state = Connected; 1170 1171 mutex_exit(&pdp->xd_lk); 1172 1173 (void) ndi_post_event(dip, dip, evc, &new_state); 1174 kmem_free(hp_status, hpl); 1175 return; 1176 } 1177 mutex_exit(&pdp->xd_lk); 1178 } 1179 1180 void 1181 xvdi_notify_oe(dev_info_t *dip) 1182 { 1183 struct xendev_ppd *pdp; 1184 1185 pdp = ddi_get_parent_data(dip); 1186 ASSERT(pdp->xd_evtchn != INVALID_EVTCHN); 1187 ec_notify_via_evtchn(pdp->xd_evtchn); 1188 } 1189 1190 static void 1191 i_xvdi_bepath_cb(struct xenbus_watch *w, const char **vec, unsigned int len) 1192 { 1193 dev_info_t *dip = (dev_info_t *)w->dev; 1194 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1195 char *be = NULL; 1196 unsigned int bel; 1197 1198 ASSERT(len > XS_WATCH_PATH); 1199 ASSERT(vec[XS_WATCH_PATH] != NULL); 1200 1201 /* 1202 * If the backend is not the same as that we already stored, 1203 * re-set our watch for its' state. 1204 */ 1205 if ((xenbus_read(XBT_NULL, "", vec[XS_WATCH_PATH], (void *)be, &bel) 1206 == 0) && (strcmp(be, pdp->xd_xsdev.otherend) != 0)) 1207 (void) i_xvdi_add_watch_oestate(dip); 1208 1209 if (be != NULL) { 1210 ASSERT(bel > 0); 1211 kmem_free(be, bel); 1212 } 1213 } 1214 1215 static int 1216 i_xvdi_add_watch_oestate(dev_info_t *dip) 1217 { 1218 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1219 1220 ASSERT(pdp != NULL); 1221 ASSERT(pdp->xd_xsdev.nodename != NULL); 1222 ASSERT(mutex_owned(&pdp->xd_lk)); 1223 1224 /* 1225 * Create taskq for delivering other end state change event to 1226 * this device later. 1227 * 1228 * Set nthreads to 1 to make sure that events can be delivered 1229 * in order. 1230 * 1231 * Note: It is _not_ guaranteed that driver can see every 1232 * xenstore change under the path that it is watching. If two 1233 * changes happen consecutively in a very short amount of 1234 * time, it is likely that the driver will see only the last 1235 * one. 1236 */ 1237 if (pdp->xd_oe_taskq == NULL) 1238 if ((pdp->xd_oe_taskq = ddi_taskq_create(dip, 1239 "xendev_oe_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL) 1240 return (DDI_FAILURE); 1241 1242 /* 1243 * Watch for changes to the XenbusState of otherend. 1244 */ 1245 pdp->xd_xsdev.otherend_state = XenbusStateUnknown; 1246 pdp->xd_xsdev.otherend_changed = i_xvdi_oestate_cb; 1247 1248 if (talk_to_otherend(&pdp->xd_xsdev) != 0) { 1249 i_xvdi_rem_watch_oestate(dip); 1250 return (DDI_FAILURE); 1251 } 1252 1253 return (DDI_SUCCESS); 1254 } 1255 1256 static void 1257 i_xvdi_rem_watch_oestate(dev_info_t *dip) 1258 { 1259 struct xendev_ppd *pdp; 1260 struct xenbus_device *dev; 1261 1262 pdp = ddi_get_parent_data(dip); 1263 ASSERT(pdp != NULL); 1264 ASSERT(mutex_owned(&pdp->xd_lk)); 1265 1266 dev = &pdp->xd_xsdev; 1267 1268 /* Unwatch for changes to XenbusState of otherend */ 1269 if (dev->otherend_watch.node != NULL) { 1270 mutex_exit(&pdp->xd_lk); 1271 unregister_xenbus_watch(&dev->otherend_watch); 1272 mutex_enter(&pdp->xd_lk); 1273 } 1274 1275 /* make sure no event handler is running */ 1276 if (pdp->xd_oe_taskq != NULL) { 1277 mutex_exit(&pdp->xd_lk); 1278 ddi_taskq_destroy(pdp->xd_oe_taskq); 1279 mutex_enter(&pdp->xd_lk); 1280 pdp->xd_oe_taskq = NULL; 1281 } 1282 1283 /* clean up */ 1284 dev->otherend_state = XenbusStateUnknown; 1285 dev->otherend_id = (domid_t)-1; 1286 if (dev->otherend_watch.node != NULL) 1287 kmem_free((void *)dev->otherend_watch.node, 1288 strlen(dev->otherend_watch.node) + 1); 1289 dev->otherend_watch.node = NULL; 1290 if (dev->otherend != NULL) 1291 kmem_free((void *)dev->otherend, strlen(dev->otherend) + 1); 1292 dev->otherend = NULL; 1293 } 1294 1295 static int 1296 i_xvdi_add_watch_hpstate(dev_info_t *dip) 1297 { 1298 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1299 1300 ASSERT(pdp != NULL); 1301 ASSERT(pdp->xd_xsdev.frontend == 0); 1302 ASSERT(mutex_owned(&pdp->xd_lk)); 1303 1304 /* 1305 * Create taskq for delivering hotplug status change event to 1306 * this device later. 1307 * 1308 * Set nthreads to 1 to make sure that events can be delivered 1309 * in order. 1310 * 1311 * Note: It is _not_ guaranteed that driver can see every 1312 * hotplug status change under the path that it is 1313 * watching. If two changes happen consecutively in a very 1314 * short amount of time, it is likely that the driver only 1315 * sees the last one. 1316 */ 1317 if (pdp->xd_hp_taskq == NULL) 1318 if ((pdp->xd_hp_taskq = ddi_taskq_create(dip, 1319 "xendev_hp_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL) 1320 return (DDI_FAILURE); 1321 1322 if (pdp->xd_hp_watch.node == NULL) { 1323 size_t len; 1324 char *path; 1325 1326 ASSERT(pdp->xd_xsdev.nodename != NULL); 1327 1328 len = strlen(pdp->xd_xsdev.nodename) + 1329 strlen("/hotplug-status") + 1; 1330 path = kmem_alloc(len, KM_SLEEP); 1331 (void) snprintf(path, len, "%s/hotplug-status", 1332 pdp->xd_xsdev.nodename); 1333 1334 pdp->xd_hp_watch.node = path; 1335 pdp->xd_hp_watch.callback = i_xvdi_hpstate_cb; 1336 pdp->xd_hp_watch.dev = (struct xenbus_device *)dip; /* yuck! */ 1337 if (register_xenbus_watch(&pdp->xd_hp_watch) != 0) { 1338 i_xvdi_rem_watch_hpstate(dip); 1339 return (DDI_FAILURE); 1340 } 1341 } 1342 1343 return (DDI_SUCCESS); 1344 } 1345 1346 static void 1347 i_xvdi_rem_watch_hpstate(dev_info_t *dip) 1348 { 1349 struct xendev_ppd *pdp; 1350 pdp = ddi_get_parent_data(dip); 1351 1352 ASSERT(pdp != NULL); 1353 ASSERT(pdp->xd_xsdev.frontend == 0); 1354 ASSERT(mutex_owned(&pdp->xd_lk)); 1355 1356 /* Unwatch for changes to "hotplug-status" node for backend device. */ 1357 if (pdp->xd_hp_watch.node != NULL) { 1358 mutex_exit(&pdp->xd_lk); 1359 unregister_xenbus_watch(&pdp->xd_hp_watch); 1360 mutex_enter(&pdp->xd_lk); 1361 } 1362 1363 /* Make sure no event handler is running. */ 1364 if (pdp->xd_hp_taskq != NULL) { 1365 mutex_exit(&pdp->xd_lk); 1366 ddi_taskq_destroy(pdp->xd_hp_taskq); 1367 mutex_enter(&pdp->xd_lk); 1368 pdp->xd_hp_taskq = NULL; 1369 } 1370 1371 /* Clean up. */ 1372 if (pdp->xd_hp_watch.node != NULL) { 1373 kmem_free((void *)pdp->xd_hp_watch.node, 1374 strlen(pdp->xd_hp_watch.node) + 1); 1375 pdp->xd_hp_watch.node = NULL; 1376 } 1377 } 1378 1379 static int 1380 i_xvdi_add_watches(dev_info_t *dip) 1381 { 1382 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1383 1384 ASSERT(pdp != NULL); 1385 1386 mutex_enter(&pdp->xd_lk); 1387 1388 if (i_xvdi_add_watch_oestate(dip) != DDI_SUCCESS) { 1389 mutex_exit(&pdp->xd_lk); 1390 return (DDI_FAILURE); 1391 } 1392 1393 if (pdp->xd_xsdev.frontend == 1) { 1394 /* 1395 * Frontend devices must watch for the backend path 1396 * changing. 1397 */ 1398 if (i_xvdi_add_watch_bepath(dip) != DDI_SUCCESS) 1399 goto unwatch_and_fail; 1400 } else { 1401 /* 1402 * Backend devices must watch for hotplug events. 1403 */ 1404 if (i_xvdi_add_watch_hpstate(dip) != DDI_SUCCESS) 1405 goto unwatch_and_fail; 1406 } 1407 1408 mutex_exit(&pdp->xd_lk); 1409 1410 return (DDI_SUCCESS); 1411 1412 unwatch_and_fail: 1413 i_xvdi_rem_watch_oestate(dip); 1414 mutex_exit(&pdp->xd_lk); 1415 1416 return (DDI_FAILURE); 1417 } 1418 1419 static void 1420 i_xvdi_rem_watches(dev_info_t *dip) 1421 { 1422 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1423 1424 ASSERT(pdp != NULL); 1425 1426 mutex_enter(&pdp->xd_lk); 1427 1428 i_xvdi_rem_watch_oestate(dip); 1429 1430 if (pdp->xd_xsdev.frontend == 1) 1431 i_xvdi_rem_watch_bepath(dip); 1432 else 1433 i_xvdi_rem_watch_hpstate(dip); 1434 1435 mutex_exit(&pdp->xd_lk); 1436 } 1437 1438 static int 1439 i_xvdi_add_watch_bepath(dev_info_t *dip) 1440 { 1441 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1442 1443 ASSERT(pdp != NULL); 1444 ASSERT(pdp->xd_xsdev.frontend == 1); 1445 1446 /* 1447 * Frontend devices need to watch for the backend path changing. 1448 */ 1449 if (pdp->xd_bepath_watch.node == NULL) { 1450 size_t len; 1451 char *path; 1452 1453 ASSERT(pdp->xd_xsdev.nodename != NULL); 1454 1455 len = strlen(pdp->xd_xsdev.nodename) + strlen("/backend") + 1; 1456 path = kmem_alloc(len, KM_SLEEP); 1457 (void) snprintf(path, len, "%s/backend", 1458 pdp->xd_xsdev.nodename); 1459 1460 pdp->xd_bepath_watch.node = path; 1461 pdp->xd_bepath_watch.callback = i_xvdi_bepath_cb; 1462 pdp->xd_bepath_watch.dev = (struct xenbus_device *)dip; 1463 if (register_xenbus_watch(&pdp->xd_bepath_watch) != 0) { 1464 kmem_free(path, len); 1465 pdp->xd_bepath_watch.node = NULL; 1466 return (DDI_FAILURE); 1467 } 1468 } 1469 1470 return (DDI_SUCCESS); 1471 } 1472 1473 static void 1474 i_xvdi_rem_watch_bepath(dev_info_t *dip) 1475 { 1476 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1477 1478 ASSERT(pdp != NULL); 1479 ASSERT(pdp->xd_xsdev.frontend == 1); 1480 ASSERT(mutex_owned(&pdp->xd_lk)); 1481 1482 if (pdp->xd_bepath_watch.node != NULL) { 1483 mutex_exit(&pdp->xd_lk); 1484 unregister_xenbus_watch(&pdp->xd_bepath_watch); 1485 mutex_enter(&pdp->xd_lk); 1486 1487 kmem_free((void *)(pdp->xd_bepath_watch.node), 1488 strlen(pdp->xd_bepath_watch.node) + 1); 1489 pdp->xd_bepath_watch.node = NULL; 1490 } 1491 } 1492 1493 int 1494 xvdi_switch_state(dev_info_t *dip, xenbus_transaction_t xbt, 1495 XenbusState newState) 1496 { 1497 int rv; 1498 struct xendev_ppd *pdp; 1499 1500 pdp = ddi_get_parent_data(dip); 1501 ASSERT(pdp != NULL); 1502 1503 XVDI_DPRINTF(XVDI_DBG_STATE, 1504 "xvdi_switch_state: dip 0x%p moves to %d", 1505 (void *)dip, newState); 1506 1507 rv = xenbus_switch_state(&pdp->xd_xsdev, xbt, newState); 1508 if (rv > 0) 1509 cmn_err(CE_WARN, "xvdi_switch_state: change state failed"); 1510 1511 return (rv); 1512 } 1513 1514 /* 1515 * Notify hotplug script running in userland 1516 */ 1517 int 1518 xvdi_post_event(dev_info_t *dip, xendev_hotplug_cmd_t hpc) 1519 { 1520 struct xendev_ppd *pdp; 1521 nvlist_t *attr_list = NULL; 1522 i_xd_cfg_t *xdcp; 1523 sysevent_id_t eid; 1524 int err; 1525 char devname[256]; /* XXPV dme: ? */ 1526 1527 pdp = ddi_get_parent_data(dip); 1528 ASSERT(pdp != NULL); 1529 1530 xdcp = i_xvdi_devclass2cfg(pdp->xd_devclass); 1531 ASSERT(xdcp != NULL); 1532 1533 (void) snprintf(devname, sizeof (devname) - 1, "%s%d", 1534 ddi_driver_name(dip), ddi_get_instance(dip)); 1535 1536 err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME, KM_NOSLEEP); 1537 if (err != DDI_SUCCESS) 1538 goto failure; 1539 1540 err = nvlist_add_int32(attr_list, "domain", pdp->xd_domain); 1541 if (err != DDI_SUCCESS) 1542 goto failure; 1543 err = nvlist_add_int32(attr_list, "vdev", pdp->xd_vdevnum); 1544 if (err != DDI_SUCCESS) 1545 goto failure; 1546 err = nvlist_add_string(attr_list, "devclass", xdcp->xsdev); 1547 if (err != DDI_SUCCESS) 1548 goto failure; 1549 err = nvlist_add_string(attr_list, "device", devname); 1550 if (err != DDI_SUCCESS) 1551 goto failure; 1552 err = nvlist_add_string(attr_list, "fob", 1553 ((pdp->xd_xsdev.frontend == 1) ? "frontend" : "backend")); 1554 if (err != DDI_SUCCESS) 1555 goto failure; 1556 1557 switch (hpc) { 1558 case XEN_HP_ADD: 1559 err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev", 1560 "add", attr_list, &eid, DDI_NOSLEEP); 1561 break; 1562 case XEN_HP_REMOVE: 1563 err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev", 1564 "remove", attr_list, &eid, DDI_NOSLEEP); 1565 break; 1566 default: 1567 err = DDI_FAILURE; 1568 goto failure; 1569 } 1570 1571 failure: 1572 if (attr_list != NULL) 1573 nvlist_free(attr_list); 1574 1575 return (err); 1576 } 1577 1578 /* ARGSUSED */ 1579 static void 1580 i_xvdi_probe_path_cb(struct xenbus_watch *w, const char **vec, 1581 unsigned int len) 1582 { 1583 char *path; 1584 1585 if (xendev_dip == NULL) 1586 xendev_dip = ddi_find_devinfo("xpvd", -1, 0); 1587 1588 path = i_ddi_strdup((char *)vec[XS_WATCH_PATH], KM_SLEEP); 1589 1590 (void) ddi_taskq_dispatch(DEVI(xendev_dip)->devi_taskq, 1591 i_xvdi_probe_path_handler, (void *)path, DDI_SLEEP); 1592 } 1593 1594 static void 1595 i_xvdi_watch_device(char *path) 1596 { 1597 struct xenbus_watch *w; 1598 1599 ASSERT(path != NULL); 1600 1601 w = kmem_zalloc(sizeof (*w), KM_SLEEP); 1602 w->node = path; 1603 w->callback = &i_xvdi_probe_path_cb; 1604 w->dev = NULL; 1605 1606 if (register_xenbus_watch(w) != 0) { 1607 cmn_err(CE_WARN, "i_xvdi_watch_device: " 1608 "cannot set watch on %s", path); 1609 kmem_free(w, sizeof (*w)); 1610 return; 1611 } 1612 } 1613 1614 void 1615 xvdi_watch_devices(int newstate) 1616 { 1617 int devclass; 1618 1619 /* 1620 * Watch for devices being created in the store. 1621 */ 1622 if (newstate == XENSTORE_DOWN) 1623 return; 1624 for (devclass = 0; devclass < NXDC; devclass++) { 1625 if (xdci[devclass].xs_path_fe != NULL) 1626 i_xvdi_watch_device(xdci[devclass].xs_path_fe); 1627 if (xdci[devclass].xs_path_be != NULL) 1628 i_xvdi_watch_device(xdci[devclass].xs_path_be); 1629 } 1630 } 1631 1632 /* 1633 * Iterate over the store looking for backend devices to create. 1634 */ 1635 static void 1636 i_xvdi_enum_be(dev_info_t *parent, i_xd_cfg_t *xdcp) 1637 { 1638 char **domains; 1639 unsigned int ndomains; 1640 int ldomains, i; 1641 1642 if ((domains = xenbus_directory(XBT_NULL, xdcp->xs_path_be, "", 1643 &ndomains)) == NULL) 1644 return; 1645 1646 for (i = 0, ldomains = 0; i < ndomains; i++) { 1647 ldomains += strlen(domains[i]) + 1 + sizeof (char *); 1648 1649 i_xvdi_enum_worker(parent, xdcp, domains[i]); 1650 } 1651 kmem_free(domains, ldomains); 1652 } 1653 1654 /* 1655 * Iterate over the store looking for frontend devices to create. 1656 */ 1657 static void 1658 i_xvdi_enum_fe(dev_info_t *parent, i_xd_cfg_t *xdcp) 1659 { 1660 i_xvdi_enum_worker(parent, xdcp, NULL); 1661 } 1662 1663 static void 1664 i_xvdi_enum_worker(dev_info_t *parent, i_xd_cfg_t *xdcp, 1665 char *domain) 1666 { 1667 char *path, *domain_path, *ep; 1668 char **devices; 1669 unsigned int ndevices; 1670 int ldevices, j, circ; 1671 domid_t dom; 1672 1673 if (domain == NULL) { 1674 dom = DOMID_SELF; 1675 path = xdcp->xs_path_fe; 1676 domain_path = ""; 1677 } else { 1678 (void) ddi_strtol(domain, &ep, 0, (long *)&dom); 1679 path = xdcp->xs_path_be; 1680 domain_path = domain; 1681 } 1682 1683 if ((devices = xenbus_directory(XBT_NULL, path, domain_path, 1684 &ndevices)) == NULL) 1685 return; 1686 1687 for (j = 0, ldevices = 0; j < ndevices; j++) { 1688 int vdev; 1689 1690 ldevices += strlen(devices[j]) + 1 + sizeof (char *); 1691 (void) ddi_strtol(devices[j], &ep, 0, (long *)&vdev); 1692 1693 ndi_devi_enter(parent, &circ); 1694 1695 if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) 1696 == NULL) 1697 (void) xvdi_create_dev(parent, xdcp->devclass, 1698 dom, vdev); 1699 1700 ndi_devi_exit(parent, circ); 1701 } 1702 kmem_free(devices, ldevices); 1703 } 1704 1705 /* 1706 * Leaf drivers should call this in their detach() routine during suspend. 1707 */ 1708 void 1709 xvdi_suspend(dev_info_t *dip) 1710 { 1711 i_xvdi_rem_watches(dip); 1712 } 1713 1714 /* 1715 * Leaf drivers should call this in their attach() routine during resume. 1716 */ 1717 int 1718 xvdi_resume(dev_info_t *dip) 1719 { 1720 return (i_xvdi_add_watches(dip)); 1721 } 1722 1723 /* 1724 * Add event handler for the leaf driver 1725 * to handle event triggered by the change in xenstore 1726 */ 1727 int 1728 xvdi_add_event_handler(dev_info_t *dip, char *name, 1729 void (*evthandler)(dev_info_t *, ddi_eventcookie_t, void *, void *)) 1730 { 1731 ddi_eventcookie_t ecv; 1732 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1733 ddi_callback_id_t *cbid; 1734 1735 ASSERT(pdp != NULL); 1736 1737 mutex_enter(&pdp->xd_lk); 1738 1739 if (strcmp(name, XS_OE_STATE) == 0) { 1740 ASSERT(pdp->xd_xsdev.otherend != NULL); 1741 1742 cbid = &pdp->xd_oe_ehid; 1743 } else if (strcmp(name, XS_HP_STATE) == 0) { 1744 if (pdp->xd_xsdev.frontend == 1) { 1745 mutex_exit(&pdp->xd_lk); 1746 return (DDI_FAILURE); 1747 } 1748 1749 ASSERT(pdp->xd_hp_watch.node != NULL); 1750 1751 cbid = &pdp->xd_hp_ehid; 1752 } else { 1753 /* Unsupported watch. */ 1754 mutex_exit(&pdp->xd_lk); 1755 return (DDI_FAILURE); 1756 } 1757 1758 /* 1759 * No event handler provided, take default action to handle 1760 * event. 1761 */ 1762 if (evthandler == NULL) { 1763 mutex_exit(&pdp->xd_lk); 1764 return (DDI_SUCCESS); 1765 } 1766 1767 ASSERT(*cbid == NULL); 1768 1769 if (ddi_get_eventcookie(dip, name, &ecv) != DDI_SUCCESS) { 1770 cmn_err(CE_WARN, "failed to find %s cookie for %s@%s", 1771 name, ddi_get_name(dip), ddi_get_name_addr(dip)); 1772 mutex_exit(&pdp->xd_lk); 1773 return (DDI_FAILURE); 1774 } 1775 if (ddi_add_event_handler(dip, ecv, evthandler, NULL, cbid) 1776 != DDI_SUCCESS) { 1777 cmn_err(CE_WARN, "failed to add %s event handler for %s@%s", 1778 name, ddi_get_name(dip), ddi_get_name_addr(dip)); 1779 *cbid = NULL; 1780 mutex_exit(&pdp->xd_lk); 1781 return (DDI_FAILURE); 1782 } 1783 1784 mutex_exit(&pdp->xd_lk); 1785 1786 return (DDI_SUCCESS); 1787 } 1788 1789 /* 1790 * Remove event handler for the leaf driver and unwatch xenstore 1791 * so, driver will not be notified when xenstore entry changed later 1792 */ 1793 void 1794 xvdi_remove_event_handler(dev_info_t *dip, char *name) 1795 { 1796 struct xendev_ppd *pdp; 1797 boolean_t rem_oe = B_FALSE, rem_hp = B_FALSE; 1798 ddi_callback_id_t oeid = NULL, hpid = NULL; 1799 1800 pdp = ddi_get_parent_data(dip); 1801 ASSERT(pdp != NULL); 1802 1803 if (name == NULL) { 1804 rem_oe = B_TRUE; 1805 rem_hp = B_TRUE; 1806 } else if (strcmp(name, XS_OE_STATE) == 0) { 1807 rem_oe = B_TRUE; 1808 } else if (strcmp(name, XS_HP_STATE) == 0) { 1809 rem_hp = B_TRUE; 1810 } else { 1811 cmn_err(CE_WARN, "event %s not supported, cannot remove", name); 1812 return; 1813 } 1814 1815 mutex_enter(&pdp->xd_lk); 1816 1817 if (rem_oe && (pdp->xd_oe_ehid != NULL)) { 1818 oeid = pdp->xd_oe_ehid; 1819 pdp->xd_oe_ehid = NULL; 1820 } 1821 1822 if (rem_hp && (pdp->xd_hp_ehid != NULL)) { 1823 hpid = pdp->xd_hp_ehid; 1824 pdp->xd_hp_ehid = NULL; 1825 } 1826 1827 mutex_exit(&pdp->xd_lk); 1828 1829 if (oeid != NULL) 1830 (void) ddi_remove_event_handler(oeid); 1831 if (hpid != NULL) 1832 (void) ddi_remove_event_handler(hpid); 1833 } 1834 1835 1836 /* 1837 * common ring interfaces 1838 */ 1839 1840 #define FRONT_RING(_ringp) (&(_ringp)->xr_sring.fr) 1841 #define BACK_RING(_ringp) (&(_ringp)->xr_sring.br) 1842 #define GET_RING_SIZE(_ringp) RING_SIZE(FRONT_RING(ringp)) 1843 #define GET_RING_ENTRY_FE(_ringp, _idx) \ 1844 (FRONT_RING(_ringp)->sring->ring + \ 1845 (_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1))) 1846 #define GET_RING_ENTRY_BE(_ringp, _idx) \ 1847 (BACK_RING(_ringp)->sring->ring + \ 1848 (_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1))) 1849 1850 unsigned int 1851 xvdi_ring_avail_slots(xendev_ring_t *ringp) 1852 { 1853 comif_ring_fe_t *frp; 1854 comif_ring_be_t *brp; 1855 1856 if (ringp->xr_frontend) { 1857 frp = FRONT_RING(ringp); 1858 return (GET_RING_SIZE(ringp) - 1859 (frp->req_prod_pvt - frp->rsp_cons)); 1860 } else { 1861 brp = BACK_RING(ringp); 1862 return (GET_RING_SIZE(ringp) - 1863 (brp->rsp_prod_pvt - brp->req_cons)); 1864 } 1865 } 1866 1867 int 1868 xvdi_ring_has_unconsumed_requests(xendev_ring_t *ringp) 1869 { 1870 comif_ring_be_t *brp; 1871 1872 ASSERT(!ringp->xr_frontend); 1873 brp = BACK_RING(ringp); 1874 return ((brp->req_cons != 1875 ddi_get32(ringp->xr_acc_hdl, &brp->sring->req_prod)) && 1876 ((brp->req_cons - brp->rsp_prod_pvt) != RING_SIZE(brp))); 1877 } 1878 1879 int 1880 xvdi_ring_has_incomp_request(xendev_ring_t *ringp) 1881 { 1882 comif_ring_fe_t *frp; 1883 1884 ASSERT(ringp->xr_frontend); 1885 frp = FRONT_RING(ringp); 1886 return (frp->req_prod_pvt != 1887 ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod)); 1888 } 1889 1890 int 1891 xvdi_ring_has_unconsumed_responses(xendev_ring_t *ringp) 1892 { 1893 comif_ring_fe_t *frp; 1894 1895 ASSERT(ringp->xr_frontend); 1896 frp = FRONT_RING(ringp); 1897 return (frp->rsp_cons != 1898 ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod)); 1899 } 1900 1901 /* NOTE: req_event will be increased as needed */ 1902 void * 1903 xvdi_ring_get_request(xendev_ring_t *ringp) 1904 { 1905 comif_ring_fe_t *frp; 1906 comif_ring_be_t *brp; 1907 1908 if (ringp->xr_frontend) { 1909 /* for frontend ring */ 1910 frp = FRONT_RING(ringp); 1911 if (!RING_FULL(frp)) 1912 return (GET_RING_ENTRY_FE(ringp, frp->req_prod_pvt++)); 1913 else 1914 return (NULL); 1915 } else { 1916 /* for backend ring */ 1917 brp = BACK_RING(ringp); 1918 /* RING_FINAL_CHECK_FOR_REQUESTS() */ 1919 if (xvdi_ring_has_unconsumed_requests(ringp)) 1920 return (GET_RING_ENTRY_BE(ringp, brp->req_cons++)); 1921 else { 1922 ddi_put32(ringp->xr_acc_hdl, &brp->sring->req_event, 1923 brp->req_cons + 1); 1924 membar_enter(); 1925 if (xvdi_ring_has_unconsumed_requests(ringp)) 1926 return (GET_RING_ENTRY_BE(ringp, 1927 brp->req_cons++)); 1928 else 1929 return (NULL); 1930 } 1931 } 1932 } 1933 1934 int 1935 xvdi_ring_push_request(xendev_ring_t *ringp) 1936 { 1937 RING_IDX old, new, reqevt; 1938 comif_ring_fe_t *frp; 1939 1940 /* only frontend should be able to push request */ 1941 ASSERT(ringp->xr_frontend); 1942 1943 /* RING_PUSH_REQUEST_AND_CHECK_NOTIFY() */ 1944 frp = FRONT_RING(ringp); 1945 old = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_prod); 1946 new = frp->req_prod_pvt; 1947 ddi_put32(ringp->xr_acc_hdl, &frp->sring->req_prod, new); 1948 membar_enter(); 1949 reqevt = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_event); 1950 return ((RING_IDX)(new - reqevt) < (RING_IDX)(new - old)); 1951 } 1952 1953 /* NOTE: rsp_event will be increased as needed */ 1954 void * 1955 xvdi_ring_get_response(xendev_ring_t *ringp) 1956 { 1957 comif_ring_fe_t *frp; 1958 comif_ring_be_t *brp; 1959 1960 if (!ringp->xr_frontend) { 1961 /* for backend ring */ 1962 brp = BACK_RING(ringp); 1963 return (GET_RING_ENTRY_BE(ringp, brp->rsp_prod_pvt++)); 1964 } else { 1965 /* for frontend ring */ 1966 frp = FRONT_RING(ringp); 1967 /* RING_FINAL_CHECK_FOR_RESPONSES() */ 1968 if (xvdi_ring_has_unconsumed_responses(ringp)) 1969 return (GET_RING_ENTRY_FE(ringp, frp->rsp_cons++)); 1970 else { 1971 ddi_put32(ringp->xr_acc_hdl, &frp->sring->rsp_event, 1972 frp->rsp_cons + 1); 1973 membar_enter(); 1974 if (xvdi_ring_has_unconsumed_responses(ringp)) 1975 return (GET_RING_ENTRY_FE(ringp, 1976 frp->rsp_cons++)); 1977 else 1978 return (NULL); 1979 } 1980 } 1981 } 1982 1983 int 1984 xvdi_ring_push_response(xendev_ring_t *ringp) 1985 { 1986 RING_IDX old, new, rspevt; 1987 comif_ring_be_t *brp; 1988 1989 /* only backend should be able to push response */ 1990 ASSERT(!ringp->xr_frontend); 1991 1992 /* RING_PUSH_RESPONSE_AND_CHECK_NOTIFY() */ 1993 brp = BACK_RING(ringp); 1994 old = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_prod); 1995 new = brp->rsp_prod_pvt; 1996 ddi_put32(ringp->xr_acc_hdl, &brp->sring->rsp_prod, new); 1997 membar_enter(); 1998 rspevt = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_event); 1999 return ((RING_IDX)(new - rspevt) < (RING_IDX)(new - old)); 2000 } 2001 2002 static void 2003 xvdi_ring_init_sring(xendev_ring_t *ringp) 2004 { 2005 ddi_acc_handle_t acchdl; 2006 comif_sring_t *xsrp; 2007 int i; 2008 2009 xsrp = (comif_sring_t *)ringp->xr_vaddr; 2010 acchdl = ringp->xr_acc_hdl; 2011 2012 /* shared ring initialization */ 2013 ddi_put32(acchdl, &xsrp->req_prod, 0); 2014 ddi_put32(acchdl, &xsrp->rsp_prod, 0); 2015 ddi_put32(acchdl, &xsrp->req_event, 1); 2016 ddi_put32(acchdl, &xsrp->rsp_event, 1); 2017 for (i = 0; i < sizeof (xsrp->pad); i++) 2018 ddi_put8(acchdl, xsrp->pad + i, 0); 2019 } 2020 2021 static void 2022 xvdi_ring_init_front_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize) 2023 { 2024 comif_ring_fe_t *xfrp; 2025 2026 xfrp = &ringp->xr_sring.fr; 2027 xfrp->req_prod_pvt = 0; 2028 xfrp->rsp_cons = 0; 2029 xfrp->nr_ents = nentry; 2030 xfrp->sring = (comif_sring_t *)ringp->xr_vaddr; 2031 2032 ringp->xr_frontend = 1; 2033 ringp->xr_entry_size = entrysize; 2034 } 2035 2036 #ifndef XPV_HVM_DRIVER 2037 static void 2038 xvdi_ring_init_back_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize) 2039 { 2040 comif_ring_be_t *xbrp; 2041 2042 xbrp = &ringp->xr_sring.br; 2043 xbrp->rsp_prod_pvt = 0; 2044 xbrp->req_cons = 0; 2045 xbrp->nr_ents = nentry; 2046 xbrp->sring = (comif_sring_t *)ringp->xr_vaddr; 2047 2048 ringp->xr_frontend = 0; 2049 ringp->xr_entry_size = entrysize; 2050 } 2051 #endif /* XPV_HVM_DRIVER */ 2052 2053 static void 2054 xendev_offline_device(void *arg) 2055 { 2056 dev_info_t *dip = (dev_info_t *)arg; 2057 char devname[MAXNAMELEN] = {0}; 2058 2059 /* 2060 * This is currently the only chance to delete a devinfo node, which 2061 * is _not_ always successful. 2062 */ 2063 (void) ddi_deviname(dip, devname); 2064 (void) devfs_clean(ddi_get_parent(dip), devname + 1, DV_CLEAN_FORCE); 2065 (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE); 2066 } 2067 2068 static void 2069 i_xvdi_oestate_cb(struct xenbus_device *dev, XenbusState oestate) 2070 { 2071 dev_info_t *dip = (dev_info_t *)dev->data; 2072 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 2073 2074 /* 2075 * Don't trigger two consecutive ndi_devi_offline on the same 2076 * dip. 2077 */ 2078 if ((oestate == XenbusStateClosed) && 2079 (dev->otherend_state == XenbusStateClosed)) 2080 return; 2081 2082 dev->otherend_state = oestate; 2083 (void) ddi_taskq_dispatch(pdp->xd_oe_taskq, 2084 i_xvdi_oestate_handler, (void *)dip, DDI_SLEEP); 2085 } 2086 2087 /*ARGSUSED*/ 2088 static void 2089 i_xvdi_hpstate_cb(struct xenbus_watch *w, const char **vec, 2090 unsigned int len) 2091 { 2092 dev_info_t *dip = (dev_info_t *)w->dev; 2093 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 2094 2095 (void) ddi_taskq_dispatch(pdp->xd_hp_taskq, 2096 i_xvdi_hpstate_handler, (void *)dip, DDI_SLEEP); 2097 } 2098 2099 static void 2100 i_xvdi_probe_path_handler(void *arg) 2101 { 2102 dev_info_t *parent; 2103 char *path = arg, *p = NULL; 2104 int i, vdev, circ; 2105 i_xd_cfg_t *xdcp; 2106 boolean_t frontend; 2107 domid_t dom; 2108 2109 for (i = 0, xdcp = &xdci[0]; i < NXDC; i++, xdcp++) { 2110 2111 if ((xdcp->xs_path_fe != NULL) && 2112 (strncmp(path, xdcp->xs_path_fe, strlen(xdcp->xs_path_fe)) 2113 == 0)) { 2114 2115 frontend = B_TRUE; 2116 p = path + strlen(xdcp->xs_path_fe); 2117 break; 2118 } 2119 2120 if ((xdcp->xs_path_be != NULL) && 2121 (strncmp(path, xdcp->xs_path_be, strlen(xdcp->xs_path_be)) 2122 == 0)) { 2123 2124 frontend = B_FALSE; 2125 p = path + strlen(xdcp->xs_path_be); 2126 break; 2127 } 2128 2129 } 2130 2131 if (p == NULL) { 2132 cmn_err(CE_WARN, "i_xvdi_probe_path_handler: " 2133 "unexpected path prefix in %s", path); 2134 goto done; 2135 } 2136 2137 if (frontend) { 2138 dom = DOMID_SELF; 2139 if (sscanf(p, "/%d/", &vdev) != 1) { 2140 XVDI_DPRINTF(XVDI_DBG_PROBE, 2141 "i_xvdi_probe_path_handler: " 2142 "cannot parse frontend path %s", 2143 path); 2144 goto done; 2145 } 2146 } else { 2147 if (sscanf(p, "/%d/%d/", &dom, &vdev) != 2) { 2148 XVDI_DPRINTF(XVDI_DBG_PROBE, 2149 "i_xvdi_probe_path_handler: " 2150 "cannot parse backend path %s", 2151 path); 2152 goto done; 2153 } 2154 } 2155 2156 /* 2157 * This is an oxymoron, so indicates a bogus configuration we 2158 * must check for. 2159 */ 2160 if (vdev == VDEV_NOXS) { 2161 cmn_err(CE_WARN, "i_xvdi_probe_path_handler: " 2162 "invalid path %s", path); 2163 goto done; 2164 } 2165 2166 parent = xendev_dip; 2167 ASSERT(parent != NULL); 2168 2169 ndi_devi_enter(parent, &circ); 2170 2171 if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) == NULL) { 2172 XVDI_DPRINTF(XVDI_DBG_PROBE, 2173 "i_xvdi_probe_path_handler: create for %s", path); 2174 (void) xvdi_create_dev(parent, xdcp->devclass, dom, vdev); 2175 } else { 2176 XVDI_DPRINTF(XVDI_DBG_PROBE, 2177 "i_xvdi_probe_path_handler: %s already exists", path); 2178 } 2179 2180 ndi_devi_exit(parent, circ); 2181 2182 done: 2183 kmem_free(path, strlen(path) + 1); 2184 } 2185