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