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